@weasel-js/core 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +184 -0
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/barrel/canvas.js +3 -1
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +8 -4
- package/dist/barrel/renderer.js +3 -2
- package/dist/barrel/routing.js +4 -4
- package/dist/barrel/scene.js +2 -1
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +6 -2
- package/dist/canvas/Canvas.js +2 -1
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +23 -34
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/ModalityHud.js +1 -1
- package/dist/canvas/NodeShape.js +4 -1
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.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/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
- package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +1 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +7 -2
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +10 -2
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +1 -0
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +19 -4
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +11 -10
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- package/dist/canvas/defaultDrawOne.js +2 -0
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/booleans.js +2 -1
- package/dist/canvas/deps/booleans.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +2 -2
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/insert.js +6 -2
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +3 -7
- package/dist/canvas/deps/pathEditCommits.js.map +1 -1
- package/dist/canvas/drawnBounds.js +11 -3
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/inheritedPaints.js +44 -0
- package/dist/canvas/inheritedPaints.js.map +1 -0
- package/dist/canvas/nodeShapes/derivedPainter.js +15 -16
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +13 -34
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +9 -8
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +11 -10
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/textPainter.js +13 -12
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
- package/dist/canvas/pickReach.js +3 -3
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +3 -1
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +1 -1
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +2 -1
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +2 -1
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/surfaceContribution.js +12 -8
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useLayerStack.js +6 -2
- package/dist/canvas/useLayerStack.js.map +1 -1
- package/dist/canvas/useViewAim.js +121 -0
- package/dist/canvas/useViewAim.js.map +1 -0
- package/dist/canvas/useViewNesting.js +3 -2
- package/dist/canvas/useViewNesting.js.map +1 -1
- package/dist/canvas/useViewRegistrySurface.js +4 -2
- package/dist/canvas/useViewRegistrySurface.js.map +1 -1
- package/dist/canvas/viewMarkers.js +63 -0
- package/dist/canvas/viewMarkers.js.map +1 -0
- package/dist/canvas/viewRegistry.js +27 -1
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/core/pages/pageEdits.js +2 -3
- package/dist/core/pages/pageEdits.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js +59 -2
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/scene/clipNothing.js +13 -0
- package/dist/core/scene/clipNothing.js.map +1 -0
- package/dist/core/scene/depMemo.js +11 -3
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +7 -1
- package/dist/core/scene/dependents.js.map +1 -1
- package/dist/core/scene/derivedParts.js +10 -11
- package/dist/core/scene/derivedParts.js.map +1 -1
- package/dist/core/scene/effectivePose.js +7 -2
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fontReads.js +37 -0
- package/dist/core/scene/fontReads.js.map +1 -0
- package/dist/core/scene/inheritedPaint.js +75 -0
- package/dist/core/scene/inheritedPaint.js.map +1 -0
- package/dist/core/scene/kitRegistry.js +5 -0
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +15 -7
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js.map +1 -1
- package/dist/core/scene/pathEffects/derive.js +7 -2
- package/dist/core/scene/pathEffects/derive.js.map +1 -1
- package/dist/core/scene/pathEffects/effects.js +3 -1
- package/dist/core/scene/pathEffects/effects.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlong.js +95 -0
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
- package/dist/{cornerHandles-BHuoMs1o.d.ts → cornerHandles-p8fDIAKt.d.ts} +2 -1
- package/dist/{depSchema-BpZNOv7q.d.ts → depSchema-mG19aEdD.d.ts} +61 -13
- package/dist/devtools/registry.js +4 -4
- package/dist/devtools/registry.js.map +1 -1
- package/dist/features/measure/measureContribution.js +4 -2
- package/dist/features/measure/measureContribution.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +7 -3
- package/dist/features/modes/modeTriggers.js.map +1 -1
- package/dist/features/pathEffects/effectSources.js +60 -0
- package/dist/features/pathEffects/effectSources.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +17 -1
- package/dist/features/pathEffects/readSource.js.map +1 -1
- package/dist/features/pathEffects/textItems.js +53 -0
- package/dist/features/pathEffects/textItems.js.map +1 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/features/paths/pathEditState.js +5 -2
- package/dist/features/paths/pathEditState.js.map +1 -1
- package/dist/features/text/sceneTextDrafts.js +65 -0
- package/dist/features/text/sceneTextDrafts.js.map +1 -0
- package/dist/features/text/textHitAt.js +31 -2
- package/dist/features/text/textHitAt.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +22 -18
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/viewports/aim.js +105 -0
- package/dist/features/viewports/aim.js.map +1 -0
- package/dist/features/viewports/viewMarker.js +82 -0
- package/dist/features/viewports/viewMarker.js.map +1 -0
- package/dist/features/viewports/viewMarkerDrag.js +55 -0
- package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
- package/dist/index.d.ts +500 -201
- package/dist/index.js +23 -12
- package/dist/interactions/actions/booleans/booleans.js +2 -1
- package/dist/interactions/actions/booleans/booleans.js.map +1 -1
- package/dist/interactions/actions/booleans/operands.js +6 -5
- package/dist/interactions/actions/booleans/operands.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +27 -17
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
- package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +7 -4
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
- package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
- package/dist/interactions/actions/defaults/contextMenu.js +17 -8
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +28 -14
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +11 -8
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/escape.js +11 -8
- package/dist/interactions/actions/defaults/escape.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +19 -13
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +10 -4
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +8 -2
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
- package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
- package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
- package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
- package/dist/interactions/actions/defaults/reorder.js +24 -6
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/selectAll.js +8 -5
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +7 -3
- package/dist/interactions/actions/defaults/setFill.js.map +1 -1
- package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
- package/dist/interactions/actions/defaults/setStroke.js +12 -11
- package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
- package/dist/interactions/actions/defaults/toolActivate.js +7 -1
- package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
- package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
- package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
- package/dist/interactions/actions/defaults/undoRedo.js +19 -13
- package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
- package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
- package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +7 -4
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +8 -2
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/insert/repositionAction.js +2 -1
- package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
- package/dist/interactions/actions/move/action.js +7 -4
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
- package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
- package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
- package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
- package/dist/interactions/actions/resize/cornerHandles.js +2 -1
- package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +12 -7
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +8 -5
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -1
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js +2 -1
- package/dist/resize.d.ts +1 -1
- package/dist/test-seams.d.ts +2 -2
- package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
- package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +7 -4
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/image/useImageTool.js +1 -0
- package/dist/tools/builtin/image/useImageTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
- package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js +1 -0
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
- package/dist/tools/builtin/pen/usePenTool.js +14 -6
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
- package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/rect/useRectTool.js +1 -0
- package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
- package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/pressDecision.js +32 -0
- package/dist/tools/builtin/select/pressDecision.js.map +1 -0
- package/dist/tools/builtin/select/selectionContributions.js +22 -13
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +13 -10
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +22 -8
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +13 -4
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/sticky/stickyNode.js +4 -1
- package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
- package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
- package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
- package/dist/tools/builtin/text/useTextTool.js +3 -1
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +28 -24
|
@@ -6,18 +6,23 @@ import { createTransformOp } from "../../core/ops/transform.js";
|
|
|
6
6
|
//#region src/interactions/actions/selectionSubtree.ts
|
|
7
7
|
/** True when any ancestor of `id` is also in `set` — acting on that ancestor
|
|
8
8
|
* already reaches this node, so acting on it again would double it. */
|
|
9
|
-
function hasSelectedAncestor(
|
|
10
|
-
|
|
9
|
+
function hasSelectedAncestor(parentOf, id, set) {
|
|
10
|
+
return selectedAncestor(parentOf, id, set) !== null;
|
|
11
|
+
}
|
|
12
|
+
/** The nearest ancestor of `id` that is in `set`, or `null`. */
|
|
13
|
+
function selectedAncestor(parentOf, id, set) {
|
|
14
|
+
let parent = parentOf(id);
|
|
11
15
|
while (parent != null) {
|
|
12
|
-
if (set.has(parent)) return
|
|
13
|
-
parent =
|
|
16
|
+
if (set.has(parent)) return parent;
|
|
17
|
+
parent = parentOf(parent);
|
|
14
18
|
}
|
|
15
|
-
return
|
|
19
|
+
return null;
|
|
16
20
|
}
|
|
17
21
|
/** The ids in `ids` that are in the scene and have no selected ancestor. */
|
|
18
22
|
function selectedRoots(scene, ids) {
|
|
19
23
|
const set = new Set(ids);
|
|
20
|
-
|
|
24
|
+
const parentOf = (id) => scene.get(asNodeId(id))?.parent ?? null;
|
|
25
|
+
return ids.map((id) => asNodeId(id)).filter((id) => scene.get(id) !== void 0 && !hasSelectedAncestor(parentOf, id, set));
|
|
21
26
|
}
|
|
22
27
|
/** Whether `id` draws a path derived from other nodes. Its pose is a
|
|
23
28
|
* placeholder: the path follows the nodes it derives from. */
|
|
@@ -147,5 +152,5 @@ function storedDelta(frame, descriptor, id, dx, dy) {
|
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
//#endregion
|
|
150
|
-
export { hasSelectedAncestor, moveSources, selectedRoots, shapeSources, storedDelta, subtreeIds, translateEach, translateTargets };
|
|
155
|
+
export { hasSelectedAncestor, moveSources, selectedAncestor, selectedRoots, shapeSources, storedDelta, subtreeIds, translateEach, translateTargets };
|
|
151
156
|
//# sourceMappingURL=selectionSubtree.js.map
|
|
@@ -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 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
|
+
{"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(\n parentOf: (id: string) => string | null,\n id: string,\n set: ReadonlySet<string>,\n): boolean {\n return selectedAncestor(parentOf, id, set) !== null;\n}\n\n/** The nearest ancestor of `id` that is in `set`, or `null`. */\nexport function selectedAncestor(\n parentOf: (id: string) => string | null,\n id: string,\n set: ReadonlySet<string>,\n): string | null {\n let parent = parentOf(id);\n while (parent != null) {\n if (set.has(parent)) return parent;\n parent = parentOf(parent);\n }\n return null;\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 const parentOf = (id: string) => scene.get(asNodeId(id))?.parent ?? null;\n return ids\n .map((id) => asNodeId(id))\n .filter((id) => scene.get(id) !== undefined && !hasSelectedAncestor(parentOf, 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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"}
|
|
@@ -42,11 +42,14 @@ var transformAgainAction = {
|
|
|
42
42
|
label: LABEL,
|
|
43
43
|
icon: /* @icon */ "core:transformAgain",
|
|
44
44
|
group: "edit",
|
|
45
|
-
defaultBinding: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
defaultBinding: [{
|
|
46
|
+
spec: {
|
|
47
|
+
kind: "key",
|
|
48
|
+
key: "d",
|
|
49
|
+
mods: { mod: true }
|
|
50
|
+
},
|
|
51
|
+
opts: { id: "transformAgain.key" }
|
|
52
|
+
}],
|
|
50
53
|
eligible: { capability: "transforms-selection" },
|
|
51
54
|
requires: [
|
|
52
55
|
"scene",
|
|
@@ -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 { 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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"}
|
|
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: [{ spec: { kind: 'key', key: 'd', mods: { mod: true } }, opts: { id: 'transformAgain.key' } }],\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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"}
|
package/dist/json.d.ts
ADDED
package/dist/json.js
ADDED
|
@@ -41,7 +41,14 @@ var coreKitSettingsSchema = pref.group("Canvas", {
|
|
|
41
41
|
doubleClickPx: pxLeaf("Double-click distance", DOUBLE_CLICK_MAX_PX),
|
|
42
42
|
longPressMs: msLeaf("Long-press hold", LONG_PRESS_MS),
|
|
43
43
|
tapPx: pxLeaf("Tap travel", TAP_THRESHOLD_PX),
|
|
44
|
-
dragPx: pxLeaf("Drag threshold", DRAG_THRESHOLD_PX)
|
|
44
|
+
dragPx: pxLeaf("Drag threshold", DRAG_THRESHOLD_PX),
|
|
45
|
+
keymapUnbound: pref.enum("Keys a keymap does not bind", "modal", [{
|
|
46
|
+
value: "modal",
|
|
47
|
+
label: "Ignore them"
|
|
48
|
+
}, {
|
|
49
|
+
value: "cascade",
|
|
50
|
+
label: "Close it and pass them on"
|
|
51
|
+
}])
|
|
45
52
|
}),
|
|
46
53
|
targets: pref.group("Targets", {
|
|
47
54
|
handlePx: pxLeaf("Selection handle", HANDLE_BASE_PX),
|
|
@@ -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 { 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;
|
|
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 keymapUnbound: pref.enum('Keys a keymap does not bind', 'modal', [\n { value: 'modal', label: 'Ignore them' },\n { value: 'cascade', label: 'Close it and pass them on' },\n ]),\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;EAClD,eAAe,KAAK,KAAK,+BAA+B,SAAS,CAC/D;GAAE,OAAO;GAAS,OAAO;EAAc,GACvC;GAAE,OAAO;GAAW,OAAO;EAA4B,CACzD,CAAC;CACH,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"}
|
|
@@ -29,4 +29,13 @@ declare function rotatedRectCorners(pose: RotatedPose): {
|
|
|
29
29
|
* rect's local frame. */
|
|
30
30
|
declare function pointInRotatedRect(pose: RotatedPose, worldX: number, worldY: number): boolean;
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
/** Registry key for {@link clipNothing}; every scene's registry carries it. */
|
|
33
|
+
declare const CLIP_NOTHING = "kit:clipNothing";
|
|
34
|
+
/**
|
|
35
|
+
* A container's `clipFromPose` that clips nothing, for a container whose
|
|
36
|
+
* children may draw outside it. A container without one clips its children to
|
|
37
|
+
* its painter's silhouette.
|
|
38
|
+
*/
|
|
39
|
+
declare const clipNothing: () => null;
|
|
40
|
+
|
|
41
|
+
export { CLIP_NOTHING as C, aabbCenter as a, rotatePoint as b, clipNothing as c, rotatedRectCorners as d, pointInRotatedRect as p, rectCorners as r };
|
package/dist/math.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PA
|
|
|
2
2
|
export { P as PoseDescriptor, t as translatePoseViaDescriptor } from './poseDescriptor-DN2yfnq_.js';
|
|
3
3
|
export { Simulation, SimulationCore, SimulationForce, SimulationNode, SimulationOptions, createSimulation } from '@weasel-js/simulation';
|
|
4
4
|
export { A as AUTO_POSE_DESCRIPTOR } from './autoPoseDescriptor-CZ1eXbzY.js';
|
|
5
|
-
export { b as rotatePoint } from './math-
|
|
5
|
+
export { C as CLIP_NOTHING, c as clipNothing, b as rotatePoint } from './math-B56zxVs5.js';
|
|
6
6
|
import '@weasel-js/animator';
|
package/dist/math.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { translatePoseViaDescriptor } from "./core/geometry/poseDescriptor.js";
|
|
2
2
|
import { AUTO_POSE_DESCRIPTOR } from "./core/geometry/autoPoseDescriptor.js";
|
|
3
3
|
import { rotatePoint } from "./interactions/actions/rotate/geometry.js";
|
|
4
|
+
import { CLIP_NOTHING, clipNothing } from "./core/scene/clipNothing.js";
|
|
4
5
|
import { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pathCommandCoordCount, pointAlongPath, polygonFromPoints, polylineFromPoints, rectPath } from "@weasel-js/geom";
|
|
5
6
|
import { createSimulation } from "@weasel-js/simulation";
|
|
6
7
|
|
|
7
|
-
export { AUTO_POSE_DESCRIPTOR, DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, createSimulation, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pathCommandCoordCount, pointAlongPath, polygonFromPoints, polylineFromPoints, rectPath, rotatePoint, translatePoseViaDescriptor };
|
|
8
|
+
export { AUTO_POSE_DESCRIPTOR, CLIP_NOTHING, DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, clipNothing, createSimulation, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pathCommandCoordCount, pointAlongPath, polygonFromPoints, polylineFromPoints, rectPath, rotatePoint, translatePoseViaDescriptor };
|
package/dist/resize.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-p8fDIAKt.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
3
|
import { B as BoundsConstraint } from './clone-C3e0OTuF.js';
|
|
4
4
|
import { FramedBox } from '@weasel-js/geom';
|
package/dist/test-seams.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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-mG19aEdD.js';
|
|
2
|
+
export { _ as _resetPaintKindsForTests } from './depSchema-mG19aEdD.js';
|
|
3
3
|
export { _resetMarkersForTests } from '@weasel-js/stroke/test-seams';
|
|
4
4
|
import { S as Scene } from './types-CniVctmk.js';
|
|
5
5
|
import { SelectionApi, ActionTunings, ResizeAnchor } from '@weasel-js/routing';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEllipseTool.js","names":[],"sources":["../../../../src/tools/builtin/ellipse/useEllipseTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/**\n * Drag-to-draw ellipse tool. Mirrors `useRectTool`: the `drag` binding\n * routes to `insertAction`, which owns the live preview and commits\n * through the `insert` dep. Alt toggles from-corner ⇄ from-center\n * mid-drag via the action's live modifier read.\n */\nexport function useEllipseTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'ellipse',\n keybinding: { key: 'E' },\n capabilities: ['creates-shapes'],\n hookName: 'useEllipseTool',\n cursor: cursorFor('crosshairEllipse', { fallback: 'crosshair' }),\n presentation: {\n label: 'Ellipse',\n group: 'shape',\n icon: icon('ellipse'),\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'ellipse' }
|
|
1
|
+
{"version":3,"file":"useEllipseTool.js","names":[],"sources":["../../../../src/tools/builtin/ellipse/useEllipseTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/**\n * Drag-to-draw ellipse tool. Mirrors `useRectTool`: the `drag` binding\n * routes to `insertAction`, which owns the live preview and commits\n * through the `insert` dep. Alt toggles from-corner ⇄ from-center\n * mid-drag via the action's live modifier read.\n */\nexport function useEllipseTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'ellipse',\n keybinding: { key: 'E' },\n capabilities: ['creates-shapes'],\n hookName: 'useEllipseTool',\n cursor: cursorFor('crosshairEllipse', { fallback: 'crosshair' }),\n presentation: {\n label: 'Ellipse',\n group: 'shape',\n icon: icon('ellipse'),\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { id: 'ellipse.drag', params: { kind: 'ellipse' }, ...insertBindingBehaviors(behaviors) },\n },\n INSERT_REPOSITION_BINDING,\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEyedropperTool.js","names":[],"sources":["../../../../src/tools/builtin/eyedropper/useEyedropperTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { HotkeyTrigger } from '@weasel-js/routing';\nimport type { ToolKeybinding } from '@weasel-js/routing';\nimport type { Action } from '@weasel-js/routing';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useEyedropperTool`. */\nexport interface UseEyedropperToolOptions {\n /** Called when the user picks a color. `null` means `colorOf` returned\n * null on a real hit; an empty click is a no-op. */\n onPick: (color: string | null) => void;\n\n /** Map a node id to a color string, or `null` if the node has no color\n * to sample. Called with the id of the topmost node under the press. */\n colorOf: (id: string) => string | null;\n\n /** Override the default `{ key: 'I' }` keybinding. Pass `null` to omit\n * the keybinding entirely (palette-only or hotkey-only wiring). */\n keybinding?: ToolKeybinding | null;\n\n /** Override the default `'alt'` hotkey trigger. Pass `null` to omit. */\n hotkey?: HotkeyTrigger | null;\n}\n\n/**\n * Eyedropper. Click a node to sample its color; the consumer's `onPick`\n * callback decides where the color goes. Engages as a sticky active-slot\n * tool (`I` keybinding) and as a momentary hotkey-slot tool while Alt\n * is held — consumers can override either trigger to `null`.\n *\n * Does not mutate the scene. Click-only; drag is unbound.\n *\n * The node under the click comes from the `nodeAtPoint` dep, so an\n * eyedropper in a consumer that never registered that dep samples nothing.\n */\nexport function useEyedropperTool(opts: UseEyedropperToolOptions): Tool {\n const onPickRef = useLatest(opts.onPick);\n const colorOfRef = useLatest(opts.colorOf);\n\n // Closing over the option refs here is what lets the consumer's `onPick`\n // stay a plain callback instead of a dep.\n const pickAction = useMemo<Action>(\n () => ({\n id: 'eyedropper.pick',\n label: 'Eyedropper — sample color',\n // Same tag the tool declares, so a mode that disallows color sampling\n // can't be reached through the gesture either.\n eligible: { capability: 'samples-color' },\n requires: ['nodeAtPoint'],\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const p = params as { pressX?: number; pressY?: number } | undefined;\n if (p?.pressX === undefined || p.pressY === undefined) return;\n const nodeAtPoint = deps.nodeAtPoint;\n const id = nodeAtPoint?.({ x: p.pressX, y: p.pressY }) ?? null;\n if (id === null) return;\n onPickRef.current(colorOfRef.current(id));\n },\n },\n }),\n [onPickRef, colorOfRef],\n );\n\n return useMemo(() => {\n // `null` means omit; the registry reads `undefined` as \"no trigger\".\n const keybinding =\n opts.keybinding === null ? undefined : (opts.keybinding ?? { key: 'I' });\n const hotkey =\n opts.hotkey === null ? undefined : (opts.hotkey ?? 'alt');\n\n return defineTool({\n id: 'eyedropper',\n capabilities: ['samples-color'],\n hookName: 'useEyedropperTool',\n keybinding,\n hotkey,\n cursor: cursorFor('eyedropper', { fallback: 'crosshair' }),\n presentation: {\n label: 'Eyedropper',\n icon: icon('eyedropper'),\n group: 'view',\n },\n actions: [pickAction],\n // One binding, no target filter: the action resolves the node itself\n // and no-ops on empty. Sampling deliberately reads the PRESS point\n // rather than the release — a 4px drift between the two can land on a\n // different node, and the color you meant is the one you pressed.\n bindings: [{ spec: { kind: 'click' as const }, actionId: 'eyedropper.pick' }],\n });\n }, [opts.keybinding, opts.hotkey, pickAction]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useEyedropperTool.js","names":[],"sources":["../../../../src/tools/builtin/eyedropper/useEyedropperTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { HotkeyTrigger } from '@weasel-js/routing';\nimport type { ToolKeybinding } from '@weasel-js/routing';\nimport type { Action } from '@weasel-js/routing';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useEyedropperTool`. */\nexport interface UseEyedropperToolOptions {\n /** Called when the user picks a color. `null` means `colorOf` returned\n * null on a real hit; an empty click is a no-op. */\n onPick: (color: string | null) => void;\n\n /** Map a node id to a color string, or `null` if the node has no color\n * to sample. Called with the id of the topmost node under the press. */\n colorOf: (id: string) => string | null;\n\n /** Override the default `{ key: 'I' }` keybinding. Pass `null` to omit\n * the keybinding entirely (palette-only or hotkey-only wiring). */\n keybinding?: ToolKeybinding | null;\n\n /** Override the default `'alt'` hotkey trigger. Pass `null` to omit. */\n hotkey?: HotkeyTrigger | null;\n}\n\n/**\n * Eyedropper. Click a node to sample its color; the consumer's `onPick`\n * callback decides where the color goes. Engages as a sticky active-slot\n * tool (`I` keybinding) and as a momentary hotkey-slot tool while Alt\n * is held — consumers can override either trigger to `null`.\n *\n * Does not mutate the scene. Click-only; drag is unbound.\n *\n * The node under the click comes from the `nodeAtPoint` dep, so an\n * eyedropper in a consumer that never registered that dep samples nothing.\n */\nexport function useEyedropperTool(opts: UseEyedropperToolOptions): Tool {\n const onPickRef = useLatest(opts.onPick);\n const colorOfRef = useLatest(opts.colorOf);\n\n // Closing over the option refs here is what lets the consumer's `onPick`\n // stay a plain callback instead of a dep.\n const pickAction = useMemo<Action>(\n () => ({\n id: 'eyedropper.pick',\n label: 'Eyedropper — sample color',\n // Same tag the tool declares, so a mode that disallows color sampling\n // can't be reached through the gesture either.\n eligible: { capability: 'samples-color' },\n requires: ['nodeAtPoint'],\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const p = params as { pressX?: number; pressY?: number } | undefined;\n if (p?.pressX === undefined || p.pressY === undefined) return;\n const nodeAtPoint = deps.nodeAtPoint;\n const id = nodeAtPoint?.({ x: p.pressX, y: p.pressY }) ?? null;\n if (id === null) return;\n onPickRef.current(colorOfRef.current(id));\n },\n },\n }),\n [onPickRef, colorOfRef],\n );\n\n return useMemo(() => {\n // `null` means omit; the registry reads `undefined` as \"no trigger\".\n const keybinding =\n opts.keybinding === null ? undefined : (opts.keybinding ?? { key: 'I' });\n const hotkey =\n opts.hotkey === null ? undefined : (opts.hotkey ?? 'alt');\n\n return defineTool({\n id: 'eyedropper',\n capabilities: ['samples-color'],\n hookName: 'useEyedropperTool',\n keybinding,\n hotkey,\n cursor: cursorFor('eyedropper', { fallback: 'crosshair' }),\n presentation: {\n label: 'Eyedropper',\n icon: icon('eyedropper'),\n group: 'view',\n },\n actions: [pickAction],\n // One binding, no target filter: the action resolves the node itself\n // and no-ops on empty. Sampling deliberately reads the PRESS point\n // rather than the release — a 4px drift between the two can land on a\n // different node, and the color you meant is the one you pressed.\n bindings: [{ spec: { kind: 'click' as const }, actionId: 'eyedropper.pick', opts: { id: 'eyedropper.click' } }],\n });\n }, [opts.keybinding, opts.hotkey, pickAction]);\n}\n"],"mappings":"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"}
|
|
@@ -12,7 +12,10 @@ function dragPanContribution(params = {}) {
|
|
|
12
12
|
bindings: [{
|
|
13
13
|
spec: { kind: "drag" },
|
|
14
14
|
actionId: "viewport.dragPan",
|
|
15
|
-
|
|
15
|
+
opts: {
|
|
16
|
+
id: "viewport.dragPanBinding.drag",
|
|
17
|
+
...Object.keys(params).length > 0 ? { params: { ...params } } : {}
|
|
18
|
+
}
|
|
16
19
|
}]
|
|
17
20
|
};
|
|
18
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dragPanContribution.js","names":[],"sources":["../../../../src/tools/builtin/hand/dragPanContribution.ts"],"sourcesContent":["import type { Contribution } from '../../overlayBinding';\nimport type { DragPanParams } from '../../../interactions/actions/defaults/viewportDragPan';\n\n/** Id of the entry {@link dragPanContribution} builds. */\nexport const DRAG_PAN_ID = 'viewport.dragPanBinding';\n\n/** An always-live entry that pans the view on a drag no tool claims. No preset\n * installs it: the hand tool pans, space-held or chosen, and a canvas that\n * should pan on a plain drag — a viewer, a map — adds this to its ambient\n * list. `params` are `viewport.dragPan`'s, as the hand tool passes them. */\nexport function dragPanContribution(params: DragPanParams = {}): Contribution {\n return {\n id: DRAG_PAN_ID,\n eligibility: { always: true },\n bindings: [{\n spec: { kind: 'drag' },\n actionId: 'viewport.dragPan',\n ...(Object.keys(params).length > 0 ? {
|
|
1
|
+
{"version":3,"file":"dragPanContribution.js","names":[],"sources":["../../../../src/tools/builtin/hand/dragPanContribution.ts"],"sourcesContent":["import type { Contribution } from '../../overlayBinding';\nimport type { DragPanParams } from '../../../interactions/actions/defaults/viewportDragPan';\n\n/** Id of the entry {@link dragPanContribution} builds. */\nexport const DRAG_PAN_ID = 'viewport.dragPanBinding';\n\n/** An always-live entry that pans the view on a drag no tool claims. No preset\n * installs it: the hand tool pans, space-held or chosen, and a canvas that\n * should pan on a plain drag — a viewer, a map — adds this to its ambient\n * list. `params` are `viewport.dragPan`'s, as the hand tool passes them. */\nexport function dragPanContribution(params: DragPanParams = {}): Contribution {\n return {\n id: DRAG_PAN_ID,\n eligibility: { always: true },\n bindings: [{\n spec: { kind: 'drag' },\n actionId: 'viewport.dragPan',\n opts: { id: 'viewport.dragPanBinding.drag', ...(Object.keys(params).length > 0 ? { params: { ...params } } : {}) },\n }],\n };\n}\n"],"mappings":";;AAIA,IAAa,cAAc;;;;;AAM3B,SAAgB,oBAAoB,SAAwB,CAAC,GAAiB;CAC5E,OAAO;EACL,IAAI;EACJ,aAAa,EAAE,QAAQ,KAAK;EAC5B,UAAU,CAAC;GACT,MAAM,EAAE,MAAM,OAAO;GACrB,UAAU;GACV,MAAM;IAAE,IAAI;IAAgC,GAAI,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,IAAI,CAAC;GAAG;EACnH,CAAC;CACH;AACF"}
|
|
@@ -28,10 +28,13 @@ function useHandTool(opts = {}) {
|
|
|
28
28
|
}), { bindings: [{
|
|
29
29
|
spec: { kind: "drag" },
|
|
30
30
|
actionId: "viewport.dragPan",
|
|
31
|
-
opts: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
opts: {
|
|
32
|
+
id: "hand.drag",
|
|
33
|
+
params: () => ({
|
|
34
|
+
axis: optsRef.current.axis ?? "both",
|
|
35
|
+
inertia: optsRef.current.inertia
|
|
36
|
+
})
|
|
37
|
+
}
|
|
35
38
|
}] }), [optsRef]);
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHandTool.js","names":[],"sources":["../../../../src/tools/builtin/hand/useHandTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { InertiaConfig } from 'core/viewport/useDecayLoop';\nimport { icon } from '../../../icons.gen';\n\nexport type { InertiaConfig };\n\n/** Options for `useHandTool`. Both are forwarded to `viewport.dragPan` as\n * binding params; momentum additionally needs a `view` dep publishing\n * `decay`, which `<SceneCanvas>` wires. */\nexport interface UseHandToolOptions {\n /** Momentum after release: `true` for the kit defaults, or the settings.\n * Omit or pass `false` for none. */\n inertia?: boolean | InertiaConfig;\n /**\n * Which axes the drag responds to. Default `'both'`.\n *\n * - `'both'` — pan both axes (default).\n * - `'x'` — drag only changes `view.x`. Inertia (if enabled) also stays on x.\n * - `'y'` — drag only changes `view.y`. Inertia stays on y.\n *\n * Locks drag panning to a single axis. The former `useWheelPanTool` /\n * `useWheelZoomTool` / `useKeyboardZoomTool` axis option is dissolved.\n */\n axis?: 'both' | 'x' | 'y';\n}\n\n/**\n * Pan-on-drag tool. Registered in both the active slot (sticky, `H` key)\n * and the hotkey slot (momentary, hold `space`).\n *\n * A declarative shell: its one binding routes a drag to the\n * `viewport.dragPan` action, which owns the gesture, the view writes, and\n * the grabbing cursor. The tool only passes `axis` and `inertia` along.\n */\nexport function useHandTool(opts: UseHandToolOptions = {}): Tool {\n // Read through a ref from a params thunk rather than closing over the\n // values: a consumer passing `inertia={{ friction: 0.9 }}` inline would\n // otherwise mint a new tool identity on every render.\n const optsRef = useLatest(opts);\n return useMemo(\n () =>\n Object.assign(defineTool({\n id: 'hand',\n keybinding: { key: 'H' },\n capabilities: ['navigation'],\n hotkey: 'space',\n hookName: 'useHandTool',\n presentation: {\n label: 'Hand',\n icon: icon('hand'),\n group: 'view',\n },\n cursor: 'grab',\n }), {\n // Declarative binding routes drag through the dispatcher +\n // viewportDragPanAction, which also owns the grabbing cursor\n // (`Action.activeCursor`) the tool used to declare as an `engaged`\n // phase entry.\n bindings: [{\n spec: { kind: 'drag' as const },\n actionId: 'viewport.dragPan',\n opts: {\n params: () => ({\n axis: optsRef.current.axis ?? 'both',\n inertia: optsRef.current.inertia,\n }),\n },\n }],\n }) as Tool,\n [optsRef],\n );\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useHandTool.js","names":[],"sources":["../../../../src/tools/builtin/hand/useHandTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { InertiaConfig } from 'core/viewport/useDecayLoop';\nimport { icon } from '../../../icons.gen';\n\nexport type { InertiaConfig };\n\n/** Options for `useHandTool`. Both are forwarded to `viewport.dragPan` as\n * binding params; momentum additionally needs a `view` dep publishing\n * `decay`, which `<SceneCanvas>` wires. */\nexport interface UseHandToolOptions {\n /** Momentum after release: `true` for the kit defaults, or the settings.\n * Omit or pass `false` for none. */\n inertia?: boolean | InertiaConfig;\n /**\n * Which axes the drag responds to. Default `'both'`.\n *\n * - `'both'` — pan both axes (default).\n * - `'x'` — drag only changes `view.x`. Inertia (if enabled) also stays on x.\n * - `'y'` — drag only changes `view.y`. Inertia stays on y.\n *\n * Locks drag panning to a single axis. The former `useWheelPanTool` /\n * `useWheelZoomTool` / `useKeyboardZoomTool` axis option is dissolved.\n */\n axis?: 'both' | 'x' | 'y';\n}\n\n/**\n * Pan-on-drag tool. Registered in both the active slot (sticky, `H` key)\n * and the hotkey slot (momentary, hold `space`).\n *\n * A declarative shell: its one binding routes a drag to the\n * `viewport.dragPan` action, which owns the gesture, the view writes, and\n * the grabbing cursor. The tool only passes `axis` and `inertia` along.\n */\nexport function useHandTool(opts: UseHandToolOptions = {}): Tool {\n // Read through a ref from a params thunk rather than closing over the\n // values: a consumer passing `inertia={{ friction: 0.9 }}` inline would\n // otherwise mint a new tool identity on every render.\n const optsRef = useLatest(opts);\n return useMemo(\n () =>\n Object.assign(defineTool({\n id: 'hand',\n keybinding: { key: 'H' },\n capabilities: ['navigation'],\n hotkey: 'space',\n hookName: 'useHandTool',\n presentation: {\n label: 'Hand',\n icon: icon('hand'),\n group: 'view',\n },\n cursor: 'grab',\n }), {\n // Declarative binding routes drag through the dispatcher +\n // viewportDragPanAction, which also owns the grabbing cursor\n // (`Action.activeCursor`) the tool used to declare as an `engaged`\n // phase entry.\n bindings: [{\n spec: { kind: 'drag' as const },\n actionId: 'viewport.dragPan',\n opts: {\n id: 'hand.drag',\n params: () => ({\n axis: optsRef.current.axis ?? 'both',\n inertia: optsRef.current.inertia,\n }),\n },\n }],\n }) as Tool,\n [optsRef],\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useImageTool.js","names":[],"sources":["../../../../src/tools/builtin/image/useImageTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useImageTool`. */\nexport interface UseImageToolOptions extends InsertToolOptions {\n /** Image source for inserted nodes — a URL, a `blob:` URL, or a\n * `data:image/…;base64,…` URI. Stored verbatim on each new node's\n * `data.image.src`. */\n src: string;\n label?: string;\n /** What the live drag paints. `'bitmap'` (default) previews the decoded\n * image inside the drag bounds, falling back to the outline until it\n * decodes; `'outline'` never draws the image. */\n preview?: 'bitmap' | 'outline';\n}\n\n/**\n * Drag-to-insert image tool. A drag-rect commits a leaf node with\n * `data: { image: { src } }` through the dispatcher's `insertAction` + the\n * kit's `insert` dep (the same path the shape tools use); the `kit:image`\n * painter renders it once the bitmap decodes.\n *\n * Thin declarative veneer — the node is minted by `useInsertDepSource`'s\n * `'image'` case, not the tool. `src` is baked into the binding's `params`\n * so the insert dep can stamp it onto the new node.\n */\nexport function useImageTool(options: UseImageToolOptions): Tool {\n const { src, label = 'Image', preview = 'bitmap', behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'image',\n capabilities: ['creates-shapes'],\n hookName: 'useImageTool',\n cursor: 'crosshair',\n presentation: {\n label,\n group: 'shape',\n icon: icon('image'),\n },\n // Declarative binding routes empty-space drags through the\n // dispatcher + insertAction; `kind: 'image'` selects the insert\n // dep's image factory and `src` rides along on the new node.\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'image', src, preview }, ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [src, label, preview, behaviors],\n );\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useImageTool.js","names":[],"sources":["../../../../src/tools/builtin/image/useImageTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useImageTool`. */\nexport interface UseImageToolOptions extends InsertToolOptions {\n /** Image source for inserted nodes — a URL, a `blob:` URL, or a\n * `data:image/…;base64,…` URI. Stored verbatim on each new node's\n * `data.image.src`. */\n src: string;\n label?: string;\n /** What the live drag paints. `'bitmap'` (default) previews the decoded\n * image inside the drag bounds, falling back to the outline until it\n * decodes; `'outline'` never draws the image. */\n preview?: 'bitmap' | 'outline';\n}\n\n/**\n * Drag-to-insert image tool. A drag-rect commits a leaf node with\n * `data: { image: { src } }` through the dispatcher's `insertAction` + the\n * kit's `insert` dep (the same path the shape tools use); the `kit:image`\n * painter renders it once the bitmap decodes.\n *\n * Thin declarative veneer — the node is minted by `useInsertDepSource`'s\n * `'image'` case, not the tool. `src` is baked into the binding's `params`\n * so the insert dep can stamp it onto the new node.\n */\nexport function useImageTool(options: UseImageToolOptions): Tool {\n const { src, label = 'Image', preview = 'bitmap', behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'image',\n capabilities: ['creates-shapes'],\n hookName: 'useImageTool',\n cursor: 'crosshair',\n presentation: {\n label,\n group: 'shape',\n icon: icon('image'),\n },\n // Declarative binding routes empty-space drags through the\n // dispatcher + insertAction; `kind: 'image'` selects the insert\n // dep's image factory and `src` rides along on the new node.\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { id: 'image.drag', params: { kind: 'image', src, preview }, ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [src, label, preview, behaviors],\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLassoTool.js","names":[],"sources":["../../../../src/tools/builtin/lasso/useLassoTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { UseLassoSelectOptions } from 'interactions/actions/lasso-select/options';\nimport type { LassoHitMode } from 'core/adapters/types';\nimport type { ToolKeybinding } from '@weasel-js/routing';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useLassoTool` — the lasso-select action's options plus the\n * tool's own hit mode and activation key. */\nexport interface UseLassoToolOptions extends UseLassoSelectOptions {\n /** Hit mode for the action's own selection commit, which runs when no\n * behavior claims the gesture. A behavior carries its own, as\n * `selectFromLasso({ mode })` does. Default 'intersect'. */\n mode?: LassoHitMode;\n /** Override the default keybinding (`{ key: 'L' }`). Pass `null` to omit. */\n keybinding?: ToolKeybinding | null;\n}\n\n/** Free-form polygon select Tool. Drag is handled entirely by the gesture\n * dispatcher via the `lassoSelect` action binding below; the dispatcher\n * overlay layer (`useDispatcherOverlayLayer`) paints the live polyline +\n * dashed close-line while the gesture is in flight. Esc cancels through\n * the dispatcher's standard cancel pipeline.\n *\n * The legacy `useLassoSelect` hook is removed — all gesture\n * state, overlay rendering, and selection commit live in\n * `lassoSelectAction` (see `src/interactions/actions/defaults/lassoSelect.ts`). */\nexport function useLassoTool(options: UseLassoToolOptions = {}): Tool {\n const paramsRef = useLatest<{ mode: LassoHitMode; minVertexSpacing?: number }>({\n mode: options.mode ?? 'intersect',\n ...(options.minVertexSpacing !== undefined ? { minVertexSpacing: options.minVertexSpacing } : {}),\n });\n const { behaviors } = options;\n\n return useMemo(() => {\n return defineTool({\n id: 'lasso',\n capabilities: ['creates-selection'],\n hookName: 'useLassoTool',\n ...(options.keybinding === null ? {} : { keybinding: options.keybinding ?? { key: 'L' } }),\n cursor: 'crosshair',\n presentation: {\n label: 'Lasso',\n icon: icon('lasso'),\n group: 'select',\n },\n // Declarative drag binding for the new gesture dispatcher. The\n // dispatcher invokes `lassoSelectAction`, which owns vertex buffering,\n // overlay state, and the commit-on-end selection write.\n bindings: [\n {\n spec: { kind: 'drag', mods: { shift: 'optional' } },\n actionId: 'lassoSelect',\n // Thunked so a mode or spacing change reaches the next gesture\n // without rebuilding the tool.\n opts: {\n params: () => paramsRef.current,\n ...(behaviors ? { behaviors } : {}),\n },\n },\n ],\n });\n }, [options.keybinding, behaviors, paramsRef]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useLassoTool.js","names":[],"sources":["../../../../src/tools/builtin/lasso/useLassoTool.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { UseLassoSelectOptions } from 'interactions/actions/lasso-select/options';\nimport type { LassoHitMode } from 'core/adapters/types';\nimport type { ToolKeybinding } from '@weasel-js/routing';\nimport { icon } from '../../../icons.gen';\n\n/** Options for `useLassoTool` — the lasso-select action's options plus the\n * tool's own hit mode and activation key. */\nexport interface UseLassoToolOptions extends UseLassoSelectOptions {\n /** Hit mode for the action's own selection commit, which runs when no\n * behavior claims the gesture. A behavior carries its own, as\n * `selectFromLasso({ mode })` does. Default 'intersect'. */\n mode?: LassoHitMode;\n /** Override the default keybinding (`{ key: 'L' }`). Pass `null` to omit. */\n keybinding?: ToolKeybinding | null;\n}\n\n/** Free-form polygon select Tool. Drag is handled entirely by the gesture\n * dispatcher via the `lassoSelect` action binding below; the dispatcher\n * overlay layer (`useDispatcherOverlayLayer`) paints the live polyline +\n * dashed close-line while the gesture is in flight. Esc cancels through\n * the dispatcher's standard cancel pipeline.\n *\n * The legacy `useLassoSelect` hook is removed — all gesture\n * state, overlay rendering, and selection commit live in\n * `lassoSelectAction` (see `src/interactions/actions/defaults/lassoSelect.ts`). */\nexport function useLassoTool(options: UseLassoToolOptions = {}): Tool {\n const paramsRef = useLatest<{ mode: LassoHitMode; minVertexSpacing?: number }>({\n mode: options.mode ?? 'intersect',\n ...(options.minVertexSpacing !== undefined ? { minVertexSpacing: options.minVertexSpacing } : {}),\n });\n const { behaviors } = options;\n\n return useMemo(() => {\n return defineTool({\n id: 'lasso',\n capabilities: ['creates-selection'],\n hookName: 'useLassoTool',\n ...(options.keybinding === null ? {} : { keybinding: options.keybinding ?? { key: 'L' } }),\n cursor: 'crosshair',\n presentation: {\n label: 'Lasso',\n icon: icon('lasso'),\n group: 'select',\n },\n // Declarative drag binding for the new gesture dispatcher. The\n // dispatcher invokes `lassoSelectAction`, which owns vertex buffering,\n // overlay state, and the commit-on-end selection write.\n bindings: [\n {\n spec: { kind: 'drag', mods: { shift: 'optional' } },\n actionId: 'lassoSelect',\n // Thunked so a mode or spacing change reaches the next gesture\n // without rebuilding the tool.\n opts: {\n id: 'lasso.drag',\n params: () => paramsRef.current,\n ...(behaviors ? { behaviors } : {}),\n },\n },\n ],\n });\n }, [options.keybinding, behaviors, paramsRef]);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLineTool.js","names":[],"sources":["../../../../src/tools/builtin/line/useLineTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/** An endpoint of a line, in world coordinates. */\nexport interface LinePoint { x: number; y: number }\n\n/**\n * Drag-to-draw line tool. The `drag` binding routes to `insertAction`, which\n * commits through the `insert` dep with `{ kind: 'line', a, b }` endpoints\n * (not the AABB diagonal), so the drag direction is preserved.\n *\n * Shift constrains to 15° increments; alt mirrors the end around the start\n * (the drag is treated as a half-line).\n */\nexport function useLineTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'line',\n keybinding: { key: '\\\\' },\n capabilities: ['creates-shapes'],\n hookName: 'useLineTool',\n cursor: cursorFor('crosshairLine', { fallback: 'crosshair' }),\n presentation: {\n label: 'Line',\n group: 'shape',\n icon: icon('line'),\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'line' }
|
|
1
|
+
{"version":3,"file":"useLineTool.js","names":[],"sources":["../../../../src/tools/builtin/line/useLineTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { icon } from '../../../icons.gen';\n\n/** An endpoint of a line, in world coordinates. */\nexport interface LinePoint { x: number; y: number }\n\n/**\n * Drag-to-draw line tool. The `drag` binding routes to `insertAction`, which\n * commits through the `insert` dep with `{ kind: 'line', a, b }` endpoints\n * (not the AABB diagonal), so the drag direction is preserved.\n *\n * Shift constrains to 15° increments; alt mirrors the end around the start\n * (the drag is treated as a half-line).\n */\nexport function useLineTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'line',\n keybinding: { key: '\\\\' },\n capabilities: ['creates-shapes'],\n hookName: 'useLineTool',\n cursor: cursorFor('crosshairLine', { fallback: 'crosshair' }),\n presentation: {\n label: 'Line',\n group: 'shape',\n icon: icon('line'),\n },\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { id: 'line.drag', params: { kind: 'line' }, ...insertBindingBehaviors(behaviors) },\n },\n INSERT_REPOSITION_BINDING,\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":"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"}
|