@weasel-js/core 1.11.0 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +427 -0
- package/README.md +1 -1
- package/dist/animation/index.js +3 -3
- package/dist/animation/rig/bindRig.js +1 -1
- package/dist/animation/rig/rigNode.js.map +1 -1
- package/dist/barrel/canvas.js +7 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paths.js +3 -3
- package/dist/barrel/renderer.js +3 -2
- package/dist/barrel/routing.js +6 -11
- package/dist/barrel/scene.js +8 -5
- package/dist/barrel/viewport.js +4 -3
- package/dist/canvas/Canvas.js +3 -1
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +45 -5
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js +1 -11
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +93 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
- package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
- package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +8 -8
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +13 -2
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +1 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +5 -3
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +3 -4
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +16 -14
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SurfaceCanvas.js +5 -22
- package/dist/canvas/SurfaceCanvas.js.map +1 -1
- package/dist/canvas/canvasRenderer.js +9 -5
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/contextAttributes.js +14 -0
- package/dist/canvas/contextAttributes.js.map +1 -0
- package/dist/canvas/deps/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/insert.js +4 -2
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +193 -0
- package/dist/canvas/deps/pathEditCommits.js.map +1 -0
- package/dist/canvas/deps/snap.js +12 -9
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/transformFollowers.js +20 -0
- package/dist/canvas/deps/transformFollowers.js.map +1 -0
- package/dist/canvas/derivedPath.js +20 -1
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/drawnBounds.js +29 -3
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/nodeShapes/derivedPainter.js +9 -1
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +3 -2
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +1 -1
- package/dist/canvas/overlayRoleStrokes.js +12 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/pathOverlay.js +27 -7
- package/dist/canvas/pathOverlay.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +6 -5
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- package/dist/canvas/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/clipboard.d.ts +3 -2
- package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
- package/dist/clone.d.ts +4 -3
- package/dist/core/geometry/autoPoseDescriptor.js +1 -1
- package/dist/core/ops/setDependsOn.js +37 -0
- package/dist/core/ops/setDependsOn.js.map +1 -0
- package/dist/core/ops/writtenBy.js +53 -0
- package/dist/core/ops/writtenBy.js.map +1 -0
- package/dist/core/pages/fitViewToPage.js +12 -1
- package/dist/core/pages/fitViewToPage.js.map +1 -1
- package/dist/core/pages/pageEdits.js +164 -0
- package/dist/core/pages/pageEdits.js.map +1 -0
- package/dist/core/pages/pages.js +30 -1
- package/dist/core/pages/pages.js.map +1 -1
- package/dist/core/scene/NodeRouting.js +8 -3
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/carryDescendants.js +51 -0
- package/dist/core/scene/carryDescendants.js.map +1 -0
- package/dist/core/scene/docValues.js +57 -0
- package/dist/core/scene/docValues.js.map +1 -0
- package/dist/core/scene/editPass.js +111 -0
- package/dist/core/scene/editPass.js.map +1 -0
- package/dist/core/scene/effectivePose.js +7 -1
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +4 -1
- package/dist/core/scene/fieldEdits.js.map +1 -1
- package/dist/core/scene/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/layoutPass.js +28 -3
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/recorder.js +28 -19
- package/dist/core/scene/recorder.js.map +1 -1
- package/dist/core/scene/scene.js +15 -9
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneChanges.js +13 -0
- package/dist/core/scene/sceneChanges.js.map +1 -0
- package/dist/core/scene/sceneEdits.js +8 -1
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneMutators.js +1 -0
- package/dist/core/scene/sceneMutators.js.map +1 -1
- package/dist/core/scene/sceneRecording.js +20 -3
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/scene/sceneSelection.js +4 -1
- package/dist/core/scene/sceneSelection.js.map +1 -1
- package/dist/core/scene/sceneState.js +11 -5
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +5 -3
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/unitScopes.js +19 -1
- package/dist/core/scene/unitScopes.js.map +1 -1
- package/dist/core/selection/usePublishSceneSelection.js +6 -12
- package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
- package/dist/core/shapeKinds.js +25 -11
- package/dist/core/shapeKinds.js.map +1 -1
- package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-BHuoMs1o.d.ts} +1 -1
- package/dist/debug/createDebugOverlayLayer.js +16 -111
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/createDebugSink.js +2 -1
- package/dist/debug/createDebugSink.js.map +1 -1
- package/dist/debug/defaultTheme.js +4 -2
- package/dist/debug/defaultTheme.js.map +1 -1
- package/dist/debug/features.js +17 -0
- package/dist/debug/features.js.map +1 -0
- package/dist/debug/overlayPanels.js +117 -0
- package/dist/debug/overlayPanels.js.map +1 -0
- package/dist/debug/parseDebugFlags.js +4 -13
- package/dist/debug/parseDebugFlags.js.map +1 -1
- package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-BpZNOv7q.d.ts} +114 -892
- package/dist/devtools/handlers.js +112 -0
- package/dist/devtools/handlers.js.map +1 -0
- package/dist/devtools/history.js +71 -0
- package/dist/devtools/history.js.map +1 -0
- package/dist/devtools/hook.js +74 -0
- package/dist/devtools/hook.js.map +1 -0
- package/dist/devtools/label.js +25 -0
- package/dist/devtools/label.js.map +1 -0
- package/dist/devtools/notices.js +58 -0
- package/dist/devtools/notices.js.map +1 -0
- package/dist/devtools/protocol.js +7 -0
- package/dist/devtools/protocol.js.map +1 -0
- package/dist/devtools/registry.js +90 -0
- package/dist/devtools/registry.js.map +1 -0
- package/dist/devtools/root.js +80 -0
- package/dist/devtools/root.js.map +1 -0
- package/dist/devtools/serialize.js +86 -0
- package/dist/devtools/serialize.js.map +1 -0
- package/dist/devtools/session.js +111 -0
- package/dist/devtools/session.js.map +1 -0
- package/dist/devtools/transport.js +67 -0
- package/dist/devtools/transport.js.map +1 -0
- package/dist/devtools/useDevtoolsRoot.js +81 -0
- package/dist/devtools/useDevtoolsRoot.js.map +1 -0
- package/dist/devtools-protocol.d.ts +435 -0
- package/dist/devtools-protocol.js +7 -0
- package/dist/devtools.d.ts +8 -0
- package/dist/devtools.js +12 -0
- package/dist/devtools.js.map +1 -0
- package/dist/features/chrome-caps/useHoverTracking.js +16 -10
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +25 -2
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/measure/measureCommands.js +7 -5
- package/dist/features/measure/measureCommands.js.map +1 -1
- package/dist/features/paths/index.js +2 -2
- package/dist/features/paths/pathEditExtension.js.map +1 -1
- package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
- package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
- package/dist/features/selection/selectionPose.js +4 -1
- package/dist/features/selection/selectionPose.js.map +1 -1
- package/dist/features/snap/gather.js +9 -1
- package/dist/features/snap/gather.js.map +1 -1
- package/dist/features/snap/lazySession.js +17 -0
- package/dist/features/snap/lazySession.js.map +1 -0
- package/dist/features/snap/marks.js.map +1 -1
- package/dist/features/snap/probes2d.js +27 -19
- package/dist/features/snap/probes2d.js.map +1 -1
- package/dist/features/snap/readoutLayer.js.map +1 -1
- package/dist/features/snap/roles.js +2 -1
- package/dist/features/snap/roles.js.map +1 -1
- package/dist/features/snap/rotationSource.js +25 -8
- package/dist/features/snap/rotationSource.js.map +1 -1
- package/dist/features/snap/sceneSession2d.js +6 -4
- package/dist/features/snap/sceneSession2d.js.map +1 -1
- package/dist/features/snap/session2d.js +37 -23
- package/dist/features/snap/session2d.js.map +1 -1
- package/dist/features/snap/spanSnap.js +5 -2
- package/dist/features/snap/spanSnap.js.map +1 -1
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +0 -10
- package/dist/index.d.ts +701 -696
- package/dist/index.js +35 -29
- package/dist/interactions/actions/align/action.js +6 -4
- package/dist/interactions/actions/align/action.js.map +1 -1
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/action.js +7 -1
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/clone/action.js +1 -1
- package/dist/interactions/actions/clone/behaviors.js +4 -4
- package/dist/interactions/actions/clone/behaviors.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +1 -1
- package/dist/interactions/actions/defaults/delete.js +48 -39
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +1 -1
- package/dist/interactions/actions/defaults/group.js +2 -2
- package/dist/interactions/actions/defaults/ingest.js +7 -5
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +13 -38
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/distribute/action.js +6 -4
- package/dist/interactions/actions/distribute/action.js.map +1 -1
- package/dist/interactions/actions/drawnBoxes.js +2 -1
- package/dist/interactions/actions/drawnBoxes.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +3 -6
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js +41 -8
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +6 -4
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/gestureLifecycle.js +5 -2
- package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +1 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/commit.js +1 -1
- package/dist/interactions/actions/insert/parent.js +11 -0
- package/dist/interactions/actions/insert/parent.js.map +1 -0
- package/dist/interactions/actions/insert/placeAction.js +7 -2
- package/dist/interactions/actions/insert/placeAction.js.map +1 -1
- package/dist/interactions/actions/insert/session.js +5 -1
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +8 -4
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
- package/dist/interactions/actions/move/capture.js +1 -1
- package/dist/interactions/actions/move/commit/index.js +0 -2
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
- package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
- package/dist/interactions/actions/move/commit/reparent.js +11 -5
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +4 -10
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +20 -17
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +2 -1
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +18 -1
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +5 -5
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/session.js +14 -3
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +8 -37
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/moveNodes.js +87 -0
- package/dist/interactions/actions/moveNodes.js.map +1 -0
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +83 -72
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +2 -1
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/session.js +2 -0
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +3 -3
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +7 -4
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/commit.js +2 -1
- package/dist/interactions/actions/rotate/commit.js.map +1 -1
- package/dist/interactions/actions/rotate/session.js +2 -0
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +13 -2
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/testUtils.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +5 -6
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/interactions/actions/transformFinish.js +106 -0
- package/dist/interactions/actions/transformFinish.js.map +1 -0
- package/dist/kitSettingsSchema.js +0 -4
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/move.d.ts +5 -4
- package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
- package/dist/resize.d.ts +4 -3
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +2 -2
- package/dist/test-hook/createTestHook.js +1 -1
- package/dist/test-hook/createTestHook.js.map +1 -1
- package/dist/test-hook/useTestHook.js +2 -1
- package/dist/test-hook/useTestHook.js.map +1 -1
- package/dist/test-seams.d.ts +9 -5
- package/dist/tools/builtin/pen/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.js.map +1 -1
- package/dist/tools/index.js +26 -0
- package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
- package/dist/types-BN9hbdMI.d.ts +184 -0
- package/dist/types-CniVctmk.d.ts +949 -0
- package/dist/types-oFeQ5VjV.d.ts +264 -0
- package/dist/version.js +1 -1
- package/package.json +35 -25
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
- package/dist/tools/builtin/bone/boneActions.js +0 -156
- package/dist/tools/builtin/bone/boneActions.js.map +0 -1
- package/dist/tools/builtin/bone/boneOverlay.js +0 -71
- package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
- package/dist/tools/builtin/bone/placedRig.js +0 -28
- package/dist/tools/builtin/bone/placedRig.js.map +0 -1
- package/dist/tools/builtin/bone/rigEditState.js +0 -30
- package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
- package/dist/tools/builtin/bone/useBoneTool.js +0 -125
- package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
- package/dist/tools/builtin/weight/useWeightTool.js +0 -101
- package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
- package/dist/tools/builtin/weight/weightActions.js +0 -140
- package/dist/tools/builtin/weight/weightActions.js.map +0 -1
- package/dist/tools/builtin/weight/weightOverlay.js +0 -78
- package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":[],"sources":["../../../../src/interactions/actions/rotate/session.ts"],"sourcesContent":["import type { ActionDeps, BindingOpts, InvocationCtx } from '@weasel-js/routing';\nimport { pointerStateOf } from '../pointerState';\nimport { sceneGestureFrames } from '../gestureFrames';\nimport { resolveParams } from '@weasel-js/routing';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { gestureReaders, type GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { GestureContext, RotateBehavior } from '../../gestures/types';\nimport { readGestureLifecycle, type GestureLifecycle } from '../gestureLifecycle';\nimport { moveGestureAdapter } from '../move/gestureAdapter';\nimport { carryPose, invertPlane, planeOf } from '../planeInput';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport { shapeSources } from '../selectionSubtree';\nimport type { SnapBegin, SnapSession } from '../snapDep';\nimport { inputSession } from 'features/snap/session2d';\nimport { SNAP_ANGLE_STEP } from 'features/snap/roles';\n\n/** One rotated node as the press found it, in the plane the pointer's angle\n * is read in. */\nexport interface TurnOrigin {\n readonly world: unknown;\n /** Center of `world`'s bounds. */\n readonly center: { x: number; y: number };\n readonly rotation: number;\n}\n\n/** What a turn by some delta is computed from. */\nexport interface Turn {\n readonly origins: ReadonlyMap<NodeId, TurnOrigin>;\n /** The point the pointer orbits: the center of what the selection draws. */\n readonly pivot: { x: number; y: number };\n /** Orbit each node's center around `pivot`, for a multi-selection. Off,\n * each node turns about its own center. */\n readonly useUnionPivot: boolean;\n readonly descriptorOf: (id: NodeId) => PoseDescriptor<unknown>;\n}\n\n/** What a rotate captured at press. Nothing here changes during the drag. */\nexport interface RotateSession {\n readonly scene: Scene<unknown, string, unknown>;\n readonly ids: readonly NodeId[];\n readonly turn: Turn;\n /** World reads and local writes over the scene's composition strategy. */\n readonly poseFrame: PoseFrame<unknown>;\n readonly view: unknown;\n /** Each rotated node's pose as stored: the `from` of its op. */\n readonly originPoses: ReadonlyMap<NodeId, unknown>;\n /** Pointer angle around the pivot at press. */\n readonly startPointerAngle: number;\n /** The first rotated node's rotation at press: the angle that snaps. */\n readonly theta0: number;\n /** The drag's snapping: the `snap` dep's session, else one that only\n * steps while `snap.constrain` is held. */\n readonly snap: SnapSession;\n readonly behaviors: readonly RotateBehavior<unknown>[];\n /** Reused across the drag; behaviors mutate its `scratch`. */\n readonly gestureCtx: GestureContext<unknown>;\n readonly applyOps?: (ops: Op[], label: string) => void;\n readonly selectionMethods: SelectionApi['adapterMethods'] | undefined;\n readonly lifecycle: GestureLifecycle;\n}\n\n/** What one `onMove` produced. Replaced, not mutated, by the next. */\nexport interface RotateFrame {\n /** Radians turned since press, as the behaviors shaped it. */\n readonly delta: number;\n /** Stored-frame pose of every rotated id; empty at a zero delta. */\n readonly previews: Map<NodeId, unknown>;\n}\n\nfunction captureOrigins(\n view: unknown,\n scene: Scene<unknown, string, unknown>,\n ids: readonly NodeId[],\n descriptorOf: (id: NodeId) => PoseDescriptor<unknown>,\n poseFrame: PoseFrame<unknown>,\n boxes: DrawnBoxes,\n): { originPoses: Map<NodeId, unknown>; origins: Map<NodeId, TurnOrigin>; visual: Bounds[] } {\n const originPoses = new Map<NodeId, unknown>();\n const origins = new Map<NodeId, TurnOrigin>();\n const visual: Bounds[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const g = descriptorOf(id);\n if (!g.withRotation || g.supportsRotation?.(node.pose) === false) continue;\n originPoses.set(id, node.pose);\n // The pivot is a world point, so every measurement the gesture orbits\n // is taken from the world pose, not the stored one — carried into the\n // plane the edit is measured in, where the pointer's angle is read.\n const world = carryPose(g, poseFrame.world(id), invertPlane(planeOf(view, node.layer)));\n const b = g.getBounds(world);\n origins.set(id, {\n world,\n center: { x: b.x + b.width / 2, y: b.y + b.height / 2 },\n rotation: g.getRotation?.(world) ?? 0,\n });\n visual.push(boxes.aabb(id, world));\n }\n return { originPoses, origins, visual };\n}\n\nfunction buildGestureContext(\n ctx: InvocationCtx,\n scene: Scene<unknown, string, unknown>,\n origins: ReadonlyMap<NodeId, TurnOrigin>,\n readers: GestureReaders,\n selectionMethods: SelectionApi['adapterMethods'],\n): GestureContext<unknown> {\n return {\n draggedIds: [...origins.keys()] as string[],\n origin: new Map([...origins].map(([id, o]) => [id as string, o.world])),\n current: new Map([...origins].map(([id, o]) => [id as string, o.world])),\n snap: null,\n modifiers: { ...ctx.modifiers },\n pointer: pointerStateOf(ctx.world, ctx),\n view: readers.view(),\n plane: readers.plane(),\n kitSettings: readers.kitSettings,\n frames: sceneGestureFrames(scene, ctx.deps),\n adapter: moveGestureAdapter(scene, undefined, selectionMethods) as unknown as GestureContext<unknown>['adapter'],\n scratch: {},\n };\n}\n\n/** What turning `ids` (already resolved to shape sources) is computed from,\n * with each one's pose as stored. Null when none of them can turn. */\nexport function captureTurn(\n scene: Scene<unknown, string, unknown>,\n ids: readonly NodeId[],\n deps: Pick<ActionDeps, 'view' | 'poseDescriptor' | 'boundsIncludeStroke'>,\n pivot: 'union' | 'each',\n): { turn: Turn; originPoses: Map<NodeId, unknown>; poseFrame: PoseFrame<unknown> } | null {\n const view = deps.view;\n const descriptorOf = nodeDescriptors(scene, poseDescriptorOf(deps.poseDescriptor));\n // The pivot the pointer orbits is a world point, so every pose the\n // gesture turns is a world pose. Each turned result is stored back in\n // the node's own parent frame at preview and commit alike.\n const poseFrame = scenePoseFrame(scene);\n // A selection turns about the center of the box its chrome draws.\n const boxes = drawnBoxes({ ...deps, scene }, poseFrame);\n const { originPoses, origins, visual } = captureOrigins(view, scene, ids, descriptorOf, poseFrame, boxes);\n if (originPoses.size === 0) return null;\n const union = unionAABB(visual)!;\n return {\n turn: {\n origins,\n pivot: { x: union.x + union.width / 2, y: union.y + union.height / 2 },\n useUnionPivot: ids.length > 1 && pivot !== 'each',\n descriptorOf,\n },\n originPoses,\n poseFrame,\n };\n}\n\n/** The drag's snap session: the first rotated node's angle about the pivot,\n * stepping by `SNAP_ANGLE_STEP` while `snap.constrain` is held. */\nfunction beginSnap(ctx: InvocationCtx, ids: readonly string[], pivot: { x: number; y: number }, theta0: number): SnapSession {\n const req: SnapBegin = {\n gesture: 'rotate', ids, press: ctx.world, pivot, theta0, constrain: { step: SNAP_ANGLE_STEP },\n };\n return ctx.deps.snap?.begin(req) ?? inputSession(req);\n}\n\n/** Capture a rotate at press. Null when nothing selected can turn. Runs each\n * behavior's `onStart`. */\nexport function beginRotate(\n ctx: InvocationCtx,\n opts: BindingOpts | undefined,\n): { session: RotateSession; readers: GestureReaders } | null {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene;\n const params = resolveParams(opts?.params);\n const behaviors = (opts?.behaviors ?? []) as readonly RotateBehavior<unknown>[];\n\n if (!selection || !scene) return null;\n\n // A group whose pose derives from its children turns by turning them.\n const ids = shapeSources(scene, selection.get()) as NodeId[];\n if (ids.length === 0) return null;\n\n const captured = captureTurn(scene, ids, ctx.deps, params?.['pivot'] === 'each' ? 'each' : 'union');\n if (!captured) return null;\n const { turn, originPoses, poseFrame } = captured;\n const { origins, pivot } = turn;\n const readers = gestureReaders(ctx.deps);\n const gestureCtx = buildGestureContext(ctx, scene, origins, readers, selection.adapterMethods);\n for (const b of behaviors) b.onStart?.(gestureCtx);\n const theta0 = origins.values().next().value?.rotation ?? 0;\n\n const session: RotateSession = {\n scene,\n ids,\n turn,\n poseFrame,\n view: ctx.deps.view,\n originPoses,\n startPointerAngle: Math.atan2(ctx.world.y - pivot.y, ctx.world.x - pivot.x),\n theta0,\n snap: beginSnap(ctx, [...new Set([...selection.get(), ...ids])], pivot, theta0),\n behaviors,\n gestureCtx,\n applyOps: ctx.deps.applyOps,\n selectionMethods: selection.adapterMethods,\n lifecycle: readGestureLifecycle(params, 'Rotate', behaviors),\n };\n return { session, readers };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.js","names":[],"sources":["../../../../src/interactions/actions/rotate/session.ts"],"sourcesContent":["import type { ActionDeps, BindingOpts, InvocationCtx } from '@weasel-js/routing';\nimport { pointerStateOf } from '../pointerState';\nimport { transformFinisher, type TransformFinisher } from '../transformFinish';\nimport { sceneGestureFrames } from '../gestureFrames';\nimport { resolveParams } from '@weasel-js/routing';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { gestureReaders, type GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { GestureContext, RotateBehavior } from '../../gestures/types';\nimport { readGestureLifecycle, type GestureLifecycle } from '../gestureLifecycle';\nimport { moveGestureAdapter } from '../move/gestureAdapter';\nimport { carryPose, invertPlane, planeOf } from '../planeInput';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport { shapeSources } from '../selectionSubtree';\nimport type { SnapBegin, SnapSession } from '../snapDep';\nimport { inputSession } from 'features/snap/session2d';\nimport { SNAP_ANGLE_STEP } from 'features/snap/roles';\n\n/** One rotated node as the press found it, in the plane the pointer's angle\n * is read in. */\nexport interface TurnOrigin {\n readonly world: unknown;\n /** Center of `world`'s bounds. */\n readonly center: { x: number; y: number };\n readonly rotation: number;\n}\n\n/** What a turn by some delta is computed from. */\nexport interface Turn {\n readonly origins: ReadonlyMap<NodeId, TurnOrigin>;\n /** The point the pointer orbits: the center of what the selection draws. */\n readonly pivot: { x: number; y: number };\n /** Orbit each node's center around `pivot`, for a multi-selection. Off,\n * each node turns about its own center. */\n readonly useUnionPivot: boolean;\n readonly descriptorOf: (id: NodeId) => PoseDescriptor<unknown>;\n}\n\n/** What a rotate captured at press. Nothing here changes during the drag. */\nexport interface RotateSession {\n readonly scene: Scene<unknown, string, unknown>;\n readonly ids: readonly NodeId[];\n readonly turn: Turn;\n /** World reads and local writes over the scene's composition strategy. */\n readonly poseFrame: PoseFrame<unknown>;\n readonly view: unknown;\n /** Each rotated node's pose as stored: the `from` of its op. */\n readonly originPoses: ReadonlyMap<NodeId, unknown>;\n /** Pointer angle around the pivot at press. */\n readonly startPointerAngle: number;\n /** The first rotated node's rotation at press: the angle that snaps. */\n readonly theta0: number;\n /** The drag's snapping: the `snap` dep's session, else one that only\n * steps while `snap.constrain` is held. */\n readonly snap: SnapSession;\n readonly behaviors: readonly RotateBehavior<unknown>[];\n /** Reused across the drag; behaviors mutate its `scratch`. */\n readonly gestureCtx: GestureContext<unknown>;\n readonly applyOps?: (ops: Op[], label: string) => void;\n /** Finishes the committed batch with the other nodes that change with it. */\n readonly finish?: TransformFinisher;\n readonly selectionMethods: SelectionApi['adapterMethods'] | undefined;\n readonly lifecycle: GestureLifecycle;\n}\n\n/** What one `onMove` produced. Replaced, not mutated, by the next. */\nexport interface RotateFrame {\n /** Radians turned since press, as the behaviors shaped it. */\n readonly delta: number;\n /** Stored-frame pose of every rotated id; empty at a zero delta. */\n readonly previews: Map<NodeId, unknown>;\n}\n\nfunction captureOrigins(\n view: unknown,\n scene: Scene<unknown, string, unknown>,\n ids: readonly NodeId[],\n descriptorOf: (id: NodeId) => PoseDescriptor<unknown>,\n poseFrame: PoseFrame<unknown>,\n boxes: DrawnBoxes,\n): { originPoses: Map<NodeId, unknown>; origins: Map<NodeId, TurnOrigin>; visual: Bounds[] } {\n const originPoses = new Map<NodeId, unknown>();\n const origins = new Map<NodeId, TurnOrigin>();\n const visual: Bounds[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const g = descriptorOf(id);\n if (!g.withRotation || g.supportsRotation?.(node.pose) === false) continue;\n originPoses.set(id, node.pose);\n // The pivot is a world point, so every measurement the gesture orbits\n // is taken from the world pose, not the stored one — carried into the\n // plane the edit is measured in, where the pointer's angle is read.\n const world = carryPose(g, poseFrame.world(id), invertPlane(planeOf(view, node.layer)));\n const b = g.getBounds(world);\n origins.set(id, {\n world,\n center: { x: b.x + b.width / 2, y: b.y + b.height / 2 },\n rotation: g.getRotation?.(world) ?? 0,\n });\n visual.push(boxes.aabb(id, world));\n }\n return { originPoses, origins, visual };\n}\n\nfunction buildGestureContext(\n ctx: InvocationCtx,\n scene: Scene<unknown, string, unknown>,\n origins: ReadonlyMap<NodeId, TurnOrigin>,\n readers: GestureReaders,\n selectionMethods: SelectionApi['adapterMethods'],\n): GestureContext<unknown> {\n return {\n draggedIds: [...origins.keys()] as string[],\n origin: new Map([...origins].map(([id, o]) => [id as string, o.world])),\n current: new Map([...origins].map(([id, o]) => [id as string, o.world])),\n snap: null,\n modifiers: { ...ctx.modifiers },\n pointer: pointerStateOf(ctx.world, ctx),\n view: readers.view(),\n plane: readers.plane(),\n kitSettings: readers.kitSettings,\n frames: sceneGestureFrames(scene, ctx.deps),\n adapter: moveGestureAdapter(scene, undefined, selectionMethods) as unknown as GestureContext<unknown>['adapter'],\n scratch: {},\n };\n}\n\n/** What turning `ids` (already resolved to shape sources) is computed from,\n * with each one's pose as stored. Null when none of them can turn. */\nexport function captureTurn(\n scene: Scene<unknown, string, unknown>,\n ids: readonly NodeId[],\n deps: Pick<ActionDeps, 'view' | 'poseDescriptor' | 'boundsIncludeStroke'>,\n pivot: 'union' | 'each',\n): { turn: Turn; originPoses: Map<NodeId, unknown>; poseFrame: PoseFrame<unknown> } | null {\n const view = deps.view;\n const descriptorOf = nodeDescriptors(scene, poseDescriptorOf(deps.poseDescriptor));\n // The pivot the pointer orbits is a world point, so every pose the\n // gesture turns is a world pose. Each turned result is stored back in\n // the node's own parent frame at preview and commit alike.\n const poseFrame = scenePoseFrame(scene);\n // A selection turns about the center of the box its chrome draws.\n const boxes = drawnBoxes({ ...deps, scene }, poseFrame);\n const { originPoses, origins, visual } = captureOrigins(view, scene, ids, descriptorOf, poseFrame, boxes);\n if (originPoses.size === 0) return null;\n const union = unionAABB(visual)!;\n return {\n turn: {\n origins,\n pivot: { x: union.x + union.width / 2, y: union.y + union.height / 2 },\n useUnionPivot: ids.length > 1 && pivot !== 'each',\n descriptorOf,\n },\n originPoses,\n poseFrame,\n };\n}\n\n/** The drag's snap session: the first rotated node's angle about the pivot,\n * stepping by `SNAP_ANGLE_STEP` while `snap.constrain` is held. */\nfunction beginSnap(ctx: InvocationCtx, ids: readonly string[], pivot: { x: number; y: number }, theta0: number): SnapSession {\n const req: SnapBegin = {\n gesture: 'rotate', ids, press: ctx.world, pivot, theta0, constrain: { step: SNAP_ANGLE_STEP },\n };\n return ctx.deps.snap?.begin(req) ?? inputSession(req);\n}\n\n/** Capture a rotate at press. Null when nothing selected can turn. Runs each\n * behavior's `onStart`. */\nexport function beginRotate(\n ctx: InvocationCtx,\n opts: BindingOpts | undefined,\n): { session: RotateSession; readers: GestureReaders } | null {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene;\n const params = resolveParams(opts?.params);\n const behaviors = (opts?.behaviors ?? []) as readonly RotateBehavior<unknown>[];\n\n if (!selection || !scene) return null;\n\n // A group whose pose derives from its children turns by turning them.\n const ids = shapeSources(scene, selection.get()) as NodeId[];\n if (ids.length === 0) return null;\n\n const captured = captureTurn(scene, ids, ctx.deps, params?.['pivot'] === 'each' ? 'each' : 'union');\n if (!captured) return null;\n const { turn, originPoses, poseFrame } = captured;\n const { origins, pivot } = turn;\n const readers = gestureReaders(ctx.deps);\n const gestureCtx = buildGestureContext(ctx, scene, origins, readers, selection.adapterMethods);\n for (const b of behaviors) b.onStart?.(gestureCtx);\n const theta0 = origins.values().next().value?.rotation ?? 0;\n\n const session: RotateSession = {\n scene,\n ids,\n turn,\n poseFrame,\n view: ctx.deps.view,\n originPoses,\n startPointerAngle: Math.atan2(ctx.world.y - pivot.y, ctx.world.x - pivot.x),\n theta0,\n snap: beginSnap(ctx, [...new Set([...selection.get(), ...ids])], pivot, theta0),\n behaviors,\n gestureCtx,\n applyOps: ctx.deps.applyOps,\n finish: transformFinisher(ctx.deps),\n selectionMethods: selection.adapterMethods,\n lifecycle: readGestureLifecycle(params, 'Rotate', behaviors),\n };\n return { session, readers };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { poseDescriptorForNode, translatePoseViaDescriptor } from "../../core/geometry/poseDescriptor.js";
|
|
2
2
|
import { asNodeId } from "../../core/scene/types.js";
|
|
3
|
+
import { sceneMutators } from "../../core/scene/sceneMutators.js";
|
|
4
|
+
import { createTransformOp } from "../../core/ops/transform.js";
|
|
3
5
|
|
|
4
6
|
//#region src/interactions/actions/selectionSubtree.ts
|
|
5
7
|
/** True when any ancestor of `id` is also in `set` — acting on that ancestor
|
|
@@ -100,7 +102,7 @@ function translateTargets(scene, frame, ids) {
|
|
|
100
102
|
* world pose is read before the first write, so one move cannot shift what a
|
|
101
103
|
* later one reads. Call inside a `scene.batch`.
|
|
102
104
|
*/
|
|
103
|
-
function translateEach(scene, frame, descriptor, moves) {
|
|
105
|
+
function translateEach(scene, frame, descriptor, moves, finish, label = "Translate") {
|
|
104
106
|
const writes = [];
|
|
105
107
|
const seen = /* @__PURE__ */ new Set();
|
|
106
108
|
for (const { id, dx, dy } of moves) {
|
|
@@ -117,7 +119,16 @@ function translateEach(scene, frame, descriptor, moves) {
|
|
|
117
119
|
});
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
|
-
|
|
122
|
+
const ops = writes.map(({ id, to }) => createTransformOp({
|
|
123
|
+
id,
|
|
124
|
+
from: scene.get(id).pose,
|
|
125
|
+
to,
|
|
126
|
+
label
|
|
127
|
+
}));
|
|
128
|
+
const all = finish && ops.length > 0 ? finish(ops, label) : ops;
|
|
129
|
+
if (!all) return;
|
|
130
|
+
const adapter = sceneMutators(scene);
|
|
131
|
+
for (const op of all) op.apply(adapter);
|
|
121
132
|
}
|
|
122
133
|
/** The world translation `(dx, dy)` as a translation of `id`'s stored pose,
|
|
123
134
|
* which under a turned frame points another way. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selectionSubtree.js","names":[],"sources":["../../../src/interactions/actions/selectionSubtree.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { PoseFrame } from './poseFrame';\nimport { poseDescriptorForNode, translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\n\ntype AnyScene = Scene<unknown, string, unknown>;\n\n/** True when any ancestor of `id` is also in `set` — acting on that ancestor\n * already reaches this node, so acting on it again would double it. */\nexport function hasSelectedAncestor(scene: AnyScene, id: NodeId, set: ReadonlySet<string>): boolean {\n let parent = scene.get(id)?.parent ?? null;\n while (parent != null) {\n if (set.has(parent)) return true;\n parent = scene.get(parent)?.parent ?? null;\n }\n return false;\n}\n\n/** The ids in `ids` that are in the scene and have no selected ancestor. */\nexport function selectedRoots(scene: AnyScene, ids: readonly string[]): NodeId[] {\n const set = new Set<string>(ids);\n return ids\n .map((id) => asNodeId(id))\n .filter((id) => scene.get(id) !== undefined && !hasSelectedAncestor(scene, id, set));\n}\n\n/** Whether `id` draws a path derived from other nodes. Its pose is a\n * placeholder: the path follows the nodes it derives from. */\nfunction derivesPathOnly(scene: AnyScene, id: string): boolean {\n const node = scene.get(asNodeId(id));\n return node?.derivePath !== undefined && node.derivePose === undefined\n && Array.isArray(node.dependsOn) && node.dependsOn.length > 0;\n}\n\n/**\n * The nodes a translation of `ids` has to act on. A node whose pose is derived\n * from an id list cannot be moved itself, since a pose written to it is\n * overwritten on the next read, so the nodes it derives from stand in for it,\n * through however many derived nodes that takes. A node reached that way which\n * derives only its path — a wire under a label — follows its own dependencies\n * and is not written. Each id appears once, in the order it was first reached.\n */\nexport function moveSources(scene: AnyScene, ids: readonly string[]): string[] {\n const out = new Set<string>();\n const walked = new Set<string>();\n const visit = (id: string, reached: boolean): void => {\n if (walked.has(id)) return;\n walked.add(id);\n if (reached && derivesPathOnly(scene, id)) return;\n const node = scene.get(asNodeId(id));\n const deps = node?.derivePose !== undefined && Array.isArray(node.dependsOn) ? node.dependsOn : [];\n if (deps.length === 0) out.add(id);\n else for (const dep of deps) visit(dep, true);\n };\n for (const id of ids) visit(id, false);\n return [...out];\n}\n\n/**\n * The nodes a resize, rotation, flip, or alignment of `ids` has to write. A\n * node whose pose is derived cannot be written itself, so what it derives\n * from stands in for it — a container's children, or the ids a node names —\n * through however many derived nodes that takes, leaving out one reached that\n * way which derives only its path, as {@link moveSources} does. Each id appears once, in the order it\n * was first reached.\n */\nexport function shapeSources(scene: AnyScene, ids: readonly string[]): string[] {\n const out = new Set<string>();\n const walked = new Set<string>();\n const visit = (id: string, reached: boolean): void => {\n if (walked.has(id)) return;\n walked.add(id);\n if (reached && derivesPathOnly(scene, id)) return;\n const node = scene.get(asNodeId(id));\n const deps = node?.derivePose === undefined\n ? []\n : node.dependsOn === 'children' ? scene.childrenOf(asNodeId(id)) : node.dependsOn ?? [];\n if (deps.length === 0 && node?.dependsOn !== 'children') out.add(id);\n else for (const dep of deps) visit(dep, true);\n };\n for (const id of ids) visit(id, false);\n return [...out];\n}\n\n/** `id` and everything under it, a parent ahead of its children. */\nexport function subtreeIds(scene: AnyScene, id: NodeId): NodeId[] {\n const out: NodeId[] = [];\n const walk = (at: NodeId): void => {\n out.push(at);\n for (const child of scene.childrenOf(at)) walk(child);\n };\n walk(id);\n return out;\n}\n\n/**\n * The nodes whose stored pose has to change for `ids` to move as a unit: each\n * selected node and its descendants, less any stored in the frame of another\n * node in the set, which that frame carries. With the default absolute poses\n * nothing is carried and every descendant is written.\n */\nexport function translateTargets(\n scene: AnyScene,\n frame: PoseFrame<unknown>,\n ids: readonly string[],\n): NodeId[] {\n const moving = new Set<NodeId>();\n for (const root of selectedRoots(scene, ids)) {\n for (const id of subtreeIds(scene, root)) moving.add(id);\n }\n if (frame.pc.closure === 'identity') return [...moving];\n return [...moving].filter((id) => {\n const storedIn = frame.frame(id);\n return storedIn === null || !moving.has(storedIn);\n });\n}\n\n/**\n * Move each of `moves` by its own delta, taking along whatever has to be\n * written for that node to move as a unit ({@link translateTargets}). Every\n * world pose is read before the first write, so one move cannot shift what a\n * later one reads. Call inside a `scene.batch`.\n */\nexport function translateEach(\n scene: AnyScene,\n frame: PoseFrame<unknown>,\n descriptor: PoseDescriptor<unknown>,\n moves: readonly { id: string; dx: number; dy: number }[],\n): void {\n const writes: { id: NodeId; to: unknown }[] = [];\n const seen = new Set<NodeId>();\n for (const { id, dx, dy } of moves) {\n if (dx === 0 && dy === 0) continue;\n for (const target of translateTargets(scene, frame, [id])) {\n if (seen.has(target)) continue;\n seen.add(target);\n const node = scene.get(target);\n if (!node) continue;\n const d = poseDescriptorForNode(descriptor, node);\n writes.push({ id: target, to: frame.local(target, translatePoseViaDescriptor(frame.world(target), dx, dy, d)) });\n }\n }\n for (const { id, to } of writes) scene.setPose(id, to);\n}\n\n/** The world translation `(dx, dy)` as a translation of `id`'s stored pose,\n * which under a turned frame points another way. */\nexport function storedDelta(\n frame: PoseFrame<unknown>,\n descriptor: PoseDescriptor<unknown>,\n id: NodeId,\n dx: number,\n dy: number,\n): { dx: number; dy: number } {\n if (frame.pc.closure === 'identity' || frame.frame(id) === null) return { dx, dy };\n const world = frame.world(id);\n const from = descriptor.getBounds(frame.local(id, world));\n const to = descriptor.getBounds(frame.local(id, translatePoseViaDescriptor(world, dx, dy, descriptor)));\n return { dx: to.x - from.x, dy: to.y - from.y };\n}\n"],"mappings":";;;;;;AASA,SAAgB,oBAAoB,OAAiB,IAAY,KAAmC;CAClG,IAAI,SAAS,MAAM,IAAI,EAAE,CAAC,EAAE,UAAU;CACtC,OAAO,UAAU,MAAM;EACrB,IAAI,IAAI,IAAI,MAAM,GAAG,OAAO;EAC5B,SAAS,MAAM,IAAI,MAAM,CAAC,EAAE,UAAU;CACxC;CACA,OAAO;AACT;;AAGA,SAAgB,cAAc,OAAiB,KAAkC;CAC/E,MAAM,MAAM,IAAI,IAAY,GAAG;CAC/B,OAAO,IACJ,KAAK,OAAO,SAAS,EAAE,CAAC,CAAC,CACzB,QAAQ,OAAO,MAAM,IAAI,EAAE,MAAM,UAAa,CAAC,oBAAoB,OAAO,IAAI,GAAG,CAAC;AACvF;;;AAIA,SAAS,gBAAgB,OAAiB,IAAqB;CAC7D,MAAM,OAAO,MAAM,IAAI,SAAS,EAAE,CAAC;CACnC,OAAO,MAAM,eAAe,UAAa,KAAK,eAAe,UACxD,MAAM,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,SAAS;AAChE;;;;;;;;;AAUA,SAAgB,YAAY,OAAiB,KAAkC;CAC7E,MAAM,sBAAM,IAAI,IAAY;CAC5B,MAAM,yBAAS,IAAI,IAAY;CAC/B,MAAM,SAAS,IAAY,YAA2B;EACpD,IAAI,OAAO,IAAI,EAAE,GAAG;EACpB,OAAO,IAAI,EAAE;EACb,IAAI,WAAW,gBAAgB,OAAO,EAAE,GAAG;EAC3C,MAAM,OAAO,MAAM,IAAI,SAAS,EAAE,CAAC;EACnC,MAAM,OAAO,MAAM,eAAe,UAAa,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;EACjG,IAAI,KAAK,WAAW,GAAG,IAAI,IAAI,EAAE;OAC5B,KAAK,MAAM,OAAO,MAAM,MAAM,KAAK,IAAI;CAC9C;CACA,KAAK,MAAM,MAAM,KAAK,MAAM,IAAI,KAAK;CACrC,OAAO,CAAC,GAAG,GAAG;AAChB;;;;;;;;;AAUA,SAAgB,aAAa,OAAiB,KAAkC;CAC9E,MAAM,sBAAM,IAAI,IAAY;CAC5B,MAAM,yBAAS,IAAI,IAAY;CAC/B,MAAM,SAAS,IAAY,YAA2B;EACpD,IAAI,OAAO,IAAI,EAAE,GAAG;EACpB,OAAO,IAAI,EAAE;EACb,IAAI,WAAW,gBAAgB,OAAO,EAAE,GAAG;EAC3C,MAAM,OAAO,MAAM,IAAI,SAAS,EAAE,CAAC;EACnC,MAAM,OAAO,MAAM,eAAe,SAC9B,CAAC,IACD,KAAK,cAAc,aAAa,MAAM,WAAW,SAAS,EAAE,CAAC,IAAI,KAAK,aAAa,CAAC;EACxF,IAAI,KAAK,WAAW,KAAK,MAAM,cAAc,YAAY,IAAI,IAAI,EAAE;OAC9D,KAAK,MAAM,OAAO,MAAM,MAAM,KAAK,IAAI;CAC9C;CACA,KAAK,MAAM,MAAM,KAAK,MAAM,IAAI,KAAK;CACrC,OAAO,CAAC,GAAG,GAAG;AAChB;;AAGA,SAAgB,WAAW,OAAiB,IAAsB;CAChE,MAAM,MAAgB,CAAC;CACvB,MAAM,QAAQ,OAAqB;EACjC,IAAI,KAAK,EAAE;EACX,KAAK,MAAM,SAAS,MAAM,WAAW,EAAE,GAAG,KAAK,KAAK;CACtD;CACA,KAAK,EAAE;CACP,OAAO;AACT;;;;;;;AAQA,SAAgB,iBACd,OACA,OACA,KACU;CACV,MAAM,yBAAS,IAAI,IAAY;CAC/B,KAAK,MAAM,QAAQ,cAAc,OAAO,GAAG,GACzC,KAAK,MAAM,MAAM,WAAW,OAAO,IAAI,GAAG,OAAO,IAAI,EAAE;CAEzD,IAAI,MAAM,GAAG,YAAY,YAAY,OAAO,CAAC,GAAG,MAAM;CACtD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,OAAO;EAChC,MAAM,WAAW,MAAM,MAAM,EAAE;EAC/B,OAAO,aAAa,QAAQ,CAAC,OAAO,IAAI,QAAQ;CAClD,CAAC;AACH;;;;;;;AAQA,SAAgB,cACd,OACA,OACA,YACA,OACM;CACN,MAAM,SAAwC,CAAC;CAC/C,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,QAAQ,OAAO;EAClC,IAAI,OAAO,KAAK,OAAO,GAAG;EAC1B,KAAK,MAAM,UAAU,iBAAiB,OAAO,OAAO,CAAC,EAAE,CAAC,GAAG;GACzD,IAAI,KAAK,IAAI,MAAM,GAAG;GACtB,KAAK,IAAI,MAAM;GACf,MAAM,OAAO,MAAM,IAAI,MAAM;GAC7B,IAAI,CAAC,MAAM;GACX,MAAM,IAAI,sBAAsB,YAAY,IAAI;GAChD,OAAO,KAAK;IAAE,IAAI;IAAQ,IAAI,MAAM,MAAM,QAAQ,2BAA2B,MAAM,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,CAAC;GAAE,CAAC;EACjH;CACF;CACA,KAAK,MAAM,EAAE,IAAI,QAAQ,QAAQ,MAAM,QAAQ,IAAI,EAAE;AACvD;;;AAIA,SAAgB,YACd,OACA,YACA,IACA,IACA,IAC4B;CAC5B,IAAI,MAAM,GAAG,YAAY,cAAc,MAAM,MAAM,EAAE,MAAM,MAAM,OAAO;EAAE;EAAI;CAAG;CACjF,MAAM,QAAQ,MAAM,MAAM,EAAE;CAC5B,MAAM,OAAO,WAAW,UAAU,MAAM,MAAM,IAAI,KAAK,CAAC;CACxD,MAAM,KAAK,WAAW,UAAU,MAAM,MAAM,IAAI,2BAA2B,OAAO,IAAI,IAAI,UAAU,CAAC,CAAC;CACtG,OAAO;EAAE,IAAI,GAAG,IAAI,KAAK;EAAG,IAAI,GAAG,IAAI,KAAK;CAAE;AAChD"}
|
|
1
|
+
{"version":3,"file":"selectionSubtree.js","names":[],"sources":["../../../src/interactions/actions/selectionSubtree.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { PoseFrame } from './poseFrame';\nimport type { TransformFinisher } from './transformFinish';\nimport { createTransformOp } from 'core/ops/transform';\nimport { sceneMutators } from 'core/scene/sceneMutators';\nimport { poseDescriptorForNode, translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\n\ntype AnyScene = Scene<unknown, string, unknown>;\n\n/** True when any ancestor of `id` is also in `set` — acting on that ancestor\n * already reaches this node, so acting on it again would double it. */\nexport function hasSelectedAncestor(scene: AnyScene, id: NodeId, set: ReadonlySet<string>): boolean {\n let parent = scene.get(id)?.parent ?? null;\n while (parent != null) {\n if (set.has(parent)) return true;\n parent = scene.get(parent)?.parent ?? null;\n }\n return false;\n}\n\n/** The ids in `ids` that are in the scene and have no selected ancestor. */\nexport function selectedRoots(scene: AnyScene, ids: readonly string[]): NodeId[] {\n const set = new Set<string>(ids);\n return ids\n .map((id) => asNodeId(id))\n .filter((id) => scene.get(id) !== undefined && !hasSelectedAncestor(scene, id, set));\n}\n\n/** Whether `id` draws a path derived from other nodes. Its pose is a\n * placeholder: the path follows the nodes it derives from. */\nfunction derivesPathOnly(scene: AnyScene, id: string): boolean {\n const node = scene.get(asNodeId(id));\n return node?.derivePath !== undefined && node.derivePose === undefined\n && Array.isArray(node.dependsOn) && node.dependsOn.length > 0;\n}\n\n/**\n * The nodes a translation of `ids` has to act on. A node whose pose is derived\n * from an id list cannot be moved itself, since a pose written to it is\n * overwritten on the next read, so the nodes it derives from stand in for it,\n * through however many derived nodes that takes. A node reached that way which\n * derives only its path — a wire under a label — follows its own dependencies\n * and is not written. Each id appears once, in the order it was first reached.\n */\nexport function moveSources(scene: AnyScene, ids: readonly string[]): string[] {\n const out = new Set<string>();\n const walked = new Set<string>();\n const visit = (id: string, reached: boolean): void => {\n if (walked.has(id)) return;\n walked.add(id);\n if (reached && derivesPathOnly(scene, id)) return;\n const node = scene.get(asNodeId(id));\n const deps = node?.derivePose !== undefined && Array.isArray(node.dependsOn) ? node.dependsOn : [];\n if (deps.length === 0) out.add(id);\n else for (const dep of deps) visit(dep, true);\n };\n for (const id of ids) visit(id, false);\n return [...out];\n}\n\n/**\n * The nodes a resize, rotation, flip, or alignment of `ids` has to write. A\n * node whose pose is derived cannot be written itself, so what it derives\n * from stands in for it — a container's children, or the ids a node names —\n * through however many derived nodes that takes, leaving out one reached that\n * way which derives only its path, as {@link moveSources} does. Each id appears once, in the order it\n * was first reached.\n */\nexport function shapeSources(scene: AnyScene, ids: readonly string[]): string[] {\n const out = new Set<string>();\n const walked = new Set<string>();\n const visit = (id: string, reached: boolean): void => {\n if (walked.has(id)) return;\n walked.add(id);\n if (reached && derivesPathOnly(scene, id)) return;\n const node = scene.get(asNodeId(id));\n const deps = node?.derivePose === undefined\n ? []\n : node.dependsOn === 'children' ? scene.childrenOf(asNodeId(id)) : node.dependsOn ?? [];\n if (deps.length === 0 && node?.dependsOn !== 'children') out.add(id);\n else for (const dep of deps) visit(dep, true);\n };\n for (const id of ids) visit(id, false);\n return [...out];\n}\n\n/** `id` and everything under it, a parent ahead of its children. */\nexport function subtreeIds(scene: AnyScene, id: NodeId): NodeId[] {\n const out: NodeId[] = [];\n const walk = (at: NodeId): void => {\n out.push(at);\n for (const child of scene.childrenOf(at)) walk(child);\n };\n walk(id);\n return out;\n}\n\n/**\n * The nodes whose stored pose has to change for `ids` to move as a unit: each\n * selected node and its descendants, less any stored in the frame of another\n * node in the set, which that frame carries. With the default absolute poses\n * nothing is carried and every descendant is written.\n */\nexport function translateTargets(\n scene: AnyScene,\n frame: PoseFrame<unknown>,\n ids: readonly string[],\n): NodeId[] {\n const moving = new Set<NodeId>();\n for (const root of selectedRoots(scene, ids)) {\n for (const id of subtreeIds(scene, root)) moving.add(id);\n }\n if (frame.pc.closure === 'identity') return [...moving];\n return [...moving].filter((id) => {\n const storedIn = frame.frame(id);\n return storedIn === null || !moving.has(storedIn);\n });\n}\n\n/**\n * Move each of `moves` by its own delta, taking along whatever has to be\n * written for that node to move as a unit ({@link translateTargets}). Every\n * world pose is read before the first write, so one move cannot shift what a\n * later one reads. Call inside a `scene.batch`.\n */\nexport function translateEach(\n scene: AnyScene,\n frame: PoseFrame<unknown>,\n descriptor: PoseDescriptor<unknown>,\n moves: readonly { id: string; dx: number; dy: number }[],\n finish?: TransformFinisher,\n label = 'Translate',\n): void {\n const writes: { id: NodeId; to: unknown }[] = [];\n const seen = new Set<NodeId>();\n for (const { id, dx, dy } of moves) {\n if (dx === 0 && dy === 0) continue;\n for (const target of translateTargets(scene, frame, [id])) {\n if (seen.has(target)) continue;\n seen.add(target);\n const node = scene.get(target);\n if (!node) continue;\n const d = poseDescriptorForNode(descriptor, node);\n writes.push({ id: target, to: frame.local(target, translatePoseViaDescriptor(frame.world(target), dx, dy, d)) });\n }\n }\n const ops = writes.map(({ id, to }) => createTransformOp({ id, from: scene.get(id)!.pose, to, label }));\n const all = finish && ops.length > 0 ? finish(ops, label) : ops;\n if (!all) return;\n const adapter = sceneMutators(scene);\n for (const op of all) op.apply(adapter);\n}\n\n/** The world translation `(dx, dy)` as a translation of `id`'s stored pose,\n * which under a turned frame points another way. */\nexport function storedDelta(\n frame: PoseFrame<unknown>,\n descriptor: PoseDescriptor<unknown>,\n id: NodeId,\n dx: number,\n dy: number,\n): { dx: number; dy: number } {\n if (frame.pc.closure === 'identity' || frame.frame(id) === null) return { dx, dy };\n const world = frame.world(id);\n const from = descriptor.getBounds(frame.local(id, world));\n const to = descriptor.getBounds(frame.local(id, translatePoseViaDescriptor(world, dx, dy, descriptor)));\n return { dx: to.x - from.x, dy: to.y - from.y };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.js","names":[],"sources":["../../../src/interactions/actions/testUtils.ts"],"sourcesContent":["import type { ActionDeps } from '@weasel-js/routing';\nimport type { MoveEnd } from '../gestures/types';\nimport type { EditAnchorsDep } from './depSchema';\n\n/**\n * Deps for an action unit test, stubbing only the slice the action reads.\n * Such stubs fall short of the full `DepSchema` types an action's deps carry,\n * and this is where they are let through.\n */\nexport function stubDeps(deps: Record<string, unknown>): ActionDeps {\n return deps as ActionDeps;\n}\n\n/**\n * What a move behavior's `onEnd` is told, for a test calling it directly:\n * unanswered and released at the world origin, with a `translateOps` that\n * emits nothing unless one is given.\n */\nexport function moveEnd(translateOps: MoveEnd['translateOps'] = () => []): MoveEnd {\n return { answered: false, translateOps, pointer: { x: 0, y: 0 } };\n}\n\n/**\n * Build an inert {@link EditAnchorsDep} for action unit tests. Every\n * member has a harmless default; override just the ones a test cares\n * about.\n *\n * Anchor selection and the marquee default to a **live** in-memory store\n * rather than a no-op, because most anchor-editing actions read back what\n * they wrote (select-then-nudge, marquee-then-delete). A test that wants\n * to assert the write instead of the round trip can pass its own spies.\n */\nexport function makeEditAnchorsDep(over: Partial<EditAnchorsDep> = {}): EditAnchorsDep {\n let selected: ReadonlySet<number> = new Set();\n let marquee: EditAnchorsDep['marquee'] = null;\n let handleLocks: EditAnchorsDep['handleLocks'];\n let tool: string | null = null;\n const base: EditAnchorsDep = {\n get handleLocks() {\n return handleLocks;\n },\n setHandleLocks(next) {\n handleLocks = next;\n },\n editingId: 'node-a',\n setEditingId: () => {},\n getStorageKind: () => 'pose',\n getNodeShape: () => null,\n getEditablePath: () => null,\n applyEdit: () => {},\n get selectedAnchors() {\n return selected;\n },\n setSelectedAnchors(next: Iterable<number>) {\n selected = new Set(next);\n },\n get marquee() {\n return marquee;\n },\n setMarquee(rect) {\n marquee = rect;\n },\n get tool() {\n return tool;\n },\n setTool(id) {\n tool = id;\n },\n };\n // Spread order matters: an explicit `selectedAnchors` / `marquee`\n // override must win over the accessor pair above, so copy descriptors\n // rather than plain-assigning (a getter would otherwise be clobbered by\n // an undefined value or survive a legitimate override).\n return Object.defineProperties(\n base,\n Object.getOwnPropertyDescriptors(over),\n ) as EditAnchorsDep;\n}\n"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"testUtils.js","names":[],"sources":["../../../src/interactions/actions/testUtils.ts"],"sourcesContent":["import type { NodeId, PoseOverrides } from 'core/scene/types';\nimport type { ActionDeps } from '@weasel-js/routing';\nimport type { MoveEnd } from '../gestures/types';\nimport type { EditAnchorsDep } from './depSchema';\n\n/**\n * Deps for an action unit test, stubbing only the slice the action reads.\n * Such stubs fall short of the full `DepSchema` types an action's deps carry,\n * and this is where they are let through.\n */\nexport function stubDeps(deps: Record<string, unknown>): ActionDeps {\n return deps as ActionDeps;\n}\n\n/**\n * What a move behavior's `onEnd` is told, for a test calling it directly:\n * unanswered and released at the world origin, with a `translateOps` that\n * emits nothing unless one is given.\n */\nexport function moveEnd(translateOps: MoveEnd['translateOps'] = () => []): MoveEnd {\n return { answered: false, translateOps, pointer: { x: 0, y: 0 } };\n}\n\n/**\n * Build an inert {@link EditAnchorsDep} for action unit tests. Every\n * member has a harmless default; override just the ones a test cares\n * about.\n *\n * Anchor selection and the marquee default to a **live** in-memory store\n * rather than a no-op, because most anchor-editing actions read back what\n * they wrote (select-then-nudge, marquee-then-delete). A test that wants\n * to assert the write instead of the round trip can pass its own spies.\n */\nexport function makeEditAnchorsDep(over: Partial<EditAnchorsDep> = {}): EditAnchorsDep {\n let selected: ReadonlySet<number> = new Set();\n let marquee: EditAnchorsDep['marquee'] = null;\n let handleLocks: EditAnchorsDep['handleLocks'];\n let tool: string | null = null;\n const base: EditAnchorsDep = {\n get handleLocks() {\n return handleLocks;\n },\n setHandleLocks(next) {\n handleLocks = next;\n },\n editingId: 'node-a',\n setEditingId: () => {},\n getStorageKind: () => 'pose',\n getNodeShape: () => null,\n getEditablePath: () => null,\n applyEdit: () => {},\n get selectedAnchors() {\n return selected;\n },\n setSelectedAnchors(next: Iterable<number>) {\n selected = new Set(next);\n },\n get marquee() {\n return marquee;\n },\n setMarquee(rect) {\n marquee = rect;\n },\n get tool() {\n return tool;\n },\n setTool(id) {\n tool = id;\n },\n };\n // Spread order matters: an explicit `selectedAnchors` / `marquee`\n // override must win over the accessor pair above, so copy descriptors\n // rather than plain-assigning (a getter would otherwise be clobbered by\n // an undefined value or survive a legitimate override).\n return Object.defineProperties(\n base,\n Object.getOwnPropertyDescriptors(over),\n ) as EditAnchorsDep;\n}\n\n/** The pose a transform drag publishes for `id` to the scene's overrides, or\n * null: where the drag shows it, since its handle carries no pose. */\nexport function heldPose(scene: unknown, id: string): unknown {\n return (scene as { overrides: PoseOverrides<unknown> }).overrides.read(id as NodeId)?.pose ?? null;\n}\n"],"mappings":";;;;;;;;;;;AAiCA,SAAgB,mBAAmB,OAAgC,CAAC,GAAmB;CACrF,IAAI,2BAAgC,IAAI,IAAI;CAC5C,IAAI,UAAqC;CACzC,IAAI;CACJ,IAAI,OAAsB;CAqC1B,OAAO,OAAO,iBACZ;EApCA,IAAI,cAAc;GAChB,OAAO;EACT;EACA,eAAe,MAAM;GACnB,cAAc;EAChB;EACA,WAAW;EACX,oBAAoB,CAAC;EACrB,sBAAsB;EACtB,oBAAoB;EACpB,uBAAuB;EACvB,iBAAiB,CAAC;EAClB,IAAI,kBAAkB;GACpB,OAAO;EACT;EACA,mBAAmB,MAAwB;GACzC,WAAW,IAAI,IAAI,IAAI;EACzB;EACA,IAAI,UAAU;GACZ,OAAO;EACT;EACA,WAAW,MAAM;GACf,UAAU;EACZ;EACA,IAAI,OAAO;GACT,OAAO;EACT;EACA,QAAQ,IAAI;GACV,OAAO;EACT;CAOA,GACA,OAAO,0BAA0B,IAAI,CACvC;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { poseDescriptorOf } from "../poseDescriptorDep.js";
|
|
2
|
-
import {
|
|
2
|
+
import { commitTransformOps, transformApplyOps } from "../transformFinish.js";
|
|
3
3
|
import { lastTransform, recordTransform } from "./memory.js";
|
|
4
4
|
import { requiresSelection } from "../defaults/requiresSelection.js";
|
|
5
5
|
import { resizeSelectionOps } from "../resize/replay.js";
|
|
@@ -16,9 +16,7 @@ var FIRST = {
|
|
|
16
16
|
dy: DUPLICATE_OFFSET
|
|
17
17
|
};
|
|
18
18
|
function commit(deps, ops) {
|
|
19
|
-
|
|
20
|
-
commitOps(deps, ops, LABEL);
|
|
21
|
-
return true;
|
|
19
|
+
return commitTransformOps(deps, ops, LABEL);
|
|
22
20
|
}
|
|
23
21
|
/** Apply `t` to the selection as one undo entry. Returns the ids selected
|
|
24
22
|
* afterwards, or null when nothing changed. */
|
|
@@ -27,7 +25,7 @@ function replay(deps, scene, t) {
|
|
|
27
25
|
const selected = selection.get();
|
|
28
26
|
switch (t.kind) {
|
|
29
27
|
case "duplicate": return duplicateSelection(deps, t.dx, t.dy, LABEL);
|
|
30
|
-
case "translate": return translateSelection(selection, scene, t.dx, t.dy, deps
|
|
28
|
+
case "translate": return translateSelection(selection, scene, t.dx, t.dy, transformApplyOps(deps), deps.geometryProjection, poseDescriptorOf(deps.poseDescriptor), LABEL) ? selected : null;
|
|
31
29
|
case "rotate": return commit(deps, rotateSelectionOps(scene, selected, deps, t.angle, t.pivot, LABEL)) ? selected : null;
|
|
32
30
|
case "scale": return commit(deps, resizeSelectionOps(scene, selected, t.anchor, t.to, deps, LABEL)) ? selected : null;
|
|
33
31
|
}
|
|
@@ -58,7 +56,8 @@ var transformAgainAction = {
|
|
|
58
56
|
"geometryProjection",
|
|
59
57
|
"resizePolicy",
|
|
60
58
|
"view",
|
|
61
|
-
"boundsIncludeStroke"
|
|
59
|
+
"boundsIncludeStroke",
|
|
60
|
+
"transformFollowers"
|
|
62
61
|
],
|
|
63
62
|
invoker: {
|
|
64
63
|
timing: "immediate",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/transform-again/action.ts"],"sourcesContent":["import type { Action, ActionDeps } from '@weasel-js/routing';\nimport type { Op } from 'core/ops/types';\nimport type { Scene } from 'core/scene/types';\nimport { commitOps } from '../defaultCommitAdapter';\nimport { DUPLICATE_OFFSET, duplicateSelection } from '../defaults/duplicate';\nimport { translateSelection } from '../defaults/nudge';\nimport { requiresSelection } from '../defaults/requiresSelection';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { resizeSelectionOps } from '../resize/replay';\nimport { rotateSelectionOps } from '../rotate/replay';\nimport { lastTransform, recordTransform, type RepeatableTransform } from './memory';\nimport { icon } from '../../../icons.gen';\n\nconst LABEL = 'Transform Again';\n\n/** With nothing recorded yet, a repeat is a plain duplicate. */\nconst FIRST: RepeatableTransform = { kind: 'duplicate', dx: DUPLICATE_OFFSET, dy: DUPLICATE_OFFSET };\n\nfunction commit(deps: ActionDeps, ops: Op[]): boolean {\n if (ops.length === 0) return false;\n commitOps(deps, ops, LABEL);\n return true;\n}\n\n/** Apply `t` to the selection as one undo entry. Returns the ids selected\n * afterwards, or null when nothing changed. */\nfunction replay(deps: ActionDeps, scene: Scene<unknown, string, unknown>, t: RepeatableTransform): readonly string[] | null {\n const selection = deps.selection!;\n const selected = selection.get() as string[];\n switch (t.kind) {\n case 'duplicate':\n return duplicateSelection(deps, t.dx, t.dy, LABEL);\n case 'translate':\n return translateSelection(\n selection, scene, t.dx, t.dy, deps.applyOps, deps.geometryProjection,\n poseDescriptorOf(deps.poseDescriptor), LABEL,\n ) ? selected : null;\n case 'rotate':\n return commit(deps, rotateSelectionOps(\n scene, selected, deps, t.angle, t.pivot, LABEL,\n )) ? selected : null;\n case 'scale':\n return commit(deps, resizeSelectionOps(scene, selected, t.anchor, t.to, deps, LABEL)) ? selected : null;\n }\n}\n\n/**\n * Repeat the last move, rotate, resize, nudge, duplicate, or Alt-drag clone on\n * the current selection, as one undo entry. A repeated duplicate copies the\n * selection — the last copies — again by the same offset, so pressing it over\n * and over makes a step-and-repeat; moving the copies between a duplicate and\n * its repeat changes that offset. With nothing to repeat it duplicates.\n */\nexport const transformAgainAction: Action & { requires: string[] } = {\n id: 'transformAgain',\n label: LABEL,\n icon: icon('transformAgain'),\n group: 'edit',\n defaultBinding: { kind: 'key', key: 'd', mods: { mod: true } },\n eligible: { capability: 'transforms-selection' },\n requires: [\n 'scene', 'selection', 'applyOps', 'poseDescriptor', 'geometryProjection', 'resizePolicy', 'view',\n 'boundsIncludeStroke',\n ],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const scene = deps.scene;\n if (!scene || !deps.selection || deps.selection.get().length === 0) return;\n const t = lastTransform(scene) ?? FIRST;\n const subject = replay(deps, scene, t);\n if (subject) recordTransform(scene, t, subject);\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/transform-again/action.ts"],"sourcesContent":["import type { Action, ActionDeps } from '@weasel-js/routing';\nimport type { Op } from 'core/ops/types';\nimport type { Scene } from 'core/scene/types';\nimport { commitTransformOps, transformApplyOps } from '../transformFinish';\nimport { DUPLICATE_OFFSET, duplicateSelection } from '../defaults/duplicate';\nimport { translateSelection } from '../defaults/nudge';\nimport { requiresSelection } from '../defaults/requiresSelection';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { resizeSelectionOps } from '../resize/replay';\nimport { rotateSelectionOps } from '../rotate/replay';\nimport { lastTransform, recordTransform, type RepeatableTransform } from './memory';\nimport { icon } from '../../../icons.gen';\n\nconst LABEL = 'Transform Again';\n\n/** With nothing recorded yet, a repeat is a plain duplicate. */\nconst FIRST: RepeatableTransform = { kind: 'duplicate', dx: DUPLICATE_OFFSET, dy: DUPLICATE_OFFSET };\n\nfunction commit(deps: ActionDeps, ops: Op[]): boolean {\n return commitTransformOps(deps, ops, LABEL);\n}\n\n/** Apply `t` to the selection as one undo entry. Returns the ids selected\n * afterwards, or null when nothing changed. */\nfunction replay(deps: ActionDeps, scene: Scene<unknown, string, unknown>, t: RepeatableTransform): readonly string[] | null {\n const selection = deps.selection!;\n const selected = selection.get() as string[];\n switch (t.kind) {\n case 'duplicate':\n return duplicateSelection(deps, t.dx, t.dy, LABEL);\n case 'translate':\n return translateSelection(\n selection, scene, t.dx, t.dy, transformApplyOps(deps), deps.geometryProjection,\n poseDescriptorOf(deps.poseDescriptor), LABEL,\n ) ? selected : null;\n case 'rotate':\n return commit(deps, rotateSelectionOps(\n scene, selected, deps, t.angle, t.pivot, LABEL,\n )) ? selected : null;\n case 'scale':\n return commit(deps, resizeSelectionOps(scene, selected, t.anchor, t.to, deps, LABEL)) ? selected : null;\n }\n}\n\n/**\n * Repeat the last move, rotate, resize, nudge, duplicate, or Alt-drag clone on\n * the current selection, as one undo entry. A repeated duplicate copies the\n * selection — the last copies — again by the same offset, so pressing it over\n * and over makes a step-and-repeat; moving the copies between a duplicate and\n * its repeat changes that offset. With nothing to repeat it duplicates.\n */\nexport const transformAgainAction: Action & { requires: string[] } = {\n id: 'transformAgain',\n label: LABEL,\n icon: icon('transformAgain'),\n group: 'edit',\n defaultBinding: { kind: 'key', key: 'd', mods: { mod: true } },\n eligible: { capability: 'transforms-selection' },\n requires: [\n 'scene', 'selection', 'applyOps', 'poseDescriptor', 'geometryProjection', 'resizePolicy', 'view',\n 'boundsIncludeStroke', 'transformFollowers',\n ],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const scene = deps.scene;\n if (!scene || !deps.selection || deps.selection.get().length === 0) return;\n const t = lastTransform(scene) ?? FIRST;\n const subject = replay(deps, scene, t);\n if (subject) recordTransform(scene, t, subject);\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { commitOps } from "./defaultCommitAdapter.js";
|
|
2
|
+
|
|
3
|
+
//#region src/interactions/actions/transformFinish.ts
|
|
4
|
+
/** Every follower in `deps.transformFollowers` finishing the batch in turn, as a {@link TransformFinisher}; undefined with none. */
|
|
5
|
+
function transformFinisher(deps) {
|
|
6
|
+
const followers = deps?.transformFollowers;
|
|
7
|
+
if (followers === void 0 || followers.length === 0) return void 0;
|
|
8
|
+
return (ops, label) => {
|
|
9
|
+
let all = ops;
|
|
10
|
+
for (const follower of followers) {
|
|
11
|
+
const next = follower.finish(all, label);
|
|
12
|
+
if (next === null) return null;
|
|
13
|
+
all = next;
|
|
14
|
+
}
|
|
15
|
+
return all;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** `ops` finished as a whole-node transform's batch under `deps`; null when the transform should not happen. */
|
|
19
|
+
function finishTransformOps(deps, ops, label) {
|
|
20
|
+
const finish = transformFinisher(deps);
|
|
21
|
+
return finish && ops.length > 0 ? finish(ops, label) : ops;
|
|
22
|
+
}
|
|
23
|
+
/** Commit `ops`, a whole-node transform's batch, finished under `deps`, as
|
|
24
|
+
* one undo entry. Returns whether anything was committed. */
|
|
25
|
+
function commitTransformOps(deps, ops, label) {
|
|
26
|
+
const all = finishTransformOps(deps, ops, label);
|
|
27
|
+
if (!all || all.length === 0) return false;
|
|
28
|
+
commitOps(deps, all, label);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
/** What a whole-node transform commits its batch through: `deps.applyOps`
|
|
32
|
+
* when nothing finishes transforms, else a commit that finishes it first. */
|
|
33
|
+
function transformApplyOps(deps) {
|
|
34
|
+
if (!transformFinisher(deps)) return deps.applyOps;
|
|
35
|
+
return (ops, label) => {
|
|
36
|
+
commitTransformOps(deps, ops, label);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Every follower's preview of `frame`, each reading the frame with the poses and data the ones before it previewed. */
|
|
40
|
+
function previewFollowers(followers, frame) {
|
|
41
|
+
const out = /* @__PURE__ */ new Map();
|
|
42
|
+
let seen = frame;
|
|
43
|
+
const data = /* @__PURE__ */ new Map();
|
|
44
|
+
for (const follower of followers) {
|
|
45
|
+
const more = follower.preview(seen, data);
|
|
46
|
+
if (more.length === 0) continue;
|
|
47
|
+
const next = new Map(seen);
|
|
48
|
+
for (const node of more) {
|
|
49
|
+
const had = out.get(node.id);
|
|
50
|
+
out.set(node.id, node.data === void 0 && had?.data !== void 0 ? {
|
|
51
|
+
...node,
|
|
52
|
+
data: had.data
|
|
53
|
+
} : node);
|
|
54
|
+
if (node.data !== void 0) data.set(node.id, node.data);
|
|
55
|
+
next.set(node.id, node.pose);
|
|
56
|
+
}
|
|
57
|
+
seen = next;
|
|
58
|
+
}
|
|
59
|
+
return [...out.values()];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A transform drag's preview over `previews`, its frame's stored poses by id,
|
|
63
|
+
* with the nodes `deps.transformFollowers` say change with each frame added:
|
|
64
|
+
* they follow the drag as the commit will leave them. Pose goes to the
|
|
65
|
+
* scene's overrides through {@link TransformPreview.poses}, never on the
|
|
66
|
+
* handle; readers resolve it with `effectivePose`. Each frame is read once,
|
|
67
|
+
* keyed on the map.
|
|
68
|
+
*/
|
|
69
|
+
function transformPreview(deps, scene, previews) {
|
|
70
|
+
const followers = deps?.transformFollowers ?? [];
|
|
71
|
+
let seen = null;
|
|
72
|
+
let others = /* @__PURE__ */ new Map();
|
|
73
|
+
let posed = /* @__PURE__ */ new Map();
|
|
74
|
+
const read = () => {
|
|
75
|
+
const now = previews();
|
|
76
|
+
if (now !== seen) {
|
|
77
|
+
seen = now;
|
|
78
|
+
others = followers.length === 0 || now.size === 0 ? /* @__PURE__ */ new Map() : new Map(previewFollowers(followers, now).map((o) => [o.id, o]));
|
|
79
|
+
let moved = null;
|
|
80
|
+
for (const [id, node] of others) {
|
|
81
|
+
const nid = id;
|
|
82
|
+
if (now.has(nid) || node.pose === scene.get(nid)?.pose) continue;
|
|
83
|
+
moved ??= new Map(now);
|
|
84
|
+
moved.set(nid, node.pose);
|
|
85
|
+
}
|
|
86
|
+
posed = moved ?? now;
|
|
87
|
+
}
|
|
88
|
+
return others;
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
poses: () => {
|
|
92
|
+
read();
|
|
93
|
+
return posed;
|
|
94
|
+
},
|
|
95
|
+
previewIds: () => {
|
|
96
|
+
const more = read();
|
|
97
|
+
const own = previews();
|
|
98
|
+
return more.size === 0 || own.size === 0 ? own.keys() : [...own.keys(), ...[...more.keys()].filter((id) => !own.has(id))];
|
|
99
|
+
},
|
|
100
|
+
previewData: (id) => read().get(id)?.data ?? null
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
export { commitTransformOps, finishTransformOps, transformApplyOps, transformFinisher, transformPreview };
|
|
106
|
+
//# sourceMappingURL=transformFinish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformFinish.js","names":[],"sources":["../../../src/interactions/actions/transformFinish.ts"],"sourcesContent":["import type { ActionDeps } from '@weasel-js/routing';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { commitOps } from './defaultCommitAdapter';\n\n/** Finishes a whole-node transform's batch: the batch with the ops for the\n * other nodes that change with it, or null when the transform should not\n * happen. */\nexport type TransformFinisher = (ops: Op[], label: string) => Op[] | null;\n\n/** A node as a transform frame previews it: its stored pose, and its data where that changes. */\nexport interface TransformPreviewNode {\n id: string;\n pose: unknown;\n data?: unknown;\n}\n\n/**\n * Something that changes other nodes along with a whole-node transform — a\n * move, resize, rotate, flip, align, distribute, or nudge. The\n * `transformFollowers` dep holds every one, and each transform runs them all,\n * in order.\n */\nexport interface TransformFollower {\n /** The other nodes a drag's frame changes, given the stored pose the frame\n * puts each transformed node in: what `finish` would commit for it.\n * `data` holds the data the followers before this one previewed, by id. */\n preview(frame: ReadonlyMap<string, unknown>, data: ReadonlyMap<string, unknown>): readonly TransformPreviewNode[];\n /** `ops`, the batch so far, with this follower's ops added after it; null\n * when it refuses the transform. */\n finish(ops: readonly Op[], label: string): Op[] | null;\n}\n\n/** Every follower in `deps.transformFollowers` finishing the batch in turn, as a {@link TransformFinisher}; undefined with none. */\nexport function transformFinisher(deps: ActionDeps | undefined): TransformFinisher | undefined {\n const followers = deps?.transformFollowers;\n if (followers === undefined || followers.length === 0) return undefined;\n return (ops, label) => {\n let all: Op[] = ops;\n for (const follower of followers) {\n const next = follower.finish(all, label);\n if (next === null) return null;\n all = next;\n }\n return all;\n };\n}\n\n/** `ops` finished as a whole-node transform's batch under `deps`; null when the transform should not happen. */\nexport function finishTransformOps(deps: ActionDeps | undefined, ops: Op[], label: string): Op[] | null {\n const finish = transformFinisher(deps);\n return finish && ops.length > 0 ? finish(ops, label) : ops;\n}\n\n/** Commit `ops`, a whole-node transform's batch, finished under `deps`, as\n * one undo entry. Returns whether anything was committed. */\nexport function commitTransformOps(deps: ActionDeps, ops: Op[], label: string): boolean {\n const all = finishTransformOps(deps, ops, label);\n if (!all || all.length === 0) return false;\n commitOps(deps, all, label);\n return true;\n}\n\n/** What a whole-node transform commits its batch through: `deps.applyOps`\n * when nothing finishes transforms, else a commit that finishes it first. */\nexport function transformApplyOps(deps: ActionDeps): ((ops: Op[], label: string) => void) | undefined {\n if (!transformFinisher(deps)) return deps.applyOps;\n return (ops, label) => { commitTransformOps(deps, ops, label); };\n}\n\n/** Every follower's preview of `frame`, each reading the frame with the poses and data the ones before it previewed. */\nfunction previewFollowers(followers: readonly TransformFollower[], frame: ReadonlyMap<string, unknown>): TransformPreviewNode[] {\n const out = new Map<string, TransformPreviewNode>();\n let seen = frame;\n const data = new Map<string, unknown>();\n for (const follower of followers) {\n const more = follower.preview(seen, data);\n if (more.length === 0) continue;\n const next = new Map(seen);\n for (const node of more) {\n const had = out.get(node.id);\n out.set(node.id, node.data === undefined && had?.data !== undefined ? { ...node, data: had.data } : node);\n if (node.data !== undefined) data.set(node.id, node.data);\n next.set(node.id, node.pose);\n }\n seen = next;\n }\n return [...out.values()];\n}\n\n/** The preview half of a whole-node transform drag: its own previews, and\n * the other nodes each frame changes with them. */\nexport interface TransformPreview {\n /** What the drag publishes to the scene's pose overrides: the frame's own\n * poses, and each follower's pose that is not the node's own. A follower\n * answering a node's own pose pins nothing, so a derived node keeps\n * deriving. */\n poses(): ReadonlyMap<NodeId, unknown>;\n /** The handle's `previewIds`: the frame's ids, then the followers'. */\n previewIds(): Iterable<string>;\n /** The handle's `previewData`: what the followers preview for `id`. */\n previewData(id: string): unknown | null;\n}\n\n/**\n * A transform drag's preview over `previews`, its frame's stored poses by id,\n * with the nodes `deps.transformFollowers` say change with each frame added:\n * they follow the drag as the commit will leave them. Pose goes to the\n * scene's overrides through {@link TransformPreview.poses}, never on the\n * handle; readers resolve it with `effectivePose`. Each frame is read once,\n * keyed on the map.\n */\nexport function transformPreview(\n deps: ActionDeps | undefined,\n scene: { get(id: NodeId): { pose: unknown } | undefined },\n previews: () => ReadonlyMap<NodeId, unknown>,\n): TransformPreview {\n const followers = deps?.transformFollowers ?? [];\n let seen: ReadonlyMap<NodeId, unknown> | null = null;\n let others = new Map<string, TransformPreviewNode>();\n let posed: ReadonlyMap<NodeId, unknown> = new Map();\n const read = () => {\n const now = previews();\n if (now !== seen) {\n seen = now;\n others = followers.length === 0 || now.size === 0\n ? new Map()\n : new Map(previewFollowers(followers, now as ReadonlyMap<string, unknown>).map((o) => [o.id, o]));\n let moved: Map<NodeId, unknown> | null = null;\n for (const [id, node] of others) {\n const nid = id as NodeId;\n if (now.has(nid) || node.pose === scene.get(nid)?.pose) continue;\n moved ??= new Map(now);\n moved.set(nid, node.pose);\n }\n posed = moved ?? now;\n }\n return others;\n };\n return {\n poses: () => {\n read();\n return posed;\n },\n previewIds: () => {\n const more = read();\n const own = previews();\n // The close empties the frame in place, so the memo still holds its followers.\n return more.size === 0 || own.size === 0 ? own.keys() : [...own.keys(), ...[...more.keys()].filter((id) => !own.has(id as NodeId))];\n },\n previewData: (id) => read().get(id)?.data ?? null,\n };\n}\n"],"mappings":"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"}
|
|
@@ -3,8 +3,6 @@ import { DEFAULT_VIEW_ANIMATION_MS } from "./core/viewport/useViewAnimation.js";
|
|
|
3
3
|
import { DEFAULT_SNAP_PX } from "./features/snap/session2d.js";
|
|
4
4
|
import { ANCHOR_CLICK_PX } from "./interactions/actions/defaults/anchorEditing.js";
|
|
5
5
|
import { SEGMENT_HIT_PX } from "./interactions/actions/defaults/segmentUnder.js";
|
|
6
|
-
import { JOINT_RADIUS_PX } from "./tools/builtin/bone/boneOverlay.js";
|
|
7
|
-
import { POINT_RADIUS_PX } from "./tools/builtin/weight/weightOverlay.js";
|
|
8
6
|
import { ANCHOR_RADIUS_PX, CLOSE_HINT_RADIUS_PX, HANDLE_DOT_RADIUS_PX, PEN_CLOSE_HIT_PX } from "./features/paths/penPreviewLayer.js";
|
|
9
7
|
import { SLICE_CLOSE_HIT_PX, VERTEX_RADIUS_PX } from "./tools/builtin/slice/useSliceTool.js";
|
|
10
8
|
import { DEFAULT_PICK_TOLERANCE_PX } from "./canvas/SceneCanvas/useSceneSelectTool.js";
|
|
@@ -67,8 +65,6 @@ var coreKitSettingsSchema = pref.group("Canvas", {
|
|
|
67
65
|
penHandleDotRadiusPx: pxLeaf("Pen handle dot", HANDLE_DOT_RADIUS_PX, 16),
|
|
68
66
|
penCloseHintRadiusPx: pxLeaf("Pen close hint", CLOSE_HINT_RADIUS_PX, 24),
|
|
69
67
|
penCloseHitPx: pxLeaf("Pen close reach", PEN_CLOSE_HIT_PX),
|
|
70
|
-
boneJointRadiusPx: pxLeaf("Bone joint dot", JOINT_RADIUS_PX, 16),
|
|
71
|
-
weightPointRadiusPx: pxLeaf("Weight point dot", POINT_RADIUS_PX, 16),
|
|
72
68
|
sliceVertexRadiusPx: pxLeaf("Slice vertex dot", VERTEX_RADIUS_PX, 16),
|
|
73
69
|
sliceCloseHitPx: pxLeaf("Slice close reach", SLICE_CLOSE_HIT_PX)
|
|
74
70
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kitSettingsSchema.js","names":[],"sources":["../src/kitSettingsSchema.ts"],"sourcesContent":["import { pref } from '@weasel-js/prefs';\nimport {\n DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, LONG_PRESS_MS, TAP_THRESHOLD_PX,\n} from '@weasel-js/gestures';\nimport { ANCHOR_HIT_BASE_PX, HANDLE_BASE_PX, ROTATION_HANDLE_BASE_PX } from 'core/device/targets';\nimport { DEFAULT_VIEW_ANIMATION_MS } from 'core/viewport/useViewAnimation';\nimport { DEFAULT_PICK_TOLERANCE_PX } from 'canvas/SceneCanvas/useSceneSelectTool';\nimport { SEGMENT_HIT_PX } from 'interactions/actions/defaults/segmentUnder';\nimport { ANCHOR_CLICK_PX } from 'interactions/actions/defaults/anchorEditing';\nimport {\n ANCHOR_RADIUS_PX, CLOSE_HINT_RADIUS_PX, HANDLE_DOT_RADIUS_PX, PEN_CLOSE_HIT_PX,\n} from 'features/paths/penPreviewLayer';\nimport {
|
|
1
|
+
{"version":3,"file":"kitSettingsSchema.js","names":[],"sources":["../src/kitSettingsSchema.ts"],"sourcesContent":["import { pref } from '@weasel-js/prefs';\nimport {\n DOUBLE_CLICK_MAX_MS, DOUBLE_CLICK_MAX_PX, DRAG_THRESHOLD_PX, LONG_PRESS_MS, TAP_THRESHOLD_PX,\n} from '@weasel-js/gestures';\nimport { ANCHOR_HIT_BASE_PX, HANDLE_BASE_PX, ROTATION_HANDLE_BASE_PX } from 'core/device/targets';\nimport { DEFAULT_VIEW_ANIMATION_MS } from 'core/viewport/useViewAnimation';\nimport { DEFAULT_PICK_TOLERANCE_PX } from 'canvas/SceneCanvas/useSceneSelectTool';\nimport { SEGMENT_HIT_PX } from 'interactions/actions/defaults/segmentUnder';\nimport { ANCHOR_CLICK_PX } from 'interactions/actions/defaults/anchorEditing';\nimport {\n ANCHOR_RADIUS_PX, CLOSE_HINT_RADIUS_PX, HANDLE_DOT_RADIUS_PX, PEN_CLOSE_HIT_PX,\n} from 'features/paths/penPreviewLayer';\nimport { DEFAULT_SNAP_PX } from 'features/snap/session2d';\nimport { SLICE_CLOSE_HIT_PX, VERTEX_RADIUS_PX } from 'tools/builtin/slice/useSliceTool';\n\nconst ms = { scale: 1, suffix: 'ms' };\nconst px = { scale: 1, suffix: 'px' };\nconst pxLeaf = (name: string, def: number, max = 48) => pref.number(name, def, { unit: px, min: 1, max, step: 0.5 });\nconst msLeaf = (name: string, def: number, min = 50, max = 2000) => pref.number(name, def, { unit: ms, min, max, step: 10 });\n\n/**\n * Core's kit settings — gestures, core's `targets` leaves, and view — as a\n * prefs group whose paths are the `KitSettings` paths. Compose it beside the\n * other packages' groups to build a settings page.\n */\nexport const coreKitSettingsSchema = pref.group('Canvas', {\n gestures: pref.group('Gestures', {\n doubleClickMs: msLeaf('Double-click interval', DOUBLE_CLICK_MAX_MS),\n doubleClickPx: pxLeaf('Double-click distance', DOUBLE_CLICK_MAX_PX),\n longPressMs: msLeaf('Long-press hold', LONG_PRESS_MS),\n tapPx: pxLeaf('Tap travel', TAP_THRESHOLD_PX),\n dragPx: pxLeaf('Drag threshold', DRAG_THRESHOLD_PX),\n }),\n targets: pref.group('Targets', {\n handlePx: pxLeaf('Selection handle', HANDLE_BASE_PX),\n anchorHitPx: pxLeaf('Anchor reach', ANCHOR_HIT_BASE_PX),\n rotationDistancePx: pxLeaf('Rotation handle distance', ROTATION_HANDLE_BASE_PX, 96),\n segmentHitPx: pxLeaf('Segment reach', SEGMENT_HIT_PX),\n anchorClickPx: pxLeaf('Anchor click reach', ANCHOR_CLICK_PX),\n pickTolerancePx: pref.number('Shape pick slop', DEFAULT_PICK_TOLERANCE_PX, { unit: px, min: 0, max: 24, step: 0.5 }),\n snapPx: pref.number('Snap reach', DEFAULT_SNAP_PX, { unit: px, min: 0, max: 48, step: 0.5 }),\n penAnchorRadiusPx: pxLeaf('Pen anchor dot', ANCHOR_RADIUS_PX, 16),\n penHandleDotRadiusPx: pxLeaf('Pen handle dot', HANDLE_DOT_RADIUS_PX, 16),\n penCloseHintRadiusPx: pxLeaf('Pen close hint', CLOSE_HINT_RADIUS_PX, 24),\n penCloseHitPx: pxLeaf('Pen close reach', PEN_CLOSE_HIT_PX),\n sliceVertexRadiusPx: pxLeaf('Slice vertex dot', VERTEX_RADIUS_PX, 16),\n sliceCloseHitPx: pxLeaf('Slice close reach', SLICE_CLOSE_HIT_PX),\n }),\n view: pref.group('View', {\n animationMs: msLeaf('Camera animation', DEFAULT_VIEW_ANIMATION_MS, 0),\n }),\n});\n"],"mappings":";;;;;;;;;;;;AAeA,IAAM,KAAK;CAAE,OAAO;CAAG,QAAQ;AAAK;AACpC,IAAM,KAAK;CAAE,OAAO;CAAG,QAAQ;AAAK;AACpC,IAAM,UAAU,MAAc,KAAa,MAAM,OAAO,KAAK,OAAO,MAAM,KAAK;CAAE,MAAM;CAAI,KAAK;CAAG;CAAK,MAAM;AAAI,CAAC;AACnH,IAAM,UAAU,MAAc,KAAa,MAAM,IAAI,MAAM,QAAS,KAAK,OAAO,MAAM,KAAK;CAAE,MAAM;CAAI;CAAK;CAAK,MAAM;AAAG,CAAC;;;;;;AAO3H,IAAa,wBAAwB,KAAK,MAAM,UAAU;CACxD,UAAU,KAAK,MAAM,YAAY;EAC/B,eAAe,OAAO,yBAAyB,mBAAmB;EAClE,eAAe,OAAO,yBAAyB,mBAAmB;EAClE,aAAa,OAAO,mBAAmB,aAAa;EACpD,OAAO,OAAO,cAAc,gBAAgB;EAC5C,QAAQ,OAAO,kBAAkB,iBAAiB;CACpD,CAAC;CACD,SAAS,KAAK,MAAM,WAAW;EAC7B,UAAU,OAAO,oBAAoB,cAAc;EACnD,aAAa,OAAO,gBAAgB,kBAAkB;EACtD,oBAAoB,OAAO,4BAA4B,yBAAyB,EAAE;EAClF,cAAc,OAAO,iBAAiB,cAAc;EACpD,eAAe,OAAO,sBAAsB,eAAe;EAC3D,iBAAiB,KAAK,OAAO,mBAAmB,2BAA2B;GAAE,MAAM;GAAI,KAAK;GAAG,KAAK;GAAI,MAAM;EAAI,CAAC;EACnH,QAAQ,KAAK,OAAO,cAAc,iBAAiB;GAAE,MAAM;GAAI,KAAK;GAAG,KAAK;GAAI,MAAM;EAAI,CAAC;EAC3F,mBAAmB,OAAO,kBAAkB,kBAAkB,EAAE;EAChE,sBAAsB,OAAO,kBAAkB,sBAAsB,EAAE;EACvE,sBAAsB,OAAO,kBAAkB,sBAAsB,EAAE;EACvE,eAAe,OAAO,mBAAmB,gBAAgB;EACzD,qBAAqB,OAAO,oBAAoB,kBAAkB,EAAE;EACpE,iBAAiB,OAAO,qBAAqB,kBAAkB;CACjE,CAAC;CACD,MAAM,KAAK,MAAM,QAAQ,EACvB,aAAa,OAAO,oBAAoB,2BAA2B,CAAC,EACtE,CAAC;AACH,CAAC"}
|
package/dist/move.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export { U as UseMoveOptions } from './options-
|
|
2
|
-
import { S as SnapTarget } from './types-
|
|
3
|
-
import { M as MoveBehavior } from './clone-
|
|
1
|
+
export { U as UseMoveOptions } from './options-DBxEryYq.js';
|
|
2
|
+
import { S as SnapTarget } from './types-oFeQ5VjV.js';
|
|
3
|
+
import { M as MoveBehavior } from './clone-C3e0OTuF.js';
|
|
4
4
|
import { O as OriginProjection } from './originProjection-gY0jb4Wb.js';
|
|
5
|
-
import '
|
|
5
|
+
import './types-7puAuVD2.js';
|
|
6
6
|
import '@weasel-js/geom';
|
|
7
|
+
import '@weasel-js/history';
|
|
7
8
|
import './poseDescriptor-DN2yfnq_.js';
|
|
8
9
|
import '@weasel-js/animator';
|
|
9
10
|
import '@weasel-js/react';
|
package/dist/resize.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, E as EDGE_HANDLE_MIN_RADII, H as HandleEdge, R as RESIZE_HANDLE_ANCHORS, c as ResizeHandleAnchor, d as ResizeHandleLayout, U as UseResizeOptions, e as cornerPoint, f as cornerResizeHandles, g as fixedCornerOf, h as handlePoint, i as hitCornerHandle, j as isCornerHandle, r as resizeHandlesFor } from './cornerHandles-
|
|
1
|
+
export { C as CORNER_ANCHORS, a as CornerAnchor, b as CornerHandle, E as EDGE_HANDLE_MIN_RADII, H as HandleEdge, R as RESIZE_HANDLE_ANCHORS, c as ResizeHandleAnchor, d as ResizeHandleLayout, U as UseResizeOptions, e as cornerPoint, f as cornerResizeHandles, g as fixedCornerOf, h as handlePoint, i as hitCornerHandle, j as isCornerHandle, r as resizeHandlesFor } from './cornerHandles-BHuoMs1o.js';
|
|
2
2
|
export { P as PoseDescriptor, R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, p as poseDescriptorForNode } from './poseDescriptor-DN2yfnq_.js';
|
|
3
|
-
import { B as BoundsConstraint } from './clone-
|
|
3
|
+
import { B as BoundsConstraint } from './clone-C3e0OTuF.js';
|
|
4
4
|
import { FramedBox } from '@weasel-js/geom';
|
|
5
5
|
export { A as AUTO_POSE_DESCRIPTOR, i as isPathLike, a as isRectPose } from './autoPoseDescriptor-CZ1eXbzY.js';
|
|
6
6
|
import '@weasel-js/routing';
|
|
7
7
|
import '@weasel-js/animator';
|
|
8
|
-
import './types-
|
|
8
|
+
import './types-7puAuVD2.js';
|
|
9
9
|
import '@weasel-js/history';
|
|
10
|
+
import './types-oFeQ5VjV.js';
|
|
10
11
|
import '@weasel-js/react';
|
|
11
12
|
|
|
12
13
|
/** Resize constraint that stops a node shrinking past a minimum. The anchored
|
package/dist/routing.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { ChannelRef, Conflict, DescribeRouteOptions, DispatchRecord, DispatchRecordInput, DroppedCandidate, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, GestureName, ModRequirement, ModeSwitchLogEntry, ModifierKey, PREDICATE_TARGET, ParsedModifiers, ParsedRoute, PhaseAtom, PlacedBy, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, RankedCandidate, RecordCandidate, RegistryEntry, RouteDescriptionPart, RouteFieldName, RouteTermLabel, SpecificityPart, TraceLogEntry, WalkStep, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture } from '@weasel-js/routing';
|
|
1
|
+
export { ChannelRef, Conflict, DescribeRouteOptions, DispatchRecord, DispatchRecordInput, DispatchTrace, DroppedCandidate, GESTURE_DESCRIPTORS, GestureArgSpec, GestureDescriptor, GestureName, ModRequirement, ModeSwitchLogEntry, ModifierKey, PREDICATE_TARGET, ParsedModifiers, ParsedRoute, PhaseAtom, PlacedBy, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, RankedCandidate, RecordCandidate, RegistryEntry, RouteDescriptionPart, RouteFieldName, RouteTermLabel, SpecificityPart, TraceLogEntry, TraceRing, WalkStep, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, createDispatchTrace, createTraceRing, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture } from '@weasel-js/routing';
|
package/dist/routing.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture } from "@weasel-js/routing";
|
|
1
|
+
import { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, createDispatchTrace, createTraceRing, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture } from "@weasel-js/routing";
|
|
2
2
|
|
|
3
|
-
export { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture };
|
|
3
|
+
export { GESTURE_DESCRIPTORS, PREDICATE_TARGET, RESERVED_ID_NAMES, RESERVED_ID_PREFIXES, ROUTE_FIELD_DEFINITIONS, ROUTE_TERMS, buildRouteRegistry, canonicalModifiers, collapseShiftPairs, createDispatchTrace, createTraceRing, describeRoute, describeRouteParts, findConflicts, formatPhaseAtom, formatRoute, getGestureDescriptor, isKnownGestureName, parseRoute, reportRouteConflicts, routeGestureForSpecKind, routesForSpec, specKindForRouteGesture };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createTestHook.js","names":[],"sources":["../../src/test-hook/createTestHook.ts"],"sourcesContent":["import type { TestHookRefs, WeaselTestHook } from './types';\n\nexport function createTestHook(refs: TestHookRefs): WeaselTestHook {\n let resolveReady!: () => void;\n const ready = new Promise<void>((r) => { resolveReady = r; });\n const probes = new Map<string, () => unknown>();\n\n return {\n ready,\n getScene() {\n const s = refs.getScene();\n if (!s) throw new Error('weasel test hook: scene not mounted yet');\n return s.toJSON();\n },\n getSelection() {\n return [...refs.getSelectionIds()];\n },\n getView() {\n return refs.getView();\n },\n getActiveToolId() {\n return refs.getActiveToolId();\n },\n probe<T = unknown>(name: string): T | undefined {\n const fn = probes.get(name);\n return fn ? (fn() as T) : undefined;\n },\n registerProbe<T>(name: string, fn: () => T) {\n probes.set(name, fn as () => unknown);\n return () => {\n if (probes.get(name) === fn) probes.delete(name);\n };\n },\n _markReady() {\n resolveReady();\n },\n };\n}\n"],"mappings":";AAEA,SAAgB,eAAe,MAAoC;CACjE,IAAI;CACJ,MAAM,QAAQ,IAAI,SAAe,MAAM;EAAE,eAAe;CAAG,CAAC;CAC5D,MAAM,
|
|
1
|
+
{"version":3,"file":"createTestHook.js","names":[],"sources":["../../src/test-hook/createTestHook.ts"],"sourcesContent":["import type { TestHookRefs, WeaselTestHook } from './types';\n\nexport function createTestHook(refs: TestHookRefs): WeaselTestHook {\n let resolveReady!: () => void;\n const ready = new Promise<void>((r) => { resolveReady = r; });\n const probes = refs.probes ?? new Map<string, () => unknown>();\n\n return {\n ready,\n getScene() {\n const s = refs.getScene();\n if (!s) throw new Error('weasel test hook: scene not mounted yet');\n return s.toJSON();\n },\n getSelection() {\n return [...refs.getSelectionIds()];\n },\n getView() {\n return refs.getView();\n },\n getActiveToolId() {\n return refs.getActiveToolId();\n },\n probe<T = unknown>(name: string): T | undefined {\n const fn = probes.get(name);\n return fn ? (fn() as T) : undefined;\n },\n registerProbe<T>(name: string, fn: () => T) {\n probes.set(name, fn as () => unknown);\n return () => {\n if (probes.get(name) === fn) probes.delete(name);\n };\n },\n _markReady() {\n resolveReady();\n },\n };\n}\n"],"mappings":";AAEA,SAAgB,eAAe,MAAoC;CACjE,IAAI;CACJ,MAAM,QAAQ,IAAI,SAAe,MAAM;EAAE,eAAe;CAAG,CAAC;CAC5D,MAAM,SAAS,KAAK,0BAAU,IAAI,IAA2B;CAE7D,OAAO;EACL;EACA,WAAW;GACT,MAAM,IAAI,KAAK,SAAS;GACxB,IAAI,CAAC,GAAG,MAAM,IAAI,MAAM,yCAAyC;GACjE,OAAO,EAAE,OAAO;EAClB;EACA,eAAe;GACb,OAAO,CAAC,GAAG,KAAK,gBAAgB,CAAC;EACnC;EACA,UAAU;GACR,OAAO,KAAK,QAAQ;EACtB;EACA,kBAAkB;GAChB,OAAO,KAAK,gBAAgB;EAC9B;EACA,MAAmB,MAA6B;GAC9C,MAAM,KAAK,OAAO,IAAI,IAAI;GAC1B,OAAO,KAAM,GAAG,IAAU;EAC5B;EACA,cAAiB,MAAc,IAAa;GAC1C,OAAO,IAAI,MAAM,EAAmB;GACpC,aAAa;IACX,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,OAAO,OAAO,IAAI;GACjD;EACF;EACA,aAAa;GACX,aAAa;EACf;CACF;AACF"}
|
|
@@ -13,7 +13,8 @@ function useTestHook(read) {
|
|
|
13
13
|
getScene: () => live.current.getScene(),
|
|
14
14
|
getSelectionIds: () => live.current.getSelectionIds(),
|
|
15
15
|
getView: () => live.current.getView(),
|
|
16
|
-
getActiveToolId: () => live.current.getActiveToolId()
|
|
16
|
+
getActiveToolId: () => live.current.getActiveToolId(),
|
|
17
|
+
...live.current.probes ? { probes: live.current.probes } : {}
|
|
17
18
|
});
|
|
18
19
|
if (hook) {
|
|
19
20
|
hook._markReady();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTestHook.js","names":[],"sources":["../../src/test-hook/useTestHook.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useLatest, isDev } from '@weasel-js/react';\nimport { installTestHookIfRequested, releaseTestHook } from './install';\nimport type { TestHookRefs } from './types';\n\n/** The test hook for one canvas: opt-in via `?test=1`, never in a production\n * build. `read` is called for the values of the last committed render. */\nexport function useTestHook(read: TestHookRefs): void {\n const live = useLatest(read);\n useEffect(() => {\n if (isDev()) {\n const hook = installTestHookIfRequested({\n getScene: () => live.current.getScene(),\n getSelectionIds: () => live.current.getSelectionIds(),\n getView: () => live.current.getView(),\n getActiveToolId: () => live.current.getActiveToolId(),\n });\n if (hook) {\n hook._markReady();\n return () => releaseTestHook(hook);\n }\n }\n return undefined;\n }, [live]);\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,YAAY,MAA0B;CACpD,MAAM,OAAO,UAAU,IAAI;CAC3B,gBAAgB;EACd,IAAI,MAAM,GAAG;GACX,MAAM,OAAO,2BAA2B;IACtC,gBAAgB,KAAK,QAAQ,SAAS;IACtC,uBAAuB,KAAK,QAAQ,gBAAgB;IACpD,eAAe,KAAK,QAAQ,QAAQ;IACpC,uBAAuB,KAAK,QAAQ,gBAAgB;
|
|
1
|
+
{"version":3,"file":"useTestHook.js","names":[],"sources":["../../src/test-hook/useTestHook.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useLatest, isDev } from '@weasel-js/react';\nimport { installTestHookIfRequested, releaseTestHook } from './install';\nimport type { TestHookRefs } from './types';\n\n/** The test hook for one canvas: opt-in via `?test=1`, never in a production\n * build. `read` is called for the values of the last committed render. */\nexport function useTestHook(read: TestHookRefs): void {\n const live = useLatest(read);\n useEffect(() => {\n if (isDev()) {\n const hook = installTestHookIfRequested({\n getScene: () => live.current.getScene(),\n getSelectionIds: () => live.current.getSelectionIds(),\n getView: () => live.current.getView(),\n getActiveToolId: () => live.current.getActiveToolId(),\n ...(live.current.probes ? { probes: live.current.probes } : {}),\n });\n if (hook) {\n hook._markReady();\n return () => releaseTestHook(hook);\n }\n }\n return undefined;\n }, [live]);\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,YAAY,MAA0B;CACpD,MAAM,OAAO,UAAU,IAAI;CAC3B,gBAAgB;EACd,IAAI,MAAM,GAAG;GACX,MAAM,OAAO,2BAA2B;IACtC,gBAAgB,KAAK,QAAQ,SAAS;IACtC,uBAAuB,KAAK,QAAQ,gBAAgB;IACpD,eAAe,KAAK,QAAQ,QAAQ;IACpC,uBAAuB,KAAK,QAAQ,gBAAgB;IACpD,GAAI,KAAK,QAAQ,SAAS,EAAE,QAAQ,KAAK,QAAQ,OAAO,IAAI,CAAC;GAC/D,CAAC;GACD,IAAI,MAAM;IACR,KAAK,WAAW;IAChB,aAAa,gBAAgB,IAAI;GACnC;EACF;CAEF,GAAG,CAAC,IAAI,CAAC;AACX"}
|
package/dist/test-seams.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { E as EditAnchorsDep, P as PathEditMark, a as PathEditExtension, H as HandleLocks, S as
|
|
2
|
-
export { _ as _resetPaintKindsForTests } from './depSchema-
|
|
1
|
+
import { E as EditAnchorsDep, P as PathEditMark, a as PathEditExtension, H as HandleLocks, S as SnapSource, b as SnapGesture, c as SnapConstrain, d as SnapResizeBox, e as SnapGeometry, f as SnapOutcomeStore, g as SnapSession } from './depSchema-BpZNOv7q.js';
|
|
2
|
+
export { _ as _resetPaintKindsForTests } from './depSchema-BpZNOv7q.js';
|
|
3
3
|
export { _resetMarkersForTests } from '@weasel-js/stroke/test-seams';
|
|
4
|
+
import { S as Scene } from './types-CniVctmk.js';
|
|
4
5
|
import { SelectionApi, ActionTunings, ResizeAnchor } from '@weasel-js/routing';
|
|
5
6
|
import { Op } from '@weasel-js/history';
|
|
6
7
|
import { View } from '@weasel-js/geom';
|
|
7
8
|
import { P as PoseDescriptor } from './poseDescriptor-DN2yfnq_.js';
|
|
8
|
-
import {
|
|
9
|
+
import { a as PlaneMap } from './types-7puAuVD2.js';
|
|
9
10
|
import { O as OriginProjection } from './originProjection-gY0jb4Wb.js';
|
|
10
11
|
import '@weasel-js/paint';
|
|
11
12
|
import '@weasel-js/registry';
|
|
@@ -17,10 +18,11 @@ import '@weasel-js/text';
|
|
|
17
18
|
import '@weasel-js/cursor';
|
|
18
19
|
import '@weasel-js/gestures';
|
|
19
20
|
import '@weasel-js/geom/nd';
|
|
20
|
-
import '@weasel-js/quantity';
|
|
21
21
|
import '@weasel-js/animator';
|
|
22
|
-
import './
|
|
22
|
+
import './types-oFeQ5VjV.js';
|
|
23
|
+
import './clone-C3e0OTuF.js';
|
|
23
24
|
import '@weasel-js/react';
|
|
25
|
+
import '@weasel-js/quantity';
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Build an inert {@link EditAnchorsDep} for action unit tests. Every
|
|
@@ -129,6 +131,8 @@ interface SnapSession2dOptions {
|
|
|
129
131
|
press: Point;
|
|
130
132
|
/** The subject, whose geometry offers no targets. */
|
|
131
133
|
ids?: readonly string[];
|
|
134
|
+
/** The container a subject not yet in the scene lands in. */
|
|
135
|
+
parent?: string;
|
|
132
136
|
/** Point gestures: the previous anchor, a line's start. */
|
|
133
137
|
origin?: Point;
|
|
134
138
|
constrain?: SnapConstrain;
|