@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
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { serialize } from "./serialize.js";
|
|
2
|
+
import { historySlice } from "./history.js";
|
|
3
|
+
|
|
4
|
+
//#region src/devtools/handlers.ts
|
|
5
|
+
function sceneOf(root) {
|
|
6
|
+
const scene = root.source.scene();
|
|
7
|
+
if (!scene) throw new Error("scene not mounted yet");
|
|
8
|
+
return scene;
|
|
9
|
+
}
|
|
10
|
+
function summaryOf(node) {
|
|
11
|
+
return {
|
|
12
|
+
id: node.id,
|
|
13
|
+
kind: node.kind,
|
|
14
|
+
layer: node.layer,
|
|
15
|
+
childCount: node.kind === "container" ? node.children.length : 0,
|
|
16
|
+
hidden: node.hidden === true,
|
|
17
|
+
locked: node.locked === true,
|
|
18
|
+
pickable: node.pickable !== false
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function nodeOf(scene, id) {
|
|
22
|
+
const node = scene.get(id);
|
|
23
|
+
if (!node) throw new Error(`no node "${id}"`);
|
|
24
|
+
return node;
|
|
25
|
+
}
|
|
26
|
+
function childrenOf(root, nodeId) {
|
|
27
|
+
const scene = sceneOf(root);
|
|
28
|
+
return (nodeId === void 0 ? scene.roots : (nodeOf(scene, nodeId), scene.childrenOf(nodeId))).map((id) => summaryOf(nodeOf(scene, id)));
|
|
29
|
+
}
|
|
30
|
+
function nodeDetail(root, nodeId) {
|
|
31
|
+
const node = nodeOf(sceneOf(root), nodeId);
|
|
32
|
+
return {
|
|
33
|
+
...summaryOf(node),
|
|
34
|
+
parent: node.parent ?? null,
|
|
35
|
+
pose: serialize(node.pose),
|
|
36
|
+
data: serialize(node.data)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** The on/off features of a debug config, leaving out its theme and strokes. */
|
|
40
|
+
function overlayFlags(config) {
|
|
41
|
+
const flags = {};
|
|
42
|
+
if (!config) return flags;
|
|
43
|
+
for (const [key, value] of Object.entries(config)) if (typeof value === "boolean") flags[key] = value;
|
|
44
|
+
return flags;
|
|
45
|
+
}
|
|
46
|
+
function rootState(root) {
|
|
47
|
+
const { source } = root;
|
|
48
|
+
const probes = {};
|
|
49
|
+
for (const [name, read] of root.probes) try {
|
|
50
|
+
probes[name] = serialize(read());
|
|
51
|
+
} catch (err) {
|
|
52
|
+
probes[name] = `[threw: ${err.message}]`;
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
selection: [...source.selection()],
|
|
56
|
+
view: serialize(source.view()),
|
|
57
|
+
activeTool: source.activeTool(),
|
|
58
|
+
tools: [...source.tools()],
|
|
59
|
+
overlays: overlayFlags(source.overlays()),
|
|
60
|
+
probes
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Trace records are plain data by contract, and nest deeper than a node's data is shown. */
|
|
64
|
+
var RECORD = { depth: 12 };
|
|
65
|
+
function traceSlice(root, cursor, coordCursor) {
|
|
66
|
+
const { trace, coords } = root.source;
|
|
67
|
+
const slice = trace.since(cursor);
|
|
68
|
+
const out = {
|
|
69
|
+
entries: slice.entries.map((e) => serialize(e, RECORD)),
|
|
70
|
+
cursor: slice.cursor,
|
|
71
|
+
live: serialize(trace.live(), RECORD)
|
|
72
|
+
};
|
|
73
|
+
if (coordCursor !== void 0) {
|
|
74
|
+
const c = coords.since(coordCursor);
|
|
75
|
+
out.coords = {
|
|
76
|
+
entries: c.entries.map((e) => serialize(e, RECORD)),
|
|
77
|
+
cursor: c.cursor
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** Answer `req` about `root`. `steer` lays a change over the panel's override. Throws on a bad request. */
|
|
83
|
+
function answer(root, req, steer) {
|
|
84
|
+
switch (req.type) {
|
|
85
|
+
case "get-children": return childrenOf(root, req.nodeId);
|
|
86
|
+
case "get-node": return nodeDetail(root, req.nodeId);
|
|
87
|
+
case "get-state": return rootState(root);
|
|
88
|
+
case "get-trace": return traceSlice(root, req.cursor, req.coordCursor);
|
|
89
|
+
case "get-frame": return serialize(root.source.frame());
|
|
90
|
+
case "get-registry":
|
|
91
|
+
if (!root.source.registry) throw new Error("this root serves no registry");
|
|
92
|
+
return root.source.registry();
|
|
93
|
+
case "get-history": return historySlice(root, req.cursor, req.checkpoints);
|
|
94
|
+
case "select":
|
|
95
|
+
root.source.select(req.ids);
|
|
96
|
+
return null;
|
|
97
|
+
case "set-tool":
|
|
98
|
+
if (req.toolId !== null && !root.source.tools().includes(req.toolId)) throw new Error(`no tool "${req.toolId}"`);
|
|
99
|
+
root.source.setTool(req.toolId);
|
|
100
|
+
return null;
|
|
101
|
+
case "highlight":
|
|
102
|
+
steer({ highlight: [...req.ids] });
|
|
103
|
+
return null;
|
|
104
|
+
case "set-overlays":
|
|
105
|
+
steer({ overlays: req.overlays });
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
export { answer, childrenOf, nodeDetail, overlayFlags, rootState, traceSlice };
|
|
112
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","names":[],"sources":["../../src/devtools/handlers.ts"],"sourcesContent":["/** The answer to each devtools request, for one root. The session owns the override a steering request changes. */\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport type { DebugConfig } from '../debug/types';\nimport type { DevtoolsRoot } from './root';\nimport type {\n DevtoolsNodeDetail, DevtoolsNodeSummary, DevtoolsOverlays, DevtoolsRequest, DevtoolsResult,\n DevtoolsRootState, DevtoolsTraceSlice,\n} from './protocol';\nimport { serialize } from './serialize';\nimport { historySlice } from './history';\n\ntype AnyScene = Scene<unknown, string, unknown>;\ntype AnyNode = Node<unknown, string, unknown>;\n\nfunction sceneOf(root: DevtoolsRoot): AnyScene {\n const scene = root.source.scene();\n if (!scene) throw new Error('scene not mounted yet');\n return scene;\n}\n\nfunction summaryOf(node: AnyNode): DevtoolsNodeSummary {\n return {\n id: node.id,\n kind: node.kind,\n layer: node.layer,\n childCount: node.kind === 'container' ? node.children.length : 0,\n hidden: node.hidden === true,\n locked: node.locked === true,\n pickable: node.pickable !== false,\n };\n}\n\nfunction nodeOf(scene: AnyScene, id: string): AnyNode {\n const node = scene.get(id as NodeId);\n if (!node) throw new Error(`no node \"${id}\"`);\n return node;\n}\n\nexport function childrenOf(root: DevtoolsRoot, nodeId: string | undefined): DevtoolsNodeSummary[] {\n const scene = sceneOf(root);\n const ids = nodeId === undefined ? scene.roots : (nodeOf(scene, nodeId), scene.childrenOf(nodeId as NodeId));\n return ids.map((id) => summaryOf(nodeOf(scene, id)));\n}\n\nexport function nodeDetail(root: DevtoolsRoot, nodeId: string): DevtoolsNodeDetail {\n const node = nodeOf(sceneOf(root), nodeId);\n return {\n ...summaryOf(node),\n parent: node.parent ?? null,\n pose: serialize(node.pose),\n data: serialize(node.data),\n };\n}\n\n/** The on/off features of a debug config, leaving out its theme and strokes. */\nexport function overlayFlags(config: DebugConfig | null): DevtoolsOverlays {\n const flags: DevtoolsOverlays = {};\n if (!config) return flags;\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === 'boolean') (flags as Record<string, boolean>)[key] = value;\n }\n return flags;\n}\n\nexport function rootState(root: DevtoolsRoot): DevtoolsRootState {\n const { source } = root;\n const probes: DevtoolsRootState['probes'] = {};\n for (const [name, read] of root.probes) {\n try {\n probes[name] = serialize(read());\n } catch (err) {\n probes[name] = `[threw: ${(err as Error).message}]`;\n }\n }\n return {\n selection: [...source.selection()],\n view: serialize(source.view()),\n activeTool: source.activeTool(),\n tools: [...source.tools()],\n overlays: overlayFlags(source.overlays()),\n probes,\n };\n}\n\n/** Trace records are plain data by contract, and nest deeper than a node's data is shown. */\nconst RECORD = { depth: 12 };\n\nexport function traceSlice(root: DevtoolsRoot, cursor: number, coordCursor: number | undefined): DevtoolsTraceSlice {\n const { trace, coords } = root.source;\n const slice = trace.since(cursor);\n const out: DevtoolsTraceSlice = {\n entries: slice.entries.map((e) => serialize(e, RECORD)),\n cursor: slice.cursor,\n live: serialize(trace.live(), RECORD),\n };\n if (coordCursor !== undefined) {\n const c = coords.since(coordCursor);\n out.coords = { entries: c.entries.map((e) => serialize(e, RECORD)), cursor: c.cursor };\n }\n return out;\n}\n\n/** Answer `req` about `root`. `steer` lays a change over the panel's override. Throws on a bad request. */\nexport function answer(\n root: DevtoolsRoot,\n req: DevtoolsRequest,\n steer: (change: { overlays?: DevtoolsOverlays; highlight?: readonly string[] }) => void,\n): DevtoolsResult {\n switch (req.type) {\n case 'get-children': return childrenOf(root, req.nodeId);\n case 'get-node': return nodeDetail(root, req.nodeId);\n case 'get-state': return rootState(root);\n case 'get-trace': return traceSlice(root, req.cursor, req.coordCursor);\n case 'get-frame': return serialize(root.source.frame());\n case 'get-registry':\n if (!root.source.registry) throw new Error('this root serves no registry');\n return root.source.registry();\n case 'get-history': return historySlice(root, req.cursor, req.checkpoints);\n case 'select':\n root.source.select(req.ids);\n return null;\n case 'set-tool':\n if (req.toolId !== null && !root.source.tools().includes(req.toolId)) throw new Error(`no tool \"${req.toolId}\"`);\n root.source.setTool(req.toolId);\n return null;\n case 'highlight':\n steer({ highlight: [...req.ids] });\n return null;\n case 'set-overlays':\n steer({ overlays: req.overlays });\n return null;\n }\n}\n"],"mappings":";;;;AAcA,SAAS,QAAQ,MAA8B;CAC7C,MAAM,QAAQ,KAAK,OAAO,MAAM;CAChC,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,uBAAuB;CACnD,OAAO;AACT;AAEA,SAAS,UAAU,MAAoC;CACrD,OAAO;EACL,IAAI,KAAK;EACT,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,YAAY,KAAK,SAAS,cAAc,KAAK,SAAS,SAAS;EAC/D,QAAQ,KAAK,WAAW;EACxB,QAAQ,KAAK,WAAW;EACxB,UAAU,KAAK,aAAa;CAC9B;AACF;AAEA,SAAS,OAAO,OAAiB,IAAqB;CACpD,MAAM,OAAO,MAAM,IAAI,EAAY;CACnC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,YAAY,GAAG,EAAE;CAC5C,OAAO;AACT;AAEA,SAAgB,WAAW,MAAoB,QAAmD;CAChG,MAAM,QAAQ,QAAQ,IAAI;CAE1B,QADY,WAAW,SAAY,MAAM,SAAS,OAAO,OAAO,MAAM,GAAG,MAAM,WAAW,MAAgB,GACnG,CAAI,KAAK,OAAO,UAAU,OAAO,OAAO,EAAE,CAAC,CAAC;AACrD;AAEA,SAAgB,WAAW,MAAoB,QAAoC;CACjF,MAAM,OAAO,OAAO,QAAQ,IAAI,GAAG,MAAM;CACzC,OAAO;EACL,GAAG,UAAU,IAAI;EACjB,QAAQ,KAAK,UAAU;EACvB,MAAM,UAAU,KAAK,IAAI;EACzB,MAAM,UAAU,KAAK,IAAI;CAC3B;AACF;;AAGA,SAAgB,aAAa,QAA8C;CACzE,MAAM,QAA0B,CAAC;CACjC,IAAI,CAAC,QAAQ,OAAO;CACpB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,UAAU,WAAW,MAAmC,OAAO;CAE5E,OAAO;AACT;AAEA,SAAgB,UAAU,MAAuC;CAC/D,MAAM,EAAE,WAAW;CACnB,MAAM,SAAsC,CAAC;CAC7C,KAAK,MAAM,CAAC,MAAM,SAAS,KAAK,QAC9B,IAAI;EACF,OAAO,QAAQ,UAAU,KAAK,CAAC;CACjC,SAAS,KAAK;EACZ,OAAO,QAAQ,WAAY,IAAc,QAAQ;CACnD;CAEF,OAAO;EACL,WAAW,CAAC,GAAG,OAAO,UAAU,CAAC;EACjC,MAAM,UAAU,OAAO,KAAK,CAAC;EAC7B,YAAY,OAAO,WAAW;EAC9B,OAAO,CAAC,GAAG,OAAO,MAAM,CAAC;EACzB,UAAU,aAAa,OAAO,SAAS,CAAC;EACxC;CACF;AACF;;AAGA,IAAM,SAAS,EAAE,OAAO,GAAG;AAE3B,SAAgB,WAAW,MAAoB,QAAgB,aAAqD;CAClH,MAAM,EAAE,OAAO,WAAW,KAAK;CAC/B,MAAM,QAAQ,MAAM,MAAM,MAAM;CAChC,MAAM,MAA0B;EAC9B,SAAS,MAAM,QAAQ,KAAK,MAAM,UAAU,GAAG,MAAM,CAAC;EACtD,QAAQ,MAAM;EACd,MAAM,UAAU,MAAM,KAAK,GAAG,MAAM;CACtC;CACA,IAAI,gBAAgB,QAAW;EAC7B,MAAM,IAAI,OAAO,MAAM,WAAW;EAClC,IAAI,SAAS;GAAE,SAAS,EAAE,QAAQ,KAAK,MAAM,UAAU,GAAG,MAAM,CAAC;GAAG,QAAQ,EAAE;EAAO;CACvF;CACA,OAAO;AACT;;AAGA,SAAgB,OACd,MACA,KACA,OACgB;CAChB,QAAQ,IAAI,MAAZ;EACE,KAAK,gBAAgB,OAAO,WAAW,MAAM,IAAI,MAAM;EACvD,KAAK,YAAY,OAAO,WAAW,MAAM,IAAI,MAAM;EACnD,KAAK,aAAa,OAAO,UAAU,IAAI;EACvC,KAAK,aAAa,OAAO,WAAW,MAAM,IAAI,QAAQ,IAAI,WAAW;EACrE,KAAK,aAAa,OAAO,UAAU,KAAK,OAAO,MAAM,CAAC;EACtD,KAAK;GACH,IAAI,CAAC,KAAK,OAAO,UAAU,MAAM,IAAI,MAAM,8BAA8B;GACzE,OAAO,KAAK,OAAO,SAAS;EAC9B,KAAK,eAAe,OAAO,aAAa,MAAM,IAAI,QAAQ,IAAI,WAAW;EACzE,KAAK;GACH,KAAK,OAAO,OAAO,IAAI,GAAG;GAC1B,OAAO;EACT,KAAK;GACH,IAAI,IAAI,WAAW,QAAQ,CAAC,KAAK,OAAO,MAAM,CAAC,CAAC,SAAS,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,YAAY,IAAI,OAAO,EAAE;GAC/G,KAAK,OAAO,QAAQ,IAAI,MAAM;GAC9B,OAAO;EACT,KAAK;GACH,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;GACjC,OAAO;EACT,KAAK;GACH,MAAM,EAAE,UAAU,IAAI,SAAS,CAAC;GAChC,OAAO;CACX;AACF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { serialize } from "./serialize.js";
|
|
2
|
+
import { touchedIdsFromOps } from "@weasel-js/history";
|
|
3
|
+
|
|
4
|
+
//#region src/devtools/history.ts
|
|
5
|
+
/** A scene's history steps as the devtools hook keeps them: one plain record per step, in a rolling ring. */
|
|
6
|
+
/** How much of one step a record keeps: a jump can walk the whole stack, and a batch can hold any number of ops. */
|
|
7
|
+
var HISTORY_RECORD_LIMITS = {
|
|
8
|
+
entries: 50,
|
|
9
|
+
ops: 50
|
|
10
|
+
};
|
|
11
|
+
var SUMMARY = {
|
|
12
|
+
depth: 4,
|
|
13
|
+
items: 20,
|
|
14
|
+
chars: 200
|
|
15
|
+
};
|
|
16
|
+
function opOf(op) {
|
|
17
|
+
return {
|
|
18
|
+
kind: op.name ?? "?",
|
|
19
|
+
targets: [...touchedIdsFromOps([op])],
|
|
20
|
+
summary: serialize(op.args, SUMMARY)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function recordOf(step, history) {
|
|
24
|
+
const index = history.undoDepth();
|
|
25
|
+
return {
|
|
26
|
+
ts: Date.now(),
|
|
27
|
+
step: step.kind,
|
|
28
|
+
entries: step.entries.slice(0, HISTORY_RECORD_LIMITS.entries).map((e) => ({
|
|
29
|
+
id: e.id,
|
|
30
|
+
label: e.label,
|
|
31
|
+
opCount: e.ops.length,
|
|
32
|
+
ops: e.ops.slice(0, HISTORY_RECORD_LIMITS.ops).map(opOf)
|
|
33
|
+
})),
|
|
34
|
+
position: {
|
|
35
|
+
index,
|
|
36
|
+
total: index + history.redoDepth()
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Push a record of each step `history` takes into `ring`, while the ring is recording. Returns the stop. */
|
|
41
|
+
function recordHistory(history, ring) {
|
|
42
|
+
return history.observe((step) => {
|
|
43
|
+
if (ring.recording()) ring.push(recordOf(step, history));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function historySlice(root, cursor, checkpoints) {
|
|
47
|
+
const ring = root.source.history;
|
|
48
|
+
const scene = root.source.scene();
|
|
49
|
+
if (!ring || !scene) throw new Error("no history to read");
|
|
50
|
+
const slice = ring.since(cursor);
|
|
51
|
+
const index = scene.history.undoDepth();
|
|
52
|
+
const out = {
|
|
53
|
+
entries: slice.entries,
|
|
54
|
+
cursor: slice.cursor,
|
|
55
|
+
position: {
|
|
56
|
+
index,
|
|
57
|
+
total: index + scene.history.redoDepth(),
|
|
58
|
+
canUndo: scene.canUndo(),
|
|
59
|
+
canRedo: scene.canRedo()
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
if (checkpoints) out.checkpoints = scene.historyEntries().map((e) => ({
|
|
63
|
+
id: e.id,
|
|
64
|
+
label: e.label
|
|
65
|
+
}));
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { HISTORY_RECORD_LIMITS, historySlice, recordHistory };
|
|
71
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","names":[],"sources":["../../src/devtools/history.ts"],"sourcesContent":["/** A scene's history steps as the devtools hook keeps them: one plain record per step, in a rolling ring. */\nimport { touchedIdsFromOps, type History, type HistoryStep } from '@weasel-js/history';\nimport type { TraceRing } from '@weasel-js/routing';\nimport type { DevtoolsHistoryOp, DevtoolsHistoryRecord, DevtoolsHistorySlice } from './protocol';\nimport type { DevtoolsRoot } from './root';\nimport { serialize } from './serialize';\n\n/** How much of one step a record keeps: a jump can walk the whole stack, and a batch can hold any number of ops. */\nexport const HISTORY_RECORD_LIMITS = { entries: 50, ops: 50 };\n\nconst SUMMARY = { depth: 4, items: 20, chars: 200 };\n\nfunction opOf(op: HistoryStep['entries'][number]['ops'][number]): DevtoolsHistoryOp {\n return { kind: op.name ?? '?', targets: [...touchedIdsFromOps([op])], summary: serialize(op.args, SUMMARY) };\n}\n\nfunction recordOf(step: HistoryStep, history: Pick<History, 'undoDepth' | 'redoDepth'>): DevtoolsHistoryRecord {\n const index = history.undoDepth();\n return {\n ts: Date.now(),\n step: step.kind,\n entries: step.entries.slice(0, HISTORY_RECORD_LIMITS.entries).map((e) => ({\n id: e.id,\n label: e.label,\n opCount: e.ops.length,\n ops: e.ops.slice(0, HISTORY_RECORD_LIMITS.ops).map(opOf),\n })),\n position: { index, total: index + history.redoDepth() },\n };\n}\n\n/** Push a record of each step `history` takes into `ring`, while the ring is recording. Returns the stop. */\nexport function recordHistory(history: History, ring: TraceRing<DevtoolsHistoryRecord>): () => void {\n return history.observe((step) => {\n if (ring.recording()) ring.push(recordOf(step, history));\n });\n}\n\nexport function historySlice(root: DevtoolsRoot, cursor: number, checkpoints: boolean | undefined): DevtoolsHistorySlice {\n const ring = root.source.history;\n const scene = root.source.scene();\n if (!ring || !scene) throw new Error('no history to read');\n const slice = ring.since(cursor);\n const index = scene.history.undoDepth();\n const out: DevtoolsHistorySlice = {\n entries: slice.entries,\n cursor: slice.cursor,\n position: { index, total: index + scene.history.redoDepth(), canUndo: scene.canUndo(), canRedo: scene.canRedo() },\n };\n if (checkpoints) out.checkpoints = scene.historyEntries().map((e) => ({ id: e.id, label: e.label }));\n return out;\n}\n"],"mappings":";;;;;;AAQA,IAAa,wBAAwB;CAAE,SAAS;CAAI,KAAK;AAAG;AAE5D,IAAM,UAAU;CAAE,OAAO;CAAG,OAAO;CAAI,OAAO;AAAI;AAElD,SAAS,KAAK,IAAsE;CAClF,OAAO;EAAE,MAAM,GAAG,QAAQ;EAAK,SAAS,CAAC,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;EAAG,SAAS,UAAU,GAAG,MAAM,OAAO;CAAE;AAC7G;AAEA,SAAS,SAAS,MAAmB,SAA0E;CAC7G,MAAM,QAAQ,QAAQ,UAAU;CAChC,OAAO;EACL,IAAI,KAAK,IAAI;EACb,MAAM,KAAK;EACX,SAAS,KAAK,QAAQ,MAAM,GAAG,sBAAsB,OAAO,CAAC,CAAC,KAAK,OAAO;GACxE,IAAI,EAAE;GACN,OAAO,EAAE;GACT,SAAS,EAAE,IAAI;GACf,KAAK,EAAE,IAAI,MAAM,GAAG,sBAAsB,GAAG,CAAC,CAAC,IAAI,IAAI;EACzD,EAAE;EACF,UAAU;GAAE;GAAO,OAAO,QAAQ,QAAQ,UAAU;EAAE;CACxD;AACF;;AAGA,SAAgB,cAAc,SAAkB,MAAoD;CAClG,OAAO,QAAQ,SAAS,SAAS;EAC/B,IAAI,KAAK,UAAU,GAAG,KAAK,KAAK,SAAS,MAAM,OAAO,CAAC;CACzD,CAAC;AACH;AAEA,SAAgB,aAAa,MAAoB,QAAgB,aAAwD;CACvH,MAAM,OAAO,KAAK,OAAO;CACzB,MAAM,QAAQ,KAAK,OAAO,MAAM;CAChC,IAAI,CAAC,QAAQ,CAAC,OAAO,MAAM,IAAI,MAAM,oBAAoB;CACzD,MAAM,QAAQ,KAAK,MAAM,MAAM;CAC/B,MAAM,QAAQ,MAAM,QAAQ,UAAU;CACtC,MAAM,MAA4B;EAChC,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,UAAU;GAAE;GAAO,OAAO,QAAQ,MAAM,QAAQ,UAAU;GAAG,SAAS,MAAM,QAAQ;GAAG,SAAS,MAAM,QAAQ;EAAE;CAClH;CACA,IAAI,aAAa,IAAI,cAAc,MAAM,eAAe,CAAC,CAAC,KAAK,OAAO;EAAE,IAAI,EAAE;EAAI,OAAO,EAAE;CAAM,EAAE;CACnG,OAAO;AACT"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { VERSION } from "../version.js";
|
|
2
|
+
import { DEVTOOLS_PROTOCOL } from "./protocol.js";
|
|
3
|
+
import { openSession } from "./session.js";
|
|
4
|
+
import { createWindowPageTransport, isDevtoolsEnvelope } from "./transport.js";
|
|
5
|
+
import { createEmitter } from "@weasel-js/registry";
|
|
6
|
+
|
|
7
|
+
//#region src/devtools/hook.ts
|
|
8
|
+
/**
|
|
9
|
+
* The devtools hook: the page-wide registry of roots a panel connects to,
|
|
10
|
+
* published as `window.__weaselDevtools__`.
|
|
11
|
+
*/
|
|
12
|
+
/** Waits for the next frame: the one-shot callback coalesces notices, it never loops. */
|
|
13
|
+
var nextFrame = (flush) => {
|
|
14
|
+
if (typeof requestAnimationFrame === "function") requestAnimationFrame(() => flush());
|
|
15
|
+
else setTimeout(flush, 16);
|
|
16
|
+
};
|
|
17
|
+
/** A hook not published anywhere: what {@link installDevtoolsHook} publishes, and what tests build. */
|
|
18
|
+
function createDevtoolsHook(opts = {}) {
|
|
19
|
+
const live = /* @__PURE__ */ new Map();
|
|
20
|
+
const rootEvents = createEmitter();
|
|
21
|
+
const host = {
|
|
22
|
+
roots: () => [...live.values()],
|
|
23
|
+
root: (id) => live.get(id),
|
|
24
|
+
onRoots: (listener) => rootEvents.subscribe(listener),
|
|
25
|
+
schedule: opts.schedule ?? nextFrame
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
protocol: DEVTOOLS_PROTOCOL,
|
|
29
|
+
kitVersion: VERSION,
|
|
30
|
+
roots: () => [...live.values()].map((r) => r.info()),
|
|
31
|
+
root: (id) => live.get(id),
|
|
32
|
+
register(root) {
|
|
33
|
+
live.set(root.id, root);
|
|
34
|
+
rootEvents.emit({ added: root });
|
|
35
|
+
return () => {
|
|
36
|
+
if (live.get(root.id) !== root) return;
|
|
37
|
+
live.delete(root.id);
|
|
38
|
+
rootEvents.emit({ removed: root.id });
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
connect(transport, opening) {
|
|
42
|
+
const session = openSession(host, transport);
|
|
43
|
+
const off = transport.onMessage((m) => session.receive(m));
|
|
44
|
+
if (opening) session.receive(opening);
|
|
45
|
+
return () => {
|
|
46
|
+
off();
|
|
47
|
+
session.close();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Serve the one window-transport panel there can be: a `yo` posted to the window opens it, replacing any before. */
|
|
53
|
+
function serveWindow(hook) {
|
|
54
|
+
const transport = createWindowPageTransport();
|
|
55
|
+
let close = null;
|
|
56
|
+
window.addEventListener("message", (e) => {
|
|
57
|
+
if (!isDevtoolsEnvelope(e.data) || e.data.side !== "panel" || e.data.message.type !== "yo") return;
|
|
58
|
+
close?.();
|
|
59
|
+
close = hook.connect(transport, e.data.message);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Publish the hook on `window.__weaselDevtools__`, once; later calls return the same hook. */
|
|
63
|
+
function installDevtoolsHook() {
|
|
64
|
+
if (typeof window === "undefined") return null;
|
|
65
|
+
if (window.__weaselDevtools__) return window.__weaselDevtools__;
|
|
66
|
+
const hook = createDevtoolsHook();
|
|
67
|
+
window.__weaselDevtools__ = hook;
|
|
68
|
+
serveWindow(hook);
|
|
69
|
+
return hook;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//#endregion
|
|
73
|
+
export { createDevtoolsHook, installDevtoolsHook };
|
|
74
|
+
//# sourceMappingURL=hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","names":[],"sources":["../../src/devtools/hook.ts"],"sourcesContent":["/**\n * The devtools hook: the page-wide registry of roots a panel connects to,\n * published as `window.__weaselDevtools__`.\n */\nimport { createEmitter } from '@weasel-js/registry';\nimport { VERSION } from '../version';\nimport { DEVTOOLS_PROTOCOL, type DevtoolsRootInfo, type PanelMessage } from './protocol';\nimport type { DevtoolsRoot } from './root';\nimport type { DevtoolsSchedule } from './notices';\nimport { openSession, type SessionHost } from './session';\nimport { createWindowPageTransport, isDevtoolsEnvelope, type PageTransport } from './transport';\n\n/** What `window.__weaselDevtools__` holds: the page's canvases, and the way a panel connects to them. */\nexport interface WeaselDevtoolsHook {\n readonly protocol: number;\n readonly kitVersion: string;\n roots(): DevtoolsRootInfo[];\n /** The root registered under `id`, for in-page readers such as the test hook. */\n root(id: string): DevtoolsRoot | undefined;\n /** Add a canvas's root. Returns its removal. */\n register(root: DevtoolsRoot): () => void;\n /** Serve a panel over `transport` until the panel says `bye` or the returned close is called.\n * `opening` is a message that arrived before the transport was listened to — the `yo` that\n * prompted the connection. */\n connect(transport: PageTransport, opening?: PanelMessage): () => void;\n}\n\ndeclare global {\n interface Window {\n __weaselDevtools__?: WeaselDevtoolsHook;\n }\n}\n\n/** Waits for the next frame: the one-shot callback coalesces notices, it never loops. */\nconst nextFrame: DevtoolsSchedule = (flush) => {\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(() => flush());\n else setTimeout(flush, 16);\n};\n\n/** A hook not published anywhere: what {@link installDevtoolsHook} publishes, and what tests build. */\nexport function createDevtoolsHook(opts: { schedule?: DevtoolsSchedule } = {}): WeaselDevtoolsHook {\n const live = new Map<string, DevtoolsRoot>();\n const rootEvents = createEmitter<[{ added: DevtoolsRoot } | { removed: string }]>();\n const host: SessionHost = {\n roots: () => [...live.values()],\n root: (id) => live.get(id),\n onRoots: (listener) => rootEvents.subscribe(listener),\n schedule: opts.schedule ?? nextFrame,\n };\n return {\n protocol: DEVTOOLS_PROTOCOL,\n kitVersion: VERSION,\n roots: () => [...live.values()].map((r) => r.info()),\n root: (id) => live.get(id),\n register(root) {\n live.set(root.id, root);\n rootEvents.emit({ added: root });\n return () => {\n if (live.get(root.id) !== root) return;\n live.delete(root.id);\n rootEvents.emit({ removed: root.id });\n };\n },\n connect(transport, opening) {\n const session = openSession(host, transport);\n const off = transport.onMessage((m) => session.receive(m));\n if (opening) session.receive(opening);\n return () => { off(); session.close(); };\n },\n };\n}\n\n/** Serve the one window-transport panel there can be: a `yo` posted to the window opens it, replacing any before. */\nfunction serveWindow(hook: WeaselDevtoolsHook): void {\n const transport = createWindowPageTransport();\n let close: (() => void) | null = null;\n window.addEventListener('message', (e) => {\n if (!isDevtoolsEnvelope(e.data) || e.data.side !== 'panel' || e.data.message.type !== 'yo') return;\n close?.();\n close = hook.connect(transport, e.data.message as PanelMessage);\n });\n}\n\n/** Publish the hook on `window.__weaselDevtools__`, once; later calls return the same hook. */\nexport function installDevtoolsHook(): WeaselDevtoolsHook | null {\n if (typeof window === 'undefined') return null;\n if (window.__weaselDevtools__) return window.__weaselDevtools__;\n const hook = createDevtoolsHook();\n window.__weaselDevtools__ = hook;\n serveWindow(hook);\n return hook;\n}\n"],"mappings":";;;;;;;;;;;;AAkCA,IAAM,aAA+B,UAAU;CAC7C,IAAI,OAAO,0BAA0B,YAAY,4BAA4B,MAAM,CAAC;MAC/E,WAAW,OAAO,EAAE;AAC3B;;AAGA,SAAgB,mBAAmB,OAAwC,CAAC,GAAuB;CACjG,MAAM,uBAAO,IAAI,IAA0B;CAC3C,MAAM,aAAa,cAA+D;CAClF,MAAM,OAAoB;EACxB,aAAa,CAAC,GAAG,KAAK,OAAO,CAAC;EAC9B,OAAO,OAAO,KAAK,IAAI,EAAE;EACzB,UAAU,aAAa,WAAW,UAAU,QAAQ;EACpD,UAAU,KAAK,YAAY;CAC7B;CACA,OAAO;EACL,UAAU;EACV,YAAY;EACZ,aAAa,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;EACnD,OAAO,OAAO,KAAK,IAAI,EAAE;EACzB,SAAS,MAAM;GACb,KAAK,IAAI,KAAK,IAAI,IAAI;GACtB,WAAW,KAAK,EAAE,OAAO,KAAK,CAAC;GAC/B,aAAa;IACX,IAAI,KAAK,IAAI,KAAK,EAAE,MAAM,MAAM;IAChC,KAAK,OAAO,KAAK,EAAE;IACnB,WAAW,KAAK,EAAE,SAAS,KAAK,GAAG,CAAC;GACtC;EACF;EACA,QAAQ,WAAW,SAAS;GAC1B,MAAM,UAAU,YAAY,MAAM,SAAS;GAC3C,MAAM,MAAM,UAAU,WAAW,MAAM,QAAQ,QAAQ,CAAC,CAAC;GACzD,IAAI,SAAS,QAAQ,QAAQ,OAAO;GACpC,aAAa;IAAE,IAAI;IAAG,QAAQ,MAAM;GAAG;EACzC;CACF;AACF;;AAGA,SAAS,YAAY,MAAgC;CACnD,MAAM,YAAY,0BAA0B;CAC5C,IAAI,QAA6B;CACjC,OAAO,iBAAiB,YAAY,MAAM;EACxC,IAAI,CAAC,mBAAmB,EAAE,IAAI,KAAK,EAAE,KAAK,SAAS,WAAW,EAAE,KAAK,QAAQ,SAAS,MAAM;EAC5F,QAAQ;EACR,QAAQ,KAAK,QAAQ,WAAW,EAAE,KAAK,OAAuB;CAChE,CAAC;AACH;;AAGA,SAAgB,sBAAiD;CAC/D,IAAI,OAAO,WAAW,aAAa,OAAO;CAC1C,IAAI,OAAO,oBAAoB,OAAO,OAAO;CAC7C,MAAM,OAAO,mBAAmB;CAChC,OAAO,qBAAqB;CAC5B,YAAY,IAAI;CAChB,OAAO;AACT"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/devtools/label.tsx
|
|
5
|
+
var DevtoolsLabelContext = createContext(null);
|
|
6
|
+
/**
|
|
7
|
+
* Names the canvases beneath it in a devtools panel, ahead of any labeled
|
|
8
|
+
* element between them and it. A host that frames canvases it did not write,
|
|
9
|
+
* such as a lab's trial or a story's frame, knows the right name; the nearest
|
|
10
|
+
* labeled ancestor is only a guess.
|
|
11
|
+
*/
|
|
12
|
+
function DevtoolsLabel({ value, children }) {
|
|
13
|
+
return /* @__PURE__ */ jsx(DevtoolsLabelContext.Provider, {
|
|
14
|
+
value,
|
|
15
|
+
children
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/** The label the nearest `<DevtoolsLabel>` gives, or null outside one. */
|
|
19
|
+
function useDevtoolsLabel() {
|
|
20
|
+
return useContext(DevtoolsLabelContext);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { DevtoolsLabel, useDevtoolsLabel };
|
|
25
|
+
//# sourceMappingURL=label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.js","names":[],"sources":["../../src/devtools/label.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\n\nconst DevtoolsLabelContext = createContext<string | null>(null);\n\n/** Props for `<DevtoolsLabel>`. */\nexport interface DevtoolsLabelProps {\n /** The name a devtools panel lists each canvas below this under, unless the canvas has an `aria-label` or id. */\n value: string;\n children?: ReactNode;\n}\n\n/**\n * Names the canvases beneath it in a devtools panel, ahead of any labeled\n * element between them and it. A host that frames canvases it did not write,\n * such as a lab's trial or a story's frame, knows the right name; the nearest\n * labeled ancestor is only a guess.\n */\nexport function DevtoolsLabel({ value, children }: DevtoolsLabelProps) {\n return <DevtoolsLabelContext.Provider value={value}>{children}</DevtoolsLabelContext.Provider>;\n}\n\n/** The label the nearest `<DevtoolsLabel>` gives, or null outside one. */\nexport function useDevtoolsLabel(): string | null {\n return useContext(DevtoolsLabelContext);\n}\n"],"mappings":";;;;AAEA,IAAM,uBAAuB,cAA6B,IAAI;;;;;;;AAe9D,SAAgB,cAAc,EAAE,OAAO,YAAgC;CACrE,OAAO,oBAAC,qBAAqB,UAAtB;EAAsC;EAAQ;CAAwC,CAAA;AAC/F;;AAGA,SAAgB,mBAAkC;CAChD,OAAO,WAAW,oBAAoB;AACxC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DEVTOOLS_PROTOCOL } from "./protocol.js";
|
|
2
|
+
|
|
3
|
+
//#region src/devtools/notices.ts
|
|
4
|
+
/** A session's change notices: the roots it follows, and what changed in each since the last flush. */
|
|
5
|
+
function createNotices(rootOf, schedule, send) {
|
|
6
|
+
const following = /* @__PURE__ */ new Map();
|
|
7
|
+
const pending = /* @__PURE__ */ new Map();
|
|
8
|
+
let scheduled = false;
|
|
9
|
+
const flush = () => {
|
|
10
|
+
scheduled = false;
|
|
11
|
+
for (const [rootId, areas] of pending) {
|
|
12
|
+
const root = rootOf(rootId);
|
|
13
|
+
if (!root || !following.has(rootId)) continue;
|
|
14
|
+
const versions = {};
|
|
15
|
+
for (const area of areas) versions[area] = root.version(area);
|
|
16
|
+
send({
|
|
17
|
+
type: "changed",
|
|
18
|
+
protocol: DEVTOOLS_PROTOCOL,
|
|
19
|
+
rootId,
|
|
20
|
+
areas: versions
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
pending.clear();
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
follow(root) {
|
|
27
|
+
if (following.has(root.id)) return;
|
|
28
|
+
const releaseTrace = root.source.trace.watch();
|
|
29
|
+
const releaseCoords = root.source.coords.watch();
|
|
30
|
+
const releaseHistory = root.source.history?.watch();
|
|
31
|
+
const off = root.subscribe((area) => {
|
|
32
|
+
let areas = pending.get(root.id);
|
|
33
|
+
if (!areas) pending.set(root.id, areas = /* @__PURE__ */ new Set());
|
|
34
|
+
areas.add(area);
|
|
35
|
+
if (!scheduled) {
|
|
36
|
+
scheduled = true;
|
|
37
|
+
schedule(flush);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
following.set(root.id, () => {
|
|
41
|
+
releaseTrace();
|
|
42
|
+
releaseCoords();
|
|
43
|
+
releaseHistory?.();
|
|
44
|
+
off();
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
unfollow(rootId) {
|
|
48
|
+
following.get(rootId)?.();
|
|
49
|
+
following.delete(rootId);
|
|
50
|
+
pending.delete(rootId);
|
|
51
|
+
},
|
|
52
|
+
ids: () => [...following.keys()]
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { createNotices };
|
|
58
|
+
//# sourceMappingURL=notices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notices.js","names":[],"sources":["../../src/devtools/notices.ts"],"sourcesContent":["/** A session's change notices: the roots it follows, and what changed in each since the last flush. */\nimport { DEVTOOLS_PROTOCOL, type DevtoolsArea, type PageMessage } from './protocol';\nimport type { DevtoolsRoot } from './root';\n\n/** Run `flush` once, soon. The hook's default waits for the next animation frame. */\nexport type DevtoolsSchedule = (flush: () => void) => void;\n\nexport interface Notices {\n /** Trace this root and report its changes, until {@link Notices.unfollow}. */\n follow(root: DevtoolsRoot): void;\n unfollow(rootId: string): void;\n /** The roots followed now. */\n ids(): string[];\n}\n\nexport function createNotices(\n rootOf: (id: string) => DevtoolsRoot | undefined,\n schedule: DevtoolsSchedule,\n send: (m: PageMessage) => void,\n): Notices {\n const following = new Map<string, () => void>();\n const pending = new Map<string, Set<DevtoolsArea>>();\n let scheduled = false;\n\n const flush = (): void => {\n scheduled = false;\n for (const [rootId, areas] of pending) {\n const root = rootOf(rootId);\n if (!root || !following.has(rootId)) continue;\n const versions: Partial<Record<DevtoolsArea, number>> = {};\n for (const area of areas) versions[area] = root.version(area);\n send({ type: 'changed', protocol: DEVTOOLS_PROTOCOL, rootId, areas: versions });\n }\n pending.clear();\n };\n\n return {\n follow(root) {\n if (following.has(root.id)) return;\n const releaseTrace = root.source.trace.watch();\n const releaseCoords = root.source.coords.watch();\n const releaseHistory = root.source.history?.watch();\n const off = root.subscribe((area) => {\n let areas = pending.get(root.id);\n if (!areas) pending.set(root.id, (areas = new Set()));\n areas.add(area);\n if (!scheduled) {\n scheduled = true;\n schedule(flush);\n }\n });\n following.set(root.id, () => { releaseTrace(); releaseCoords(); releaseHistory?.(); off(); });\n },\n unfollow(rootId) {\n following.get(rootId)?.();\n following.delete(rootId);\n pending.delete(rootId);\n },\n ids: () => [...following.keys()],\n };\n}\n"],"mappings":";;;;AAeA,SAAgB,cACd,QACA,UACA,MACS;CACT,MAAM,4BAAY,IAAI,IAAwB;CAC9C,MAAM,0BAAU,IAAI,IAA+B;CACnD,IAAI,YAAY;CAEhB,MAAM,cAAoB;EACxB,YAAY;EACZ,KAAK,MAAM,CAAC,QAAQ,UAAU,SAAS;GACrC,MAAM,OAAO,OAAO,MAAM;GAC1B,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,MAAM,GAAG;GACrC,MAAM,WAAkD,CAAC;GACzD,KAAK,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK,QAAQ,IAAI;GAC5D,KAAK;IAAE,MAAM;IAAW,UAAU;IAAmB;IAAQ,OAAO;GAAS,CAAC;EAChF;EACA,QAAQ,MAAM;CAChB;CAEA,OAAO;EACL,OAAO,MAAM;GACX,IAAI,UAAU,IAAI,KAAK,EAAE,GAAG;GAC5B,MAAM,eAAe,KAAK,OAAO,MAAM,MAAM;GAC7C,MAAM,gBAAgB,KAAK,OAAO,OAAO,MAAM;GAC/C,MAAM,iBAAiB,KAAK,OAAO,SAAS,MAAM;GAClD,MAAM,MAAM,KAAK,WAAW,SAAS;IACnC,IAAI,QAAQ,QAAQ,IAAI,KAAK,EAAE;IAC/B,IAAI,CAAC,OAAO,QAAQ,IAAI,KAAK,IAAK,wBAAQ,IAAI,IAAI,CAAE;IACpD,MAAM,IAAI,IAAI;IACd,IAAI,CAAC,WAAW;KACd,YAAY;KACZ,SAAS,KAAK;IAChB;GACF,CAAC;GACD,UAAU,IAAI,KAAK,UAAU;IAAE,aAAa;IAAG,cAAc;IAAG,iBAAiB;IAAG,IAAI;GAAG,CAAC;EAC9F;EACA,SAAS,QAAQ;GACf,UAAU,IAAI,MAAM,CAAC,GAAG;GACxB,UAAU,OAAO,MAAM;GACvB,QAAQ,OAAO,MAAM;EACvB;EACA,WAAW,CAAC,GAAG,UAAU,KAAK,CAAC;CACjC;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","names":[],"sources":["../../src/devtools/protocol.ts"],"sourcesContent":["/**\n * The messages a devtools panel and a page running weasel exchange. Plain\n * data only, so the same messages cross a direct call or `window.postMessage`.\n */\nimport type { DebugFeature } from '../debug/types';\nimport type { SerializedValue } from './serialize';\n\n/** Bumped on any change a panel built against the previous number would misread. */\nexport const DEVTOOLS_PROTOCOL = 1;\n\n/** The areas of a root a `changed` notice reports. */\nexport type DevtoolsArea = 'scene' | 'selection' | 'view' | 'tool' | 'trace' | 'registry' | 'history';\n\n/** One mounted `<SceneCanvas>`. */\nexport interface DevtoolsRootInfo {\n id: string;\n /** The canvas's `aria-label`, else its DOM id, else its root id. */\n label: string;\n dimension: '2d' | '3d';\n}\n\n/** Debug overlay features a panel turns on or off over the canvas's own `debug` prop. */\nexport type DevtoolsOverlays = Partial<Record<DebugFeature, boolean>>;\n\n/** A request a panel sends about one root. */\nexport type DevtoolsRequest = { protocol: number; requestId: number; rootId: string } & (\n | { type: 'get-children'; nodeId?: string }\n | { type: 'get-node'; nodeId: string }\n | { type: 'get-state' }\n /** Coord records come back only when `coordCursor` is given. */\n | { type: 'get-trace'; cursor: number; coordCursor?: number }\n | { type: 'get-frame' }\n | { type: 'get-registry' }\n /** The stack's entry labels come back only when `checkpoints` is true. */\n | { type: 'get-history'; cursor: number; checkpoints?: boolean }\n | { type: 'select'; ids: string[] }\n | { type: 'highlight'; ids: string[] }\n | { type: 'set-tool'; toolId: string | null }\n | { type: 'set-overlays'; overlays: DevtoolsOverlays }\n);\n\n/** Every message a panel sends the page. */\nexport type PanelMessage =\n | { type: 'yo'; protocol: number }\n /** The panel is closing: drop its overlays and highlight, and stop tracing for it. */\n | { type: 'bye'; protocol: number }\n | DevtoolsRequest;\n\n/** Every message the page sends a panel. */\nexport type PageMessage =\n | { type: 'sup'; protocol: number; kitVersion: string; roots: DevtoolsRootInfo[] }\n | { type: 'root-added'; protocol: number; root: DevtoolsRootInfo }\n | { type: 'root-removed'; protocol: number; rootId: string }\n /** Each changed area with its new version. At most one per root per frame. */\n | { type: 'changed'; protocol: number; rootId: string; areas: Partial<Record<DevtoolsArea, number>> }\n | { type: 'result'; protocol: number; requestId: number; result: DevtoolsResult }\n /** `requestId` is null for a message that was not a request. */\n | { type: 'error'; protocol: number; requestId: number | null; message: string };\n\n/** One child row of the scene tree. `nodeId` absent asks for the top level. */\nexport interface DevtoolsNodeSummary {\n id: string;\n kind: 'leaf' | 'container';\n layer: string;\n childCount: number;\n hidden: boolean;\n locked: boolean;\n pickable: boolean;\n}\n\n/** A node as `get-node` returns it: its row in the tree, plus its parent, pose and data. */\nexport interface DevtoolsNodeDetail extends DevtoolsNodeSummary {\n parent: string | null;\n pose: SerializedValue;\n data: SerializedValue;\n}\n\n/** What `get-state` returns about a root. */\nexport interface DevtoolsRootState {\n selection: string[];\n view: SerializedValue;\n activeTool: string | null;\n tools: string[];\n /** The debug overlay features in effect: the canvas's own, with the panel's over them. */\n overlays: DevtoolsOverlays;\n /** Probes registered through the test hook, by name. */\n probes: Record<string, SerializedValue>;\n}\n\n/** What `get-trace` returns: the records after the cursor, and the cursor to send next. */\nexport interface DevtoolsTraceSlice {\n entries: SerializedValue[];\n cursor: number;\n /** What a press at the pointer would do, or null when the pointer is off the canvas. */\n live: SerializedValue;\n coords?: { entries: SerializedValue[]; cursor: number };\n}\n\n/** One gesture-to-action binding, as a tool, an always-on entry or an action declares it. */\nexport interface DevtoolsBinding {\n actionId: string;\n /** The `GestureSpec` as written. */\n spec: SerializedValue;\n /** The spec in the route grammar, one string per route it expands to. */\n routes: string[];\n /** The binding's `BindingOpts`: params, roles, views. */\n opts: SerializedValue;\n}\n\n/** A tool or other contribution the canvas's dispatcher assembles bindings from. */\nexport interface DevtoolsToolEntry {\n id: string;\n /** A switchable tool, an always-on entry, or one a `features` preset brought. */\n slot: 'tool' | 'ambient' | 'contribution';\n label: string;\n /** The icon's qualified name. */\n icon: string | null;\n group: string | null;\n shortcut: string | null;\n /** The key that holds it engaged while pressed. */\n hotkey: string | null;\n hidden: boolean;\n cursor: SerializedValue;\n eligibility: SerializedValue;\n bindings: DevtoolsBinding[];\n /** Ids of the actions it brings with it. */\n actions: string[];\n /** Names of the deps it registers. */\n deps: string[];\n hasOverlay: boolean;\n}\n\n/** A registered action. `enabled` and `active` are asked when the registry is read. */\nexport interface DevtoolsActionEntry {\n id: string;\n label: string;\n icon: string | null;\n group: string | null;\n tags: string[];\n shortcut: string | null;\n /** Which binding scope its own bindings ride. */\n scope: 'hotkey' | 'ambient';\n invoker: 'immediate' | 'ongoing' | null;\n requires: string[];\n variants: { key: string; label: string; icon: string | null; params: SerializedValue }[];\n /** `true`, or the reason it is disabled. */\n enabled: true | string;\n /** Null for an action with no pressed state. */\n active: boolean | null;\n hasPreview: boolean;\n /** The eligibility rule, or null for always eligible. */\n eligible: SerializedValue;\n bindings: DevtoolsBinding[];\n}\n\n/** A dep name the canvas's registry answers. */\nexport interface DevtoolsDepEntry {\n name: string;\n /** How many scopes above the canvas's own its live source sits: 0 for the canvas's. */\n depth: number;\n /** How many sources are stacked under the name there, the live one included. */\n stacked: number;\n}\n\n/** What `get-registry` returns: what one canvas has registered. */\nexport interface DevtoolsRegistry {\n tools: DevtoolsToolEntry[];\n actions: DevtoolsActionEntry[];\n deps: DevtoolsDepEntry[];\n /** The node routing kinds a binding's `kind:` target can name, in classify order. */\n routingKinds: string[];\n}\n\n/** One op of a recorded history step. */\nexport interface DevtoolsHistoryOp {\n /** The op's registered name, `'kit:setPose'` and the like; `'?'` for an op with none. */\n kind: string;\n /** The node ids its args address. */\n targets: string[];\n summary: SerializedValue;\n}\n\n/** One change to a scene's history: an edit recorded, merged, undone, redone or jumped across. */\nexport interface DevtoolsHistoryRecord {\n ts: number;\n step: 'push' | 'coalesce' | 'undo' | 'redo' | 'goto' | 'branch' | 'prune' | 'clear' | 'restore';\n /** The entries the step pushed, merged into or walked across, in the order it touched them. */\n entries: { id: number; label: string; opCount: number; ops: DevtoolsHistoryOp[] }[];\n /** Where the history stood after the step: entries applied, and entries in all. */\n position: { index: number; total: number };\n}\n\n/** What `get-history` returns: the steps after the cursor, the cursor to send next, and where the history stands. */\nexport interface DevtoolsHistorySlice {\n entries: DevtoolsHistoryRecord[];\n cursor: number;\n position: { index: number; total: number; canUndo: boolean; canRedo: boolean };\n /** Every entry on the stacks, oldest applied first, then the redoable ones. */\n checkpoints?: { id: string; label: string }[];\n}\n\n/** The body of a `result` reply; which one depends on the request it answers. */\nexport type DevtoolsResult =\n | DevtoolsNodeSummary[]\n | DevtoolsNodeDetail\n | DevtoolsRootState\n | DevtoolsTraceSlice\n | DevtoolsRegistry\n | DevtoolsHistorySlice\n | SerializedValue\n | null;\n"],"mappings":";;AAQA,IAAa,oBAAoB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { serialize } from "./serialize.js";
|
|
2
|
+
import { actionBindings, buildDepsFromRequires, evaluateActive, evaluateEnabled, overriddenBindings, routesForSpec } from "@weasel-js/routing";
|
|
3
|
+
|
|
4
|
+
//#region src/devtools/registry.ts
|
|
5
|
+
/** What one canvas has registered — its tools, actions, deps and node kinds — as plain data for `get-registry`. */
|
|
6
|
+
function routesOf(binding) {
|
|
7
|
+
try {
|
|
8
|
+
return [...routesForSpec(binding.spec)];
|
|
9
|
+
} catch {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function bindingOf(binding) {
|
|
14
|
+
return {
|
|
15
|
+
actionId: binding.actionId,
|
|
16
|
+
spec: serialize(binding.spec),
|
|
17
|
+
routes: routesOf(binding),
|
|
18
|
+
opts: serialize(binding.opts)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function toolOf(entry, slot, overrides) {
|
|
22
|
+
const p = entry.presentation;
|
|
23
|
+
return {
|
|
24
|
+
id: entry.id,
|
|
25
|
+
slot,
|
|
26
|
+
label: p?.label ?? entry.id,
|
|
27
|
+
icon: p?.icon ?? null,
|
|
28
|
+
group: p?.group ?? null,
|
|
29
|
+
shortcut: p?.shortcut ?? null,
|
|
30
|
+
hotkey: entry.eligibility?.offhand ?? null,
|
|
31
|
+
hidden: p?.hide === true,
|
|
32
|
+
cursor: serialize(entry.cursor),
|
|
33
|
+
eligibility: serialize(entry.eligibility),
|
|
34
|
+
bindings: overriddenBindings(entry.bindings ?? [], entry.id, overrides).map(bindingOf),
|
|
35
|
+
actions: (entry.actions ?? []).map((a) => a.id),
|
|
36
|
+
deps: Object.keys(entry.deps ?? {}),
|
|
37
|
+
hasOverlay: entry.overlay !== void 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function actionOf(action, deps) {
|
|
41
|
+
const bag = deps ? buildDepsFromRequires(action, deps) : void 0;
|
|
42
|
+
const enabled = evaluateEnabled(action, bag);
|
|
43
|
+
const rule = action.eligible;
|
|
44
|
+
return {
|
|
45
|
+
id: action.id,
|
|
46
|
+
label: action.label ?? action.id,
|
|
47
|
+
icon: action.icon ?? null,
|
|
48
|
+
group: action.group ?? null,
|
|
49
|
+
tags: [...action.tags ?? []],
|
|
50
|
+
shortcut: action.shortcut ?? null,
|
|
51
|
+
scope: action.scope === "hotkey" ? "hotkey" : "ambient",
|
|
52
|
+
invoker: action.invoker?.timing ?? null,
|
|
53
|
+
requires: [...action.requires ?? []],
|
|
54
|
+
variants: (action.variants ?? []).map((v) => ({
|
|
55
|
+
key: v.key,
|
|
56
|
+
label: v.label,
|
|
57
|
+
icon: v.icon ?? null,
|
|
58
|
+
params: serialize(v.params)
|
|
59
|
+
})),
|
|
60
|
+
enabled: enabled.enabled ? true : enabled.reason ?? "disabled",
|
|
61
|
+
active: evaluateActive(action, bag) ?? null,
|
|
62
|
+
hasPreview: action.preview !== void 0,
|
|
63
|
+
eligible: serialize(typeof rule === "function" ? rule.rule : rule ?? null),
|
|
64
|
+
bindings: actionBindings(action).map(bindingOf)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function describeRegistry(inputs) {
|
|
68
|
+
const seen = /* @__PURE__ */ new Set();
|
|
69
|
+
const tools = [];
|
|
70
|
+
const add = (entries, slot) => {
|
|
71
|
+
for (const e of entries) {
|
|
72
|
+
if (seen.has(e.id)) continue;
|
|
73
|
+
seen.add(e.id);
|
|
74
|
+
tools.push(toolOf(e, slot, inputs.overrides));
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
add(Object.values(inputs.tools.registry), "tool");
|
|
78
|
+
add(inputs.tools.ambient, "ambient");
|
|
79
|
+
add(inputs.contributions, "contribution");
|
|
80
|
+
return {
|
|
81
|
+
tools,
|
|
82
|
+
actions: (inputs.actions?.list() ?? []).map((a) => actionOf(a, inputs.deps)),
|
|
83
|
+
deps: (inputs.deps?.list?.() ?? []).map((d) => ({ ...d })),
|
|
84
|
+
routingKinds: [...inputs.routingKinds]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
export { describeRegistry };
|
|
90
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../../src/devtools/registry.ts"],"sourcesContent":["/** What one canvas has registered — its tools, actions, deps and node kinds — as plain data for `get-registry`. */\nimport {\n actionBindings, buildDepsFromRequires, evaluateActive, evaluateEnabled, overriddenBindings, routesForSpec,\n type Action, type ActionSource, type Contribution, type DepRegistry, type GestureBinding, type ResolvedBindingOverrides,\n} from '@weasel-js/routing';\nimport type {\n DevtoolsActionEntry, DevtoolsBinding, DevtoolsRegistry, DevtoolsToolEntry,\n} from './protocol';\nimport { serialize } from './serialize';\n\ntype Entry = Contribution<unknown> & { cursor?: unknown };\n\n/** The live registries {@link describeRegistry} reads. */\nexport interface RegistryInputs {\n tools: { registry: Readonly<Record<string, Entry>>; ambient: readonly Entry[] };\n /** The entries a `features` preset brought beside the tools. */\n contributions: readonly Entry[];\n actions: ActionSource | null;\n /** Binding overrides in force, applied to the entries' bindings; `actions`\n * lists its own already overridden. */\n overrides?: ResolvedBindingOverrides;\n deps: DepRegistry | null;\n routingKinds: readonly string[];\n}\n\nfunction routesOf(binding: GestureBinding): string[] {\n try {\n return [...routesForSpec(binding.spec)];\n } catch {\n return [];\n }\n}\n\nfunction bindingOf(binding: GestureBinding): DevtoolsBinding {\n return {\n actionId: binding.actionId,\n spec: serialize(binding.spec),\n routes: routesOf(binding),\n opts: serialize(binding.opts),\n };\n}\n\nfunction toolOf(entry: Entry, slot: DevtoolsToolEntry['slot'], overrides: ResolvedBindingOverrides | undefined): DevtoolsToolEntry {\n const p = entry.presentation;\n return {\n id: entry.id,\n slot,\n label: p?.label ?? entry.id,\n icon: p?.icon ?? null,\n group: p?.group ?? null,\n shortcut: p?.shortcut ?? null,\n hotkey: entry.eligibility?.offhand ?? null,\n hidden: p?.hide === true,\n cursor: serialize(entry.cursor),\n eligibility: serialize(entry.eligibility),\n bindings: overriddenBindings(entry.bindings ?? [], entry.id, overrides).map(bindingOf),\n actions: (entry.actions ?? []).map((a) => a.id),\n deps: Object.keys(entry.deps ?? {}),\n hasOverlay: entry.overlay !== undefined,\n };\n}\n\nfunction actionOf(action: Action, deps: DepRegistry | null): DevtoolsActionEntry {\n const bag = deps ? buildDepsFromRequires(action, deps) : undefined;\n const enabled = evaluateEnabled(action, bag);\n const rule: unknown = action.eligible;\n return {\n id: action.id,\n label: action.label ?? action.id,\n icon: action.icon ?? null,\n group: action.group ?? null,\n tags: [...(action.tags ?? [])],\n shortcut: action.shortcut ?? null,\n scope: action.scope === 'hotkey' ? 'hotkey' : 'ambient',\n invoker: action.invoker?.timing ?? null,\n requires: [...(action.requires ?? [])],\n variants: (action.variants ?? []).map((v) => ({\n key: v.key, label: v.label, icon: v.icon ?? null, params: serialize(v.params),\n })),\n enabled: enabled.enabled ? true : (enabled.reason ?? 'disabled'),\n active: evaluateActive(action, bag) ?? null,\n hasPreview: action.preview !== undefined,\n // A fluent condition is callable and carries its rule tree on `.rule`.\n eligible: serialize(typeof rule === 'function' ? (rule as { rule?: unknown }).rule : (rule ?? null)),\n bindings: actionBindings(action).map(bindingOf),\n };\n}\n\nexport function describeRegistry(inputs: RegistryInputs): DevtoolsRegistry {\n const seen = new Set<string>();\n const tools: DevtoolsToolEntry[] = [];\n const add = (entries: readonly Entry[], slot: DevtoolsToolEntry['slot']): void => {\n for (const e of entries) {\n if (seen.has(e.id)) continue;\n seen.add(e.id);\n tools.push(toolOf(e, slot, inputs.overrides));\n }\n };\n add(Object.values(inputs.tools.registry), 'tool');\n add(inputs.tools.ambient, 'ambient');\n add(inputs.contributions, 'contribution');\n return {\n tools,\n actions: (inputs.actions?.list() ?? []).map((a) => actionOf(a, inputs.deps)),\n deps: (inputs.deps?.list?.() ?? []).map((d) => ({ ...d })),\n routingKinds: [...inputs.routingKinds],\n };\n}\n"],"mappings":";;;;;AAyBA,SAAS,SAAS,SAAmC;CACnD,IAAI;EACF,OAAO,CAAC,GAAG,cAAc,QAAQ,IAAI,CAAC;CACxC,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,UAAU,SAA0C;CAC3D,OAAO;EACL,UAAU,QAAQ;EAClB,MAAM,UAAU,QAAQ,IAAI;EAC5B,QAAQ,SAAS,OAAO;EACxB,MAAM,UAAU,QAAQ,IAAI;CAC9B;AACF;AAEA,SAAS,OAAO,OAAc,MAAiC,WAAoE;CACjI,MAAM,IAAI,MAAM;CAChB,OAAO;EACL,IAAI,MAAM;EACV;EACA,OAAO,GAAG,SAAS,MAAM;EACzB,MAAM,GAAG,QAAQ;EACjB,OAAO,GAAG,SAAS;EACnB,UAAU,GAAG,YAAY;EACzB,QAAQ,MAAM,aAAa,WAAW;EACtC,QAAQ,GAAG,SAAS;EACpB,QAAQ,UAAU,MAAM,MAAM;EAC9B,aAAa,UAAU,MAAM,WAAW;EACxC,UAAU,mBAAmB,MAAM,YAAY,CAAC,GAAG,MAAM,IAAI,SAAS,CAAC,CAAC,IAAI,SAAS;EACrF,UAAU,MAAM,WAAW,CAAC,EAAA,CAAG,KAAK,MAAM,EAAE,EAAE;EAC9C,MAAM,OAAO,KAAK,MAAM,QAAQ,CAAC,CAAC;EAClC,YAAY,MAAM,YAAY;CAChC;AACF;AAEA,SAAS,SAAS,QAAgB,MAA+C;CAC/E,MAAM,MAAM,OAAO,sBAAsB,QAAQ,IAAI,IAAI;CACzD,MAAM,UAAU,gBAAgB,QAAQ,GAAG;CAC3C,MAAM,OAAgB,OAAO;CAC7B,OAAO;EACL,IAAI,OAAO;EACX,OAAO,OAAO,SAAS,OAAO;EAC9B,MAAM,OAAO,QAAQ;EACrB,OAAO,OAAO,SAAS;EACvB,MAAM,CAAC,GAAI,OAAO,QAAQ,CAAC,CAAE;EAC7B,UAAU,OAAO,YAAY;EAC7B,OAAO,OAAO,UAAU,WAAW,WAAW;EAC9C,SAAS,OAAO,SAAS,UAAU;EACnC,UAAU,CAAC,GAAI,OAAO,YAAY,CAAC,CAAE;EACrC,WAAW,OAAO,YAAY,CAAC,EAAA,CAAG,KAAK,OAAO;GAC5C,KAAK,EAAE;GAAK,OAAO,EAAE;GAAO,MAAM,EAAE,QAAQ;GAAM,QAAQ,UAAU,EAAE,MAAM;EAC9E,EAAE;EACF,SAAS,QAAQ,UAAU,OAAQ,QAAQ,UAAU;EACrD,QAAQ,eAAe,QAAQ,GAAG,KAAK;EACvC,YAAY,OAAO,YAAY;EAE/B,UAAU,UAAU,OAAO,SAAS,aAAc,KAA4B,OAAQ,QAAQ,IAAK;EACnG,UAAU,eAAe,MAAM,CAAC,CAAC,IAAI,SAAS;CAChD;AACF;AAEA,SAAgB,iBAAiB,QAA0C;CACzE,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,QAA6B,CAAC;CACpC,MAAM,OAAO,SAA2B,SAA0C;EAChF,KAAK,MAAM,KAAK,SAAS;GACvB,IAAI,KAAK,IAAI,EAAE,EAAE,GAAG;GACpB,KAAK,IAAI,EAAE,EAAE;GACb,MAAM,KAAK,OAAO,GAAG,MAAM,OAAO,SAAS,CAAC;EAC9C;CACF;CACA,IAAI,OAAO,OAAO,OAAO,MAAM,QAAQ,GAAG,MAAM;CAChD,IAAI,OAAO,MAAM,SAAS,SAAS;CACnC,IAAI,OAAO,eAAe,cAAc;CACxC,OAAO;EACL;EACA,UAAU,OAAO,SAAS,KAAK,KAAK,CAAC,EAAA,CAAG,KAAK,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC;EAC3E,OAAO,OAAO,MAAM,OAAO,KAAK,CAAC,EAAA,CAAG,KAAK,OAAO,EAAE,GAAG,EAAE,EAAE;EACzD,cAAc,CAAC,GAAG,OAAO,YAAY;CACvC;AACF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//#region src/devtools/root.ts
|
|
2
|
+
var nextId = 1;
|
|
3
|
+
/** A root over `source`, with a fresh page-unique id. */
|
|
4
|
+
function createDevtoolsRoot(source) {
|
|
5
|
+
const id = `root-${nextId++}`;
|
|
6
|
+
const versions = {
|
|
7
|
+
scene: 0,
|
|
8
|
+
selection: 0,
|
|
9
|
+
view: 0,
|
|
10
|
+
tool: 0,
|
|
11
|
+
trace: 0,
|
|
12
|
+
registry: 0,
|
|
13
|
+
history: 0
|
|
14
|
+
};
|
|
15
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
16
|
+
const notify = (area) => {
|
|
17
|
+
versions[area]++;
|
|
18
|
+
for (const l of [...listeners]) l(area);
|
|
19
|
+
};
|
|
20
|
+
let detach = null;
|
|
21
|
+
let watchedScene = null;
|
|
22
|
+
let offScene = null;
|
|
23
|
+
const followScene = () => {
|
|
24
|
+
const s = detach ? source.scene() : null;
|
|
25
|
+
if (s === watchedScene) return;
|
|
26
|
+
offScene?.();
|
|
27
|
+
watchedScene = s;
|
|
28
|
+
if (!s) {
|
|
29
|
+
offScene = null;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let content = s.getContentVersion();
|
|
33
|
+
offScene = s.subscribe(() => {
|
|
34
|
+
const next = s.getContentVersion();
|
|
35
|
+
if (next === content) return;
|
|
36
|
+
content = next;
|
|
37
|
+
notify("scene");
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const attach = () => {
|
|
41
|
+
const offs = [
|
|
42
|
+
source.trace.subscribe(() => notify("trace")),
|
|
43
|
+
source.history?.subscribe(() => notify("history")),
|
|
44
|
+
source.subscribeRegistry?.(() => notify("registry"))
|
|
45
|
+
];
|
|
46
|
+
detach = () => {
|
|
47
|
+
for (const off of offs) off?.();
|
|
48
|
+
detach = null;
|
|
49
|
+
followScene();
|
|
50
|
+
};
|
|
51
|
+
followScene();
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
source,
|
|
56
|
+
info: () => ({
|
|
57
|
+
id,
|
|
58
|
+
label: source.label() || id,
|
|
59
|
+
dimension: source.dimension
|
|
60
|
+
}),
|
|
61
|
+
probes: /* @__PURE__ */ new Map(),
|
|
62
|
+
version: (area) => versions[area],
|
|
63
|
+
notify(area) {
|
|
64
|
+
if (area === "scene") followScene();
|
|
65
|
+
notify(area);
|
|
66
|
+
},
|
|
67
|
+
subscribe(listener) {
|
|
68
|
+
listeners.add(listener);
|
|
69
|
+
if (!detach) attach();
|
|
70
|
+
return () => {
|
|
71
|
+
listeners.delete(listener);
|
|
72
|
+
if (listeners.size === 0) detach?.();
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { createDevtoolsRoot };
|
|
80
|
+
//# sourceMappingURL=root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.js","names":[],"sources":["../../src/devtools/root.ts"],"sourcesContent":["/**\n * A root: what one mounted `<SceneCanvas>` exposes to the devtools hook and to\n * the test hook. The canvas supplies live getters; the root adds change\n * versions and the probe registry.\n */\nimport type { DispatchTrace, TraceRing } from '@weasel-js/routing';\nimport type { Scene } from 'core/scene/types';\nimport type { CoordTraceEntry } from '../canvas/SceneCanvas/coordTrace';\nimport type { DebugConfig } from '../debug/types';\nimport type {\n DevtoolsArea, DevtoolsHistoryRecord, DevtoolsOverlays, DevtoolsRegistry, DevtoolsRootInfo,\n} from './protocol';\n\n/** What a canvas hands {@link createDevtoolsRoot}. Every getter reads the latest committed value. */\nexport interface DevtoolsRootSource {\n label(): string;\n readonly dimension: '2d' | '3d';\n scene(): Scene<unknown, string, unknown> | null;\n selection(): readonly string[];\n select(ids: readonly string[]): void;\n view(): unknown;\n activeTool(): string | null;\n tools(): readonly string[];\n setTool(id: string | null): void;\n trace: DispatchTrace;\n coords: TraceRing<CoordTraceEntry>;\n /** The debug sink's stats for the last paint, or null while the frame panel is off. */\n frame(): unknown;\n /** The debug overlay config in effect, or null when the overlay is off. */\n overlays(): DebugConfig | null;\n /** Lay the panel's overlay flags and highlight over the canvas's own `debug`; null drops them. */\n setOverride(override: { overlays: DevtoolsOverlays; highlight: readonly string[] } | null): void;\n /** What the canvas has registered, described when asked. Absent, `get-registry` is refused. */\n registry?(): DevtoolsRegistry;\n /** Hear that what {@link DevtoolsRootSource.registry} describes may have changed. Returns the unsubscribe. */\n subscribeRegistry?(listener: () => void): () => void;\n /** The scene's history steps. Absent, `get-history` is refused. */\n history?: TraceRing<DevtoolsHistoryRecord>;\n}\n\n/** One canvas as the devtools hook holds it. */\nexport interface DevtoolsRoot {\n readonly id: string;\n readonly source: DevtoolsRootSource;\n info(): DevtoolsRootInfo;\n /** Name-keyed probes; the test hook's `registerProbe` writes here. */\n readonly probes: Map<string, () => unknown>;\n version(area: DevtoolsArea): number;\n /** Say that `area` changed. The scene and the trace say so themselves while anything listens. */\n notify(area: DevtoolsArea): void;\n /** Hear each change, with the area. Returns the unsubscribe. */\n subscribe(listener: (area: DevtoolsArea) => void): () => void;\n}\n\nlet nextId = 1;\n\n/** A root over `source`, with a fresh page-unique id. */\nexport function createDevtoolsRoot(source: DevtoolsRootSource): DevtoolsRoot {\n const id = `root-${nextId++}`;\n const versions: Record<DevtoolsArea, number> = {\n scene: 0, selection: 0, view: 0, tool: 0, trace: 0, registry: 0, history: 0,\n };\n const listeners = new Set<(area: DevtoolsArea) => void>();\n const notify = (area: DevtoolsArea): void => {\n versions[area]++;\n for (const l of [...listeners]) l(area);\n };\n\n // Attached only while something listens, so a root nobody inspects holds no\n // subscription on a scene that may outlive its canvas.\n let detach: (() => void) | null = null;\n let watchedScene: Scene<unknown, string, unknown> | null = null;\n let offScene: (() => void) | null = null;\n const followScene = (): void => {\n const s = detach ? source.scene() : null;\n if (s === watchedScene) return;\n offScene?.();\n watchedScene = s;\n if (!s) {\n offScene = null;\n return;\n }\n // A selection change notifies the scene's subscribers too; the canvas reports it as `selection`.\n let content = s.getContentVersion();\n offScene = s.subscribe(() => {\n const next = s.getContentVersion();\n if (next === content) return;\n content = next;\n notify('scene');\n });\n };\n const attach = (): void => {\n const offs = [\n source.trace.subscribe(() => notify('trace')),\n source.history?.subscribe(() => notify('history')),\n source.subscribeRegistry?.(() => notify('registry')),\n ];\n detach = () => {\n for (const off of offs) off?.();\n detach = null;\n followScene();\n };\n followScene();\n };\n\n return {\n id,\n source,\n info: () => ({ id, label: source.label() || id, dimension: source.dimension }),\n probes: new Map(),\n version: (area) => versions[area],\n notify(area) {\n if (area === 'scene') followScene();\n notify(area);\n },\n subscribe(listener) {\n listeners.add(listener);\n if (!detach) attach();\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) detach?.();\n };\n },\n };\n}\n"],"mappings":";AAsDA,IAAI,SAAS;;AAGb,SAAgB,mBAAmB,QAA0C;CAC3E,MAAM,KAAK,QAAQ;CACnB,MAAM,WAAyC;EAC7C,OAAO;EAAG,WAAW;EAAG,MAAM;EAAG,MAAM;EAAG,OAAO;EAAG,UAAU;EAAG,SAAS;CAC5E;CACA,MAAM,4BAAY,IAAI,IAAkC;CACxD,MAAM,UAAU,SAA6B;EAC3C,SAAS,KAAK;EACd,KAAK,MAAM,KAAK,CAAC,GAAG,SAAS,GAAG,EAAE,IAAI;CACxC;CAIA,IAAI,SAA8B;CAClC,IAAI,eAAuD;CAC3D,IAAI,WAAgC;CACpC,MAAM,oBAA0B;EAC9B,MAAM,IAAI,SAAS,OAAO,MAAM,IAAI;EACpC,IAAI,MAAM,cAAc;EACxB,WAAW;EACX,eAAe;EACf,IAAI,CAAC,GAAG;GACN,WAAW;GACX;EACF;EAEA,IAAI,UAAU,EAAE,kBAAkB;EAClC,WAAW,EAAE,gBAAgB;GAC3B,MAAM,OAAO,EAAE,kBAAkB;GACjC,IAAI,SAAS,SAAS;GACtB,UAAU;GACV,OAAO,OAAO;EAChB,CAAC;CACH;CACA,MAAM,eAAqB;EACzB,MAAM,OAAO;GACX,OAAO,MAAM,gBAAgB,OAAO,OAAO,CAAC;GAC5C,OAAO,SAAS,gBAAgB,OAAO,SAAS,CAAC;GACjD,OAAO,0BAA0B,OAAO,UAAU,CAAC;EACrD;EACA,eAAe;GACb,KAAK,MAAM,OAAO,MAAM,MAAM;GAC9B,SAAS;GACT,YAAY;EACd;EACA,YAAY;CACd;CAEA,OAAO;EACL;EACA;EACA,aAAa;GAAE;GAAI,OAAO,OAAO,MAAM,KAAK;GAAI,WAAW,OAAO;EAAU;EAC5E,wBAAQ,IAAI,IAAI;EAChB,UAAU,SAAS,SAAS;EAC5B,OAAO,MAAM;GACX,IAAI,SAAS,SAAS,YAAY;GAClC,OAAO,IAAI;EACb;EACA,UAAU,UAAU;GAClB,UAAU,IAAI,QAAQ;GACtB,IAAI,CAAC,QAAQ,OAAO;GACpB,aAAa;IACX,UAAU,OAAO,QAAQ;IACzB,IAAI,UAAU,SAAS,GAAG,SAAS;GACrC;EACF;CACF;AACF"}
|