@weasel-js/core 1.10.0 → 1.11.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 +755 -0
- package/README.md +45 -11
- package/dist/WeaselProvider.js +25 -9
- package/dist/WeaselProvider.js.map +1 -1
- package/dist/affordances/composeAffordanceLayer.js +217 -140
- package/dist/affordances/composeAffordanceLayer.js.map +1 -1
- package/dist/affordances/cornerResize.js +92 -50
- package/dist/affordances/cornerResize.js.map +1 -1
- package/dist/affordances/hitAffordanceRegions.js +152 -73
- package/dist/affordances/hitAffordanceRegions.js.map +1 -1
- package/dist/affordances/pathAnchors.js +148 -51
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/affordances/rotateCursor.js +18 -0
- package/dist/affordances/rotateCursor.js.map +1 -0
- package/dist/affordances/rotationHandle.js +83 -63
- package/dist/affordances/rotationHandle.js.map +1 -1
- package/dist/animation/behaviors/coast.js +20 -14
- package/dist/animation/behaviors/coast.js.map +1 -1
- package/dist/animation/behaviors/coastByWrite.js +98 -70
- package/dist/animation/behaviors/coastByWrite.js.map +1 -1
- package/dist/animation/behaviors/coastOnTargets.js +115 -67
- package/dist/animation/behaviors/coastOnTargets.js.map +1 -1
- package/dist/animation/behaviors/momentum.js +88 -53
- package/dist/animation/behaviors/momentum.js.map +1 -1
- package/dist/animation/clipTargets.js +14 -7
- package/dist/animation/clipTargets.js.map +1 -1
- package/dist/animation/departures.js +116 -0
- package/dist/animation/departures.js.map +1 -0
- package/dist/animation/index.js +18 -15
- package/dist/animation/poseHelpers.js +147 -107
- package/dist/animation/poseHelpers.js.map +1 -1
- package/dist/animation/poseTarget.js +158 -85
- package/dist/animation/poseTarget.js.map +1 -1
- package/dist/animation/poseTransition.js +64 -0
- package/dist/animation/poseTransition.js.map +1 -0
- package/dist/animation/reflow.js +208 -120
- package/dist/animation/reflow.js.map +1 -1
- package/dist/animation/rewind.js +76 -45
- package/dist/animation/rewind.js.map +1 -1
- package/dist/animation/rig/bindRig.js +135 -82
- package/dist/animation/rig/bindRig.js.map +1 -1
- package/dist/animation/rig/rigNode.js +120 -69
- package/dist/animation/rig/rigNode.js.map +1 -1
- package/dist/animation/rig/rigSeat.js +70 -17
- package/dist/animation/rig/rigSeat.js.map +1 -1
- package/dist/animation/rig/skinBinding.js +59 -39
- package/dist/animation/rig/skinBinding.js.map +1 -1
- package/dist/animation/rig/useRig.js +44 -30
- package/dist/animation/rig/useRig.js.map +1 -1
- package/dist/animation/wrappers/animateLifecycle.js +51 -35
- package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
- package/dist/animation/wrappers/animateOnSetPose.js +55 -32
- package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
- package/dist/animation/wrappers/instantPose.js +13 -8
- package/dist/animation/wrappers/instantPose.js.map +1 -1
- package/dist/animation/writtenPoseTarget.js +44 -22
- package/dist/animation/writtenPoseTarget.js.map +1 -1
- package/dist/{autoPoseDescriptor-DHg5KqaJ.d.ts → autoPoseDescriptor-CZ1eXbzY.d.ts} +1 -1
- package/dist/barrel/canvas.js +41 -31
- package/dist/barrel/chrome.js +19 -16
- package/dist/barrel/icons.js +6 -0
- package/dist/barrel/input.js +19 -18
- package/dist/barrel/interactions.js +40 -38
- package/dist/barrel/paint.js +12 -11
- package/dist/barrel/paths.js +39 -12
- package/dist/barrel/renderer.js +24 -14
- package/dist/barrel/routing.js +69 -57
- package/dist/barrel/scene.js +48 -37
- package/dist/barrel/text.js +10 -9
- package/dist/barrel/viewport.js +47 -42
- package/dist/canvas/Canvas.js +189 -317
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +273 -202
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/CursorCoordsHud.js +103 -64
- package/dist/canvas/CursorCoordsHud.js.map +1 -1
- package/dist/canvas/DrawCanvas.js +68 -41
- package/dist/canvas/DrawCanvas.js.map +1 -1
- package/dist/canvas/LeanSceneCanvas.js +23 -0
- package/dist/canvas/LeanSceneCanvas.js.map +1 -0
- package/dist/canvas/ModalityHud.js +58 -43
- package/dist/canvas/ModalityHud.js.map +1 -1
- package/dist/canvas/NodeShape.js +137 -60
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/PickHud.js +77 -59
- package/dist/canvas/PickHud.js.map +1 -1
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +9 -6
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/CanvasKitProviders.js +25 -0
- package/dist/canvas/SceneCanvas/CanvasKitProviders.js.map +1 -0
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +10 -6
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/DevHuds.js +47 -32
- package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +72 -36
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +110 -0
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -0
- package/dist/canvas/SceneCanvas/brushOverlay.js +36 -0
- package/dist/canvas/SceneCanvas/brushOverlay.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +72 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -0
- package/dist/canvas/SceneCanvas/contributionFrameHooks.js +54 -32
- package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -1
- package/dist/canvas/SceneCanvas/coordTrace.js +36 -29
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +513 -316
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js +39 -13
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
- package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +83 -47
- package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +83 -127
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/insertPreviewCommands.js +115 -0
- package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
- package/dist/canvas/SceneCanvas/mergeLayers.js +43 -0
- package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -0
- package/dist/canvas/SceneCanvas/namedPresets.js +56 -0
- package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -0
- package/dist/canvas/SceneCanvas/poseGeometry.js +66 -31
- package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
- package/dist/canvas/SceneCanvas/poseRegistrars.js +18 -8
- package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/arrange.js +27 -0
- package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/chrome.js +14 -0
- package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/edit.js +59 -0
- package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/ingest.js +13 -0
- package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/paths.js +67 -0
- package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/select.js +19 -0
- package/dist/canvas/SceneCanvas/presets/select.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/toolDriven.js +20 -0
- package/dist/canvas/SceneCanvas/presets/toolDriven.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/transform.js +41 -0
- package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/view.js +14 -0
- package/dist/canvas/SceneCanvas/presets/view.js.map +1 -0
- package/dist/canvas/SceneCanvas/props.js +19 -35
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +58 -0
- package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +59 -0
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
- package/dist/canvas/SceneCanvas/toolRegistry.js +30 -15
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js +20 -0
- package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js +68 -35
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBakedScene.js +17 -0
- package/dist/canvas/SceneCanvas/useBakedScene.js.map +1 -0
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +65 -0
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +1 -0
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +47 -23
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +29 -14
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasCamera.js +55 -32
- package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +24 -14
- package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasSelection.js +30 -12
- package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +112 -53
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useChromeAffordances.js +31 -0
- package/dist/canvas/SceneCanvas/useChromeAffordances.js.map +1 -0
- package/dist/canvas/SceneCanvas/useContributionRoles.js +107 -56
- package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
- package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +64 -0
- package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -0
- package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +105 -136
- package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useHeldModifiers.js +21 -14
- package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeAtPoint.js +21 -19
- package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js +28 -19
- package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +93 -53
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +62 -35
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +110 -50
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +30 -0
- package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -0
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +40 -0
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -0
- package/dist/canvas/SceneCanvas/useSceneChrome.js +100 -44
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +163 -0
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -0
- package/dist/canvas/SceneCanvas/useScenePicking.js +69 -0
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -0
- package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +28 -17
- package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +158 -111
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +38 -26
- package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +108 -0
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -0
- package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +40 -27
- package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSurfaceRouting.js +29 -0
- package/dist/canvas/SceneCanvas/useSurfaceRouting.js.map +1 -0
- package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js +44 -0
- package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -0
- package/dist/canvas/SceneCanvas/useToolKeybindings.js +28 -0
- package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -0
- package/dist/canvas/SceneCanvas/useViewportActions.js +52 -28
- package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
- package/dist/canvas/SceneCanvas/worldPointAt.js +10 -5
- package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +274 -315
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SceneViewCanvas.js +68 -42
- package/dist/canvas/SceneViewCanvas.js.map +1 -1
- package/dist/canvas/SurfaceCanvas.js +62 -0
- package/dist/canvas/SurfaceCanvas.js.map +1 -0
- package/dist/canvas/accentColor.js +8 -5
- package/dist/canvas/accentColor.js.map +1 -1
- package/dist/canvas/adapterDerivedPath.js +33 -18
- package/dist/canvas/adapterDerivedPath.js.map +1 -1
- package/dist/canvas/adapterPickSource.js +60 -0
- package/dist/canvas/adapterPickSource.js.map +1 -0
- package/dist/canvas/affordanceAt.js +106 -50
- package/dist/canvas/affordanceAt.js.map +1 -1
- package/dist/canvas/buildSceneLayer.js +111 -80
- package/dist/canvas/buildSceneLayer.js.map +1 -1
- package/dist/canvas/buildSceneTree.js +110 -46
- package/dist/canvas/buildSceneTree.js.map +1 -1
- package/dist/canvas/canvasRenderer.js +156 -71
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/colorOverrides.js +18 -10
- package/dist/canvas/colorOverrides.js.map +1 -1
- package/dist/canvas/copiesAbove.js +37 -0
- package/dist/canvas/copiesAbove.js.map +1 -0
- package/dist/canvas/defaultDrawOne.js +56 -31
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/areaSelect.js +30 -12
- package/dist/canvas/deps/areaSelect.js.map +1 -1
- package/dist/canvas/deps/booleans.js +104 -0
- package/dist/canvas/deps/booleans.js.map +1 -0
- package/dist/canvas/deps/changes.js +17 -9
- package/dist/canvas/deps/changes.js.map +1 -1
- package/dist/canvas/deps/debug.js +12 -5
- package/dist/canvas/deps/debug.js.map +1 -1
- package/dist/canvas/deps/dispatchSources.js +27 -0
- package/dist/canvas/deps/dispatchSources.js.map +1 -0
- package/dist/canvas/deps/dispatcher.js +18 -7
- package/dist/canvas/deps/dispatcher.js.map +1 -1
- package/dist/canvas/deps/editAnchors.js +253 -68
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/geometryProjection.js +13 -7
- package/dist/canvas/deps/geometryProjection.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +80 -40
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/ingestion.js +18 -13
- package/dist/canvas/deps/ingestion.js.map +1 -1
- package/dist/canvas/deps/insert.js +205 -111
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/kitSettings.js +16 -0
- package/dist/canvas/deps/kitSettings.js.map +1 -0
- package/dist/canvas/deps/lassoSelect.js +25 -13
- package/dist/canvas/deps/lassoSelect.js.map +1 -1
- package/dist/canvas/deps/layout.js +32 -26
- package/dist/canvas/deps/layout.js.map +1 -1
- package/dist/canvas/deps/nodeAtPoint.js +28 -14
- package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
- package/dist/canvas/deps/pathLeaf.js +66 -0
- package/dist/canvas/deps/pathLeaf.js.map +1 -0
- package/dist/canvas/deps/pathLeafDeps.js +13 -0
- package/dist/canvas/deps/pathLeafDeps.js.map +1 -0
- package/dist/canvas/deps/poseDescriptor.js +10 -8
- package/dist/canvas/deps/poseDescriptor.js.map +1 -1
- package/dist/canvas/deps/previewPaths.js +44 -0
- package/dist/canvas/deps/previewPaths.js.map +1 -0
- package/dist/canvas/deps/resizePolicy.js +32 -25
- package/dist/canvas/deps/resizePolicy.js.map +1 -1
- package/dist/canvas/deps/slice.js +73 -87
- package/dist/canvas/deps/slice.js.map +1 -1
- package/dist/canvas/deps/snap.js +58 -7
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/surface.js +30 -0
- package/dist/canvas/deps/surface.js.map +1 -0
- package/dist/canvas/deps/textEdit.js +21 -13
- package/dist/canvas/deps/textEdit.js.map +1 -1
- package/dist/canvas/deps/view.js +46 -34
- package/dist/canvas/deps/view.js.map +1 -1
- package/dist/canvas/derivedPath.js +158 -50
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/doubleClickTarget.js +20 -0
- package/dist/canvas/doubleClickTarget.js.map +1 -0
- package/dist/canvas/drawEnvelope.js +26 -17
- package/dist/canvas/drawEnvelope.js.map +1 -1
- package/dist/canvas/drawnBounds.js +116 -0
- package/dist/canvas/drawnBounds.js.map +1 -0
- package/dist/canvas/getNodeAtPoint.js +11 -8
- package/dist/canvas/getNodeAtPoint.js.map +1 -1
- package/dist/canvas/hostAnchor.js +35 -18
- package/dist/canvas/hostAnchor.js.map +1 -1
- package/dist/canvas/hud.module.js +25 -14
- package/dist/canvas/hud.module.js.map +1 -1
- package/dist/canvas/insertPreviewExtent.js +81 -58
- package/dist/canvas/insertPreviewExtent.js.map +1 -1
- package/dist/canvas/kitRequirements.js +154 -115
- package/dist/canvas/kitRequirements.js.map +1 -1
- package/dist/canvas/layerHover.js +28 -0
- package/dist/canvas/layerHover.js.map +1 -0
- package/dist/canvas/layerOrder.js +107 -57
- package/dist/canvas/layerOrder.js.map +1 -1
- package/dist/canvas/layerSlots.js +16 -9
- package/dist/canvas/layerSlots.js.map +1 -1
- package/dist/canvas/mountedCanvases.js +23 -13
- package/dist/canvas/mountedCanvases.js.map +1 -1
- package/dist/canvas/nodeShapes/derivedPainter.js +65 -25
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/imagePainter.js +69 -53
- package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/measurePainter.js +58 -0
- package/dist/canvas/nodeShapes/measurePainter.js.map +1 -0
- package/dist/canvas/nodeShapes/memo.js +16 -5
- package/dist/canvas/nodeShapes/memo.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +125 -46
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +41 -27
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/poseBox.js +20 -13
- package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +26 -22
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +67 -46
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/strokedBounds.js +177 -0
- package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -0
- package/dist/canvas/nodeShapes/textPainter.js +170 -37
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
- package/dist/canvas/overChildren.js +40 -0
- package/dist/canvas/overChildren.js.map +1 -0
- package/dist/canvas/overlayRoleStrokes.js +20 -3
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/paintCull.js +24 -12
- package/dist/canvas/paintCull.js.map +1 -1
- package/dist/canvas/paintedCursorLayer.js +59 -35
- package/dist/canvas/paintedCursorLayer.js.map +1 -1
- package/dist/canvas/pathOverlay.js +63 -0
- package/dist/canvas/pathOverlay.js.map +1 -0
- package/dist/canvas/pickReach.js +40 -0
- package/dist/canvas/pickReach.js.map +1 -0
- package/dist/canvas/pickWalk.js +150 -130
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/planeClips.js +39 -22
- package/dist/canvas/planeClips.js.map +1 -1
- package/dist/canvas/poseCascade.js +51 -27
- package/dist/canvas/poseCascade.js.map +1 -1
- package/dist/canvas/poseRotation.js +24 -14
- package/dist/canvas/poseRotation.js.map +1 -1
- package/dist/canvas/rasterReadback.js +23 -15
- package/dist/canvas/rasterReadback.js.map +1 -1
- package/dist/canvas/rasterToPng.js +21 -15
- package/dist/canvas/rasterToPng.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +36 -19
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderNeeds.js +33 -18
- package/dist/canvas/renderNeeds.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +202 -87
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js +96 -96
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneClipboard.js +141 -92
- package/dist/canvas/sceneClipboard.js.map +1 -1
- package/dist/canvas/sceneLayerPaint.js +56 -27
- package/dist/canvas/sceneLayerPaint.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +24 -13
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +85 -55
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/slopsDebugLayer.js +58 -49
- package/dist/canvas/slopsDebugLayer.js.map +1 -1
- package/dist/canvas/surfaceContribution.js +22 -10
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasElements.js +31 -0
- package/dist/canvas/useCanvasElements.js.map +1 -0
- package/dist/canvas/useCanvasHandle.js +69 -0
- package/dist/canvas/useCanvasHandle.js.map +1 -0
- package/dist/canvas/useCanvasPaint.js +91 -0
- package/dist/canvas/useCanvasPaint.js.map +1 -0
- package/dist/canvas/useCanvasRenderer.js +45 -23
- package/dist/canvas/useCanvasRenderer.js.map +1 -1
- package/dist/canvas/useCanvasSurface.js +41 -23
- package/dist/canvas/useCanvasSurface.js.map +1 -1
- package/dist/canvas/useCanvasView.js +80 -50
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useClientToWorld.js +27 -0
- package/dist/canvas/useClientToWorld.js.map +1 -0
- package/dist/canvas/useExtraLayers.js +45 -0
- package/dist/canvas/useExtraLayers.js.map +1 -0
- package/dist/canvas/useFrameLoop.js +109 -49
- package/dist/canvas/useFrameLoop.js.map +1 -1
- package/dist/canvas/useHitObserver.js +22 -15
- package/dist/canvas/useHitObserver.js.map +1 -1
- package/dist/canvas/useHostAnchor.js +83 -53
- package/dist/canvas/useHostAnchor.js.map +1 -1
- package/dist/canvas/useLateContentRedraw.js +21 -14
- package/dist/canvas/useLateContentRedraw.js.map +1 -1
- package/dist/canvas/useLayerStack.js +72 -0
- package/dist/canvas/useLayerStack.js.map +1 -0
- package/dist/canvas/usePaintedCursor.js +28 -0
- package/dist/canvas/usePaintedCursor.js.map +1 -0
- package/dist/canvas/useRedrawOn.js +24 -14
- package/dist/canvas/useRedrawOn.js.map +1 -1
- package/dist/canvas/useSceneAdapter.js +27 -0
- package/dist/canvas/useSceneAdapter.js.map +1 -0
- package/dist/canvas/useSceneLayerList.js +15 -7
- package/dist/canvas/useSceneLayerList.js.map +1 -1
- package/dist/canvas/useSurfaceInput.js +46 -30
- package/dist/canvas/useSurfaceInput.js.map +1 -1
- package/dist/canvas/useSurfaceSize.js +43 -0
- package/dist/canvas/useSurfaceSize.js.map +1 -0
- package/dist/canvas/useToolCursor.js +30 -21
- package/dist/canvas/useToolCursor.js.map +1 -1
- package/dist/canvas/useViewHelpers.js +112 -61
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/canvas/useViewLayerGate.js +29 -0
- package/dist/canvas/useViewLayerGate.js.map +1 -0
- package/dist/canvas/useViewNesting.js +104 -0
- package/dist/canvas/useViewNesting.js.map +1 -0
- package/dist/canvas/useViewRegistrySurface.js +44 -0
- package/dist/canvas/useViewRegistrySurface.js.map +1 -0
- package/dist/canvas/viewInputs.js +14 -11
- package/dist/canvas/viewInputs.js.map +1 -1
- package/dist/canvas/viewRegistry.js +144 -38
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/canvas/watchElementMove.js +71 -33
- package/dist/canvas/watchElementMove.js.map +1 -1
- package/dist/canvas/wrapNodeOutput.js +21 -9
- package/dist/canvas/wrapNodeOutput.js.map +1 -1
- package/dist/clipboard.d.ts +7 -3
- package/dist/clipboard.js +4 -3
- package/dist/{clone-2a5hVbBd.d.ts → clone-DZDrfIlU.d.ts} +31 -64
- package/dist/clone.d.ts +5 -4
- package/dist/core/adapters/testing/rootsTree.js +17 -0
- package/dist/core/adapters/testing/rootsTree.js.map +1 -0
- package/dist/core/applyOps.js +23 -7
- package/dist/core/applyOps.js.map +1 -1
- package/dist/core/device/index.js +6 -5
- package/dist/core/device/targets.js +29 -8
- package/dist/core/device/targets.js.map +1 -1
- package/dist/core/device/useDeviceProfile.js +86 -52
- package/dist/core/device/useDeviceProfile.js.map +1 -1
- package/dist/core/device/useTargetBasePx.js +23 -0
- package/dist/core/device/useTargetBasePx.js.map +1 -0
- package/dist/core/device/watchDevicePixelRatio.js +27 -10
- package/dist/core/device/watchDevicePixelRatio.js.map +1 -1
- package/dist/core/geometry/autoPoseDescriptor.js +38 -24
- package/dist/core/geometry/autoPoseDescriptor.js.map +1 -1
- package/dist/core/geometry/inkExtents.js +60 -0
- package/dist/core/geometry/inkExtents.js.map +1 -0
- package/dist/core/geometry/pathPoseDescriptor.js +101 -76
- package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
- package/dist/core/geometry/poseDescriptor.js +209 -120
- package/dist/core/geometry/poseDescriptor.js.map +1 -1
- package/dist/core/geometry/regionHit.js +127 -79
- package/dist/core/geometry/regionHit.js.map +1 -1
- package/dist/core/geometry/targetFrame.js +84 -60
- package/dist/core/geometry/targetFrame.js.map +1 -1
- package/dist/core/geometry/unionBounds.js +103 -48
- package/dist/core/geometry/unionBounds.js.map +1 -1
- package/dist/core/isPlainObject.js +3 -2
- package/dist/core/layers/backgroundFill.js +23 -15
- package/dist/core/layers/backgroundFill.js.map +1 -1
- package/dist/core/layers/children.js +16 -15
- package/dist/core/layers/children.js.map +1 -1
- package/dist/core/layers/gateLayer.js +24 -9
- package/dist/core/layers/gateLayer.js.map +1 -1
- package/dist/core/layers/layerGroup.js +42 -29
- package/dist/core/layers/layerGroup.js.map +1 -1
- package/dist/core/layers/redrawSource.js +15 -0
- package/dist/core/layers/redrawSource.js.map +1 -0
- package/dist/core/layers/render.js +183 -93
- package/dist/core/layers/render.js.map +1 -1
- package/dist/core/layers/retain.js +38 -0
- package/dist/core/layers/retain.js.map +1 -0
- package/dist/core/ops/arrange.js +30 -19
- package/dist/core/ops/arrange.js.map +1 -1
- package/dist/core/ops/create.js +32 -23
- package/dist/core/ops/create.js.map +1 -1
- package/dist/core/ops/createHistory.js +23 -14
- package/dist/core/ops/createHistory.js.map +1 -1
- package/dist/core/ops/delete.js +80 -57
- package/dist/core/ops/delete.js.map +1 -1
- package/dist/core/ops/nodeFlags.js +44 -0
- package/dist/core/ops/nodeFlags.js.map +1 -0
- package/dist/core/ops/registry.js +26 -11
- package/dist/core/ops/registry.js.map +1 -1
- package/dist/core/ops/reorder/algorithms.js +62 -38
- package/dist/core/ops/reorder/algorithms.js.map +1 -1
- package/dist/core/ops/reorder/index.js +124 -88
- package/dist/core/ops/reorder/index.js.map +1 -1
- package/dist/core/ops/reorder/setChildOrder.js +32 -25
- package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
- package/dist/core/ops/reparent.js +63 -38
- package/dist/core/ops/reparent.js.map +1 -1
- package/dist/core/ops/select.js +23 -20
- package/dist/core/ops/select.js.map +1 -1
- package/dist/core/ops/setData.js +23 -21
- package/dist/core/ops/setData.js.map +1 -1
- package/dist/core/ops/setLayer.js +26 -21
- package/dist/core/ops/setLayer.js.map +1 -1
- package/dist/core/ops/setLayout.js +27 -18
- package/dist/core/ops/setLayout.js.map +1 -1
- package/dist/core/ops/setPath.js +60 -41
- package/dist/core/ops/setPath.js.map +1 -1
- package/dist/core/ops/setText.js +26 -21
- package/dist/core/ops/setText.js.map +1 -1
- package/dist/core/ops/slot.js +36 -25
- package/dist/core/ops/slot.js.map +1 -1
- package/dist/core/ops/transform.js +35 -28
- package/dist/core/ops/transform.js.map +1 -1
- package/dist/core/pages/fitViewToPage.js +17 -0
- package/dist/core/pages/fitViewToPage.js.map +1 -0
- package/dist/core/pages/pages.js +96 -0
- package/dist/core/pages/pages.js.map +1 -0
- package/dist/core/pages/pagesLayer.js +33 -0
- package/dist/core/pages/pagesLayer.js.map +1 -0
- package/dist/core/paint/meshKind.js +16 -11
- package/dist/core/paint/meshKind.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js +3 -3
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/paint/paintKindEntry.js +13 -4
- package/dist/core/paint/paintKindEntry.js.map +1 -1
- package/dist/core/paint/paintKinds.js +149 -88
- package/dist/core/paint/paintKinds.js.map +1 -1
- package/dist/core/paint/registerMesh.js +6 -4
- package/dist/core/paint/registerMesh.js.map +1 -1
- package/dist/core/scene/NodeProperties.js +15 -10
- package/dist/core/scene/NodeProperties.js.map +1 -1
- package/dist/core/scene/NodeRouting.js +16 -12
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/annotation.js +28 -0
- package/dist/core/scene/annotation.js.map +1 -0
- package/dist/core/scene/appliedLog.js +31 -23
- package/dist/core/scene/appliedLog.js.map +1 -1
- package/dist/core/scene/arrivalWindow.js +120 -75
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/arrivals.js +17 -6
- package/dist/core/scene/arrivals.js.map +1 -1
- package/dist/core/scene/boundOps.js +42 -23
- package/dist/core/scene/boundOps.js.map +1 -1
- package/dist/core/scene/composeFrame.js +51 -21
- package/dist/core/scene/composeFrame.js.map +1 -1
- package/dist/core/scene/composePose.js +129 -39
- package/dist/core/scene/composePose.js.map +1 -1
- package/dist/core/scene/depFrame.js +94 -0
- package/dist/core/scene/depFrame.js.map +1 -0
- package/dist/core/scene/depMemo.js +44 -19
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +73 -45
- package/dist/core/scene/dependents.js.map +1 -1
- package/dist/core/scene/derivedParts.js +58 -0
- package/dist/core/scene/derivedParts.js.map +1 -0
- package/dist/core/scene/derivedPath.js +52 -22
- package/dist/core/scene/derivedPath.js.map +1 -1
- package/dist/core/scene/editMode.js +11 -11
- package/dist/core/scene/editMode.js.map +1 -1
- package/dist/core/scene/effectivePose.js +168 -48
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +95 -75
- package/dist/core/scene/fieldEdits.js.map +1 -1
- package/dist/core/scene/historyFacade.js +130 -85
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/historyForm.js +7 -3
- package/dist/core/scene/historyForm.js.map +1 -1
- package/dist/core/scene/kitOps.js +203 -131
- package/dist/core/scene/kitOps.js.map +1 -1
- package/dist/core/scene/kitRegistry.js +49 -22
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/layerStack.js +123 -92
- package/dist/core/scene/layerStack.js.map +1 -1
- package/dist/core/scene/layoutPass.js +118 -72
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/lockGuard.js +32 -24
- package/dist/core/scene/lockGuard.js.map +1 -1
- package/dist/core/scene/minSize.js +17 -0
- package/dist/core/scene/minSize.js.map +1 -0
- package/dist/core/scene/nestedHit.js +45 -31
- package/dist/core/scene/nestedHit.js.map +1 -1
- package/dist/core/scene/nodeFlags.js +43 -0
- package/dist/core/scene/nodeFlags.js.map +1 -0
- package/dist/core/scene/nodeFnFields.js +64 -40
- package/dist/core/scene/nodeFnFields.js.map +1 -1
- package/dist/core/scene/nodeGates.js +58 -0
- package/dist/core/scene/nodeGates.js.map +1 -0
- package/dist/core/scene/nodeMemo.js +92 -40
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/nodeStore.js +179 -99
- package/dist/core/scene/nodeStore.js.map +1 -1
- package/dist/core/scene/notifier.js +30 -19
- package/dist/core/scene/notifier.js.map +1 -1
- package/dist/core/scene/opTable.js +42 -36
- package/dist/core/scene/opTable.js.map +1 -1
- package/dist/core/scene/outerOps.js +50 -43
- package/dist/core/scene/outerOps.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js +80 -0
- package/dist/core/scene/pathEffects/blend.js.map +1 -0
- package/dist/core/scene/pathEffects/derive.js +112 -0
- package/dist/core/scene/pathEffects/derive.js.map +1 -0
- package/dist/core/scene/pathEffects/effects.js +40 -0
- package/dist/core/scene/pathEffects/effects.js.map +1 -0
- package/dist/core/scene/poseFeed.js +95 -60
- package/dist/core/scene/poseFeed.js.map +1 -1
- package/dist/core/scene/poseHold.js +33 -24
- package/dist/core/scene/poseHold.js.map +1 -1
- package/dist/core/scene/poseOverrides.js +86 -49
- package/dist/core/scene/poseOverrides.js.map +1 -1
- package/dist/core/scene/poseRemovals.js +58 -0
- package/dist/core/scene/poseRemovals.js.map +1 -0
- package/dist/core/scene/poseSnapshot.js +62 -41
- package/dist/core/scene/poseSnapshot.js.map +1 -1
- package/dist/core/scene/poseWrites.js +151 -0
- package/dist/core/scene/poseWrites.js.map +1 -0
- package/dist/core/scene/reconcileSpecs.js +63 -34
- package/dist/core/scene/reconcileSpecs.js.map +1 -1
- package/dist/core/scene/recorder.js +90 -57
- package/dist/core/scene/recorder.js.map +1 -1
- package/dist/core/scene/renderOrder.js +105 -59
- package/dist/core/scene/renderOrder.js.map +1 -1
- package/dist/core/scene/scene.js +133 -80
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneEdits.js +62 -49
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneMutators.js +44 -36
- package/dist/core/scene/sceneMutators.js.map +1 -1
- package/dist/core/scene/scenePoseAdapter.js +13 -9
- package/dist/core/scene/scenePoseAdapter.js.map +1 -1
- package/dist/core/scene/sceneRecording.js +89 -72
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/scene/sceneSelection.js +23 -16
- package/dist/core/scene/sceneSelection.js.map +1 -1
- package/dist/core/scene/sceneState.js +54 -36
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +87 -50
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/staleReplay.js +35 -26
- package/dist/core/scene/staleReplay.js.map +1 -1
- package/dist/core/scene/statedFields.js +10 -5
- package/dist/core/scene/statedFields.js.map +1 -1
- package/dist/core/scene/treeEdits.js +129 -98
- package/dist/core/scene/treeEdits.js.map +1 -1
- package/dist/core/scene/treeOrder.js +13 -8
- package/dist/core/scene/treeOrder.js.map +1 -1
- package/dist/core/scene/treeReads.js +25 -16
- package/dist/core/scene/treeReads.js.map +1 -1
- package/dist/core/scene/types.js +4 -3
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/unionOfChildren.js +20 -10
- package/dist/core/scene/unionOfChildren.js.map +1 -1
- package/dist/core/scene/unitScopes.js +15 -8
- package/dist/core/scene/unitScopes.js.map +1 -1
- package/dist/core/scene/useScene.js +32 -24
- package/dist/core/scene/useScene.js.map +1 -1
- package/dist/core/selection/chromeState.js +41 -17
- package/dist/core/selection/chromeState.js.map +1 -1
- package/dist/core/selection/readOnlySelection.js +39 -24
- package/dist/core/selection/readOnlySelection.js.map +1 -1
- package/dist/core/selection/selectionTarget.js +14 -3
- package/dist/core/selection/selectionTarget.js.map +1 -1
- package/dist/core/selection/usePublishSceneSelection.js +25 -18
- package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
- package/dist/core/selection/useSelection.js +90 -57
- package/dist/core/selection/useSelection.js.map +1 -1
- package/dist/core/shapeKinds.js +43 -28
- package/dist/core/shapeKinds.js.map +1 -1
- package/dist/core/stableStringify.js +5 -4
- package/dist/core/stableStringify.js.map +1 -1
- package/dist/core/stylus/stylus.js +49 -25
- package/dist/core/stylus/stylus.js.map +1 -1
- package/dist/core/stylus/usePointerStylus.js +61 -34
- package/dist/core/stylus/usePointerStylus.js.map +1 -1
- package/dist/core/usePaintKinds.js +21 -11
- package/dist/core/usePaintKinds.js.map +1 -1
- package/dist/core/viewport/clampView.js +31 -15
- package/dist/core/viewport/clampView.js.map +1 -1
- package/dist/core/viewport/clientToWorld.js +15 -4
- package/dist/core/viewport/clientToWorld.js.map +1 -1
- package/dist/core/viewport/createVelocityTracker.js +23 -19
- package/dist/core/viewport/createVelocityTracker.js.map +1 -1
- package/dist/core/viewport/fitToBounds.js +28 -11
- package/dist/core/viewport/fitToBounds.js.map +1 -1
- package/dist/core/viewport/fitViewToBounds.js +45 -19
- package/dist/core/viewport/fitViewToBounds.js.map +1 -1
- package/dist/core/viewport/interpolateView.js +40 -20
- package/dist/core/viewport/interpolateView.js.map +1 -1
- package/dist/core/viewport/parallax.js +89 -56
- package/dist/core/viewport/parallax.js.map +1 -1
- package/dist/core/viewport/sceneNodeClientRect.js +21 -12
- package/dist/core/viewport/sceneNodeClientRect.js.map +1 -1
- package/dist/core/viewport/screenSlop.js +40 -17
- package/dist/core/viewport/screenSlop.js.map +1 -1
- package/dist/core/viewport/useAutoCenter.js +36 -22
- package/dist/core/viewport/useAutoCenter.js.map +1 -1
- package/dist/core/viewport/useCanvasSize.js +43 -22
- package/dist/core/viewport/useCanvasSize.js.map +1 -1
- package/dist/core/viewport/useDecayLoop.js +120 -50
- package/dist/core/viewport/useDecayLoop.js.map +1 -1
- package/dist/core/viewport/useNodeOverlayFrame.js +93 -58
- package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
- package/dist/core/viewport/useVelocityTracker.js +9 -6
- package/dist/core/viewport/useVelocityTracker.js.map +1 -1
- package/dist/core/viewport/useViewAnimation.js +159 -99
- package/dist/core/viewport/useViewAnimation.js.map +1 -1
- package/dist/core/viewport/view.js +49 -22
- package/dist/core/viewport/view.js.map +1 -1
- package/dist/core/viewport/viewTransform.js +8 -6
- package/dist/core/viewport/viewTransform.js.map +1 -1
- package/dist/core/viewport/viewportWorldRect.js +15 -7
- package/dist/core/viewport/viewportWorldRect.js.map +1 -1
- package/dist/core/viewport/wheelHandler.js +31 -20
- package/dist/core/viewport/wheelHandler.js.map +1 -1
- package/dist/core/viewport/zoomAt.js +50 -13
- package/dist/core/viewport/zoomAt.js.map +1 -1
- package/dist/core/viewport/zoomBounds.js +33 -17
- package/dist/core/viewport/zoomBounds.js.map +1 -1
- package/dist/cornerHandles-Camw_yeu.d.ts +169 -0
- package/dist/debug/createDebugOverlayLayer.js +303 -215
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/createDebugSink.js +68 -47
- package/dist/debug/createDebugSink.js.map +1 -1
- package/dist/debug/defaultTheme.js +16 -4
- package/dist/debug/defaultTheme.js.map +1 -1
- package/dist/debug/flag.js +3 -2
- package/dist/debug/frameStats.js +11 -9
- package/dist/debug/frameStats.js.map +1 -1
- package/dist/debug/parseDebugFlags.js +25 -17
- package/dist/debug/parseDebugFlags.js.map +1 -1
- package/dist/debug/useDebugSink.js +52 -33
- package/dist/debug/useDebugSink.js.map +1 -1
- package/dist/depSchema-Cgfu_G9s.d.ts +3581 -0
- package/dist/features/chrome-caps/buildChromeCtx.js +12 -10
- package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
- package/dist/features/chrome-caps/conditions.js +103 -25
- package/dist/features/chrome-caps/conditions.js.map +1 -1
- package/dist/features/chrome-caps/defaults.js +18 -10
- package/dist/features/chrome-caps/defaults.js.map +1 -1
- package/dist/features/chrome-caps/index.js +8 -7
- package/dist/features/chrome-caps/resolve.js +28 -16
- package/dist/features/chrome-caps/resolve.js.map +1 -1
- package/dist/features/chrome-caps/useChromeCaps.js +52 -44
- package/dist/features/chrome-caps/useChromeCaps.js.map +1 -1
- package/dist/features/chrome-caps/useHoverTracking.js +52 -26
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +80 -34
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/ingestion/imageHandler.js +49 -29
- package/dist/features/ingestion/imageHandler.js.map +1 -1
- package/dist/features/ingestion/openFilePicker.js +27 -9
- package/dist/features/ingestion/openFilePicker.js.map +1 -1
- package/dist/features/ingestion/placement.js +20 -11
- package/dist/features/ingestion/placement.js.map +1 -1
- package/dist/features/ingestion/registerKitHandlers.js +35 -18
- package/dist/features/ingestion/registerKitHandlers.js.map +1 -1
- package/dist/features/ingestion/svgHandler.js +60 -34
- package/dist/features/ingestion/svgHandler.js.map +1 -1
- package/dist/features/ingestion/textHandler.js +37 -16
- package/dist/features/ingestion/textHandler.js.map +1 -1
- package/dist/features/ingestion/useCanvasIngestion.js +57 -39
- package/dist/features/ingestion/useCanvasIngestion.js.map +1 -1
- package/dist/features/ingestion/weaselJsonHandler.js +38 -28
- package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
- package/dist/features/longPress/longPressFeedback.js +110 -81
- package/dist/features/longPress/longPressFeedback.js.map +1 -1
- package/dist/features/measure/actionIds.js +22 -0
- package/dist/features/measure/actionIds.js.map +1 -0
- package/dist/features/measure/measureCommands.js +178 -0
- package/dist/features/measure/measureCommands.js.map +1 -0
- package/dist/features/measure/measureContribution.js +57 -0
- package/dist/features/measure/measureContribution.js.map +1 -0
- package/dist/features/measure/measureEdits.js +82 -0
- package/dist/features/measure/measureEdits.js.map +1 -0
- package/dist/features/measure/measureGestures.js +185 -0
- package/dist/features/measure/measureGestures.js.map +1 -0
- package/dist/features/measure/measureHit.js +80 -0
- package/dist/features/measure/measureHit.js.map +1 -0
- package/dist/features/measure/measureLayer.js +86 -0
- package/dist/features/measure/measureLayer.js.map +1 -0
- package/dist/features/measure/measurement.js +79 -0
- package/dist/features/measure/measurement.js.map +1 -0
- package/dist/features/measure/measurements.js +41 -0
- package/dist/features/measure/measurements.js.map +1 -0
- package/dist/features/modes/modeLayers.js +81 -55
- package/dist/features/modes/modeLayers.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +66 -0
- package/dist/features/modes/modeTriggers.js.map +1 -0
- package/dist/features/pathEffects/index.js +35 -0
- package/dist/features/pathEffects/index.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +46 -0
- package/dist/features/pathEffects/readSource.js.map +1 -0
- package/dist/features/paths/anchorData.js +65 -0
- package/dist/features/paths/anchorData.js.map +1 -0
- package/dist/features/paths/anchorMarkers.js +137 -0
- package/dist/features/paths/anchorMarkers.js.map +1 -0
- package/dist/features/paths/editablePath.js +155 -36
- package/dist/features/paths/editablePath.js.map +1 -1
- package/dist/features/paths/index.js +12 -9
- package/dist/features/paths/originProjection.js +16 -9
- package/dist/features/paths/originProjection.js.map +1 -1
- package/dist/features/paths/pathEditExtension.js +26 -0
- package/dist/features/paths/pathEditExtension.js.map +1 -0
- package/dist/features/paths/pathEditState.js +107 -26
- package/dist/features/paths/pathEditState.js.map +1 -1
- package/dist/features/paths/pathEditingOverlayLayer.js +58 -110
- package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
- package/dist/features/paths/pathLayer.js +79 -29
- package/dist/features/paths/pathLayer.js.map +1 -1
- package/dist/features/paths/pathRepresentation.js +27 -0
- package/dist/features/paths/pathRepresentation.js.map +1 -0
- package/dist/features/paths/pathSnap/glyphs.js +39 -0
- package/dist/features/paths/pathSnap/glyphs.js.map +1 -0
- package/dist/features/paths/pathSnap/pathSnapSource.js +82 -0
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -0
- package/dist/features/paths/pathSnap/sceneIndex.js +78 -0
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -0
- package/dist/features/paths/pathSnap/snapGeometry.js +47 -0
- package/dist/features/paths/pathSnap/snapGeometry.js.map +1 -0
- package/dist/features/paths/penPreviewLayer.js +135 -102
- package/dist/features/paths/penPreviewLayer.js.map +1 -1
- package/dist/features/paths/shapeGenerator.js +141 -0
- package/dist/features/paths/shapeGenerator.js.map +1 -0
- package/dist/features/paths/strokeOutline.js +15 -0
- package/dist/features/paths/strokeOutline.js.map +1 -0
- package/dist/features/paths/useAnchorFields.js +35 -0
- package/dist/features/paths/useAnchorFields.js.map +1 -0
- package/dist/features/paths/usePathEdit.js +58 -28
- package/dist/features/paths/usePathEdit.js.map +1 -1
- package/dist/features/poseRun/usePoseRun.js +111 -44
- package/dist/features/poseRun/usePoseRun.js.map +1 -1
- package/dist/features/selection/handleCommands.js +116 -0
- package/dist/features/selection/handleCommands.js.map +1 -0
- package/dist/features/selection/overlay.js +288 -328
- package/dist/features/selection/overlay.js.map +1 -1
- package/dist/features/selection/selectionPose.js +109 -0
- package/dist/features/selection/selectionPose.js.map +1 -0
- package/dist/features/snap/angle2d.js +158 -0
- package/dist/features/snap/angle2d.js.map +1 -0
- package/dist/features/snap/debugCandidates.js +27 -0
- package/dist/features/snap/debugCandidates.js.map +1 -0
- package/dist/features/snap/gather.js +71 -0
- package/dist/features/snap/gather.js.map +1 -0
- package/dist/features/snap/inputSubspace.js +46 -0
- package/dist/features/snap/inputSubspace.js.map +1 -0
- package/dist/features/snap/marks.js +29 -0
- package/dist/features/snap/marks.js.map +1 -0
- package/dist/features/snap/outcomeStore.js +25 -0
- package/dist/features/snap/outcomeStore.js.map +1 -0
- package/dist/features/snap/pointSnap.js +48 -0
- package/dist/features/snap/pointSnap.js.map +1 -0
- package/dist/features/snap/probes2d.js +91 -0
- package/dist/features/snap/probes2d.js.map +1 -0
- package/dist/features/snap/readoutDraw.js +93 -0
- package/dist/features/snap/readoutDraw.js.map +1 -0
- package/dist/features/snap/readoutLayer.js +49 -0
- package/dist/features/snap/readoutLayer.js.map +1 -0
- package/dist/features/snap/registry.js +27 -0
- package/dist/features/snap/registry.js.map +1 -0
- package/dist/features/snap/resizeBox.js +137 -0
- package/dist/features/snap/resizeBox.js.map +1 -0
- package/dist/features/snap/roles.js +31 -0
- package/dist/features/snap/roles.js.map +1 -0
- package/dist/features/snap/rotationSource.js +30 -0
- package/dist/features/snap/rotationSource.js.map +1 -0
- package/dist/features/snap/sceneReads.js +45 -0
- package/dist/features/snap/sceneReads.js.map +1 -0
- package/dist/features/snap/sceneSession2d.js +79 -0
- package/dist/features/snap/sceneSession2d.js.map +1 -0
- package/dist/features/snap/screen.js +23 -0
- package/dist/features/snap/screen.js.map +1 -0
- package/dist/features/snap/session2d.js +129 -0
- package/dist/features/snap/session2d.js.map +1 -0
- package/dist/features/snap/spanSnap.js +77 -0
- package/dist/features/snap/spanSnap.js.map +1 -0
- package/dist/features/snap/stepAngles.js +15 -0
- package/dist/features/snap/stepAngles.js.map +1 -0
- package/dist/features/text/editingDrawOne.js +32 -0
- package/dist/features/text/editingDrawOne.js.map +1 -0
- package/dist/features/text/index.js +7 -6
- package/dist/features/text/textHitAt.js +51 -0
- package/dist/features/text/textHitAt.js.map +1 -0
- package/dist/features/text/textLayer.js +21 -27
- package/dist/features/text/textLayer.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +203 -123
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/viewports/viewResolver.js +51 -38
- package/dist/features/viewports/viewResolver.js.map +1 -1
- package/dist/features/viewports/viewportLayer.js +60 -29
- package/dist/features/viewports/viewportLayer.js.map +1 -1
- package/dist/iconRegistry/IconRegistryProvider.js +73 -0
- package/dist/iconRegistry/IconRegistryProvider.js.map +1 -0
- package/dist/iconRegistry/useIconGlyph.js +14 -0
- package/dist/iconRegistry/useIconGlyph.js.map +1 -0
- package/dist/iconRegistry/useIconVariant.js +29 -0
- package/dist/iconRegistry/useIconVariant.js.map +1 -0
- package/dist/icons.d.ts +6 -0
- package/dist/icons.js +3 -0
- package/dist/icons.table.js +13 -0
- package/dist/icons.table.js.map +1 -0
- package/dist/icons.table.json +556 -0
- package/dist/icons2.table.js +9 -0
- package/dist/icons2.table.js.map +1 -0
- package/dist/index.d.ts +4552 -4992
- package/dist/index.js +340 -276
- package/dist/input/keyState.js +118 -54
- package/dist/input/keyState.js.map +1 -1
- package/dist/input/useKeyModifiers.js +13 -7
- package/dist/input/useKeyModifiers.js.map +1 -1
- package/dist/input/useKeyState.js +23 -16
- package/dist/input/useKeyState.js.map +1 -1
- package/dist/interactions/actions/align/action.js +76 -45
- package/dist/interactions/actions/align/action.js.map +1 -1
- package/dist/interactions/actions/align/align.js +86 -48
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/action.js +67 -33
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/booleans/booleans.js +77 -70
- package/dist/interactions/actions/booleans/booleans.js.map +1 -1
- package/dist/interactions/actions/booleans/commit.js +49 -0
- package/dist/interactions/actions/booleans/commit.js.map +1 -0
- package/dist/interactions/actions/booleans/custom.js +48 -0
- package/dist/interactions/actions/booleans/custom.js.map +1 -0
- package/dist/interactions/actions/booleans/operands.js +43 -32
- package/dist/interactions/actions/booleans/operands.js.map +1 -1
- package/dist/interactions/actions/booleans/pieces.js +29 -23
- package/dist/interactions/actions/booleans/pieces.js.map +1 -1
- package/dist/interactions/actions/booleans/placement.js +30 -17
- package/dist/interactions/actions/booleans/placement.js.map +1 -1
- package/dist/interactions/actions/booleans/useBooleans.js +30 -17
- package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
- package/dist/interactions/actions/booleans/useBooleansAdapter.js +8 -5
- package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +81 -40
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/clipboard/clipboardOps.js +100 -72
- package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
- package/dist/interactions/actions/clipboard/materializePaste.js +38 -19
- package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
- package/dist/interactions/actions/clipboard/wireFormat.js +66 -28
- package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
- package/dist/interactions/actions/clone/action.js +102 -65
- package/dist/interactions/actions/clone/action.js.map +1 -1
- package/dist/interactions/actions/clone/behaviors.js +55 -38
- package/dist/interactions/actions/clone/behaviors.js.map +1 -1
- package/dist/interactions/actions/defaultCommitAdapter.js +32 -10
- package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +253 -115
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorFields.js +54 -0
- package/dist/interactions/actions/defaults/anchorFields.js.map +1 -0
- package/dist/interactions/actions/defaults/anchorHandles.js +46 -0
- package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
- package/dist/interactions/actions/defaults/anchorJoin.js +110 -0
- package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
- package/dist/interactions/actions/defaults/areaSelect.js +56 -40
- package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +82 -0
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
- package/dist/interactions/actions/defaults/cancelGesture.js +12 -5
- package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
- package/dist/interactions/actions/defaults/clearSelection.js +22 -7
- package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
- package/dist/interactions/actions/defaults/contextMenu.js +149 -0
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -0
- package/dist/interactions/actions/defaults/copySubtree.js +43 -29
- package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +79 -54
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +61 -33
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +65 -22
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +29 -13
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/enterTextEdit.js +20 -8
- package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/escape.js +16 -7
- package/dist/interactions/actions/defaults/escape.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +6 -6
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +122 -73
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +52 -35
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +39 -33
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +80 -48
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/nudgeSteps.js +17 -12
- package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditMarks.js +60 -0
- package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -0
- package/dist/interactions/actions/defaults/pathEditTools.js +57 -0
- package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -0
- package/dist/interactions/actions/defaults/pinchZoom.js +54 -38
- package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
- package/dist/interactions/actions/defaults/reorder.js +71 -40
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/requiresSelection.js +13 -6
- package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
- package/dist/interactions/actions/defaults/segmentUnder.js +30 -0
- package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
- package/dist/interactions/actions/defaults/selectAll.js +21 -7
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +37 -21
- package/dist/interactions/actions/defaults/setFill.js.map +1 -1
- package/dist/interactions/actions/defaults/setFillOpacity.js +19 -10
- package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
- package/dist/interactions/actions/defaults/setStroke.js +46 -25
- package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +19 -11
- package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -1
- package/dist/interactions/actions/defaults/slice.js +42 -17
- package/dist/interactions/actions/defaults/slice.js.map +1 -1
- package/dist/interactions/actions/defaults/sliceOps.js +63 -42
- package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
- package/dist/interactions/actions/defaults/toolActivate.js +34 -16
- package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
- package/dist/interactions/actions/defaults/toolResetToDefault.js +29 -10
- package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
- package/dist/interactions/actions/defaults/undoRedo.js +26 -20
- package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportDragPan.js +91 -58
- package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportWheelPan.js +42 -23
- package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportZoom.js +142 -91
- package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
- package/dist/interactions/actions/distribute/action.js +62 -39
- package/dist/interactions/actions/distribute/action.js.map +1 -1
- package/dist/interactions/actions/distribute/distribute.js +53 -34
- package/dist/interactions/actions/distribute/distribute.js.map +1 -1
- package/dist/interactions/actions/distribute/plan.js +40 -22
- package/dist/interactions/actions/distribute/plan.js.map +1 -1
- package/dist/interactions/actions/drawnBoxes.js +31 -0
- package/dist/interactions/actions/drawnBoxes.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/action.js +254 -75
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/extensionDrags.js +50 -0
- package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/geometry.js +74 -47
- package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/handleDrag.js +101 -0
- package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/handles.js +41 -27
- package/dist/interactions/actions/edit-anchors/handles.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/params.js +12 -0
- package/dist/interactions/actions/edit-anchors/params.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/preview.js +68 -0
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/symmetry.js +16 -0
- package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
- package/dist/interactions/actions/flip/action.js +119 -61
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/flip/helpers.js +69 -36
- package/dist/interactions/actions/flip/helpers.js.map +1 -1
- package/dist/interactions/actions/geometryProjection.js +17 -12
- package/dist/interactions/actions/geometryProjection.js.map +1 -1
- package/dist/interactions/actions/gestureFrames.js +20 -11
- package/dist/interactions/actions/gestureFrames.js.map +1 -1
- package/dist/interactions/actions/gestureLifecycle.js +93 -48
- package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
- package/dist/interactions/actions/hitSelection.js +6 -4
- package/dist/interactions/actions/hitSelection.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +75 -39
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/commit.js +44 -22
- package/dist/interactions/actions/insert/commit.js.map +1 -1
- package/dist/interactions/actions/insert/extras.js +60 -38
- package/dist/interactions/actions/insert/extras.js.map +1 -1
- package/dist/interactions/actions/insert/frame.js +59 -33
- package/dist/interactions/actions/insert/frame.js.map +1 -1
- package/dist/interactions/actions/insert/geometry.js +29 -25
- package/dist/interactions/actions/insert/geometry.js.map +1 -1
- package/dist/interactions/actions/insert/placeAction.js +108 -0
- package/dist/interactions/actions/insert/placeAction.js.map +1 -0
- package/dist/interactions/actions/insert/repositionAction.js +46 -0
- package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
- package/dist/interactions/actions/insert/rotateAction.js +19 -8
- package/dist/interactions/actions/insert/rotateAction.js.map +1 -1
- package/dist/interactions/actions/insert/session.js +57 -41
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/insert/shape.js +83 -25
- package/dist/interactions/actions/insert/shape.js.map +1 -1
- package/dist/interactions/actions/lasso-select/action.js +160 -100
- package/dist/interactions/actions/lasso-select/action.js.map +1 -1
- package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +44 -25
- package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
- package/dist/interactions/actions/move/action.js +87 -48
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +56 -36
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +20 -10
- package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +40 -24
- package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +107 -63
- package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
- package/dist/interactions/actions/move/capture.js +106 -72
- package/dist/interactions/actions/move/capture.js.map +1 -1
- package/dist/interactions/actions/move/commit/index.js +43 -34
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +43 -32
- package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutRelease.js +97 -77
- package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
- package/dist/interactions/actions/move/commit/rebase.js +16 -13
- package/dist/interactions/actions/move/commit/rebase.js.map +1 -1
- package/dist/interactions/actions/move/commit/reparent.js +83 -57
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/delta.js +58 -36
- package/dist/interactions/actions/move/delta.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +73 -48
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/gestureAdapter.js +30 -20
- package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +40 -25
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +92 -72
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +61 -39
- package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +136 -94
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +58 -30
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/layout/glide.js +55 -34
- package/dist/interactions/actions/move/layout/glide.js.map +1 -1
- package/dist/interactions/actions/move/session.js +85 -56
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +58 -43
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/outlines/createOutlines.js +28 -20
- package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
- package/dist/interactions/actions/outlines/createOutlinesAction.js +43 -31
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStroke.js +68 -45
- package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStrokeAction.js +24 -19
- package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -1
- package/dist/interactions/actions/outlines/replaceWithPaths.js +57 -42
- package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
- package/dist/interactions/actions/outlines/strokeRegion.js +37 -22
- package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
- package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +8 -5
- package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -1
- package/dist/interactions/actions/pathCommands/cutJoin.js +149 -0
- package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
- package/dist/interactions/actions/pathCommands/livePathEdit.js +98 -0
- package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
- package/dist/interactions/actions/pathCommands/pathNodes.js +108 -0
- package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
- package/dist/interactions/actions/pathCommands/simplifyOffset.js +66 -0
- package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
- package/dist/interactions/actions/pathGestureTags.js +29 -0
- package/dist/interactions/actions/pathGestureTags.js.map +1 -0
- package/dist/interactions/actions/planeInput.js +198 -123
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/pointerState.js +12 -7
- package/dist/interactions/actions/pointerState.js.map +1 -1
- package/dist/interactions/actions/poseDescriptorDep.js +24 -14
- package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
- package/dist/interactions/actions/poseFrame.js +45 -28
- package/dist/interactions/actions/poseFrame.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +70 -30
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/aspect.js +44 -0
- package/dist/interactions/actions/resize/aspect.js.map +1 -0
- package/dist/interactions/actions/resize/behaviors/clampMinSize.js +38 -13
- package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -1
- package/dist/interactions/actions/resize/boxFrame.js +15 -11
- package/dist/interactions/actions/resize/boxFrame.js.map +1 -1
- package/dist/interactions/actions/resize/capture.js +105 -62
- package/dist/interactions/actions/resize/capture.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +75 -56
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/cornerHandles.js +154 -17
- package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
- package/dist/interactions/actions/resize/frame.js +138 -57
- package/dist/interactions/actions/resize/frame.js.map +1 -1
- package/dist/interactions/actions/resize/minimum.js +35 -0
- package/dist/interactions/actions/resize/minimum.js.map +1 -0
- package/dist/interactions/actions/resize/replay.js +57 -0
- package/dist/interactions/actions/resize/replay.js.map +1 -0
- package/dist/interactions/actions/resize/ruleBounds.js +8 -5
- package/dist/interactions/actions/resize/ruleBounds.js.map +1 -1
- package/dist/interactions/actions/resize/session.js +100 -41
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolveOverlays.js +48 -32
- package/dist/interactions/actions/resolveOverlays.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +63 -46
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +71 -30
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/commit.js +39 -31
- package/dist/interactions/actions/rotate/commit.js.map +1 -1
- package/dist/interactions/actions/rotate/frame.js +75 -47
- package/dist/interactions/actions/rotate/frame.js.map +1 -1
- package/dist/interactions/actions/rotate/geometry.js +36 -24
- package/dist/interactions/actions/rotate/geometry.js.map +1 -1
- package/dist/interactions/actions/rotate/handle.js +28 -15
- package/dist/interactions/actions/rotate/handle.js.map +1 -1
- package/dist/interactions/actions/rotate/replay.js +26 -0
- package/dist/interactions/actions/rotate/replay.js.map +1 -0
- package/dist/interactions/actions/rotate/session.js +122 -73
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +124 -53
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/spatialReference.js +33 -26
- package/dist/interactions/actions/spatialReference.js.map +1 -1
- package/dist/interactions/actions/testUtils.js +53 -0
- package/dist/interactions/actions/testUtils.js.map +1 -0
- package/dist/interactions/actions/transform-again/action.js +78 -0
- package/dist/interactions/actions/transform-again/action.js.map +1 -0
- package/dist/interactions/actions/transform-again/memory.js +46 -0
- package/dist/interactions/actions/transform-again/memory.js.map +1 -0
- package/dist/interactions/actions/useActionSet.js +83 -0
- package/dist/interactions/actions/useActionSet.js.map +1 -0
- package/dist/interactions/actions/useStandardActions.js +23 -147
- package/dist/interactions/actions/useStandardActions.js.map +1 -1
- package/dist/interactions/gestures/dragGesture/dragGesture.js +109 -68
- package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
- package/dist/interactions/gestures/dragGesture/dragPointOf.js +17 -10
- package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -1
- package/dist/interactions/gestures/dragRadial/dragRadial.js +129 -93
- package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
- package/dist/interactions/gestures/dragRect/dragRect.js +155 -111
- package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
- package/dist/interactions/gestures/handleDrag/handleDrag.js +52 -30
- package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
- package/dist/interactions/gestures/pointerDrag/pointerDrag.js +168 -97
- package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
- package/dist/interactions/gestures/shared/originProjection.js +32 -25
- package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
- package/dist/interactions/gestures/shared/screenTolerance.js +26 -17
- package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +39 -21
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
- package/dist/kitSettingsSchema.js +80 -0
- package/dist/kitSettingsSchema.js.map +1 -0
- package/dist/{math-CYUjoyyU.d.ts → math-CrJULaZI.d.ts} +5 -6
- package/dist/math.d.ts +4 -5
- package/dist/math.js +7 -6
- package/dist/mesh.js +3 -2
- package/dist/move.d.ts +7 -6
- package/dist/move.js +4 -3
- package/dist/{originProjection-PPT88jZv.d.ts → options-p9GZMXbY.d.ts} +4 -27
- package/dist/originProjection-gY0jb4Wb.d.ts +24 -0
- package/dist/patterns-builtin.js +3 -2
- package/dist/{poseDescriptor-Bqk-11Rl.d.ts → poseDescriptor-DN2yfnq_.d.ts} +7 -7
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +3 -2
- package/dist/resize.d.ts +10 -28
- package/dist/resize.js +6 -7
- package/dist/routing.js +3 -2
- package/dist/style.css +88 -1
- package/dist/test-hook/createTestHook.js +23 -20
- package/dist/test-hook/createTestHook.js.map +1 -1
- package/dist/test-hook/install.js +32 -13
- package/dist/test-hook/install.js.map +1 -1
- package/dist/test-hook/useTestHook.js +22 -16
- package/dist/test-hook/useTestHook.js.map +1 -1
- package/dist/test-seams.d.ts +164 -1
- package/dist/test-seams.js +8 -3
- package/dist/tools/builtin/bone/boneActions.js +96 -70
- package/dist/tools/builtin/bone/boneActions.js.map +1 -1
- package/dist/tools/builtin/bone/boneOverlay.js +49 -36
- package/dist/tools/builtin/bone/boneOverlay.js.map +1 -1
- package/dist/tools/builtin/bone/placedRig.js +18 -14
- package/dist/tools/builtin/bone/placedRig.js.map +1 -1
- package/dist/tools/builtin/bone/rigEditState.js +22 -13
- package/dist/tools/builtin/bone/rigEditState.js.map +1 -1
- package/dist/tools/builtin/bone/useBoneTool.js +68 -41
- package/dist/tools/builtin/bone/useBoneTool.js.map +1 -1
- package/dist/tools/builtin/ellipse/useEllipseTool.js +22 -16
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +44 -28
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/hand/dragPanContribution.js +12 -7
- package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +21 -13
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/image/useImageTool.js +28 -19
- package/dist/tools/builtin/image/useImageTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +48 -36
- package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js +24 -16
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +84 -0
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -0
- package/dist/tools/builtin/pen/penHandle.js +60 -0
- package/dist/tools/builtin/pen/penHandle.js.map +1 -0
- package/dist/tools/builtin/pen/usePenTool.js +463 -305
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/pencil/usePencilTool.js +20 -15
- package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
- package/dist/tools/builtin/pickTopMostHit.js +51 -34
- package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +45 -26
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/rect/useRectTool.js +24 -15
- package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
- package/dist/tools/builtin/select/adapterPointQuery.js +48 -27
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/selectionContributions.js +94 -56
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +155 -107
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/shared/insertToolOptions.js +5 -4
- package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -1
- package/dist/tools/builtin/shared/pointerFollower.js +15 -8
- package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +148 -99
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +48 -29
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/sticky/stickyNode.js +49 -0
- package/dist/tools/builtin/sticky/stickyNode.js.map +1 -0
- package/dist/tools/builtin/sticky/useStickyTool.js +86 -0
- package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -0
- package/dist/tools/builtin/text/useTextTool.js +61 -36
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/builtin/weight/useWeightTool.js +66 -42
- package/dist/tools/builtin/weight/useWeightTool.js.map +1 -1
- package/dist/tools/builtin/weight/weightActions.js +93 -65
- package/dist/tools/builtin/weight/weightActions.js.map +1 -1
- package/dist/tools/builtin/weight/weightOverlay.js +47 -30
- package/dist/tools/builtin/weight/weightOverlay.js.map +1 -1
- package/dist/tools/overlayBinding.js +7 -5
- package/dist/tools/overlayBinding.js.map +1 -1
- package/dist/tools/useKeybindings.js +62 -46
- package/dist/tools/useKeybindings.js.map +1 -1
- package/dist/{types-CIKDwlsP.d.ts → types-CHVXGfYm.d.ts} +27 -20
- package/dist/util/color.js +39 -18
- package/dist/util/color.js.map +1 -1
- package/dist/util/paint.js +93 -38
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +11 -3
- package/dist/version.js.map +1 -1
- package/package.json +35 -23
- package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +0 -126
- package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +0 -1
- package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +0 -64
- package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +0 -1
- package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +0 -16
- package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +0 -1
- package/dist/canvas/SceneCanvas/isDev.js +0 -12
- package/dist/canvas/SceneCanvas/isDev.js.map +0 -1
- package/dist/canvas/SceneCanvas/useViewLayerGate.js +0 -20
- package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +0 -1
- package/dist/canvas/surface.module.js +0 -6
- package/dist/canvas/surface.module.js.map +0 -1
- package/dist/canvas/surfaceBox.js +0 -16
- package/dist/canvas/surfaceBox.js.map +0 -1
- package/dist/cornerHandles-BEshc4z3.d.ts +0 -104
- package/dist/icons/ArrowIcon.js +0 -23
- package/dist/icons/ArrowIcon.js.map +0 -1
- package/dist/icons/EllipseIcon.js +0 -21
- package/dist/icons/EllipseIcon.js.map +0 -1
- package/dist/icons/EyedropperIcon.js +0 -49
- package/dist/icons/EyedropperIcon.js.map +0 -1
- package/dist/icons/HandIcon.js +0 -59
- package/dist/icons/HandIcon.js.map +0 -1
- package/dist/icons/ImageIcon.js +0 -34
- package/dist/icons/ImageIcon.js.map +0 -1
- package/dist/icons/LassoIcon.js +0 -22
- package/dist/icons/LassoIcon.js.map +0 -1
- package/dist/icons/LineIcon.js +0 -22
- package/dist/icons/LineIcon.js.map +0 -1
- package/dist/icons/PenIcon.js +0 -36
- package/dist/icons/PenIcon.js.map +0 -1
- package/dist/icons/PencilIcon.js +0 -25
- package/dist/icons/PencilIcon.js.map +0 -1
- package/dist/icons/PolygonIcon.js +0 -19
- package/dist/icons/PolygonIcon.js.map +0 -1
- package/dist/icons/RectIcon.js +0 -37
- package/dist/icons/RectIcon.js.map +0 -1
- package/dist/icons/SelectIcon.js +0 -20
- package/dist/icons/SelectIcon.js.map +0 -1
- package/dist/icons/StarIcon.js +0 -19
- package/dist/icons/StarIcon.js.map +0 -1
- package/dist/icons/TextIcon.js +0 -19
- package/dist/icons/TextIcon.js.map +0 -1
- package/dist/icons/UnknownIcon.js +0 -33
- package/dist/icons/UnknownIcon.js.map +0 -1
- package/dist/icons/_base.js +0 -12
- package/dist/icons/_base.js.map +0 -1
- package/dist/interactions/actions/actionShortcuts.js +0 -32
- package/dist/interactions/actions/actionShortcuts.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +0 -40
- package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/actionGlyphs.js +0 -10
- package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/alignIcons.js +0 -173
- package/dist/interactions/actions/defaults/icons/alignIcons.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/booleanIcons.js +0 -194
- package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/distributeIcons.js +0 -63
- package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/editIcons.js +0 -280
- package/dist/interactions/actions/defaults/icons/editIcons.js.map +0 -1
- package/dist/interactions/actions/defaults/icons/outlineIcons.js +0 -91
- package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +0 -1
- package/dist/interactions/actions/resize/behaviors/index.js +0 -8
- package/dist/interactions/actions/resize/behaviors/index.js.map +0 -1
- package/dist/interactions/actions/resize/behaviors/lockAspect.js +0 -24
- package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +0 -1
- package/dist/interactions/actions/resize/pointSnap.js +0 -111
- package/dist/interactions/actions/resize/pointSnap.js.map +0 -1
- package/dist/interactions/actions/rotate/behaviors/index.js +0 -7
- package/dist/interactions/actions/rotate/behaviors/index.js.map +0 -1
- package/dist/interactions/actions/rotate/behaviors/snapRotation.js +0 -12
- package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +0 -1
- package/dist/interactions/gestures/shared/snap.js +0 -24
- package/dist/interactions/gestures/shared/snap.js.map +0 -1
- package/dist/layout/arrivals.js +0 -33
- package/dist/layout/arrivals.js.map +0 -1
- package/dist/test-seams-D0pyV3pR.d.ts +0 -149
- package/dist/util/constrainTo45.js +0 -17
- package/dist/util/constrainTo45.js.map +0 -1
|
@@ -0,0 +1,3581 @@
|
|
|
1
|
+
import { TileKind, Paint, GradStop, TilePaint, Fill, Stroke, CommandFill, CommandStroke, CommandPaint } from '@weasel-js/paint';
|
|
2
|
+
import { Reflection } from '@weasel-js/registry';
|
|
3
|
+
import { ComponentType } from 'react';
|
|
4
|
+
import { IconRef } from '@weasel-js/icons';
|
|
5
|
+
import { PaintDrawKind, DrawCommand, Effect, CompositeOp, BlendFactors } from '@weasel-js/renderer';
|
|
6
|
+
import * as _weasel_js_routing_react from '@weasel-js/routing/react';
|
|
7
|
+
import * as _weasel_js_geom from '@weasel-js/geom';
|
|
8
|
+
import { Path, PoseLinear, Affine, FramedBox, View, Rect, Scale2, PolygonPath, PathFillRule, AnchorSet, PointOrigin } from '@weasel-js/geom';
|
|
9
|
+
import * as _weasel_js_history from '@weasel-js/history';
|
|
10
|
+
import { SerializedHistory, Op, History } from '@weasel-js/history';
|
|
11
|
+
import { NodeId, ModifierState, OverlayRole, ResizeAnchor, ActionDeps, OngoingHandle, OngoingOverlay, SelectionApi, IngestItem, Point2, DragSample, DebugSink, LongPressState } from '@weasel-js/routing';
|
|
12
|
+
import { TextNodeSource, TextOutlinesError, TextStyle, StyledRun, TextVerticalAlign } from '@weasel-js/text';
|
|
13
|
+
import { CursorSpec } from '@weasel-js/cursor';
|
|
14
|
+
import { ClaimableGesture } from '@weasel-js/gestures';
|
|
15
|
+
import { SnapTier, ProbeRole } from '@weasel-js/geom/nd';
|
|
16
|
+
import { a as ParallaxOpts, C as ContainerBounds, L as LayoutStrategy, P as PlaneMap, I as InsertAdapter, b as PasteOmission, R as RegionPickView, c as LayoutDropTargetMode, d as ReflowTransition } from './types-CHVXGfYm.js';
|
|
17
|
+
import { UnitScope } from '@weasel-js/quantity';
|
|
18
|
+
import { O as OriginProjection } from './originProjection-gY0jb4Wb.js';
|
|
19
|
+
import { EasingSpec, InterpolatorFactory, Target, Animator, TargetAxes } from '@weasel-js/animator';
|
|
20
|
+
import { B as BoundsConstraint } from './clone-DZDrfIlU.js';
|
|
21
|
+
import { P as PoseDescriptor } from './poseDescriptor-DN2yfnq_.js';
|
|
22
|
+
|
|
23
|
+
/** The form a scene's undo entries are recorded in. A serialized history
|
|
24
|
+
* carries it, and one carrying another is not restored. Form 2 holds the
|
|
25
|
+
* scene's own ops for every edit; before it, an `applyBatch` entry held the
|
|
26
|
+
* ops it was given. */
|
|
27
|
+
declare const SCENE_HISTORY_FORM = 2;
|
|
28
|
+
/** What `Scene.serializeHistory` answers with. */
|
|
29
|
+
interface SerializedSceneHistory extends SerializedHistory {
|
|
30
|
+
form: typeof SCENE_HISTORY_FORM;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface LayerRecordBase<TLayer extends string> {
|
|
34
|
+
id: TLayer;
|
|
35
|
+
visible: boolean;
|
|
36
|
+
locked: boolean;
|
|
37
|
+
/** Draw this layer as a parallax plane: through a view derived from the
|
|
38
|
+
* camera's (see `deriveParallaxView`), and picked through the same one.
|
|
39
|
+
* Absent means the layer moves with the camera. */
|
|
40
|
+
parallax?: ParallaxOpts;
|
|
41
|
+
/** A non-printing layer of aids — measurements, notes — rather than content.
|
|
42
|
+
* Its nodes draw on the canvas and save with the scene, but export leaves
|
|
43
|
+
* them out and content picking passes through them. Read it through
|
|
44
|
+
* `isAnnotationLayer`. Absent means content. */
|
|
45
|
+
annotation?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** A layer declared when the scene was created. Fixed set, no display name —
|
|
48
|
+
* these are the kit's own render bands, not something a user manages. */
|
|
49
|
+
interface SystemLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
|
|
50
|
+
kind: 'system';
|
|
51
|
+
}
|
|
52
|
+
/** A layer the user created and can rename, reorder or delete. */
|
|
53
|
+
interface UserLayerRecord<TLayer extends string> extends LayerRecordBase<TLayer> {
|
|
54
|
+
kind: 'user';
|
|
55
|
+
name: string;
|
|
56
|
+
}
|
|
57
|
+
/** Per-layer metadata held by the scene: whether it is visible and locked,
|
|
58
|
+
* and where it sits in the render stack. Distinct from a node's `layer` tag,
|
|
59
|
+
* which merely names one of these. */
|
|
60
|
+
type LayerRecord<TLayer extends string> = SystemLayerRecord<TLayer> | UserLayerRecord<TLayer>;
|
|
61
|
+
/** One of the layers a scene is created with. */
|
|
62
|
+
interface SystemLayerSpec<TLayer extends string> {
|
|
63
|
+
id: TLayer;
|
|
64
|
+
visible?: boolean;
|
|
65
|
+
locked?: boolean;
|
|
66
|
+
/** See `LayerRecord.parallax`. */
|
|
67
|
+
parallax?: ParallaxOpts;
|
|
68
|
+
/** See `LayerRecord.annotation`. */
|
|
69
|
+
annotation?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** Argument to `Scene.addLayer`. Always produces a `UserLayerRecord`
|
|
72
|
+
* (`kind: 'user'`). */
|
|
73
|
+
interface AddLayerSpec<TLayer extends string> {
|
|
74
|
+
id: TLayer;
|
|
75
|
+
name: string;
|
|
76
|
+
/** Default `true`. */
|
|
77
|
+
visible?: boolean;
|
|
78
|
+
/** Default `false`. */
|
|
79
|
+
locked?: boolean;
|
|
80
|
+
/** See `LayerRecord.parallax`. */
|
|
81
|
+
parallax?: ParallaxOpts;
|
|
82
|
+
/** See `LayerRecord.annotation`. */
|
|
83
|
+
annotation?: boolean;
|
|
84
|
+
/** Render-stack position. Default: top of stack (highest render index). */
|
|
85
|
+
index?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** A pose a container's layout wrote — reported by `Scene.onReflow` — in the
|
|
89
|
+
* node's stored frame. */
|
|
90
|
+
interface LayoutMove<TPose> {
|
|
91
|
+
id: NodeId;
|
|
92
|
+
from: TPose;
|
|
93
|
+
to: TPose;
|
|
94
|
+
}
|
|
95
|
+
/** How a scene reads and resizes a laid-out container's bounds. */
|
|
96
|
+
interface LayoutFrame<TPose> {
|
|
97
|
+
/** The container's bounds, from its world pose. Default: the pose's own
|
|
98
|
+
* `x`/`y`/`width`/`height`; a pose without them is not laid out. */
|
|
99
|
+
bounds?(pose: TPose): ContainerBounds | null;
|
|
100
|
+
/** `pose` resized from bounds `from` to `to`, for a layout that grows its
|
|
101
|
+
* container. Default: `to`'s fields written over the pose. */
|
|
102
|
+
remap?(pose: TPose, from: ContainerBounds, to: ContainerBounds): TPose;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Folding a node's pose up its parent chain to world, and back down. */
|
|
106
|
+
/** Minimal adapter needed by `composeWorldPose` and friends — pose lookup plus parent walk. */
|
|
107
|
+
interface PoseAdapter<TPose> {
|
|
108
|
+
getPose(id: string): TPose;
|
|
109
|
+
getParent(id: string): string | null;
|
|
110
|
+
/** Whether `id`'s pose is a frame its children are expressed in. Absent
|
|
111
|
+
* means every node is one. A container whose pose derives from its children
|
|
112
|
+
* is not: its children share its frame, so the fold passes over it. */
|
|
113
|
+
definesFrame?(id: string): boolean;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* What a container's pose does to its children under a `compose`: nothing,
|
|
117
|
+
* an offset, or a whole frame. `'rigid'` is the frame: a container's rotation
|
|
118
|
+
* and its `transform` both reach its children, and a child's `transform`
|
|
119
|
+
* holds the skew or stretch its box and rotation cannot.
|
|
120
|
+
*/
|
|
121
|
+
type PoseClosure = 'identity' | 'translation' | 'rigid';
|
|
122
|
+
/** Consumer's pose-composition strategy for hierarchical scenes. `compose`
|
|
123
|
+
* folds a child's pose (in parent's frame) up to the next frame; `decompose`
|
|
124
|
+
* is its inverse. Default is IDENTITY — an absolute-pose scene where every
|
|
125
|
+
* node already stores world coords (parent is grouping-only, no transform). */
|
|
126
|
+
interface PoseComposition<TPose> {
|
|
127
|
+
compose(parent: TPose, child: TPose): TPose;
|
|
128
|
+
decompose(parent: TPose, world: TPose): TPose;
|
|
129
|
+
closure: PoseClosure;
|
|
130
|
+
}
|
|
131
|
+
/** Default pose-composition strategy: IDENTITY, an absolute-pose scene. */
|
|
132
|
+
declare const IDENTITY_POSE_COMPOSITION: PoseComposition<unknown>;
|
|
133
|
+
/** Whether `composition` makes a container's pose a frame, so a stored pose
|
|
134
|
+
* is local to it. False for the absolute-pose model. */
|
|
135
|
+
declare function composesFrames(composition: {
|
|
136
|
+
closure: PoseClosure;
|
|
137
|
+
}): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Walk `id`'s parent chain and fold local poses into a world pose via
|
|
140
|
+
* `compose`. Cycle-safe.
|
|
141
|
+
*
|
|
142
|
+
* `compose(parent, child)` interprets `child` as expressed *in `parent`'s
|
|
143
|
+
* local frame* and returns the equivalent pose in the next frame up.
|
|
144
|
+
*/
|
|
145
|
+
declare function composeWorldPose<TPose>(adapter: PoseAdapter<TPose>, id: string, compose: (parent: TPose, child: TPose) => TPose): TPose;
|
|
146
|
+
/**
|
|
147
|
+
* Convert `worldPose` into a local pose expressed under `newParentId`'s
|
|
148
|
+
* frame, so a reparented child keeps its visual world position.
|
|
149
|
+
*
|
|
150
|
+
* `decompose(parent, world)` returns the local pose `child` such that
|
|
151
|
+
* `compose(parent, child) === world`. Pass `newParentId === null` for the
|
|
152
|
+
* root frame; the function returns `worldPose` unchanged.
|
|
153
|
+
*/
|
|
154
|
+
declare function rebaseLocalPose<TPose>(adapter: PoseAdapter<TPose>, worldPose: TPose, newParentId: string | null, compose: (parent: TPose, child: TPose) => TPose, decompose: (parent: TPose, world: TPose) => TPose): TPose;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Where a reported pose write came from.
|
|
158
|
+
*
|
|
159
|
+
* - `'call'` — a scene method called directly, alone or inside `scene.batch`:
|
|
160
|
+
* a button's `scene.setPose`, a `scene.add`.
|
|
161
|
+
* - `'ops'` — ops applied as one edit through `applyBatch` or `history.apply`,
|
|
162
|
+
* which is how actions commit: a drag's release, a resize, a nudge, an align.
|
|
163
|
+
* - `'undo'` / `'redo'` — a history step, a jump through the history included.
|
|
164
|
+
* - `'layout'` — a container's layout arranging what a live edit changed; also
|
|
165
|
+
* reported to `onReflow`.
|
|
166
|
+
* - `'untracked'` — a write inside `scene.untracked`, such as a pose target
|
|
167
|
+
* committing an animation's destination.
|
|
168
|
+
*/
|
|
169
|
+
type PoseWriteOrigin = 'call' | 'ops' | 'undo' | 'redo' | 'layout' | 'untracked';
|
|
170
|
+
/** One node's pose as a scene change left it, in the node's stored frame. */
|
|
171
|
+
interface PoseWrite<TPose> {
|
|
172
|
+
id: NodeId;
|
|
173
|
+
/** The pose before the change; `undefined` for a node the change added. */
|
|
174
|
+
from: TPose | undefined;
|
|
175
|
+
to: TPose;
|
|
176
|
+
origin: PoseWriteOrigin;
|
|
177
|
+
/** The edit's label (`'setPose'`, a batch's, an action's `'Move'`) for
|
|
178
|
+
* `'call'` and `'ops'`; `undefined` otherwise. */
|
|
179
|
+
label?: string;
|
|
180
|
+
}
|
|
181
|
+
/** A removed node as it was last shown, with the descendants it took along. */
|
|
182
|
+
interface RemovedNode<TPose, TNode = unknown> {
|
|
183
|
+
/** The node as it stood before the change removed it. */
|
|
184
|
+
node: TNode;
|
|
185
|
+
/** Where it was shown, override included, in its stored frame. */
|
|
186
|
+
pose: TPose;
|
|
187
|
+
children: readonly RemovedNode<TPose, TNode>[];
|
|
188
|
+
}
|
|
189
|
+
/** One node a scene change removed, a removal's root: its descendants ride
|
|
190
|
+
* beneath it rather than being reported apart. */
|
|
191
|
+
interface PoseRemoval<TPose, TNode = unknown> extends RemovedNode<TPose, TNode> {
|
|
192
|
+
id: NodeId;
|
|
193
|
+
/** The parent it was removed from, which may still be in the scene. */
|
|
194
|
+
parent: NodeId | null;
|
|
195
|
+
origin: PoseWriteOrigin;
|
|
196
|
+
label?: string;
|
|
197
|
+
}
|
|
198
|
+
/** What a scene reports about the poses its edits write. */
|
|
199
|
+
interface ScenePoseReports<TPose, TNode = unknown> {
|
|
200
|
+
/** Called with the poses each live edit's layout pass wrote, after the
|
|
201
|
+
* edit lands — never for an undo or redo, which restore poses rather than
|
|
202
|
+
* arrange them. What a reflow animation glides from. */
|
|
203
|
+
onReflow(listener: (moves: readonly LayoutMove<TPose>[]) => void): () => void;
|
|
204
|
+
/** Called once per change, before the scene's subscribers hear of it, with
|
|
205
|
+
* every node whose pose the change wrote or that it added, and every node
|
|
206
|
+
* it removed — an undone add among them. A node written back to the pose
|
|
207
|
+
* it had, or both added and removed by the change, is left out of both.
|
|
208
|
+
* Not called for `loadState` or the scene's initial nodes. */
|
|
209
|
+
onPoseWrite(listener: (writes: readonly PoseWrite<TPose>[], removed: readonly PoseRemoval<TPose, TNode>[]) => void): () => void;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* One node's ephemeral presentation override — what a frame loop wants to say
|
|
214
|
+
* about a node without saying it about the document.
|
|
215
|
+
*
|
|
216
|
+
* Not document content: never recorded in history, never in `toJSON`, and
|
|
217
|
+
* writing one does not bump `Scene.getVersion()`. Hoist one entry per node and
|
|
218
|
+
* mutate it in place on a frame loop; `PoseOverrides.commit()` is what makes a
|
|
219
|
+
* mutation visible.
|
|
220
|
+
*/
|
|
221
|
+
interface PoseOverride<TPose> {
|
|
222
|
+
/** Replaces the node's document pose everywhere the render and hit-test
|
|
223
|
+
* paths read one, including the clip a container derives from its pose, and
|
|
224
|
+
* winning over a `derivePose`. Resolved by `effectivePose` — reading
|
|
225
|
+
* `node.pose` directly is how those paths came to disagree about where a
|
|
226
|
+
* node is. */
|
|
227
|
+
pose?: TPose;
|
|
228
|
+
/** Multiplied into the node's painted alpha, on top of any `alphaFor`. */
|
|
229
|
+
alpha?: number;
|
|
230
|
+
/** Replaces the geometry the node paints and is picked by: the path in its data, or the one
|
|
231
|
+
* it derives. It is in the frame a painter draws in, so give `pose` beside it, as the
|
|
232
|
+
* path's bounds with no rotation, or the pose's turn is applied to the path again and the
|
|
233
|
+
* selection chrome stays on the old box. A skinned rig is the writer. */
|
|
234
|
+
path?: Path;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* The scene's ephemeral per-node overrides — see {@link PoseOverride}.
|
|
238
|
+
*
|
|
239
|
+
* The intended shape of a frame is: `set` each node once, mutate the entries
|
|
240
|
+
* in place per frame, `commit()` once. `commit` is not optional bookkeeping —
|
|
241
|
+
* the painter memo keys on pose *reference*, so a mutation without a commit
|
|
242
|
+
* paints the previous frame with no error.
|
|
243
|
+
*
|
|
244
|
+
* To promote a frame to document state (dropping a drag, baking an animation),
|
|
245
|
+
* write it once through `Scene.setPose` and `clear` the override.
|
|
246
|
+
*/
|
|
247
|
+
interface PoseOverrides<TPose> {
|
|
248
|
+
/** Store `entry` for `id` **by reference**; the caller keeps mutating it. */
|
|
249
|
+
set(id: NodeId, entry: PoseOverride<TPose>): void;
|
|
250
|
+
/** The entry `set` stored, by reference — what a writer checks to know
|
|
251
|
+
* whether its own entry is still installed. Painting reads `read`. */
|
|
252
|
+
get(id: NodeId): PoseOverride<TPose> | undefined;
|
|
253
|
+
/** What the node is drawn and picked with: every source of overrides for
|
|
254
|
+
* it folded into one, as of the last write or `commit()`. `undefined` for
|
|
255
|
+
* a node nothing overrides. The object is reused per node. */
|
|
256
|
+
read(id: NodeId): PoseOverride<TPose> | undefined;
|
|
257
|
+
has(id: NodeId): boolean;
|
|
258
|
+
/** The overridden ids, as a snapshot array. */
|
|
259
|
+
ids(): readonly NodeId[];
|
|
260
|
+
clear(id: NodeId): void;
|
|
261
|
+
clearAll(): void;
|
|
262
|
+
/** Publish this frame's in-place mutations: invalidate the painter memo for
|
|
263
|
+
* every overridden node, then notify subscribers. */
|
|
264
|
+
commit(): void;
|
|
265
|
+
/** Notified after every write. The canvas uses this to repaint without a
|
|
266
|
+
* scene version bump. */
|
|
267
|
+
subscribe(fn: () => void): () => void;
|
|
268
|
+
/** Monotonic write counter. A snapshot for observers that poll. */
|
|
269
|
+
getGeneration(): number;
|
|
270
|
+
/** A claim on some nodes' poses for a writer that publishes a whole frame
|
|
271
|
+
* at a time: a gesture's preview, a layout run. Each call is a new claim. */
|
|
272
|
+
hold(): PoseHold<TPose>;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* One writer's claim on some nodes' pose overrides, from
|
|
276
|
+
* {@link PoseOverrides.hold}.
|
|
277
|
+
*
|
|
278
|
+
* A hold knows which entries are its own, so several writers share the table
|
|
279
|
+
* without clearing each other: a drag and a layout run each publish their
|
|
280
|
+
* frame, and each sees the other's nodes as pinned.
|
|
281
|
+
*/
|
|
282
|
+
interface PoseHold<TPose> {
|
|
283
|
+
/** Publish this frame's poses. It is the whole picture, not a delta: an id
|
|
284
|
+
* the frame leaves out is released. Subscribers are notified once. */
|
|
285
|
+
set(poses: Iterable<readonly [NodeId, TPose]>): void;
|
|
286
|
+
/** The poses other writers are publishing, by id. */
|
|
287
|
+
others(): ReadonlyMap<NodeId, TPose>;
|
|
288
|
+
/** Release every id still held. An id whose entry another writer has since
|
|
289
|
+
* replaced is left alone: that writer owns it now. When the frame is being
|
|
290
|
+
* committed to the document, call this after the write lands, or the scene
|
|
291
|
+
* answers with the old pose in between. */
|
|
292
|
+
drop(): void;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** One layer as it appears in a snapshot. A snapshot written before layer
|
|
296
|
+
* kind was serialized carries neither field, and loads as a system layer —
|
|
297
|
+
* which is what every layer in such a snapshot was. */
|
|
298
|
+
interface SerializedLayer<TLayer extends string> extends SystemLayerSpec<TLayer> {
|
|
299
|
+
kind?: 'system' | 'user';
|
|
300
|
+
/** Present on a user layer, absent on a system one. */
|
|
301
|
+
name?: string;
|
|
302
|
+
}
|
|
303
|
+
/** JSON-serializable shape of a Scene's current state. Produced by
|
|
304
|
+
* `scene.toJSON()`; consumed by `sceneFromJSON()`. Function fields
|
|
305
|
+
* (e.g., `clipFromPose`) appear as string keys (`clipFromPoseKey`) and
|
|
306
|
+
* are resolved through `SceneRegistry` at load time. */
|
|
307
|
+
interface SerializedScene<TData, TLayer extends string, TPose> {
|
|
308
|
+
version: 1;
|
|
309
|
+
/** The whole layer stack, system and user alike — the name predates user
|
|
310
|
+
* layers and is kept so existing snapshots still parse. */
|
|
311
|
+
systemLayers: readonly SerializedLayer<TLayer>[];
|
|
312
|
+
nodes: readonly SerializedNode<TData, TLayer, TPose>[];
|
|
313
|
+
}
|
|
314
|
+
/** JSON-serializable shape of a single node. Mirrors `AddNodeSpec` but
|
|
315
|
+
* with function fields replaced by registry keys. */
|
|
316
|
+
interface SerializedNode<TData, TLayer extends string, TPose> {
|
|
317
|
+
id: string;
|
|
318
|
+
kind: 'leaf' | 'container';
|
|
319
|
+
layer: TLayer;
|
|
320
|
+
pose: TPose;
|
|
321
|
+
data: TData;
|
|
322
|
+
/** Parent id; omitted for roots. */
|
|
323
|
+
parent?: string;
|
|
324
|
+
/** Registry key for the container's clip-path factory.
|
|
325
|
+
* Containers only; omitted when the container has no clip. */
|
|
326
|
+
clipFromPoseKey?: string;
|
|
327
|
+
/** Registry key for the container's `copiesFromPose`. Containers only;
|
|
328
|
+
* omitted when it draws no copies. */
|
|
329
|
+
copiesFromPoseKey?: string;
|
|
330
|
+
/** Ids this node's geometry derives from, or `'children'`. Omitted when it
|
|
331
|
+
* derives from nothing. */
|
|
332
|
+
dependsOn?: readonly string[] | 'children';
|
|
333
|
+
/** Mirrors `SceneNode.pickable`. Omitted when the node is pickable. */
|
|
334
|
+
pickable?: boolean;
|
|
335
|
+
/** Mirrors `SceneNode.hidden`. Omitted when the node is shown. */
|
|
336
|
+
hidden?: boolean;
|
|
337
|
+
/** Mirrors `SceneNode.locked`. Omitted when the node is unlocked. */
|
|
338
|
+
locked?: boolean;
|
|
339
|
+
/** Registry key for the node's `derivePath` function. Omitted when it has none. */
|
|
340
|
+
derivePathKey?: string;
|
|
341
|
+
/** Registry key for the node's `derivePose` function. Omitted when it has none. */
|
|
342
|
+
derivePoseKey?: string;
|
|
343
|
+
/** Registry key for the container's layout strategy. Omitted when it has none. */
|
|
344
|
+
layoutKey?: string;
|
|
345
|
+
/** Mirrors `ContainerNode.units`. Omitted when the container declares none. */
|
|
346
|
+
units?: UnitScope;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Axis-aligned rectangle pose with optional rotation. Rotation is in
|
|
351
|
+
* radians, pivoted on the unrotated AABB center; absent === 0.
|
|
352
|
+
*/
|
|
353
|
+
interface RectPose {
|
|
354
|
+
x: number;
|
|
355
|
+
y: number;
|
|
356
|
+
width: number;
|
|
357
|
+
height: number;
|
|
358
|
+
/** Rotation in radians around the unrotated AABB center. Absent === 0. */
|
|
359
|
+
rotation?: number;
|
|
360
|
+
/** A skew or per-axis scale the box and rotation cannot hold; see
|
|
361
|
+
* {@link PoseLinear}. Absent is the identity. */
|
|
362
|
+
transform?: PoseLinear;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* One dependency, as a derivation reads it: the node itself and the pose it is
|
|
367
|
+
* painted at.
|
|
368
|
+
*
|
|
369
|
+
* The node comes along because a connector legitimately reads more than a box
|
|
370
|
+
* — an edge that thickens with its endpoint's weight, or routes only to nodes
|
|
371
|
+
* on a given layer, is answering off `data` and `layer`.
|
|
372
|
+
*/
|
|
373
|
+
interface DerivedDep<TPose, TData = unknown, TLayer extends string = string> {
|
|
374
|
+
node: Node<TData, TLayer, TPose>;
|
|
375
|
+
/** Its override when it has one, else its own derived pose, else the pose
|
|
376
|
+
* the document stores — `effectivePose`, the same answer the renderer uses. */
|
|
377
|
+
pose: TPose;
|
|
378
|
+
/** The path a pose override shows it by, else the one it derives, else
|
|
379
|
+
* `null`; the document reading skips the override, and a `toPose` lookup
|
|
380
|
+
* carries it into the box its `toPose` answers. Read
|
|
381
|
+
* it to place something *along* a dependency: a label on a routed edge.
|
|
382
|
+
* Resolved on first read and memoized on the dependency. */
|
|
383
|
+
readonly path: Path | null;
|
|
384
|
+
}
|
|
385
|
+
/** `F` with its parameters checked bivariantly, as a method's are, so that a
|
|
386
|
+
* `Scene<D, L, MyPose>` is a `Scene<unknown, string, unknown>`. A callback for
|
|
387
|
+
* an unrelated pose is still rejected; one for a narrower pose is not. */
|
|
388
|
+
type Bivariant<F extends (...args: never[]) => unknown> = {
|
|
389
|
+
method(...args: Parameters<F>): ReturnType<F>;
|
|
390
|
+
}['method'];
|
|
391
|
+
/** Computes a node's path from its dependencies: the type of a node's
|
|
392
|
+
* `derivePath` and of each entry in `SceneRegistry.derivePath`. */
|
|
393
|
+
type DerivePathFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(node: Node<TData, TLayer, TPose>, deps: readonly (DerivedDep<TPose, TData, TLayer> | undefined)[]) => Path | null>;
|
|
394
|
+
/** Computes a node's pose from its dependencies: the type of a node's
|
|
395
|
+
* `derivePose` and of each entry in `SceneRegistry.derivePose`. */
|
|
396
|
+
type DerivePoseFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(node: Node<TData, TLayer, TPose>, deps: readonly (DerivedDep<TPose, TData, TLayer> | undefined)[]) => TPose | null>;
|
|
397
|
+
/** A container's clip, from its pose: the type of `ContainerNode.clipFromPose`
|
|
398
|
+
* and of each entry in `SceneRegistry.clipFromPose`. */
|
|
399
|
+
type ClipFromPoseFn<TPose> = Bivariant<(pose: TPose) => Path | null>;
|
|
400
|
+
/** The extra times a container draws its children: the type of
|
|
401
|
+
* `ContainerNode.copiesFromPose` and of each entry in
|
|
402
|
+
* `SceneRegistry.copiesFromPose`. Each affine is in world coordinates and
|
|
403
|
+
* carries the children, as drawn, to one copy. */
|
|
404
|
+
type CopiesFromPoseFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(pose: TPose, node: ContainerNode<TData, TLayer, TPose>) => readonly Affine[] | null>;
|
|
405
|
+
|
|
406
|
+
/** Brand a string as a NodeId. */
|
|
407
|
+
declare const asNodeId: (s: string) => NodeId;
|
|
408
|
+
|
|
409
|
+
interface NodeBase<TData, TLayer extends string, TPose> {
|
|
410
|
+
id: NodeId;
|
|
411
|
+
layer: TLayer;
|
|
412
|
+
pose: TPose;
|
|
413
|
+
data: TData;
|
|
414
|
+
parent: NodeId | null;
|
|
415
|
+
/** Nodes whose poses this node's geometry is computed from. Fixed at add
|
|
416
|
+
* time. Absent or empty means the node's geometry is authored, which is the
|
|
417
|
+
* normal case.
|
|
418
|
+
*
|
|
419
|
+
* `'children'` means "my own children, in child order" — a container that
|
|
420
|
+
* hugs its contents, which a fixed id list cannot express because
|
|
421
|
+
* reparenting would have to maintain it. The two forms differ in lifetime
|
|
422
|
+
* as well as in membership: deleting a node deletes everything that names
|
|
423
|
+
* it in `dependsOn`, but a container outlives the children it derives
|
|
424
|
+
* from — an emptied group is still a group. */
|
|
425
|
+
dependsOn?: readonly NodeId[] | 'children';
|
|
426
|
+
/** Whether the hit-test walk can return this node. Default `true`; `false`
|
|
427
|
+
* makes it transparent to picking, so a click on it lands on whatever is
|
|
428
|
+
* behind — normally its own container.
|
|
429
|
+
*
|
|
430
|
+
* For content a container owns rather than content the user selects on its
|
|
431
|
+
* own: the label inside a box, a body's rows. It does not hide the node
|
|
432
|
+
* from anything else — it still paints, still clips, and a consumer can
|
|
433
|
+
* still select it by id. */
|
|
434
|
+
pickable?: boolean;
|
|
435
|
+
/** Not drawn, with its whole subtree: picking, area selection, select-all,
|
|
436
|
+
* snapping and the selection pass over it, and an SVG export writes it with
|
|
437
|
+
* `display="none"`. Absent means shown; `Scene.isHidden` folds in its
|
|
438
|
+
* ancestors' flags and its layer's visibility. */
|
|
439
|
+
hidden?: boolean;
|
|
440
|
+
/** Out of reach, with its whole subtree: still drawn, but picking and area
|
|
441
|
+
* selection pass over it, the selection drops it, and every edit to it
|
|
442
|
+
* throws, as on a locked layer. Absent means unlocked; `Scene.isLocked`
|
|
443
|
+
* folds in its ancestors' and its layer's. */
|
|
444
|
+
locked?: boolean;
|
|
445
|
+
/** Computes this node's path from its dependencies, in `dependsOn` order —
|
|
446
|
+
* each one the node and the pose it is painted at.
|
|
447
|
+
* A dependency that has been removed arrives as `undefined`.
|
|
448
|
+
* Returning `null` means "nothing to draw right now". Re-evaluated when a
|
|
449
|
+
* dependency's world pose changes, never authored. */
|
|
450
|
+
derivePath?: DerivePathFn<TPose, TData, TLayer>;
|
|
451
|
+
/** Computes this node's pose from its dependencies' poses, the same way
|
|
452
|
+
* `derivePath` computes its path — same `dependsOn` list, same
|
|
453
|
+
* registry-keyed serialization.
|
|
454
|
+
*
|
|
455
|
+
* Where a derived path is resolved at paint time and reaches only the
|
|
456
|
+
* painter, a derived pose is what the node *is* at: it feeds bounds,
|
|
457
|
+
* hit-testing, selection chrome, snapping and layout, and every reader
|
|
458
|
+
* gets it through `effectivePose`. A pose override still wins over it.
|
|
459
|
+
*
|
|
460
|
+
* Returning `null` means "I have nothing to derive from right now", and
|
|
461
|
+
* the node falls back to its authored `pose`. `setPose` on a derived node
|
|
462
|
+
* still writes that authored pose; it is simply not what anything reads. */
|
|
463
|
+
derivePose?: DerivePoseFn<TPose, TData, TLayer>;
|
|
464
|
+
}
|
|
465
|
+
/** A node with no children — a shape, a label, an image. */
|
|
466
|
+
interface LeafNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
|
|
467
|
+
kind: 'leaf';
|
|
468
|
+
}
|
|
469
|
+
/** A node with an ordered list of children. This is the real group: what
|
|
470
|
+
* Cmd+G creates, what SVG `<g>` round-trips to. A container has its own pose,
|
|
471
|
+
* which its children's poses are relative to, and may optionally clip them. */
|
|
472
|
+
interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
|
|
473
|
+
kind: 'container';
|
|
474
|
+
children: NodeId[];
|
|
475
|
+
/** Optional clip-path source. Re-evaluated each render. Returning `null`
|
|
476
|
+
* means "no clip for this container right now"; an empty / zero-area path
|
|
477
|
+
* means "clip everything out" (children render nowhere). */
|
|
478
|
+
clipFromPose?: ClipFromPoseFn<TPose>;
|
|
479
|
+
/** Draws the whole subtree again under each affine it returns, on top of
|
|
480
|
+
* the original, which still draws once as authored. The copies are paint,
|
|
481
|
+
* not nodes: nothing stores them, so they follow every edit to the
|
|
482
|
+
* children, and a pick that lands on one answers with the child it copies.
|
|
483
|
+
* A copy is a copy of the clipped content — the clip travels with it.
|
|
484
|
+
* Re-evaluated each render; `null` or `[]` draws no copies. */
|
|
485
|
+
copiesFromPose?: CopiesFromPoseFn<TPose, TData, TLayer>;
|
|
486
|
+
/** How this container arranges its children. Whenever the container's
|
|
487
|
+
* child set or order changes, or its bounds change size, the scene hands
|
|
488
|
+
* the change to the strategy — `depart` for children that left it,
|
|
489
|
+
* `arrive` for children that joined it, `childPoses` otherwise — and records the poses it writes in the same
|
|
490
|
+
* undo entry as the change. A drag reads it too: it is the layout `move`
|
|
491
|
+
* reflows and drops against. */
|
|
492
|
+
layout?: LayoutStrategy<TPose>;
|
|
493
|
+
/** The unit system this container's contents are written in, and what one
|
|
494
|
+
* of its base units is worth in the enclosing scope's. It covers the
|
|
495
|
+
* children, not the container; `sceneUnitScopes` reads the chain. */
|
|
496
|
+
units?: UnitScope;
|
|
497
|
+
}
|
|
498
|
+
/** A node in the scene tree: either a leaf or a container. Re-exported
|
|
499
|
+
* publicly as `SceneNode`, to avoid colliding with the DOM's `Node`. */
|
|
500
|
+
type Node<TData, TLayer extends string, TPose = RectPose> = LeafNode<TData, TLayer, TPose> | ContainerNode<TData, TLayer, TPose>;
|
|
501
|
+
/** What `Scene.add` needs to mint a node. Everything except the id is
|
|
502
|
+
* required; the id is generated unless one is supplied. */
|
|
503
|
+
interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
|
|
504
|
+
kind: 'leaf' | 'container';
|
|
505
|
+
layer: TLayer;
|
|
506
|
+
pose: TPose;
|
|
507
|
+
data: TData;
|
|
508
|
+
parent?: NodeId | null;
|
|
509
|
+
index?: number;
|
|
510
|
+
/** Explicit id wins over the Scene's `generateId` and the kit default. */
|
|
511
|
+
id?: NodeId;
|
|
512
|
+
/** Mirrors `SceneNode.pickable`. Omit for the default, which is pickable. */
|
|
513
|
+
pickable?: boolean;
|
|
514
|
+
/** Mirrors `SceneNode.hidden`. */
|
|
515
|
+
hidden?: boolean;
|
|
516
|
+
/** Mirrors `SceneNode.locked`. */
|
|
517
|
+
locked?: boolean;
|
|
518
|
+
/** Only meaningful when `kind === 'container'`. Attach a clip-path function
|
|
519
|
+
* to the node; ignored for leaves. Mirrors `ContainerNode.clipFromPose`. */
|
|
520
|
+
clipFromPose?: ClipFromPoseFn<TPose>;
|
|
521
|
+
/** Mirrors `ContainerNode.copiesFromPose`; ignored for leaves. */
|
|
522
|
+
copiesFromPose?: CopiesFromPoseFn<TPose, TData, TLayer>;
|
|
523
|
+
/** Mirrors `SceneNode.dependsOn`. */
|
|
524
|
+
dependsOn?: readonly NodeId[] | 'children';
|
|
525
|
+
/** Mirrors `SceneNode.derivePath`. Taken as a live function; its registry key is
|
|
526
|
+
* looked up from it, never passed in. */
|
|
527
|
+
derivePath?: DerivePathFn<TPose, TData, TLayer>;
|
|
528
|
+
/** Mirrors `SceneNode.derivePose`, on the same terms as `derivePath`. */
|
|
529
|
+
derivePose?: DerivePoseFn<TPose, TData, TLayer>;
|
|
530
|
+
/** Mirrors `ContainerNode.layout`; ignored for leaves. */
|
|
531
|
+
layout?: LayoutStrategy<TPose>;
|
|
532
|
+
/** Mirrors `ContainerNode.units`; ignored for leaves. */
|
|
533
|
+
units?: UnitScope;
|
|
534
|
+
}
|
|
535
|
+
/** A custom scene mutation registered with `Scene.registerOp`: how to apply
|
|
536
|
+
* it and how to undo it. The pair is what makes it participate in history. */
|
|
537
|
+
interface RegisteredOp<P> {
|
|
538
|
+
apply: (payload: P) => void;
|
|
539
|
+
revert: (payload: P) => void;
|
|
540
|
+
/** Opts this kind into coalescing under `UseSceneOptions.coalesceWindowMs`:
|
|
541
|
+
* two entries of this kind that return the same key inside the window
|
|
542
|
+
* merge, and undoing the merged entry calls `revert` with the first
|
|
543
|
+
* payload only. Declare it only when `revert` restores an absolute state
|
|
544
|
+
* (a stored "from" value), never for a relative payload such as a delta.
|
|
545
|
+
* Omitted, or returning `undefined`, the op is always its own entry. */
|
|
546
|
+
coalesceKey?: (payload: P) => string | undefined;
|
|
547
|
+
}
|
|
548
|
+
/** Per-scene registry mapping string keys to live function references.
|
|
549
|
+
* Passed to `createScene({ ..., registry })` and `sceneFromJSON(json, { registry })`.
|
|
550
|
+
* Each function-field type has its own keyed map. */
|
|
551
|
+
interface SceneRegistry<TPose, TData = unknown, TLayer extends string = string> {
|
|
552
|
+
/** Maps registry keys to `clipFromPose` factory functions for container nodes. */
|
|
553
|
+
clipFromPose?: Readonly<Record<string, ClipFromPoseFn<TPose>>>;
|
|
554
|
+
/** Maps registry keys to `copiesFromPose` functions for container nodes. */
|
|
555
|
+
copiesFromPose?: Readonly<Record<string, CopiesFromPoseFn<TPose, TData, TLayer>>>;
|
|
556
|
+
/** Maps registry keys to `derivePath` functions for nodes with `dependsOn`. */
|
|
557
|
+
derivePath?: Readonly<Record<string, DerivePathFn<TPose, TData, TLayer>>>;
|
|
558
|
+
/** Maps registry keys to `derivePose` functions for nodes with `dependsOn`. */
|
|
559
|
+
derivePose?: Readonly<Record<string, DerivePoseFn<TPose, TData, TLayer>>>;
|
|
560
|
+
/** Maps registry keys to container layout strategies. */
|
|
561
|
+
layout?: Readonly<Record<string, LayoutStrategy<TPose>>>;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Decides what one edit's changes to containers do to their children.
|
|
565
|
+
* `arrivals` maps each container to the ids that joined it — by an `add`
|
|
566
|
+
* under it or a `move` into it, whatever op or call made them — in the order
|
|
567
|
+
* they arrived. `changed` names every container whose child set or order
|
|
568
|
+
* changed, or whose pose changed size, arrivals included. Both are read once
|
|
569
|
+
* the edit's other mutations have landed.
|
|
570
|
+
*
|
|
571
|
+
* Return the poses to write, in each node's stored frame; they become part of
|
|
572
|
+
* the same edit, and so of the same undo step. An empty map writes nothing.
|
|
573
|
+
* Return `null` to refuse: the whole edit is reverted (see
|
|
574
|
+
* `SceneArrivalRefused`).
|
|
575
|
+
*
|
|
576
|
+
* Runs only for live edits. Undo, redo and a restored history replay the
|
|
577
|
+
* arrangement that was decided the first time. With none installed, a scene
|
|
578
|
+
* holding declared layouts (`ContainerNode.layout`) runs its own.
|
|
579
|
+
*/
|
|
580
|
+
type SceneArrivalHandler<TPose> = (arrivals: ReadonlyMap<NodeId, readonly NodeId[]>, changed: ReadonlySet<NodeId>,
|
|
581
|
+
/** The nodes that left each container in the edit, by the container they
|
|
582
|
+
* left — removed, or moved out. */
|
|
583
|
+
departures: ReadonlyMap<NodeId, readonly NodeId[]>) => ReadonlyMap<NodeId, TPose> | null;
|
|
584
|
+
/**
|
|
585
|
+
* The kit-owned scene tree: nodes, layers, and the undo history over both.
|
|
586
|
+
*
|
|
587
|
+
* A scene is logical, not visual — it says what exists and where, and nothing
|
|
588
|
+
* about how it is painted. Every mutating method is undoable, and reads are
|
|
589
|
+
* snapshots rather than live views. Nodes are addressed by `NodeId`; hold ids
|
|
590
|
+
* across mutations, not node objects.
|
|
591
|
+
*
|
|
592
|
+
* Three type parameters keep it domain-agnostic: `TData` is the app's payload,
|
|
593
|
+
* which the kit never inspects; `TPose` is the transform shape, `RectPose` by
|
|
594
|
+
* default; `TLayer` is the union of layer names.
|
|
595
|
+
*/
|
|
596
|
+
interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePoseReports<TPose, Node<TData, TLayer, TPose>> {
|
|
597
|
+
readonly nodes: ReadonlyMap<NodeId, Node<TData, TLayer, TPose>>;
|
|
598
|
+
readonly roots: readonly NodeId[];
|
|
599
|
+
readonly layers: readonly LayerRecord<TLayer>[];
|
|
600
|
+
/** The registry this scene resolves node functions against — the consumer's
|
|
601
|
+
* entries over the kit's. */
|
|
602
|
+
readonly registry: SceneRegistry<TPose, TData, TLayer>;
|
|
603
|
+
/** See {@link UseSceneOptions.composition}. */
|
|
604
|
+
readonly composition: PoseComposition<TPose>;
|
|
605
|
+
get(id: NodeId): Node<TData, TLayer, TPose> | undefined;
|
|
606
|
+
/** A token for the node `id` names right now, for telling one node from a
|
|
607
|
+
* later one that reuses its id. It holds for as long as the node stays in
|
|
608
|
+
* the scene, whatever edits it takes, and is different every time the id
|
|
609
|
+
* enters the scene — by `add`, by an undo or redo that brings it back, or
|
|
610
|
+
* by `loadState`. `undefined` when `id` is not in the scene. Compare tokens
|
|
611
|
+
* for equality only; their order means nothing. */
|
|
612
|
+
incarnation(id: NodeId): number | undefined;
|
|
613
|
+
childrenOf(id: NodeId): readonly NodeId[];
|
|
614
|
+
ancestorsOf(id: NodeId): readonly NodeId[];
|
|
615
|
+
renderOrder(): Iterable<NodeId>;
|
|
616
|
+
/** The same layer-major sequence as {@link Scene.renderOrder}, as the nodes
|
|
617
|
+
* themselves. Prefer this wherever the ids are only going to be resolved
|
|
618
|
+
* back to nodes. Cached until a structural edit, so repeat calls hand back
|
|
619
|
+
* the same array — a snapshot, not a live view, and not yours to mutate. */
|
|
620
|
+
renderOrderNodes(): readonly Node<TData, TLayer, TPose>[];
|
|
621
|
+
/** The nodes on one layer, in render order. Cached alongside
|
|
622
|
+
* {@link Scene.renderOrderNodes} until a structural edit. A snapshot, not
|
|
623
|
+
* a live view, and not yours to mutate. An unknown layer id yields an
|
|
624
|
+
* empty array. */
|
|
625
|
+
nodesOnLayer(layer: TLayer): readonly Node<TData, TLayer, TPose>[];
|
|
626
|
+
/** A fresh id from this scene's `generateId`, or the kit default: the id
|
|
627
|
+
* `add` would give a spec with none. For code that has to name a node
|
|
628
|
+
* before it exists, such as one building an insert op. */
|
|
629
|
+
mintId(): NodeId;
|
|
630
|
+
add(spec: AddNodeSpec<TData, TLayer, TPose>): NodeId;
|
|
631
|
+
/** Delete `id`, its **entire subtree**, and **everything that derives from**
|
|
632
|
+
* any of those nodes — a node listing one of them in `dependsOn` goes too,
|
|
633
|
+
* along with its own subtree, transitively. A dependent can live anywhere in
|
|
634
|
+
* the tree, so this deletes nodes the caller never named and may unlink
|
|
635
|
+
* several disjoint subtrees at once. Recorded as one undoable step; `undo()`
|
|
636
|
+
* restores every one of them where it was, child order intact. */
|
|
637
|
+
remove(id: NodeId): void;
|
|
638
|
+
/** {@link remove} over several roots at once, as a **single** undoable step.
|
|
639
|
+
* Ids resolve against the tree as it stands at the call, so an id that
|
|
640
|
+
* another one would cascade away is absorbed rather than removed twice —
|
|
641
|
+
* which is what makes it safe to pass a whole selection. Throws if any id is
|
|
642
|
+
* not in the scene; an empty list does nothing and records no step. */
|
|
643
|
+
removeMany(ids: readonly NodeId[]): void;
|
|
644
|
+
/** Every node {@link removeMany} would take if given `ids`: each id, its
|
|
645
|
+
* subtree, everything deriving from any of those, and those nodes' subtrees
|
|
646
|
+
* in turn. Ids not in the scene come back unchanged.
|
|
647
|
+
*
|
|
648
|
+
* A set, not a restore order: a dependent can be reached before the parent
|
|
649
|
+
* it sits under, which is also in the closure. */
|
|
650
|
+
removalClosure(ids: readonly NodeId[]): readonly NodeId[];
|
|
651
|
+
update(id: NodeId, patch: {
|
|
652
|
+
data: TData;
|
|
653
|
+
}): void;
|
|
654
|
+
setPose(id: NodeId, pose: TPose): void;
|
|
655
|
+
/** Retag `id` to `layer`. On a **container this cascades**: every descendant
|
|
656
|
+
* is moved to the same layer, recorded as a **single** undo step.
|
|
657
|
+
*
|
|
658
|
+
* Invariants:
|
|
659
|
+
* - **Layer floor** — a child may not render below its parent, so retagging
|
|
660
|
+
* to a layer *below* the node's parent throws. Retagging to the parent's
|
|
661
|
+
* layer or any higher one is allowed; a node with no parent is
|
|
662
|
+
* unconstrained.
|
|
663
|
+
* - **No-op elision** — setting the layer a node already has does nothing
|
|
664
|
+
* and pushes **no** history entry. */
|
|
665
|
+
setLayer(id: NodeId, layer: TLayer): void;
|
|
666
|
+
/** Point `id` at a different set of dependencies — retargeting an edge's end
|
|
667
|
+
* onto another node, or switching a container between an id list and
|
|
668
|
+
* `'children'`. Recorded as one undoable step.
|
|
669
|
+
*
|
|
670
|
+
* Order is significant: a derivation reads its dependencies positionally,
|
|
671
|
+
* so `[b, a]` is not `[a, b]`. Ids need not be in the scene — a declared
|
|
672
|
+
* dependency that appears later invalidates the node when it does, the same
|
|
673
|
+
* as one declared at `add`. Passing `undefined` drops the declaration, after
|
|
674
|
+
* which nothing cascades the node away.
|
|
675
|
+
*
|
|
676
|
+
* **No-op elision** — declaring what the node already declares does nothing
|
|
677
|
+
* and pushes no history entry. */
|
|
678
|
+
setDependsOn(id: NodeId, dependsOn: readonly NodeId[] | 'children' | undefined): void;
|
|
679
|
+
/** Give container `id` a different layout — a strategy, its key in
|
|
680
|
+
* `SceneRegistry.layout`, or `null` for none — and re-arrange its children
|
|
681
|
+
* under it, as one undoable step. Throws for a leaf, or a key the registry
|
|
682
|
+
* does not hold. A registered layout is recorded by its key, so a
|
|
683
|
+
* serialized history restores it; an unregistered one lives only as long
|
|
684
|
+
* as the session.
|
|
685
|
+
*
|
|
686
|
+
* **No-op elision** — setting the layout a container already has does
|
|
687
|
+
* nothing and pushes no history entry. */
|
|
688
|
+
setLayout(id: NodeId, layout: LayoutStrategy<TPose> | string | null): void;
|
|
689
|
+
/** Reparent `id` under `parent` (or to a root when `parent` is `null`) at
|
|
690
|
+
* `index` within the new sibling list, appending when `index` is omitted.
|
|
691
|
+
* Siblings are reindexed. Recorded as one undoable step.
|
|
692
|
+
*
|
|
693
|
+
* Rejected (throws) when:
|
|
694
|
+
* - `parent` exists but is a **leaf**, not a container;
|
|
695
|
+
* - the move would form a **cycle** — `parent` is `id` itself or one of
|
|
696
|
+
* `id`'s own descendants;
|
|
697
|
+
* - it would drop `id` **below its new parent's layer** (child may not
|
|
698
|
+
* render below its parent).
|
|
699
|
+
*
|
|
700
|
+
* `move(id, null)` — detaching to a root — is always allowed regardless of
|
|
701
|
+
* layer, since a root has no parent to render beneath. */
|
|
702
|
+
move(id: NodeId, parent: NodeId | null, index?: number): void;
|
|
703
|
+
/** Shift `id` to `index` within its **current** parent's child list. Unlike
|
|
704
|
+
* {@link move}, the parent never changes — only sibling order. */
|
|
705
|
+
reorder(id: NodeId, index: number): void;
|
|
706
|
+
/** Show or hide a layer. Hiding drops its nodes from the selection. */
|
|
707
|
+
setLayerVisible(layer: TLayer, visible: boolean): void;
|
|
708
|
+
/** Lock or unlock a layer. A locked layer still paints, but its nodes are
|
|
709
|
+
* out of reach: picking and area selection pass over them, the selection
|
|
710
|
+
* drops them, and every node mutation on them throws. Locking is never
|
|
711
|
+
* blocked by the lock, and neither are the other layer operations. */
|
|
712
|
+
setLayerLocked(layer: TLayer, locked: boolean): void;
|
|
713
|
+
/** Set or clear (`undefined`) a layer's parallax — see
|
|
714
|
+
* `LayerRecord.parallax`. Undoable; an animation tweening it writes inside
|
|
715
|
+
* {@link Scene.untracked} so no frame becomes an undo step. */
|
|
716
|
+
setLayerParallax(layer: TLayer, parallax: ParallaxOpts | undefined): void;
|
|
717
|
+
/** Whether `id` is locked: it or an ancestor carries `locked`, or sits on a
|
|
718
|
+
* locked layer. A lock covers its whole subtree, whatever layers the
|
|
719
|
+
* descendants are tagged to. An id not in the scene is not locked. */
|
|
720
|
+
isLocked(id: NodeId): boolean;
|
|
721
|
+
/** Whether `id` is not drawn: its own layer is hidden, or it or an ancestor
|
|
722
|
+
* carries `hidden`. A hidden layer hides only the nodes tagged to it. An
|
|
723
|
+
* id not in the scene is not hidden. */
|
|
724
|
+
isHidden(id: NodeId): boolean;
|
|
725
|
+
/** Hide or show node `id` and its subtree — see `SceneNode.hidden`. One
|
|
726
|
+
* undo step; hiding drops the subtree from the selection. Never blocked by
|
|
727
|
+
* a lock, and setting what the node already has records nothing. */
|
|
728
|
+
setHidden(id: NodeId, hidden: boolean): void;
|
|
729
|
+
/** Lock or unlock node `id` and its subtree — see `SceneNode.locked`. One
|
|
730
|
+
* undo step; locking drops the subtree from the selection. Never blocked
|
|
731
|
+
* by a lock, and setting what the node already has records nothing. */
|
|
732
|
+
setLocked(id: NodeId, locked: boolean): void;
|
|
733
|
+
/** Run `fn` with the lock guard lifted, for a programmatic edit that has to
|
|
734
|
+
* reach a locked node. Undo and redo never need it. */
|
|
735
|
+
unlocked<T>(fn: () => T): T;
|
|
736
|
+
addLayer(spec: AddLayerSpec<TLayer>): void;
|
|
737
|
+
/** Drop a user layer and every node tagged to it, as one undoable step.
|
|
738
|
+
* Removal cascades, so this also deletes nodes **on other layers** that
|
|
739
|
+
* derive from a node on this one. */
|
|
740
|
+
removeLayer(layer: TLayer): void;
|
|
741
|
+
renameLayer(layer: TLayer, name: string): void;
|
|
742
|
+
moveLayer(layer: TLayer, index: number): void;
|
|
743
|
+
registerOp<P>(kind: string, handler: RegisteredOp<P>): void;
|
|
744
|
+
recordOp<P>(op: {
|
|
745
|
+
kind: string;
|
|
746
|
+
payload: P;
|
|
747
|
+
}): void;
|
|
748
|
+
/** Install (or clear with `null`) the active-journal accessor after scene
|
|
749
|
+
* construction, for a journal source built with `scene.history` as a
|
|
750
|
+
* dependency. Overrides any `getActiveJournal` set in `UseSceneOptions`. */
|
|
751
|
+
setActiveJournalAccessor(fn: (() => _weasel_js_history.Journal | null) | null): void;
|
|
752
|
+
/** Install what the scene does when nodes join a container, replacing any
|
|
753
|
+
* handler installed before; `null` removes it. Returns a function that
|
|
754
|
+
* removes this handler, and does nothing once another has replaced it.
|
|
755
|
+
* See {@link SceneArrivalHandler}. */
|
|
756
|
+
setArrivalHandler(handler: SceneArrivalHandler<TPose> | null): () => void;
|
|
757
|
+
/** Apply a batch of ops against `adapter` as one undo entry.
|
|
758
|
+
*
|
|
759
|
+
* The entry holds the scene writes the ops made, as a direct call records
|
|
760
|
+
* them, and beside them any op that wrote no scene state, bound to
|
|
761
|
+
* `adapter`. Undo restores those writes; it does not call an op's
|
|
762
|
+
* `invert()` or the adapter again. **What an op states is not recorded**:
|
|
763
|
+
* one applied over a document that already holds its result, as after an
|
|
764
|
+
* `untracked` preview, records a write from that pose to itself, and undo
|
|
765
|
+
* goes nowhere. Put the document back first.
|
|
766
|
+
*
|
|
767
|
+
* The entry lands in the open `batch` when there is one, else on the
|
|
768
|
+
* active journal, else on the scene's own history, where it can coalesce
|
|
769
|
+
* under `coalesceWindowMs` with one whose ops' keys match.
|
|
770
|
+
*
|
|
771
|
+
* Returns false when the arrival handler refused the batch: it is reverted
|
|
772
|
+
* and unrecorded. Inside `batch` it is true; that batch may still refuse. */
|
|
773
|
+
applyBatch(ops: Op[], label: string, adapter: unknown): boolean;
|
|
774
|
+
/** The transient set of active ids — "operate on these N as a unit".
|
|
775
|
+
* Shared by every view over this scene unless a view supplies its own
|
|
776
|
+
* (see `CanvasView.selection`). Not document content: it never appears
|
|
777
|
+
* in `toJSON`. It does ride on history entries, so undo and redo put
|
|
778
|
+
* back the selection an edit was made under; changing it is never an
|
|
779
|
+
* undo step of its own. Removing a node deselects it. */
|
|
780
|
+
getSelection(): readonly NodeId[];
|
|
781
|
+
setSelection(ids: readonly NodeId[]): void;
|
|
782
|
+
/** Per-node pose / alpha overrides the render and hit-test paths read
|
|
783
|
+
* through. Like {@link Scene.getSelection} this is not document content:
|
|
784
|
+
* writes are never recorded, never serialized, and do not bump
|
|
785
|
+
* {@link Scene.getVersion}. See {@link PoseOverrides}. */
|
|
786
|
+
readonly overrides: PoseOverrides<TPose>;
|
|
787
|
+
/** The scene's undo/redo engine, in the shape `@weasel-js/history` defines.
|
|
788
|
+
* Mutating members route through
|
|
789
|
+
* the scene's own wrappers, so an undo driven through this bumps
|
|
790
|
+
* {@link Scene.getVersion} and notifies subscribers exactly as
|
|
791
|
+
* {@link Scene.undo} does; `getVersion` / `subscribe` on it report the
|
|
792
|
+
* engine's history version, not the scene's. */
|
|
793
|
+
readonly history: History;
|
|
794
|
+
undo(): boolean;
|
|
795
|
+
redo(): boolean;
|
|
796
|
+
canUndo(): boolean;
|
|
797
|
+
canRedo(): boolean;
|
|
798
|
+
batch<T>(label: string, fn: () => T): T;
|
|
799
|
+
/** The layout container `id` declares, or `null` for a leaf or a
|
|
800
|
+
* container that declares none. */
|
|
801
|
+
layoutOf(id: NodeId): LayoutStrategy<TPose> | null;
|
|
802
|
+
/** Declare the unit scope of container `id`, or clear it with `null`. */
|
|
803
|
+
setUnits(id: NodeId, units: UnitScope | null): void;
|
|
804
|
+
/** Run `fn` with every mutation applied but none recorded — for writes
|
|
805
|
+
* that are not edits, such as a simulation stepping poses each frame.
|
|
806
|
+
* Undo and redo move between recorded states and never restore an
|
|
807
|
+
* untracked write; the next recorded change starts from whatever the
|
|
808
|
+
* untracked writes left, so undoing it lands there. A `batch` inside
|
|
809
|
+
* records nothing; inside a `batch`, these writes stay out of its entry.
|
|
810
|
+
* Notifies once, reverts `fn`'s writes if it throws, and throws on
|
|
811
|
+
* `applyBatch` and `history.apply` / `applyOps`, which exist to record. */
|
|
812
|
+
untracked<T>(fn: () => T): T;
|
|
813
|
+
/** Read-only snapshot of every history entry currently reachable from
|
|
814
|
+
* the present state. Oldest applied first, then redoable entries in
|
|
815
|
+
* the order they'd be re-applied. Each entry id is stable. */
|
|
816
|
+
historyEntries(): readonly {
|
|
817
|
+
id: string;
|
|
818
|
+
label: string;
|
|
819
|
+
}[];
|
|
820
|
+
/** Index of the "current state". Equals the count of applied entries;
|
|
821
|
+
* `0` means "nothing applied" (initial). */
|
|
822
|
+
historyIndex(): number;
|
|
823
|
+
/** Jump to the given history index, clamped to [0, total]. Returns true
|
|
824
|
+
* if any movement occurred. */
|
|
825
|
+
jumpToHistoryIndex(index: number): boolean;
|
|
826
|
+
/** Snapshot the undo/redo history in a JSON-serializable form (the
|
|
827
|
+
* engine's `SerializedHistory`, marked with the scene's recorded form).
|
|
828
|
+
* An entry holds the scene's own ops, whichever way the edit was made.
|
|
829
|
+
* An op handed to `applyBatch` that wrote no scene state is held as
|
|
830
|
+
* itself, and an entry with a nameless one is dropped. Payload
|
|
831
|
+
* JSON-safety (e.g. typed arrays inside poses) is the caller's concern.
|
|
832
|
+
* Do not call mid-`batch` — the open batch's ops are not yet recorded. */
|
|
833
|
+
serializeHistory(): SerializedSceneHistory;
|
|
834
|
+
/** Replace the undo/redo history from a `serializeHistory()` snapshot.
|
|
835
|
+
* Call on a scene whose node/layer state already matches the snapshot's
|
|
836
|
+
* head state (i.e. right after `loadState` from the paired scene
|
|
837
|
+
* snapshot); node state is NOT mutated. Ops re-registered via
|
|
838
|
+
* `registerOp` before this call round-trip; unknown kinds become no-op
|
|
839
|
+
* placeholders; external ops rebuild via the global op-factory registry
|
|
840
|
+
* and replay against the `setHistoryAdapter` accessor. Restored entries
|
|
841
|
+
* never coalesce with new ones. Notifies once. A snapshot that is not in
|
|
842
|
+
* the current recorded form (see `SCENE_HISTORY_FORM`) is dropped:
|
|
843
|
+
* the history is left as it was. Do not call mid-`batch`:
|
|
844
|
+
* the stacks are replaced underneath the open batch, whose eventual
|
|
845
|
+
* flush would graft onto (and evict against) the restored stacks. */
|
|
846
|
+
restoreHistory(snapshot: SerializedHistory): void;
|
|
847
|
+
/** Install (or clear with `null`) the accessor for the adapter that
|
|
848
|
+
* RESTORED external ops apply against on undo/redo: the ops handed to
|
|
849
|
+
* `applyBatch` that wrote no scene state, such as a selection change,
|
|
850
|
+
* rebuilt from a `restoreHistory` snapshot. Resolved lazily at each
|
|
851
|
+
* apply, so wiring order relative to `restoreHistory` doesn't matter.
|
|
852
|
+
* Live `applyBatch` entries are unaffected (they bind their call-site
|
|
853
|
+
* adapter). If unset when a restored op applies, the op is a debug-warned
|
|
854
|
+
* no-op. */
|
|
855
|
+
setHistoryAdapter(fn: (() => unknown) | null): void;
|
|
856
|
+
/** Snapshot the current scene state to a JSON-serializable shape.
|
|
857
|
+
* History (undo/redo stacks) is NOT captured. Function fields like
|
|
858
|
+
* `ContainerNode.clipFromPose` are translated to string keys via the
|
|
859
|
+
* scene's registry; throws if any function field has no matching key. */
|
|
860
|
+
toJSON(): SerializedScene<TData, TLayer, TPose>;
|
|
861
|
+
/** Replace this scene's entire node + layer state in place from a snapshot
|
|
862
|
+
* produced by `toJSON()`. Unlike `sceneFromJSON`, the existing Scene
|
|
863
|
+
* instance is preserved — holders such as `<SceneCanvas>` keep their
|
|
864
|
+
* reference. History (undo/redo) is cleared, matching `sceneFromJSON`.
|
|
865
|
+
* Bumps `getVersion()` and notifies subscribers exactly once. Selected
|
|
866
|
+
* ids the snapshot does not hold leave the selection, and every pose
|
|
867
|
+
* override is cleared.
|
|
868
|
+
*
|
|
869
|
+
* Throws inside any other edit — `batch`, `untracked`, `applyBatch`, an
|
|
870
|
+
* undo — which would revert to a state this replaces. Throws on an unsupported version or unknown registry/layer ids; on a
|
|
871
|
+
* malformed snapshot the scene is left empty or partially populated (callers should treat a
|
|
872
|
+
* `loadState` throw as fatal and reload). Snapshots from `toJSON()` are
|
|
873
|
+
* always well-formed. */
|
|
874
|
+
loadState(json: SerializedScene<TData, TLayer, TPose>): void;
|
|
875
|
+
subscribe(listener: () => void): () => void;
|
|
876
|
+
/** Monotonically increasing version. Snapshot for `useSyncExternalStore`. */
|
|
877
|
+
getVersion(): number;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/** Pixel dimensions of the canvas viewport. */
|
|
881
|
+
interface ViewportDims {
|
|
882
|
+
width: number;
|
|
883
|
+
height: number;
|
|
884
|
+
}
|
|
885
|
+
/** Options for {@link fitViewToBounds}. */
|
|
886
|
+
interface FitViewToBoundsOptions {
|
|
887
|
+
/** Inset (in CSS px) around the bounds. Default 16. */
|
|
888
|
+
padding?: number;
|
|
889
|
+
/** Defaults to the kit-wide max zoom (`DEFAULT_MAX_ZOOM`). */
|
|
890
|
+
maxScale?: number;
|
|
891
|
+
/** Defaults to the kit-wide min zoom (`DEFAULT_MIN_ZOOM`). */
|
|
892
|
+
minScale?: number;
|
|
893
|
+
/**
|
|
894
|
+
* Fit mode:
|
|
895
|
+
* - `'contain'` (default): uniform scale = `min(availW/w, availH/h)`. Bounds fit entirely; one axis has letterboxing.
|
|
896
|
+
* - `'fill'`: uniform scale = `max(...)`. Bounds overflow viewport on one axis.
|
|
897
|
+
* - `'stretch'`: per-axis scale. Bounds match viewport exactly; scale is non-uniform.
|
|
898
|
+
*/
|
|
899
|
+
mode?: 'contain' | 'fill' | 'stretch';
|
|
900
|
+
/**
|
|
901
|
+
* Where bounds that overflow the viewport on an axis sit, which happens when
|
|
902
|
+
* `minScale` stops the fit or `mode` is `'fill'`. `'center'` (default) shows
|
|
903
|
+
* their middle; `'start'` shows their left or top edge, inset by `padding`.
|
|
904
|
+
* An axis that fits is centered either way.
|
|
905
|
+
*/
|
|
906
|
+
anchor?: 'center' | 'start';
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Compute the target {@link View} that fits `bounds` (world space) inside
|
|
910
|
+
* `viewportDims` (CSS px). The bounds are centered in the viewport with
|
|
911
|
+
* uniform padding on all sides; the resulting scale is clamped to the
|
|
912
|
+
* configured min/max.
|
|
913
|
+
*
|
|
914
|
+
* Empty / zero-sized bounds or viewports cannot be fit — in that case this
|
|
915
|
+
* returns `currentView` unchanged and logs a `console.warn`.
|
|
916
|
+
*/
|
|
917
|
+
declare function fitViewToBounds(bounds: FramedBox, viewportDims: ViewportDims, currentView: View, opts?: FitViewToBoundsOptions): View;
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* `Paint`'s discriminant, open on the string the way `ChromeId` is: the
|
|
921
|
+
* kinds the kit ships, plus whatever a consumer registers.
|
|
922
|
+
*/
|
|
923
|
+
type PaintKind = 'solid' | 'linear-gradient' | 'radial-gradient' | 'conic-gradient' | TileKind | 'texture' | (string & {});
|
|
924
|
+
/**
|
|
925
|
+
* A set of kinds an editor offers as one choice. Kinds sharing a family show
|
|
926
|
+
* as a single segment in a kind bar, named by the family, and the member is
|
|
927
|
+
* picked inside that segment's body. The built-in tiles and `texture` are the
|
|
928
|
+
* `patternFamily`.
|
|
929
|
+
*/
|
|
930
|
+
interface PaintKindFamily {
|
|
931
|
+
id: string;
|
|
932
|
+
label: string;
|
|
933
|
+
/** Glyph for the family's segment. */
|
|
934
|
+
icon?: IconRef;
|
|
935
|
+
}
|
|
936
|
+
/** What a registered kind's editor renders. `PaintInput` in `@weasel-js/ui`
|
|
937
|
+
* is the control that mounts it. */
|
|
938
|
+
interface PaintKindEditorProps {
|
|
939
|
+
value: Paint;
|
|
940
|
+
onInput?(next: Paint): void;
|
|
941
|
+
onChange(next: Paint): void;
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* One paint kind: the renderer's draw slots, plus what an editor and a
|
|
945
|
+
* serializer read.
|
|
946
|
+
*
|
|
947
|
+
* `seed`, `label` and `colorOf` are the editor's slots and every kind has
|
|
948
|
+
* them. The rest are optional because a kind may not need them.
|
|
949
|
+
*/
|
|
950
|
+
interface PaintKindEntry extends PaintDrawKind {
|
|
951
|
+
label: string;
|
|
952
|
+
/** Glyph naming this kind in an editor's kind bar. A kind without one is
|
|
953
|
+
* named by its `label`. */
|
|
954
|
+
icon?: IconRef;
|
|
955
|
+
/** The family this kind is offered under; see {@link PaintKindFamily}. A
|
|
956
|
+
* kind without one is its own segment. */
|
|
957
|
+
family?: PaintKindFamily;
|
|
958
|
+
/** A paint of this kind seeded from a color — what an editor writes when a
|
|
959
|
+
* consumer switches a solid to this kind. */
|
|
960
|
+
seed(fromColor: string): Paint;
|
|
961
|
+
/** The single color this paint shows, or `undefined` when it has none. */
|
|
962
|
+
colorOf(paint: Paint): string | undefined;
|
|
963
|
+
/** Editor slot. */
|
|
964
|
+
Editor?: ComponentType<PaintKindEditorProps>;
|
|
965
|
+
/**
|
|
966
|
+
* The stop list this paint reads as. With `fromStops`, it is what makes a
|
|
967
|
+
* kind a gradient: `listGradientKinds` returns the kinds carrying both, and
|
|
968
|
+
* `switchGradientKind` converts between any two of them through the list.
|
|
969
|
+
*/
|
|
970
|
+
stopsOf?(paint: Paint): GradStop[];
|
|
971
|
+
/** A paint of this kind built from a stop list, in `bounds` units. The
|
|
972
|
+
* converse of `stopsOf`; supply both or neither. */
|
|
973
|
+
fromStops?(stops: GradStop[]): Paint;
|
|
974
|
+
/**
|
|
975
|
+
* The `<defs>` entry backing a `url(#id)` reference.
|
|
976
|
+
*
|
|
977
|
+
* SVG has paint servers for two gradients and a pattern and nothing else, so
|
|
978
|
+
* a kind beyond those has no element to target: write a foreign-namespaced
|
|
979
|
+
* one under the `wzl:` prefix `@weasel-js/svg` declares on the root whenever
|
|
980
|
+
* a document holds such a paint. That package emits the fallback color
|
|
981
|
+
* beside the reference on its own, from `colorOf`.
|
|
982
|
+
*/
|
|
983
|
+
toSvg?(id: string, fill: Paint): string;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* A consumer's own paint, typed as a `Paint`.
|
|
987
|
+
*
|
|
988
|
+
* `Paint` stays a closed union: opening its discriminant would widen every
|
|
989
|
+
* built-in member and break the narrowing the kit's own branches depend on.
|
|
990
|
+
* A registered kind declares its own interface instead and passes it through
|
|
991
|
+
* here — the kit reads only `kind` and hands the whole object back to that
|
|
992
|
+
* kind's slots.
|
|
993
|
+
*/
|
|
994
|
+
declare function asPaint<T extends {
|
|
995
|
+
kind: string;
|
|
996
|
+
}>(paint: T): Paint;
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* The paint-kind registry — what makes `Paint` open. The built-in kinds
|
|
1000
|
+
* are registered here at module load so an editor's kind bar can enumerate
|
|
1001
|
+
* every kind through one list.
|
|
1002
|
+
*
|
|
1003
|
+
* Every entry is also handed to the renderer's own registry, which reads only
|
|
1004
|
+
* its draw slots. A built-in kind has none: its render slot is a branch in the
|
|
1005
|
+
* GL renderer and its serialize slot lives in `@weasel-js/svg`.
|
|
1006
|
+
*/
|
|
1007
|
+
|
|
1008
|
+
/** The family the built-in tiles and `texture` are offered under. A consumer's
|
|
1009
|
+
* own pattern kind joins it by naming this as its `family`. */
|
|
1010
|
+
declare const patternFamily: PaintKindFamily;
|
|
1011
|
+
/** A tile paint seeded from a color. `units: 'bounds'` anchors the tile to the
|
|
1012
|
+
* node's box, so the texture travels with the shape. */
|
|
1013
|
+
declare function seedTile(kind: TileKind, color: string): TilePaint;
|
|
1014
|
+
/** Resolves with the entry for a kind that is loaded on first use. */
|
|
1015
|
+
type PaintKindLoader = () => Promise<PaintKindEntry>;
|
|
1016
|
+
/** Every registered paint kind, with the overrides each displaced. */
|
|
1017
|
+
declare const paintKindRegistry: Reflection<PaintKindEntry>;
|
|
1018
|
+
/** Register a paint kind. Returns a disposer that removes it. Re-registering an
|
|
1019
|
+
* existing id is an override; disposing it uncovers whatever it displaced. */
|
|
1020
|
+
declare function registerPaintKind(entry: PaintKindEntry): () => void;
|
|
1021
|
+
/**
|
|
1022
|
+
* Declare a paint kind that is loaded the first time something looks it up,
|
|
1023
|
+
* so its code stays out of the bundle until a paint of it appears — typically
|
|
1024
|
+
* `() => import('./myKind').then((m) => m.myKindEntry)`.
|
|
1025
|
+
*
|
|
1026
|
+
* Until it lands the kind is unregistered: the renderer draws nothing for its
|
|
1027
|
+
* paints, and every other reader treats it as unknown. Registering it fires
|
|
1028
|
+
* `paintKindRegistry`'s subscribers. Call `warmPaintKinds` to load ahead of
|
|
1029
|
+
* the first frame instead.
|
|
1030
|
+
*
|
|
1031
|
+
* A kind that is already registered never calls its loader. Returns a
|
|
1032
|
+
* disposer that removes the loader.
|
|
1033
|
+
*/
|
|
1034
|
+
declare function registerPaintKindLoader(id: string, load: PaintKindLoader): () => void;
|
|
1035
|
+
/** The entry for `kind`, or `undefined`. A lookup that misses on a kind with
|
|
1036
|
+
* a loader starts that load; see {@link registerPaintKindLoader}. */
|
|
1037
|
+
declare function getPaintKind(kind: string | undefined): PaintKindEntry | undefined;
|
|
1038
|
+
/** Every registered kind, built-ins first, in registration order. The same
|
|
1039
|
+
* array until the registry changes. */
|
|
1040
|
+
declare function listPaintKinds(): readonly PaintKindEntry[];
|
|
1041
|
+
/** Every registered gradient kind — the ones that read as and build from a
|
|
1042
|
+
* stop list — in registration order. The same array until the registry
|
|
1043
|
+
* changes. */
|
|
1044
|
+
declare function listGradientKinds(): readonly PaintKindEntry[];
|
|
1045
|
+
/**
|
|
1046
|
+
* `paint` retargeted to gradient kind `kind`, or `undefined` when either side
|
|
1047
|
+
* is not a gradient kind.
|
|
1048
|
+
*
|
|
1049
|
+
* Between two of the stop gradients this is `withGradientKind`, which carries
|
|
1050
|
+
* the geometry. Any other pair goes through the stop list — `stopsOf` on the
|
|
1051
|
+
* way out, `fromStops` on the way in — keeping `interpolate` and `opacity`.
|
|
1052
|
+
* Lossy wherever the kinds hold different information.
|
|
1053
|
+
*/
|
|
1054
|
+
declare function switchGradientKind(paint: Paint, kind: PaintKind): Paint | undefined;
|
|
1055
|
+
/** The registry entry for a paint, or `undefined` when its kind is unknown. */
|
|
1056
|
+
declare function paintKindOf(fill: Paint): PaintKindEntry | undefined;
|
|
1057
|
+
/** @internal Test helper — do not call from product code. */
|
|
1058
|
+
declare function _resetPaintKindsForTests(): void;
|
|
1059
|
+
|
|
1060
|
+
/** The paint a path node wears, resolved: what an action that turns ink into
|
|
1061
|
+
* geometry reads from a node and tells a consumer to put on a result. */
|
|
1062
|
+
interface PathPaint {
|
|
1063
|
+
/** `null` is no fill. */
|
|
1064
|
+
fill: Fill | null;
|
|
1065
|
+
/** Absent for no stroke. */
|
|
1066
|
+
stroke?: Stroke;
|
|
1067
|
+
}
|
|
1068
|
+
/** {@link PathPaint} of a node that keeps its paint in `data.fill` and
|
|
1069
|
+
* `data.stroke`, as the built-in path painter draws it: a stroke with no
|
|
1070
|
+
* `paint` is none, and an undeclared fill is the default shape fill unless
|
|
1071
|
+
* the node is stroked. */
|
|
1072
|
+
declare function pathPaintOf(data: {
|
|
1073
|
+
fill?: Fill | null;
|
|
1074
|
+
stroke?: Stroke | null;
|
|
1075
|
+
}): PathPaint;
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Create Outlines: replace each selected text node with path nodes carrying
|
|
1079
|
+
* its glyph outlines, giving up editability for geometry — the destructive
|
|
1080
|
+
* conversion every vector editor has. One path per paint the text wears; one
|
|
1081
|
+
* undoable batch; the replacement takes the text node's slot, so stacking
|
|
1082
|
+
* order is unchanged.
|
|
1083
|
+
*/
|
|
1084
|
+
|
|
1085
|
+
/** What a path minted by an outline action must carry — see
|
|
1086
|
+
* {@link CreateOutlinesAdapter.createPathNode}. */
|
|
1087
|
+
interface OutlinePathSpec extends PathPaint {
|
|
1088
|
+
/** The parent the path goes under: the source's own, or the container
|
|
1089
|
+
* minted to hold a source's several paths. */
|
|
1090
|
+
parent: string | null;
|
|
1091
|
+
}
|
|
1092
|
+
/** What `applyCreateOutlines` and `applyOutlineStroke` read and write through. */
|
|
1093
|
+
interface CreateOutlinesAdapter {
|
|
1094
|
+
getSelection(): readonly NodeId[] | readonly string[];
|
|
1095
|
+
/** The text node behind `id`, or `undefined` for anything else. */
|
|
1096
|
+
getTextSource(id: NodeId): TextNodeSource | undefined;
|
|
1097
|
+
/**
|
|
1098
|
+
* Optional: the world-space path of the path node behind `id`, and the
|
|
1099
|
+
* paint it wears. Outline Stroke reads both, and passes over a node that
|
|
1100
|
+
* lacks either.
|
|
1101
|
+
*/
|
|
1102
|
+
getWorldPath?(id: NodeId): Path | undefined;
|
|
1103
|
+
getPaint?(id: NodeId): PathPaint | undefined;
|
|
1104
|
+
/**
|
|
1105
|
+
* Optional: the frame the node behind `id` draws its stroke in, as the
|
|
1106
|
+
* matrix taking that frame to world (`poseFrameOf`); null or absent for a
|
|
1107
|
+
* node drawn straight. Outline Stroke skews and stretches a world-width
|
|
1108
|
+
* stroke with it. Without it every stroke is outlined in world.
|
|
1109
|
+
*/
|
|
1110
|
+
getStrokeFrame?(id: NodeId): Affine | null | undefined;
|
|
1111
|
+
/**
|
|
1112
|
+
* Mint one path node of node `sourceId`'s outlines. `path` is in world
|
|
1113
|
+
* space. The node must wear `spec`'s fill and stroke — a text whose runs
|
|
1114
|
+
* differ in paint gets one path per paint, and a filled node whose stroke
|
|
1115
|
+
* is outlined gets one for the fill and one for the stroke — and sit under
|
|
1116
|
+
* `spec.parent`. The kit places it; only the consumer knows its data shape,
|
|
1117
|
+
* so anything else of the source's `data` worth keeping is the adapter's to
|
|
1118
|
+
* copy: onto this path when it stands alone in the source's slot, onto the
|
|
1119
|
+
* container when `createContainerNode` minted one.
|
|
1120
|
+
*/
|
|
1121
|
+
createPathNode(path: Path, sourceId: NodeId, spec: OutlinePathSpec): {
|
|
1122
|
+
id: string;
|
|
1123
|
+
};
|
|
1124
|
+
/**
|
|
1125
|
+
* Mint the container that holds one source's several paths, under `parent`.
|
|
1126
|
+
* `bounds` is the world envelope of the paths. The kit puts the container in
|
|
1127
|
+
* the source's slot and the paths inside it, back to front. Without this,
|
|
1128
|
+
* the paths are laid flat in that slot instead.
|
|
1129
|
+
*/
|
|
1130
|
+
createContainerNode?(sourceId: NodeId, spec: {
|
|
1131
|
+
parent: string | null;
|
|
1132
|
+
bounds: Rect;
|
|
1133
|
+
}): {
|
|
1134
|
+
id: string;
|
|
1135
|
+
};
|
|
1136
|
+
/** Full node for `id`, so undo restores the text node whole. */
|
|
1137
|
+
getNode(id: string): {
|
|
1138
|
+
id: string;
|
|
1139
|
+
} | undefined | null;
|
|
1140
|
+
/** The tree: each path is inserted at its source node's index among its
|
|
1141
|
+
* parent's children. */
|
|
1142
|
+
getParent(id: string): string | null;
|
|
1143
|
+
getChildren(parentId: string | null): string[];
|
|
1144
|
+
applyOps?(ops: Op[], label?: string): void;
|
|
1145
|
+
setSelection?(ids: NodeId[]): void;
|
|
1146
|
+
insertNode?(node: {
|
|
1147
|
+
id: string;
|
|
1148
|
+
}, index?: number): void;
|
|
1149
|
+
removeNode?(id: string): void;
|
|
1150
|
+
}
|
|
1151
|
+
/** Outcome of {@link applyCreateOutlines}. */
|
|
1152
|
+
type CreateOutlinesResult =
|
|
1153
|
+
/** `resultIds` are what replaced the text nodes at their level — a path,
|
|
1154
|
+
* a container, or a run of flat paths each — which is also what is now
|
|
1155
|
+
* selected in the text nodes' place. */
|
|
1156
|
+
{
|
|
1157
|
+
kind: 'applied';
|
|
1158
|
+
resultIds: string[];
|
|
1159
|
+
}
|
|
1160
|
+
/** Nothing selected is text with ink. */
|
|
1161
|
+
| {
|
|
1162
|
+
kind: 'noop';
|
|
1163
|
+
reason: 'no-text';
|
|
1164
|
+
}
|
|
1165
|
+
/** Some selected text has no outline geometry; nothing was changed. */
|
|
1166
|
+
| {
|
|
1167
|
+
kind: 'failed';
|
|
1168
|
+
reason: 'text-outlines';
|
|
1169
|
+
error: TextOutlinesError;
|
|
1170
|
+
};
|
|
1171
|
+
/**
|
|
1172
|
+
* Convert every text node in the selection to outlines, as one batch labeled
|
|
1173
|
+
* "Create Outlines". Other selected nodes are left alone and stay selected.
|
|
1174
|
+
* All or nothing: if any text node's face cannot supply outlines the scene is
|
|
1175
|
+
* untouched and the error comes back in the result.
|
|
1176
|
+
*/
|
|
1177
|
+
declare function applyCreateOutlines(adapter: CreateOutlinesAdapter): CreateOutlinesResult;
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* What each selected node gives a Boolean operation: its path, its glyph
|
|
1181
|
+
* outlines, or the region its ink covers once a stroke is counted.
|
|
1182
|
+
*/
|
|
1183
|
+
|
|
1184
|
+
/**
|
|
1185
|
+
* What a stroked operand gives a Boolean operation.
|
|
1186
|
+
*
|
|
1187
|
+
* - `'ignore'`: its path, as though it had no stroke.
|
|
1188
|
+
* - `'unfilled'`: the region its stroke covers when it has no fill, as a line
|
|
1189
|
+
* or an open pencil stroke has none; its path when it is filled.
|
|
1190
|
+
* - `'include'`: what it paints — its fill and its stroke together, or the
|
|
1191
|
+
* stroke alone when it has no fill.
|
|
1192
|
+
*
|
|
1193
|
+
* Any mode but `'ignore'` needs {@link BooleansAdapter.getPaint}.
|
|
1194
|
+
*/
|
|
1195
|
+
type BooleanStrokes = 'ignore' | 'unfilled' | 'include';
|
|
1196
|
+
/** Options for `applyBooleanOp`. */
|
|
1197
|
+
interface BooleanOpOptions {
|
|
1198
|
+
/** Default `'ignore'`. */
|
|
1199
|
+
strokes?: BooleanStrokes;
|
|
1200
|
+
/** The view scale a `{ px }` stroke width resolves against: one number, or
|
|
1201
|
+
* the view's own scale per axis. Default 1. */
|
|
1202
|
+
scale?: number | Scale2;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/**
|
|
1206
|
+
* Pure action core for path boolean operations. Resolves the current
|
|
1207
|
+
* selection into z-ordered paths, runs the chosen op, and dispatches a
|
|
1208
|
+
* single batch of `Op`s (delete sources + insert results + set selection).
|
|
1209
|
+
*/
|
|
1210
|
+
|
|
1211
|
+
/** Boolean op identifiers: the five Pathfinder primaries, and Crop, Trim, and Merge. */
|
|
1212
|
+
type BooleanOp = 'union' | 'intersect' | 'subtract' | 'exclude' | 'divide' | 'crop' | 'trim' | 'merge';
|
|
1213
|
+
/** Adapter the hook and the pure core both consume. */
|
|
1214
|
+
interface BooleansAdapter {
|
|
1215
|
+
getSelection(): readonly NodeId[] | readonly string[];
|
|
1216
|
+
getWorldPath(id: NodeId): Path | undefined;
|
|
1217
|
+
/**
|
|
1218
|
+
* Optional: the text node behind `id`, for an id `getWorldPath` has no path
|
|
1219
|
+
* for. Its glyph outlines (`textToPath`) become the operand, so text can be
|
|
1220
|
+
* cut, united or intersected like any shape.
|
|
1221
|
+
*/
|
|
1222
|
+
getTextSource?(id: NodeId): TextNodeSource | undefined;
|
|
1223
|
+
/**
|
|
1224
|
+
* Optional: the paint the path node behind `id` wears. An operation told to
|
|
1225
|
+
* count strokes (`BooleanOpOptions.strokes`) reads it to learn whether the
|
|
1226
|
+
* node is stroked and whether it is filled; without it every operand is its
|
|
1227
|
+
* path alone.
|
|
1228
|
+
*/
|
|
1229
|
+
getPaint?(id: NodeId): PathPaint | undefined;
|
|
1230
|
+
/**
|
|
1231
|
+
* Optional: the frame the node behind `id` draws its stroke in, as the
|
|
1232
|
+
* matrix taking that frame to world (`poseFrameOf`); null or absent for a
|
|
1233
|
+
* node drawn straight. A counted world-width stroke is skewed and stretched
|
|
1234
|
+
* with it. Without it every stroke is outlined in world.
|
|
1235
|
+
*/
|
|
1236
|
+
getStrokeFrame?(id: NodeId): Affine | null | undefined;
|
|
1237
|
+
compareZ(a: NodeId, b: NodeId): number;
|
|
1238
|
+
/**
|
|
1239
|
+
* Mint a new node from a boolean-op result `Path`. `producedBy` names the
|
|
1240
|
+
* op that synthesized it — adapters that store provenance (e.g. for a
|
|
1241
|
+
* layer-panel icon) record it; others ignore the arg. `sourceId` is the
|
|
1242
|
+
* source the result stands in for: the topmost, except that each piece of
|
|
1243
|
+
* a Divide, Crop, Trim, or Merge names the topmost source it was cut from. Give the
|
|
1244
|
+
* node that source's parent, or the kit's reorder cannot find it there.
|
|
1245
|
+
* `paint` is passed when that source's stroke went into the geometry, and
|
|
1246
|
+
* the node must wear it as given: wearing the source's stroke again would
|
|
1247
|
+
* draw it twice. Without `paint`, give it that source's paint. The kit never
|
|
1248
|
+
* reads a node's `data`: anything else the result should keep of its source,
|
|
1249
|
+
* a name say, is the adapter's to copy from `sourceId`.
|
|
1250
|
+
*/
|
|
1251
|
+
createPathNode(path: Path, producedBy: BooleanOp, sourceId: NodeId, paint?: PathPaint): {
|
|
1252
|
+
id: string;
|
|
1253
|
+
};
|
|
1254
|
+
/**
|
|
1255
|
+
* The full object for an id. The delete ops capture it, so their `invert`
|
|
1256
|
+
* (an insert) restores the complete object on undo.
|
|
1257
|
+
*/
|
|
1258
|
+
getNode(id: NodeId): {
|
|
1259
|
+
id: string;
|
|
1260
|
+
} | undefined | null;
|
|
1261
|
+
/**
|
|
1262
|
+
* The tree. The kit reads each source's slot among its siblings through
|
|
1263
|
+
* `getParent` and `getChildren`, and moves each result into the slot of
|
|
1264
|
+
* the topmost source in its own source's parent through `setChildOrder`.
|
|
1265
|
+
* `defaultCommitAdapter` supplies all three, and `getNode`.
|
|
1266
|
+
*/
|
|
1267
|
+
getParent(id: string): string | null;
|
|
1268
|
+
getChildren(parentId: string | null): string[];
|
|
1269
|
+
setChildOrder(parentId: string | null, ids: string[]): void;
|
|
1270
|
+
applyOps?(ops: Op[], label?: string): void;
|
|
1271
|
+
setSelection?(ids: NodeId[]): void;
|
|
1272
|
+
insertNode?(node: {
|
|
1273
|
+
id: string;
|
|
1274
|
+
}): void;
|
|
1275
|
+
removeNode?(id: string): void;
|
|
1276
|
+
}
|
|
1277
|
+
/** Outcome reported back to callers (lets the hook surface no-op signals). */
|
|
1278
|
+
type BooleanOpResult = {
|
|
1279
|
+
kind: 'applied';
|
|
1280
|
+
resultIds: string[];
|
|
1281
|
+
} | {
|
|
1282
|
+
kind: 'noop';
|
|
1283
|
+
reason: 'no-paths' | 'too-few-for-subtract' | 'empty-result';
|
|
1284
|
+
}
|
|
1285
|
+
/** A text operand had no outline geometry. Nothing was changed: an op that
|
|
1286
|
+
* quietly dropped the operand would commit a different shape than asked. */
|
|
1287
|
+
| {
|
|
1288
|
+
kind: 'failed';
|
|
1289
|
+
reason: 'text-outlines';
|
|
1290
|
+
error: TextOutlinesError;
|
|
1291
|
+
};
|
|
1292
|
+
/** One path a Boolean operation would make. */
|
|
1293
|
+
interface BooleanPreviewPiece {
|
|
1294
|
+
path: Path;
|
|
1295
|
+
/** The source the piece stands in for; see `BooleansAdapter.createPathNode`. */
|
|
1296
|
+
sourceId: NodeId;
|
|
1297
|
+
/** Set when that source's stroke went into `path`: the paint the piece wears. */
|
|
1298
|
+
paint?: PathPaint;
|
|
1299
|
+
}
|
|
1300
|
+
/** What {@link previewBooleanOp} answers: the pieces, or why there are none. */
|
|
1301
|
+
type BooleanOpPreview = {
|
|
1302
|
+
kind: 'pieces';
|
|
1303
|
+
pieces: BooleanPreviewPiece[];
|
|
1304
|
+
} | Exclude<BooleanOpResult, {
|
|
1305
|
+
kind: 'applied';
|
|
1306
|
+
}>;
|
|
1307
|
+
/**
|
|
1308
|
+
* What {@link applyBooleanOp} would make of the selection, without minting a
|
|
1309
|
+
* node or committing anything: for drawing an operation before it is applied.
|
|
1310
|
+
*/
|
|
1311
|
+
declare function previewBooleanOp(adapter: BooleansAdapter, op: BooleanOp, opts?: BooleanOpOptions): BooleanOpPreview;
|
|
1312
|
+
/**
|
|
1313
|
+
* Run one Boolean operation over the selected paths and commit the result as a
|
|
1314
|
+
* single undoable batch.
|
|
1315
|
+
*
|
|
1316
|
+
* Operands are ordered back-to-front, which is what makes `subtract` mean
|
|
1317
|
+
* "everything in front removed from the backmost shape". Returns without
|
|
1318
|
+
* mutating anything when the selection holds no paths, or too few for the
|
|
1319
|
+
* requested operation. `opts.strokes` says what a stroked operand gives.
|
|
1320
|
+
*/
|
|
1321
|
+
declare function applyBooleanOp(adapter: BooleansAdapter, op: BooleanOp, opts?: BooleanOpOptions): BooleanOpResult;
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Read-only state that affordances consult on every render and hit-test
|
|
1325
|
+
* call. Built via `buildChromeState` and held across renders, so affordances
|
|
1326
|
+
* must not cache anything they read from it.
|
|
1327
|
+
*/
|
|
1328
|
+
interface ChromeState {
|
|
1329
|
+
/** Currently selected ids. Live; reflects useSelection's React state,
|
|
1330
|
+
* less any on a layer this view does not paint. */
|
|
1331
|
+
readonly selection: readonly NodeId[];
|
|
1332
|
+
/** True when the canvas is in multi-mode AND >= 2 ids are selected, and
|
|
1333
|
+
* still >= 2 once `selection` drops the ones this view does not paint. */
|
|
1334
|
+
readonly multiActive: boolean;
|
|
1335
|
+
/** Bounds for any selection member id. Honors active-tool overlay state
|
|
1336
|
+
* (move/resize/rotate ghosts → ghost bounds; otherwise → committed
|
|
1337
|
+
* pose bounds). Returns null for unknown ids or ids whose bounds aren't
|
|
1338
|
+
* computable. */
|
|
1339
|
+
boundsOf(id: string): FramedBox | null;
|
|
1340
|
+
/** Multi-union AABB when `multiActive`. Recomputed from `boundsOf` over
|
|
1341
|
+
* every selected id on each read, expanding rotated members to the extent
|
|
1342
|
+
* of their ink; null otherwise. */
|
|
1343
|
+
readonly unionBounds: FramedBox | null;
|
|
1344
|
+
/** Active modifier state at the moment of the call. */
|
|
1345
|
+
readonly modifiers: ModifierState;
|
|
1346
|
+
/** True iff the node's pose-descriptor declares it can carry a rotation.
|
|
1347
|
+
* Affordances consult this to decide whether to expose rotate cursors /
|
|
1348
|
+
* drag-bands. Defaults to `true` when the descriptor doesn't declare
|
|
1349
|
+
* (back-compat) or when the id is unknown — the rotation gesture will
|
|
1350
|
+
* no-op visually for poses without AABB fields, but the affordance
|
|
1351
|
+
* doesn't lie about the cursor. Optional on the interface so unit-test
|
|
1352
|
+
* call sites that construct `ChromeState` by hand keep compiling;
|
|
1353
|
+
* affordances should treat an absent predicate as "true". */
|
|
1354
|
+
canRotate?(id: string): boolean;
|
|
1355
|
+
/** Whether a scene layer reaches the screen in the view this state was
|
|
1356
|
+
* built for — its `layerVisibility` / `layerOrder`, as `ViewApi` answers
|
|
1357
|
+
* it. Absent: the view paints every layer the scene shows. An affordance
|
|
1358
|
+
* that reads it puts no chrome on a node whose layer it says `false` to. */
|
|
1359
|
+
layerIsPainted?(layerId: string): boolean;
|
|
1360
|
+
}
|
|
1361
|
+
/** Whether chrome goes on something painted on `layer`, as `gate` — a
|
|
1362
|
+
* `ChromeState`, a `ViewApi` — says. No layer, or no gate: it does. */
|
|
1363
|
+
declare function paintsLayer(gate: {
|
|
1364
|
+
layerIsPainted?(layerId: string): boolean;
|
|
1365
|
+
} | null | undefined, layer: string | undefined): boolean;
|
|
1366
|
+
|
|
1367
|
+
/**
|
|
1368
|
+
* A single interactive piece of chrome. Affordances declare interactive regions in a target's
|
|
1369
|
+
* *local* frame; `composeAffordanceLayer` composes the target's bounds transform (rotation
|
|
1370
|
+
* around the AABB center, when present) for both paint and hit-test, so the affordance never
|
|
1371
|
+
* touches rotation, view.scale, or world↔screen math.
|
|
1372
|
+
*/
|
|
1373
|
+
interface Affordance {
|
|
1374
|
+
/** Stable id for debug overlays + visibility maps. */
|
|
1375
|
+
id: string;
|
|
1376
|
+
/** This affordance's interactive regions. Each lives in some target id's local frame (or
|
|
1377
|
+
* the world frame when `targetId` is `null`). `[]` means no chrome for this state. */
|
|
1378
|
+
regions(state: ChromeState): readonly AffordanceRegion[];
|
|
1379
|
+
/** Optional non-interactive decoration (e.g., a leader line from a bounds edge to a
|
|
1380
|
+
* handle). Receives raw state + view because it may live outside any single target's
|
|
1381
|
+
* local frame. */
|
|
1382
|
+
decorate?(state: ChromeState, view: View): DrawCommand[];
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* One interactive region produced by an affordance. The framework owns
|
|
1386
|
+
* the local↔world transform for `targetId` (when non-null), so `shape`,
|
|
1387
|
+
* `paint.sizePx`, and `hitRadiusPx` are always specified in coordinates
|
|
1388
|
+
* the affordance can reason about directly.
|
|
1389
|
+
*/
|
|
1390
|
+
interface AffordanceRegion<TScratch = unknown> {
|
|
1391
|
+
/** Stable id, e.g. `corner-min-min`. Used for debug overlays + a11y. */
|
|
1392
|
+
id: string;
|
|
1393
|
+
/** A chrome-caps id gating this region on top of its affordance's. */
|
|
1394
|
+
chromeId?: string;
|
|
1395
|
+
/** Target id whose `state.boundsOf(targetId)` defines this region's
|
|
1396
|
+
* local frame: the bounds' `rotation` and `transform`, as `poseFrameOf`
|
|
1397
|
+
* composes them about the box center. Pass
|
|
1398
|
+
* `null` for affordances anchored to the viewport / world frame
|
|
1399
|
+
* (identity transform). */
|
|
1400
|
+
targetId: string | null;
|
|
1401
|
+
/** Region geometry, expressed in the target's local frame.
|
|
1402
|
+
*
|
|
1403
|
+
* - `point` — square hit of half-extent `hitRadiusPx` screen pixels,
|
|
1404
|
+
* axis-aligned on screen unless `turned`. `standoff` pushes the anchor `px`
|
|
1405
|
+
* screen pixels off the edge whose outward normal (target-local) is
|
|
1406
|
+
* `normal`, measured along that normal as it lands on screen — for
|
|
1407
|
+
* chrome that floats a fixed distance off an edge at any zoom.
|
|
1408
|
+
* - `rect` — axis-aligned rect (target rotation applies).
|
|
1409
|
+
* - `annulus` — outer ellipse minus inner rect cutout, for zones that sit *around* the
|
|
1410
|
+
* AABB (e.g. a rotate-on-hover band).
|
|
1411
|
+
* - `outline` — within `hitRadiusPx` screen pixels of `path`'s outline, either side of it,
|
|
1412
|
+
* for chrome that is a path's own edge (path edit's segments). Hit-only. */
|
|
1413
|
+
shape: {
|
|
1414
|
+
kind: 'point';
|
|
1415
|
+
x: number;
|
|
1416
|
+
y: number;
|
|
1417
|
+
hitRadiusPx: number;
|
|
1418
|
+
standoff?: {
|
|
1419
|
+
px: number;
|
|
1420
|
+
normal: {
|
|
1421
|
+
x: number;
|
|
1422
|
+
y: number;
|
|
1423
|
+
};
|
|
1424
|
+
};
|
|
1425
|
+
/** Turn the square to the target, at the angle the target's x axis
|
|
1426
|
+
* lands on screen (`screenAngleOf`) — for handles painted turned. */
|
|
1427
|
+
turned?: boolean;
|
|
1428
|
+
/** The body this point is a corner of: its target-local size, and
|
|
1429
|
+
* which way leads out of it on each axis. While the body spans under
|
|
1430
|
+
* four `hitRadiusPx` on an axis on screen, only the outward half of
|
|
1431
|
+
* the square on that axis takes a press, so a small body can still be
|
|
1432
|
+
* grabbed. The cut runs along the square's own axes: pair it with
|
|
1433
|
+
* `turned` on a target that can rotate. */
|
|
1434
|
+
cornerOf?: {
|
|
1435
|
+
width: number;
|
|
1436
|
+
height: number;
|
|
1437
|
+
outward: {
|
|
1438
|
+
x: -1 | 1;
|
|
1439
|
+
y: -1 | 1;
|
|
1440
|
+
};
|
|
1441
|
+
};
|
|
1442
|
+
/** The body this point is an edge midpoint of: its target-local
|
|
1443
|
+
* size. While either side spans under `EDGE_HANDLE_MIN_RADII`
|
|
1444
|
+
* `hitRadiusPx` on screen, the point is neither hit nor painted, so it
|
|
1445
|
+
* cannot crowd the corners or cover the middle of a small body. */
|
|
1446
|
+
edgeOf?: {
|
|
1447
|
+
width: number;
|
|
1448
|
+
height: number;
|
|
1449
|
+
};
|
|
1450
|
+
} | {
|
|
1451
|
+
kind: 'rect';
|
|
1452
|
+
x: number;
|
|
1453
|
+
y: number;
|
|
1454
|
+
width: number;
|
|
1455
|
+
height: number;
|
|
1456
|
+
} | {
|
|
1457
|
+
kind: 'annulus';
|
|
1458
|
+
/** Outer-ellipse center (target-local). */
|
|
1459
|
+
cx: number;
|
|
1460
|
+
cy: number;
|
|
1461
|
+
/** Outer-ellipse semi-axes (target-local). */
|
|
1462
|
+
rx: number;
|
|
1463
|
+
ry: number;
|
|
1464
|
+
/** Inner rect (target-local) — the cutout. Typically the
|
|
1465
|
+
* selection's AABB. */
|
|
1466
|
+
innerX: number;
|
|
1467
|
+
innerY: number;
|
|
1468
|
+
innerWidth: number;
|
|
1469
|
+
innerHeight: number;
|
|
1470
|
+
/** Minimum band thickness outside the inner rect, in **screen**
|
|
1471
|
+
* pixels. The framework widens `rx`/`ry` to at least
|
|
1472
|
+
* `innerHalfExtent + pxExtent(minBandPx, view.scale)` on each axis
|
|
1473
|
+
* for both paint and hit-test.
|
|
1474
|
+
*
|
|
1475
|
+
* In screen pixels because the clamp has to know the view and the affordance
|
|
1476
|
+
* doesn't: `ChromeState` carries no scale. */
|
|
1477
|
+
minBandPx?: number;
|
|
1478
|
+
} | {
|
|
1479
|
+
kind: 'outline';
|
|
1480
|
+
path: PolygonPath;
|
|
1481
|
+
hitRadiusPx: number;
|
|
1482
|
+
};
|
|
1483
|
+
/** Optional paint. World position is derived from `shape` + target
|
|
1484
|
+
* transform; visual size stays in screen pixels (so handles don't
|
|
1485
|
+
* warp under zoom or non-uniform scale). Omit for hit-only regions.
|
|
1486
|
+
*
|
|
1487
|
+
* - `square` — small fixed-size square (only valid over `point` shapes).
|
|
1488
|
+
* - `annulus` — fill + stroke the annulus ring (only valid over `annulus` shapes).
|
|
1489
|
+
* - `custom` — emit arbitrary draw commands; receives a {@link CustomPaintContext}. */
|
|
1490
|
+
paint?: {
|
|
1491
|
+
kind: 'square';
|
|
1492
|
+
sizePx: number;
|
|
1493
|
+
fill?: CommandFill;
|
|
1494
|
+
stroke?: CommandStroke;
|
|
1495
|
+
} | {
|
|
1496
|
+
kind: 'annulus';
|
|
1497
|
+
fill?: CommandFill;
|
|
1498
|
+
stroke?: CommandStroke;
|
|
1499
|
+
insetPx?: number;
|
|
1500
|
+
} | {
|
|
1501
|
+
kind: 'custom';
|
|
1502
|
+
draw: (ctx: CustomPaintContext) => DrawCommand[];
|
|
1503
|
+
};
|
|
1504
|
+
/** Discriminator a press on this region reports as `AffordanceHit.kind` —
|
|
1505
|
+
* the string routing specs match on (`'handle:top-left'`,
|
|
1506
|
+
* `'rotate-handle'`, `'anchor:3'`). Omit for regions that only exist
|
|
1507
|
+
* inside a consumer-registered layer, where the layer id is the
|
|
1508
|
+
* discriminator; `buildAffordanceAt` falls back to
|
|
1509
|
+
* `<affordanceId>:<regionId>`. */
|
|
1510
|
+
hitKind?: string;
|
|
1511
|
+
/** Cursor to show while hovering this region: one spec, or one worked out
|
|
1512
|
+
* from where the pointer is (`at`, in world coords). */
|
|
1513
|
+
cursor?: CursorSpec | ((at: {
|
|
1514
|
+
x: number;
|
|
1515
|
+
y: number;
|
|
1516
|
+
}, view: View) => CursorSpec);
|
|
1517
|
+
/** `'exclusive'` bars every binding whose target doesn't consult the
|
|
1518
|
+
* affordance. Read only when the affordance is composed into a
|
|
1519
|
+
* consumer-registered layer; kit chrome routes through
|
|
1520
|
+
* `buildAffordanceAt`, which reports `'shared'`. */
|
|
1521
|
+
strength?: 'exclusive' | 'shared';
|
|
1522
|
+
/** Which gestures an exclusive claim bars. Omitted bars all of them. */
|
|
1523
|
+
claimedKinds?: readonly ClaimableGesture[];
|
|
1524
|
+
/** Drag binding produced when this region is hit. Called lazily, so state snapshots
|
|
1525
|
+
* (e.g., capturing per-leaf poses at click time) belong inside `bind()`, not inside
|
|
1526
|
+
* `regions()`. */
|
|
1527
|
+
bind(): AffordanceBinding<TScratch>;
|
|
1528
|
+
}
|
|
1529
|
+
/** Context passed to a region's `paint.kind === 'custom'` draw callback. */
|
|
1530
|
+
interface CustomPaintContext {
|
|
1531
|
+
/** World-space mapping of `shape`. For `point`, only `x`/`y` are set.
|
|
1532
|
+
* For `rect`, all four fields are set. */
|
|
1533
|
+
world: {
|
|
1534
|
+
x: number;
|
|
1535
|
+
y: number;
|
|
1536
|
+
width?: number;
|
|
1537
|
+
height?: number;
|
|
1538
|
+
};
|
|
1539
|
+
/** The original local shape (same object identity as `region.shape`). */
|
|
1540
|
+
local: AffordanceRegion['shape'];
|
|
1541
|
+
view: View;
|
|
1542
|
+
state: ChromeState;
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Result of an affordance hit. `initialScratch` is what the region already knows (which
|
|
1546
|
+
* corner, which target id) so the action that picks up the drag doesn't re-derive it. It
|
|
1547
|
+
* reaches the matching action through `InvocationCtx.drag.affordance`.
|
|
1548
|
+
*/
|
|
1549
|
+
interface AffordanceBinding<TScratch = unknown> {
|
|
1550
|
+
initialScratch?: TScratch;
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* The fields `buildAffordanceAt` lifts out of a region's `initialScratch` when it turns a
|
|
1554
|
+
* region hit into an `AffordanceHit`. Scratch is otherwise opaque; these names mean the same
|
|
1555
|
+
* thing to every affordance. An affordance that doesn't set them produces a hit without
|
|
1556
|
+
* those fields.
|
|
1557
|
+
*/
|
|
1558
|
+
interface CommonAffordanceScratch {
|
|
1559
|
+
/** The node (or `MULTI_RESIZE_TARGET_ID`) this chrome acts on. Becomes
|
|
1560
|
+
* `AffordanceHit.targetIds`. */
|
|
1561
|
+
targetId?: string;
|
|
1562
|
+
/** For resize chrome: which corner stays pinned. Mirrors the kit's
|
|
1563
|
+
* `ResizeAnchor`, spelled inline so `affordances/` doesn't take a type
|
|
1564
|
+
* dependency on the gesture layer for one field. */
|
|
1565
|
+
anchor?: {
|
|
1566
|
+
x: 'min' | 'max' | 'free';
|
|
1567
|
+
y: 'min' | 'max' | 'free';
|
|
1568
|
+
};
|
|
1569
|
+
/** World-space invariant point of the transform — the fixed corner for a
|
|
1570
|
+
* resize, the pivot for a rotation. */
|
|
1571
|
+
fixedPoint?: {
|
|
1572
|
+
x: number;
|
|
1573
|
+
y: number;
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* What a **registered layer's** `hitTest` returns. The added fields are how a consumer's own
|
|
1578
|
+
* chrome says the things kit chrome says through `AffordanceRegion` — which cursor to show,
|
|
1579
|
+
* and whether it owns the point outright.
|
|
1580
|
+
*/
|
|
1581
|
+
interface LayerHit<TScratch = unknown> extends AffordanceBinding<TScratch> {
|
|
1582
|
+
/** Cursor while the pointer is over this hit. Reaches the hover-cursor
|
|
1583
|
+
* pump as `AffordanceHit.cursor`, the same path kit chrome uses. */
|
|
1584
|
+
cursor?: CursorSpec;
|
|
1585
|
+
/** `'exclusive'` bars every binding whose target doesn't consult the affordance. Omitted
|
|
1586
|
+
* means `'shared'`. Becomes `AffordanceHit.strength`. */
|
|
1587
|
+
strength?: 'exclusive' | 'shared';
|
|
1588
|
+
/** Which gestures an exclusive claim bars. Omitted bars all of them. */
|
|
1589
|
+
claimedKinds?: readonly ClaimableGesture[];
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* Several consecutive layers composited as one.
|
|
1594
|
+
*
|
|
1595
|
+
* A layer's own `effects` run over that layer alone, which is the wrong
|
|
1596
|
+
* picture whenever a pass reads neighboring pixels: `blur(A over B)` is not
|
|
1597
|
+
* `blur(A) over blur(B)`. A group draws its members into one buffer, runs one
|
|
1598
|
+
* chain over it, and composites the result back once.
|
|
1599
|
+
*
|
|
1600
|
+
* Membership is by `RenderLayer.id` — the same names `layerOrder` and
|
|
1601
|
+
* `layerVisibility` use, not the `layers` map's slot keys.
|
|
1602
|
+
*
|
|
1603
|
+
* Only *consecutive* members share a buffer. A group whose members are
|
|
1604
|
+
* separated in the render order is drawn as one bracket per run, with a
|
|
1605
|
+
* warning.
|
|
1606
|
+
*
|
|
1607
|
+
* This is a render-stack bracket, not a scene `ContainerNode`.
|
|
1608
|
+
*/
|
|
1609
|
+
interface LayerGroup {
|
|
1610
|
+
/** Names the group in warnings; not a layer id and never drawn. */
|
|
1611
|
+
id: string;
|
|
1612
|
+
/**
|
|
1613
|
+
* Member layer ids. Order here is ignored — the render order decides.
|
|
1614
|
+
*
|
|
1615
|
+
* A name claims that layer and every layer under it in the `:` namespace, so
|
|
1616
|
+
* `'scene'` covers the `scene:<layerId>` layers a scene with declared layers
|
|
1617
|
+
* draws as. The separator is required: `'scene'` does not reach `scenery`.
|
|
1618
|
+
* A name matching no layer being drawn is warned about.
|
|
1619
|
+
*/
|
|
1620
|
+
layers: readonly string[];
|
|
1621
|
+
/** Passes over the group's combined pixels, in order. A thunk is re-read on
|
|
1622
|
+
* every frame, so an animating radius costs no React render. */
|
|
1623
|
+
effects?: readonly Effect[] | ((view: View, dims: Dims) => readonly Effect[]);
|
|
1624
|
+
/** Opacity applied to the group's composited result, not to each member. */
|
|
1625
|
+
alpha?: number;
|
|
1626
|
+
/** 4×5 color matrix (row-major, 20 numbers) applied to the composited
|
|
1627
|
+
* result. See `GroupDrawCommand.colorMatrix`. */
|
|
1628
|
+
colorMatrix?: number[];
|
|
1629
|
+
/** How the composited result joins the layers under it. Default
|
|
1630
|
+
* `source-over`. See `GroupDrawCommand.composite`. */
|
|
1631
|
+
composite?: CompositeOp | BlendFactors;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* When `drawLayers` asks the renderer to keep a layer's pixels between frames
|
|
1636
|
+
* (`GroupDrawCommand.retain`) rather than submit its commands again.
|
|
1637
|
+
*
|
|
1638
|
+
* A layer is retained once its `deps` have held for a frame, the view has held
|
|
1639
|
+
* since the frame before (for a world-space layer, whose pixels move with
|
|
1640
|
+
* it), and it holds at least `minCommands` drawing commands. A layer changing
|
|
1641
|
+
* every frame is never retained: drawing it into its surface and compositing
|
|
1642
|
+
* that costs more than drawing it.
|
|
1643
|
+
*/
|
|
1644
|
+
interface LayerRetainPolicy {
|
|
1645
|
+
minCommands: number;
|
|
1646
|
+
}
|
|
1647
|
+
/** Measured on 1280x800 at dpr 2: an unchanged layer composites cheaper than
|
|
1648
|
+
* it submits from about 130 to 250 commands, depending on the layer count. */
|
|
1649
|
+
declare const DEFAULT_LAYER_RETAIN: LayerRetainPolicy;
|
|
1650
|
+
|
|
1651
|
+
/** Something outside React whose changes a paint reads — a mode registry, a
|
|
1652
|
+
* scoping lookup. A notification repaints the canvas; the listener takes no
|
|
1653
|
+
* arguments and the returned function unsubscribes. */
|
|
1654
|
+
interface RedrawSource {
|
|
1655
|
+
subscribe(listener: () => void): () => void;
|
|
1656
|
+
}
|
|
1657
|
+
/** The `subscribe` for a layer that draws `sources`: it notifies whenever any
|
|
1658
|
+
* of them does. A thunk is read when the subscription is made. */
|
|
1659
|
+
declare function subscribeToSources(sources: readonly {
|
|
1660
|
+
subscribe?: RedrawSource['subscribe'];
|
|
1661
|
+
}[] | (() => readonly {
|
|
1662
|
+
subscribe?: RedrawSource['subscribe'];
|
|
1663
|
+
}[])): RedrawSource['subscribe'];
|
|
1664
|
+
|
|
1665
|
+
/** Canvas size in CSS pixels, so layers don't have to know about DPR. */
|
|
1666
|
+
interface Dims {
|
|
1667
|
+
width: number;
|
|
1668
|
+
height: number;
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* What a layer's `draw` threw, and which layer threw it. A throw that escaped
|
|
1672
|
+
* the frame loop would take the whole frame with it, every other layer
|
|
1673
|
+
* included.
|
|
1674
|
+
*/
|
|
1675
|
+
interface LayerDrawFailure {
|
|
1676
|
+
layerId: string;
|
|
1677
|
+
error: unknown;
|
|
1678
|
+
}
|
|
1679
|
+
/** One layer's memoized output, keyed by layer id. Owned by the canvas that
|
|
1680
|
+
* calls `drawLayers`, not by `drawLayers` itself — the function is pure. */
|
|
1681
|
+
type LayerCommandCache = Map<string, {
|
|
1682
|
+
deps: readonly unknown[];
|
|
1683
|
+
cmds: DrawCommand[];
|
|
1684
|
+
/** Whether the last frame served `cmds` from here rather than drawing. */
|
|
1685
|
+
reused?: boolean;
|
|
1686
|
+
/** The view the last frame drew under. */
|
|
1687
|
+
view?: View;
|
|
1688
|
+
}>;
|
|
1689
|
+
/**
|
|
1690
|
+
* One layer of a canvas: `draw` turns `data` and the view into draw commands;
|
|
1691
|
+
* the other fields control caching, visibility, coordinate space and hit-testing.
|
|
1692
|
+
*
|
|
1693
|
+
* @template TData - The data object passed to each draw call.
|
|
1694
|
+
*/
|
|
1695
|
+
interface RenderLayer<TData> {
|
|
1696
|
+
/** Unique identifier used in visibility maps and ordering arrays. When a
|
|
1697
|
+
* cache is in use, an id must identify the same logical layer across
|
|
1698
|
+
* frames — reusing it for a different layer can serve cross-layer commands. */
|
|
1699
|
+
id: string;
|
|
1700
|
+
/** Human-readable name for UI toggles. */
|
|
1701
|
+
label: string;
|
|
1702
|
+
/**
|
|
1703
|
+
* Emit a DrawCommand tree, in the coordinates `space` names. A world-space
|
|
1704
|
+
* layer must NOT apply the view transform itself.
|
|
1705
|
+
*/
|
|
1706
|
+
draw: (data: TData, view: View, dims: Dims) => DrawCommand[];
|
|
1707
|
+
/**
|
|
1708
|
+
* Optional cache key. When present and a `LayerCommandCache` is supplied to
|
|
1709
|
+
* `drawLayers`, the layer's previous `DrawCommand[]` is reused as long as
|
|
1710
|
+
* every entry is `Object.is`-equal to the previous call's. A layer with no
|
|
1711
|
+
* `deps` rebuilds on every frame.
|
|
1712
|
+
*
|
|
1713
|
+
* **The returned commands must be treated as immutable.** A cached tree is
|
|
1714
|
+
* handed to the renderer again on later frames, so mutating a tree you
|
|
1715
|
+
* previously returned corrupts the cache silently rather than erroring.
|
|
1716
|
+
*
|
|
1717
|
+
* **Screen-space layers are not protected against a stale `view`/`dims`
|
|
1718
|
+
* the way world-space layers are** (see `space` below) — include them in
|
|
1719
|
+
* `deps` if `draw` reads them.
|
|
1720
|
+
*/
|
|
1721
|
+
deps?: (data: TData, view: View, dims: Dims) => readonly unknown[];
|
|
1722
|
+
/** Whether the layer is shown when no explicit visibility entry exists.
|
|
1723
|
+
* Defaults to `true` when absent. */
|
|
1724
|
+
defaultVisible?: boolean;
|
|
1725
|
+
/** When true, the layer is always drawn regardless of the visibility map. */
|
|
1726
|
+
alwaysOn?: boolean;
|
|
1727
|
+
/**
|
|
1728
|
+
* Coordinate space the layer draws in.
|
|
1729
|
+
*
|
|
1730
|
+
* - `'world'` (default): the layer's `draw` returns world-space commands;
|
|
1731
|
+
* `drawLayers` wraps them in a `kind: 'group'` with `viewToMat3(view)`
|
|
1732
|
+
* automatically.
|
|
1733
|
+
* - `'screen'`: the layer's `draw` returns screen-space (CSS-pixel)
|
|
1734
|
+
* commands; `drawLayers` passes them through unchanged. World-anchored
|
|
1735
|
+
* chrome inside a screen-space layer must call `worldToScreen` or wrap
|
|
1736
|
+
* the relevant subset with `viewToMat3(view)` manually.
|
|
1737
|
+
*/
|
|
1738
|
+
space?: 'world' | 'screen';
|
|
1739
|
+
/**
|
|
1740
|
+
* Where the layer learns that state `draw` reads, outside the scene and the
|
|
1741
|
+
* props, has changed. The canvas painting it subscribes while the layer is
|
|
1742
|
+
* mounted and repaints on every notification.
|
|
1743
|
+
*/
|
|
1744
|
+
subscribe?: RedrawSource['subscribe'];
|
|
1745
|
+
/**
|
|
1746
|
+
* Full-screen passes run over this layer's own pixels before it joins the
|
|
1747
|
+
* frame. See `GroupDrawCommand.effects` for what a pass may read, and
|
|
1748
|
+
* {@link LayerGroup} to run one chain over several layers at once.
|
|
1749
|
+
*/
|
|
1750
|
+
effects?: readonly Effect[];
|
|
1751
|
+
/**
|
|
1752
|
+
* Whether the renderer may keep this layer's pixels between frames and
|
|
1753
|
+
* composite them as one quad instead of drawing its commands again — see
|
|
1754
|
+
* {@link LayerRetainPolicy} for when `drawLayers` does. `false` never
|
|
1755
|
+
* retains it, `true` retains it whatever its size; either way only a layer
|
|
1756
|
+
* with `deps`, drawn through a cache, and without `effects`.
|
|
1757
|
+
*/
|
|
1758
|
+
retain?: boolean;
|
|
1759
|
+
/**
|
|
1760
|
+
* Optional hit-test for **consumer-attached** layers.
|
|
1761
|
+
*
|
|
1762
|
+
* Only layers registered through `CanvasExtensionApi.registerLayer` are
|
|
1763
|
+
* hit-tested, last-registered-first, ahead of the kit's own selection
|
|
1764
|
+
* chrome. First non-null result wins; null means "I don't claim this hit,
|
|
1765
|
+
* try the next layer."
|
|
1766
|
+
*
|
|
1767
|
+
* Layers that reach the draw stack some other way — a `Tool.overlay`, an
|
|
1768
|
+
* entry in the `layers` map — are painted but never hit-tested, so defining
|
|
1769
|
+
* `hitTest` on one has no effect.
|
|
1770
|
+
*
|
|
1771
|
+
* Coordinates are world-space.
|
|
1772
|
+
*/
|
|
1773
|
+
hitTest?: (worldX: number, worldY: number, data: TData, view: View, dims: Dims,
|
|
1774
|
+
/** Chrome-caps visibility predicate. When supplied, the layer must
|
|
1775
|
+
* not return a hit from any chrome element whose id reports
|
|
1776
|
+
* `false`. Absent → every element is hittable. */
|
|
1777
|
+
isVisible?: (id: string) => boolean) => LayerHit | null;
|
|
1778
|
+
/**
|
|
1779
|
+
* Called on every pointermove when no gesture is currently captured, so a
|
|
1780
|
+
* layer can track hover state. Coords are world-space, and the layer does
|
|
1781
|
+
* its own throttling.
|
|
1782
|
+
*/
|
|
1783
|
+
onUncapturedMove?: (worldX: number, worldY: number, evt: PointerEvent, view: View, dims: Dims) => void;
|
|
1784
|
+
/** Called when the cursor leaves the canvas element. */
|
|
1785
|
+
onUncapturedLeave?: () => void;
|
|
1786
|
+
}
|
|
1787
|
+
/** Where one layer's commands landed in {@link drawLayers}' output,
|
|
1788
|
+
* `[start, end)`, and the CPU milliseconds its `draw` took. A layer group's
|
|
1789
|
+
* run is one span under the group's id. */
|
|
1790
|
+
interface LayerDrawSpan {
|
|
1791
|
+
id: string;
|
|
1792
|
+
start: number;
|
|
1793
|
+
end: number;
|
|
1794
|
+
buildMs: number;
|
|
1795
|
+
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Walk visible layers and concatenate their emitted DrawCommand arrays into
|
|
1798
|
+
* one flat list, ready to feed to `WeaselRenderer.render(commands)`.
|
|
1799
|
+
*
|
|
1800
|
+
* A layer whose `draw` throws is dropped for the frame and reported through
|
|
1801
|
+
* `onLayerError` — the rest of the frame still paints.
|
|
1802
|
+
*
|
|
1803
|
+
* `groups` brackets runs of consecutive layers so they composite as one — see
|
|
1804
|
+
* `LayerGroup`. `spans`, when passed, receives one {@link LayerDrawSpan} per
|
|
1805
|
+
* layer drawn. `retain` decides which unchanged layers the renderer keeps
|
|
1806
|
+
* as pixels between frames; `false` keeps none.
|
|
1807
|
+
*/
|
|
1808
|
+
declare function drawLayers<TData>(layers: RenderLayer<TData>[], data: TData, visibility: Record<string, boolean>, order: string[] | undefined, view: View | undefined, dims: Dims, cache?: LayerCommandCache, onLayerError?: (failure: LayerDrawFailure) => void, groups?: readonly LayerGroup[], spans?: LayerDrawSpan[], retain?: LayerRetainPolicy | false): DrawCommand[];
|
|
1809
|
+
/**
|
|
1810
|
+
* Resolve one layer's visibility: `alwaysOn` wins, then an explicit entry in
|
|
1811
|
+
* `visibility`, then `defaultVisible`, defaulting to shown.
|
|
1812
|
+
*/
|
|
1813
|
+
declare function isLayerVisible<TData>(layer: RenderLayer<TData>, visibility: Record<string, boolean>): boolean;
|
|
1814
|
+
/**
|
|
1815
|
+
* Does this layer reach the screen at all — membership of
|
|
1816
|
+
* {@link paintedLayers}, asked of one layer.
|
|
1817
|
+
*
|
|
1818
|
+
* **A listed `order` is the whole list**, so omission from it drops a layer
|
|
1819
|
+
* that `visibility` would have shown, and `alwaysOn` does not rescue it.
|
|
1820
|
+
* Hit-testing asks this, not `isLayerVisible`.
|
|
1821
|
+
*/
|
|
1822
|
+
declare function isLayerPainted<TData>(layer: RenderLayer<TData>, visibility: Record<string, boolean>, order: readonly string[] | undefined): boolean;
|
|
1823
|
+
/**
|
|
1824
|
+
* The layers that reach the screen, in the order they are drawn: `order`
|
|
1825
|
+
* sequences them and drops what it leaves out, then `visibility` drops what is
|
|
1826
|
+
* hidden. What `drawLayers` paints, and what a view narrows its stack with.
|
|
1827
|
+
*/
|
|
1828
|
+
declare function paintedLayers<TData>(layers: readonly RenderLayer<TData>[], visibility: Record<string, boolean>, order: readonly string[] | undefined): RenderLayer<TData>[];
|
|
1829
|
+
/**
|
|
1830
|
+
* Draw one layer and put its commands in the space its `space` declares:
|
|
1831
|
+
* world-space output wrapped in a `viewToMat3(view)` group, screen-space
|
|
1832
|
+
* output passed through.
|
|
1833
|
+
*
|
|
1834
|
+
* Anything rendering layers through a view goes through here.
|
|
1835
|
+
*
|
|
1836
|
+
* A `draw` that throws yields no commands, and `onLayerError` is told which
|
|
1837
|
+
* layer it was. The layer's cache entry goes with it, so the next frame is a
|
|
1838
|
+
* real re-attempt.
|
|
1839
|
+
*/
|
|
1840
|
+
declare function drawOneLayer<TData>(layer: RenderLayer<TData>, data: TData, view: View, dims: Dims, cache?: LayerCommandCache, onLayerError?: (failure: LayerDrawFailure) => void): DrawCommand[];
|
|
1841
|
+
/** Whether `b` matches `a` entry for entry under `Object.is` — how
|
|
1842
|
+
* `RenderLayer.deps` is compared, and any cache keyed the same way. */
|
|
1843
|
+
declare function depsUnchanged(a: readonly unknown[], b: readonly unknown[]): boolean;
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* Paths that are no node, drawn over the scene: a region a tool would take,
|
|
1847
|
+
* the result an operation would make before it is applied.
|
|
1848
|
+
*/
|
|
1849
|
+
|
|
1850
|
+
/** One path to draw, in world coordinates, and what it is. */
|
|
1851
|
+
interface TransientPath {
|
|
1852
|
+
path: Path;
|
|
1853
|
+
/** Omitted reads as `'chrome'`. */
|
|
1854
|
+
role?: OverlayRole;
|
|
1855
|
+
}
|
|
1856
|
+
/** How one role reads. The stroke is one screen pixel wide at any zoom. */
|
|
1857
|
+
interface PathOverlayStyle {
|
|
1858
|
+
fill?: CommandPaint;
|
|
1859
|
+
stroke?: CommandPaint;
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* The kit's roles: `'chrome'` for a path shown for reference, `'picked'` for
|
|
1863
|
+
* one a gesture has taken, and `'remove'` for one it would delete.
|
|
1864
|
+
*/
|
|
1865
|
+
declare const PATH_OVERLAY_ROLES: Readonly<Record<string, PathOverlayStyle>>;
|
|
1866
|
+
/** The paths an overlay holds, and the layer that draws them. */
|
|
1867
|
+
interface PathOverlay {
|
|
1868
|
+
get(): readonly TransientPath[];
|
|
1869
|
+
/** Replace every path. */
|
|
1870
|
+
set(paths: readonly TransientPath[]): void;
|
|
1871
|
+
clear(): void;
|
|
1872
|
+
/** A world-space layer drawing the paths in order, repainting on each change. */
|
|
1873
|
+
layer: RenderLayer<unknown>;
|
|
1874
|
+
}
|
|
1875
|
+
/** Options for {@link createPathOverlay}. */
|
|
1876
|
+
interface PathOverlayOptions {
|
|
1877
|
+
/** The layer's id; see `RenderLayer.id`. */
|
|
1878
|
+
id: string;
|
|
1879
|
+
label?: string;
|
|
1880
|
+
/** Styles per role, merged over {@link PATH_OVERLAY_ROLES}. A role with
|
|
1881
|
+
* none paints as `'chrome'`. */
|
|
1882
|
+
roles?: Readonly<Record<string, PathOverlayStyle>>;
|
|
1883
|
+
}
|
|
1884
|
+
/** A store of transient paths and the layer that draws it; hand the layer to
|
|
1885
|
+
* a tool's `overlay` or a canvas's `layers`. */
|
|
1886
|
+
declare function createPathOverlay({ id, label, roles }: PathOverlayOptions): PathOverlay;
|
|
1887
|
+
|
|
1888
|
+
/** Cancel-key prefix. Each hook instance appends its own id, so two runners
|
|
1889
|
+
* sharing an animator do not cancel each other. */
|
|
1890
|
+
declare const VIEW_ANIMATION_KEY = "view";
|
|
1891
|
+
/** How the camera should move. */
|
|
1892
|
+
interface ViewAnimationOptions {
|
|
1893
|
+
/** Duration in ms. Default the `view.animationMs` kit setting, else `DEFAULT_VIEW_ANIMATION_MS`;
|
|
1894
|
+
* 0 under `prefers-reduced-motion`. */
|
|
1895
|
+
ms?: number;
|
|
1896
|
+
/** Easing curve. Default `easeOutCubic`. */
|
|
1897
|
+
easing?: EasingSpec;
|
|
1898
|
+
/** Replace the kit's log-scale / fixed-anchor curve. */
|
|
1899
|
+
interpolator?: InterpolatorFactory<View>;
|
|
1900
|
+
/** Fires when the target is reached. Not called on cancel. */
|
|
1901
|
+
onDone?: () => void;
|
|
1902
|
+
}
|
|
1903
|
+
/** Options accepted by {@link ViewAnimationApi.animateToBounds}. */
|
|
1904
|
+
interface AnimateToBoundsOptions extends FitViewToBoundsOptions, ViewAnimationOptions {
|
|
1905
|
+
}
|
|
1906
|
+
/** What the runner reads and writes. On `<SceneCanvas>` this is the same
|
|
1907
|
+
* channel `view.set` uses, so a camera animation on an uncontrolled canvas
|
|
1908
|
+
* costs no React render. */
|
|
1909
|
+
interface ViewChannel {
|
|
1910
|
+
get(): View;
|
|
1911
|
+
set(v: View): void;
|
|
1912
|
+
}
|
|
1913
|
+
/** The camera animation surface. Its own animations run one at a time. */
|
|
1914
|
+
interface ViewAnimationApi {
|
|
1915
|
+
/** Glide from the live view to `to`. A thunk receives the pending target when
|
|
1916
|
+
* one is in flight, so successive discrete steps compound. */
|
|
1917
|
+
animate(to: View | ((base: View) => View), opts?: ViewAnimationOptions): void;
|
|
1918
|
+
/** `fitViewToBounds` composed with `animate`. */
|
|
1919
|
+
animateToBounds(bounds: FramedBox, dims: ViewportDims, opts?: AnimateToBoundsOptions): void;
|
|
1920
|
+
/** Cancel. The view stays where it is — no jump to the target. */
|
|
1921
|
+
stop(): void;
|
|
1922
|
+
isAnimating(): boolean;
|
|
1923
|
+
/** Where the in-flight animation is heading, or null when none is. */
|
|
1924
|
+
target(): View | null;
|
|
1925
|
+
/** Cancel unless the write that prompted this came from the runner's own
|
|
1926
|
+
* per-frame write. Feed it from every channel that can move the camera. */
|
|
1927
|
+
stopIfExternal(): void;
|
|
1928
|
+
/**
|
|
1929
|
+
* The view as a {@link Target}, for running another animation on it: a shake
|
|
1930
|
+
* or a nudge adds to a camera animation in flight, and neither cancels the
|
|
1931
|
+
* other. Move it with the animator this runner was given, and without this
|
|
1932
|
+
* runner's cancel key. `stop` and an outside write leave such an animation
|
|
1933
|
+
* running.
|
|
1934
|
+
*/
|
|
1935
|
+
readonly viewTarget: Target<View>;
|
|
1936
|
+
}
|
|
1937
|
+
/** A `View` as the four numbers an animation moves: `x`, `y`, `scale.x`, `scale.y`. */
|
|
1938
|
+
declare const viewAxes: TargetAxes<View>;
|
|
1939
|
+
/**
|
|
1940
|
+
* Animate the viewport `View`. Runs on the kit's {@link Animator} — pass one to
|
|
1941
|
+
* share a canvas's animator, or omit it and the hook makes its own. A caller
|
|
1942
|
+
* that always has one should use {@link useViewAnimationOn}, which builds none.
|
|
1943
|
+
*
|
|
1944
|
+
* Every animation from one instance registers under that instance's cancel key,
|
|
1945
|
+
* so starting one cancels whatever *it* had in flight, and each starts from where
|
|
1946
|
+
* the last one was rather than a captured value — an interrupted camera never jumps.
|
|
1947
|
+
* Two instances on one animator are independent. The view is a target
|
|
1948
|
+
* ({@link ViewAnimationApi.viewTarget}), so other animations can add to the camera's.
|
|
1949
|
+
*/
|
|
1950
|
+
declare function useViewAnimation(view: ViewChannel, animator?: Animator): ViewAnimationApi;
|
|
1951
|
+
/** {@link useViewAnimation} on an animator the caller owns. Constructs no
|
|
1952
|
+
* animator of its own, so the camera runs on exactly the one passed. */
|
|
1953
|
+
declare function useViewAnimationOn(view: ViewChannel, animator: Animator): ViewAnimationApi;
|
|
1954
|
+
|
|
1955
|
+
/** Paths drawn over the canvas until the function `show` returns is called.
|
|
1956
|
+
* A later `show` replaces what an earlier one drew, and the earlier one's
|
|
1957
|
+
* function then takes nothing down. */
|
|
1958
|
+
interface PreviewPathsDep {
|
|
1959
|
+
show(paths: readonly TransientPath[]): () => void;
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
/** The snap readout's colors and line width, for a mark that sets no `color`. */
|
|
1963
|
+
interface SnapReadoutStyle {
|
|
1964
|
+
/** Points, lines and their labels. Default orange, as the path marker. */
|
|
1965
|
+
color?: string;
|
|
1966
|
+
/** Gap and distance marks. Default blue, as the guides. */
|
|
1967
|
+
gapColor?: string;
|
|
1968
|
+
/** Stroke width in screen px. Default 1. */
|
|
1969
|
+
lineWidth?: number;
|
|
1970
|
+
}
|
|
1971
|
+
/** A screen-space layer drawing the marks in `store`, redrawn when they change. */
|
|
1972
|
+
declare function createSnapReadoutLayer(store: SnapOutcomeStore, style?: SnapReadoutStyle): RenderLayer<unknown>;
|
|
1973
|
+
|
|
1974
|
+
/** The `snap` dep: what a drawn or dragged point locks to. */
|
|
1975
|
+
|
|
1976
|
+
type Point$4 = {
|
|
1977
|
+
x: number;
|
|
1978
|
+
y: number;
|
|
1979
|
+
};
|
|
1980
|
+
/** Geometry a gesture brings to snap to that is in no scene node: what stays
|
|
1981
|
+
* put of a path whose anchors it is dragging. World coords. */
|
|
1982
|
+
interface SnapGeometry {
|
|
1983
|
+
paths?: readonly Path[];
|
|
1984
|
+
/** Points to snap to as anchors. */
|
|
1985
|
+
anchors?: readonly Point$4[];
|
|
1986
|
+
}
|
|
1987
|
+
/** What builds a gesture's input subspace while `snap.constrain` is held:
|
|
1988
|
+
* an angle step in radians about `origin` (a rotate's every multiple of
|
|
1989
|
+
* it, required), an axis or 45° lock about the press, or a resize's
|
|
1990
|
+
* aspect. */
|
|
1991
|
+
type SnapConstrain = {
|
|
1992
|
+
step: number;
|
|
1993
|
+
} | 'aspect' | 'axis';
|
|
1994
|
+
/** The box a resize drags, as drawn, in its own frame. */
|
|
1995
|
+
interface SnapResizeBox {
|
|
1996
|
+
bounds: FramedBox;
|
|
1997
|
+
/** Its frame into ctx coordinates, an affine map. Default: the identity. */
|
|
1998
|
+
toWorld?: (p: Point$4) => Point$4;
|
|
1999
|
+
}
|
|
2000
|
+
/** What a gesture tells the snap dep when it starts. Points are ctx
|
|
2001
|
+
* coordinates: world in 2D. */
|
|
2002
|
+
interface SnapBegin {
|
|
2003
|
+
gesture: SnapGesture;
|
|
2004
|
+
press: Point$4;
|
|
2005
|
+
/** The subject, whose geometry offers no targets. */
|
|
2006
|
+
ids?: readonly string[];
|
|
2007
|
+
/** Resize: the sides the drag pins. An axis left `free` is an edge handle. */
|
|
2008
|
+
handle?: ResizeAnchor;
|
|
2009
|
+
/** Resize: the box `handle` belongs to. Default: the subject's drawn box,
|
|
2010
|
+
* axis-aligned. */
|
|
2011
|
+
box?: SnapResizeBox;
|
|
2012
|
+
/** Rotate, handle: the point the angle turns about. Default `press`. */
|
|
2013
|
+
pivot?: Point$4;
|
|
2014
|
+
/** Rotate: the subject's angle at press, radians. Default 0. */
|
|
2015
|
+
theta0?: number;
|
|
2016
|
+
/** Angle gestures: the reach as an angle, radians, in place of screen px
|
|
2017
|
+
* through the press radius; it overrides each source's `reachPx` and is
|
|
2018
|
+
* not capped. */
|
|
2019
|
+
reachRad?: number;
|
|
2020
|
+
/** Point gestures: the fixed end of what the gesture draws — a span's
|
|
2021
|
+
* start, the previous anchor, the anchor a handle pulls from. Tangent and
|
|
2022
|
+
* perpendicular targets are measured from it, a `constrain` step turns
|
|
2023
|
+
* about it, and no point target on it is offered. */
|
|
2024
|
+
origin?: Point$4;
|
|
2025
|
+
also?: SnapGeometry;
|
|
2026
|
+
constrain?: SnapConstrain;
|
|
2027
|
+
/** How the camera's world maps into the parallax plane the gesture's points
|
|
2028
|
+
* are in, read each frame; absent or null in the camera's own world. */
|
|
2029
|
+
plane?: () => PlaneMap | null;
|
|
2030
|
+
}
|
|
2031
|
+
/** The snap roles held this frame. */
|
|
2032
|
+
interface SnapMods {
|
|
2033
|
+
/** No source answers; the input subspace still applies. */
|
|
2034
|
+
suspend: boolean;
|
|
2035
|
+
constrain: boolean;
|
|
2036
|
+
/** Angle gestures: the angle stays at `theta0`, which becomes a required
|
|
2037
|
+
* target. */
|
|
2038
|
+
hold?: boolean;
|
|
2039
|
+
}
|
|
2040
|
+
/** Where a session put one frame's point, and the marks to draw for it. */
|
|
2041
|
+
interface SnapOutcome {
|
|
2042
|
+
point: Point$4;
|
|
2043
|
+
/** Whether some target holds the point. */
|
|
2044
|
+
held: boolean;
|
|
2045
|
+
marks: readonly SnapMark[];
|
|
2046
|
+
}
|
|
2047
|
+
/** One gesture's snapping, from press to release. */
|
|
2048
|
+
interface SnapSession {
|
|
2049
|
+
/** Where `p` lands. */
|
|
2050
|
+
at(p: Point$4, mods: SnapMods): SnapOutcome;
|
|
2051
|
+
/** Where the angle `theta` (radians, about `pivot`) lands. */
|
|
2052
|
+
angle(theta: number, mods: SnapMods): {
|
|
2053
|
+
theta: number;
|
|
2054
|
+
marks: readonly SnapMark[];
|
|
2055
|
+
};
|
|
2056
|
+
/** Clears the gesture's marks. */
|
|
2057
|
+
end(): void;
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Snapping, for every gesture that snaps: each one begins a session at press
|
|
2061
|
+
* and asks it, frame by frame, where its point lands. Points are ctx
|
|
2062
|
+
* coordinates — world in 2D, screen in a 3D host.
|
|
2063
|
+
*/
|
|
2064
|
+
interface SnapDep {
|
|
2065
|
+
/** Start a gesture's snap session. */
|
|
2066
|
+
begin(req: SnapBegin): SnapSession;
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
/** The snap source contract: what a target set offers a snap session, and
|
|
2070
|
+
* the marks a session draws for what it met. */
|
|
2071
|
+
|
|
2072
|
+
type Point$3 = {
|
|
2073
|
+
x: number;
|
|
2074
|
+
y: number;
|
|
2075
|
+
};
|
|
2076
|
+
/** The positions a target allows: `at` plus any combination of `dirs`. No
|
|
2077
|
+
* dirs is a point, one a line, two a plane. */
|
|
2078
|
+
interface Locus<P = Point$3> {
|
|
2079
|
+
at: P;
|
|
2080
|
+
dirs: readonly P[];
|
|
2081
|
+
/** One interval per dir, in multiples of it: a segment or a bounded face. */
|
|
2082
|
+
span?: readonly (readonly [number, number])[];
|
|
2083
|
+
}
|
|
2084
|
+
/** One locus a source offers one probe. */
|
|
2085
|
+
interface SourceCandidate<P = Point$3> {
|
|
2086
|
+
/** The id of a probe the source was offered. */
|
|
2087
|
+
probe: string;
|
|
2088
|
+
locus: Locus<P>;
|
|
2089
|
+
/** The result must meet one required candidate, whatever its reach. */
|
|
2090
|
+
required?: boolean;
|
|
2091
|
+
/** Drawn when the result meets this candidate. A function is handed the
|
|
2092
|
+
* resolved move, so the marks can sit where the probe landed. */
|
|
2093
|
+
mark?: SnapMarks<P> | ((delta: P) => SnapMarks<P>);
|
|
2094
|
+
}
|
|
2095
|
+
/** `'handle'` is an angle about an anchor, as `'rotate'` is about a pivot,
|
|
2096
|
+
* but asks only sources that name it. */
|
|
2097
|
+
type SnapGesture = 'point' | 'move' | 'resize' | 'rotate' | 'handle';
|
|
2098
|
+
/** The sides of a box a gesture moves on one axis; null for neither. */
|
|
2099
|
+
type SnapEdge = 'min' | 'max' | 'both' | null;
|
|
2100
|
+
/** Which sides of the subject's box a gesture moves, per axis. */
|
|
2101
|
+
interface SnapEdges {
|
|
2102
|
+
x: SnapEdge;
|
|
2103
|
+
y: SnapEdge;
|
|
2104
|
+
}
|
|
2105
|
+
/** A point on the subject that should land on a locus. */
|
|
2106
|
+
interface SnapProbeAt<P = Point$3> {
|
|
2107
|
+
id: string;
|
|
2108
|
+
at: P;
|
|
2109
|
+
role: ProbeRole;
|
|
2110
|
+
}
|
|
2111
|
+
/** What a session asks a source for, once per frame. */
|
|
2112
|
+
interface SnapCollect<P = Point$3> {
|
|
2113
|
+
gesture: SnapGesture;
|
|
2114
|
+
/** The probes this source matches, where the unsnapped gesture puts them. */
|
|
2115
|
+
probes: readonly SnapProbeAt<P>[];
|
|
2116
|
+
/** The unsnapped move from the press. A probe at `at` here lands at
|
|
2117
|
+
* `at - delta0 + delta` for the resolved `delta` a function mark gets. */
|
|
2118
|
+
delta0: P;
|
|
2119
|
+
/** The subject's drawn box, stroke included, where the unsnapped gesture
|
|
2120
|
+
* puts it: a move's union of boxes, or the box a resize drags. Absent for
|
|
2121
|
+
* other gestures. */
|
|
2122
|
+
box?: FramedBox;
|
|
2123
|
+
/** Which sides of `box` the gesture moves on each axis. Default: both, as
|
|
2124
|
+
* a move does. */
|
|
2125
|
+
edges?: SnapEdges;
|
|
2126
|
+
/** `id`'s drawn box, measured as `box` is. Absent in a host with no 2D
|
|
2127
|
+
* scene. */
|
|
2128
|
+
drawnBox?(id: string): FramedBox | undefined;
|
|
2129
|
+
/** Nodes that offer no targets: what the gesture moves. */
|
|
2130
|
+
exclude: readonly string[];
|
|
2131
|
+
/** Only these nodes offer targets. */
|
|
2132
|
+
include?: readonly string[];
|
|
2133
|
+
/** Where the geometry being drawn starts; tangent and perpendicular targets
|
|
2134
|
+
* are measured from it. */
|
|
2135
|
+
origin?: P;
|
|
2136
|
+
also?: SnapGeometry;
|
|
2137
|
+
/** `px` screen pixels as world units: a radius to cull targets by. */
|
|
2138
|
+
reachWorld(px: number): number;
|
|
2139
|
+
/** The reach, in screen px, the session applies to this source: its own
|
|
2140
|
+
* `reachPx`, else the canvas's. Candidates past it are dropped anyway. */
|
|
2141
|
+
reachPx: number;
|
|
2142
|
+
/** Absent in a host with no 2D scene. */
|
|
2143
|
+
scene?: Scene<unknown, string, unknown>;
|
|
2144
|
+
/** How the camera's world maps into the parallax plane the probes are in.
|
|
2145
|
+
* Absent in the camera's own world. A target the camera draws, a grid or
|
|
2146
|
+
* a ruler guide, is carried through it. */
|
|
2147
|
+
plane?: PlaneMap | null;
|
|
2148
|
+
}
|
|
2149
|
+
/** What a rotate or handle drag asks a source for, once per frame. Angles
|
|
2150
|
+
* are radians about `pivot`, in the frame `rotationOf` reads. */
|
|
2151
|
+
interface AngleCollect {
|
|
2152
|
+
pivot: Point$3;
|
|
2153
|
+
/** Where the gesture was pressed: its distance from `pivot` is the radius
|
|
2154
|
+
* the default marks are drawn at. */
|
|
2155
|
+
press: Point$3;
|
|
2156
|
+
/** The angle at press. */
|
|
2157
|
+
theta0: number;
|
|
2158
|
+
/** The unsnapped angle now. */
|
|
2159
|
+
theta: number;
|
|
2160
|
+
/** The subject. */
|
|
2161
|
+
ids: readonly string[];
|
|
2162
|
+
/** Nodes that offer no targets: the subject and everything under it. */
|
|
2163
|
+
exclude: readonly string[];
|
|
2164
|
+
mods: SnapMods;
|
|
2165
|
+
also?: SnapGeometry;
|
|
2166
|
+
/** Absent in a host with no 2D scene. */
|
|
2167
|
+
scene?: Scene<unknown, string, unknown>;
|
|
2168
|
+
/** `id`'s world rotation, read as the subject's is; undefined for a node
|
|
2169
|
+
* that cannot turn. */
|
|
2170
|
+
rotationOf?(id: string): number | undefined;
|
|
2171
|
+
}
|
|
2172
|
+
/** An angle a source offers. The session compares it round the circle, so
|
|
2173
|
+
* any whole turn of it is the same target. */
|
|
2174
|
+
interface AngleCandidate {
|
|
2175
|
+
angle: number;
|
|
2176
|
+
/** The result must land on one required angle, whatever its reach. */
|
|
2177
|
+
required?: boolean;
|
|
2178
|
+
/** Drawn when the result lands on it. Default: a ray from the pivot along
|
|
2179
|
+
* the snapped angle, labeled in degrees. */
|
|
2180
|
+
mark?: SnapMarks;
|
|
2181
|
+
}
|
|
2182
|
+
/** A set of snap targets. */
|
|
2183
|
+
interface SnapSource<P = Point$3> {
|
|
2184
|
+
id: string;
|
|
2185
|
+
/** Default `'target'`. A fallback never displaces a target in reach. */
|
|
2186
|
+
tier?: SnapTier;
|
|
2187
|
+
/** Overrides the canvas's reach for this source, in screen px. */
|
|
2188
|
+
reachPx?: number;
|
|
2189
|
+
/** The probe roles it matches; it is never offered a probe of another. */
|
|
2190
|
+
roles: readonly ProbeRole[];
|
|
2191
|
+
/** Default: every gesture but `'rotate'` and `'handle'`. */
|
|
2192
|
+
gestures?: readonly SnapGesture[];
|
|
2193
|
+
collect(q: SnapCollect<P>): Iterable<SourceCandidate<P>>;
|
|
2194
|
+
/** Angle targets, for a source whose `gestures` include `'rotate'` or `'handle'`. */
|
|
2195
|
+
angles?(q: AngleCollect): Iterable<AngleCandidate>;
|
|
2196
|
+
}
|
|
2197
|
+
/** One mark, or several, for one candidate. */
|
|
2198
|
+
type SnapMarks<P = Point$3> = SnapMark<P> | readonly SnapMark<P>[];
|
|
2199
|
+
/** What a session draws for a candidate the result meets. World coords. */
|
|
2200
|
+
type SnapMark<P = Point$3> = {
|
|
2201
|
+
kind: 'point';
|
|
2202
|
+
at: P;
|
|
2203
|
+
glyph: string;
|
|
2204
|
+
label?: string;
|
|
2205
|
+
color?: string;
|
|
2206
|
+
} | {
|
|
2207
|
+
kind: 'line';
|
|
2208
|
+
from: P;
|
|
2209
|
+
to: P;
|
|
2210
|
+
color?: string;
|
|
2211
|
+
} | {
|
|
2212
|
+
kind: 'gap';
|
|
2213
|
+
from: P;
|
|
2214
|
+
to: P;
|
|
2215
|
+
value: number;
|
|
2216
|
+
color?: string;
|
|
2217
|
+
} | {
|
|
2218
|
+
kind: 'distance';
|
|
2219
|
+
from: P;
|
|
2220
|
+
to: P;
|
|
2221
|
+
value: number;
|
|
2222
|
+
color?: string;
|
|
2223
|
+
};
|
|
2224
|
+
/** `<SceneCanvas snap>`. */
|
|
2225
|
+
interface SceneCanvasSnap {
|
|
2226
|
+
/** Sources ahead of the presets' `snapSources` and any `useSnapSource`.
|
|
2227
|
+
* One source per id is asked: the last listed, in the order prop,
|
|
2228
|
+
* presets, `useSnapSource` in mount order. A canvas default (`'rotation'`,
|
|
2229
|
+
* `'path-snap'`) loses to any of them. */
|
|
2230
|
+
sources?: readonly SnapSource[];
|
|
2231
|
+
/** Ids of canvas defaults to leave out: `'rotation'` stops a rotate
|
|
2232
|
+
* snapping to quarter turns and other nodes' angles (Shift's step is the
|
|
2233
|
+
* rotate's own and stays), and `'path-snap'` stops a point gesture (the
|
|
2234
|
+
* pen, an anchor drag, a drawn line's ends, a measurement) snapping to
|
|
2235
|
+
* other nodes' anchors. */
|
|
2236
|
+
omit?: readonly string[];
|
|
2237
|
+
/** The reach of a source that sets none, in screen px. Default: the kit
|
|
2238
|
+
* setting `targets.snapPx`. */
|
|
2239
|
+
reachPx?: number;
|
|
2240
|
+
/** How a pose's origin is read, for the `origin` probe a grid or a ruler
|
|
2241
|
+
* guide snaps: a pose neither a rect nor a `Path` needs its own. Default
|
|
2242
|
+
* `AUTO_ORIGIN_PROJECTION`. */
|
|
2243
|
+
originProjection?: OriginProjection<unknown>;
|
|
2244
|
+
/** Whether the snap marks are drawn. Default `true`. */
|
|
2245
|
+
readout?: boolean;
|
|
2246
|
+
/** The readout's default colors and line width, for a mark that sets no `color`. */
|
|
2247
|
+
readoutStyle?: SnapReadoutStyle;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
type Point$2 = {
|
|
2251
|
+
x: number;
|
|
2252
|
+
y: number;
|
|
2253
|
+
};
|
|
2254
|
+
/** The marks of the snap in flight, for the readout to draw. */
|
|
2255
|
+
interface SnapOutcomeStore<P = Point$2> {
|
|
2256
|
+
get(): readonly SnapMark<P>[];
|
|
2257
|
+
set(marks: readonly SnapMark<P>[]): void;
|
|
2258
|
+
subscribe(listener: () => void): () => void;
|
|
2259
|
+
}
|
|
2260
|
+
/** An empty outcome store, which notifies only when the marks change. */
|
|
2261
|
+
declare function createSnapOutcomeStore<P = Point$2>(): SnapOutcomeStore<P>;
|
|
2262
|
+
|
|
2263
|
+
/** The `snapReadout` dep: where marks go to be drawn. */
|
|
2264
|
+
interface SnapReadoutDep {
|
|
2265
|
+
store: SnapOutcomeStore;
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
/**
|
|
2269
|
+
* Consumer-supplied node factory for one insert `kind`. Given the drag AABB
|
|
2270
|
+
* and the tool's `extras`, returns the node's `data` (in the consumer's own
|
|
2271
|
+
* data shape) plus an optional `pose` override — the dep supplies id, layer,
|
|
2272
|
+
* and the undoable insert op. Return `null` to reject the insert.
|
|
2273
|
+
*
|
|
2274
|
+
* A factory registered for a kit kind (`rect`, `line`, …) fully replaces the
|
|
2275
|
+
* kit's default `{ path, fill }` factory for that kind; a factory for a novel
|
|
2276
|
+
* kind adds support the kit doesn't ship (e.g. `text`). To change only the
|
|
2277
|
+
* paint of a kit shape, pass an {@link InsertPaint}. See
|
|
2278
|
+
* `SceneCanvas`'s `insertNodeFactories` prop.
|
|
2279
|
+
*/
|
|
2280
|
+
type InsertNodeFactory = (bounds: {
|
|
2281
|
+
x: number;
|
|
2282
|
+
y: number;
|
|
2283
|
+
width: number;
|
|
2284
|
+
height: number;
|
|
2285
|
+
}, extras: InsertExtras) => {
|
|
2286
|
+
data: unknown;
|
|
2287
|
+
pose?: unknown;
|
|
2288
|
+
} | null;
|
|
2289
|
+
/**
|
|
2290
|
+
* The paint a kit-built shape is inserted with. `kind` is the shape being
|
|
2291
|
+
* built and `seq` counts this canvas's inserts from 1. A key left out stays
|
|
2292
|
+
* off the node, so its painter's default applies; `null` is "none". A pencil
|
|
2293
|
+
* trail too short to fit is built as a rect and asks as one. A line and an
|
|
2294
|
+
* open pen path are inserted unfilled: a fill given to either is dropped.
|
|
2295
|
+
* `fillRule` is the rule a path that carries one is built with, where the
|
|
2296
|
+
* kit's own is nonzero; a rect or an ellipse has none to set.
|
|
2297
|
+
*
|
|
2298
|
+
* It paints only the shapes the kit builds: an `InsertNodeFactory` owns its
|
|
2299
|
+
* node's whole `data`. See `SceneCanvas`'s `insertPaint` prop.
|
|
2300
|
+
*/
|
|
2301
|
+
type InsertPaint = (kind: string, seq: number) => {
|
|
2302
|
+
fill?: Fill | null;
|
|
2303
|
+
stroke?: Stroke | null;
|
|
2304
|
+
fillRule?: PathFillRule;
|
|
2305
|
+
};
|
|
2306
|
+
/** The default {@link InsertPaint}: the next color of the kit palette, as a
|
|
2307
|
+
* fill on a closed shape, a fill and a stroke on a pen path, and a stroke
|
|
2308
|
+
* alone on a line or a pencil trail. */
|
|
2309
|
+
declare const paletteInsertPaint: InsertPaint;
|
|
2310
|
+
|
|
2311
|
+
/** The `data` a `kit:text` node carries. */
|
|
2312
|
+
interface TextNodeData {
|
|
2313
|
+
text: string;
|
|
2314
|
+
style?: TextStyle;
|
|
2315
|
+
runs?: readonly StyledRun[];
|
|
2316
|
+
fill?: Fill | null;
|
|
2317
|
+
stroke?: Stroke | null;
|
|
2318
|
+
verticalAlign?: TextVerticalAlign;
|
|
2319
|
+
/** Paint for the whole pose box, drawn under the glyphs. `fill` is the
|
|
2320
|
+
* glyphs' own paint, so a box behind them needs a key of its own. */
|
|
2321
|
+
background?: Fill | null;
|
|
2322
|
+
/** World units between the pose box and the box the text lays out in, on
|
|
2323
|
+
* every side. */
|
|
2324
|
+
padding?: number;
|
|
2325
|
+
/** What happens to text that runs past the pose box: `'visible'` (the
|
|
2326
|
+
* default) draws it there, `'clip'` cuts it at the box's edge. */
|
|
2327
|
+
overflow?: TextOverflow;
|
|
2328
|
+
}
|
|
2329
|
+
/** How a text node treats lines that run past its box. */
|
|
2330
|
+
type TextOverflow = 'visible' | 'clip';
|
|
2331
|
+
/** The box a text node's lines lay out in: its pose box, inset by
|
|
2332
|
+
* `data.padding` and never past its center. */
|
|
2333
|
+
declare function textBoxOf(d: Pick<TextNodeData, 'padding'>, p: RectPose): {
|
|
2334
|
+
x: number;
|
|
2335
|
+
y: number;
|
|
2336
|
+
width: number;
|
|
2337
|
+
height: number;
|
|
2338
|
+
};
|
|
2339
|
+
|
|
2340
|
+
/** The smallest box a node may be drawn or resized to, in world units. */
|
|
2341
|
+
interface MinSize {
|
|
2342
|
+
width: number;
|
|
2343
|
+
height: number;
|
|
2344
|
+
}
|
|
2345
|
+
/** A node's minimum, from `data.minSize`, or `null` when it has none. A
|
|
2346
|
+
* side that is not a positive number holds nothing. */
|
|
2347
|
+
declare function minSizeOf(data: unknown): MinSize | null;
|
|
2348
|
+
|
|
2349
|
+
/** How a sticky note looks as it is made, named as the text node it becomes
|
|
2350
|
+
* names them. Every field but `fill` has a default, in {@link STICKY_DEFAULTS}. */
|
|
2351
|
+
interface StickyStyle {
|
|
2352
|
+
/** The note itself, painted over its whole box. */
|
|
2353
|
+
background?: Fill;
|
|
2354
|
+
/** The text's paint. Absent, the text style's default. */
|
|
2355
|
+
fill?: Fill;
|
|
2356
|
+
/** World units from the note's edge to its text, on every side. */
|
|
2357
|
+
padding?: number;
|
|
2358
|
+
/** Typography for the note's text. */
|
|
2359
|
+
style?: TextStyle;
|
|
2360
|
+
verticalAlign?: TextVerticalAlign;
|
|
2361
|
+
/** What happens to text that outgrows the note. */
|
|
2362
|
+
overflow?: TextOverflow;
|
|
2363
|
+
/** The smallest note a drag makes or a resize leaves, in world units. */
|
|
2364
|
+
minSize?: MinSize;
|
|
2365
|
+
/** The note a click makes, centered on the click, in world units. A drag
|
|
2366
|
+
* makes the note it draws. */
|
|
2367
|
+
size?: {
|
|
2368
|
+
width: number;
|
|
2369
|
+
height: number;
|
|
2370
|
+
};
|
|
2371
|
+
}
|
|
2372
|
+
/** The look a sticky note takes for any field its tool leaves out. */
|
|
2373
|
+
declare const STICKY_DEFAULTS: {
|
|
2374
|
+
readonly background: {
|
|
2375
|
+
readonly paint: {
|
|
2376
|
+
readonly kind: "solid";
|
|
2377
|
+
readonly color: "#fff1a6ff";
|
|
2378
|
+
};
|
|
2379
|
+
};
|
|
2380
|
+
readonly padding: 12;
|
|
2381
|
+
readonly style: {
|
|
2382
|
+
readonly fontSize: 18;
|
|
2383
|
+
readonly align: "center";
|
|
2384
|
+
readonly wrap: true;
|
|
2385
|
+
};
|
|
2386
|
+
readonly verticalAlign: "center";
|
|
2387
|
+
readonly overflow: "clip";
|
|
2388
|
+
readonly minSize: {
|
|
2389
|
+
readonly width: 48;
|
|
2390
|
+
readonly height: 48;
|
|
2391
|
+
};
|
|
2392
|
+
readonly size: {
|
|
2393
|
+
readonly width: 160;
|
|
2394
|
+
readonly height: 160;
|
|
2395
|
+
};
|
|
2396
|
+
};
|
|
2397
|
+
/**
|
|
2398
|
+
* A sticky note's `data`: a text node with a `background`, so the `kit:text`
|
|
2399
|
+
* painter draws it and the text editor edits it with no sticky case of its
|
|
2400
|
+
* own. `look` is the `sticky` insert's extras, which carry the tool's
|
|
2401
|
+
* {@link StickyStyle}.
|
|
2402
|
+
*/
|
|
2403
|
+
declare function stickyData(look: StickyStyle & {
|
|
2404
|
+
text?: string;
|
|
2405
|
+
}): TextNodeData & {
|
|
2406
|
+
minSize: MinSize;
|
|
2407
|
+
};
|
|
2408
|
+
/** The kit's `sticky` insert as an `InsertNodeFactory`, for a canvas that
|
|
2409
|
+
* wraps it — to tag the data with a `kind`, say — under `insertNodeFactories`. */
|
|
2410
|
+
declare const stickyNodeFactory: InsertNodeFactory;
|
|
2411
|
+
|
|
2412
|
+
/** Per-axis limits on a view's position. Any side may be left open. */
|
|
2413
|
+
interface PanBounds {
|
|
2414
|
+
minX?: number;
|
|
2415
|
+
maxX?: number;
|
|
2416
|
+
minY?: number;
|
|
2417
|
+
maxY?: number;
|
|
2418
|
+
}
|
|
2419
|
+
/** Momentum settings for a pan: how quickly a flung view slows, when it stops,
|
|
2420
|
+
* and what happens at the pan limits. The `DecayLoopConfig` fields a caller
|
|
2421
|
+
* chooses up front, without the per-gesture `velocity` / `onTick`. */
|
|
2422
|
+
interface InertiaConfig {
|
|
2423
|
+
friction?: number;
|
|
2424
|
+
minSpeed?: number;
|
|
2425
|
+
/** What to do when inertial pan reaches `bounds`. Default: no clamping. */
|
|
2426
|
+
boundary?: 'stop' | 'bounce' | 'spring';
|
|
2427
|
+
/** View-coordinate limits for boundary clamping. Requires `boundary` to take effect. */
|
|
2428
|
+
bounds?: PanBounds;
|
|
2429
|
+
}
|
|
2430
|
+
/** How a decay should run: its starting velocity, how fast it slows, and what
|
|
2431
|
+
* happens if it reaches the pan limits. */
|
|
2432
|
+
interface DecayLoopConfig {
|
|
2433
|
+
velocity: {
|
|
2434
|
+
vx: number;
|
|
2435
|
+
vy: number;
|
|
2436
|
+
};
|
|
2437
|
+
friction?: number;
|
|
2438
|
+
minSpeed?: number;
|
|
2439
|
+
/** Bounds for boundary clamping. Requires `boundary` to take effect. */
|
|
2440
|
+
viewBounds?: PanBounds;
|
|
2441
|
+
/**
|
|
2442
|
+
* What to do when the accumulated position hits `viewBounds`. Default: no clamping.
|
|
2443
|
+
* - `'stop'`: clamp at boundary, kill velocity component.
|
|
2444
|
+
* - `'bounce'`: linear reflection — flip velocity sign, magnitude preserved.
|
|
2445
|
+
* - `'spring'`: damped reflection — flip velocity sign and shrink magnitude
|
|
2446
|
+
* by `SPRING_DAMPING` per bounce so the motion settles naturally.
|
|
2447
|
+
*/
|
|
2448
|
+
boundary?: 'stop' | 'bounce' | 'spring';
|
|
2449
|
+
/** Starting position for internal boundary tracking. Required when `viewBounds` is set. */
|
|
2450
|
+
initialPosition?: {
|
|
2451
|
+
x: number;
|
|
2452
|
+
y: number;
|
|
2453
|
+
};
|
|
2454
|
+
onTick: (dx: number, dy: number) => void;
|
|
2455
|
+
onEnd?: () => void;
|
|
2456
|
+
}
|
|
2457
|
+
/** A rAF loop that coasts a value to a stop under friction, reporting the
|
|
2458
|
+
* per-frame delta. What turns a released pan drag into momentum scrolling. */
|
|
2459
|
+
declare function useDecayLoop(): {
|
|
2460
|
+
start: (config: DecayLoopConfig) => void;
|
|
2461
|
+
cancel: () => void;
|
|
2462
|
+
};
|
|
2463
|
+
|
|
2464
|
+
/**
|
|
2465
|
+
* The lifecycle the ongoing transform actions (`move`, `resize`, `rotate`)
|
|
2466
|
+
* share: what their committed batch is called in history, whether it is
|
|
2467
|
+
* recorded at all, and the callbacks fired as the gesture opens and closes.
|
|
2468
|
+
*
|
|
2469
|
+
* Move and rotate read it from their binding's params; resize reads it from
|
|
2470
|
+
* the `resizePolicy` dep, where the rest of its options already live.
|
|
2471
|
+
*/
|
|
2472
|
+
|
|
2473
|
+
/** The lifecycle options, as a binding's params or the resize policy carry
|
|
2474
|
+
* them. */
|
|
2475
|
+
interface GestureLifecycleOptions {
|
|
2476
|
+
/** History label for the committed batch. Unset, the batch takes its first
|
|
2477
|
+
* op's label (a layout drop or a behavior names its own), else the
|
|
2478
|
+
* action's. */
|
|
2479
|
+
label?: string;
|
|
2480
|
+
/** Commit through `scene.untracked`: the edit lands, but no undo entry
|
|
2481
|
+
* records it and the consumer `applyOps` hook is bypassed. Unset, any
|
|
2482
|
+
* behavior's `defaultTransient: true` turns it on. */
|
|
2483
|
+
transient?: boolean;
|
|
2484
|
+
/** Fired once the gesture starts changing poses, with the ids it moves. */
|
|
2485
|
+
onGestureStart?(ids: string[]): void;
|
|
2486
|
+
/** Fired once per `onGestureStart`: `true` when the gesture wrote to the
|
|
2487
|
+
* document, `false` on cancel, abort, or a release with nothing to write. */
|
|
2488
|
+
onGestureEnd?(committed: boolean): void;
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
/** Optional consumer seam: given a node and the affine `m` that a pose-transform
|
|
2492
|
+
* action applied to the node's POSE, return updated `data` with the node's
|
|
2493
|
+
* data-held geometry transformed by `m`, or `null` if this node has no
|
|
2494
|
+
* data-held geometry (the kit leaves `data` alone). */
|
|
2495
|
+
interface GeometryProjection {
|
|
2496
|
+
transform(node: {
|
|
2497
|
+
id?: string;
|
|
2498
|
+
data: unknown;
|
|
2499
|
+
pose: unknown;
|
|
2500
|
+
}, m: Affine): unknown | null;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
/** What a handle drag holds fixed: its direction from the anchor, or its length. */
|
|
2504
|
+
type HandleLock = 'angle' | 'length';
|
|
2505
|
+
/** Which handle locks are held for every handle drag, on top of the modifiers.
|
|
2506
|
+
* Both together freeze the handle. */
|
|
2507
|
+
interface HandleLocks {
|
|
2508
|
+
angle: boolean;
|
|
2509
|
+
length: boolean;
|
|
2510
|
+
}
|
|
2511
|
+
/**
|
|
2512
|
+
* The params `editAnchors` reads, through `<SceneCanvas tune>` or a binding.
|
|
2513
|
+
* Read on every move, so a change mid-drag reaches the drag.
|
|
2514
|
+
*/
|
|
2515
|
+
type EditAnchorsParams = {
|
|
2516
|
+
/** A lock held for every handle drag without a modifier: Shift holds the
|
|
2517
|
+
* angle, Mod (Cmd or Ctrl) the length. Under `<SceneCanvas>` this is where
|
|
2518
|
+
* the `handleLock.angle` and `handleLock.length` toggles start from; once
|
|
2519
|
+
* one is pressed, the locks the `editAnchors` dep holds decide. */
|
|
2520
|
+
handleLock?: HandleLock | null;
|
|
2521
|
+
};
|
|
2522
|
+
|
|
2523
|
+
/**
|
|
2524
|
+
* A path drawn from another form the node keeps beside it, such as a curve
|
|
2525
|
+
* solved through the points it passes. The node's path stays the geometry
|
|
2526
|
+
* every reader draws and hit-tests; `data.representation` holds the form,
|
|
2527
|
+
* named by its `kind`. A preset that knows a kind brings a
|
|
2528
|
+
* {@link PathRepresentation} for it (`PathEditExtension.representation`),
|
|
2529
|
+
* through which path edit shows and edits the form. Where none is on, path
|
|
2530
|
+
* edit edits the drawn path, and the edit drops the form.
|
|
2531
|
+
*/
|
|
2532
|
+
|
|
2533
|
+
/** What `data.representation` holds: a form named by `kind`, with whatever
|
|
2534
|
+
* that kind keeps. */
|
|
2535
|
+
interface PathForm {
|
|
2536
|
+
readonly kind: string;
|
|
2537
|
+
readonly [field: string]: unknown;
|
|
2538
|
+
}
|
|
2539
|
+
type Point$1 = {
|
|
2540
|
+
x: number;
|
|
2541
|
+
y: number;
|
|
2542
|
+
};
|
|
2543
|
+
/** The outline of an anchor's marker, in screen space: `size` px across at
|
|
2544
|
+
* `at`, with the anchor's neighbors along its subpath, null past an open
|
|
2545
|
+
* end. */
|
|
2546
|
+
type AnchorMarkerShape = (at: Point$1, size: number, prev: Point$1 | null, next: Point$1 | null) => PolygonPath;
|
|
2547
|
+
/** How path edit reads and writes one kind of {@link PathForm}. */
|
|
2548
|
+
interface PathRepresentation {
|
|
2549
|
+
/** The `kind` of the forms it reads. */
|
|
2550
|
+
readonly kind: string;
|
|
2551
|
+
/** What path edit shows and moves for a node holding `form`, whose drawn
|
|
2552
|
+
* path in world space is `path`. Null when `form` does not describe
|
|
2553
|
+
* `path`: path edit then edits `path`, and the edit drops the form. */
|
|
2554
|
+
editPath(path: PolygonPath, form: PathForm): PolygonPath | null;
|
|
2555
|
+
/**
|
|
2556
|
+
* The drawn path an edit makes, and the form to keep beside it: `edited` is
|
|
2557
|
+
* an edit of what {@link editPath} gave, `path` the drawn path it was given
|
|
2558
|
+
* from. Null when `form` does not describe `path`; the edit is then stored
|
|
2559
|
+
* as drawn, without the form. Runs on every commit of an edit and every
|
|
2560
|
+
* frame of one in flight.
|
|
2561
|
+
*/
|
|
2562
|
+
store(path: PolygonPath, form: PathForm, edited: PolygonPath): {
|
|
2563
|
+
path: PolygonPath;
|
|
2564
|
+
form: PathForm;
|
|
2565
|
+
} | null;
|
|
2566
|
+
/** The marker of each anchor of the edit path, by flat index. An anchor
|
|
2567
|
+
* with none draws path edit's square. */
|
|
2568
|
+
anchorMarkers?(form: PathForm): readonly (AnchorMarkerShape | null)[];
|
|
2569
|
+
/**
|
|
2570
|
+
* A press at world point `at` on the drawn outline of the node in path
|
|
2571
|
+
* edit: the drag it starts, or null when it starts none there. A
|
|
2572
|
+
* representation that has this takes every segment press, in place of
|
|
2573
|
+
* Bend segment.
|
|
2574
|
+
*/
|
|
2575
|
+
segmentPress?(deps: ActionDeps, at: Point$1): (() => OngoingHandle) | null;
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
/**
|
|
2579
|
+
* What a feature adds to path edit without path edit knowing it: marks drawn
|
|
2580
|
+
* on the open path, parts of it to press, marks a click selects and Delete
|
|
2581
|
+
* removes, a share in shaping an anchor or handle drag, what an edit must keep
|
|
2582
|
+
* true when it commits, and how a path drawn from another form is edited. A
|
|
2583
|
+
* preset carries its extensions as `FeaturePreset.pathEdit`; core consults
|
|
2584
|
+
* them in preset order.
|
|
2585
|
+
*/
|
|
2586
|
+
|
|
2587
|
+
/** A mark an extension drew that is selected in place of anchors: Delete
|
|
2588
|
+
* acts on it, and selecting anchors clears it. */
|
|
2589
|
+
interface PathEditMark {
|
|
2590
|
+
/** The extension that drew it. */
|
|
2591
|
+
owner: string;
|
|
2592
|
+
/** Which of its marks, in the extension's own numbering. */
|
|
2593
|
+
index: number;
|
|
2594
|
+
}
|
|
2595
|
+
/** The open path as an extension's marks and parts read it. */
|
|
2596
|
+
interface PathEditTarget {
|
|
2597
|
+
/** The node being edited. */
|
|
2598
|
+
id: string;
|
|
2599
|
+
/** Its committed pose and data. */
|
|
2600
|
+
node: {
|
|
2601
|
+
pose: unknown;
|
|
2602
|
+
data: unknown;
|
|
2603
|
+
};
|
|
2604
|
+
/** The path as drawn now, in-flight edits included, in world space. */
|
|
2605
|
+
path: PolygonPath;
|
|
2606
|
+
/** `path`'s anchors. */
|
|
2607
|
+
anchors: AnchorSet;
|
|
2608
|
+
}
|
|
2609
|
+
/** What {@link PathEditExtension.marks} draws with. */
|
|
2610
|
+
interface PathEditMarksCtx extends PathEditTarget {
|
|
2611
|
+
view: View;
|
|
2612
|
+
/** World space to the screen space the marks are drawn in. */
|
|
2613
|
+
toScreen(p: {
|
|
2614
|
+
x: number;
|
|
2615
|
+
y: number;
|
|
2616
|
+
}): {
|
|
2617
|
+
x: number;
|
|
2618
|
+
y: number;
|
|
2619
|
+
};
|
|
2620
|
+
/** Chrome-caps' answer for a chrome id; marks gated by one ask it. */
|
|
2621
|
+
isVisible(chromeId: string): boolean;
|
|
2622
|
+
/** The selected mark's index when this extension owns it, else null. */
|
|
2623
|
+
selected: number | null;
|
|
2624
|
+
}
|
|
2625
|
+
/** A grabbable point an extension adds to the open path. A press on it
|
|
2626
|
+
* routes as an affordance hit of kind `hitKind`. */
|
|
2627
|
+
interface PathEditPart {
|
|
2628
|
+
x: number;
|
|
2629
|
+
y: number;
|
|
2630
|
+
hitKind: string;
|
|
2631
|
+
/** Chrome-caps id it is hit-tested under, beside `path-edit.anchors`. */
|
|
2632
|
+
chromeId?: string;
|
|
2633
|
+
/** Hit radius in screen px; path edit's anchor radius when left out. */
|
|
2634
|
+
hitRadiusPx?: number;
|
|
2635
|
+
/** Pushes the part `px` screen pixels from (x, y) along the world-space
|
|
2636
|
+
* `normal`, so it keeps its distance at any zoom. */
|
|
2637
|
+
standoff?: {
|
|
2638
|
+
px: number;
|
|
2639
|
+
normal: {
|
|
2640
|
+
x: number;
|
|
2641
|
+
y: number;
|
|
2642
|
+
};
|
|
2643
|
+
};
|
|
2644
|
+
}
|
|
2645
|
+
type Point = {
|
|
2646
|
+
x: number;
|
|
2647
|
+
y: number;
|
|
2648
|
+
};
|
|
2649
|
+
/** An anchor or handle drag on the open path, as it starts. */
|
|
2650
|
+
interface PathEditDragStart extends Omit<PathEditTarget, 'node'> {
|
|
2651
|
+
/** The node's committed pose and data; null when it cannot be read. */
|
|
2652
|
+
node: PathEditTarget['node'] | null;
|
|
2653
|
+
/** What the press grabbed: an anchor, or one of its handles. */
|
|
2654
|
+
part: 'anchor' | 'controlIn' | 'controlOut';
|
|
2655
|
+
/** The pressed anchor, as a flat index. */
|
|
2656
|
+
anchorIndex: number;
|
|
2657
|
+
/** The anchors an anchor drag moves, as flat indices; empty for a handle
|
|
2658
|
+
* drag, or when Shift took the pressed anchor out of the selection. */
|
|
2659
|
+
dragging: readonly number[];
|
|
2660
|
+
/** The view's world-to-screen scale at the press, to measure in screen
|
|
2661
|
+
* pixels by; absent without a view. */
|
|
2662
|
+
scale?: {
|
|
2663
|
+
x: number;
|
|
2664
|
+
y: number;
|
|
2665
|
+
};
|
|
2666
|
+
/** The canvas's `snap` dep, to begin a session on; absent without one. */
|
|
2667
|
+
snap?: SnapDep;
|
|
2668
|
+
}
|
|
2669
|
+
/** A handle drag's move, as {@link PathEditDrag.handle} reads it. */
|
|
2670
|
+
interface PathEditHandleMove {
|
|
2671
|
+
/** The handle locks in force this move, modifiers included. */
|
|
2672
|
+
locks: HandleLocks;
|
|
2673
|
+
}
|
|
2674
|
+
/** One extension's share of a drag in flight. Every member is optional. */
|
|
2675
|
+
interface PathEditDrag {
|
|
2676
|
+
/**
|
|
2677
|
+
* For an anchor drag, anchors that follow it and the share of its delta
|
|
2678
|
+
* each moves by, keyed by flat index. Read every move. When any extension
|
|
2679
|
+
* gives one, the drag moves its dragged anchors in full and every anchor
|
|
2680
|
+
* named by the largest share given, and moves no symmetric images.
|
|
2681
|
+
*/
|
|
2682
|
+
weights?(): ReadonlyMap<number, number>;
|
|
2683
|
+
/** For a handle drag, where the handle goes, given `to`: where the pointer
|
|
2684
|
+
* and the locks in force put it. Extensions answer in turn, each from the
|
|
2685
|
+
* last one's answer. */
|
|
2686
|
+
handle?(to: Point, move: PathEditHandleMove): Point;
|
|
2687
|
+
/** A wheel turned while the drag is in flight. Return true to claim it;
|
|
2688
|
+
* the drag then redoes its last move. */
|
|
2689
|
+
wheel?(wheel: {
|
|
2690
|
+
deltaX: number;
|
|
2691
|
+
deltaY: number;
|
|
2692
|
+
deltaZ: number;
|
|
2693
|
+
}): boolean;
|
|
2694
|
+
/** Overlays to draw while the drag is in flight, for `current`, the path
|
|
2695
|
+
* as the drag has made it. */
|
|
2696
|
+
overlays?(current: AnchorSet): readonly OngoingOverlay[];
|
|
2697
|
+
/** The drag is over, committed or canceled. */
|
|
2698
|
+
end?(): void;
|
|
2699
|
+
}
|
|
2700
|
+
/** Another node an edit changes along with the edited one. */
|
|
2701
|
+
interface PathEditOther {
|
|
2702
|
+
id: string;
|
|
2703
|
+
/** Its new path, in world space, stored where the node keeps its own. */
|
|
2704
|
+
path?: PolygonPath;
|
|
2705
|
+
/** Data fields to set on it. */
|
|
2706
|
+
data?: Record<string, unknown>;
|
|
2707
|
+
/** Delete it: what it kept true no longer has anything to hold. */
|
|
2708
|
+
remove?: boolean;
|
|
2709
|
+
}
|
|
2710
|
+
/** What an edit commits once an extension has finished it. */
|
|
2711
|
+
interface FinishedPathEdit {
|
|
2712
|
+
path: PolygonPath;
|
|
2713
|
+
/** Data fields to set beside the path. */
|
|
2714
|
+
data?: Record<string, unknown>;
|
|
2715
|
+
/** Other nodes the edit changes, committed in the same history entry and previewed with it. */
|
|
2716
|
+
others?: readonly PathEditOther[];
|
|
2717
|
+
}
|
|
2718
|
+
/** The scene as {@link PathEditExtension.finishEdit} reads it, for an edit that reaches past one node. */
|
|
2719
|
+
interface PathEditFinishCtx {
|
|
2720
|
+
/** The edited node's id. */
|
|
2721
|
+
id: string;
|
|
2722
|
+
/** A node's committed pose, data and dependencies; null when there is none. */
|
|
2723
|
+
node(id: string): {
|
|
2724
|
+
pose: unknown;
|
|
2725
|
+
data: unknown;
|
|
2726
|
+
dependsOn?: readonly string[] | 'children';
|
|
2727
|
+
} | null;
|
|
2728
|
+
/** A node's committed editable path, in world space; null when it has none. */
|
|
2729
|
+
path(id: string): PolygonPath | null;
|
|
2730
|
+
/** The nodes that list `id` in their `dependsOn`, directly or through others. */
|
|
2731
|
+
dependents(id: string): readonly string[];
|
|
2732
|
+
}
|
|
2733
|
+
/** One feature's share of path edit. Every member is optional. */
|
|
2734
|
+
interface PathEditExtension {
|
|
2735
|
+
/** Names it as a {@link PathEditMark}'s owner. Unique per canvas. */
|
|
2736
|
+
readonly id: string;
|
|
2737
|
+
/** Draw commands for the open path, in screen space, under its anchor
|
|
2738
|
+
* markers. Called every frame the overlay paints. */
|
|
2739
|
+
marks?(ctx: PathEditMarksCtx): DrawCommand[];
|
|
2740
|
+
/** Grabbable points on the open path, pressed ahead of its segments and
|
|
2741
|
+
* behind its anchors. */
|
|
2742
|
+
parts?(target: PathEditTarget): readonly PathEditPart[];
|
|
2743
|
+
/** The index of this extension's mark a click at `screen` (in the
|
|
2744
|
+
* overlay's screen space) lands on, or -1. Asked when a click misses
|
|
2745
|
+
* every anchor. */
|
|
2746
|
+
markAt?(target: PathEditTarget, toScreen: PathEditMarksCtx['toScreen'], screen: {
|
|
2747
|
+
x: number;
|
|
2748
|
+
y: number;
|
|
2749
|
+
}): number;
|
|
2750
|
+
/** Remove mark `index` of the node `target` names, committing through
|
|
2751
|
+
* `store`. Delete in path edit calls it on the selected mark. */
|
|
2752
|
+
deleteMark?(target: PathEditTarget, index: number, store: PathEditStore): void;
|
|
2753
|
+
/** Its share of an anchor or handle drag starting on the open path, or
|
|
2754
|
+
* null to sit it out. Asked once, at the press. */
|
|
2755
|
+
drag?(start: PathEditDragStart): PathEditDrag | null;
|
|
2756
|
+
/**
|
|
2757
|
+
* `worldPath`, an edit of `node`'s committed path, finished so whatever
|
|
2758
|
+
* this extension keeps true holds — the path, and any data fields that
|
|
2759
|
+
* change with it, and any other nodes it has to move to keep it. Null when
|
|
2760
|
+
* it cannot hold, and the edit should then not happen. Runs on every commit
|
|
2761
|
+
* of an edit and every frame of one in flight. `ctx` reads the rest of the
|
|
2762
|
+
* scene; it is absent where an edit has no scene behind it.
|
|
2763
|
+
*/
|
|
2764
|
+
finishEdit?(node: {
|
|
2765
|
+
pose: unknown;
|
|
2766
|
+
data: unknown;
|
|
2767
|
+
}, worldPath: PolygonPath, origins?: readonly (PointOrigin | null)[], ctx?: PathEditFinishCtx): FinishedPathEdit | null;
|
|
2768
|
+
/** How path edit reads and writes the nodes whose `data.representation`
|
|
2769
|
+
* is of its kind. */
|
|
2770
|
+
representation?: PathRepresentation;
|
|
2771
|
+
}
|
|
2772
|
+
/** Commits a node's new path and data as one history entry, with no
|
|
2773
|
+
* extension finishing it. */
|
|
2774
|
+
type PathEditStore = (id: string, worldPath: PolygonPath, label: string, data?: Record<string, unknown>) => void;
|
|
2775
|
+
/**
|
|
2776
|
+
* Data fields that describe how a node's geometry was made, or name its
|
|
2777
|
+
* anchors, and so mean nothing once the geometry is replaced some other way.
|
|
2778
|
+
* A writer replacing a node's path drops them: a held warp, path
|
|
2779
|
+
* constraints, a skin, the form a path was drawn from.
|
|
2780
|
+
*/
|
|
2781
|
+
declare const GEOMETRY_BOUND_DATA: readonly string[];
|
|
2782
|
+
/** `data` without the fields in {@link GEOMETRY_BOUND_DATA}, other than `keep`. */
|
|
2783
|
+
declare function withoutGeometryBoundData<T>(data: T, keep?: readonly string[]): T;
|
|
2784
|
+
|
|
2785
|
+
/** An edit as {@link EditAnchorsDep.finishEdit} finishes it: the edited node's world path, and the other nodes' that move with it. */
|
|
2786
|
+
interface FinishedEditFrame {
|
|
2787
|
+
path: unknown;
|
|
2788
|
+
others: readonly {
|
|
2789
|
+
id: string;
|
|
2790
|
+
path: unknown;
|
|
2791
|
+
}[];
|
|
2792
|
+
}
|
|
2793
|
+
/**
|
|
2794
|
+
* Adapter dep for `editAnchorsAction`: narrow read/write access to the
|
|
2795
|
+
* editable polygon of a single node, so anchor-edit actions need not know
|
|
2796
|
+
* whether it lives directly on the node's pose (`pose.kind === 'polygon'`)
|
|
2797
|
+
* or on `node.data.path`.
|
|
2798
|
+
*
|
|
2799
|
+
* In-flight edit state is surfaced through the dispatcher's
|
|
2800
|
+
* `OngoingHandle.previewIds/previewPose/previewData` triple, not this dep.
|
|
2801
|
+
*/
|
|
2802
|
+
interface EditAnchorsDep {
|
|
2803
|
+
/** Id of the node currently being edited. Empty string means no node is
|
|
2804
|
+
* currently in edit mode — the chrome and gesture both opt out. */
|
|
2805
|
+
editingId: string;
|
|
2806
|
+
/** Enter/exit edit mode for a specific node. Pass `null` (or an empty
|
|
2807
|
+
* string) to exit. */
|
|
2808
|
+
setEditingId(id: string | null): void;
|
|
2809
|
+
/** Returns the COMMITTED editable polygon in world coordinates, or
|
|
2810
|
+
* null if this node has no editable polygon. For a node whose path was
|
|
2811
|
+
* drawn from a form a `PathRepresentation` reads, it is that form's edit
|
|
2812
|
+
* path, which `applyEdit` turns back into the drawn path. Does NOT consult in-
|
|
2813
|
+
* flight previews — callers that need live state read the dispatcher's
|
|
2814
|
+
* in-flight handles. */
|
|
2815
|
+
getEditablePath(id: string): unknown;
|
|
2816
|
+
/** The drawn geometry, in world coordinates, whose outline is a segment press, where it
|
|
2817
|
+
* differs from `getEditablePath`'s: a path drawn from a form. Absent, `getEditablePath`'s. */
|
|
2818
|
+
getOutlinePath?(id: string): unknown;
|
|
2819
|
+
/** Returns where the polygon is stored — `'pose'` when `node.pose`
|
|
2820
|
+
* IS the polygon, `'data'` when it lives on `node.data.path` with a
|
|
2821
|
+
* rect pose, or `null` when the node has no editable polygon. */
|
|
2822
|
+
getStorageKind(id: string): 'pose' | 'data' | null;
|
|
2823
|
+
/** Returns the node's raw `pose` and `data` so storage-aware actions
|
|
2824
|
+
* can capture origin state at gesture-start and synthesize a matching
|
|
2825
|
+
* `previewPose` / `previewData` during `onMove`. Returns null when the
|
|
2826
|
+
* node is gone. */
|
|
2827
|
+
getNodeShape(id: string): {
|
|
2828
|
+
pose: unknown;
|
|
2829
|
+
data: unknown;
|
|
2830
|
+
} | null;
|
|
2831
|
+
/** Commit `worldPath` as the new value for `id`, as one history entry
|
|
2832
|
+
* labeled `label`: a setPose when the pose IS the polygon, a batched
|
|
2833
|
+
* setPose+update when it lives on data.path. Given `origins` (from
|
|
2834
|
+
* `editAnchorSetTracked`), its per-anchor data (skin, vertex colors) is
|
|
2835
|
+
* renumbered in that entry. The edit is finished first (see `finishEdit`); one an extension cannot
|
|
2836
|
+
* finish commits nothing. */
|
|
2837
|
+
applyEdit(id: string, worldPath: unknown, label: string, origins?: readonly (PointOrigin | null)[]): void;
|
|
2838
|
+
/** The ops `applyEdit` would commit for the same arguments, unapplied, so
|
|
2839
|
+
* a caller can make the edit part of a larger batch — the pen joining
|
|
2840
|
+
* two paths edits one node and deletes the other in one undo step.
|
|
2841
|
+
* Optional; a caller that needs it declines the composite edit without
|
|
2842
|
+
* it. Returns `[]` when `id` has no editable polygon, or when an
|
|
2843
|
+
* extension cannot finish the edit. */
|
|
2844
|
+
editOps?(id: string, worldPath: unknown, label: string, origins?: readonly (PointOrigin | null)[]): Op[];
|
|
2845
|
+
/**
|
|
2846
|
+
* Anchors currently selected within the edited path, as **flat anchor
|
|
2847
|
+
* indices** — the same numbering `enumerateAnchors` produces and the
|
|
2848
|
+
* `anchor:N` affordance kinds carry.
|
|
2849
|
+
*
|
|
2850
|
+
* Selection is transient UI state, deliberately not part of the scene:
|
|
2851
|
+
* it is cleared whenever `editingId` changes, and any edit that
|
|
2852
|
+
* renumbers anchors (insert, delete) is responsible for leaving it
|
|
2853
|
+
* coherent. Empty means "no anchor selected" — the keyboard actions
|
|
2854
|
+
* (nudge, delete) no-op rather than acting on all anchors.
|
|
2855
|
+
*/
|
|
2856
|
+
selectedAnchors: ReadonlySet<number>;
|
|
2857
|
+
/** Replace the anchor selection. Pass an empty iterable to clear. */
|
|
2858
|
+
setSelectedAnchors(next: Iterable<number>): void;
|
|
2859
|
+
/** In-flight anchor-marquee rect in world coords, or null when no
|
|
2860
|
+
* marquee drag is active. */
|
|
2861
|
+
marquee: {
|
|
2862
|
+
x: number;
|
|
2863
|
+
y: number;
|
|
2864
|
+
width: number;
|
|
2865
|
+
height: number;
|
|
2866
|
+
} | null;
|
|
2867
|
+
/** Set or clear the in-flight marquee rect. */
|
|
2868
|
+
setMarquee(rect: {
|
|
2869
|
+
x: number;
|
|
2870
|
+
y: number;
|
|
2871
|
+
width: number;
|
|
2872
|
+
height: number;
|
|
2873
|
+
} | null): void;
|
|
2874
|
+
/** The path-edit tool in use, or null for plain anchor editing — one of a
|
|
2875
|
+
* set of named tools, such as `'simplifyBrush'`, that each change what a
|
|
2876
|
+
* plain drag in path edit does. Always null with no path open. */
|
|
2877
|
+
tool: string | null;
|
|
2878
|
+
/** Switch path-edit tool, or pass null for plain anchor editing. */
|
|
2879
|
+
setTool(id: string | null): void;
|
|
2880
|
+
/** The handle locks held for every handle drag, on top of the modifiers —
|
|
2881
|
+
* what the `handleLock.angle` and `handleLock.length` toggles set. Absent,
|
|
2882
|
+
* the drag holds what its `handleLock` param names. Unlike the anchor
|
|
2883
|
+
* selection, they outlast a change of edited path. */
|
|
2884
|
+
handleLocks?: HandleLocks;
|
|
2885
|
+
/** Replace the held handle locks. Absent, the toggles are unavailable. */
|
|
2886
|
+
setHandleLocks?(next: HandleLocks): void;
|
|
2887
|
+
/**
|
|
2888
|
+
* `worldPath`, an edit of `id`'s committed path, finished by every
|
|
2889
|
+
* extension's `finishEdit` in turn — path constraints made to hold, say —
|
|
2890
|
+
* with the paths of any other nodes that move with it. Null when one cannot
|
|
2891
|
+
* finish it, and the edit should then not happen. `applyEdit` and `editOps`
|
|
2892
|
+
* run it themselves; an ongoing edit calls it each frame so its preview is
|
|
2893
|
+
* what they will commit. Optional: absent, edits stand as they are.
|
|
2894
|
+
*/
|
|
2895
|
+
finishEdit?(id: string, worldPath: unknown, origins?: readonly (PointOrigin | null)[]): FinishedEditFrame | null;
|
|
2896
|
+
/**
|
|
2897
|
+
* Commit `worldPath` for `id` with `data` laid over its data, as one
|
|
2898
|
+
* history entry, finished by no extension: what an extension writing its
|
|
2899
|
+
* own data with a path it already solved commits through. Optional.
|
|
2900
|
+
*/
|
|
2901
|
+
store?: PathEditStore;
|
|
2902
|
+
/** The canvas's path-edit extensions, in order. */
|
|
2903
|
+
extensions?: readonly PathEditExtension[];
|
|
2904
|
+
/**
|
|
2905
|
+
* The extension mark selected in place of anchors, or null. Selecting one
|
|
2906
|
+
* clears the anchor selection and selecting anchors clears it, so Delete
|
|
2907
|
+
* acts on one or the other. Optional.
|
|
2908
|
+
*/
|
|
2909
|
+
selectedMark?: PathEditMark | null;
|
|
2910
|
+
/** Select an extension's mark, or pass null to clear. */
|
|
2911
|
+
setSelectedMark?(mark: PathEditMark | null): void;
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
/** Context handed to every content handler for one ingest event. */
|
|
2915
|
+
interface IngestCtx {
|
|
2916
|
+
/** World-space arrival point (drop / pointed imperative ingest); `null`
|
|
2917
|
+
* for paste and point-less calls — handlers pick their own policy
|
|
2918
|
+
* (the kit image handler centers on the viewport). */
|
|
2919
|
+
point: {
|
|
2920
|
+
x: number;
|
|
2921
|
+
y: number;
|
|
2922
|
+
} | null;
|
|
2923
|
+
/** Visible canvas area in world coordinates. */
|
|
2924
|
+
viewportWorldRect(): {
|
|
2925
|
+
x: number;
|
|
2926
|
+
y: number;
|
|
2927
|
+
width: number;
|
|
2928
|
+
height: number;
|
|
2929
|
+
};
|
|
2930
|
+
/** The kit insert dep — id/layer/undoable-op supplied; the canonical way
|
|
2931
|
+
* for a handler to mint a node (`insert.commit(bounds, { kind, ... })`). */
|
|
2932
|
+
insert: InsertDep;
|
|
2933
|
+
/** Raw op commit for handlers that build their own ops. */
|
|
2934
|
+
applyOps(ops: Op[], label?: string): void;
|
|
2935
|
+
scene: Scene<unknown, string, unknown>;
|
|
2936
|
+
selection: SelectionApi;
|
|
2937
|
+
/** Consumer file→src resolver (SceneCanvas `ingestion.resolveSrc`).
|
|
2938
|
+
* When absent, the kit image handler embeds as a `data:` URI. */
|
|
2939
|
+
resolveSrc?: (file: File) => Promise<string>;
|
|
2940
|
+
/** Kit SVG-handler options (SceneCanvas `ingestion.svg`) — e.g.
|
|
2941
|
+
* `{ unpack: unpackSvgFiles }` (from `@weasel-js/svg`) to parse SVG files
|
|
2942
|
+
* into scene nodes. */
|
|
2943
|
+
svg?: SvgIngestOptions;
|
|
2944
|
+
/** Clipboard-paste seam — present when the hosting `SceneCanvas` supplied
|
|
2945
|
+
* an adapter with `commitPaste`. `reviver` comes from
|
|
2946
|
+
* `SceneCanvasProps.ingestion.clipboard`. Absent ⇒ the kit weasel-JSON
|
|
2947
|
+
* handler declines inert (dwarn, nothing ingested) — its matched items
|
|
2948
|
+
* were already consumed at match time, so they do NOT fall through;
|
|
2949
|
+
* only match-level misses flow on to other handlers. */
|
|
2950
|
+
clipboard?: ClipboardIngestCtx;
|
|
2951
|
+
/** Set to `true` by the kit weasel-JSON handler when it successfully
|
|
2952
|
+
* pastes a payload in this event. `kit:svg`'s `text/plain` SVG fallback
|
|
2953
|
+
* reads this to decline the SVG flavor of a copy whose weasel-JSON flavor
|
|
2954
|
+
* already ingested (avoids a double-paste when both flavors ride one
|
|
2955
|
+
* clipboard event). */
|
|
2956
|
+
consumedWeaselPayload?: boolean;
|
|
2957
|
+
/** Full action-deps bag, for consumer handlers that need more. */
|
|
2958
|
+
deps: ActionDeps;
|
|
2959
|
+
}
|
|
2960
|
+
/** A handler for content arriving by paste, drop or file picker. Handlers are
|
|
2961
|
+
* matched by MIME glob or predicate and run highest-priority first; the kit's
|
|
2962
|
+
* own register at a low priority so a consumer's handler wins by default. */
|
|
2963
|
+
interface ContentHandlerEntry {
|
|
2964
|
+
/** Stable identifier — used for unregistration and debugging
|
|
2965
|
+
* (`'kit:image'`, `'app:csv'`). */
|
|
2966
|
+
id: string;
|
|
2967
|
+
/** MIME glob(s) (`'image/*'`, `'text/csv'`) or an item predicate. */
|
|
2968
|
+
match: string | string[] | ((item: IngestItem) => boolean);
|
|
2969
|
+
/** For a predicate `match`: the MIME globs it could say yes to. A drag
|
|
2970
|
+
* still in flight shows its MIMEs and no contents, so a predicate cannot be
|
|
2971
|
+
* asked about it; this is what it is asked instead. Without it, no drag
|
|
2972
|
+
* can be refused while this handler is registered. */
|
|
2973
|
+
types?: readonly string[];
|
|
2974
|
+
/** Higher runs earlier. Kit defaults register at -100 so any consumer
|
|
2975
|
+
* handler (default 0) beats them. */
|
|
2976
|
+
priority?: number;
|
|
2977
|
+
handle(items: IngestItem[], ctx: IngestCtx): void | Promise<void>;
|
|
2978
|
+
}
|
|
2979
|
+
/** Register a content handler. Returns a disposer that removes it. */
|
|
2980
|
+
declare function registerContentHandler(entry: ContentHandlerEntry): () => void;
|
|
2981
|
+
|
|
2982
|
+
/**
|
|
2983
|
+
* Options for the kit `image/svg+xml` content handler, threaded from
|
|
2984
|
+
* SceneCanvas's `ingestion={{ svg }}` prop.
|
|
2985
|
+
*/
|
|
2986
|
+
interface SvgIngestOptions {
|
|
2987
|
+
/** Parse dropped/pasted/picked SVG files into native scene nodes (path /
|
|
2988
|
+
* text leaves under containers mirroring the source `<g>` structure)
|
|
2989
|
+
* instead of the default single embedded-image node.
|
|
2990
|
+
*
|
|
2991
|
+
* Pass `unpackSvgFiles` from `@weasel-js/svg`:
|
|
2992
|
+
*
|
|
2993
|
+
* ```ts
|
|
2994
|
+
* import { unpackSvgFiles } from '@weasel-js/svg';
|
|
2995
|
+
* <SceneCanvas ingestion={{ svg: { unpack: unpackSvgFiles } }} />
|
|
2996
|
+
* ```
|
|
2997
|
+
*
|
|
2998
|
+
* It is injected rather than flagged on with `true` because the SVG parser
|
|
2999
|
+
* lives in `@weasel-js/svg`, which depends on this package. */
|
|
3000
|
+
unpack?: SvgUnpacker;
|
|
3001
|
+
}
|
|
3002
|
+
/** Parses SVG files and inserts the resulting nodes into `ctx.scene`, as one
|
|
3003
|
+
* `applyOps` batch per file. Implemented by `unpackSvgFiles` in
|
|
3004
|
+
* `@weasel-js/svg`; see {@link SvgIngestOptions.unpack}. */
|
|
3005
|
+
type SvgUnpacker = (files: File[], ctx: IngestCtx) => Promise<void>;
|
|
3006
|
+
/**
|
|
3007
|
+
* Clipboard-paste seam consumed by the kit weasel-JSON content handler
|
|
3008
|
+
* (`IngestCtx.clipboard`). Built by `<SceneCanvas>` from its own synthesized
|
|
3009
|
+
* adapter + the `ingestion.clipboard` prop; absent when the consumer set
|
|
3010
|
+
* `ingestion.clipboard.enabled === false` or the adapter lacks `commitPaste`.
|
|
3011
|
+
* Absence makes the handler decline inert (dwarn, nothing ingested) — its
|
|
3012
|
+
* matched items were already consumed at match time and do not fall through
|
|
3013
|
+
* to other handlers.
|
|
3014
|
+
*/
|
|
3015
|
+
interface ClipboardIngestCtx {
|
|
3016
|
+
/** The hosting canvas's adapter — `commitPaste` materializes the pasted
|
|
3017
|
+
* nodes (fresh ids, offset applied); insertion still goes through ops. */
|
|
3018
|
+
adapter: InsertAdapter<{
|
|
3019
|
+
id: string;
|
|
3020
|
+
}>;
|
|
3021
|
+
/** JSON reviver for the weasel wire payload (typed arrays etc.) — from
|
|
3022
|
+
* `SceneCanvasProps.ingestion.clipboard.reviver`. */
|
|
3023
|
+
reviver?: (key: string, value: unknown) => unknown;
|
|
3024
|
+
/** Told what a paste left out and why — from
|
|
3025
|
+
* `SceneCanvasProps.ingestion.clipboard.onOmitted`. */
|
|
3026
|
+
onOmitted?: (omitted: PasteOmission[]) => void;
|
|
3027
|
+
}
|
|
3028
|
+
/** Dep for the `ingest` action (external-content ingestion). */
|
|
3029
|
+
interface IngestionDep {
|
|
3030
|
+
/** Visible canvas area in world coordinates. */
|
|
3031
|
+
viewportWorldRect(): {
|
|
3032
|
+
x: number;
|
|
3033
|
+
y: number;
|
|
3034
|
+
width: number;
|
|
3035
|
+
height: number;
|
|
3036
|
+
};
|
|
3037
|
+
/** Consumer file→src resolver (from SceneCanvas's `ingestion` prop).
|
|
3038
|
+
* Live accessor — read it at use time. Destructuring (or copying the
|
|
3039
|
+
* property early) snapshots the current value and won't track later
|
|
3040
|
+
* prop changes across an `await`. */
|
|
3041
|
+
resolveSrc?: (file: File) => Promise<string>;
|
|
3042
|
+
/** Kit SVG-handler options (from SceneCanvas's `ingestion` prop).
|
|
3043
|
+
* Live accessor, same caveat as `resolveSrc`. */
|
|
3044
|
+
svg?: SvgIngestOptions;
|
|
3045
|
+
/** Clipboard-paste seam for the kit weasel-JSON handler.
|
|
3046
|
+
* Live accessor, same caveat as `resolveSrc`. */
|
|
3047
|
+
clipboard?: ClipboardIngestCtx;
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
/** The gesture an insert's bounds came from, in the same coordinates: `bounds`
|
|
3051
|
+
* is the box `start` and `end` span, or with `fromCenter`, the box centered
|
|
3052
|
+
* on `start` reaching `end`. A host whose bounds lose information on the
|
|
3053
|
+
* way, a 3D one casting them onto a plane, reads the ends instead. */
|
|
3054
|
+
interface InsertEnds {
|
|
3055
|
+
start: {
|
|
3056
|
+
x: number;
|
|
3057
|
+
y: number;
|
|
3058
|
+
};
|
|
3059
|
+
end: {
|
|
3060
|
+
x: number;
|
|
3061
|
+
y: number;
|
|
3062
|
+
};
|
|
3063
|
+
fromCenter?: boolean;
|
|
3064
|
+
}
|
|
3065
|
+
/** Adapter dep for `insertAction`. The `extras` carry the active tool's kind
|
|
3066
|
+
* + per-kind geometry. */
|
|
3067
|
+
interface InsertDep {
|
|
3068
|
+
/**
|
|
3069
|
+
* Materialise a new node from the given drag-rect bounds and typed
|
|
3070
|
+
* per-kind extras. Returns the new node's id, or `null` if the consumer
|
|
3071
|
+
* rejected the insert (e.g. sub-threshold bounds, unknown kind).
|
|
3072
|
+
*/
|
|
3073
|
+
commit(bounds: {
|
|
3074
|
+
x: number;
|
|
3075
|
+
y: number;
|
|
3076
|
+
width: number;
|
|
3077
|
+
height: number;
|
|
3078
|
+
}, extras: InsertExtras,
|
|
3079
|
+
/** Absent when no gesture made the bounds: a path the pen or spiro
|
|
3080
|
+
* drew, or content a paste ingests. A click-place reads as a drag out
|
|
3081
|
+
* from its center. */
|
|
3082
|
+
ends?: InsertEnds): NodeId | null;
|
|
3083
|
+
/**
|
|
3084
|
+
* What `commit` would apply, unapplied: the new node's id and the ops that
|
|
3085
|
+
* insert it, for a caller that has more to put in the same undo step. The
|
|
3086
|
+
* pen joins two paths this way. Without it such a caller declines.
|
|
3087
|
+
*/
|
|
3088
|
+
build?(bounds: {
|
|
3089
|
+
x: number;
|
|
3090
|
+
y: number;
|
|
3091
|
+
width: number;
|
|
3092
|
+
height: number;
|
|
3093
|
+
}, extras: InsertExtras, ends?: InsertEnds): {
|
|
3094
|
+
id: NodeId;
|
|
3095
|
+
ops: Op[];
|
|
3096
|
+
} | null;
|
|
3097
|
+
/** The scene layer `commit` puts the node on. An insert on a layer carrying
|
|
3098
|
+
* `parallax` is dragged out in that plane's world, so `bounds` arrive
|
|
3099
|
+
* there too. Omitted: the camera's world. */
|
|
3100
|
+
layer?(): string;
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* What `editAnchorsAction` keeps a path symmetric under. Asked once at the
|
|
3104
|
+
* press, with the id of the path being edited; answer every transform of the
|
|
3105
|
+
* symmetry group except the identity, in world coordinates. Of those, the
|
|
3106
|
+
* ones the path is already its own image under are held through the drag:
|
|
3107
|
+
* each image of a dragged anchor or handle follows it, and one a transform
|
|
3108
|
+
* fixes stays where that transform allows.
|
|
3109
|
+
*/
|
|
3110
|
+
interface PathSymmetryDep {
|
|
3111
|
+
transforms(id: string): readonly Affine[];
|
|
3112
|
+
}
|
|
3113
|
+
/** Where the `insert` dep puts what it makes. Read at each insert. A node
|
|
3114
|
+
* goes onto the container's layer, with its pose made local to it when the
|
|
3115
|
+
* scene composes frames; an id naming no container is the same as `null`. */
|
|
3116
|
+
interface InsertIntoDep {
|
|
3117
|
+
get(): string | null;
|
|
3118
|
+
}
|
|
3119
|
+
/** Holder for the insert gesture in flight in one input scope. `gesture` is
|
|
3120
|
+
* `insertAction`'s own state, opaque to everything else, and `null` between
|
|
3121
|
+
* gestures. A source must return the same object on every read. */
|
|
3122
|
+
interface InsertLive {
|
|
3123
|
+
gesture: unknown;
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
/**
|
|
3127
|
+
* The deps behind text editing, the clipboard, and Slice.
|
|
3128
|
+
*/
|
|
3129
|
+
|
|
3130
|
+
/**
|
|
3131
|
+
* Dep for `enterTextEditAction`.
|
|
3132
|
+
*
|
|
3133
|
+
* Wrap the return value of `useTextEdit` / `useSceneTextEdit` to source this
|
|
3134
|
+
* dep. The `isTextNode` predicate is optional — when absent the action fires
|
|
3135
|
+
* unconditionally (the binding spec acts as the gate).
|
|
3136
|
+
*
|
|
3137
|
+
* @example
|
|
3138
|
+
* ```ts
|
|
3139
|
+
* const textEdit = useSceneTextEdit(scene, container);
|
|
3140
|
+
* useDepSource('textEdit', () => ({
|
|
3141
|
+
* startEdit: textEdit.startEdit,
|
|
3142
|
+
* isTextNode: textEdit.isTextNode,
|
|
3143
|
+
* }));
|
|
3144
|
+
* ```
|
|
3145
|
+
*/
|
|
3146
|
+
interface TextEditDep {
|
|
3147
|
+
/** Begin editing the node with `id`. */
|
|
3148
|
+
startEdit(id: string, opts?: {
|
|
3149
|
+
caret?: number | 'all';
|
|
3150
|
+
}): void;
|
|
3151
|
+
/**
|
|
3152
|
+
* Optional predicate: returns `true` when the node with `id` is a text node.
|
|
3153
|
+
* When absent the action fires on any selected node (binding spec is the gate).
|
|
3154
|
+
* When present and returning `false`, the invocation is a no-op.
|
|
3155
|
+
*/
|
|
3156
|
+
isTextNode?(id: string): boolean;
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Clipboard dep — the imperative surface `useClipboardOps` returns.
|
|
3160
|
+
*
|
|
3161
|
+
* Consumers publish their live clipboard through `useDepSource('clipboard',
|
|
3162
|
+
* …)` from inside the `<DepRegistryProvider>` (i.e. under `<SceneCanvas>`).
|
|
3163
|
+
* The kit deliberately does not build one for them: `useClipboardOps` needs
|
|
3164
|
+
* an adapter and a selection reader that only the consumer can supply.
|
|
3165
|
+
*/
|
|
3166
|
+
interface ClipboardDep {
|
|
3167
|
+
copy(): void;
|
|
3168
|
+
paste(at?: {
|
|
3169
|
+
worldX: number;
|
|
3170
|
+
worldY: number;
|
|
3171
|
+
}): void;
|
|
3172
|
+
isEmpty(): boolean;
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* The commit behind the Slice action. `commit` receives the cut as a polyline
|
|
3176
|
+
* of at least two points (world coords): the drag's two ends for a straight
|
|
3177
|
+
* cut, its whole trail for a freehand one, the placed points for a
|
|
3178
|
+
* click-by-click one, whose last point equals its first when it closes into
|
|
3179
|
+
* a loop. `<SceneCanvas>` publishes one over its scene (`useSliceDepSource`);
|
|
3180
|
+
* a consumer replaces it with `useSliceDep`.
|
|
3181
|
+
*/
|
|
3182
|
+
interface SliceDep {
|
|
3183
|
+
commit(cut: ReadonlyArray<Point2>): void;
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
/** Minimal view API the action layer consumes. */
|
|
3187
|
+
interface ViewApi {
|
|
3188
|
+
get(): View;
|
|
3189
|
+
set(v: View): void;
|
|
3190
|
+
/** How this camera's world maps into the world the invocation edits in,
|
|
3191
|
+
* when that is a parallax plane — set by `inPlane` on the view it hands a
|
|
3192
|
+
* wrapped action. Absent or null: the camera's own world. */
|
|
3193
|
+
plane?(): PlaneMap | null;
|
|
3194
|
+
/** How the world the invocation edits in maps into the world `layer`'s
|
|
3195
|
+
* nodes are stored in, read now — set by `inPlane` alongside `plane`.
|
|
3196
|
+
* Absent or null: the same world. */
|
|
3197
|
+
planeOf?(layer: string): PlaneMap | null;
|
|
3198
|
+
/** Optional recenter callback. When wired, `viewportZoomAction`'s `reset`
|
|
3199
|
+
* branch (Cmd-0) calls this instead of resetting to identity. Return the
|
|
3200
|
+
* target `View` to let the action animate there; return nothing to keep
|
|
3201
|
+
* dispatching the view yourself. */
|
|
3202
|
+
recenter?(): View | void;
|
|
3203
|
+
/** Optional canvas-local host dimensions (CSS px). When wired,
|
|
3204
|
+
* `viewportZoomAction`'s keyboard branches (Cmd+= / Cmd+-) anchor at the
|
|
3205
|
+
* host center instead of the top-left origin. Null when the host isn't
|
|
3206
|
+
* measurable (unmounted). */
|
|
3207
|
+
hostSize?(): {
|
|
3208
|
+
width: number;
|
|
3209
|
+
height: number;
|
|
3210
|
+
} | null;
|
|
3211
|
+
/** Optional camera animation. `<SceneCanvas>` wires these three; a consumer
|
|
3212
|
+
* publishing their own `view` dep need not, and actions fall back to `set`. */
|
|
3213
|
+
animate?(to: View, opts?: ViewAnimationOptions): void;
|
|
3214
|
+
stopAnimation?(): void;
|
|
3215
|
+
/** Where an in-flight camera animation is heading, or null. Compute the next
|
|
3216
|
+
* discrete step from this so repeated presses compound. */
|
|
3217
|
+
animationTarget?(): View | null;
|
|
3218
|
+
/** Optional momentum decay. `<SceneCanvas>` wires this from `useDecayLoop`;
|
|
3219
|
+
* a consumer publishing their own `view` dep need not, and `viewport.dragPan`
|
|
3220
|
+
* simply lands the pan without coasting. */
|
|
3221
|
+
decay?(config: DecayLoopConfig): void;
|
|
3222
|
+
stopDecay?(): void;
|
|
3223
|
+
/** Whether a scene layer reaches the screen in this view — its own
|
|
3224
|
+
* `layerVisibility` / `layerOrder`, on top of the scene's `visible` flag.
|
|
3225
|
+
* Absent: this view paints every layer the scene shows. Selecting actions
|
|
3226
|
+
* pass over what the asking view does not paint. */
|
|
3227
|
+
layerIsPainted?(layerId: string): boolean;
|
|
3228
|
+
}
|
|
3229
|
+
/** The part of the asking view a region hit-test consults. `get` is its
|
|
3230
|
+
* camera, which a parallax layer is picked through. */
|
|
3231
|
+
type HitTestView = RegionPickView;
|
|
3232
|
+
/**
|
|
3233
|
+
* Topmost-node-at-world-point dep, for any action that needs a single-best
|
|
3234
|
+
* pick. The dep walks hits front-to-back and returns the first id not in
|
|
3235
|
+
* `exclude`. Pass moving-node roots + their descendants when the caller
|
|
3236
|
+
* wants to ignore the nodes it's manipulating.
|
|
3237
|
+
*/
|
|
3238
|
+
type NodeAtPointDep = (point: {
|
|
3239
|
+
x: number;
|
|
3240
|
+
y: number;
|
|
3241
|
+
}, exclude?: Iterable<NodeId>) => NodeId | null;
|
|
3242
|
+
/** What an area-selecting action needs: a way to ask what a region covers,
|
|
3243
|
+
* and a way to read and replace the selection. */
|
|
3244
|
+
interface AreaSelectDep {
|
|
3245
|
+
/** Return ids of all scene nodes whose AABB overlaps `bounds`, skipping any
|
|
3246
|
+
* on a layer `view` — the view the gesture ran in — does not paint. */
|
|
3247
|
+
hitTestArea(bounds: {
|
|
3248
|
+
x: number;
|
|
3249
|
+
y: number;
|
|
3250
|
+
width: number;
|
|
3251
|
+
height: number;
|
|
3252
|
+
}, view?: HitTestView): NodeId[];
|
|
3253
|
+
/** Return the current selection id list. */
|
|
3254
|
+
getSelection(): NodeId[];
|
|
3255
|
+
/** Replace the current selection. */
|
|
3256
|
+
setSelection(ids: NodeId[]): void;
|
|
3257
|
+
}
|
|
3258
|
+
/**
|
|
3259
|
+
* Adapter dep for `lassoSelectAction`: polygon-lasso hit-testing +
|
|
3260
|
+
* selection read/write.
|
|
3261
|
+
*/
|
|
3262
|
+
interface LassoSelectDep {
|
|
3263
|
+
/**
|
|
3264
|
+
* Hit-test against a closed polygon (vertex order CW or CCW; last→first
|
|
3265
|
+
* closing edge is implicit). Returns matching node ids.
|
|
3266
|
+
* Optional — when absent, `lassoSelectAction` falls back to AABB via
|
|
3267
|
+
* `hitTestArea`.
|
|
3268
|
+
*/
|
|
3269
|
+
hitTestLasso?(polygon: ReadonlyArray<{
|
|
3270
|
+
x: number;
|
|
3271
|
+
y: number;
|
|
3272
|
+
}>, mode: 'centers' | 'intersect' | 'enclosed', view?: HitTestView): string[];
|
|
3273
|
+
/** Return ids of nodes whose AABB overlaps the given rect (fallback). */
|
|
3274
|
+
hitTestArea(bounds: {
|
|
3275
|
+
x: number;
|
|
3276
|
+
y: number;
|
|
3277
|
+
width: number;
|
|
3278
|
+
height: number;
|
|
3279
|
+
}, view?: HitTestView): string[];
|
|
3280
|
+
/** Return the current selection id list. */
|
|
3281
|
+
getSelection(): string[];
|
|
3282
|
+
/** Replace the current selection. */
|
|
3283
|
+
setSelection(ids: string[]): void;
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
/**
|
|
3287
|
+
* Per-kind extra geometry passed to `InsertDep.commit`.
|
|
3288
|
+
*
|
|
3289
|
+
* Built-in tools populate a typed variant so the kit's default factory can
|
|
3290
|
+
* render the true tool params (line endpoints, polygon side count, star
|
|
3291
|
+
* geometry, pencil sample list). Consumer-defined tools may pass any
|
|
3292
|
+
* `{ kind: string; ... }` payload; the kit's factory falls back to AABB
|
|
3293
|
+
* inscription for unknown kinds.
|
|
3294
|
+
*
|
|
3295
|
+
* `bounds` is still passed alongside as a useful AABB pose hint — factories
|
|
3296
|
+
* may use it as the node's pose even when richer geometry is available. Any may carry a `minSize`
|
|
3297
|
+
* (`{ width, height }`), which the kit's factories keep as `data.minSize` so a resize holds to it.
|
|
3298
|
+
*/
|
|
3299
|
+
type InsertExtras = {
|
|
3300
|
+
kind: 'rect';
|
|
3301
|
+
} | {
|
|
3302
|
+
kind: 'ellipse';
|
|
3303
|
+
} | {
|
|
3304
|
+
kind: 'line';
|
|
3305
|
+
a: {
|
|
3306
|
+
x: number;
|
|
3307
|
+
y: number;
|
|
3308
|
+
};
|
|
3309
|
+
b: {
|
|
3310
|
+
x: number;
|
|
3311
|
+
y: number;
|
|
3312
|
+
};
|
|
3313
|
+
} | {
|
|
3314
|
+
kind: 'polygon';
|
|
3315
|
+
sides: number;
|
|
3316
|
+
rotation: number;
|
|
3317
|
+
center?: {
|
|
3318
|
+
x: number;
|
|
3319
|
+
y: number;
|
|
3320
|
+
};
|
|
3321
|
+
radius?: number;
|
|
3322
|
+
} | {
|
|
3323
|
+
kind: 'star';
|
|
3324
|
+
points: number;
|
|
3325
|
+
innerRadiusRatio: number;
|
|
3326
|
+
rotation: number;
|
|
3327
|
+
center?: {
|
|
3328
|
+
x: number;
|
|
3329
|
+
y: number;
|
|
3330
|
+
};
|
|
3331
|
+
outerRadius?: number;
|
|
3332
|
+
} | {
|
|
3333
|
+
kind: 'pencil';
|
|
3334
|
+
samples: ReadonlyArray<DragSample>;
|
|
3335
|
+
} | {
|
|
3336
|
+
kind: 'text';
|
|
3337
|
+
text?: string;
|
|
3338
|
+
}
|
|
3339
|
+
/** A sticky note: a text node with a background, in the look its tool names. */
|
|
3340
|
+
| ({
|
|
3341
|
+
kind: 'sticky';
|
|
3342
|
+
text?: string;
|
|
3343
|
+
} & StickyStyle)
|
|
3344
|
+
/** A finished path in world coords, as the pen tool commits one. `bounds`
|
|
3345
|
+
* is its AABB. An open path takes no fill. `data` is laid under the path
|
|
3346
|
+
* and paint on the node's data: the form the path was drawn from
|
|
3347
|
+
* (`data.representation`), say. */
|
|
3348
|
+
| {
|
|
3349
|
+
kind: 'path';
|
|
3350
|
+
path: _weasel_js_geom.PolygonPath;
|
|
3351
|
+
closed: boolean;
|
|
3352
|
+
data?: Readonly<Record<string, unknown>>;
|
|
3353
|
+
} | {
|
|
3354
|
+
kind: 'image';
|
|
3355
|
+
src?: string;
|
|
3356
|
+
opacity?: number;
|
|
3357
|
+
/** Chrome-only: what the in-flight drag paints. Read by the overlay
|
|
3358
|
+
* layer, ignored by the insert dep. */
|
|
3359
|
+
preview?: 'bitmap' | 'outline';
|
|
3360
|
+
} | {
|
|
3361
|
+
kind: string;
|
|
3362
|
+
[extra: string]: unknown;
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* Adapter dep for `resizeAction`: bounds-frame behaviors (e.g.
|
|
3367
|
+
* `clampMinSize`) and group-expansion (`expandIds`). Snapping is the `snap`
|
|
3368
|
+
* dep's.
|
|
3369
|
+
*
|
|
3370
|
+
* The generic is erased to `unknown` at the schema entry; consumers cast at
|
|
3371
|
+
* the call site.
|
|
3372
|
+
*/
|
|
3373
|
+
interface ResizePolicy<TPose> extends GestureLifecycleOptions {
|
|
3374
|
+
/** Bounds-frame constraints. Constrained to `TPose extends Bounds` since
|
|
3375
|
+
* constraints read/write `{x,y,width,height}`. For non-rect TPose pass `[]`. */
|
|
3376
|
+
constraints: TPose extends FramedBox ? BoundsConstraint<TPose>[] : never[];
|
|
3377
|
+
/** Group-expansion at gesture start. Identity (`ids => ids`) when group
|
|
3378
|
+
* resize isn't wanted. */
|
|
3379
|
+
expandIds: (ids: string[]) => string[];
|
|
3380
|
+
}
|
|
3381
|
+
/**
|
|
3382
|
+
* Layout-strategy lookup by container id, consumed by `moveAction` to run
|
|
3383
|
+
* the drag-time reflow pass. Sourced by `<SceneCanvas>` from the layout each
|
|
3384
|
+
* container declares on its scene node. `getLayout` returns null for a
|
|
3385
|
+
* container that declares none, so the reflow pass is a no-op then.
|
|
3386
|
+
*/
|
|
3387
|
+
interface LayoutDep {
|
|
3388
|
+
getLayout(containerId: string): LayoutStrategy<unknown> | null;
|
|
3389
|
+
/** Which container wins when several contain the drop point. Default
|
|
3390
|
+
* `'innermost'`. */
|
|
3391
|
+
dropTarget?: LayoutDropTargetMode;
|
|
3392
|
+
/** Carries displaced siblings to their slots over time. Absent, they snap. */
|
|
3393
|
+
reflow?: ReflowTransition<unknown> | null;
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3396
|
+
/**
|
|
3397
|
+
* The names an action may declare in `requires`, and what each resolves to.
|
|
3398
|
+
*
|
|
3399
|
+
* This is the whole vocabulary of things an action can reach — selection,
|
|
3400
|
+
* scene, view, history, and the rest. The interface is declared in
|
|
3401
|
+
* `@weasel-js/routing`, which knows that an action names its dependencies but
|
|
3402
|
+
* owns only `activeTool` among them; these entries are the kit's, merged in from
|
|
3403
|
+
* outside exactly the way a consumer merges its own
|
|
3404
|
+
* (`declare module '@weasel-js/core'`).
|
|
3405
|
+
*/
|
|
3406
|
+
declare module '@weasel-js/routing' {
|
|
3407
|
+
interface DepSchema {
|
|
3408
|
+
/** Kit selection state — ids of currently selected nodes. */
|
|
3409
|
+
selection: SelectionApi;
|
|
3410
|
+
/** Current viewport — camera position + scale. */
|
|
3411
|
+
view: ViewApi;
|
|
3412
|
+
/**
|
|
3413
|
+
* Scene tree — structural reads + undoable mutations.
|
|
3414
|
+
*
|
|
3415
|
+
* The entry uses the fully-erased form `Scene<unknown, string, unknown>`
|
|
3416
|
+
* because `DepSchema` must be concrete; any `Scene<MyData, MyLayer,
|
|
3417
|
+
* MyPose>` is assignable to it. Actions that need a typed scene back
|
|
3418
|
+
* should cast: `deps.scene as Scene<MyData, MyLayer, MyPose>`.
|
|
3419
|
+
*/
|
|
3420
|
+
scene: Scene<unknown, string, unknown>;
|
|
3421
|
+
/** Undo/redo history bound to the current scene. */
|
|
3422
|
+
history: History;
|
|
3423
|
+
/** Area-select dep — AABB hit-test + selection read/write. Override
|
|
3424
|
+
* per-consumer for custom hit-testing (e.g. contain-mode). */
|
|
3425
|
+
areaSelect: AreaSelectDep;
|
|
3426
|
+
/** Topmost node at a world-space point. Optional: actions that read this
|
|
3427
|
+
* (e.g. `moveAction` reparent-on-drop) fall back to a no-op when the dep
|
|
3428
|
+
* isn't registered. */
|
|
3429
|
+
nodeAtPoint?: NodeAtPointDep;
|
|
3430
|
+
/** Insert dep — node factory for drag-to-insert. Override per-consumer to
|
|
3431
|
+
* provide a typed node factory (e.g. with custom data payloads). */
|
|
3432
|
+
insert: InsertDep;
|
|
3433
|
+
/** Where `insertAction` keeps its gesture in flight, so
|
|
3434
|
+
* `insert.adjustRotation` reaches the one in its own input scope.
|
|
3435
|
+
* Sourced by `<SceneCanvas>`; without it the rotation does nothing. */
|
|
3436
|
+
insertLive?: InsertLive;
|
|
3437
|
+
/** The params an action starts with in this scope when its binding
|
|
3438
|
+
* passes `given`, `<SceneCanvas tune>` included: what a tool's chrome
|
|
3439
|
+
* reads to draw what the action it binds will make. Sourced by
|
|
3440
|
+
* `<SceneCanvas>`. */
|
|
3441
|
+
actionParams?: (id: string, given?: Record<string, unknown>) => Record<string, unknown>;
|
|
3442
|
+
/** The container the `insert` dep puts new nodes into — every shape a
|
|
3443
|
+
* tool draws and every dropped image or text. Absent, or answering
|
|
3444
|
+
* `null`: the top of the tree. */
|
|
3445
|
+
insertInto?: InsertIntoDep;
|
|
3446
|
+
/** Snap dep: the sessions a gesture snaps through, over `<SceneCanvas
|
|
3447
|
+
* snap>`'s sources. Absent means no snapping. */
|
|
3448
|
+
snap?: SnapDep;
|
|
3449
|
+
/** The store the snap readout layer draws, for an action's own marks. Sourced by `<SceneCanvas>`. */
|
|
3450
|
+
snapReadout?: SnapReadoutDep;
|
|
3451
|
+
/**
|
|
3452
|
+
* The canvas's debug sink.
|
|
3453
|
+
* Sourced by `<SceneCanvas>`; absent while its `debug` overlay is off.
|
|
3454
|
+
* Actions report what they did here, and the overlay draws it.
|
|
3455
|
+
*/
|
|
3456
|
+
debug?: DebugSink;
|
|
3457
|
+
/** Where an action's `preview` draws what it would make, over the canvas.
|
|
3458
|
+
* Sourced by `<SceneCanvas>`. */
|
|
3459
|
+
previewPaths?: PreviewPathsDep;
|
|
3460
|
+
/** Viewport point of a world point on this canvas, or null before it mounts.
|
|
3461
|
+
* Sourced by `<SceneCanvas>`. */
|
|
3462
|
+
worldToClient?: (x: number, y: number) => {
|
|
3463
|
+
x: number;
|
|
3464
|
+
y: number;
|
|
3465
|
+
} | null;
|
|
3466
|
+
/** Lasso-select dep — polygon hit-test + selection read/write. */
|
|
3467
|
+
lassoSelect: LassoSelectDep;
|
|
3468
|
+
/** Edit-anchors dep — narrow read/write of one polygon's path. If
|
|
3469
|
+
* absent, `editAnchorsAction`'s `start` returns an empty handle (no-op). */
|
|
3470
|
+
editAnchors: EditAnchorsDep;
|
|
3471
|
+
/** The transforms a path being edited should stay its own image under.
|
|
3472
|
+
* Absent: an anchor drag moves only what is dragged. */
|
|
3473
|
+
pathSymmetry?: PathSymmetryDep;
|
|
3474
|
+
/**
|
|
3475
|
+
* Text-edit dep — activates the in-place text editing overlay. Sourced
|
|
3476
|
+
* from consumer via `useTextEdit` / `useSceneTextEdit`.
|
|
3477
|
+
*
|
|
3478
|
+
* The optional `isTextNode` predicate guards against entering edit mode on
|
|
3479
|
+
* non-text nodes. A binding can pre-filter instead with a
|
|
3480
|
+
* `target: 'kind:text:selected'` spec; the guard remains for consumers who
|
|
3481
|
+
* bind the broader `'selected-body'` target or opted out of routing.
|
|
3482
|
+
*/
|
|
3483
|
+
textEdit: TextEditDep;
|
|
3484
|
+
/**
|
|
3485
|
+
* Resize-policy dep — bounds constraints, point-snap behaviors and
|
|
3486
|
+
* group expansion for `resizeAction`. Optional: when omitted,
|
|
3487
|
+
* `resizeAction` falls back to identity defaults. Consumers wire via
|
|
3488
|
+
* `useDepSource('resizePolicy', ...)` or the `useResizePolicy` helper.
|
|
3489
|
+
*/
|
|
3490
|
+
resizePolicy?: ResizePolicy<unknown>;
|
|
3491
|
+
/**
|
|
3492
|
+
* How to read and rewrite a pose — bounds, translate, remap, rotation. Every
|
|
3493
|
+
* built-in action that touches a pose reads it. Sourced by `<SceneCanvas>`
|
|
3494
|
+
* from its `poseDescriptor` prop; `AUTO_POSE_DESCRIPTOR` when absent.
|
|
3495
|
+
*/
|
|
3496
|
+
poseDescriptor?: PoseDescriptor<unknown>;
|
|
3497
|
+
/** Whether the box resize, rotate, flip, align, and distribute work against
|
|
3498
|
+
* includes the stroke. From `<SceneCanvas geometry.boundsIncludeStroke>`;
|
|
3499
|
+
* absent means `true`. */
|
|
3500
|
+
boundsIncludeStroke?: boolean;
|
|
3501
|
+
/**
|
|
3502
|
+
* Booleans adapter — read selection ids, fetch world-space `Path`s,
|
|
3503
|
+
* compare z-order, and mint result nodes for Pathfinder ops.
|
|
3504
|
+
*
|
|
3505
|
+
* Consumers wire via `useBooleansAdapter(adapter)`.
|
|
3506
|
+
*/
|
|
3507
|
+
booleansAdapter?: BooleansAdapter;
|
|
3508
|
+
/**
|
|
3509
|
+
* Create Outlines adapter — read selection ids, resolve text nodes, and
|
|
3510
|
+
* mint the path nodes that replace them. Consumers wire it with
|
|
3511
|
+
* `useCreateOutlinesAdapter(adapter)`; the `createOutlines` action reads it
|
|
3512
|
+
* in both its `enabled` predicate and its invoker.
|
|
3513
|
+
*/
|
|
3514
|
+
createOutlinesAdapter?: CreateOutlinesAdapter;
|
|
3515
|
+
/** Gesture dispatcher control surface, so an action can abort an
|
|
3516
|
+
* in-flight handle (Escape cancels a drag, etc.). */
|
|
3517
|
+
dispatcher?: {
|
|
3518
|
+
cancelAll(reason: 'commit' | 'cancel'): void;
|
|
3519
|
+
};
|
|
3520
|
+
/**
|
|
3521
|
+
* Layout-strategy lookup. Sourced by `<SceneCanvas>` from the scene.
|
|
3522
|
+
* Optional: absent (or all-null) → `moveAction` skips reflow.
|
|
3523
|
+
*/
|
|
3524
|
+
layout?: LayoutDep;
|
|
3525
|
+
/**
|
|
3526
|
+
* Slice dep — the commit for the Slice action. `<SceneCanvas>` publishes
|
|
3527
|
+
* `useSliceDepSource`; a consumer overrides it with `useSliceDep`.
|
|
3528
|
+
*
|
|
3529
|
+
* Optional: when absent, `sliceAction` is a no-op.
|
|
3530
|
+
*/
|
|
3531
|
+
slice?: SliceDep;
|
|
3532
|
+
/** Clipboard dep; see {@link ClipboardDep}. `clipboard.copy` and
|
|
3533
|
+
* `clipboard.cut` both no-op when it is absent. */
|
|
3534
|
+
clipboard?: ClipboardDep;
|
|
3535
|
+
/**
|
|
3536
|
+
* Optional consumer commit hook. When present, `moveAction` (and other
|
|
3537
|
+
* default actions) submit their committed ops through it instead of
|
|
3538
|
+
* `scene.applyBatch`, so apps with their own history integration
|
|
3539
|
+
* (checkpoint + push entry) capture the gesture as one undo entry.
|
|
3540
|
+
* When absent, commits fall back to `scene.applyBatch`.
|
|
3541
|
+
*/
|
|
3542
|
+
applyOps?: (ops: Op[], label: string) => void;
|
|
3543
|
+
/**
|
|
3544
|
+
* Ingestion dep — canvas viewport rect + consumer file→src resolver.
|
|
3545
|
+
* Optional: when absent, the `ingest` action no-ops (there is no
|
|
3546
|
+
* placement geometry to work with).
|
|
3547
|
+
*/
|
|
3548
|
+
ingestion?: IngestionDep;
|
|
3549
|
+
/**
|
|
3550
|
+
* Optional consumer seam for the eager-sync layer: lets pose-transform
|
|
3551
|
+
* actions (resize/move/nudge/flip — NOT rotate) ALSO rewrite a node's
|
|
3552
|
+
* data-held geometry. Given a node and the affine `m` applied to its pose,
|
|
3553
|
+
* `transform(node, m)` returns updated `data` (geometry mapped by `m`) or
|
|
3554
|
+
* `null` for nodes with no data-held geometry.
|
|
3555
|
+
*
|
|
3556
|
+
* Strictly opt-in: when absent (or when `transform` returns null), the kit
|
|
3557
|
+
* emits only the pose op and leaves `data` untouched. Rotate intentionally
|
|
3558
|
+
* never consults this seam (rotation lives on the pose, baked at render).
|
|
3559
|
+
*/
|
|
3560
|
+
geometryProjection?: GeometryProjection;
|
|
3561
|
+
/**
|
|
3562
|
+
* The surface's own camera. Inside a `<CanvasView>`, `view` answers that
|
|
3563
|
+
* view's camera and this one does not change: an action bound in a view
|
|
3564
|
+
* that must move the main camera — a minimap's pan — reads this.
|
|
3565
|
+
*/
|
|
3566
|
+
rootView: ViewApi;
|
|
3567
|
+
/**
|
|
3568
|
+
* The pointer store in scope: where the pointer is, in which view. Shared
|
|
3569
|
+
* by every surface under one `<PointerContextProvider>`.
|
|
3570
|
+
*/
|
|
3571
|
+
pointer?: _weasel_js_routing_react.PointerContextValue;
|
|
3572
|
+
/**
|
|
3573
|
+
* The touch or pen long-press being held, if any: where, since when, how
|
|
3574
|
+
* far through, and whether any binding would fire on it. Sourced by
|
|
3575
|
+
* `<SceneCanvas>` from its gesture dispatcher; press feedback reads it.
|
|
3576
|
+
*/
|
|
3577
|
+
longPress?: LongPressState;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
export { type CreateOutlinesAdapter as $, type AddNodeSpec as A, type LayerGroup as B, type ContentHandlerEntry as C, type Dims as D, type EditAnchorsDep as E, type FitViewToBoundsOptions as F, type GestureLifecycleOptions as G, type HandleLocks as H, type InertiaConfig as I, type SerializedScene as J, type GeometryProjection as K, type LayoutFrame as L, type InsertNodeFactory as M, type Node as N, type InsertPaint as O, type PathEditMark as P, type SvgIngestOptions as Q, type RectPose as R, type Scene as S, type SceneCanvasSnap as T, type Affordance as U, type ViewAnimationOptions as V, type AffordanceRegion as W, type AffordanceBinding as X, type CommonAffordanceScratch as Y, type TextOverflow as Z, _resetPaintKindsForTests as _, type PathEditExtension as a, type PaintKind as a$, type PaintKindEntry as a0, type DerivePoseFn as a1, type DerivePathFn as a2, type DerivedDep as a3, type PathEditTarget as a4, type PathSymmetryDep as a5, type BooleanOpOptions as a6, type BooleansAdapter as a7, type BooleanOp as a8, type PathPaint as a9, type FinishedEditFrame as aA, type FinishedPathEdit as aB, GEOMETRY_BOUND_DATA as aC, type HandleLock as aD, type HitTestView as aE, IDENTITY_POSE_COMPOSITION as aF, type IngestCtx as aG, type IngestionDep as aH, type InsertDep as aI, type InsertEnds as aJ, type InsertExtras as aK, type InsertIntoDep as aL, type InsertLive as aM, type LassoSelectDep as aN, type LayerCommandCache as aO, type LayerDrawFailure as aP, type LayerDrawSpan as aQ, type LayerRecord as aR, type LayerRetainPolicy as aS, type LayoutDep as aT, type LayoutMove as aU, type LeafNode as aV, type Locus as aW, type MinSize as aX, type NodeAtPointDep as aY, type OutlinePathSpec as aZ, PATH_OVERLAY_ROLES as a_, type BooleanOpResult as aa, type BooleanStrokes as ab, type SnapMods as ac, type SourceCandidate as ad, type SnapProbeAt as ae, type SnapCollect as af, type SnapMark as ag, type SnapDep as ah, type SnapOutcome as ai, type AddLayerSpec as aj, type AngleCandidate as ak, type AngleCollect as al, type AnimateToBoundsOptions as am, type AreaSelectDep as an, type Bivariant as ao, type BooleanOpPreview as ap, type BooleanPreviewPiece as aq, type ClipFromPoseFn as ar, type ClipboardDep as as, type ClipboardIngestCtx as at, type ContainerNode as au, type CopiesFromPoseFn as av, type CreateOutlinesResult as aw, type CustomPaintContext as ax, DEFAULT_LAYER_RETAIN as ay, type DecayLoopConfig as az, type SnapSource as b, listPaintKinds as b$, type PaintKindEditorProps as b0, type PaintKindFamily as b1, type PaintKindLoader as b2, type PanBounds as b3, type PathEditDrag as b4, type PathEditDragStart as b5, type PathEditFinishCtx as b6, type PathEditHandleMove as b7, type PathEditMarksCtx as b8, type PathEditOther as b9, type SvgUnpacker as bA, type SystemLayerRecord as bB, type TextEditDep as bC, type TextNodeData as bD, type TransientPath as bE, type UserLayerRecord as bF, VIEW_ANIMATION_KEY as bG, type ViewAnimationApi as bH, type ViewApi as bI, type ViewChannel as bJ, applyBooleanOp as bK, applyCreateOutlines as bL, asNodeId as bM, asPaint as bN, composeWorldPose as bO, composesFrames as bP, createPathOverlay as bQ, createSnapOutcomeStore as bR, createSnapReadoutLayer as bS, depsUnchanged as bT, drawLayers as bU, drawOneLayer as bV, fitViewToBounds as bW, getPaintKind as bX, isLayerPainted as bY, isLayerVisible as bZ, listGradientKinds as b_, type PathEditPart as ba, type PathEditStore as bb, type PathForm as bc, type PathOverlay as bd, type PathOverlayOptions as be, type PathOverlayStyle as bf, type PathRepresentation as bg, type PoseClosure as bh, type PoseHold as bi, type PoseOverride as bj, type PoseWriteOrigin as bk, type PreviewPathsDep as bl, type RemovedNode as bm, type ResizePolicy as bn, SCENE_HISTORY_FORM as bo, STICKY_DEFAULTS as bp, type SceneArrivalHandler as bq, type SerializedLayer as br, type SerializedNode as bs, type SerializedSceneHistory as bt, type SnapBegin as bu, type SnapEdge as bv, type SnapEdges as bw, type SnapMarks as bx, type SnapReadoutDep as by, type SnapReadoutStyle as bz, type SnapGesture as c, minSizeOf as c0, paintKindOf as c1, paintKindRegistry as c2, paintedLayers as c3, paintsLayer as c4, paletteInsertPaint as c5, pathPaintOf as c6, patternFamily as c7, previewBooleanOp as c8, rebaseLocalPose as c9, registerContentHandler as ca, registerPaintKind as cb, registerPaintKindLoader as cc, seedTile as cd, stickyData as ce, stickyNodeFactory as cf, subscribeToSources as cg, switchGradientKind as ch, textBoxOf as ci, useDecayLoop as cj, useViewAnimation as ck, useViewAnimationOn as cl, viewAxes as cm, withoutGeometryBoundData as cn, type SnapConstrain as d, type SnapResizeBox as e, type SnapGeometry as f, type SnapOutcomeStore as g, type SnapSession as h, type SystemLayerSpec as i, type RegisteredOp as j, type SceneRegistry as k, type PoseComposition as l, type RenderLayer as m, type LayerHit as n, type PoseAdapter as o, type ViewportDims as p, type RedrawSource as q, type EditAnchorsParams as r, type SliceDep as s, type StickyStyle as t, type PoseOverrides as u, type PoseRemoval as v, type PoseWrite as w, type ScenePoseReports as x, type AnchorMarkerShape as y, type ChromeState as z };
|