@weasel-js/core 1.11.0 → 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 +611 -0
- package/README.md +1 -1
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +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 +9 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +10 -6
- package/dist/barrel/renderer.js +5 -3
- package/dist/barrel/routing.js +7 -12
- package/dist/barrel/scene.js +9 -5
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +9 -4
- package/dist/canvas/Canvas.js +5 -2
- 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/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -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/scenePointQuery.js +7 -3
- package/dist/canvas/SceneCanvas/scenePointQuery.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/useActionTunings.js +6 -1
- package/dist/canvas/SceneCanvas/useActionTunings.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 +94 -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 +15 -10
- 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/useSceneCanvasHandle.js +9 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -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 +24 -7
- 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 +5 -5
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +27 -24
- 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/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- 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/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/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.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 +10 -4
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +189 -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 +38 -4
- 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 +23 -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 +12 -10
- 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 +12 -11
- 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/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/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/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +7 -6
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.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/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- 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/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.js.map +1 -1
- 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/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 +163 -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/paint/meshKindLazy.js +59 -2
- package/dist/core/paint/meshKindLazy.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/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/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 +13 -2
- 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/fontReads.js +37 -0
- package/dist/core/scene/fontReads.js.map +1 -0
- package/dist/core/scene/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.js.map +1 -1
- 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/layoutPass.js +28 -3
- package/dist/core/scene/layoutPass.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/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-p8fDIAKt.d.ts} +3 -2
- 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-mG19aEdD.d.ts} +174 -904
- 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/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/index.js +2 -2
- package/dist/features/paths/pathEditExtension.js.map +1 -1
- package/dist/features/paths/pathEditState.js +5 -2
- package/dist/features/paths/pathEditState.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/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/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 +1198 -894
- package/dist/index.js +55 -38
- 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/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/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/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 +8 -5
- 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 +2 -2
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +64 -41
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +12 -9
- 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 +21 -15
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +17 -9
- 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 +21 -40
- 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/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 +10 -10
- 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 +14 -6
- 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/repositionAction.js +2 -1
- package/dist/interactions/actions/insert/repositionAction.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 +15 -8
- 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/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/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/cornerHandles.js +2 -1
- package/dist/interactions/actions/resize/cornerHandles.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 +25 -9
- 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 +13 -11
- 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/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -5
- 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/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/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/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.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/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/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +39 -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
|
@@ -17,7 +17,12 @@ import { useMemo } from "react";
|
|
|
17
17
|
* caller's own api is not wrapped and still writes.
|
|
18
18
|
*/
|
|
19
19
|
function useCanvasSelection(args) {
|
|
20
|
-
const { scene,
|
|
20
|
+
const { scene, selectable, kindOf } = args;
|
|
21
|
+
const { selection: supplied, selectionOptions: options, describeKind } = args.props;
|
|
22
|
+
const describe = useMemo(() => describeKind ?? (kindOf && ((node) => {
|
|
23
|
+
const kind = kindOf(node);
|
|
24
|
+
return kind === "unknown" ? void 0 : kind;
|
|
25
|
+
})), [describeKind, kindOf]);
|
|
21
26
|
const derivedOptions = useMemo(() => ({
|
|
22
27
|
scene,
|
|
23
28
|
...options ?? {}
|
|
@@ -25,7 +30,7 @@ function useCanvasSelection(args) {
|
|
|
25
30
|
const internal = useSelection(derivedOptions);
|
|
26
31
|
const base = supplied ?? internal;
|
|
27
32
|
const selection = selectable ? base : readOnlySelection(base);
|
|
28
|
-
usePublishSceneSelection(scene, selection.current,
|
|
33
|
+
usePublishSceneSelection(scene, selection.current, describe);
|
|
29
34
|
return selection;
|
|
30
35
|
}
|
|
31
36
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCanvasSelection.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useCanvasSelection.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { readOnlySelection } from 'core/selection/readOnlySelection';\nimport { usePublishSceneSelection } from 'core/selection/usePublishSceneSelection';\nimport { useSelection, type SelectionApi, type UseSelectionOptions } from 'core/selection/useSelection';\n\n/**\n * The canvas's selection, published to any surrounding selection context.\n *\n * A caller-supplied api wins, and the one built here is then unused. The\n * built one is bound to the scene, so the selection an edit was made under\n * rides on the scene's history entries and undo can put it back.\n *\n * Everything the kit writes selection through (the `selection` dep, the\n * adapter's `setSelection`, ops committed through either) reads the returned\n * api, so on an unselectable canvas every write path here is closed. The\n * caller's own api is not wrapped and still writes.\n */\nexport function useCanvasSelection<TData, TLayer extends string, TPose>(args: {\n scene: Scene<TData, TLayer, TPose>;\n
|
|
1
|
+
{"version":3,"file":"useCanvasSelection.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useCanvasSelection.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { readOnlySelection } from 'core/selection/readOnlySelection';\nimport { usePublishSceneSelection } from 'core/selection/usePublishSceneSelection';\nimport { useSelection, type SelectionApi, type UseSelectionOptions } from 'core/selection/useSelection';\nimport type { SceneCanvasProps } from './props';\n\n/**\n * The canvas's selection, published to any surrounding selection context.\n *\n * A caller-supplied api wins, and the one built here is then unused. The\n * built one is bound to the scene, so the selection an edit was made under\n * rides on the scene's history entries and undo can put it back.\n *\n * Everything the kit writes selection through (the `selection` dep, the\n * adapter's `setSelection`, ops committed through either) reads the returned\n * api, so on an unselectable canvas every write path here is closed. The\n * caller's own api is not wrapped and still writes.\n */\nexport function useCanvasSelection<TData, TLayer extends string, TPose>(args: {\n scene: Scene<TData, TLayer, TPose>;\n props: Pick<SceneCanvasProps<TData, TLayer, TPose>, 'selection' | 'selectionOptions' | 'describeKind'>;\n selectable: boolean;\n /** The canvas's routing kind, published for each node unless `describeKind` is given. */\n kindOf: ((node: { kind: string; data: TData }) => string) | undefined;\n}): SelectionApi {\n const { scene, selectable, kindOf } = args;\n const { selection: supplied, selectionOptions: options, describeKind } = args.props;\n const describe = useMemo(() => describeKind ?? (kindOf && ((node: Node<TData, TLayer, TPose>) => {\n const kind = kindOf(node);\n return kind === 'unknown' ? undefined : kind;\n })), [describeKind, kindOf]);\n const derivedOptions = useMemo<UseSelectionOptions>(\n () => ({ scene, ...(options ?? {}) }),\n [scene, options],\n );\n const internal = useSelection(derivedOptions);\n const base = supplied ?? internal;\n const selection = selectable ? base : readOnlySelection(base);\n usePublishSceneSelection(scene, selection.current as readonly NodeId[], describe);\n return selection;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,SAAgB,mBAAwD,MAMvD;CACf,MAAM,EAAE,OAAO,YAAY,WAAW;CACtC,MAAM,EAAE,WAAW,UAAU,kBAAkB,SAAS,iBAAiB,KAAK;CAC9E,MAAM,WAAW,cAAc,iBAAiB,YAAY,SAAqC;EAC/F,MAAM,OAAO,OAAO,IAAI;EACxB,OAAO,SAAS,YAAY,SAAY;CAC1C,KAAK,CAAC,cAAc,MAAM,CAAC;CAC3B,MAAM,iBAAiB,eACd;EAAE;EAAO,GAAI,WAAW,CAAC;CAAG,IACnC,CAAC,OAAO,OAAO,CACjB;CACA,MAAM,WAAW,aAAa,cAAc;CAC5C,MAAM,OAAO,YAAY;CACzB,MAAM,YAAY,aAAa,OAAO,kBAAkB,IAAI;CAC5D,yBAAyB,OAAO,UAAU,SAA8B,QAAQ;CAChF,OAAO;AACT"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { createViewMarkerContribution } from "../../features/viewports/viewMarkerDrag.js";
|
|
1
2
|
import { createLongPressFeedbackContribution } from "../../features/longPress/longPressFeedback.js";
|
|
2
3
|
import { useTools } from "../../tools/overlayBinding.js";
|
|
3
4
|
import { presetActions, presetAmbient, presetContributions, resolveFeatures } from "./features.js";
|
|
4
5
|
import { useBuiltinTools } from "./useBuiltinTools.js";
|
|
5
|
-
import {
|
|
6
|
+
import { useEffect, useMemo } from "react";
|
|
6
7
|
import { useLatest } from "@weasel-js/react";
|
|
7
8
|
|
|
8
9
|
//#region src/canvas/SceneCanvas/useCanvasTools.ts
|
|
@@ -21,12 +22,16 @@ var entryKey = (e) => {
|
|
|
21
22
|
};
|
|
22
23
|
/** The presets a canvas runs with. Keyed on the entries, not the array, so
|
|
23
24
|
* an inline `features={['draw', pathTools]}` does not re-derive every render. */
|
|
24
|
-
function useEnabledFeatures(features, named, hasViewport) {
|
|
25
|
+
function useEnabledFeatures(features, named, hasViewport, selectRotates) {
|
|
25
26
|
const featuresKey = (features ?? []).map(entryKey).join("|");
|
|
26
|
-
return useMemo(() => resolveFeatures(features, named, {
|
|
27
|
+
return useMemo(() => resolveFeatures(features, named, {
|
|
28
|
+
viewport: hasViewport,
|
|
29
|
+
selectRotates
|
|
30
|
+
}), [
|
|
27
31
|
featuresKey,
|
|
28
32
|
named,
|
|
29
|
-
hasViewport
|
|
33
|
+
hasViewport,
|
|
34
|
+
selectRotates
|
|
30
35
|
]);
|
|
31
36
|
}
|
|
32
37
|
/**
|
|
@@ -37,12 +42,8 @@ function useEnabledFeatures(features, named, hasViewport) {
|
|
|
37
42
|
function useCanvasTools(args) {
|
|
38
43
|
const { select, enabled, tools: toolsProp, defaultTools, toolOptions, inertia, ambient, initialActiveTool, modes, onToolsCreated } = args;
|
|
39
44
|
const takeover = toolsProp && isToolsApi(toolsProp) ? toolsProp : null;
|
|
40
|
-
const selectionRef = useLatest(args.selection);
|
|
41
|
-
const selected = useCallback(() => selectionRef.current.get(), [selectionRef]);
|
|
42
45
|
const registry = useBuiltinTools({
|
|
43
46
|
select,
|
|
44
|
-
scene: args.scene,
|
|
45
|
-
selection: selected,
|
|
46
47
|
enabled,
|
|
47
48
|
defaultTools,
|
|
48
49
|
patch: toolsProp && !isToolsApi(toolsProp) ? toolsProp : null,
|
|
@@ -52,14 +53,18 @@ function useCanvasTools(args) {
|
|
|
52
53
|
const defaultPressFeedback = useMemo(() => createLongPressFeedbackContribution(), []);
|
|
53
54
|
const feedbackOpt = args.pressFeedback ?? true;
|
|
54
55
|
const pressFeedback = feedbackOpt === true ? defaultPressFeedback : feedbackOpt || null;
|
|
56
|
+
const defaultMarkerDrag = useMemo(() => createViewMarkerContribution(), []);
|
|
57
|
+
const markerDrag = args.actions === null ? null : defaultMarkerDrag;
|
|
55
58
|
const mergedAmbient = useMemo(() => [
|
|
56
59
|
...presetContributions(enabled),
|
|
57
60
|
...ambient ?? [],
|
|
58
|
-
...pressFeedback ? [pressFeedback] : []
|
|
61
|
+
...pressFeedback ? [pressFeedback] : [],
|
|
62
|
+
...markerDrag ? [markerDrag] : []
|
|
59
63
|
], [
|
|
60
64
|
enabled,
|
|
61
65
|
ambient,
|
|
62
|
-
pressFeedback
|
|
66
|
+
pressFeedback,
|
|
67
|
+
markerDrag
|
|
63
68
|
]);
|
|
64
69
|
const internal = useTools({
|
|
65
70
|
active: initialActiveTool ?? ("select" in registry ? "select" : null),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCanvasTools.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useCanvasTools.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"useCanvasTools.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useCanvasTools.ts"],"sourcesContent":["import { useEffect, useMemo } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { Action } from '@weasel-js/routing';\nimport { createLongPressFeedbackContribution } from '../../features/longPress/longPressFeedback';\nimport { createViewMarkerContribution } from '../../features/viewports/viewMarkerDrag';\nimport { useTools, type Contribution, type Tool, type ToolsApi } from '../../tools/overlayBinding';\nimport {\n presetActions,\n presetAmbient,\n presetContributions,\n resolveFeatures,\n type EnabledPresets,\n type FeatureBindingOptions,\n type FeatureEntry,\n type NamedPresets,\n} from './features';\nimport type { SceneCanvasProps } from './props';\nimport type { ToolsPatch } from './toolRegistry';\nimport { useBuiltinTools } from './useBuiltinTools';\n\ntype Props = SceneCanvasProps<unknown, string, unknown>;\n\n/** Discriminate the polymorphic `tools` prop: `ToolsApi` has `setActive`\n * / `active` / `registry`; the patch record shape has none of those. */\nfunction isToolsApi(tools: ToolsApi | ToolsPatch): tools is ToolsApi {\n return typeof (tools as ToolsApi).setActive === 'function';\n}\n\nconst presetSerials = new WeakMap<object, number>();\nlet nextSerial = 0;\nconst entryKey = (e: FeatureEntry): string => {\n if (typeof e === 'string') return e;\n let n = presetSerials.get(e);\n if (n === undefined) presetSerials.set(e, (n = nextSerial++));\n return `#${n}`;\n};\n\n/** The presets a canvas runs with. Keyed on the entries, not the array, so\n * an inline `features={['draw', pathTools]}` does not re-derive every render. */\nexport function useEnabledFeatures(\n features: readonly FeatureEntry[] | undefined,\n named: NamedPresets | null,\n hasViewport: boolean,\n selectRotates: boolean,\n): EnabledPresets {\n const featuresKey = (features ?? []).map(entryKey).join('|');\n return useMemo(\n () => resolveFeatures(features, named, { viewport: hasViewport, selectRotates }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [featuresKey, named, hasViewport, selectRotates],\n );\n}\n\n/**\n * The canvas's tools: a caller's own `ToolsApi` when the `tools` prop is one\n * (the takeover form), and otherwise the built-ins the presets and\n * `defaultTools` name, patched by a `tools` record.\n */\nexport function useCanvasTools(args: {\n /** The canvas's select tool, which is built from its scene and pickers. */\n select: Tool;\n enabled: EnabledPresets;\n tools: Props['tools'];\n defaultTools: Props['defaultTools'];\n toolOptions: Props['toolOptions'];\n /** `viewport.inertia`, which is the hand tool's. */\n inertia: NonNullable<Props['viewport']>['inertia'];\n ambient: Props['ambient'];\n /** `null` leaves out the kit's default actions, the marker drag among them. */\n actions: Props['actions'];\n /** `longPress.feedback`. Default true, which installs the kit's own. */\n pressFeedback: NonNullable<Props['longPress']>['feedback'];\n initialActiveTool: Props['initialActiveTool'];\n modes: Props['modes'];\n onToolsCreated: Props['onToolsCreated'];\n}): {\n /** What the canvas routes input through: the takeover, or `internal`. */\n tools: ToolsApi;\n /** The canvas's own api, built whether or not a takeover replaces it. */\n internal: ToolsApi;\n takeover: ToolsApi | null;\n} {\n const { select, enabled, tools: toolsProp, defaultTools, toolOptions, inertia, ambient, initialActiveTool, modes, onToolsCreated } = args;\n\n const takeover = toolsProp && isToolsApi(toolsProp) ? toolsProp : null;\n const registry = useBuiltinTools({\n select,\n enabled,\n defaultTools,\n patch: toolsProp && !isToolsApi(toolsProp) ? toolsProp : null,\n toolOptions,\n inertia,\n });\n\n const defaultPressFeedback = useMemo(() => createLongPressFeedbackContribution(), []);\n const feedbackOpt = args.pressFeedback ?? true;\n const pressFeedback = feedbackOpt === true ? defaultPressFeedback : feedbackOpt || null;\n const defaultMarkerDrag = useMemo(() => createViewMarkerContribution(), []);\n const markerDrag = args.actions === null ? null : defaultMarkerDrag;\n const mergedAmbient = useMemo(\n () => [\n ...presetContributions(enabled), ...(ambient ?? []),\n ...(pressFeedback ? [pressFeedback] : []), ...(markerDrag ? [markerDrag] : []),\n ],\n [enabled, ambient, pressFeedback, markerDrag],\n );\n\n const internal = useTools({\n active: initialActiveTool ?? ('select' in registry ? 'select' : null),\n registry,\n ...(mergedAmbient.length ? { ambient: mergedAmbient } : {}),\n ...(modes ? { modes } : {}),\n });\n const tools = takeover ?? internal;\n\n const onToolsCreatedRef = useLatest(onToolsCreated);\n useEffect(() => { onToolsCreatedRef.current?.(tools); }, [tools, onToolsCreatedRef]);\n\n return { tools, internal, takeover };\n}\n\n/**\n * The presets' ambient bindings, and the standard actions the canvas\n * registers. The bindings are not tools and sit outside `tools`, so they apply\n * under a takeover too. An action is registered when an enabled preset brings\n * it, or when it is in `pool` and a tool or contribution on this canvas binds\n * it: a tool brings the actions it routes to, so `defaultTools={['rect']}`\n * works under any preset.\n */\nexport function useFeatureBindings(args: {\n enabled: EnabledPresets;\n /** Actions registered only when something binds them. */\n pool: readonly Action[];\n tools: Pick<ToolsApi, 'registry' | 'ambient'>;\n move: FeatureBindingOptions['move'];\n rotate: FeatureBindingOptions['rotate'];\n}): { contributions: Contribution[]; standardActions: Action[] } {\n const { enabled, pool, tools, move, rotate } = args;\n const contributions = useMemo<Contribution[]>(\n () => presetAmbient(enabled, { move, rotate }),\n [enabled, move, rotate],\n );\n const standardActions = useMemo(() => {\n const out = presetActions(enabled);\n const have = new Set(out.map((a) => a.id));\n const bound = new Set<string>();\n for (const entry of [...Object.values(tools.registry), ...tools.ambient, ...contributions]) {\n for (const b of entry.bindings ?? []) bound.add(b.actionId);\n }\n for (const a of pool) {\n if (bound.has(a.id) && !have.has(a.id)) {\n have.add(a.id);\n out.push(a);\n }\n }\n return out;\n }, [enabled, pool, tools, contributions]);\n return { contributions, standardActions };\n}\n\n"],"mappings":";;;;;;;;;;;AAwBA,SAAS,WAAW,OAAiD;CACnE,OAAO,OAAQ,MAAmB,cAAc;AAClD;AAEA,IAAM,gCAAgB,IAAI,QAAwB;AAClD,IAAI,aAAa;AACjB,IAAM,YAAY,MAA4B;CAC5C,IAAI,OAAO,MAAM,UAAU,OAAO;CAClC,IAAI,IAAI,cAAc,IAAI,CAAC;CAC3B,IAAI,MAAM,QAAW,cAAc,IAAI,GAAI,IAAI,YAAa;CAC5D,OAAO,IAAI;AACb;;;AAIA,SAAgB,mBACd,UACA,OACA,aACA,eACgB;CAChB,MAAM,eAAe,YAAY,CAAC,EAAA,CAAG,IAAI,QAAQ,CAAC,CAAC,KAAK,GAAG;CAC3D,OAAO,cACC,gBAAgB,UAAU,OAAO;EAAE,UAAU;EAAa;CAAc,CAAC,GAE/E;EAAC;EAAa;EAAO;EAAa;CAAa,CACjD;AACF;;;;;;AAOA,SAAgB,eAAe,MAuB7B;CACA,MAAM,EAAE,QAAQ,SAAS,OAAO,WAAW,cAAc,aAAa,SAAS,SAAS,mBAAmB,OAAO,mBAAmB;CAErI,MAAM,WAAW,aAAa,WAAW,SAAS,IAAI,YAAY;CAClE,MAAM,WAAW,gBAAgB;EAC/B;EACA;EACA;EACA,OAAO,aAAa,CAAC,WAAW,SAAS,IAAI,YAAY;EACzD;EACA;CACF,CAAC;CAED,MAAM,uBAAuB,cAAc,oCAAoC,GAAG,CAAC,CAAC;CACpF,MAAM,cAAc,KAAK,iBAAiB;CAC1C,MAAM,gBAAgB,gBAAgB,OAAO,uBAAuB,eAAe;CACnF,MAAM,oBAAoB,cAAc,6BAA6B,GAAG,CAAC,CAAC;CAC1E,MAAM,aAAa,KAAK,YAAY,OAAO,OAAO;CAClD,MAAM,gBAAgB,cACd;EACJ,GAAG,oBAAoB,OAAO;EAAG,GAAI,WAAW,CAAC;EACjD,GAAI,gBAAgB,CAAC,aAAa,IAAI,CAAC;EAAI,GAAI,aAAa,CAAC,UAAU,IAAI,CAAC;CAC9E,GACA;EAAC;EAAS;EAAS;EAAe;CAAU,CAC9C;CAEA,MAAM,WAAW,SAAS;EACxB,QAAQ,sBAAsB,YAAY,WAAW,WAAW;EAChE;EACA,GAAI,cAAc,SAAS,EAAE,SAAS,cAAc,IAAI,CAAC;EACzD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;CACD,MAAM,QAAQ,YAAY;CAE1B,MAAM,oBAAoB,UAAU,cAAc;CAClD,gBAAgB;EAAE,kBAAkB,UAAU,KAAK;CAAG,GAAG,CAAC,OAAO,iBAAiB,CAAC;CAEnF,OAAO;EAAE;EAAO;EAAU;CAAS;AACrC;;;;;;;;;AAUA,SAAgB,mBAAmB,MAO8B;CAC/D,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,WAAW;CAC/C,MAAM,gBAAgB,cACd,cAAc,SAAS;EAAE;EAAM;CAAO,CAAC,GAC7C;EAAC;EAAS;EAAM;CAAM,CACxB;CAgBA,OAAO;EAAE;EAAe,iBAfA,cAAc;GACpC,MAAM,MAAM,cAAc,OAAO;GACjC,MAAM,OAAO,IAAI,IAAI,IAAI,KAAK,MAAM,EAAE,EAAE,CAAC;GACzC,MAAM,wBAAQ,IAAI,IAAY;GAC9B,KAAK,MAAM,SAAS;IAAC,GAAG,OAAO,OAAO,MAAM,QAAQ;IAAG,GAAG,MAAM;IAAS,GAAG;GAAa,GACvF,KAAK,MAAM,KAAK,MAAM,YAAY,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ;GAE5D,KAAK,MAAM,KAAK,MACd,IAAI,MAAM,IAAI,EAAE,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,GAAG;IACtC,KAAK,IAAI,EAAE,EAAE;IACb,IAAI,KAAK,CAAC;GACZ;GAEF,OAAO;EACT,GAAG;GAAC;GAAS;GAAM;GAAO;EAAa,CACf;CAAgB;AAC1C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createNodeRouting } from "../../core/scene/NodeRouting.js";
|
|
2
1
|
import { inferredNodeRouting } from "./defaultNodeRouting.js";
|
|
2
|
+
import { createNodeRouting } from "../../core/scene/NodeRouting.js";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/canvas/SceneCanvas/useNodeKinds.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNodeKinds.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useNodeKinds.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { createNodeRouting, type NodeRoutingEntry } from 'core/scene/NodeRouting';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport { inferredNodeRouting } from './defaultNodeRouting';\n\n/**\n * The canvas's routing-trait classifier, by node data and by node id, so\n * `target: 'kind:text'` on a binding speaks the vocabulary of `Hit.kind`.\n * Unset `routing` falls back to `inferredNodeRouting`. An explicit empty list\n * opts out: both are undefined, every hit is `kind: 'unknown'`, and no\n * `kind:` target form can match.\n */\nexport function useNodeKinds<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n routing: readonly NodeRoutingEntry[] | undefined,\n):
|
|
1
|
+
{"version":3,"file":"useNodeKinds.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useNodeKinds.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { createNodeRouting, type NodeRoutingEntry } from 'core/scene/NodeRouting';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport { inferredNodeRouting } from './defaultNodeRouting';\n\nexport interface NodeKinds<TData> {\n kindOf: ((node: { kind: string; data: TData }) => string) | undefined;\n kindOfNode: ((id: string) => string | undefined) | undefined;\n}\n\n/**\n * The canvas's routing-trait classifier, by node data and by node id, so\n * `target: 'kind:text'` on a binding speaks the vocabulary of `Hit.kind`.\n * Unset `routing` falls back to `inferredNodeRouting`. An explicit empty list\n * opts out: both are undefined, every hit is `kind: 'unknown'`, and no\n * `kind:` target form can match.\n */\nexport function useNodeKinds<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n routing: readonly NodeRoutingEntry[] | undefined,\n): NodeKinds<TData> {\n const kindOf = useMemo(() => {\n const effective = routing === undefined ? inferredNodeRouting : routing;\n if (effective.length === 0) return undefined;\n const registry = createNodeRouting();\n for (const k of effective) registry.register(k);\n return (node: { kind: string; data: TData }) => registry.classify(node.data, node);\n }, [routing]);\n\n const kindOfNode = useMemo(() => {\n if (!kindOf) return undefined;\n return (id: string): string | undefined => {\n const node = scene.get(id as NodeId);\n return node ? kindOf(node) : undefined;\n };\n }, [kindOf, scene]);\n\n return { kindOf, kindOfNode };\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,SAAgB,aACd,OACA,SACkB;CAClB,MAAM,SAAS,cAAc;EAC3B,MAAM,YAAY,YAAY,SAAY,sBAAsB;EAChE,IAAI,UAAU,WAAW,GAAG,OAAO;EACnC,MAAM,WAAW,kBAAkB;EACnC,KAAK,MAAM,KAAK,WAAW,SAAS,SAAS,CAAC;EAC9C,QAAQ,SAAwC,SAAS,SAAS,KAAK,MAAM,IAAI;CACnF,GAAG,CAAC,OAAO,CAAC;CAUZ,OAAO;EAAE;EAAQ,YARE,cAAc;GAC/B,IAAI,CAAC,QAAQ,OAAO;GACpB,QAAQ,OAAmC;IACzC,MAAM,OAAO,MAAM,IAAI,EAAY;IACnC,OAAO,OAAO,OAAO,IAAI,IAAI;GAC/B;EACF,GAAG,CAAC,QAAQ,KAAK,CAEA;CAAW;AAC9B"}
|
|
@@ -26,7 +26,9 @@ function useAddedViews() {
|
|
|
26
26
|
w: 0,
|
|
27
27
|
h: 0
|
|
28
28
|
}
|
|
29
|
-
}, [surfaceViewRegistry])
|
|
29
|
+
}, [surfaceViewRegistry]),
|
|
30
|
+
aimOf: useCallback((id) => surfaceViewRegistry?.aimOf(id) ?? null, [surfaceViewRegistry]),
|
|
31
|
+
setAim: useCallback((id, aim) => surfaceViewRegistry?.setAim(id, aim) ?? false, [surfaceViewRegistry])
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
@@ -35,7 +37,7 @@ function useAddedViews() {
|
|
|
35
37
|
* and keeps the canvas's own copies of the element and the handle current.
|
|
36
38
|
*/
|
|
37
39
|
function useSceneCanvasHandle(args) {
|
|
38
|
-
const { ref, elementRef, apiRef, onElement, ingest, viewAnimation, camera, addView, viewAt } = args;
|
|
40
|
+
const { ref, elementRef, apiRef, onElement, ingest, viewAnimation, camera, addView, viewAt, aimOf, setAim } = args;
|
|
39
41
|
const [ready, setReady] = useState(false);
|
|
40
42
|
return {
|
|
41
43
|
handleRef: useCallback((node) => {
|
|
@@ -49,7 +51,9 @@ function useSceneCanvasHandle(args) {
|
|
|
49
51
|
isViewAnimating: viewAnimation.isAnimating,
|
|
50
52
|
camera,
|
|
51
53
|
addView,
|
|
52
|
-
viewAt
|
|
54
|
+
viewAt,
|
|
55
|
+
aimOf,
|
|
56
|
+
setAim
|
|
53
57
|
} : null;
|
|
54
58
|
apiRef.current = extended;
|
|
55
59
|
setReady(extended !== null);
|
|
@@ -63,6 +67,8 @@ function useSceneCanvasHandle(args) {
|
|
|
63
67
|
camera,
|
|
64
68
|
addView,
|
|
65
69
|
viewAt,
|
|
70
|
+
aimOf,
|
|
71
|
+
setAim,
|
|
66
72
|
onElement
|
|
67
73
|
]),
|
|
68
74
|
ready
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSceneCanvasHandle.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasHandle.ts"],"sourcesContent":["import { useCallback, useState, type ForwardedRef, type MutableRefObject } from 'react';\nimport { assignRef } from '@weasel-js/react';\nimport type { ViewAnimationApi } from 'core/viewport/useViewAnimation';\nimport type { CanvasViewProps } from '../CanvasView';\nimport type { CanvasExtensionApi, CanvasViewHandle, SceneCanvasApi } from '../canvasExtension';\nimport { IDENTITY_VIEW, useOptionalViewRegistry } from '../viewRegistry';\n\n/** Views added through the handle rather than declared as props or children. */\nexport function useAddedViews(): {\n views: readonly CanvasViewProps[];\n addView: SceneCanvasApi['addView'];\n viewAt: SceneCanvasApi['viewAt'];\n} {\n const surfaceViewRegistry = useOptionalViewRegistry();\n const [views, setViews] = useState<readonly CanvasViewProps[]>([]);\n const addView = useCallback((props: CanvasViewProps): CanvasViewHandle => {\n setViews((list) => [...list.filter((v) => v.id !== props.id), props]);\n return {\n id: props.id,\n draw: (data, outer, dims) =>\n surfaceViewRegistry?.list().find((r) => r.id === props.id)?.layer.draw(data, outer, dims) ?? [],\n remove: () => setViews((list) => list.filter((v) => v !== props)),\n };\n }, [surfaceViewRegistry]);\n const viewAt = useCallback<SceneCanvasApi['viewAt']>((at, opts) => (\n surfaceViewRegistry?.viewAt(at, opts) ?? { id: null, view: IDENTITY_VIEW, rect: { x: 0, y: 0, w: 0, h: 0 } }\n ), [surfaceViewRegistry]);\n return { views, addView, viewAt };\n}\n\n/**\n * The ref callback `<SceneCanvas>` hands `<Canvas>`. It extends the\n * primitive's handle into the `SceneCanvasApi` the consumer's ref receives,\n * and keeps the canvas's own copies of the element and the handle current.\n */\nexport function useSceneCanvasHandle(args: {\n ref: ForwardedRef<SceneCanvasApi>;\n /** Written with the canvas element, for the input listeners. */\n elementRef: MutableRefObject<HTMLElement | null>;\n /** Written with the extended handle, for `requestRedraw` and point conversion. */\n apiRef: MutableRefObject<CanvasExtensionApi | null>;\n /** Told the element whenever it attaches or detaches. */\n onElement: (element: HTMLElement | null) => void;\n ingest: SceneCanvasApi['ingest'];\n viewAnimation: Pick<ViewAnimationApi, 'animate' | 'stop' | 'isAnimating'>;\n camera: SceneCanvasApi['camera'];\n addView: SceneCanvasApi['addView'];\n viewAt: SceneCanvasApi['viewAt'];\n}): {\n handleRef: (node: CanvasExtensionApi | null) => void;\n /** Whether the handle is attached, as state: an effect needing the handle\n * keys off this instead of assuming when React attaches it. */\n ready: boolean;\n} {\n const { ref, elementRef, apiRef, onElement, ingest, viewAnimation, camera, addView, viewAt } = args;\n const [ready, setReady] = useState(false);\n const handleRef = useCallback(\n (node: CanvasExtensionApi | null) => {\n elementRef.current = node?.element ?? null;\n onElement(elementRef.current);\n const extended: SceneCanvasApi | null = node\n ? {\n ...node,\n ingest,\n animateView: viewAnimation.animate,\n stopViewAnimation: viewAnimation.stop,\n isViewAnimating: viewAnimation.isAnimating,\n camera,\n addView,\n viewAt,\n }\n : null;\n apiRef.current = extended;\n setReady(extended !== null);\n assignRef(ref, extended);\n },\n [ref, elementRef, apiRef, ingest, viewAnimation, camera, addView, viewAt, onElement],\n );\n return { handleRef, ready };\n}\n"],"mappings":";;;;;;AAQA,SAAgB,
|
|
1
|
+
{"version":3,"file":"useSceneCanvasHandle.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasHandle.ts"],"sourcesContent":["import { useCallback, useState, type ForwardedRef, type MutableRefObject } from 'react';\nimport { assignRef } from '@weasel-js/react';\nimport type { ViewAnimationApi } from 'core/viewport/useViewAnimation';\nimport type { CanvasViewProps } from '../CanvasView';\nimport type { CanvasExtensionApi, CanvasViewHandle, SceneCanvasApi } from '../canvasExtension';\nimport { IDENTITY_VIEW, useOptionalViewRegistry } from '../viewRegistry';\n\n/** Views added through the handle rather than declared as props or children. */\nexport function useAddedViews(): {\n views: readonly CanvasViewProps[];\n addView: SceneCanvasApi['addView'];\n viewAt: SceneCanvasApi['viewAt'];\n aimOf: SceneCanvasApi['aimOf'];\n setAim: SceneCanvasApi['setAim'];\n} {\n const surfaceViewRegistry = useOptionalViewRegistry();\n const [views, setViews] = useState<readonly CanvasViewProps[]>([]);\n const addView = useCallback((props: CanvasViewProps): CanvasViewHandle => {\n setViews((list) => [...list.filter((v) => v.id !== props.id), props]);\n return {\n id: props.id,\n draw: (data, outer, dims) =>\n surfaceViewRegistry?.list().find((r) => r.id === props.id)?.layer.draw(data, outer, dims) ?? [],\n remove: () => setViews((list) => list.filter((v) => v !== props)),\n };\n }, [surfaceViewRegistry]);\n const viewAt = useCallback<SceneCanvasApi['viewAt']>((at, opts) => (\n surfaceViewRegistry?.viewAt(at, opts) ?? { id: null, view: IDENTITY_VIEW, rect: { x: 0, y: 0, w: 0, h: 0 } }\n ), [surfaceViewRegistry]);\n const aimOf = useCallback<SceneCanvasApi['aimOf']>(\n (id) => surfaceViewRegistry?.aimOf(id) ?? null, [surfaceViewRegistry]);\n const setAim = useCallback<SceneCanvasApi['setAim']>(\n (id, aim) => surfaceViewRegistry?.setAim(id, aim) ?? false, [surfaceViewRegistry]);\n return { views, addView, viewAt, aimOf, setAim };\n}\n\n/**\n * The ref callback `<SceneCanvas>` hands `<Canvas>`. It extends the\n * primitive's handle into the `SceneCanvasApi` the consumer's ref receives,\n * and keeps the canvas's own copies of the element and the handle current.\n */\nexport function useSceneCanvasHandle(args: {\n ref: ForwardedRef<SceneCanvasApi>;\n /** Written with the canvas element, for the input listeners. */\n elementRef: MutableRefObject<HTMLElement | null>;\n /** Written with the extended handle, for `requestRedraw` and point conversion. */\n apiRef: MutableRefObject<CanvasExtensionApi | null>;\n /** Told the element whenever it attaches or detaches. */\n onElement: (element: HTMLElement | null) => void;\n ingest: SceneCanvasApi['ingest'];\n viewAnimation: Pick<ViewAnimationApi, 'animate' | 'stop' | 'isAnimating'>;\n camera: SceneCanvasApi['camera'];\n addView: SceneCanvasApi['addView'];\n viewAt: SceneCanvasApi['viewAt'];\n aimOf: SceneCanvasApi['aimOf'];\n setAim: SceneCanvasApi['setAim'];\n}): {\n handleRef: (node: CanvasExtensionApi | null) => void;\n /** Whether the handle is attached, as state: an effect needing the handle\n * keys off this instead of assuming when React attaches it. */\n ready: boolean;\n} {\n const { ref, elementRef, apiRef, onElement, ingest, viewAnimation, camera, addView, viewAt, aimOf, setAim } = args;\n const [ready, setReady] = useState(false);\n const handleRef = useCallback(\n (node: CanvasExtensionApi | null) => {\n elementRef.current = node?.element ?? null;\n onElement(elementRef.current);\n const extended: SceneCanvasApi | null = node\n ? {\n ...node,\n ingest,\n animateView: viewAnimation.animate,\n stopViewAnimation: viewAnimation.stop,\n isViewAnimating: viewAnimation.isAnimating,\n camera,\n addView,\n viewAt,\n aimOf,\n setAim,\n }\n : null;\n apiRef.current = extended;\n setReady(extended !== null);\n assignRef(ref, extended);\n },\n [ref, elementRef, apiRef, ingest, viewAnimation, camera, addView, viewAt, aimOf, setAim, onElement],\n );\n return { handleRef, ready };\n}\n"],"mappings":";;;;;;AAQA,SAAgB,gBAMd;CACA,MAAM,sBAAsB,wBAAwB;CACpD,MAAM,CAAC,OAAO,YAAY,SAAqC,CAAC,CAAC;CAiBjE,OAAO;EAAE;EAAO,SAhBA,aAAa,UAA6C;GACxE,UAAU,SAAS,CAAC,GAAG,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,GAAG,KAAK,CAAC;GACpE,OAAO;IACL,IAAI,MAAM;IACV,OAAO,MAAM,OAAO,SAClB,qBAAqB,KAAK,CAAC,CAAC,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC;IAChG,cAAc,UAAU,SAAS,KAAK,QAAQ,MAAM,MAAM,KAAK,CAAC;GAClE;EACF,GAAG,CAAC,mBAAmB,CAQP;EAAS,QAPV,aAAuC,IAAI,SACxD,qBAAqB,OAAO,IAAI,IAAI,KAAK;GAAE,IAAI;GAAM,MAAM;GAAe,MAAM;IAAE,GAAG;IAAG,GAAG;IAAG,GAAG;IAAG,GAAG;GAAE;EAAE,GAC1G,CAAC,mBAAmB,CAKE;EAAQ,OAJnB,aACX,OAAO,qBAAqB,MAAM,EAAE,KAAK,MAAM,CAAC,mBAAmB,CAGrC;EAAO,QAFzB,aACZ,IAAI,QAAQ,qBAAqB,OAAO,IAAI,GAAG,KAAK,OAAO,CAAC,mBAAmB,CAC1C;CAAO;AACjD;;;;;;AAOA,SAAgB,qBAAqB,MAoBnC;CACA,MAAM,EAAE,KAAK,YAAY,QAAQ,WAAW,QAAQ,eAAe,QAAQ,SAAS,QAAQ,OAAO,WAAW;CAC9G,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CAyBxC,OAAO;EAAE,WAxBS,aACf,SAAoC;GACnC,WAAW,UAAU,MAAM,WAAW;GACtC,UAAU,WAAW,OAAO;GAC5B,MAAM,WAAkC,OACpC;IACE,GAAG;IACH;IACA,aAAa,cAAc;IAC3B,mBAAmB,cAAc;IACjC,iBAAiB,cAAc;IAC/B;IACA;IACA;IACA;IACA;GACF,IACA;GACJ,OAAO,UAAU;GACjB,SAAS,aAAa,IAAI;GAC1B,UAAU,KAAK,QAAQ;EACzB,GACA;GAAC;GAAK;GAAY;GAAQ;GAAQ;GAAe;GAAQ;GAAS;GAAQ;GAAO;GAAQ;EAAS,CAE3F;EAAW;CAAM;AAC5B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { targetSizesPx } from "../../core/device/targets.js";
|
|
2
|
+
import { drawnBoundsScene } from "../derivedPath.js";
|
|
2
3
|
import { createSnapOutcomeStore } from "../../features/snap/outcomeStore.js";
|
|
3
4
|
import { builtLayersOf, isCustomEntry } from "../layerSlots.js";
|
|
4
5
|
import { useTargetBasePx } from "../../core/device/useTargetBasePx.js";
|
|
@@ -8,6 +9,7 @@ import { mergeLayersWithDefaults } from "./mergeLayers.js";
|
|
|
8
9
|
import { useDispatcherOverlayLayer } from "./useDispatcherOverlayLayer.js";
|
|
9
10
|
import { usePreviewGhostLayer } from "./usePreviewGhostLayer.js";
|
|
10
11
|
import { useDepartureGhostLayer } from "./useDepartureGhostLayer.js";
|
|
12
|
+
import { useEffectSourcesLayer } from "../../features/pathEffects/useEffectSourcesLayer.js";
|
|
11
13
|
import { usePoseTransition } from "../../animation/poseTransition.js";
|
|
12
14
|
import { useSceneSlotLayers } from "./useSceneSlotLayers.js";
|
|
13
15
|
import { useSelectionOverlayLayer } from "./useSelectionOverlayLayer.js";
|
|
@@ -19,7 +21,8 @@ import { useMemo, useRef, useState } from "react";
|
|
|
19
21
|
* The layer map `<SceneCanvas>` hands `<Canvas>`: the caller's `layers` over
|
|
20
22
|
* the kit defaults, with the scene and selection-overlay slots built, and the
|
|
21
23
|
* canvas's own layers anchored around them. Removed nodes leave just above
|
|
22
|
-
* the scene, the preview ghost above them,
|
|
24
|
+
* the scene, the preview ghost above them, a selected path effect's hidden sources above that, the dispatcher's
|
|
25
|
+
* overlay (marquee, lasso) above those, and the
|
|
23
26
|
* anchor overlay above the selection chrome.
|
|
24
27
|
*/
|
|
25
28
|
function useSceneCanvasLayers(args) {
|
|
@@ -50,6 +53,7 @@ function useSceneCanvasLayers(args) {
|
|
|
50
53
|
sceneSlot,
|
|
51
54
|
departures
|
|
52
55
|
});
|
|
56
|
+
const effectSourcesLayer = useEffectSourcesLayer(scene);
|
|
53
57
|
const dispatcherOverlay = useDispatcherOverlayLayer({ dispatcher });
|
|
54
58
|
const hitRadiusPx = args.selectTool?.handleHitRadius ?? targetSizesPx(targetScale, baseSizes).handle;
|
|
55
59
|
const edges = args.selectTool?.resize?.edgeHandles ?? true;
|
|
@@ -60,7 +64,17 @@ function useSceneCanvasLayers(args) {
|
|
|
60
64
|
const chromeAffordancesRef = useRef([]);
|
|
61
65
|
const slopsLayer = useMemo(() => createSlopsDebugLayer({ getAffordances: () => chromeAffordancesRef.current }), []);
|
|
62
66
|
const [snapStore] = useState(() => createSnapOutcomeStore());
|
|
63
|
-
const
|
|
67
|
+
const { color, gapColor, lineWidth } = args.snapReadoutStyle ?? {};
|
|
68
|
+
const snapReadoutLayer = useMemo(() => createSnapReadoutLayer(snapStore, {
|
|
69
|
+
...color !== void 0 ? { color } : {},
|
|
70
|
+
...gapColor !== void 0 ? { gapColor } : {},
|
|
71
|
+
...lineWidth !== void 0 ? { lineWidth } : {}
|
|
72
|
+
}), [
|
|
73
|
+
snapStore,
|
|
74
|
+
color,
|
|
75
|
+
gapColor,
|
|
76
|
+
lineWidth
|
|
77
|
+
]);
|
|
64
78
|
const overlaySlot = merged.pathEditingOverlay;
|
|
65
79
|
const overlayConfig = overlaySlot && !isCustomEntry(overlaySlot) ? overlaySlot : void 0;
|
|
66
80
|
const overlayAnchor = overlaySlot === null ? "dispatcherOverlay" : "pathEditingOverlay";
|
|
@@ -68,7 +82,7 @@ function useSceneCanvasLayers(args) {
|
|
|
68
82
|
nodeOf: (id) => scene.get(id),
|
|
69
83
|
planeOfNode: args.planeOfNode
|
|
70
84
|
}, overlayConfig);
|
|
71
|
-
const { layer: selectionOverlayLayer, rotationBadge } = useSelectionOverlayLayer(merged.selectionOverlay, pathEditState.getEditingIds, poseDescriptor, args.boundsIncludeStroke ? scene : void 0, resizeHandles);
|
|
85
|
+
const { layer: selectionOverlayLayer, rotationBadge } = useSelectionOverlayLayer(merged.selectionOverlay, pathEditState.getEditingIds, poseDescriptor, args.boundsIncludeStroke ? drawnBoundsScene(scene) : void 0, resizeHandles);
|
|
72
86
|
return {
|
|
73
87
|
layers: useMemo(() => ({
|
|
74
88
|
...builtLayersOf(merged),
|
|
@@ -82,9 +96,13 @@ function useSceneCanvasLayers(args) {
|
|
|
82
96
|
layer: previewLayer,
|
|
83
97
|
after: "departureGhost"
|
|
84
98
|
},
|
|
99
|
+
effectSources: {
|
|
100
|
+
layer: effectSourcesLayer,
|
|
101
|
+
after: "previewGhost"
|
|
102
|
+
},
|
|
85
103
|
dispatcherOverlay: {
|
|
86
104
|
layer: dispatcherOverlay,
|
|
87
|
-
after: "
|
|
105
|
+
after: "effectSources"
|
|
88
106
|
},
|
|
89
107
|
pathEditingOverlay: overlaySlot === null || isCustomEntry(overlaySlot) ? overlaySlot : {
|
|
90
108
|
layer: pathEditingOverlayLayer,
|
|
@@ -104,6 +122,7 @@ function useSceneCanvasLayers(args) {
|
|
|
104
122
|
selectionOverlayLayer,
|
|
105
123
|
departureLayer,
|
|
106
124
|
previewLayer,
|
|
125
|
+
effectSourcesLayer,
|
|
107
126
|
dispatcherOverlay,
|
|
108
127
|
pathEditingOverlayLayer,
|
|
109
128
|
overlaySlot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSceneCanvasLayers.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasLayers.ts"],"sourcesContent":["import { useMemo, useRef, useState, type MutableRefObject } from 'react';\nimport type { ColorOverrideRegistry } from '@weasel-js/animator';\nimport type { Dispatcher } from '@weasel-js/routing';\nimport type { Affordance } from 'affordances/types';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport type { PlaneMap } from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport type { PathEditState } from 'features/paths/pathEditState';\nimport { usePathEditOverlayLayer } from 'features/paths/usePathEdit';\nimport type { rotationBadgeOf } from 'features/selection/overlay';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport type { HierarchicalAdapter } from '../buildSceneTree';\nimport { builtLayersOf, isCustomEntry, type CanvasLayers } from '../layerSlots';\nimport { createSlopsDebugLayer } from '../slopsDebugLayer';\nimport { useTargetBasePx } from 'core/device/useTargetBasePx';\nimport { targetSizesPx } from 'core/device/targets';\nimport type { ResizeHandleLayout } from 'interactions/actions/resize/cornerHandles';\nimport { mergeLayersWithDefaults } from './mergeLayers';\nimport type { SceneCanvasLayers } from './props';\nimport { useDispatcherOverlayLayer } from './useDispatcherOverlayLayer';\nimport { usePreviewGhostLayer } from './usePreviewGhostLayer';\nimport { useDepartureGhostLayer } from './useDepartureGhostLayer';\nimport type { Departures } from '../../animation/departures';\nimport { usePoseTransition, type PoseTransitionSeat } from '../../animation/poseTransition';\nimport { useSceneSlotLayers } from './useSceneSlotLayers';\nimport { useSelectionOverlayLayer } from './useSelectionOverlayLayer';\nimport type { DrawnBoundsScene } from '../drawnBounds';\nimport { createSnapOutcomeStore, type SnapOutcomeStore } from 'features/snap/outcomeStore';\nimport { createSnapReadoutLayer, type SnapReadoutStyle } from 'features/snap/readoutLayer';\n\n/**\n * The layer map `<SceneCanvas>` hands `<Canvas>`: the caller's `layers` over\n * the kit defaults, with the scene and selection-overlay slots built, and the\n * canvas's own layers anchored around them. Removed nodes leave just above\n * the scene, the preview ghost above them, the dispatcher's overlay (marquee, lasso) above the ghost, and the\n * anchor overlay above the selection chrome.\n */\nexport function useSceneCanvasLayers<TData, TLayer extends string, TPose>(args: {\n /** `<SceneCanvas layers>`. Omitted, the result is the full default set. */\n layers: SceneCanvasLayers<Node<TData, TLayer, TPose>, TPose> | undefined;\n /** The device profile's, which sizes the default handles. */\n targetScale: number;\n scene: Scene<TData, TLayer, TPose>;\n adapter: HierarchicalAdapter<Node<TData, TLayer, TPose>, TPose>;\n poseDescriptor: PoseDescriptor<TPose>;\n alphaFor: ((id: string) => number) | undefined;\n colorOverrides: ColorOverrideRegistry | undefined;\n boundsOf: (id: string) => Bounds | null;\n planeOfNode: (id: string, view: View) => PlaneMap | null;\n /** `<SceneCanvas poseTransition>`, whose ghosts of removed nodes this draws. */\n poseTransition: PoseTransitionSeat<TPose> | null | undefined;\n /** Ids an in-flight gesture is ghosting. */\n previewIds: () => Iterable<string> | null;\n dispatcher: Dispatcher;\n /** Whether to mount the snap readout layer. */\n snapReadout: boolean;\n snapReadoutStyle?: SnapReadoutStyle;\n pathEditState: PathEditState;\n /** `debug.slops`: paint the hit regions of the chrome affordances. */\n slops: boolean;\n /** `geometry.boundsIncludeStroke`: whether chrome sits on the stroke. */\n boundsIncludeStroke: boolean;\n /** `selectTool`'s `handleHitRadius` and `resize.edgeHandles`, resolved here into\n * the one {@link ResizeHandleLayout} the overlay paints and the hit-test reads. */\n selectTool?: { handleHitRadius?: number; resize?: { edgeHandles?: boolean } };\n}): {\n layers: CanvasLayers;\n /** Where the selection overlay paints its rotate badge, or null. */\n rotationBadge: ReturnType<typeof rotationBadgeOf>;\n /** Which resize handles exist and their hit radius, for every hit-test of this canvas. */\n resizeHandles: ResizeHandleLayout;\n /** The affordances the gesture mounter hit-tests, which it publishes here\n * so the slops halos are the hit regions rather than a copy of them. */\n chromeAffordancesRef: MutableRefObject<readonly Affordance[]>;\n /** The marks the readout layer draws; the canvas's snap dep writes them. */\n snapStore: SnapOutcomeStore;\n /** The removed nodes the seat is seeing off. */\n departures: Departures<TPose, Node<TData, TLayer, TPose>>;\n} {\n const { scene, adapter, poseDescriptor, alphaFor, dispatcher, pathEditState, slops, targetScale } = args;\n\n const baseSizes = useTargetBasePx();\n const merged = useMemo(\n () => mergeLayersWithDefaults(args.layers, targetScale, baseSizes),\n [args.layers, targetScale, baseSizes],\n );\n\n const { config: sceneSlot, layers: sceneLayers } = useSceneSlotLayers({\n slot: merged.scene,\n scene,\n adapter,\n alphaFor,\n colorOverrides: args.colorOverrides,\n boundsOf: args.boundsOf,\n previewIds: args.previewIds,\n });\n // Takes the scene-wired slot, so a ghosted derived node still resolves its path.\n const previewLayer = usePreviewGhostLayer<TData, TLayer, TPose>({ scene, sceneSlot, dispatcher });\n const departures = usePoseTransition(scene, args.poseTransition);\n const departureLayer = useDepartureGhostLayer({ scene, sceneSlot, departures });\n const dispatcherOverlay = useDispatcherOverlayLayer({ dispatcher });\n\n const hitRadiusPx = args.selectTool?.handleHitRadius ?? targetSizesPx(targetScale, baseSizes).handle;\n const edges = args.selectTool?.resize?.edgeHandles ?? true;\n const resizeHandles = useMemo<ResizeHandleLayout>(() => ({ edges, hitRadiusPx }), [edges, hitRadiusPx]);\n\n const chromeAffordancesRef = useRef<readonly Affordance[]>([]);\n const slopsLayer = useMemo(\n () => createSlopsDebugLayer({ getAffordances: () => chromeAffordancesRef.current }),\n [],\n );\n\n const [snapStore] = useState(() => createSnapOutcomeStore());\n const snapReadoutLayer = useMemo(() => createSnapReadoutLayer(snapStore, args.snapReadoutStyle), [snapStore, args.snapReadoutStyle]);\n const overlaySlot = merged.pathEditingOverlay;\n const overlayConfig = overlaySlot && !isCustomEntry(overlaySlot) ? overlaySlot : undefined;\n const overlayAnchor = overlaySlot === null ? 'dispatcherOverlay' : 'pathEditingOverlay';\n const pathEditingOverlayLayer = usePathEditOverlayLayer(pathEditState, {\n nodeOf: (id) => scene.get(id as NodeId),\n planeOfNode: args.planeOfNode,\n }, overlayConfig);\n\n const { layer: selectionOverlayLayer, rotationBadge } = useSelectionOverlayLayer<TPose>(\n merged.selectionOverlay,\n pathEditState.getEditingIds,\n poseDescriptor,\n args.boundsIncludeStroke ? (scene as unknown as DrawnBoundsScene) : undefined,\n resizeHandles,\n );\n\n const layers = useMemo<CanvasLayers>(() => ({\n ...builtLayersOf(merged),\n scene: sceneLayers,\n selectionOverlay: selectionOverlayLayer ? { layer: selectionOverlayLayer } : null,\n departureGhost: { layer: departureLayer, after: 'scene' },\n previewGhost: { layer: previewLayer, after: 'departureGhost' },\n dispatcherOverlay: { layer: dispatcherOverlay, after: 'previewGhost' },\n pathEditingOverlay: overlaySlot === null || isCustomEntry(overlaySlot)\n ? overlaySlot\n : { layer: pathEditingOverlayLayer, after: 'selectionOverlay' },\n ...(args.snapReadout ? { snapReadout: { layer: snapReadoutLayer, after: overlayAnchor } } : {}),\n ...(slops ? { slopsDebug: { layer: slopsLayer, after: args.snapReadout ? 'snapReadout' : overlayAnchor } } : {}),\n }), [\n merged, sceneLayers, selectionOverlayLayer, departureLayer, previewLayer, dispatcherOverlay, pathEditingOverlayLayer, overlaySlot, overlayAnchor,\n snapReadoutLayer, args.snapReadout, slops, slopsLayer,\n ]);\n\n return { layers, rotationBadge, resizeHandles, chromeAffordancesRef, snapStore, departures };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,qBAA0D,MAyCxE;CACA,MAAM,EAAE,OAAO,SAAS,gBAAgB,UAAU,YAAY,eAAe,OAAO,gBAAgB;CAEpG,MAAM,YAAY,gBAAgB;CAClC,MAAM,SAAS,cACP,wBAAwB,KAAK,QAAQ,aAAa,SAAS,GACjE;EAAC,KAAK;EAAQ;EAAa;CAAS,CACtC;CAEA,MAAM,EAAE,QAAQ,WAAW,QAAQ,gBAAgB,mBAAmB;EACpE,MAAM,OAAO;EACb;EACA;EACA;EACA,gBAAgB,KAAK;EACrB,UAAU,KAAK;EACf,YAAY,KAAK;CACnB,CAAC;CAED,MAAM,eAAe,qBAA2C;EAAE;EAAO;EAAW;CAAW,CAAC;CAChG,MAAM,aAAa,kBAAkB,OAAO,KAAK,cAAc;CAC/D,MAAM,iBAAiB,uBAAuB;EAAE;EAAO;EAAW;CAAW,CAAC;CAC9E,MAAM,oBAAoB,0BAA0B,EAAE,WAAW,CAAC;CAElE,MAAM,cAAc,KAAK,YAAY,mBAAmB,cAAc,aAAa,SAAS,CAAC,CAAC;CAC9F,MAAM,QAAQ,KAAK,YAAY,QAAQ,eAAe;CACtD,MAAM,gBAAgB,eAAmC;EAAE;EAAO;CAAY,IAAI,CAAC,OAAO,WAAW,CAAC;CAEtG,MAAM,uBAAuB,OAA8B,CAAC,CAAC;CAC7D,MAAM,aAAa,cACX,sBAAsB,EAAE,sBAAsB,qBAAqB,QAAQ,CAAC,GAClF,CAAC,CACH;CAEA,MAAM,CAAC,aAAa,eAAe,uBAAuB,CAAC;CAC3D,MAAM,mBAAmB,cAAc,uBAAuB,WAAW,KAAK,gBAAgB,GAAG,CAAC,WAAW,KAAK,gBAAgB,CAAC;CACnI,MAAM,cAAc,OAAO;CAC3B,MAAM,gBAAgB,eAAe,CAAC,cAAc,WAAW,IAAI,cAAc;CACjF,MAAM,gBAAgB,gBAAgB,OAAO,sBAAsB;CACnE,MAAM,0BAA0B,wBAAwB,eAAe;EACrE,SAAS,OAAO,MAAM,IAAI,EAAY;EACtC,aAAa,KAAK;CACpB,GAAG,aAAa;CAEhB,MAAM,EAAE,OAAO,uBAAuB,kBAAkB,yBACtD,OAAO,kBACP,cAAc,eACd,gBACA,KAAK,sBAAuB,QAAwC,QACpE,aACF;CAmBA,OAAO;EAAE,QAjBM,eAA6B;GAC1C,GAAG,cAAc,MAAM;GACvB,OAAO;GACP,kBAAkB,wBAAwB,EAAE,OAAO,sBAAsB,IAAI;GAC7E,gBAAgB;IAAE,OAAO;IAAgB,OAAO;GAAQ;GACxD,cAAc;IAAE,OAAO;IAAc,OAAO;GAAiB;GAC7D,mBAAmB;IAAE,OAAO;IAAmB,OAAO;GAAe;GACrE,oBAAoB,gBAAgB,QAAQ,cAAc,WAAW,IACjE,cACA;IAAE,OAAO;IAAyB,OAAO;GAAmB;GAChE,GAAI,KAAK,cAAc,EAAE,aAAa;IAAE,OAAO;IAAkB,OAAO;GAAc,EAAE,IAAI,CAAC;GAC7F,GAAI,QAAQ,EAAE,YAAY;IAAE,OAAO;IAAY,OAAO,KAAK,cAAc,gBAAgB;GAAc,EAAE,IAAI,CAAC;EAChH,IAAI;GACF;GAAQ;GAAa;GAAuB;GAAgB;GAAc;GAAmB;GAAyB;GAAa;GACnI;GAAkB,KAAK;GAAa;GAAO;EAC7C,CAES;EAAQ;EAAe;EAAe;EAAsB;EAAW;CAAW;AAC7F"}
|
|
1
|
+
{"version":3,"file":"useSceneCanvasLayers.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasLayers.ts"],"sourcesContent":["import { useMemo, useRef, useState, type MutableRefObject } from 'react';\nimport type { ColorOverrideRegistry } from '@weasel-js/animator';\nimport type { Dispatcher } from '@weasel-js/routing';\nimport type { Affordance } from 'affordances/types';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport type { PlaneMap } from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport type { PathEditState } from 'features/paths/pathEditState';\nimport { usePathEditOverlayLayer } from 'features/paths/usePathEdit';\nimport type { rotationBadgeOf } from 'features/selection/overlay';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport type { HierarchicalAdapter } from '../buildSceneTree';\nimport { builtLayersOf, isCustomEntry, type CanvasLayers } from '../layerSlots';\nimport { createSlopsDebugLayer } from '../slopsDebugLayer';\nimport { useTargetBasePx } from 'core/device/useTargetBasePx';\nimport { targetSizesPx } from 'core/device/targets';\nimport type { ResizeHandleLayout } from 'interactions/actions/resize/cornerHandles';\nimport { mergeLayersWithDefaults } from './mergeLayers';\nimport type { SceneCanvasLayers } from './props';\nimport { useDispatcherOverlayLayer } from './useDispatcherOverlayLayer';\nimport { usePreviewGhostLayer } from './usePreviewGhostLayer';\nimport { useDepartureGhostLayer } from './useDepartureGhostLayer';\nimport { useEffectSourcesLayer } from 'features/pathEffects/useEffectSourcesLayer';\nimport type { Departures } from '../../animation/departures';\nimport { usePoseTransition, type PoseTransitionSeat } from '../../animation/poseTransition';\nimport { useSceneSlotLayers } from './useSceneSlotLayers';\nimport { useSelectionOverlayLayer } from './useSelectionOverlayLayer';\nimport { drawnBoundsScene } from '../derivedPath';\nimport { createSnapOutcomeStore, type SnapOutcomeStore } from 'features/snap/outcomeStore';\nimport { createSnapReadoutLayer } from 'features/snap/readoutLayer';\nimport type { SnapReadoutStyle } from 'features/snap/types';\n\n/**\n * The layer map `<SceneCanvas>` hands `<Canvas>`: the caller's `layers` over\n * the kit defaults, with the scene and selection-overlay slots built, and the\n * canvas's own layers anchored around them. Removed nodes leave just above\n * the scene, the preview ghost above them, a selected path effect's hidden sources above that, the dispatcher's\n * overlay (marquee, lasso) above those, and the\n * anchor overlay above the selection chrome.\n */\nexport function useSceneCanvasLayers<TData, TLayer extends string, TPose>(args: {\n /** `<SceneCanvas layers>`. Omitted, the result is the full default set. */\n layers: SceneCanvasLayers<Node<TData, TLayer, TPose>, TPose> | undefined;\n /** The device profile's, which sizes the default handles. */\n targetScale: number;\n scene: Scene<TData, TLayer, TPose>;\n adapter: HierarchicalAdapter<Node<TData, TLayer, TPose>, TPose>;\n poseDescriptor: PoseDescriptor<TPose>;\n alphaFor: ((id: string) => number) | undefined;\n colorOverrides: ColorOverrideRegistry | undefined;\n boundsOf: (id: string) => Bounds | null;\n planeOfNode: (id: string, view: View) => PlaneMap | null;\n /** `<SceneCanvas poseTransition>`, whose ghosts of removed nodes this draws. */\n poseTransition: PoseTransitionSeat<TPose> | null | undefined;\n /** Ids an in-flight gesture is ghosting. */\n previewIds: () => Iterable<string> | null;\n dispatcher: Dispatcher;\n /** Whether to mount the snap readout layer. */\n snapReadout: boolean;\n snapReadoutStyle?: SnapReadoutStyle;\n pathEditState: PathEditState;\n /** `debug.slops`: paint the hit regions of the chrome affordances. */\n slops: boolean;\n /** `geometry.boundsIncludeStroke`: whether chrome sits on the stroke. */\n boundsIncludeStroke: boolean;\n /** `selectTool`'s `handleHitRadius` and `resize.edgeHandles`, resolved here into\n * the one {@link ResizeHandleLayout} the overlay paints and the hit-test reads. */\n selectTool?: { handleHitRadius?: number; resize?: { edgeHandles?: boolean } };\n}): {\n layers: CanvasLayers;\n /** Where the selection overlay paints its rotate badge, or null. */\n rotationBadge: ReturnType<typeof rotationBadgeOf>;\n /** Which resize handles exist and their hit radius, for every hit-test of this canvas. */\n resizeHandles: ResizeHandleLayout;\n /** The affordances the gesture mounter hit-tests, which it publishes here\n * so the slops halos are the hit regions rather than a copy of them. */\n chromeAffordancesRef: MutableRefObject<readonly Affordance[]>;\n /** The marks the readout layer draws; the canvas's snap dep writes them. */\n snapStore: SnapOutcomeStore;\n /** The removed nodes the seat is seeing off. */\n departures: Departures<TPose, Node<TData, TLayer, TPose>>;\n} {\n const { scene, adapter, poseDescriptor, alphaFor, dispatcher, pathEditState, slops, targetScale } = args;\n\n const baseSizes = useTargetBasePx();\n const merged = useMemo(\n () => mergeLayersWithDefaults(args.layers, targetScale, baseSizes),\n [args.layers, targetScale, baseSizes],\n );\n\n const { config: sceneSlot, layers: sceneLayers } = useSceneSlotLayers({\n slot: merged.scene,\n scene,\n adapter,\n alphaFor,\n colorOverrides: args.colorOverrides,\n boundsOf: args.boundsOf,\n previewIds: args.previewIds,\n });\n // Takes the scene-wired slot, so a ghosted derived node still resolves its path.\n const previewLayer = usePreviewGhostLayer<TData, TLayer, TPose>({ scene, sceneSlot, dispatcher });\n const departures = usePoseTransition(scene, args.poseTransition);\n const departureLayer = useDepartureGhostLayer({ scene, sceneSlot, departures });\n const effectSourcesLayer = useEffectSourcesLayer(scene);\n const dispatcherOverlay = useDispatcherOverlayLayer({ dispatcher });\n\n const hitRadiusPx = args.selectTool?.handleHitRadius ?? targetSizesPx(targetScale, baseSizes).handle;\n const edges = args.selectTool?.resize?.edgeHandles ?? true;\n const resizeHandles = useMemo<ResizeHandleLayout>(() => ({ edges, hitRadiusPx }), [edges, hitRadiusPx]);\n\n const chromeAffordancesRef = useRef<readonly Affordance[]>([]);\n const slopsLayer = useMemo(\n () => createSlopsDebugLayer({ getAffordances: () => chromeAffordancesRef.current }),\n [],\n );\n\n const [snapStore] = useState(() => createSnapOutcomeStore());\n // Keyed on the style's values, so an inline `readoutStyle` literal keeps the layer.\n const { color, gapColor, lineWidth } = args.snapReadoutStyle ?? {};\n const snapReadoutLayer = useMemo(() => createSnapReadoutLayer(snapStore, {\n ...(color !== undefined ? { color } : {}),\n ...(gapColor !== undefined ? { gapColor } : {}),\n ...(lineWidth !== undefined ? { lineWidth } : {}),\n }), [snapStore, color, gapColor, lineWidth]);\n const overlaySlot = merged.pathEditingOverlay;\n const overlayConfig = overlaySlot && !isCustomEntry(overlaySlot) ? overlaySlot : undefined;\n const overlayAnchor = overlaySlot === null ? 'dispatcherOverlay' : 'pathEditingOverlay';\n const pathEditingOverlayLayer = usePathEditOverlayLayer(pathEditState, {\n nodeOf: (id) => scene.get(id as NodeId),\n planeOfNode: args.planeOfNode,\n }, overlayConfig);\n\n const { layer: selectionOverlayLayer, rotationBadge } = useSelectionOverlayLayer<TPose>(\n merged.selectionOverlay,\n pathEditState.getEditingIds,\n poseDescriptor,\n args.boundsIncludeStroke ? drawnBoundsScene(scene) : undefined,\n resizeHandles,\n );\n\n const layers = useMemo<CanvasLayers>(() => ({\n ...builtLayersOf(merged),\n scene: sceneLayers,\n selectionOverlay: selectionOverlayLayer ? { layer: selectionOverlayLayer } : null,\n departureGhost: { layer: departureLayer, after: 'scene' },\n previewGhost: { layer: previewLayer, after: 'departureGhost' },\n effectSources: { layer: effectSourcesLayer, after: 'previewGhost' },\n dispatcherOverlay: { layer: dispatcherOverlay, after: 'effectSources' },\n pathEditingOverlay: overlaySlot === null || isCustomEntry(overlaySlot)\n ? overlaySlot\n : { layer: pathEditingOverlayLayer, after: 'selectionOverlay' },\n ...(args.snapReadout ? { snapReadout: { layer: snapReadoutLayer, after: overlayAnchor } } : {}),\n ...(slops ? { slopsDebug: { layer: slopsLayer, after: args.snapReadout ? 'snapReadout' : overlayAnchor } } : {}),\n }), [\n merged, sceneLayers, selectionOverlayLayer, departureLayer, previewLayer, effectSourcesLayer, dispatcherOverlay, pathEditingOverlayLayer, overlaySlot, overlayAnchor,\n snapReadoutLayer, args.snapReadout, slops, slopsLayer,\n ]);\n\n return { layers, rotationBadge, resizeHandles, chromeAffordancesRef, snapStore, departures };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,qBAA0D,MAyCxE;CACA,MAAM,EAAE,OAAO,SAAS,gBAAgB,UAAU,YAAY,eAAe,OAAO,gBAAgB;CAEpG,MAAM,YAAY,gBAAgB;CAClC,MAAM,SAAS,cACP,wBAAwB,KAAK,QAAQ,aAAa,SAAS,GACjE;EAAC,KAAK;EAAQ;EAAa;CAAS,CACtC;CAEA,MAAM,EAAE,QAAQ,WAAW,QAAQ,gBAAgB,mBAAmB;EACpE,MAAM,OAAO;EACb;EACA;EACA;EACA,gBAAgB,KAAK;EACrB,UAAU,KAAK;EACf,YAAY,KAAK;CACnB,CAAC;CAED,MAAM,eAAe,qBAA2C;EAAE;EAAO;EAAW;CAAW,CAAC;CAChG,MAAM,aAAa,kBAAkB,OAAO,KAAK,cAAc;CAC/D,MAAM,iBAAiB,uBAAuB;EAAE;EAAO;EAAW;CAAW,CAAC;CAC9E,MAAM,qBAAqB,sBAAsB,KAAK;CACtD,MAAM,oBAAoB,0BAA0B,EAAE,WAAW,CAAC;CAElE,MAAM,cAAc,KAAK,YAAY,mBAAmB,cAAc,aAAa,SAAS,CAAC,CAAC;CAC9F,MAAM,QAAQ,KAAK,YAAY,QAAQ,eAAe;CACtD,MAAM,gBAAgB,eAAmC;EAAE;EAAO;CAAY,IAAI,CAAC,OAAO,WAAW,CAAC;CAEtG,MAAM,uBAAuB,OAA8B,CAAC,CAAC;CAC7D,MAAM,aAAa,cACX,sBAAsB,EAAE,sBAAsB,qBAAqB,QAAQ,CAAC,GAClF,CAAC,CACH;CAEA,MAAM,CAAC,aAAa,eAAe,uBAAuB,CAAC;CAE3D,MAAM,EAAE,OAAO,UAAU,cAAc,KAAK,oBAAoB,CAAC;CACjE,MAAM,mBAAmB,cAAc,uBAAuB,WAAW;EACvE,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;CACjD,CAAC,GAAG;EAAC;EAAW;EAAO;EAAU;CAAS,CAAC;CAC3C,MAAM,cAAc,OAAO;CAC3B,MAAM,gBAAgB,eAAe,CAAC,cAAc,WAAW,IAAI,cAAc;CACjF,MAAM,gBAAgB,gBAAgB,OAAO,sBAAsB;CACnE,MAAM,0BAA0B,wBAAwB,eAAe;EACrE,SAAS,OAAO,MAAM,IAAI,EAAY;EACtC,aAAa,KAAK;CACpB,GAAG,aAAa;CAEhB,MAAM,EAAE,OAAO,uBAAuB,kBAAkB,yBACtD,OAAO,kBACP,cAAc,eACd,gBACA,KAAK,sBAAsB,iBAAiB,KAAK,IAAI,QACrD,aACF;CAoBA,OAAO;EAAE,QAlBM,eAA6B;GAC1C,GAAG,cAAc,MAAM;GACvB,OAAO;GACP,kBAAkB,wBAAwB,EAAE,OAAO,sBAAsB,IAAI;GAC7E,gBAAgB;IAAE,OAAO;IAAgB,OAAO;GAAQ;GACxD,cAAc;IAAE,OAAO;IAAc,OAAO;GAAiB;GAC7D,eAAe;IAAE,OAAO;IAAoB,OAAO;GAAe;GAClE,mBAAmB;IAAE,OAAO;IAAmB,OAAO;GAAgB;GACtE,oBAAoB,gBAAgB,QAAQ,cAAc,WAAW,IACjE,cACA;IAAE,OAAO;IAAyB,OAAO;GAAmB;GAChE,GAAI,KAAK,cAAc,EAAE,aAAa;IAAE,OAAO;IAAkB,OAAO;GAAc,EAAE,IAAI,CAAC;GAC7F,GAAI,QAAQ,EAAE,YAAY;IAAE,OAAO;IAAY,OAAO,KAAK,cAAc,gBAAgB;GAAc,EAAE,IAAI,CAAC;EAChH,IAAI;GACF;GAAQ;GAAa;GAAuB;GAAgB;GAAc;GAAoB;GAAmB;GAAyB;GAAa;GACvJ;GAAkB,KAAK;GAAa;GAAO;EAC7C,CAES;EAAQ;EAAe;EAAe;EAAsB;EAAW;CAAW;AAC7F"}
|
|
@@ -3,17 +3,16 @@ import { useCanvasTools, useFeatureBindings } from "./useCanvasTools.js";
|
|
|
3
3
|
//#region src/canvas/SceneCanvas/useSceneCanvasTools.ts
|
|
4
4
|
/** The canvas's tools, and the contributions and standard actions its presets bring. */
|
|
5
5
|
function useSceneCanvasTools(args) {
|
|
6
|
-
const { props, select,
|
|
6
|
+
const { props, select, enabled } = args;
|
|
7
7
|
const { tools, internal, takeover } = useCanvasTools({
|
|
8
8
|
select,
|
|
9
|
-
scene,
|
|
10
|
-
selection,
|
|
11
9
|
enabled,
|
|
12
10
|
tools: props.tools,
|
|
13
11
|
defaultTools: props.defaultTools,
|
|
14
12
|
toolOptions: props.toolOptions,
|
|
15
13
|
inertia: props.viewport?.inertia,
|
|
16
14
|
ambient: props.ambient,
|
|
15
|
+
actions: props.actions,
|
|
17
16
|
pressFeedback: props.longPress?.feedback,
|
|
18
17
|
initialActiveTool: props.initialActiveTool,
|
|
19
18
|
modes: props.modes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSceneCanvasTools.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasTools.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"useSceneCanvasTools.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneCanvasTools.ts"],"sourcesContent":["import type { Tool } from '../../tools/overlayBinding';\nimport type { EnabledPresets, FeatureBindingOptions, PresetSource } from './features';\nimport type { SceneCanvasProps } from './props';\nimport { useCanvasTools, useFeatureBindings } from './useCanvasTools';\n\ntype Props = SceneCanvasProps<unknown, string, unknown>;\n\n/** The `<SceneCanvas>` props its tools and preset bindings read. */\nexport type SceneCanvasToolProps = Pick<\n Props,\n | 'tools' | 'defaultTools' | 'toolOptions' | 'viewport' | 'ambient' | 'longPress'\n | 'initialActiveTool' | 'modes' | 'onToolsCreated' | 'selectTool' | 'actions'\n>;\n\n/** The canvas's tools, and the contributions and standard actions its presets bring. */\nexport function useSceneCanvasTools(args: {\n props: SceneCanvasToolProps;\n select: Tool;\n /** The select tool's move options, which the selection's `move` binding takes. */\n move: unknown;\n enabled: EnabledPresets;\n presetSource: PresetSource;\n}) {\n const { props, select, enabled } = args;\n const { tools, internal, takeover } = useCanvasTools({\n select,\n enabled,\n tools: props.tools,\n defaultTools: props.defaultTools,\n toolOptions: props.toolOptions,\n inertia: props.viewport?.inertia,\n ambient: props.ambient,\n actions: props.actions,\n pressFeedback: props.longPress?.feedback,\n initialActiveTool: props.initialActiveTool,\n modes: props.modes,\n onToolsCreated: props.onToolsCreated,\n });\n const { contributions, standardActions } = useFeatureBindings({\n enabled, pool: args.presetSource.pool,\n tools,\n move: args.move as FeatureBindingOptions['move'],\n rotate: (props.selectTool?.rotate || undefined) as FeatureBindingOptions['rotate'],\n });\n return { tools, internal, takeover, contributions, standardActions };\n}\n"],"mappings":";;;;AAeA,SAAgB,oBAAoB,MAOjC;CACD,MAAM,EAAE,OAAO,QAAQ,YAAY;CACnC,MAAM,EAAE,OAAO,UAAU,aAAa,eAAe;EACnD;EACA;EACA,OAAO,MAAM;EACb,cAAc,MAAM;EACpB,aAAa,MAAM;EACnB,SAAS,MAAM,UAAU;EACzB,SAAS,MAAM;EACf,SAAS,MAAM;EACf,eAAe,MAAM,WAAW;EAChC,mBAAmB,MAAM;EACzB,OAAO,MAAM;EACb,gBAAgB,MAAM;CACxB,CAAC;CACD,MAAM,EAAE,eAAe,oBAAoB,mBAAmB;EAC5D;EAAS,MAAM,KAAK,aAAa;EACjC;EACA,MAAM,KAAK;EACX,QAAS,MAAM,YAAY,UAAU;CACvC,CAAC;CACD,OAAO;EAAE;EAAO;EAAU;EAAU;EAAe;CAAgB;AACrE"}
|
|
@@ -16,7 +16,7 @@ import { useLatest } from "@weasel-js/react";
|
|
|
16
16
|
* pointer to capture, so whichever view is under the cursor owns the point.
|
|
17
17
|
*/
|
|
18
18
|
function useSceneHover(args) {
|
|
19
|
-
const { canvasApiRef, viewRef, nodeAtPointRef, enabled } = args;
|
|
19
|
+
const { canvasApiRef, viewRef, nodeAtPointRef, enabled, onChange } = args;
|
|
20
20
|
const surfaceViewRegistry = useOptionalViewRegistry();
|
|
21
21
|
return useHoverTracking({
|
|
22
22
|
nodeAtClientPoint: (clientX, clientY) => {
|
|
@@ -32,7 +32,8 @@ function useSceneHover(args) {
|
|
|
32
32
|
} : view);
|
|
33
33
|
return hit ? { id: hit.id } : null;
|
|
34
34
|
},
|
|
35
|
-
enabled
|
|
35
|
+
enabled,
|
|
36
|
+
...onChange ? { onChange } : {}
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
/**
|
|
@@ -42,17 +43,16 @@ function useSceneHover(args) {
|
|
|
42
43
|
* An unselectable canvas hides the marquee and lasso by default: every
|
|
43
44
|
* selection write no-ops there, so the select tool's empty-drag binding still
|
|
44
45
|
* claims the gesture, keeping it from falling through to an ambient drag such
|
|
45
|
-
* as insert, but paints nothing.
|
|
46
|
+
* as insert, but paints nothing.
|
|
46
47
|
*/
|
|
47
48
|
function useChromeRules(args) {
|
|
48
|
-
const { enabled, selectable,
|
|
49
|
+
const { enabled, selectable, chromeVisibility } = args;
|
|
49
50
|
return useMemo(() => {
|
|
50
51
|
const defaults = presetChromeRules(enabled, PRESET_OWNED_CHROME);
|
|
51
52
|
if (!selectable) {
|
|
52
53
|
defaults["action.marquee"] = never;
|
|
53
54
|
defaults["action.lasso"] = never;
|
|
54
55
|
}
|
|
55
|
-
if (rotateOff) defaults["selection.rotation-handle"] = never;
|
|
56
56
|
return {
|
|
57
57
|
...defaults,
|
|
58
58
|
...chromeVisibility
|
|
@@ -60,7 +60,6 @@ function useChromeRules(args) {
|
|
|
60
60
|
}, [
|
|
61
61
|
chromeVisibility,
|
|
62
62
|
selectable,
|
|
63
|
-
rotateOff,
|
|
64
63
|
enabled
|
|
65
64
|
]);
|
|
66
65
|
}
|
|
@@ -93,7 +92,7 @@ function useSceneCanvasChrome(args) {
|
|
|
93
92
|
const { getHover, canvasRef: trackHoverOn } = useSceneHover({
|
|
94
93
|
...args.hover,
|
|
95
94
|
viewRef,
|
|
96
|
-
enabled: rules.chromeVisibility !== void 0
|
|
95
|
+
enabled: rules.chromeVisibility !== void 0 || args.hover.onChange !== void 0
|
|
97
96
|
});
|
|
98
97
|
return {
|
|
99
98
|
...useSurfaceChromeCaps({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSceneChrome.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneChrome.ts"],"sourcesContent":["import { useCallback, useMemo, type RefObject } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { Dispatcher, RuleCtx } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport type { View } from 'core/viewport/view';\nimport { never, useHoverTracking, type HoverTracking, type VisibilityRules } from 'features/chrome-caps';\nimport {\n useChromeCaps,\n type ChromeCaps,\n type ChromeCapsSource,\n type ViewRuleInputs,\n} from 'features/chrome-caps/useChromeCaps';\nimport type { CanvasExtensionApi } from '../canvasExtension';\nimport { useOptionalViewRegistry } from '../viewRegistry';\nimport { presetChromeRules, type EnabledPresets } from './features';\nimport { PRESET_OWNED_CHROME } from './presets/chrome';\nimport type { NodeAtPoint } from './useNodeAtPoint';\nimport { worldPointAt } from './worldPointAt';\n\n/**\n * The node under the pointer, for `RuleCtx.hover`. One lookup, not a\n * client-to-world thunk beside a picker: the point and the camera its\n * tolerance converts against have to come from the same view. Hover has no\n * pointer to capture, so whichever view is under the cursor owns the point.\n */\nexport function useSceneHover(args: {\n canvasApiRef: RefObject<Pick<CanvasExtensionApi, 'clientToWorld'> | null>;\n /** The surface's own camera, for a point no declared view claims. */\n viewRef: { readonly current: View };\n nodeAtPointRef: { readonly current: NodeAtPoint | undefined };\n enabled: boolean;\n}): HoverTracking {\n const { canvasApiRef, viewRef, nodeAtPointRef, enabled } = args;\n const surfaceViewRegistry = useOptionalViewRegistry();\n return useHoverTracking({\n nodeAtClientPoint: (clientX, clientY) => {\n const api = canvasApiRef.current;\n if (!api) return null;\n const target = surfaceViewRegistry?.resolver.at(null, clientX, clientY);\n const view = target?.view ?? viewRef.current;\n const [x, y] = worldPointAt(api, target, clientX, clientY);\n // A view judges its own layers; the surface's gate is the picker's default.\n const reg = target?.id != null\n ? surfaceViewRegistry?.list().find((r) => r.id === target.id)\n : undefined;\n const hit = nodeAtPointRef.current?.(\n x, y, reg ? { scale: view.scale, layerIsPainted: reg.layerIsPainted } : view,\n );\n return hit ? { id: hit.id as NodeId } : null;\n },\n enabled,\n });\n}\n\n/**\n * The surface's chrome-visibility rules: the presets' defaults under the\n * consumer's `chromeVisibility`, which wins.\n *\n * An unselectable canvas hides the marquee and lasso by default: every\n * selection write no-ops there, so the select tool's empty-drag binding still\n * claims the gesture, keeping it from falling through to an ambient drag such\n * as insert, but paints nothing
|
|
1
|
+
{"version":3,"file":"useSceneChrome.js","names":[],"sources":["../../../src/canvas/SceneCanvas/useSceneChrome.ts"],"sourcesContent":["import { useCallback, useMemo, type RefObject } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { Dispatcher, RuleCtx } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport type { View } from 'core/viewport/view';\nimport { never, useHoverTracking, type HoverTracking, type VisibilityRules } from 'features/chrome-caps';\nimport {\n useChromeCaps,\n type ChromeCaps,\n type ChromeCapsSource,\n type ViewRuleInputs,\n} from 'features/chrome-caps/useChromeCaps';\nimport type { CanvasExtensionApi } from '../canvasExtension';\nimport { useOptionalViewRegistry } from '../viewRegistry';\nimport { presetChromeRules, type EnabledPresets } from './features';\nimport { PRESET_OWNED_CHROME } from './presets/chrome';\nimport type { NodeAtPoint } from './useNodeAtPoint';\nimport { worldPointAt } from './worldPointAt';\n\n/**\n * The node under the pointer, for `RuleCtx.hover`. One lookup, not a\n * client-to-world thunk beside a picker: the point and the camera its\n * tolerance converts against have to come from the same view. Hover has no\n * pointer to capture, so whichever view is under the cursor owns the point.\n */\nexport function useSceneHover(args: {\n canvasApiRef: RefObject<Pick<CanvasExtensionApi, 'clientToWorld'> | null>;\n /** The surface's own camera, for a point no declared view claims. */\n viewRef: { readonly current: View };\n nodeAtPointRef: { readonly current: NodeAtPoint | undefined };\n enabled: boolean;\n onChange?: (id: NodeId | null) => void;\n}): HoverTracking {\n const { canvasApiRef, viewRef, nodeAtPointRef, enabled, onChange } = args;\n const surfaceViewRegistry = useOptionalViewRegistry();\n return useHoverTracking({\n nodeAtClientPoint: (clientX, clientY) => {\n const api = canvasApiRef.current;\n if (!api) return null;\n const target = surfaceViewRegistry?.resolver.at(null, clientX, clientY);\n const view = target?.view ?? viewRef.current;\n const [x, y] = worldPointAt(api, target, clientX, clientY);\n // A view judges its own layers; the surface's gate is the picker's default.\n const reg = target?.id != null\n ? surfaceViewRegistry?.list().find((r) => r.id === target.id)\n : undefined;\n const hit = nodeAtPointRef.current?.(\n x, y, reg ? { scale: view.scale, layerIsPainted: reg.layerIsPainted } : view,\n );\n return hit ? { id: hit.id as NodeId } : null;\n },\n enabled,\n ...(onChange ? { onChange } : {}),\n });\n}\n\n/**\n * The surface's chrome-visibility rules: the presets' defaults under the\n * consumer's `chromeVisibility`, which wins.\n *\n * An unselectable canvas hides the marquee and lasso by default: every\n * selection write no-ops there, so the select tool's empty-drag binding still\n * claims the gesture, keeping it from falling through to an ambient drag such\n * as insert, but paints nothing.\n */\nexport function useChromeRules(args: {\n enabled: EnabledPresets;\n selectable: boolean;\n chromeVisibility: VisibilityRules | undefined;\n}): VisibilityRules {\n const { enabled, selectable, chromeVisibility } = args;\n return useMemo(() => {\n const defaults = presetChromeRules(enabled, PRESET_OWNED_CHROME);\n if (!selectable) {\n defaults['action.marquee'] = never;\n defaults['action.lasso'] = never;\n }\n return { ...defaults, ...chromeVisibility };\n }, [chromeVisibility, selectable, enabled]);\n}\n\n/** The chrome-caps answers for the surface's own view. */\nexport function useSurfaceChromeCaps(args: {\n source: ChromeCapsSource;\n /** The selection as rendered. `SelectionApi.current` can be a live getter\n * that runs ahead of the commit the painted chrome was built from. */\n selection: readonly NodeId[];\n viewRef: { readonly current: View };\n dispatcher: Pick<Dispatcher, 'getActiveAction'>;\n}): {\n chromeCaps: ChromeCaps;\n getIsVisible: () => (id: string) => boolean;\n getRuleCtx: () => RuleCtx | undefined;\n} {\n const { viewRef, dispatcher } = args;\n const chromeCaps = useChromeCaps(args.source);\n const committedSelectionRef = useLatest(args.selection);\n const currentRuleInputs = useCallback((): ViewRuleInputs => ({\n selection: committedSelectionRef.current,\n view: viewRef.current,\n action: dispatcher.getActiveAction(),\n }), [dispatcher, committedSelectionRef, viewRef]);\n const getIsVisible = useCallback(\n (): ((id: string) => boolean) => chromeCaps.isVisible(currentRuleInputs()),\n [chromeCaps, currentRuleInputs],\n );\n const getRuleCtx = useCallback(\n () => chromeCaps.ruleCtx(currentRuleInputs()),\n [chromeCaps, currentRuleInputs],\n );\n return { chromeCaps, getIsVisible, getRuleCtx };\n}\n\n/**\n * The surface's chrome: hover tracking, the visibility rules, and the chrome-caps answers they\n * feed. `source` is the chrome-caps source minus the parts built here.\n */\nexport function useSceneCanvasChrome(args: {\n source: Omit<ChromeCapsSource, 'rules' | 'getHover'>;\n rules: Parameters<typeof useChromeRules>[0];\n hover: Omit<Parameters<typeof useSceneHover>[0], 'enabled' | 'viewRef'>;\n selection: readonly NodeId[];\n viewRef: { readonly current: View };\n dispatcher: Pick<Dispatcher, 'getActiveAction'>;\n}) {\n const { rules, viewRef } = args;\n const { getHover, canvasRef: trackHoverOn } = useSceneHover({\n ...args.hover, viewRef, enabled: rules.chromeVisibility !== undefined || args.hover.onChange !== undefined,\n });\n const chromeRules = useChromeRules(rules);\n const caps = useSurfaceChromeCaps({\n source: { rules: chromeRules, getHover, ...args.source },\n selection: args.selection,\n viewRef,\n dispatcher: args.dispatcher,\n });\n return { ...caps, trackHoverOn };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAyBA,SAAgB,cAAc,MAOZ;CAChB,MAAM,EAAE,cAAc,SAAS,gBAAgB,SAAS,aAAa;CACrE,MAAM,sBAAsB,wBAAwB;CACpD,OAAO,iBAAiB;EACtB,oBAAoB,SAAS,YAAY;GACvC,MAAM,MAAM,aAAa;GACzB,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,SAAS,qBAAqB,SAAS,GAAG,MAAM,SAAS,OAAO;GACtE,MAAM,OAAO,QAAQ,QAAQ,QAAQ;GACrC,MAAM,CAAC,GAAG,KAAK,aAAa,KAAK,QAAQ,SAAS,OAAO;GAEzD,MAAM,MAAM,QAAQ,MAAM,OACtB,qBAAqB,KAAK,CAAC,CAAC,MAAM,MAAM,EAAE,OAAO,OAAO,EAAE,IAC1D;GACJ,MAAM,MAAM,eAAe,UACzB,GAAG,GAAG,MAAM;IAAE,OAAO,KAAK;IAAO,gBAAgB,IAAI;GAAe,IAAI,IAC1E;GACA,OAAO,MAAM,EAAE,IAAI,IAAI,GAAa,IAAI;EAC1C;EACA;EACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;CACjC,CAAC;AACH;;;;;;;;;;AAWA,SAAgB,eAAe,MAIX;CAClB,MAAM,EAAE,SAAS,YAAY,qBAAqB;CAClD,OAAO,cAAc;EACnB,MAAM,WAAW,kBAAkB,SAAS,mBAAmB;EAC/D,IAAI,CAAC,YAAY;GACf,SAAS,oBAAoB;GAC7B,SAAS,kBAAkB;EAC7B;EACA,OAAO;GAAE,GAAG;GAAU,GAAG;EAAiB;CAC5C,GAAG;EAAC;EAAkB;EAAY;CAAO,CAAC;AAC5C;;AAGA,SAAgB,qBAAqB,MAWnC;CACA,MAAM,EAAE,SAAS,eAAe;CAChC,MAAM,aAAa,cAAc,KAAK,MAAM;CAC5C,MAAM,wBAAwB,UAAU,KAAK,SAAS;CACtD,MAAM,oBAAoB,mBAAmC;EAC3D,WAAW,sBAAsB;EACjC,MAAM,QAAQ;EACd,QAAQ,WAAW,gBAAgB;CACrC,IAAI;EAAC;EAAY;EAAuB;CAAO,CAAC;CAShD,OAAO;EAAE;EAAY,cARA,kBACc,WAAW,UAAU,kBAAkB,CAAC,GACzE,CAAC,YAAY,iBAAiB,CAMX;EAAc,YAJhB,kBACX,WAAW,QAAQ,kBAAkB,CAAC,GAC5C,CAAC,YAAY,iBAAiB,CAEG;CAAW;AAChD;;;;;AAMA,SAAgB,qBAAqB,MAOlC;CACD,MAAM,EAAE,OAAO,YAAY;CAC3B,MAAM,EAAE,UAAU,WAAW,iBAAiB,cAAc;EAC1D,GAAG,KAAK;EAAO;EAAS,SAAS,MAAM,qBAAqB,UAAa,KAAK,MAAM,aAAa;CACnG,CAAC;CAQD,OAAO;EAAE,GANI,qBAAqB;GAChC,QAAQ;IAAE,OAFQ,eAAe,KAEhB;IAAa;IAAU,GAAG,KAAK;GAAO;GACvD,WAAW,KAAK;GAChB;GACA,YAAY,KAAK;EACnB,CACY;EAAM;CAAa;AACjC"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { EMPTY_CHROME_STATE } from "../../core/selection/chromeState.js";
|
|
2
|
-
import { useDispatchDepSources } from "../deps/dispatchSources.js";
|
|
3
2
|
import { anchorStateFrom, buildAffordanceAt, buildClassifyTarget, layerAffordance } from "../affordanceAt.js";
|
|
4
|
-
import { pathFromPlane } from "../planeClips.js";
|
|
5
3
|
import { useOptionalViewRegistry } from "../viewRegistry.js";
|
|
4
|
+
import { useDispatchDepSources } from "../deps/dispatchSources.js";
|
|
5
|
+
import { pathFromPlane } from "../planeClips.js";
|
|
6
|
+
import { VIEW_MARKER_ENTRY_ID } from "../../features/viewports/viewMarkerDrag.js";
|
|
6
7
|
import { useKitSettingsDepSource } from "../deps/kitSettings.js";
|
|
7
8
|
import { useChromeAffordances } from "./useChromeAffordances.js";
|
|
8
9
|
import { useSurfaceRouting } from "./useSurfaceRouting.js";
|
|
9
10
|
import { traceConversion } from "./coordTrace.js";
|
|
10
|
-
import { useCallback, useInsertionEffect, useMemo, useState } from "react";
|
|
11
|
+
import { useCallback, useEffect, useInsertionEffect, useMemo, useState } from "react";
|
|
11
12
|
import { useLatest } from "@weasel-js/react";
|
|
12
13
|
import { createLongPressStore } from "@weasel-js/routing";
|
|
13
14
|
import { useActionsRegistry, useDepRegistry, useGestureDispatcher } from "@weasel-js/routing/react";
|
|
@@ -57,9 +58,22 @@ function useAffordanceAt(inputs, depRegistry, viewRegistry) {
|
|
|
57
58
|
return (worldPoint) => {
|
|
58
59
|
const extra = canvasApiRef.current?.hitTestExtras?.(worldPoint.x, worldPoint.y);
|
|
59
60
|
if (extra) return layerAffordance(extra.layerId, extra.hit);
|
|
61
|
+
const marker = viewRegistry?.markerAt(null, worldPoint);
|
|
62
|
+
if (marker) return marker;
|
|
60
63
|
return affordanceAt ? affordanceAt(worldPoint) : null;
|
|
61
64
|
};
|
|
62
|
-
}, [
|
|
65
|
+
}, [
|
|
66
|
+
affordanceAt,
|
|
67
|
+
canvasApiRef,
|
|
68
|
+
viewRegistry
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
/** Markers take presses only while the routed tools carry the marker drag:
|
|
72
|
+
* `actions={null}` and a tools takeover both leave it out. */
|
|
73
|
+
function useMarkerGate(viewRegistry, ambient) {
|
|
74
|
+
const installed = ambient.some((entry) => entry.id === VIEW_MARKER_ENTRY_ID);
|
|
75
|
+
const installedRef = useLatest(installed);
|
|
76
|
+
useEffect(() => viewRegistry?.gateMarkers(() => installedRef.current), [viewRegistry, installedRef]);
|
|
63
77
|
}
|
|
64
78
|
/** Which body a world point lands on, its selection state, and its routing kind. */
|
|
65
79
|
function useClassifyTarget(inputs, kindOfNodeRef) {
|
|
@@ -86,7 +100,7 @@ function useClassifyTarget(inputs, kindOfNodeRef) {
|
|
|
86
100
|
}
|
|
87
101
|
/** Runs this canvas's gesture dispatcher over its tools, contributions, and chrome. */
|
|
88
102
|
function useSceneGestureDispatcher(inputs) {
|
|
89
|
-
const { canvasRef, canvasApiRef, tools, contributions, enabled, keyboard, claimKeys, viewRef, kindOfNode, dispatcher, getRuleCtx, onDoubleClick, onClick, longPress: { duration: longPressDuration, haptics: longPressHaptics } = {} } = inputs;
|
|
103
|
+
const { canvasRef, canvasApiRef, tools, contributions, enabled, keyboard, claimKeys, viewRef, kindOfNode, dispatcher, traces, getRuleCtx, onDoubleClick, onClick, longPress: { duration: longPressDuration, haptics: longPressHaptics } = {} } = inputs;
|
|
90
104
|
const registry = useActionsRegistry();
|
|
91
105
|
const depRegistry = useDepRegistry();
|
|
92
106
|
const viewRegistry = useOptionalViewRegistry();
|
|
@@ -102,6 +116,7 @@ function useSceneGestureDispatcher(inputs) {
|
|
|
102
116
|
contributions
|
|
103
117
|
]);
|
|
104
118
|
const kindOfNodeRef = useLatest(kindOfNode);
|
|
119
|
+
useMarkerGate(viewRegistry, tools.ambient);
|
|
105
120
|
const affordanceWithLayers = useAffordanceAt(inputs, depRegistry, viewRegistry);
|
|
106
121
|
const classifyTarget = useClassifyTarget(inputs, kindOfNodeRef);
|
|
107
122
|
const clientToWorld = useCallback((clientX, clientY) => {
|
|
@@ -111,12 +126,13 @@ function useSceneGestureDispatcher(inputs) {
|
|
|
111
126
|
x,
|
|
112
127
|
y
|
|
113
128
|
};
|
|
114
|
-
traceConversion(clientX, clientY, api ? canvasRef.current : null, viewRef?.current, world);
|
|
129
|
+
traceConversion(traces.coords, clientX, clientY, api ? canvasRef.current : null, viewRef?.current, world);
|
|
115
130
|
return world;
|
|
116
131
|
}, [
|
|
117
132
|
canvasRef,
|
|
118
133
|
canvasApiRef,
|
|
119
|
-
viewRef
|
|
134
|
+
viewRef,
|
|
135
|
+
traces.coords
|
|
120
136
|
]);
|
|
121
137
|
const requestRedraw = useCallback(() => {
|
|
122
138
|
canvasApiRef.current?.requestRedraw?.();
|
|
@@ -144,6 +160,7 @@ function useSceneGestureDispatcher(inputs) {
|
|
|
144
160
|
affordanceAt: affordanceWithLayers,
|
|
145
161
|
classifyTarget,
|
|
146
162
|
dispatcher,
|
|
163
|
+
trace: traces.dispatch,
|
|
147
164
|
clientToWorld,
|
|
148
165
|
requestRedraw,
|
|
149
166
|
paintedCursor,
|