@weasel-js/core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +611 -0
- package/README.md +1 -1
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/animation/index.js +3 -3
- package/dist/animation/rig/bindRig.js +1 -1
- package/dist/animation/rig/rigNode.js.map +1 -1
- package/dist/barrel/canvas.js +9 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +10 -6
- package/dist/barrel/renderer.js +5 -3
- package/dist/barrel/routing.js +7 -12
- package/dist/barrel/scene.js +9 -5
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +9 -4
- package/dist/canvas/Canvas.js +5 -2
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +23 -34
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/ModalityHud.js +1 -1
- package/dist/canvas/NodeShape.js +4 -1
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +45 -5
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js +1 -11
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
- package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
- package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +94 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
- package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
- package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +15 -10
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +24 -7
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -5
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +27 -24
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SurfaceCanvas.js +5 -22
- package/dist/canvas/SurfaceCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- package/dist/canvas/canvasRenderer.js +9 -5
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/contextAttributes.js +14 -0
- package/dist/canvas/contextAttributes.js.map +1 -0
- package/dist/canvas/defaultDrawOne.js +2 -0
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/booleans.js +2 -1
- package/dist/canvas/deps/booleans.js.map +1 -1
- package/dist/canvas/deps/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +2 -2
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/insert.js +10 -4
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +189 -0
- package/dist/canvas/deps/pathEditCommits.js.map +1 -0
- package/dist/canvas/deps/snap.js +12 -9
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/transformFollowers.js +20 -0
- package/dist/canvas/deps/transformFollowers.js.map +1 -0
- package/dist/canvas/derivedPath.js +20 -1
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/drawnBounds.js +38 -4
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/inheritedPaints.js +44 -0
- package/dist/canvas/inheritedPaints.js.map +1 -0
- package/dist/canvas/nodeShapes/derivedPainter.js +23 -16
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +13 -34
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +12 -10
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +12 -11
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/textPainter.js +13 -12
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
- package/dist/canvas/overlayRoleStrokes.js +12 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/pathOverlay.js +27 -7
- package/dist/canvas/pathOverlay.js.map +1 -1
- package/dist/canvas/pickReach.js +3 -3
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +3 -1
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +7 -6
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +2 -1
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +2 -1
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/surfaceContribution.js +12 -8
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- package/dist/canvas/useLayerStack.js +6 -2
- package/dist/canvas/useLayerStack.js.map +1 -1
- package/dist/canvas/useViewAim.js +121 -0
- package/dist/canvas/useViewAim.js.map +1 -0
- package/dist/canvas/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/canvas/useViewNesting.js +3 -2
- package/dist/canvas/useViewNesting.js.map +1 -1
- package/dist/canvas/useViewRegistrySurface.js +4 -2
- package/dist/canvas/useViewRegistrySurface.js.map +1 -1
- package/dist/canvas/viewMarkers.js +63 -0
- package/dist/canvas/viewMarkers.js.map +1 -0
- package/dist/canvas/viewRegistry.js +27 -1
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/clipboard.d.ts +3 -2
- package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
- package/dist/clone.d.ts +4 -3
- package/dist/core/geometry/autoPoseDescriptor.js +1 -1
- package/dist/core/ops/setDependsOn.js +37 -0
- package/dist/core/ops/setDependsOn.js.map +1 -0
- package/dist/core/ops/writtenBy.js +53 -0
- package/dist/core/ops/writtenBy.js.map +1 -0
- package/dist/core/pages/fitViewToPage.js +12 -1
- package/dist/core/pages/fitViewToPage.js.map +1 -1
- package/dist/core/pages/pageEdits.js +163 -0
- package/dist/core/pages/pageEdits.js.map +1 -0
- package/dist/core/pages/pages.js +30 -1
- package/dist/core/pages/pages.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js +59 -2
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/scene/NodeRouting.js +8 -3
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/carryDescendants.js +51 -0
- package/dist/core/scene/carryDescendants.js.map +1 -0
- package/dist/core/scene/clipNothing.js +13 -0
- package/dist/core/scene/clipNothing.js.map +1 -0
- package/dist/core/scene/depMemo.js +11 -3
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +7 -1
- package/dist/core/scene/dependents.js.map +1 -1
- package/dist/core/scene/derivedParts.js +10 -11
- package/dist/core/scene/derivedParts.js.map +1 -1
- package/dist/core/scene/docValues.js +57 -0
- package/dist/core/scene/docValues.js.map +1 -0
- package/dist/core/scene/editPass.js +111 -0
- package/dist/core/scene/editPass.js.map +1 -0
- package/dist/core/scene/effectivePose.js +13 -2
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +4 -1
- package/dist/core/scene/fieldEdits.js.map +1 -1
- package/dist/core/scene/fontReads.js +37 -0
- package/dist/core/scene/fontReads.js.map +1 -0
- package/dist/core/scene/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/inheritedPaint.js +75 -0
- package/dist/core/scene/inheritedPaint.js.map +1 -0
- package/dist/core/scene/kitRegistry.js +5 -0
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/layoutPass.js +28 -3
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +15 -7
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js.map +1 -1
- package/dist/core/scene/pathEffects/derive.js +7 -2
- package/dist/core/scene/pathEffects/derive.js.map +1 -1
- package/dist/core/scene/pathEffects/effects.js +3 -1
- package/dist/core/scene/pathEffects/effects.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlong.js +95 -0
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
- package/dist/core/scene/recorder.js +28 -19
- package/dist/core/scene/recorder.js.map +1 -1
- package/dist/core/scene/scene.js +15 -9
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneChanges.js +13 -0
- package/dist/core/scene/sceneChanges.js.map +1 -0
- package/dist/core/scene/sceneEdits.js +8 -1
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneMutators.js +1 -0
- package/dist/core/scene/sceneMutators.js.map +1 -1
- package/dist/core/scene/sceneRecording.js +20 -3
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/scene/sceneSelection.js +4 -1
- package/dist/core/scene/sceneSelection.js.map +1 -1
- package/dist/core/scene/sceneState.js +11 -5
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +5 -3
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/unitScopes.js +19 -1
- package/dist/core/scene/unitScopes.js.map +1 -1
- package/dist/core/selection/usePublishSceneSelection.js +6 -12
- package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
- package/dist/core/shapeKinds.js +25 -11
- package/dist/core/shapeKinds.js.map +1 -1
- package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-p8fDIAKt.d.ts} +3 -2
- package/dist/debug/createDebugOverlayLayer.js +16 -111
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/createDebugSink.js +2 -1
- package/dist/debug/createDebugSink.js.map +1 -1
- package/dist/debug/defaultTheme.js +4 -2
- package/dist/debug/defaultTheme.js.map +1 -1
- package/dist/debug/features.js +17 -0
- package/dist/debug/features.js.map +1 -0
- package/dist/debug/overlayPanels.js +117 -0
- package/dist/debug/overlayPanels.js.map +1 -0
- package/dist/debug/parseDebugFlags.js +4 -13
- package/dist/debug/parseDebugFlags.js.map +1 -1
- package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-mG19aEdD.d.ts} +174 -904
- package/dist/devtools/handlers.js +112 -0
- package/dist/devtools/handlers.js.map +1 -0
- package/dist/devtools/history.js +71 -0
- package/dist/devtools/history.js.map +1 -0
- package/dist/devtools/hook.js +74 -0
- package/dist/devtools/hook.js.map +1 -0
- package/dist/devtools/label.js +25 -0
- package/dist/devtools/label.js.map +1 -0
- package/dist/devtools/notices.js +58 -0
- package/dist/devtools/notices.js.map +1 -0
- package/dist/devtools/protocol.js +7 -0
- package/dist/devtools/protocol.js.map +1 -0
- package/dist/devtools/registry.js +90 -0
- package/dist/devtools/registry.js.map +1 -0
- package/dist/devtools/root.js +80 -0
- package/dist/devtools/root.js.map +1 -0
- package/dist/devtools/serialize.js +86 -0
- package/dist/devtools/serialize.js.map +1 -0
- package/dist/devtools/session.js +111 -0
- package/dist/devtools/session.js.map +1 -0
- package/dist/devtools/transport.js +67 -0
- package/dist/devtools/transport.js.map +1 -0
- package/dist/devtools/useDevtoolsRoot.js +81 -0
- package/dist/devtools/useDevtoolsRoot.js.map +1 -0
- package/dist/devtools-protocol.d.ts +435 -0
- package/dist/devtools-protocol.js +7 -0
- package/dist/devtools.d.ts +8 -0
- package/dist/devtools.js +12 -0
- package/dist/devtools.js.map +1 -0
- package/dist/features/chrome-caps/useHoverTracking.js +16 -10
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +25 -2
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/measure/measureCommands.js +7 -5
- package/dist/features/measure/measureCommands.js.map +1 -1
- package/dist/features/measure/measureContribution.js +4 -2
- package/dist/features/measure/measureContribution.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +7 -3
- package/dist/features/modes/modeTriggers.js.map +1 -1
- package/dist/features/pathEffects/effectSources.js +60 -0
- package/dist/features/pathEffects/effectSources.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +17 -1
- package/dist/features/pathEffects/readSource.js.map +1 -1
- package/dist/features/pathEffects/textItems.js +53 -0
- package/dist/features/pathEffects/textItems.js.map +1 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/features/paths/index.js +2 -2
- package/dist/features/paths/pathEditExtension.js.map +1 -1
- package/dist/features/paths/pathEditState.js +5 -2
- package/dist/features/paths/pathEditState.js.map +1 -1
- package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
- package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
- package/dist/features/selection/selectionPose.js +4 -1
- package/dist/features/selection/selectionPose.js.map +1 -1
- package/dist/features/snap/gather.js +9 -1
- package/dist/features/snap/gather.js.map +1 -1
- package/dist/features/snap/lazySession.js +17 -0
- package/dist/features/snap/lazySession.js.map +1 -0
- package/dist/features/snap/marks.js.map +1 -1
- package/dist/features/snap/probes2d.js +27 -19
- package/dist/features/snap/probes2d.js.map +1 -1
- package/dist/features/snap/readoutLayer.js.map +1 -1
- package/dist/features/snap/roles.js +2 -1
- package/dist/features/snap/roles.js.map +1 -1
- package/dist/features/snap/rotationSource.js +25 -8
- package/dist/features/snap/rotationSource.js.map +1 -1
- package/dist/features/snap/sceneSession2d.js +6 -4
- package/dist/features/snap/sceneSession2d.js.map +1 -1
- package/dist/features/snap/session2d.js +37 -23
- package/dist/features/snap/session2d.js.map +1 -1
- package/dist/features/snap/spanSnap.js +5 -2
- package/dist/features/snap/spanSnap.js.map +1 -1
- package/dist/features/text/sceneTextDrafts.js +65 -0
- package/dist/features/text/sceneTextDrafts.js.map +1 -0
- package/dist/features/text/textHitAt.js +31 -2
- package/dist/features/text/textHitAt.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +22 -18
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/viewports/aim.js +105 -0
- package/dist/features/viewports/aim.js.map +1 -0
- package/dist/features/viewports/viewMarker.js +82 -0
- package/dist/features/viewports/viewMarker.js.map +1 -0
- package/dist/features/viewports/viewMarkerDrag.js +55 -0
- package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +0 -10
- package/dist/index.d.ts +1198 -894
- package/dist/index.js +55 -38
- package/dist/interactions/actions/align/action.js +6 -4
- package/dist/interactions/actions/align/action.js.map +1 -1
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/action.js +7 -1
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/booleans/booleans.js +2 -1
- package/dist/interactions/actions/booleans/booleans.js.map +1 -1
- package/dist/interactions/actions/booleans/operands.js +6 -5
- package/dist/interactions/actions/booleans/operands.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +27 -17
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/clone/action.js +1 -1
- package/dist/interactions/actions/clone/behaviors.js +4 -4
- package/dist/interactions/actions/clone/behaviors.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
- package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +8 -5
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
- package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
- package/dist/interactions/actions/defaults/contextMenu.js +17 -8
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +2 -2
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +64 -41
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +12 -9
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/escape.js +11 -8
- package/dist/interactions/actions/defaults/escape.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +21 -15
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +17 -9
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +21 -40
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
- package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
- package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
- package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
- package/dist/interactions/actions/defaults/reorder.js +24 -6
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/selectAll.js +8 -5
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +7 -3
- package/dist/interactions/actions/defaults/setFill.js.map +1 -1
- package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
- package/dist/interactions/actions/defaults/setStroke.js +12 -11
- package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
- package/dist/interactions/actions/defaults/toolActivate.js +7 -1
- package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
- package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
- package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
- package/dist/interactions/actions/defaults/undoRedo.js +19 -13
- package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
- package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
- package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
- package/dist/interactions/actions/distribute/action.js +6 -4
- package/dist/interactions/actions/distribute/action.js.map +1 -1
- package/dist/interactions/actions/drawnBoxes.js +2 -1
- package/dist/interactions/actions/drawnBoxes.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +10 -10
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js +41 -8
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +14 -6
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/gestureLifecycle.js +5 -2
- package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +1 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/commit.js +1 -1
- package/dist/interactions/actions/insert/parent.js +11 -0
- package/dist/interactions/actions/insert/parent.js.map +1 -0
- package/dist/interactions/actions/insert/placeAction.js +7 -2
- package/dist/interactions/actions/insert/placeAction.js.map +1 -1
- package/dist/interactions/actions/insert/repositionAction.js +2 -1
- package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
- package/dist/interactions/actions/insert/session.js +5 -1
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +15 -8
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
- package/dist/interactions/actions/move/capture.js +1 -1
- package/dist/interactions/actions/move/commit/index.js +0 -2
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
- package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
- package/dist/interactions/actions/move/commit/reparent.js +11 -5
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +4 -10
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +20 -17
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +2 -1
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +18 -1
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +5 -5
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/session.js +14 -3
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +8 -37
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/moveNodes.js +87 -0
- package/dist/interactions/actions/moveNodes.js.map +1 -0
- package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
- package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
- package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
- package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +83 -72
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +2 -1
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/cornerHandles.js +2 -1
- package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
- package/dist/interactions/actions/resize/session.js +2 -0
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +3 -3
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +7 -4
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/commit.js +2 -1
- package/dist/interactions/actions/rotate/commit.js.map +1 -1
- package/dist/interactions/actions/rotate/session.js +2 -0
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +25 -9
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/testUtils.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +13 -11
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/interactions/actions/transformFinish.js +106 -0
- package/dist/interactions/actions/transformFinish.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -5
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js +2 -1
- package/dist/move.d.ts +5 -4
- package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
- package/dist/resize.d.ts +4 -3
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +2 -2
- package/dist/test-hook/createTestHook.js +1 -1
- package/dist/test-hook/createTestHook.js.map +1 -1
- package/dist/test-hook/useTestHook.js +2 -1
- package/dist/test-hook/useTestHook.js.map +1 -1
- package/dist/test-seams.d.ts +9 -5
- package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
- package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +7 -4
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/image/useImageTool.js +1 -0
- package/dist/tools/builtin/image/useImageTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
- package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js +1 -0
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
- package/dist/tools/builtin/pen/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.js.map +1 -1
- package/dist/tools/builtin/pen/usePenTool.js +14 -6
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
- package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/rect/useRectTool.js +1 -0
- package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
- package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/pressDecision.js +32 -0
- package/dist/tools/builtin/select/pressDecision.js.map +1 -0
- package/dist/tools/builtin/select/selectionContributions.js +22 -13
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +13 -10
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +22 -8
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +13 -4
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/sticky/stickyNode.js +4 -1
- package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
- package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
- package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
- package/dist/tools/builtin/text/useTextTool.js +3 -1
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/index.js +26 -0
- package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
- package/dist/types-BN9hbdMI.d.ts +184 -0
- package/dist/types-CniVctmk.d.ts +949 -0
- package/dist/types-oFeQ5VjV.d.ts +264 -0
- package/dist/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +39 -25
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
- package/dist/tools/builtin/bone/boneActions.js +0 -156
- package/dist/tools/builtin/bone/boneActions.js.map +0 -1
- package/dist/tools/builtin/bone/boneOverlay.js +0 -71
- package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
- package/dist/tools/builtin/bone/placedRig.js +0 -28
- package/dist/tools/builtin/bone/placedRig.js.map +0 -1
- package/dist/tools/builtin/bone/rigEditState.js +0 -30
- package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
- package/dist/tools/builtin/bone/useBoneTool.js +0 -125
- package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
- package/dist/tools/builtin/weight/useWeightTool.js +0 -101
- package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
- package/dist/tools/builtin/weight/weightActions.js +0 -140
- package/dist/tools/builtin/weight/weightActions.js.map +0 -1
- package/dist/tools/builtin/weight/weightOverlay.js +0 -78
- package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as PlaneMap } from './types-7puAuVD2.js';
|
|
2
2
|
import { Op } from '@weasel-js/history';
|
|
3
|
+
import { S as SnapTarget, M as MoveAdapter } from './types-oFeQ5VjV.js';
|
|
3
4
|
import { FramedBox, View } from '@weasel-js/geom';
|
|
4
5
|
import { KitSettingsStore } from '@weasel-js/react';
|
|
5
6
|
import { ModifierState, ResizeAnchor } from '@weasel-js/routing';
|
|
@@ -140,29 +141,15 @@ interface BehaviorEnd {
|
|
|
140
141
|
answered: boolean;
|
|
141
142
|
}
|
|
142
143
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
144
|
+
* The translation a drag proposes and its behaviors shape, applied identically
|
|
145
|
+
* to every dragged id so a multi-select gesture cannot drift apart. Resize and
|
|
146
|
+
* rotate behaviors answer in their own terms (`ResizeMoveResult`,
|
|
147
|
+
* `RotateMoveResult`), not through this.
|
|
146
148
|
*/
|
|
147
149
|
type GroupTransform = {
|
|
148
150
|
kind: 'translate';
|
|
149
151
|
dx: number;
|
|
150
152
|
dy: number;
|
|
151
|
-
} | {
|
|
152
|
-
kind: 'scale';
|
|
153
|
-
pivot: {
|
|
154
|
-
x: number;
|
|
155
|
-
y: number;
|
|
156
|
-
};
|
|
157
|
-
sx: number;
|
|
158
|
-
sy: number;
|
|
159
|
-
} | {
|
|
160
|
-
kind: 'rotate';
|
|
161
|
-
pivot: {
|
|
162
|
-
x: number;
|
|
163
|
-
y: number;
|
|
164
|
-
};
|
|
165
|
-
angle: number;
|
|
166
153
|
};
|
|
167
154
|
/**
|
|
168
155
|
* Per-frame result a `MoveBehavior.onMove` can return. `snap` announces a
|
|
@@ -202,8 +189,8 @@ interface MoveEnd extends BehaviorEnd {
|
|
|
202
189
|
};
|
|
203
190
|
}
|
|
204
191
|
/** A behavior on a move — shapes the proposed transform during a drag.
|
|
205
|
-
* Behaviors receive a `GroupTransform`
|
|
206
|
-
*
|
|
192
|
+
* Behaviors receive a `GroupTransform` and return a `BehaviorResult` shaping
|
|
193
|
+
* it. */
|
|
207
194
|
type MoveBehavior<TPose> = ActionBehavior<TPose, GroupTransform, BehaviorResult<TPose>, MoveEnd>;
|
|
208
195
|
|
|
209
196
|
/** Per-frame proposed resize: pose plus the anchor pinning the opposite corner. */
|
package/dist/clone.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { C as CloneBehavior, d as CloneBehaviorResult } from './clone-
|
|
2
|
-
import './types-
|
|
3
|
-
import '@weasel-js/history';
|
|
1
|
+
export { C as CloneBehavior, d as CloneBehaviorResult } from './clone-C3e0OTuF.js';
|
|
2
|
+
import './types-7puAuVD2.js';
|
|
4
3
|
import '@weasel-js/geom';
|
|
4
|
+
import '@weasel-js/history';
|
|
5
|
+
import './types-oFeQ5VjV.js';
|
|
5
6
|
import './poseDescriptor-DN2yfnq_.js';
|
|
6
7
|
import '@weasel-js/animator';
|
|
7
8
|
import '@weasel-js/react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { pathPoseDescriptor } from "./pathPoseDescriptor.js";
|
|
2
1
|
import { RECT_POSE_DESCRIPTOR } from "./poseDescriptor.js";
|
|
2
|
+
import { pathPoseDescriptor } from "./pathPoseDescriptor.js";
|
|
3
3
|
|
|
4
4
|
//#region src/core/geometry/autoPoseDescriptor.ts
|
|
5
5
|
/** True for Path-shaped poses (`{kind: 'polygon' | 'rect'}`). Useful for
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { registerOpFactory } from "./registry.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/ops/setDependsOn.ts
|
|
4
|
+
/** Op: set what a derived node's geometry derives from, inverting back to
|
|
5
|
+
* `from`. */
|
|
6
|
+
function createSetDependsOnOp(args) {
|
|
7
|
+
const { id, from, to, label, coalesceKey } = args;
|
|
8
|
+
return {
|
|
9
|
+
name: "setDependsOn",
|
|
10
|
+
args: {
|
|
11
|
+
id,
|
|
12
|
+
from,
|
|
13
|
+
to,
|
|
14
|
+
label,
|
|
15
|
+
coalesceKey
|
|
16
|
+
},
|
|
17
|
+
label,
|
|
18
|
+
coalesceKey,
|
|
19
|
+
apply(adapter) {
|
|
20
|
+
adapter.setDependsOn(id, to);
|
|
21
|
+
},
|
|
22
|
+
invert() {
|
|
23
|
+
return createSetDependsOnOp({
|
|
24
|
+
id,
|
|
25
|
+
from: to,
|
|
26
|
+
to: from,
|
|
27
|
+
label,
|
|
28
|
+
coalesceKey
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
registerOpFactory("setDependsOn", (args) => createSetDependsOnOp(args));
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createSetDependsOnOp };
|
|
37
|
+
//# sourceMappingURL=setDependsOn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setDependsOn.js","names":[],"sources":["../../../src/core/ops/setDependsOn.ts"],"sourcesContent":["import type { Op } from './types';\nimport { registerOpFactory } from './registry';\n\ntype DependsOn = readonly string[] | 'children' | undefined;\n\ninterface SetDependsOnAdapter {\n setDependsOn(id: string, dependsOn: DependsOn): void;\n}\n\n/** Arguments to {@link createSetDependsOnOp}: retarget node `id`'s derivation\n * from the sources `from` to `to`. `undefined` is no derivation. */\nexport interface SetDependsOnArgs {\n id: string;\n from: DependsOn;\n to: DependsOn;\n label?: string;\n coalesceKey?: string;\n}\n\n/** Op: set what a derived node's geometry derives from, inverting back to\n * `from`. */\nexport function createSetDependsOnOp(args: SetDependsOnArgs): Op {\n const { id, from, to, label, coalesceKey } = args;\n return {\n name: 'setDependsOn',\n args: { id, from, to, label, coalesceKey },\n label,\n coalesceKey,\n apply(adapter) {\n (adapter as SetDependsOnAdapter).setDependsOn(id, to);\n },\n invert() {\n return createSetDependsOnOp({ id, from: to, to: from, label, coalesceKey });\n },\n };\n}\n\nregisterOpFactory<SetDependsOnArgs>('setDependsOn', (args) => createSetDependsOnOp(args));\n"],"mappings":";;;;;AAqBA,SAAgB,qBAAqB,MAA4B;CAC/D,MAAM,EAAE,IAAI,MAAM,IAAI,OAAO,gBAAgB;CAC7C,OAAO;EACL,MAAM;EACN,MAAM;GAAE;GAAI;GAAM;GAAI;GAAO;EAAY;EACzC;EACA;EACA,MAAM,SAAS;GACb,QAAiC,aAAa,IAAI,EAAE;EACtD;EACA,SAAS;GACP,OAAO,qBAAqB;IAAE;IAAI,MAAM;IAAI,IAAI;IAAM;IAAO;GAAY,CAAC;EAC5E;CACF;AACF;AAEA,kBAAoC,iBAAiB,SAAS,qBAAqB,IAAI,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { sceneMutators } from "../scene/sceneMutators.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/ops/writtenBy.ts
|
|
4
|
+
/**
|
|
5
|
+
* The pose and data `ops` leave each node they write, by id, read by applying
|
|
6
|
+
* them to a recorder rather than the scene; null when one cannot be read that
|
|
7
|
+
* way. A node only re-parented, re-layered, inserted, or removed is not in it.
|
|
8
|
+
*/
|
|
9
|
+
function writtenBy(sc, ops) {
|
|
10
|
+
const after = /* @__PURE__ */ new Map();
|
|
11
|
+
const current = (id) => {
|
|
12
|
+
const node = after.get(id) ?? sc.get(id);
|
|
13
|
+
return node ? {
|
|
14
|
+
pose: node.pose,
|
|
15
|
+
data: node.data
|
|
16
|
+
} : null;
|
|
17
|
+
};
|
|
18
|
+
const write = (id, field, value) => {
|
|
19
|
+
const node = current(id);
|
|
20
|
+
if (node) after.set(id, {
|
|
21
|
+
...node,
|
|
22
|
+
[field]: value
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
const reads = sceneMutators(sc);
|
|
26
|
+
const noop = () => {};
|
|
27
|
+
const recorder = {
|
|
28
|
+
...reads,
|
|
29
|
+
setPose: (id, pose) => write(id, "pose", pose),
|
|
30
|
+
setData: (id, data) => write(id, "data", data),
|
|
31
|
+
setParent: noop,
|
|
32
|
+
setChildOrder: noop,
|
|
33
|
+
setLayer: noop,
|
|
34
|
+
setDependsOn: noop,
|
|
35
|
+
setLayout: noop,
|
|
36
|
+
setHidden: noop,
|
|
37
|
+
setLocked: noop,
|
|
38
|
+
removeNode: noop,
|
|
39
|
+
insertNode: noop,
|
|
40
|
+
getSelection: () => [...sc.getSelection()],
|
|
41
|
+
setSelection: noop
|
|
42
|
+
};
|
|
43
|
+
try {
|
|
44
|
+
for (const op of ops) op.apply(recorder);
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return after;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { writtenBy };
|
|
53
|
+
//# sourceMappingURL=writtenBy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writtenBy.js","names":[],"sources":["../../../src/core/ops/writtenBy.ts"],"sourcesContent":["import { sceneMutators } from '../scene/sceneMutators';\nimport type { NodeId, Scene } from '../scene/types';\nimport type { Op } from './types';\n\n/** A node's pose and data, as a batch of ops leaves them. */\nexport interface WrittenNode {\n pose: unknown;\n data: unknown;\n}\n\n/**\n * The pose and data `ops` leave each node they write, by id, read by applying\n * them to a recorder rather than the scene; null when one cannot be read that\n * way. A node only re-parented, re-layered, inserted, or removed is not in it.\n */\nexport function writtenBy(sc: Scene<unknown, string, unknown>, ops: readonly Op[]): Map<string, WrittenNode> | null {\n const after = new Map<string, WrittenNode>();\n const current = (id: string): WrittenNode | null => {\n const node = after.get(id) ?? sc.get(id as NodeId);\n return node ? { pose: node.pose, data: node.data } : null;\n };\n const write = (id: string, field: keyof WrittenNode, value: unknown) => {\n const node = current(id);\n if (node) after.set(id, { ...node, [field]: value });\n };\n const reads = sceneMutators(sc);\n const noop = () => {};\n const recorder = {\n ...reads,\n setPose: (id: string, pose: unknown) => write(id, 'pose', pose),\n setData: (id: string, data: unknown) => write(id, 'data', data),\n setParent: noop, setChildOrder: noop, setLayer: noop, setDependsOn: noop, setLayout: noop,\n setHidden: noop, setLocked: noop, removeNode: noop, insertNode: noop,\n getSelection: (): string[] => [...sc.getSelection()],\n setSelection: noop,\n };\n try {\n for (const op of ops) op.apply(recorder);\n } catch {\n return null;\n }\n return after;\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,UAAU,IAAqC,KAAqD;CAClH,MAAM,wBAAQ,IAAI,IAAyB;CAC3C,MAAM,WAAW,OAAmC;EAClD,MAAM,OAAO,MAAM,IAAI,EAAE,KAAK,GAAG,IAAI,EAAY;EACjD,OAAO,OAAO;GAAE,MAAM,KAAK;GAAM,MAAM,KAAK;EAAK,IAAI;CACvD;CACA,MAAM,SAAS,IAAY,OAA0B,UAAmB;EACtE,MAAM,OAAO,QAAQ,EAAE;EACvB,IAAI,MAAM,MAAM,IAAI,IAAI;GAAE,GAAG;IAAO,QAAQ;EAAM,CAAC;CACrD;CACA,MAAM,QAAQ,cAAc,EAAE;CAC9B,MAAM,aAAa,CAAC;CACpB,MAAM,WAAW;EACf,GAAG;EACH,UAAU,IAAY,SAAkB,MAAM,IAAI,QAAQ,IAAI;EAC9D,UAAU,IAAY,SAAkB,MAAM,IAAI,QAAQ,IAAI;EAC9D,WAAW;EAAM,eAAe;EAAM,UAAU;EAAM,cAAc;EAAM,WAAW;EACrF,WAAW;EAAM,WAAW;EAAM,YAAY;EAAM,YAAY;EAChE,oBAA8B,CAAC,GAAG,GAAG,aAAa,CAAC;EACnD,cAAc;CAChB;CACA,IAAI;EACF,KAAK,MAAM,MAAM,KAAK,GAAG,MAAM,QAAQ;CACzC,QAAQ;EACN,OAAO;CACT;CACA,OAAO;AACT"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fitViewToBounds } from "../viewport/fitViewToBounds.js";
|
|
2
|
+
import { pageOfBounds } from "./pages.js";
|
|
2
3
|
|
|
3
4
|
//#region src/core/pages/fitViewToPage.ts
|
|
4
5
|
/** The view that shows one placed page whole: `fitViewToBounds` on its rect. */
|
|
@@ -11,7 +12,17 @@ function fitViewToPage(page, viewportDims, currentView, options) {
|
|
|
11
12
|
height
|
|
12
13
|
}, viewportDims, currentView, options);
|
|
13
14
|
}
|
|
15
|
+
/** The page the view shows most of: the one overlapping the visible world rect most, or `null` when none shows. */
|
|
16
|
+
function pageInView(pages, view, viewportDims) {
|
|
17
|
+
const visible = {
|
|
18
|
+
x: view.x,
|
|
19
|
+
y: view.y,
|
|
20
|
+
width: viewportDims.width / view.scale.x,
|
|
21
|
+
height: viewportDims.height / view.scale.y
|
|
22
|
+
};
|
|
23
|
+
return pageOfBounds(pages, visible);
|
|
24
|
+
}
|
|
14
25
|
|
|
15
26
|
//#endregion
|
|
16
|
-
export { fitViewToPage };
|
|
27
|
+
export { fitViewToPage, pageInView };
|
|
17
28
|
//# sourceMappingURL=fitViewToPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitViewToPage.js","names":[],"sources":["../../../src/core/pages/fitViewToPage.ts"],"sourcesContent":["import {\n fitViewToBounds,\n type FitViewToBoundsOptions,\n type ViewportDims,\n} from '../viewport/fitViewToBounds';\nimport type { View } from '../viewport/view';\nimport type
|
|
1
|
+
{"version":3,"file":"fitViewToPage.js","names":[],"sources":["../../../src/core/pages/fitViewToPage.ts"],"sourcesContent":["import {\n fitViewToBounds,\n type FitViewToBoundsOptions,\n type ViewportDims,\n} from '../viewport/fitViewToBounds';\nimport type { View } from '../viewport/view';\nimport { pageOfBounds, type PlacedPage } from './pages';\n\n/** The view that shows one placed page whole: `fitViewToBounds` on its rect. */\nexport function fitViewToPage(\n page: PlacedPage,\n viewportDims: ViewportDims,\n currentView: View,\n options?: FitViewToBoundsOptions,\n): View {\n const { x, y, width, height } = page;\n return fitViewToBounds({ x, y, width, height }, viewportDims, currentView, options);\n}\n\n/** The page the view shows most of: the one overlapping the visible world rect most, or `null` when none shows. */\nexport function pageInView(\n pages: readonly PlacedPage[],\n view: View,\n viewportDims: ViewportDims,\n): PlacedPage | null {\n const visible = { x: view.x, y: view.y, width: viewportDims.width / view.scale.x, height: viewportDims.height / view.scale.y };\n return pageOfBounds(pages, visible);\n}\n"],"mappings":";;;;;AASA,SAAgB,cACd,MACA,cACA,aACA,SACM;CACN,MAAM,EAAE,GAAG,GAAG,OAAO,WAAW;CAChC,OAAO,gBAAgB;EAAE;EAAG;EAAG;EAAO;CAAO,GAAG,cAAc,aAAa,OAAO;AACpF;;AAGA,SAAgB,WACd,OACA,MACA,cACmB;CACnB,MAAM,UAAU;EAAE,GAAG,KAAK;EAAG,GAAG,KAAK;EAAG,OAAO,aAAa,QAAQ,KAAK,MAAM;EAAG,QAAQ,aAAa,SAAS,KAAK,MAAM;CAAE;CAC7H,OAAO,aAAa,OAAO,OAAO;AACpC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { effectivePose, isEnvelope } from "../scene/effectivePose.js";
|
|
2
|
+
import { layoutPages, pageOfBounds } from "./pages.js";
|
|
3
|
+
import { RECT_POSE_DESCRIPTOR, poseDescriptorForNode, translatePoseViaDescriptor } from "../geometry/poseDescriptor.js";
|
|
4
|
+
import { carriedDescendants, sceneCarrySource } from "../scene/carryDescendants.js";
|
|
5
|
+
|
|
6
|
+
//#region src/core/pages/pageEdits.ts
|
|
7
|
+
/**
|
|
8
|
+
* A document's pages as a scene document value, and the edits that change
|
|
9
|
+
* them. Each edit moves the nodes on a page by however far the page itself
|
|
10
|
+
* moved, so what is on a page stays where it is on that page.
|
|
11
|
+
*/
|
|
12
|
+
/** The scene document value key a page list lives under (`scene.doc`). */
|
|
13
|
+
var PAGES_DOC_KEY = "core:pages";
|
|
14
|
+
var asAny = (scene) => scene;
|
|
15
|
+
/** The scene's pages doc, or `null` when it has none. */
|
|
16
|
+
function pagesOf(scene) {
|
|
17
|
+
return scene.doc.get(PAGES_DOC_KEY) ?? null;
|
|
18
|
+
}
|
|
19
|
+
/** The scene's pages, placed in world space; empty when it has no pages doc. */
|
|
20
|
+
function placedPagesOf(scene) {
|
|
21
|
+
const doc = pagesOf(scene);
|
|
22
|
+
return doc ? layoutPages(doc.pages, doc.layout) : [];
|
|
23
|
+
}
|
|
24
|
+
/** An id none of `pages` has: `page-1`, `page-2`, and so on. */
|
|
25
|
+
function nextPageId(pages) {
|
|
26
|
+
const taken = new Set(pages.map((p) => p.id));
|
|
27
|
+
let n = 1;
|
|
28
|
+
while (taken.has(`page-${n}`)) n++;
|
|
29
|
+
return `page-${n}`;
|
|
30
|
+
}
|
|
31
|
+
/** Whether `id` draws from other nodes and goes wherever they go. */
|
|
32
|
+
function followsOthers(scene, id) {
|
|
33
|
+
const deps = scene.get(id)?.dependsOn;
|
|
34
|
+
return Array.isArray(deps) && deps.length > 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The root nodes on each placed page, by page id: each root belongs to the
|
|
38
|
+
* page its bounds overlap most (`pageOfBounds`). A root in the gaps belongs to
|
|
39
|
+
* none, and one that derives from other nodes is left out, since it follows
|
|
40
|
+
* them.
|
|
41
|
+
*/
|
|
42
|
+
function pageMembers(scene, placed, descriptor = RECT_POSE_DESCRIPTOR) {
|
|
43
|
+
const s = asAny(scene);
|
|
44
|
+
const out = new Map(placed.map((p) => [p.id, []]));
|
|
45
|
+
for (const id of s.roots) {
|
|
46
|
+
const node = s.get(id);
|
|
47
|
+
if (!node || followsOthers(s, id)) continue;
|
|
48
|
+
const bounds = poseDescriptorForNode(descriptor, node).getBounds(effectivePose(s, node));
|
|
49
|
+
const page = pageOfBounds(placed, bounds);
|
|
50
|
+
if (page) out.get(page.id).push(id);
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function derivesPose(scene, id) {
|
|
55
|
+
const node = scene.get(id);
|
|
56
|
+
return node !== void 0 && isEnvelope(node);
|
|
57
|
+
}
|
|
58
|
+
/** The stored poses that move root `id` and what it carries by `dx`, `dy`: the
|
|
59
|
+
* root, unless its pose derives from its children (then each child moves in
|
|
60
|
+
* its place), and the descendants it carries, less whatever derives its pose. */
|
|
61
|
+
function pageMoveWrites(scene, id, dx, dy, descriptor, out) {
|
|
62
|
+
const node = scene.get(id);
|
|
63
|
+
if (!node || followsOthers(scene, id)) return;
|
|
64
|
+
if (derivesPose(scene, id)) {
|
|
65
|
+
for (const child of scene.childrenOf(id)) pageMoveWrites(scene, child, dx, dy, descriptor, out);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const move = (pose, at) => translatePoseViaDescriptor(pose, dx, dy, poseDescriptorForNode(descriptor, scene.get(at)));
|
|
69
|
+
out.push({
|
|
70
|
+
id,
|
|
71
|
+
pose: move(node.pose, id)
|
|
72
|
+
});
|
|
73
|
+
const carried = carriedDescendants(sceneCarrySource(scene), id, (world, at) => followsOthers(scene, at) || derivesPose(scene, at) ? null : move(world, at));
|
|
74
|
+
for (const [at, pose] of carried) out.push({
|
|
75
|
+
id: at,
|
|
76
|
+
pose
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Replace the scene's pages doc with `next`, moving each page's members by
|
|
81
|
+
* the change in their page's place, all as one undo entry labeled `label`.
|
|
82
|
+
* Members of a page `next` drops are left where they are; `removePage` deletes
|
|
83
|
+
* them first.
|
|
84
|
+
*/
|
|
85
|
+
function setPages(scene, next, label, options = {}) {
|
|
86
|
+
const s = asAny(scene);
|
|
87
|
+
const descriptor = options.descriptor ?? RECT_POSE_DESCRIPTOR;
|
|
88
|
+
const before = placedPagesOf(s);
|
|
89
|
+
const after = new Map(layoutPages(next.pages, next.layout).map((p) => [p.id, p]));
|
|
90
|
+
const members = pageMembers(s, before, descriptor);
|
|
91
|
+
const writes = [];
|
|
92
|
+
for (const page of before) {
|
|
93
|
+
const to = after.get(page.id);
|
|
94
|
+
if (!to) continue;
|
|
95
|
+
const dx = to.x - page.x;
|
|
96
|
+
const dy = to.y - page.y;
|
|
97
|
+
if (dx === 0 && dy === 0) continue;
|
|
98
|
+
for (const root of members.get(page.id) ?? []) pageMoveWrites(s, root, dx, dy, descriptor, writes);
|
|
99
|
+
}
|
|
100
|
+
s.batch(label, () => {
|
|
101
|
+
for (const { id, pose } of writes) s.setPose(id, pose);
|
|
102
|
+
s.doc.set(PAGES_DOC_KEY, next);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function edit(scene, fallback, options, change) {
|
|
106
|
+
const doc = pagesOf(scene) ?? { pages: [] };
|
|
107
|
+
setPages(scene, {
|
|
108
|
+
...doc,
|
|
109
|
+
pages: change([...doc.pages])
|
|
110
|
+
}, options.label ?? fallback, options);
|
|
111
|
+
}
|
|
112
|
+
/** Insert `page` at `index`, by default after the last page. */
|
|
113
|
+
function addPage(scene, page, options = {}) {
|
|
114
|
+
edit(scene, "Add page", options, (pages) => {
|
|
115
|
+
pages.splice(options.index ?? pages.length, 0, page);
|
|
116
|
+
return pages;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** Delete page `id`, what is on it, and every node that derives from that, as one entry. */
|
|
120
|
+
function removePage(scene, id, options = {}) {
|
|
121
|
+
const label = options.label ?? "Delete page";
|
|
122
|
+
const members = pageMembers(scene, placedPagesOf(scene), options.descriptor).get(id) ?? [];
|
|
123
|
+
scene.batch(label, () => {
|
|
124
|
+
if (members.length > 0) scene.removeMany(members);
|
|
125
|
+
edit(scene, label, {
|
|
126
|
+
...options,
|
|
127
|
+
label
|
|
128
|
+
}, (pages) => pages.filter((p) => p.id !== id));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** Move page `id` to `index` in the page order. */
|
|
132
|
+
function movePage(scene, id, index, options = {}) {
|
|
133
|
+
edit(scene, "Move page", options, (pages) => {
|
|
134
|
+
const at = pages.findIndex((p) => p.id === id);
|
|
135
|
+
if (at < 0) return pages;
|
|
136
|
+
const [page] = pages.splice(at, 1);
|
|
137
|
+
pages.splice(Math.max(0, Math.min(index, pages.length)), 0, page);
|
|
138
|
+
return pages;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Give page `id` a new size. Its members keep their places on it; the pages after it shift. */
|
|
142
|
+
function resizePage(scene, id, size, options = {}) {
|
|
143
|
+
edit(scene, "Resize page", options, (pages) => pages.map((p) => p.id === id ? {
|
|
144
|
+
...p,
|
|
145
|
+
width: size.width,
|
|
146
|
+
height: size.height
|
|
147
|
+
} : p));
|
|
148
|
+
}
|
|
149
|
+
/** Rename page `id`; an empty name removes it. */
|
|
150
|
+
function renamePage(scene, id, name, options = {}) {
|
|
151
|
+
edit(scene, "Rename page", options, (pages) => pages.map((p) => {
|
|
152
|
+
if (p.id !== id) return p;
|
|
153
|
+
const { name: _old, ...rest } = p;
|
|
154
|
+
return name === "" ? rest : {
|
|
155
|
+
...rest,
|
|
156
|
+
name
|
|
157
|
+
};
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
//#endregion
|
|
162
|
+
export { PAGES_DOC_KEY, addPage, movePage, nextPageId, pageMembers, pagesOf, placedPagesOf, removePage, renamePage, resizePage, setPages };
|
|
163
|
+
//# sourceMappingURL=pageEdits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageEdits.js","names":[],"sources":["../../../src/core/pages/pageEdits.ts"],"sourcesContent":["/**\n * A document's pages as a scene document value, and the edits that change\n * them. Each edit moves the nodes on a page by however far the page itself\n * moved, so what is on a page stays where it is on that page.\n */\nimport {\n RECT_POSE_DESCRIPTOR, poseDescriptorForNode, translatePoseViaDescriptor, type PoseDescriptor,\n} from '../geometry/poseDescriptor';\nimport { carriedDescendants, sceneCarrySource } from '../scene/carryDescendants';\nimport { effectivePose, isEnvelope } from '../scene/effectivePose';\nimport type { NodeId, Scene } from '../scene/types';\nimport { layoutPages, pageOfBounds, type Page, type PageLayoutOptions, type PlacedPage } from './pages';\n\n/** The document value under {@link PAGES_DOC_KEY}: the pages in order, and how they are laid out. */\nexport interface PagesDoc {\n readonly pages: readonly Page[];\n readonly layout?: PageLayoutOptions;\n}\n\n/** The scene document value key a page list lives under (`scene.doc`). */\nexport const PAGES_DOC_KEY = 'core:pages';\n\n/** Options every page edit takes. */\nexport interface PageEditOptions {\n /** The undo entry's label. */\n label?: string;\n /** How node poses are measured and moved. Default: poses are rects. */\n descriptor?: PoseDescriptor<unknown>;\n}\n\ntype AnyScene = Scene<unknown, string, unknown>;\nconst asAny = <TData, TLayer extends string, TPose>(scene: Scene<TData, TLayer, TPose>) =>\n scene as unknown as AnyScene;\n\n/** The scene's pages doc, or `null` when it has none. */\nexport function pagesOf<TData, TLayer extends string, TPose>(scene: Scene<TData, TLayer, TPose>): PagesDoc | null {\n return scene.doc.get<PagesDoc>(PAGES_DOC_KEY) ?? null;\n}\n\n/** The scene's pages, placed in world space; empty when it has no pages doc. */\nexport function placedPagesOf<TData, TLayer extends string, TPose>(scene: Scene<TData, TLayer, TPose>): PlacedPage[] {\n const doc = pagesOf(scene);\n return doc ? layoutPages(doc.pages, doc.layout) : [];\n}\n\n/** An id none of `pages` has: `page-1`, `page-2`, and so on. */\nexport function nextPageId(pages: readonly Page[]): string {\n const taken = new Set(pages.map((p) => p.id));\n let n = 1;\n while (taken.has(`page-${n}`)) n++;\n return `page-${n}`;\n}\n\n/** Whether `id` draws from other nodes and goes wherever they go. */\nfunction followsOthers(scene: AnyScene, id: NodeId): boolean {\n const deps = scene.get(id)?.dependsOn;\n return Array.isArray(deps) && deps.length > 0;\n}\n\n/**\n * The root nodes on each placed page, by page id: each root belongs to the\n * page its bounds overlap most (`pageOfBounds`). A root in the gaps belongs to\n * none, and one that derives from other nodes is left out, since it follows\n * them.\n */\nexport function pageMembers<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n placed: readonly PlacedPage[],\n descriptor: PoseDescriptor<unknown> = RECT_POSE_DESCRIPTOR as PoseDescriptor<unknown>,\n): Map<string, NodeId[]> {\n const s = asAny(scene);\n const out = new Map<string, NodeId[]>(placed.map((p) => [p.id, []]));\n for (const id of s.roots) {\n const node = s.get(id);\n if (!node || followsOthers(s, id)) continue;\n const bounds = poseDescriptorForNode(descriptor, node).getBounds(effectivePose(s, node));\n const page = pageOfBounds(placed, bounds);\n if (page) out.get(page.id)!.push(id);\n }\n return out;\n}\n\nfunction derivesPose(scene: AnyScene, id: NodeId): boolean {\n const node = scene.get(id);\n return node !== undefined && isEnvelope(node);\n}\n\n/** The stored poses that move root `id` and what it carries by `dx`, `dy`: the\n * root, unless its pose derives from its children (then each child moves in\n * its place), and the descendants it carries, less whatever derives its pose. */\nfunction pageMoveWrites(\n scene: AnyScene,\n id: NodeId,\n dx: number,\n dy: number,\n descriptor: PoseDescriptor<unknown>,\n out: { id: NodeId; pose: unknown }[],\n): void {\n const node = scene.get(id);\n if (!node || followsOthers(scene, id)) return;\n if (derivesPose(scene, id)) {\n for (const child of scene.childrenOf(id)) pageMoveWrites(scene, child, dx, dy, descriptor, out);\n return;\n }\n const move = (pose: unknown, at: NodeId) => translatePoseViaDescriptor(pose, dx, dy, poseDescriptorForNode(descriptor, scene.get(at)!));\n out.push({ id, pose: move(node.pose, id) });\n const carried = carriedDescendants(sceneCarrySource(scene), id, (world, at) => (\n followsOthers(scene, at) || derivesPose(scene, at) ? null : move(world, at)\n ));\n for (const [at, pose] of carried) out.push({ id: at, pose });\n}\n\n/**\n * Replace the scene's pages doc with `next`, moving each page's members by\n * the change in their page's place, all as one undo entry labeled `label`.\n * Members of a page `next` drops are left where they are; `removePage` deletes\n * them first.\n */\nexport function setPages<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n next: PagesDoc,\n label: string,\n options: Pick<PageEditOptions, 'descriptor'> = {},\n): void {\n const s = asAny(scene);\n const descriptor = options.descriptor ?? (RECT_POSE_DESCRIPTOR as PoseDescriptor<unknown>);\n const before = placedPagesOf(s);\n const after = new Map(layoutPages(next.pages, next.layout).map((p) => [p.id, p]));\n const members = pageMembers(s, before, descriptor);\n const writes: { id: NodeId; pose: unknown }[] = [];\n for (const page of before) {\n const to = after.get(page.id);\n if (!to) continue;\n const dx = to.x - page.x;\n const dy = to.y - page.y;\n if (dx === 0 && dy === 0) continue;\n for (const root of members.get(page.id) ?? []) pageMoveWrites(s, root, dx, dy, descriptor, writes);\n }\n s.batch(label, () => {\n for (const { id, pose } of writes) s.setPose(id, pose);\n s.doc.set(PAGES_DOC_KEY, next);\n });\n}\n\nfunction edit<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n fallback: string,\n options: PageEditOptions,\n change: (pages: Page[]) => Page[],\n): void {\n const doc = pagesOf(scene) ?? { pages: [] };\n setPages(scene, { ...doc, pages: change([...doc.pages]) }, options.label ?? fallback, options);\n}\n\n/** Insert `page` at `index`, by default after the last page. */\nexport function addPage<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n page: Page,\n options: PageEditOptions & { index?: number } = {},\n): void {\n edit(scene, 'Add page', options, (pages) => {\n pages.splice(options.index ?? pages.length, 0, page);\n return pages;\n });\n}\n\n/** Delete page `id`, what is on it, and every node that derives from that, as one entry. */\nexport function removePage<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n id: string,\n options: PageEditOptions = {},\n): void {\n const label = options.label ?? 'Delete page';\n const members = pageMembers(scene, placedPagesOf(scene), options.descriptor).get(id) ?? [];\n scene.batch(label, () => {\n if (members.length > 0) scene.removeMany(members);\n edit(scene, label, { ...options, label }, (pages) => pages.filter((p) => p.id !== id));\n });\n}\n\n/** Move page `id` to `index` in the page order. */\nexport function movePage<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n id: string,\n index: number,\n options: PageEditOptions = {},\n): void {\n edit(scene, 'Move page', options, (pages) => {\n const at = pages.findIndex((p) => p.id === id);\n if (at < 0) return pages;\n const [page] = pages.splice(at, 1);\n pages.splice(Math.max(0, Math.min(index, pages.length)), 0, page!);\n return pages;\n });\n}\n\n/** Give page `id` a new size. Its members keep their places on it; the pages after it shift. */\nexport function resizePage<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n id: string,\n size: { readonly width: number; readonly height: number },\n options: PageEditOptions = {},\n): void {\n edit(scene, 'Resize page', options, (pages) =>\n pages.map((p) => (p.id === id ? { ...p, width: size.width, height: size.height } : p)));\n}\n\n/** Rename page `id`; an empty name removes it. */\nexport function renamePage<TData, TLayer extends string, TPose>(\n scene: Scene<TData, TLayer, TPose>,\n id: string,\n name: string,\n options: PageEditOptions = {},\n): void {\n edit(scene, 'Rename page', options, (pages) => pages.map((p) => {\n if (p.id !== id) return p;\n const { name: _old, ...rest } = p;\n return name === '' ? rest : { ...rest, name };\n }));\n}\n"],"mappings":"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"}
|
package/dist/core/pages/pages.js
CHANGED
|
@@ -33,6 +33,10 @@ function layoutPages(pages, options = {}) {
|
|
|
33
33
|
return placed;
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
/** The name page `index` of the page order shows: its own, else "Page" and its place. */
|
|
37
|
+
function pageName(page, index) {
|
|
38
|
+
return page.name ?? `Page ${index + 1}`;
|
|
39
|
+
}
|
|
36
40
|
/** The page under a world point, or `null` between and outside them. A point on an edge is on the page. */
|
|
37
41
|
function pageAt(pages, point) {
|
|
38
42
|
return pageOfBounds(pages, {
|
|
@@ -64,6 +68,31 @@ function pageOfBounds(pages, bounds) {
|
|
|
64
68
|
}
|
|
65
69
|
return best;
|
|
66
70
|
}
|
|
71
|
+
function gap(page, b) {
|
|
72
|
+
const dx = Math.max(page.x - (b.x + b.width), b.x - (page.x + page.width), 0);
|
|
73
|
+
const dy = Math.max(page.y - (b.y + b.height), b.y - (page.y + page.height), 0);
|
|
74
|
+
return Math.hypot(dx, dy);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The page a world-space box is held by: the one it is on (`pageOfBounds`),
|
|
78
|
+
* else the one nearest it by the box-to-box gap, the earlier of two equally
|
|
79
|
+
* near. `null` only with no pages. Used where every object must land on some
|
|
80
|
+
* page, such as an export; `pageOfBounds` stays the rule for what is on one.
|
|
81
|
+
*/
|
|
82
|
+
function pageHolding(pages, bounds) {
|
|
83
|
+
const on = pageOfBounds(pages, bounds);
|
|
84
|
+
if (on !== null) return on;
|
|
85
|
+
let best = null;
|
|
86
|
+
let least = Infinity;
|
|
87
|
+
for (const page of pages) {
|
|
88
|
+
const d = gap(page, bounds);
|
|
89
|
+
if (d < least) {
|
|
90
|
+
best = page;
|
|
91
|
+
least = d;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return best;
|
|
95
|
+
}
|
|
67
96
|
/**
|
|
68
97
|
* The page `step` places along the page order from the one with id `current`:
|
|
69
98
|
* the next slide is `1`, the one before is `-1`. `null` past either end, unless
|
|
@@ -92,5 +121,5 @@ function pagesBounds(pages) {
|
|
|
92
121
|
}
|
|
93
122
|
|
|
94
123
|
//#endregion
|
|
95
|
-
export { adjacentPage, layoutPages, pageAt, pageOfBounds, pagesBounds };
|
|
124
|
+
export { adjacentPage, layoutPages, pageAt, pageHolding, pageName, pageOfBounds, pagesBounds };
|
|
96
125
|
//# sourceMappingURL=pages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.js","names":[],"sources":["../../../src/core/pages/pages.ts"],"sourcesContent":["import type { Bounds } from '@weasel-js/routing';\n\n/** One page of a document: a sheet of a fixed size, in world units. */\nexport interface Page {\n readonly id: string;\n readonly name?: string;\n readonly width: number;\n readonly height: number;\n}\n\n/** A page and where it sits in world space. */\nexport interface PlacedPage extends Page {\n readonly x: number;\n readonly y: number;\n /** Its place in the document's page order. */\n readonly index: number;\n}\n\n/** Options for {@link layoutPages}. */\nexport interface PageLayoutOptions {\n /** Which way the pages run. Default `'row'`. */\n direction?: 'row' | 'column';\n /** World units between neighbors. Default 40. */\n gap?: number;\n /** Where a page sits across the run, against the largest page. Default `'start'`. */\n align?: 'start' | 'center' | 'end';\n /** Where the first page's run starts. Default the world origin. */\n origin?: { readonly x: number; readonly y: number };\n}\n\nconst ALIGN = { start: 0, center: 0.5, end: 1 } as const;\n\n/**\n * Place a document's pages in one world space, in order, so a single scene,\n * view, and history serve all of them. With the defaults the first page's\n * top-left corner is the world origin, where a one-page document's page is.\n * Throws on two pages with one id.\n */\nexport function layoutPages(pages: readonly Page[], options: PageLayoutOptions = {}): PlacedPage[] {\n const { direction = 'row', gap = 40, align = 'start', origin = { x: 0, y: 0 } } = options;\n const row = direction === 'row';\n const across = Math.max(0, ...pages.map((p) => (row ? p.height : p.width)));\n const seen = new Set<string>();\n let along = 0;\n return pages.map((page, index) => {\n if (seen.has(page.id)) throw new Error(`layoutPages: two pages have the id \"${page.id}\"`);\n seen.add(page.id);\n const offset = (across - (row ? page.height : page.width)) * ALIGN[align];\n const placed = {\n ...page,\n x: origin.x + (row ? along : offset),\n y: origin.y + (row ? offset : along),\n index,\n };\n along += (row ? page.width : page.height) + gap;\n return placed;\n });\n}\n\n/** The page under a world point, or `null` between and outside them. A point on an edge is on the page. */\nexport function pageAt(\n pages: readonly PlacedPage[],\n point: { readonly x: number; readonly y: number },\n): PlacedPage | null {\n return pageOfBounds(pages, { x: point.x, y: point.y, width: 0, height: 0 });\n}\n\nfunction overlap(page: PlacedPage, b: Bounds): number | null {\n const w = Math.min(page.x + page.width, b.x + b.width) - Math.max(page.x, b.x);\n const h = Math.min(page.y + page.height, b.y + b.height) - Math.max(page.y, b.y);\n return w < 0 || h < 0 ? null : w * h;\n}\n\n/**\n * The page a world-space box belongs to: the one it overlaps most, the earlier\n * of two it overlaps equally, and `null` when it touches none. This is the\n * rule that says which page an object is on.\n */\nexport function pageOfBounds(pages: readonly PlacedPage[], bounds: Bounds): PlacedPage | null {\n let best: PlacedPage | null = null;\n let most = -1;\n for (const page of pages) {\n const area = overlap(page, bounds);\n if (area !== null && area > most) {\n best = page;\n most = area;\n }\n }\n return best;\n}\n\n/**\n * The page `step` places along the page order from the one with id `current`:\n * the next slide is `1`, the one before is `-1`. `null` past either end, unless\n * `wrap`. With no current page in the list, a step forward starts at the first\n * page and a step back at the last.\n */\nexport function adjacentPage(\n pages: readonly PlacedPage[],\n current: string | null,\n step: number,\n options: { wrap?: boolean } = {},\n): PlacedPage | null {\n const n = pages.length;\n if (n === 0) return null;\n const at = pages.findIndex((p) => p.id === current);\n if (at < 0) return pages[step < 0 ? n - 1 : 0] ?? null;\n const to = at + step;\n return pages[options.wrap ? ((to % n) + n) % n : to] ?? null;\n}\n\n/** The box around every page, or `null` for a document with none. */\nexport function pagesBounds(pages: readonly PlacedPage[]): Bounds | null {\n if (pages.length === 0) return null;\n const x = Math.min(...pages.map((p) => p.x));\n const y = Math.min(...pages.map((p) => p.y));\n return {\n x,\n y,\n width: Math.max(...pages.map((p) => p.x + p.width)) - x,\n height: Math.max(...pages.map((p) => p.y + p.height)) - y,\n };\n}\n"],"mappings":";AA8BA,IAAM,QAAQ;CAAE,OAAO;CAAG,QAAQ;CAAK,KAAK;AAAE;;;;;;;AAQ9C,SAAgB,YAAY,OAAwB,UAA6B,CAAC,GAAiB;CACjG,MAAM,EAAE,YAAY,OAAO,MAAM,IAAI,QAAQ,SAAS,SAAS;EAAE,GAAG;EAAG,GAAG;CAAE,MAAM;CAClF,MAAM,MAAM,cAAc;CAC1B,MAAM,SAAS,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,MAAO,MAAM,EAAE,SAAS,EAAE,KAAM,CAAC;CAC1E,MAAM,uBAAO,IAAI,IAAY;CAC7B,IAAI,QAAQ;CACZ,OAAO,MAAM,KAAK,MAAM,UAAU;EAChC,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,MAAM,IAAI,MAAM,uCAAuC,KAAK,GAAG,EAAE;EACxF,KAAK,IAAI,KAAK,EAAE;EAChB,MAAM,UAAU,UAAU,MAAM,KAAK,SAAS,KAAK,UAAU,MAAM;EACnE,MAAM,SAAS;GACb,GAAG;GACH,GAAG,OAAO,KAAK,MAAM,QAAQ;GAC7B,GAAG,OAAO,KAAK,MAAM,SAAS;GAC9B;EACF;EACA,UAAU,MAAM,KAAK,QAAQ,KAAK,UAAU;EAC5C,OAAO;CACT,CAAC;AACH;;AAGA,SAAgB,OACd,OACA,OACmB;CACnB,OAAO,aAAa,OAAO;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;EAAG,OAAO;EAAG,QAAQ;CAAE,CAAC;AAC5E;AAEA,SAAS,QAAQ,MAAkB,GAA0B;CAC3D,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,EAAE,CAAC;CAC7E,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,QAAQ,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,KAAK,GAAG,EAAE,CAAC;CAC/E,OAAO,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI;AACrC;;;;;;AAOA,SAAgB,aAAa,OAA8B,QAAmC;CAC5F,IAAI,OAA0B;CAC9B,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,OAAO,QAAQ,MAAM,MAAM;EACjC,IAAI,SAAS,QAAQ,OAAO,MAAM;GAChC,OAAO;GACP,OAAO;EACT;CACF;CACA,OAAO;AACT;;;;;;;AAQA,SAAgB,aACd,OACA,SACA,MACA,UAA8B,CAAC,GACZ;CACnB,MAAM,IAAI,MAAM;CAChB,IAAI,MAAM,GAAG,OAAO;CACpB,MAAM,KAAK,MAAM,WAAW,MAAM,EAAE,OAAO,OAAO;CAClD,IAAI,KAAK,GAAG,OAAO,MAAM,OAAO,IAAI,IAAI,IAAI,MAAM;CAClD,MAAM,KAAK,KAAK;CAChB,OAAO,MAAM,QAAQ,QAAS,KAAK,IAAK,KAAK,IAAI,OAAO;AAC1D;;AAGA,SAAgB,YAAY,OAA6C;CACvE,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,IAAI,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;CAC3C,MAAM,IAAI,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;CAC3C,OAAO;EACL;EACA;EACA,OAAO,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI;EACtD,QAAQ,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI;CAC1D;AACF"}
|
|
1
|
+
{"version":3,"file":"pages.js","names":[],"sources":["../../../src/core/pages/pages.ts"],"sourcesContent":["import type { Bounds } from '@weasel-js/routing';\n\n/** One page of a document: a sheet of a fixed size, in world units. */\nexport interface Page {\n readonly id: string;\n readonly name?: string;\n readonly width: number;\n readonly height: number;\n}\n\n/** A page and where it sits in world space. */\nexport interface PlacedPage extends Page {\n readonly x: number;\n readonly y: number;\n /** Its place in the document's page order. */\n readonly index: number;\n}\n\n/** Options for {@link layoutPages}. */\nexport interface PageLayoutOptions {\n /** Which way the pages run. Default `'row'`. */\n direction?: 'row' | 'column';\n /** World units between neighbors. Default 40. */\n gap?: number;\n /** Where a page sits across the run, against the largest page. Default `'start'`. */\n align?: 'start' | 'center' | 'end';\n /** Where the first page's run starts. Default the world origin. */\n origin?: { readonly x: number; readonly y: number };\n}\n\nconst ALIGN = { start: 0, center: 0.5, end: 1 } as const;\n\n/**\n * Place a document's pages in one world space, in order, so a single scene,\n * view, and history serve all of them. With the defaults the first page's\n * top-left corner is the world origin, where a one-page document's page is.\n * Throws on two pages with one id.\n */\nexport function layoutPages(pages: readonly Page[], options: PageLayoutOptions = {}): PlacedPage[] {\n const { direction = 'row', gap = 40, align = 'start', origin = { x: 0, y: 0 } } = options;\n const row = direction === 'row';\n const across = Math.max(0, ...pages.map((p) => (row ? p.height : p.width)));\n const seen = new Set<string>();\n let along = 0;\n return pages.map((page, index) => {\n if (seen.has(page.id)) throw new Error(`layoutPages: two pages have the id \"${page.id}\"`);\n seen.add(page.id);\n const offset = (across - (row ? page.height : page.width)) * ALIGN[align];\n const placed = {\n ...page,\n x: origin.x + (row ? along : offset),\n y: origin.y + (row ? offset : along),\n index,\n };\n along += (row ? page.width : page.height) + gap;\n return placed;\n });\n}\n\n/** The name page `index` of the page order shows: its own, else \"Page\" and its place. */\nexport function pageName(page: { readonly name?: string | undefined }, index: number): string {\n return page.name ?? `Page ${index + 1}`;\n}\n\n/** The page under a world point, or `null` between and outside them. A point on an edge is on the page. */\nexport function pageAt(\n pages: readonly PlacedPage[],\n point: { readonly x: number; readonly y: number },\n): PlacedPage | null {\n return pageOfBounds(pages, { x: point.x, y: point.y, width: 0, height: 0 });\n}\n\nfunction overlap(page: PlacedPage, b: Bounds): number | null {\n const w = Math.min(page.x + page.width, b.x + b.width) - Math.max(page.x, b.x);\n const h = Math.min(page.y + page.height, b.y + b.height) - Math.max(page.y, b.y);\n return w < 0 || h < 0 ? null : w * h;\n}\n\n/**\n * The page a world-space box belongs to: the one it overlaps most, the earlier\n * of two it overlaps equally, and `null` when it touches none. This is the\n * rule that says which page an object is on.\n */\nexport function pageOfBounds(pages: readonly PlacedPage[], bounds: Bounds): PlacedPage | null {\n let best: PlacedPage | null = null;\n let most = -1;\n for (const page of pages) {\n const area = overlap(page, bounds);\n if (area !== null && area > most) {\n best = page;\n most = area;\n }\n }\n return best;\n}\n\nfunction gap(page: PlacedPage, b: Bounds): number {\n const dx = Math.max(page.x - (b.x + b.width), b.x - (page.x + page.width), 0);\n const dy = Math.max(page.y - (b.y + b.height), b.y - (page.y + page.height), 0);\n return Math.hypot(dx, dy);\n}\n\n/**\n * The page a world-space box is held by: the one it is on (`pageOfBounds`),\n * else the one nearest it by the box-to-box gap, the earlier of two equally\n * near. `null` only with no pages. Used where every object must land on some\n * page, such as an export; `pageOfBounds` stays the rule for what is on one.\n */\nexport function pageHolding(pages: readonly PlacedPage[], bounds: Bounds): PlacedPage | null {\n const on = pageOfBounds(pages, bounds);\n if (on !== null) return on;\n let best: PlacedPage | null = null;\n let least = Infinity;\n for (const page of pages) {\n const d = gap(page, bounds);\n if (d < least) {\n best = page;\n least = d;\n }\n }\n return best;\n}\n\n/**\n * The page `step` places along the page order from the one with id `current`:\n * the next slide is `1`, the one before is `-1`. `null` past either end, unless\n * `wrap`. With no current page in the list, a step forward starts at the first\n * page and a step back at the last.\n */\nexport function adjacentPage(\n pages: readonly PlacedPage[],\n current: string | null,\n step: number,\n options: { wrap?: boolean } = {},\n): PlacedPage | null {\n const n = pages.length;\n if (n === 0) return null;\n const at = pages.findIndex((p) => p.id === current);\n if (at < 0) return pages[step < 0 ? n - 1 : 0] ?? null;\n const to = at + step;\n return pages[options.wrap ? ((to % n) + n) % n : to] ?? null;\n}\n\n/** The box around every page, or `null` for a document with none. */\nexport function pagesBounds(pages: readonly PlacedPage[]): Bounds | null {\n if (pages.length === 0) return null;\n const x = Math.min(...pages.map((p) => p.x));\n const y = Math.min(...pages.map((p) => p.y));\n return {\n x,\n y,\n width: Math.max(...pages.map((p) => p.x + p.width)) - x,\n height: Math.max(...pages.map((p) => p.y + p.height)) - y,\n };\n}\n"],"mappings":"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"}
|
|
@@ -202,6 +202,12 @@ function lerpColorArray(from, to, t, space = "rgb") {
|
|
|
202
202
|
}
|
|
203
203
|
return out;
|
|
204
204
|
}
|
|
205
|
+
/** Linear-light channel to sRGB encoding (0..1). Unclamped. */
|
|
206
|
+
function linearToSrgb(c) {
|
|
207
|
+
const a = Math.abs(c);
|
|
208
|
+
const v = a <= .0031308 ? a * 12.92 : 1.055 * Math.pow(a, 1 / 2.4) - .055;
|
|
209
|
+
return c < 0 ? -v : v;
|
|
210
|
+
}
|
|
205
211
|
/** HSL to sRGB. Hue in degrees, saturation, lightness and output all 0..1. */
|
|
206
212
|
function hslToSrgb(h, s, l) {
|
|
207
213
|
if (s === 0) return [
|
|
@@ -240,8 +246,9 @@ function hueToChannel(p, q, t) {
|
|
|
240
246
|
* unitless in the modern syntax); same alpha rules and separator rules
|
|
241
247
|
* as `rgb()`
|
|
242
248
|
* - The 148 CSS named colors plus `transparent`
|
|
249
|
+
* - `color(srgb …)` and `color(srgb-linear …)`; `oklab()` and `oklch()`, clamped into sRGB
|
|
243
250
|
*
|
|
244
|
-
* Not supported: `
|
|
251
|
+
* Not supported: `lab()`, `lch()`, other `color()` spaces, `currentColor`, system
|
|
245
252
|
* colors. Throws on anything unrecognized.
|
|
246
253
|
*
|
|
247
254
|
* Results are cached by input-string identity. Callers MUST treat the
|
|
@@ -271,6 +278,14 @@ function parseColorUncached(input) {
|
|
|
271
278
|
const parsed = parseHslFunction(lower);
|
|
272
279
|
if (parsed) return parsed;
|
|
273
280
|
}
|
|
281
|
+
if (lower.startsWith("color(")) {
|
|
282
|
+
const parsed = parseColorFunction(lower);
|
|
283
|
+
if (parsed) return parsed;
|
|
284
|
+
}
|
|
285
|
+
if (lower.startsWith("ok")) {
|
|
286
|
+
const parsed = parseOkFunction(lower);
|
|
287
|
+
if (parsed) return parsed;
|
|
288
|
+
}
|
|
274
289
|
throw new Error(`parseColor: unrecognized color "${input}"`);
|
|
275
290
|
}
|
|
276
291
|
const RESOLVE_COLOR_CACHE_CAP = 1024;
|
|
@@ -399,7 +414,49 @@ function parseHslFunction(s) {
|
|
|
399
414
|
parseAlpha(channels.alpha)
|
|
400
415
|
];
|
|
401
416
|
}
|
|
402
|
-
/**
|
|
417
|
+
/** `color(srgb …)` or `color(srgb-linear …)`, channels as numbers 0..1 or percents. */
|
|
418
|
+
function parseColorFunction(s) {
|
|
419
|
+
const body = unwrapFn(s, "color");
|
|
420
|
+
const space = body?.match(/^(srgb-linear|srgb)\s+/);
|
|
421
|
+
if (!body || !space || body.includes(",")) return null;
|
|
422
|
+
const channels = splitChannels(body.slice(space[0].length));
|
|
423
|
+
if (!channels) return null;
|
|
424
|
+
const rgb = channels.rgb.map((tok) => parseChannel(tok, 1));
|
|
425
|
+
if (rgb.some((c) => c === null)) return null;
|
|
426
|
+
const [r, g, b] = space[1] === "srgb" ? rgb : rgb.map((c) => linearToSrgb(c));
|
|
427
|
+
return [
|
|
428
|
+
clamp01(r),
|
|
429
|
+
clamp01(g),
|
|
430
|
+
clamp01(b),
|
|
431
|
+
parseAlpha(channels.alpha)
|
|
432
|
+
];
|
|
433
|
+
}
|
|
434
|
+
/** `oklab(L a b)` or `oklch(L C h)`, clamped into sRGB. L is 0..1 or a percent; a, b and C are numbers. */
|
|
435
|
+
function parseOkFunction(s) {
|
|
436
|
+
const lch = unwrapFn(s, "oklch");
|
|
437
|
+
const body = lch ?? unwrapFn(s, "oklab");
|
|
438
|
+
if (body === null || body.includes(",")) return null;
|
|
439
|
+
const channels = splitChannels(body);
|
|
440
|
+
if (!channels) return null;
|
|
441
|
+
const L = parsePercentOrNumber(channels.rgb[0]);
|
|
442
|
+
const second = Number(channels.rgb[1]);
|
|
443
|
+
if (L === null || !Number.isFinite(second)) return null;
|
|
444
|
+
let A = second;
|
|
445
|
+
let B = Number(channels.rgb[2]);
|
|
446
|
+
if (lch !== null) {
|
|
447
|
+
const h = parseHue(channels.rgb[2]);
|
|
448
|
+
if (h === null) return null;
|
|
449
|
+
[, A, B] = oklchToOklab(L, second, h * (Math.PI / 180));
|
|
450
|
+
} else if (!Number.isFinite(B)) return null;
|
|
451
|
+
const [r, g, b] = oklabToLinearSrgb(L, A, B).map((c) => clamp01(linearToSrgb(c)));
|
|
452
|
+
return [
|
|
453
|
+
r,
|
|
454
|
+
g,
|
|
455
|
+
b,
|
|
456
|
+
parseAlpha(channels.alpha)
|
|
457
|
+
];
|
|
458
|
+
}
|
|
459
|
+
/** Parse a hue token:`<number>`, `<number>deg`, `<number>rad`, `<number>grad`, `<number>turn`. Returns degrees 0..360 (modulo). */
|
|
403
460
|
function parseHue(tok) {
|
|
404
461
|
let n;
|
|
405
462
|
if (tok.endsWith("deg")) n = Number(tok.slice(0, -3));
|