@weasel-js/core 1.9.3 → 1.9.4
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 +356 -0
- package/README.md +2 -2
- package/dist/WeaselProvider.js +5 -5
- package/dist/affordances/composeAffordanceLayer.js +10 -20
- package/dist/affordances/composeAffordanceLayer.js.map +1 -1
- package/dist/affordances/cornerResize.js +25 -17
- package/dist/affordances/cornerResize.js.map +1 -1
- package/dist/affordances/hitAffordanceRegions.js +27 -20
- package/dist/affordances/hitAffordanceRegions.js.map +1 -1
- package/dist/affordances/rotationHandle.js +18 -18
- package/dist/affordances/rotationHandle.js.map +1 -1
- package/dist/animation/behaviors/momentum.js +93 -55
- package/dist/animation/behaviors/momentum.js.map +1 -1
- package/dist/animation/loop.js +10 -12
- package/dist/animation/loop.js.map +1 -1
- package/dist/animation/reflow.js +8 -8
- package/dist/animation/reflow.js.map +1 -1
- package/dist/animation/stagger.js +64 -56
- package/dist/animation/stagger.js.map +1 -1
- package/dist/animation/timeline/booking.js +62 -54
- package/dist/animation/timeline/booking.js.map +1 -1
- package/dist/animation/timeline/createTimeline.js +85 -76
- package/dist/animation/timeline/createTimeline.js.map +1 -1
- package/dist/animation/timeline/sampleTrack.js +13 -5
- package/dist/animation/timeline/sampleTrack.js.map +1 -1
- package/dist/animation/useAnimator.js +45 -35
- package/dist/animation/useAnimator.js.map +1 -1
- package/dist/animation/wrappers/animateLifecycle.js +31 -24
- package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
- package/dist/animation/wrappers/animateOnSetPose.js +28 -26
- package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
- package/dist/animation/wrappers/instantPose.js +13 -0
- package/dist/animation/wrappers/instantPose.js.map +1 -0
- package/dist/{poseDescriptor-D-OH-tu5.d.ts → autoPoseDescriptor-Ct7yqivU.d.ts} +28 -3
- package/dist/barrel/chrome.js +16 -0
- package/dist/barrel/input.js +19 -0
- package/dist/barrel/interactions.js +42 -0
- package/dist/barrel/paint.js +18 -0
- package/dist/barrel/paths.js +19 -0
- package/dist/barrel/renderer.js +20 -0
- package/dist/barrel/routing.js +51 -0
- package/dist/barrel/text.js +18 -0
- package/dist/barrel/viewport.js +52 -0
- package/dist/builtins-DPcdghtB.d.ts +1223 -0
- package/dist/canvas/Canvas.js +363 -448
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +164 -165
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/CursorCoordsHud.js +37 -32
- package/dist/canvas/CursorCoordsHud.js.map +1 -1
- package/dist/canvas/DrawCanvas.js +49 -43
- package/dist/canvas/DrawCanvas.js.map +1 -1
- package/dist/canvas/MinimapCanvas.js +26 -25
- package/dist/canvas/MinimapCanvas.js.map +1 -1
- package/dist/canvas/NodeShape.js +59 -377
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/PickHud.js +50 -47
- package/dist/canvas/PickHud.js.map +1 -1
- package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +167 -0
- package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -0
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +13 -13
- package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +67 -0
- package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -0
- package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +16 -0
- package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -0
- package/dist/canvas/SceneCanvas/coordTrace.js +10 -0
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -0
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +112 -70
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js +9 -8
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +1 -0
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/isDev.js +12 -0
- package/dist/canvas/SceneCanvas/isDev.js.map +1 -0
- package/dist/canvas/SceneCanvas/poseGeometry.js +29 -28
- package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
- package/dist/canvas/SceneCanvas/poseRegistrars.js +13 -0
- package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -0
- package/dist/canvas/SceneCanvas/props.js +38 -0
- package/dist/canvas/SceneCanvas/props.js.map +1 -0
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +21 -62
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +46 -48
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +33 -33
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +534 -788
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SceneViewCanvas.js +45 -43
- package/dist/canvas/SceneViewCanvas.js.map +1 -1
- package/dist/canvas/buildSceneLayer.js +91 -0
- package/dist/canvas/buildSceneLayer.js.map +1 -0
- package/dist/canvas/buildSceneTree.js +16 -19
- package/dist/canvas/buildSceneTree.js.map +1 -1
- package/dist/canvas/canvasRenderer.js +68 -52
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/deps/changes.js +13 -0
- package/dist/canvas/deps/changes.js.map +1 -0
- package/dist/canvas/deps/editAnchors.js +28 -28
- package/dist/canvas/deps/insert.js +119 -91
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/slice.js +46 -45
- package/dist/canvas/deps/slice.js.map +1 -1
- package/dist/canvas/deps/textEdit.js +10 -9
- package/dist/canvas/deps/textEdit.js.map +1 -1
- package/dist/canvas/derivedPath.js +46 -23
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/getNodeAtPoint.js +7 -7
- package/dist/canvas/getNodeAtPoint.js.map +1 -1
- package/dist/canvas/hud.module.js +1 -1
- package/dist/canvas/hud.module.js.map +1 -1
- package/dist/canvas/kitRequirements.js +2 -2
- package/dist/canvas/kitRequirements.js.map +1 -1
- package/dist/canvas/layerOrder.js +13 -6
- package/dist/canvas/layerOrder.js.map +1 -1
- package/dist/canvas/minimapMath.js +12 -10
- package/dist/canvas/minimapMath.js.map +1 -1
- package/dist/canvas/nodeShapes/derivedPainter.js +34 -0
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -0
- package/dist/canvas/nodeShapes/imagePainter.js +87 -0
- package/dist/canvas/nodeShapes/imagePainter.js.map +1 -0
- package/dist/canvas/nodeShapes/memo.js +9 -0
- package/dist/canvas/nodeShapes/memo.js.map +1 -0
- package/dist/canvas/nodeShapes/nodePaint.js +57 -0
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -0
- package/dist/canvas/nodeShapes/pathPainter.js +38 -0
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -0
- package/dist/canvas/nodeShapes/poseBox.js +20 -0
- package/dist/canvas/nodeShapes/poseBox.js.map +1 -0
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +38 -0
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -0
- package/dist/canvas/nodeShapes/shapePainter.js +72 -0
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -0
- package/dist/canvas/nodeShapes/textPainter.js +55 -0
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/paintCull.js +10 -11
- package/dist/canvas/paintCull.js.map +1 -1
- package/dist/canvas/pickWalk.js +52 -63
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/poseRotation.js +11 -23
- package/dist/canvas/poseRotation.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +5 -5
- package/dist/canvas/renderSceneToPixels.js +3 -1
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js +66 -148
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneClipboard.js +112 -0
- package/dist/canvas/sceneClipboard.js.map +1 -0
- package/dist/canvas/sceneSlotWiring.js +4 -4
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +39 -40
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/useCanvasRenderer.js +14 -6
- package/dist/canvas/useCanvasRenderer.js.map +1 -1
- package/dist/canvas/useCanvasView.js +58 -0
- package/dist/canvas/useCanvasView.js.map +1 -0
- package/dist/canvas/useFrameLoop.js +35 -26
- package/dist/canvas/useFrameLoop.js.map +1 -1
- package/dist/canvas/useSceneLayerList.js +21 -0
- package/dist/canvas/useSceneLayerList.js.map +1 -0
- package/dist/clipboard.d.ts +10 -6
- package/dist/clone.d.ts +4 -3
- package/dist/core/adapters/arrayAdapter.js +48 -39
- package/dist/core/adapters/arrayAdapter.js.map +1 -1
- package/dist/core/device/index.js +5 -4
- package/dist/core/device/useDeviceProfile.js +38 -44
- package/dist/core/device/useDeviceProfile.js.map +1 -1
- package/dist/core/device/watchDevicePixelRatio.js +17 -0
- package/dist/core/device/watchDevicePixelRatio.js.map +1 -0
- package/dist/core/fillInPoseFrame.js.map +1 -1
- package/dist/core/geometry/poseDescriptor.js +21 -19
- package/dist/core/geometry/poseDescriptor.js.map +1 -1
- package/dist/core/geometry/poseFrame.js +44 -0
- package/dist/core/geometry/poseFrame.js.map +1 -0
- package/dist/core/geometry/poseRotation.js.map +1 -1
- package/dist/core/geometry/regionHit.js +9 -10
- package/dist/core/geometry/regionHit.js.map +1 -1
- package/dist/core/geometry/unionBounds.js +31 -29
- package/dist/core/geometry/unionBounds.js.map +1 -1
- package/dist/core/isPlainObject.js +2 -11
- package/dist/core/ops/arrange.js +1 -0
- package/dist/core/ops/arrange.js.map +1 -1
- package/dist/core/ops/create.js +10 -5
- package/dist/core/ops/create.js.map +1 -1
- package/dist/core/ops/delete.js +12 -24
- package/dist/core/ops/delete.js.map +1 -1
- package/dist/core/ops/reorder/index.js +43 -40
- package/dist/core/ops/reorder/index.js.map +1 -1
- package/dist/core/ops/reorder/setChildOrder.js +34 -0
- package/dist/core/ops/reorder/setChildOrder.js.map +1 -0
- package/dist/core/paintKinds.js +5 -5
- package/dist/core/paintKinds.js.map +1 -1
- package/dist/core/scene/NodeProperties.js.map +1 -1
- package/dist/core/scene/appliedLog.js +37 -0
- package/dist/core/scene/appliedLog.js.map +1 -0
- package/dist/core/scene/arrivalWindow.js +101 -0
- package/dist/core/scene/arrivalWindow.js.map +1 -0
- package/dist/core/scene/derivedPath.js.map +1 -1
- package/dist/core/scene/historyFacade.js +84 -0
- package/dist/core/scene/historyFacade.js.map +1 -0
- package/dist/core/scene/kitOps.js +173 -0
- package/dist/core/scene/kitOps.js.map +1 -0
- package/dist/core/scene/layerStack.js +38 -0
- package/dist/core/scene/layerStack.js.map +1 -0
- package/dist/core/scene/lockGuard.js +37 -0
- package/dist/core/scene/lockGuard.js.map +1 -0
- package/dist/core/scene/nodeFnFields.js +5 -6
- package/dist/core/scene/nodeFnFields.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +45 -19
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/nodeStore.js +126 -0
- package/dist/core/scene/nodeStore.js.map +1 -0
- package/dist/core/scene/pickability.js +6 -0
- package/dist/core/scene/pickability.js.map +1 -0
- package/dist/core/scene/poseFeed.js +38 -38
- package/dist/core/scene/poseFeed.js.map +1 -1
- package/dist/core/scene/poseOverrides.js +34 -38
- package/dist/core/scene/poseOverrides.js.map +1 -1
- package/dist/core/scene/renderOrder.js +84 -0
- package/dist/core/scene/renderOrder.js.map +1 -0
- package/dist/core/scene/scene.js +289 -866
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/serialization.js +68 -0
- package/dist/core/scene/serialization.js.map +1 -0
- package/dist/core/scene/treeOrder.js +13 -0
- package/dist/core/scene/treeOrder.js.map +1 -0
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/viewport/meanScale.js +1 -1
- package/dist/core/viewport/meanScale.js.map +1 -1
- package/dist/core/viewport/view.js +12 -12
- package/dist/core/viewport/view.js.map +1 -1
- package/dist/core/viewport/zoomBounds.js +10 -8
- package/dist/core/viewport/zoomBounds.js.map +1 -1
- package/dist/{cornerHandles-BCrDp_mH.d.ts → cornerHandles-CtCb8a3G.d.ts} +1 -1
- package/dist/debug/createDebugOverlayLayer.js +14 -14
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/flag.js +2 -41
- package/dist/features/chrome-caps/useHoverTracking.js +22 -17
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/focus/gateLayer.js +3 -4
- package/dist/features/focus/gateLayer.js.map +1 -1
- package/dist/features/images/imageCache.js +19 -9
- package/dist/features/images/imageCache.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +14 -11
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/ingestion/index.js +1 -1
- package/dist/features/ingestion/registerKitHandlers.js +7 -7
- package/dist/features/ingestion/weaselJsonHandler.js +17 -14
- package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
- package/dist/features/meshPaint/lazyKind.js +201 -35
- package/dist/features/meshPaint/lazyKind.js.map +1 -1
- package/dist/features/meshPaint/meshPaint.js +82 -79
- package/dist/features/meshPaint/meshPaint.js.map +1 -1
- package/dist/features/minimap/createMinimapContribution.js +42 -42
- package/dist/features/minimap/layers.js +44 -62
- package/dist/features/minimap/layers.js.map +1 -1
- package/dist/features/parallax/createParallaxPlane.js +10 -14
- package/dist/features/parallax/createParallaxPlane.js.map +1 -1
- package/dist/features/paths/anchorEdits.js +19 -8
- package/dist/features/paths/anchorEdits.js.map +1 -1
- package/dist/features/paths/anchors.js +31 -26
- package/dist/features/paths/anchors.js.map +1 -1
- package/dist/features/paths/booleans.js +2 -2
- package/dist/features/paths/index.js +13 -11
- package/dist/features/paths/markerCommands.js +37 -36
- package/dist/features/paths/markerCommands.js.map +1 -1
- package/dist/features/paths/pathInWorld.js +19 -19
- package/dist/features/paths/pathInWorld.js.map +1 -1
- package/dist/features/paths/pathLayer.js.map +1 -1
- package/dist/features/paths/strokeToPath.js +40 -0
- package/dist/features/paths/strokeToPath.js.map +1 -0
- package/dist/features/paths/tessellate/stroke.js.map +1 -1
- package/dist/features/patterns/commandPaint.js +18 -0
- package/dist/features/patterns/commandPaint.js.map +1 -0
- package/dist/features/patterns/index.js +5 -17
- package/dist/features/patterns/index.js.map +1 -1
- package/dist/features/patterns/rasterizeTile.js +17 -0
- package/dist/features/patterns/rasterizeTile.js.map +1 -0
- package/dist/features/patterns/resolveSpec.js +52 -44
- package/dist/features/patterns/resolveSpec.js.map +1 -1
- package/dist/features/poseRun/usePoseRun.js +8 -3
- package/dist/features/poseRun/usePoseRun.js.map +1 -1
- package/dist/features/selection/SelectionContext.js +5 -0
- package/dist/features/selection/SelectionContext.js.map +1 -1
- package/dist/features/selection/overlay.js +18 -18
- package/dist/features/selection/overlay.js.map +1 -1
- package/dist/features/text/domOffsets.js +82 -0
- package/dist/features/text/domOffsets.js.map +1 -0
- package/dist/features/text/domRuns.js +103 -131
- package/dist/features/text/domRuns.js.map +1 -1
- package/dist/features/text/hitTest.js +5 -2
- package/dist/features/text/hitTest.js.map +1 -1
- package/dist/features/text/isTextData.js +8 -0
- package/dist/features/text/isTextData.js.map +1 -0
- package/dist/features/text/overlayDirection.js +15 -0
- package/dist/features/text/overlayDirection.js.map +1 -0
- package/dist/features/text/runs/rangeStyle.js +32 -34
- package/dist/features/text/runs/rangeStyle.js.map +1 -1
- package/dist/features/text/textCommand.js +34 -33
- package/dist/features/text/textCommand.js.map +1 -1
- package/dist/features/text/textToPath.js +40 -40
- package/dist/features/text/textToPath.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +76 -82
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/text/useTextEdit.js +184 -160
- package/dist/features/text/useTextEdit.js.map +1 -1
- package/dist/features/tiling/createTiledLayer.js +24 -22
- package/dist/features/tiling/createTiledLayer.js.map +1 -1
- package/dist/index.d.ts +11033 -7749
- package/dist/index.js +316 -309
- package/dist/input/keyState.js +42 -43
- package/dist/input/keyState.js.map +1 -1
- package/dist/input/useKeyModifiers.js +11 -0
- package/dist/input/useKeyModifiers.js.map +1 -0
- package/dist/interactions/actions/align/align.js +8 -8
- package/dist/interactions/actions/clipboard/clipboardOps.js +34 -32
- package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
- package/dist/interactions/actions/clipboard/materializePaste.js +10 -7
- package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
- package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
- package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +1 -1
- package/dist/interactions/actions/defaultCommitAdapter.js +20 -18
- package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
- package/dist/interactions/actions/defaults/align.js +9 -10
- package/dist/interactions/actions/defaults/align.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +59 -81
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/areaSelect.js +35 -38
- package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
- package/dist/interactions/actions/defaults/clipboard.js +26 -10
- package/dist/interactions/actions/defaults/clipboard.js.map +1 -1
- package/dist/interactions/actions/defaults/clone.js +44 -60
- package/dist/interactions/actions/defaults/clone.js.map +1 -1
- package/dist/interactions/actions/defaults/copySubtree.js +40 -0
- package/dist/interactions/actions/defaults/copySubtree.js.map +1 -0
- package/dist/interactions/actions/defaults/distribute.js +14 -13
- package/dist/interactions/actions/defaults/distribute.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +17 -57
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/editAnchors.js +18 -18
- package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/flip.js +52 -46
- package/dist/interactions/actions/defaults/flip.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +43 -48
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +35 -33
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insert.js +50 -51
- package/dist/interactions/actions/defaults/insert.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -7
- package/dist/interactions/actions/defaults/lassoSelect.js +67 -70
- package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -1
- package/dist/interactions/actions/defaults/move.js +267 -249
- package/dist/interactions/actions/defaults/move.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +40 -68
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/nudgeSteps.js +37 -0
- package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -0
- package/dist/interactions/actions/defaults/reorder.js +2 -0
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/resize.js +104 -98
- package/dist/interactions/actions/defaults/resize.js.map +1 -1
- package/dist/interactions/actions/defaults/rotate.js +111 -110
- package/dist/interactions/actions/defaults/rotate.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +7 -7
- package/dist/interactions/actions/defaults/setFillOpacity.js +4 -4
- package/dist/interactions/actions/defaults/setStroke.js +12 -12
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +6 -6
- package/dist/interactions/actions/defaults/sliceOps.js +19 -19
- package/dist/interactions/actions/defaults/viewportDragPan.js +37 -26
- package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/geometry.js +28 -23
- package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
- package/dist/interactions/actions/flip/helpers.js +30 -17
- package/dist/interactions/actions/flip/helpers.js.map +1 -1
- package/dist/interactions/actions/hitSelection.js +8 -0
- package/dist/interactions/actions/hitSelection.js.map +1 -0
- package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +14 -18
- package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +5 -5
- package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +32 -21
- package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
- package/dist/interactions/actions/move/gestureAdapter.js +32 -15
- package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +33 -0
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -0
- package/dist/interactions/actions/outlines/createOutlines.js +18 -18
- package/dist/interactions/actions/poseDescriptorDep.js +16 -4
- package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
- package/dist/interactions/actions/poseFrame.js +11 -6
- package/dist/interactions/actions/poseFrame.js.map +1 -1
- package/dist/interactions/actions/previewOverrides.js +5 -5
- package/dist/interactions/actions/previewOverrides.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +69 -0
- package/dist/interactions/actions/selectionSubtree.js.map +1 -0
- package/dist/interactions/actions/useStandardActions.js +66 -62
- package/dist/interactions/actions/useStandardActions.js.map +1 -1
- package/dist/interactions/gestures/dragGesture/dragGesture.js +4 -7
- package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
- package/dist/interactions/gestures/dragGesture/dragPointOf.js +23 -0
- package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -0
- package/dist/interactions/gestures/handleDrag/handleDrag.js +21 -26
- package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
- package/dist/interactions/gestures/pointerDrag/pointerDrag.js +8 -6
- package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +8 -4
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
- package/dist/{math-Drrw4ewZ.d.ts → math-J-ACHyEg.d.ts} +1 -2
- package/dist/math.d.ts +2 -3
- package/dist/move.d.ts +12 -11
- package/dist/{originProjection-DEklpDc_.d.ts → originProjection-gHnOup4e.d.ts} +1 -1
- package/dist/{registerProgram-BMZRDgrh.d.ts → registerProgram-T9S_PfAX.d.ts} +18 -7
- package/dist/renderer/DrawCommand.js.map +1 -1
- package/dist/renderer/WeaselRenderer.js +75 -73
- package/dist/renderer/WeaselRenderer.js.map +1 -1
- package/dist/renderer/cache/GLImageCache.js +15 -5
- package/dist/renderer/cache/GLImageCache.js.map +1 -1
- package/dist/renderer/cache/GLMeshCache.js +23 -23
- package/dist/renderer/cache/GLMeshCache.js.map +1 -1
- package/dist/renderer/cache/GLTextureCache.js +18 -1
- package/dist/renderer/cache/GLTextureCache.js.map +1 -1
- package/dist/renderer/cache/cache.js.map +1 -1
- package/dist/renderer/cache/markerCommandCache.js.map +1 -1
- package/dist/renderer/cache/strokeMeshCache.js.map +1 -1
- package/dist/renderer/cullDrawCommands.js +11 -11
- package/dist/renderer/draw/batch.js +133 -0
- package/dist/renderer/draw/batch.js.map +1 -0
- package/dist/renderer/draw/clip.js +89 -0
- package/dist/renderer/draw/clip.js.map +1 -0
- package/dist/renderer/draw/customShader.js +230 -0
- package/dist/renderer/draw/customShader.js.map +1 -0
- package/dist/renderer/draw/drawTriangles.js +8 -0
- package/dist/renderer/draw/drawTriangles.js.map +1 -0
- package/dist/renderer/draw/effects.js +28 -0
- package/dist/renderer/draw/effects.js.map +1 -0
- package/dist/renderer/draw/flushBatch.js +35 -0
- package/dist/renderer/draw/flushBatch.js.map +1 -0
- package/dist/renderer/draw/gradient.js +90 -0
- package/dist/renderer/draw/gradient.js.map +1 -0
- package/dist/renderer/draw/image.js +38 -0
- package/dist/renderer/draw/image.js.map +1 -0
- package/dist/renderer/draw/mesh.js +16 -0
- package/dist/renderer/draw/mesh.js.map +1 -0
- package/dist/renderer/draw/paintBind.js +70 -0
- package/dist/renderer/draw/paintBind.js.map +1 -0
- package/dist/renderer/draw/pathPaint.js +142 -0
- package/dist/renderer/draw/pathPaint.js.map +1 -0
- package/dist/renderer/draw/scratchPass.js +83 -0
- package/dist/renderer/draw/scratchPass.js.map +1 -0
- package/dist/renderer/draw/stencil.js +28 -0
- package/dist/renderer/draw/stencil.js.map +1 -0
- package/dist/renderer/draw/text.js +167 -0
- package/dist/renderer/draw/text.js.map +1 -0
- package/dist/renderer/draw/uniforms.js +77 -0
- package/dist/renderer/draw/uniforms.js.map +1 -0
- package/dist/renderer/draw.js +60 -1116
- package/dist/renderer/draw.js.map +1 -1
- package/dist/renderer/effects/EffectTargets.js +3 -0
- package/dist/renderer/effects/EffectTargets.js.map +1 -1
- package/dist/renderer/effects/composite.js +7 -5
- package/dist/renderer/effects/composite.js.map +1 -1
- package/dist/renderer/index.js +18 -17
- package/dist/renderer/math/color.js +63 -83
- package/dist/renderer/math/color.js.map +1 -1
- package/dist/renderer/math/mat3.js +15 -11
- package/dist/renderer/math/mat3.js.map +1 -1
- package/dist/renderer/math/viewToMat3.js +1 -1
- package/dist/renderer/math/viewToMat3.js.map +1 -1
- package/dist/renderer/shaders/ShaderProgram.js +13 -13
- package/dist/renderer/shaders/ShaderProgram.js.map +1 -1
- package/dist/renderer/shaders/glyphPaint.js +3 -3
- package/dist/renderer/shaders/glyphPaint.js.map +1 -1
- package/dist/renderer/shaders/gradFill.js +2 -1
- package/dist/renderer/shaders/gradFill.js.map +1 -1
- package/dist/renderer/shaders/pathFill.js +2 -1
- package/dist/renderer/shaders/pathFill.js.map +1 -1
- package/dist/renderer/shaders/patternFill.js +2 -1
- package/dist/renderer/shaders/patternFill.js.map +1 -1
- package/dist/renderer/shaders/registerProgram.js.map +1 -1
- package/dist/renderer/strokeLengths.js.map +1 -1
- package/dist/renderer/textures/registerTexture.js +25 -5
- package/dist/renderer/textures/registerTexture.js.map +1 -1
- package/dist/renderer.d.ts +16 -15
- package/dist/renderer.js +17 -16
- package/dist/resize.d.ts +5 -6
- package/dist/resize.js +5 -5
- package/dist/style.css +1 -1
- package/dist/test-hook/install.js +12 -6
- package/dist/test-hook/install.js.map +1 -1
- package/dist/{test-seams-CuIxe0xY.d.ts → test-seams-DM2B87-g.d.ts} +4 -4
- package/dist/test-seams.d.ts +2 -2
- package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +1 -0
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +11 -11
- 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/pen/usePenTool.js +153 -103
- 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 -8
- 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/selectionContributions.js +24 -23
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +51 -48
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/shared/pointerFollower.js +17 -0
- package/dist/tools/builtin/shared/pointerFollower.js.map +1 -0
- package/dist/tools/builtin/slice/useSliceTool.js +49 -54
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +22 -16
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/text/useTextTool.js +1 -0
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/useKeybindings.js +14 -30
- package/dist/tools/useKeybindings.js.map +1 -1
- package/dist/{types-B_9g6hMM.d.ts → types-B4iJRHC3.d.ts} +5 -1
- package/dist/{types-A37hYkeR.d.ts → types-k-5Oqh-U.d.ts} +31 -7
- package/dist/util/color.js +3 -3
- package/dist/util/color.js.map +1 -1
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +20 -18
- package/dist/autoPoseDescriptor-vCdt55xm.d.ts +0 -27
- package/dist/builtins-C-VgUlWI.d.ts +0 -4514
- package/dist/core/isPlainObject.js.map +0 -1
- package/dist/debug/flag.js.map +0 -1
- package/dist/interactions/actions/defaults/freshNodeId.js +0 -10
- package/dist/interactions/actions/defaults/freshNodeId.js.map +0 -1
- package/dist/renderer/shaders/imageFill.js +0 -14
- package/dist/renderer/shaders/imageFill.js.map +0 -1
- package/dist/tools/prefs.js +0 -62
- package/dist/tools/prefs.js.map +0 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { poseRotationOf as e, rotatePathAround as t } from "./poseRotation.js";
|
|
2
|
+
import { invert as n, multiply as r, rotateAboutPoint as i, transformPath as a } from "@weasel-js/geom";
|
|
3
|
+
//#region src/core/geometry/poseFrame.ts
|
|
4
|
+
function o(e) {
|
|
5
|
+
let t = e?.transform;
|
|
6
|
+
return !Array.isArray(t) || t.length !== 4 || t[0] === 1 && t[1] === 0 && t[2] === 0 && t[3] === 1 ? null : t;
|
|
7
|
+
}
|
|
8
|
+
function s(e) {
|
|
9
|
+
let t = e;
|
|
10
|
+
if (!t || t.x == null || t.y == null || t.width == null || t.height == null) return null;
|
|
11
|
+
let n = o(t);
|
|
12
|
+
if (!t.rotation && !n) return null;
|
|
13
|
+
let a = t.x + t.width / 2, s = t.y + t.height / 2;
|
|
14
|
+
if (!n) return i(a, s, t.rotation);
|
|
15
|
+
let [c, l, u, d] = n, f = [
|
|
16
|
+
c,
|
|
17
|
+
l,
|
|
18
|
+
u,
|
|
19
|
+
d,
|
|
20
|
+
a - (c * a + u * s),
|
|
21
|
+
s - (l * a + d * s)
|
|
22
|
+
];
|
|
23
|
+
return t.rotation ? r(i(a, s, t.rotation), f) : f;
|
|
24
|
+
}
|
|
25
|
+
function c(t) {
|
|
26
|
+
if (!o(t)) {
|
|
27
|
+
let n = e(t);
|
|
28
|
+
return n && i(n.cx, n.cy, -n.rotation);
|
|
29
|
+
}
|
|
30
|
+
let r = s(t);
|
|
31
|
+
return r && n(r);
|
|
32
|
+
}
|
|
33
|
+
function l(n, r) {
|
|
34
|
+
if (o(r)) {
|
|
35
|
+
let e = s(r);
|
|
36
|
+
return e ? a(n, e) : n;
|
|
37
|
+
}
|
|
38
|
+
let i = e(r);
|
|
39
|
+
return i ? t(n, i.cx, i.cy, i.rotation) : n;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { l as pathThroughPoseFrame, c as poseFrameInverseOf, s as poseFrameOf, o as poseLinearOf };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=poseFrame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poseFrame.js","names":["poseLinearOf","pose","poseFrameOf","p","linear","cx","cy","rotateAboutPoint","a","b","c","about","multiply","poseFrameInverseOf","r","poseRotationOf","frame","invert","pathThroughPoseFrame","transformPath","path","rotatePathAround"],"sources":["../../../src/core/geometry/poseFrame.ts"],"sourcesContent":["/**\n * The one composition of a box pose into the matrix that carries its own\n * frame to its parent's: the rotation convention of `poseRotationOf`, and the\n * pose's residual `transform` inside it. Painting, culling, silhouettes, and\n * picking all read a pose through `poseFrameOf` so they agree on where the\n * node is.\n */\nimport {\n invert, multiply, rotateAboutPoint, transformPath, type Mat3, type Path,\n} from '@weasel-js/geom';\nimport { poseRotationOf, rotatePathAround } from './poseRotation';\n\n/**\n * The linear part of a box pose that its box, rotation, and flips cannot\n * hold: a skew, or a scale that differs by axis. `[a, b, c, d]` in\n * `Mat3` order (`x' = a·x + c·y`, `y' = b·x + d·y`), applied about the\n * box center to what the node draws in its unrotated box, before the\n * rotation. Absent is the identity.\n *\n * The box, `rotation`, and flips keep their meaning beside it: a node at\n * `(x, y, width, height)` is laid out and painted in that box exactly as it\n * would be without a `transform`, and the result is then taken through\n * `rotate(rotation) · transform` about the box center.\n */\nexport type PoseLinear = readonly [a: number, b: number, c: number, d: number];\n\ninterface FramedBox {\n x: number;\n y: number;\n width: number;\n height: number;\n rotation?: number;\n transform?: PoseLinear;\n}\n\n/** `transform` when it changes anything, `null` for absent or the identity. */\nexport function poseLinearOf(pose: unknown): PoseLinear | null {\n const t = (pose as { transform?: unknown } | null | undefined)?.transform;\n if (!Array.isArray(t) || t.length !== 4) return null;\n if (t[0] === 1 && t[1] === 0 && t[2] === 0 && t[3] === 1) return null;\n return t as unknown as PoseLinear;\n}\n\n/**\n * The matrix taking a point in the pose's own unrotated box frame to where\n * the node draws it: `rotate(rotation) · transform`, about the box center.\n * `null` when the pose has neither, or is not a box, so a caller can skip\n * the step.\n */\nexport function poseFrameOf(pose: unknown): Mat3 | null {\n const p = pose as Partial<FramedBox> | null | undefined;\n if (!p || p.x == null || p.y == null || p.width == null || p.height == null) return null;\n const linear = poseLinearOf(p);\n if (!p.rotation && !linear) return null;\n const cx = p.x + p.width / 2;\n const cy = p.y + p.height / 2;\n if (!linear) return rotateAboutPoint(cx, cy, p.rotation as number);\n const [a, b, c, d] = linear;\n const about: Mat3 = [a, b, c, d, cx - (a * cx + c * cy), cy - (b * cx + d * cy)];\n return p.rotation ? multiply(rotateAboutPoint(cx, cy, p.rotation), about) : about;\n}\n\n/**\n * The inverse of {@link poseFrameOf}: where a parent-frame point falls in the\n * pose's unrotated box frame. `null` when there is no frame to undo, or when\n * the `transform` is singular and nothing maps back.\n */\nexport function poseFrameInverseOf(pose: unknown): Mat3 | null {\n if (!poseLinearOf(pose)) {\n // The same pivot turned back: exact, where inverting the matrix is not.\n const r = poseRotationOf(pose);\n return r && rotateAboutPoint(r.cx, r.cy, -r.rotation);\n }\n const frame = poseFrameOf(pose);\n return frame && invert(frame);\n}\n\n/** `path`, given in the pose's unrotated box frame, as the node draws it. */\nexport function pathThroughPoseFrame(path: Path, pose: unknown): Path {\n if (poseLinearOf(pose)) {\n const frame = poseFrameOf(pose);\n return frame ? transformPath(path, frame) : path;\n }\n const r = poseRotationOf(pose);\n return r ? rotatePathAround(path, r.cx, r.cy, r.rotation) : path;\n}\n"],"mappings":";;;AAoCA,SAAgBA,EAAa,GAAkC;CAC7D,IAAM,IAAKC,GAAqD;CAGhE,OAFI,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,KAClC,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,OAAO,IAAU,OAC1D;AACT;AAQA,SAAgBC,EAAY,GAA4B;CACtD,IAAMC,IAAIF;CACV,IAAI,CAACE,KAAKA,EAAE,KAAK,QAAQA,EAAE,KAAK,QAAQA,EAAE,SAAS,QAAQA,EAAE,UAAU,MAAM,OAAO;CACpF,IAAMC,IAASJ,EAAaG,CAAC;CAC7B,IAAI,CAACA,EAAE,YAAY,CAACC,GAAQ,OAAO;CACnC,IAAMC,IAAKF,EAAE,IAAIA,EAAE,QAAQ,GACrBG,IAAKH,EAAE,IAAIA,EAAE,SAAS;CAC5B,IAAI,CAACC,GAAQ,OAAOG,EAAiBF,GAAIC,GAAIH,EAAE,QAAkB;CACjE,IAAM,CAACK,GAAGC,GAAGC,GAAG,KAAKN,GACfO,IAAc;EAACH;EAAGC;EAAGC;EAAG;EAAGL,KAAMG,IAAIH,IAAKK,IAAIJ;EAAKA,KAAMG,IAAIJ,IAAK,IAAIC;CAAG;CAC/E,OAAOH,EAAE,WAAWS,EAASL,EAAiBF,GAAIC,GAAIH,EAAE,QAAQ,GAAGQ,CAAK,IAAIA;AAC9E;AAOA,SAAgBE,EAAmB,GAA4B;CAC7D,IAAI,CAACb,EAAaC,CAAI,GAAG;EAEvB,IAAMa,IAAIC,EAAed,CAAI;EAC7B,OAAOa,KAAKP,EAAiBO,EAAE,IAAIA,EAAE,IAAI,CAACA,EAAE,QAAQ;CACtD;CACA,IAAME,IAAQd,EAAYD,CAAI;CAC9B,OAAOe,KAASC,EAAOD,CAAK;AAC9B;AAGA,SAAgBE,EAAqB,GAAY,GAAqB;CACpE,IAAIlB,EAAaC,CAAI,GAAG;EACtB,IAAMe,IAAQd,EAAYD,CAAI;EAC9B,OAAOe,IAAQG,EAAcC,GAAMJ,CAAK,IAAII;CAC9C;CACA,IAAMN,IAAIC,EAAed,CAAI;CAC7B,OAAOa,IAAIO,EAAiBD,GAAMN,EAAE,IAAIA,EAAE,IAAIA,EAAE,QAAQ,IAAIM;AAC9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poseRotation.js","names":["poseRotationOf","p","pose","rotatePathAround","path","rotateRectCorners","cx","cy","rotation","rotatePolygon","cos","sin","next","coords","forEachSegment","commands","k","len","pathCommandCoordCount","cmd","dx","ci","dy","rotate","px","py","x0","y0","x","y","x1","y1","w","x2","y2","h","x3","y3","PATH_M","PATH_L","PATH_Z"],"sources":["../../../src/core/geometry/poseRotation.ts"],"sourcesContent":["/**\n * The kit's single encoding of the pose-rotation convention: \"rotate about the\n * pose's unrotated AABB center by `pose.rotation` (radians).\"\n *\n * Every consumer that needs to apply rotation — the render-tree wrap\n * (`canvas/poseRotation.ts`), the world coordinate bake (`pathInWorld`), the\n * silhouette/clip bake (`findShapeSilhouette`), the hit-test inverse\n * (`poseContainsRotated`), and selection chrome — derives its pivot + angle\n * from `poseRotationOf` rather than re-inlining the `if (rotation && x != null\n * …)` gate. If the convention ever changes (different pivot,
|
|
1
|
+
{"version":3,"file":"poseRotation.js","names":["poseRotationOf","p","pose","rotatePathAround","path","rotateRectCorners","cx","cy","rotation","rotatePolygon","cos","sin","next","coords","forEachSegment","commands","k","len","pathCommandCoordCount","cmd","dx","ci","dy","rotate","px","py","x0","y0","x","y","x1","y1","w","x2","y2","h","x3","y3","PATH_M","PATH_L","PATH_Z"],"sources":["../../../src/core/geometry/poseRotation.ts"],"sourcesContent":["/**\n * The kit's single encoding of the pose-rotation convention: \"rotate about the\n * pose's unrotated AABB center by `pose.rotation` (radians).\"\n *\n * Every consumer that needs to apply rotation — the render-tree wrap\n * (`canvas/poseRotation.ts`), the world coordinate bake (`pathInWorld`), the\n * silhouette/clip bake (`findShapeSilhouette`), the hit-test inverse\n * (`poseContainsRotated`), and selection chrome — derives its pivot + angle\n * from `poseRotationOf` rather than re-inlining the `if (rotation && x != null\n * …)` gate. If the convention ever changes (a different pivot, say), it\n * changes here.\n *\n * A pose may also carry a `transform` inside the rotation. `poseFrameOf`\n * (`./poseFrame`) composes the two, and is what a reader that draws, bounds,\n * or picks the node wants; this module is the angle and pivot alone.\n *\n * Lives in `core/geometry` so `core/`'s own adapters can bake rotation too.\n */\nimport {\n forEachSegment,\n pathCommandCoordCount,\n PATH_L,\n PATH_M,\n PATH_Z,\n type Path,\n type PolygonPath,\n} from '@weasel-js/geom';\n\n/** Pivot (`cx`, `cy`) and angle resolved from a pose's rotation convention. */\nexport interface PoseRotation {\n cx: number;\n cy: number;\n rotation: number;\n}\n\n/**\n * Resolve a pose's rotation transform, or `null` when the pose carries no\n * effective rotation. Non-null requires a nonzero `rotation` **and** all four\n * AABB fields (`x`, `y`, `width`, `height`) — the pivot is the unrotated AABB\n * center. Poses missing any AABB field (e.g. a bare polygon pose) or with\n * zero/absent rotation return `null`, so callers can treat `null` as \"draw /\n * hit / clip in the local frame, no rotation step.\"\n */\nexport function poseRotationOf(pose: unknown): PoseRotation | null {\n const p = pose as Partial<{ x: number; y: number; width: number; height: number; rotation: number }>;\n if (p.rotation && p.x != null && p.y != null && p.width != null && p.height != null) {\n return { cx: p.x + p.width / 2, cy: p.y + p.height / 2, rotation: p.rotation };\n }\n return null;\n}\n\n/**\n * Rotate every coordinate of `path` about `(cx, cy)` by `rotation` radians.\n * A `rect` promotes to a four-corner polygon (axis-aligned rects can't encode\n * rotation); a polygon keeps its command list and rotates each coord. Returns\n * a fresh `PolygonPath`; never mutates the input. This is the coordinate-baking\n * companion to `poseRotationOf` — `pathInWorld` and `findShapeSilhouette` both\n * apply it so they share one rotation implementation.\n */\nexport function rotatePathAround(path: Path, cx: number, cy: number, rotation: number): PolygonPath {\n if (path.kind === 'rect') {\n return rotateRectCorners(path.x, path.y, path.width, path.height, cx, cy, rotation);\n }\n return rotatePolygon(path, cx, cy, rotation);\n}\n\nfunction rotatePolygon(path: PolygonPath, cx: number, cy: number, rotation: number): PolygonPath {\n const cos = Math.cos(rotation);\n const sin = Math.sin(rotation);\n const { commands, coords } = path;\n const next = new Float32Array(coords.length);\n forEachSegment(commands, coords, (cmd, ci) => {\n for (let k = 0, len = pathCommandCoordCount(cmd); k < len; k += 2) {\n const dx = coords[ci + k] - cx;\n const dy = coords[ci + k + 1] - cy;\n next[ci + k] = cx + dx * cos - dy * sin;\n next[ci + k + 1] = cy + dx * sin + dy * cos;\n }\n });\n return { kind: 'polygon', commands: path.commands, coords: next, fillRule: path.fillRule };\n}\n\nfunction rotateRectCorners(\n x: number, y: number, w: number, h: number,\n cx: number, cy: number, rotation: number,\n): PolygonPath {\n const cos = Math.cos(rotation);\n const sin = Math.sin(rotation);\n const rotate = (px: number, py: number): [number, number] => {\n const dx = px - cx;\n const dy = py - cy;\n return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];\n };\n const [x0, y0] = rotate(x, y);\n const [x1, y1] = rotate(x + w, y);\n const [x2, y2] = rotate(x + w, y + h);\n const [x3, y3] = rotate(x, y + h);\n // M, L, L, L, Z\n const commands = new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]);\n const coords = new Float32Array([x0, y0, x1, y1, x2, y2, x3, y3]);\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n"],"mappings":";;AA2CA,SAAgBA,EAAe,GAAoC;CACjE,IAAMC,IAAIC;CAIV,OAHID,EAAE,YAAYA,EAAE,KAAK,QAAQA,EAAE,KAAK,QAAQA,EAAE,SAAS,QAAQA,EAAE,UAAU,OACtE;EAAE,IAAIA,EAAE,IAAIA,EAAE,QAAQ;EAAG,IAAIA,EAAE,IAAIA,EAAE,SAAS;EAAG,UAAUA,EAAE;CAAS,IAExE;AACT;AAUA,SAAgBE,EAAiB,GAAY,GAAY,GAAY,GAA+B;CAIlG,OAHIC,EAAK,SAAS,SACTC,EAAkBD,EAAK,GAAGA,EAAK,GAAGA,EAAK,OAAOA,EAAK,QAAQE,GAAIC,GAAIC,CAAQ,IAE7EC,EAAcL,GAAME,GAAIC,GAAIC,CAAQ;AAC7C;AAEA,SAASC,EAAc,GAAmB,GAAY,GAAY,GAA+B;CAC/F,IAAMC,IAAM,KAAK,IAAIF,CAAQ,GACvBG,IAAM,KAAK,IAAIH,CAAQ,GACvB,EAAE,aAAU,cAAWJ,GACvBQ,IAAO,IAAI,aAAaC,EAAO,MAAM;CAS3C,OARAC,EAAeC,GAAUF,IAAS,GAAK,MAAO;EAC5C,KAAK,IAAIG,IAAI,GAAGC,IAAMC,EAAsBC,CAAG,GAAGH,IAAIC,GAAK,KAAK,GAAG;GACjE,IAAMG,IAAKP,EAAOQ,IAAKL,KAAKV,GACtBgB,IAAKT,EAAOQ,IAAKL,IAAI,KAAKT;GAEhC,AADA,EAAKc,IAAKL,KAAKV,IAAKc,IAAKV,IAAMY,IAAKX,GACpC,EAAKU,IAAKL,IAAI,KAAKT,IAAKa,IAAKT,IAAMW,IAAKZ;EAC1C;CACF,CAAC,GACM;EAAE,MAAM;EAAW,UAAUN,EAAK;EAAU,QAAQQ;EAAM,UAAUR,EAAK;CAAS;AAC3F;AAEA,SAASC,EACP,GAAW,GAAW,GAAW,GACjC,GAAY,GAAY,GACX;CACb,IAAMK,IAAM,KAAK,IAAIF,CAAQ,GACvBG,IAAM,KAAK,IAAIH,CAAQ,GACvBe,KAAU,GAAY,MAAiC;EAC3D,IAAMH,IAAKI,IAAKlB,GACVgB,IAAKG,IAAKlB;EAChB,OAAO,CAACD,IAAKc,IAAKV,IAAMY,IAAKX,GAAKJ,IAAKa,IAAKT,IAAMW,IAAKZ,CAAG;CAC5D,GACM,CAACgB,GAAIC,KAAMJ,EAAOK,GAAGC,CAAC,GACtB,CAACC,GAAIC,KAAMR,EAAOK,IAAII,GAAGH,CAAC,GAC1B,CAACI,GAAIC,KAAMX,EAAOK,IAAII,GAAGH,IAAIM,CAAC,GAC9B,CAACC,GAAIC,KAAMd,EAAOK,GAAGC,IAAIM,CAAC;CAIhC,OAAO;EAAE,MAAM;EAAW,UAAA,IAFL,WAAW;GAACG;GAAQC;GAAQA;GAAQA;GAAQC;EAAM,CAE7C;EAAU,QAAA,IADjB,aAAa;GAACd;GAAIC;GAAIG;GAAIC;GAAIE;GAAIC;GAAIE;GAAIC;EAAE,CAC3B;EAAQ,UAAU;CAAU;AAClE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { nodeMemo as e } from "../scene/nodeMemo.js";
|
|
2
|
-
import {
|
|
2
|
+
import { pathThroughPoseFrame as t, poseFrameOf as n } from "./poseFrame.js";
|
|
3
3
|
import { visualBoundsViaDescriptor as r } from "./poseDescriptor.js";
|
|
4
4
|
import { boxContainsBox as i, pointInPolygon as a, polygonContainsPath as o, polygonIntersectsPath as s } from "@weasel-js/geom";
|
|
5
5
|
//#region src/core/geometry/regionHit.ts
|
|
@@ -55,16 +55,15 @@ function f(t, n, i) {
|
|
|
55
55
|
return d(n) ? e(t, "aabb", n, () => i.getBounds(n)) : r(n, i);
|
|
56
56
|
}
|
|
57
57
|
function p(e, r) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return n({
|
|
58
|
+
if (n(e)) {
|
|
59
|
+
let n = e;
|
|
60
|
+
return t({
|
|
62
61
|
kind: "rect",
|
|
63
|
-
x:
|
|
64
|
-
y:
|
|
65
|
-
width:
|
|
66
|
-
height:
|
|
67
|
-
},
|
|
62
|
+
x: n.x,
|
|
63
|
+
y: n.y,
|
|
64
|
+
width: n.width,
|
|
65
|
+
height: n.height
|
|
66
|
+
}, e);
|
|
68
67
|
}
|
|
69
68
|
return {
|
|
70
69
|
kind: "rect",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"regionHit.js","names":["rectRegion","w","h","r","regionOf","x","y","verts","flat","minX","minY","maxX","maxY","i","coords","bounds","polygonRegion","polygon","p","isSilhouettePose","pose","regionBoundsOf","nodeMemo","node","g","visualBoundsViaDescriptor","poseOutline","
|
|
1
|
+
{"version":3,"file":"regionHit.js","names":["rectRegion","w","h","r","regionOf","x","y","verts","flat","minX","minY","maxX","maxY","i","coords","bounds","polygonRegion","polygon","p","isSilhouettePose","pose","regionBoundsOf","nodeMemo","node","g","visualBoundsViaDescriptor","poseOutline","poseFrameOf","pathThroughPoseFrame","b","regionTakes","ab","region","mode","pointInPolygon","inBox","boxContainsBox","silhouette","polygonContainsPath","outline","polygonIntersectsPath","drawn"],"sources":["../../../src/core/geometry/regionHit.ts"],"sourcesContent":["/**\n * Whether a marquee or a lasso takes one node: the per-node decision shared by\n * `sceneToAdapter` (through `canvas/deps/hitTestArea`) and `arrayAdapter`.\n *\n * What a node draws is not knowable here — the painters sit above `core/` — so\n * the caller hands in the node's outline as a thunk, asked for only when the\n * bounds cannot decide. A pose that is itself a polygon path is its own\n * outline and never asks.\n */\nimport {\n boxContainsBox,\n pointInPolygon,\n polygonContainsPath,\n polygonIntersectsPath,\n type Path,\n type PolygonPath,\n} from '@weasel-js/geom';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport type { LassoHitMode } from 'core/adapters/types';\nimport { nodeMemo } from 'core/scene/nodeMemo';\nimport type { Vec2 } from './vec2';\nimport { pathThroughPoseFrame, poseFrameOf } from './poseFrame';\nimport { visualBoundsViaDescriptor, type PoseDescriptor } from './poseDescriptor';\n\n/** A closed selection area: a marquee rect or a lasso polygon. */\nexport interface SelectRegion {\n /** The area's vertices; the closing edge back to the first is implicit. */\n readonly verts: readonly Vec2[];\n /** `verts` interleaved as `[x0, y0, x1, y1, …]`. */\n readonly coords: readonly number[];\n readonly bounds: Bounds;\n /** True when the area is its own bounding rect, so a node inside `bounds`\n * is inside the area without further work. Never true for a lasso: a node\n * inside the hull's box can still miss the hull. */\n readonly isRect: boolean;\n}\n\n/** A marquee's region. */\nexport function rectRegion(r: Bounds): SelectRegion {\n const { x, y, width: w, height: h } = r;\n return regionOf([x, y, x + w, y, x + w, y + h, x, y + h], { x, y, width: w, height: h }, true)!;\n}\n\n/** A region from interleaved coords. `bounds` is derived when omitted; `null`\n * when there are no coords to bound. */\nexport function regionOf(\n coords: ArrayLike<number>,\n bounds?: Bounds,\n isRect = false,\n): SelectRegion | null {\n const verts: Vec2[] = [];\n const flat: number[] = [];\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i + 1 < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n verts.push({ x, y });\n flat.push(x, y);\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n if (verts.length === 0) return null;\n return {\n verts,\n coords: flat,\n bounds: bounds ?? { x: minX, y: minY, width: maxX - minX, height: maxY - minY },\n isRect,\n };\n}\n\n/** A lasso's region, or `null` for fewer than three vertices. */\nexport function polygonRegion(polygon: ReadonlyArray<Vec2>): SelectRegion | null {\n if (polygon.length < 3) return null;\n const coords: number[] = [];\n for (const p of polygon) coords.push(p.x, p.y);\n return regionOf(coords);\n}\n\n/** A pose that is its own drawn outline. */\nexport function isSilhouettePose(pose: unknown): pose is PolygonPath {\n return pose !== null && typeof pose === 'object' && (pose as Path).kind === 'polygon';\n}\n\n/**\n * The box a region fast-rejects a node against: a silhouette pose's own bounds,\n * else the pose's visual bounds — which for a rotated pose is the box of its\n * rotated ink, reaching past the pose box. `g` is the node's descriptor.\n */\nexport function regionBoundsOf(node: object, pose: unknown, g: PoseDescriptor<unknown>): Bounds {\n // Memo is silhouettes-only: a rect pose's bounds are the pose itself, and\n // memoizing it costs more than it saves. The result may be shared; never mutate it.\n return isSilhouettePose(pose)\n ? nodeMemo(node, 'aabb', pose, () => g.getBounds(pose))\n : visualBoundsViaDescriptor(pose, g);\n}\n\n/** The outline of a node nothing paints: its pose rect through the pose's\n * frame, else its visual bounds `b`. */\nexport function poseOutline(pose: unknown, b: Bounds): Path {\n if (poseFrameOf(pose)) {\n const p = pose as Bounds;\n return pathThroughPoseFrame({ kind: 'rect', x: p.x, y: p.y, width: p.width, height: p.height }, pose);\n }\n return { kind: 'rect', x: b.x, y: b.y, width: b.width, height: b.height };\n}\n\n/**\n * Whether `region` takes a node under `mode`, given its pose, its bounds `b`\n * from {@link regionBoundsOf}, and its drawn outline on demand.\n *\n * - `intersect` — the outline meets the region anywhere.\n * - `enclosed` — the whole outline lies inside it.\n * - `centers` — the center of `b` lies inside it.\n *\n * A node without finite bounds is never taken.\n */\nexport function regionTakes(\n region: SelectRegion,\n mode: LassoHitMode,\n pose: unknown,\n b: Bounds,\n outline: () => Path,\n): boolean {\n if (\n !Number.isFinite(b.x) || !Number.isFinite(b.y) ||\n !Number.isFinite(b.width) || !Number.isFinite(b.height)\n ) {\n return false;\n }\n const ab = region.bounds;\n if (\n b.x >= ab.x + ab.width || b.x + b.width <= ab.x ||\n b.y >= ab.y + ab.height || b.y + b.height <= ab.y\n ) {\n return false;\n }\n if (mode === 'centers') {\n return pointInPolygon(region.coords, b.x + b.width / 2, b.y + b.height / 2);\n }\n const inBox = boxContainsBox(\n [ab.x, ab.y, ab.x + ab.width, ab.y + ab.height],\n [b.x, b.y, b.x + b.width, b.y + b.height],\n );\n const silhouette = isSilhouettePose(pose);\n if (mode === 'enclosed') {\n // A node sticking out of the region's box cannot be inside the region.\n if (!inBox) return false;\n return polygonContainsPath(region.verts, silhouette ? pose : outline());\n }\n // Swallowed whole by a marquee: no outline can change the answer.\n if (region.isRect && inBox) return true;\n if (silhouette) return polygonIntersectsPath(region.verts, pose);\n const drawn = outline();\n // An axis-aligned rect overlapping a marquee's box already meets it.\n if (drawn.kind === 'rect' && region.isRect) return true;\n return polygonIntersectsPath(region.verts, drawn);\n}\n"],"mappings":";;;;;AAsCA,SAAgBA,EAAW,GAAyB;CAClD,IAAM,EAAE,MAAG,MAAG,OAAOC,GAAG,QAAQC,MAAMC;CACtC,OAAOC,EAAS;EAACC;EAAGC;EAAGD,IAAIJ;EAAGK;EAAGD,IAAIJ;EAAGK,IAAIJ;EAAGG;EAAGC,IAAIJ;CAAC,GAAG;EAAE;EAAG;EAAG,OAAOD;EAAG,QAAQC;CAAE,GAAG,EAAI;AAC/F;AAIA,SAAgBE,EACd,GACA,GACA,IAAS,IACY;CACrB,IAAMG,IAAgB,CAAC,GACjBC,IAAiB,CAAC,GACpBC,IAAO,UAAUC,IAAO,UAAUC,IAAO,WAAWC,IAAO;CAC/D,KAAK,IAAIC,IAAI,GAAGA,IAAI,IAAIC,EAAO,QAAQ,KAAK,GAAG;EAC7C,IAAMT,IAAIS,EAAOD,IAAIP,IAAIQ,EAAOD,IAAI;EAMpC,AALAN,EAAM,KAAK;GAAE;GAAG;EAAE,CAAC,GACnBC,EAAK,KAAKH,GAAGC,CAAC,GACVD,IAAII,MAAM,IAAOJ,IACjBC,IAAII,MAAM,IAAOJ,IACjBD,IAAIM,MAAM,IAAON,IACjBC,IAAIM,MAAM,IAAON;CACvB;CAEA,OADIC,EAAM,WAAW,IAAU,OACxB;EACL;EACA,QAAQC;EACR,QAAQO,KAAU;GAAE,GAAGN;GAAM,GAAGC;GAAM,OAAOC,IAAOF;GAAM,QAAQG,IAAOF;EAAK;EAC9E;CACF;AACF;AAGA,SAAgBM,EAAc,GAAmD;CAC/E,IAAIC,EAAQ,SAAS,GAAG,OAAO;CAC/B,IAAMH,IAAmB,CAAC;CAC1B,KAAK,IAAMI,KAAKD,GAAS,EAAO,KAAKC,EAAE,GAAGA,EAAE,CAAC;CAC7C,OAAOd,EAASU,CAAM;AACxB;AAGA,SAAgBK,EAAiB,GAAoC;CACnE,OAAwB,OAAOC,KAAS,cAAjCA,KAA8CA,EAAc,SAAS;AAC9E;AAOA,SAAgBC,EAAe,GAAc,GAAe,GAAoC;CAG9F,OAAOF,EAAiBC,CAAI,IACxBE,EAASC,GAAM,QAAQH,SAAYI,EAAE,UAAUJ,CAAI,CAAC,IACpDK,EAA0BL,GAAMI,CAAC;AACvC;AAIA,SAAgBE,EAAY,GAAe,GAAiB;CAC1D,IAAIC,EAAYP,CAAI,GAAG;EACrB,IAAMF,IAAIE;EACV,OAAOQ,EAAqB;GAAE,MAAM;GAAQ,GAAGV,EAAE;GAAG,GAAGA,EAAE;GAAG,OAAOA,EAAE;GAAO,QAAQA,EAAE;EAAO,GAAGE,CAAI;CACtG;CACA,OAAO;EAAE,MAAM;EAAQ,GAAGS,EAAE;EAAG,GAAGA,EAAE;EAAG,OAAOA,EAAE;EAAO,QAAQA,EAAE;CAAO;AAC1E;AAYA,SAAgBC,EACd,GACA,GACA,GACA,GACA,GACS;CACT,IACE,CAAC,OAAO,SAASD,EAAE,CAAC,KAAK,CAAC,OAAO,SAASA,EAAE,CAAC,KAC7C,CAAC,OAAO,SAASA,EAAE,KAAK,KAAK,CAAC,OAAO,SAASA,EAAE,MAAM,GAEtD,OAAO;CAET,IAAME,IAAKC,EAAO;CAClB,IACEH,EAAE,KAAKE,EAAG,IAAIA,EAAG,SAASF,EAAE,IAAIA,EAAE,SAASE,EAAG,KAC9CF,EAAE,KAAKE,EAAG,IAAIA,EAAG,UAAUF,EAAE,IAAIA,EAAE,UAAUE,EAAG,GAEhD,OAAO;CAET,IAAIE,MAAS,WACX,OAAOC,EAAeF,EAAO,QAAQH,EAAE,IAAIA,EAAE,QAAQ,GAAGA,EAAE,IAAIA,EAAE,SAAS,CAAC;CAE5E,IAAMM,IAAQC,EACZ;EAACL,EAAG;EAAGA,EAAG;EAAGA,EAAG,IAAIA,EAAG;EAAOA,EAAG,IAAIA,EAAG;CAAM,GAC9C;EAACF,EAAE;EAAGA,EAAE;EAAGA,EAAE,IAAIA,EAAE;EAAOA,EAAE,IAAIA,EAAE;CAAM,CAC1C,GACMQ,IAAalB,EAAiBC,CAAI;CACxC,IAAIa,MAAS,YAGX,OADKE,IACEG,EAAoBN,EAAO,OAAOK,IAAajB,IAAOmB,EAAQ,CAAC,IADnD;CAIrB,IAAIP,EAAO,UAAUG,GAAO,OAAO;CACnC,IAAIE,GAAY,OAAOG,EAAsBR,EAAO,OAAOZ,CAAI;CAC/D,IAAMqB,IAAQF,EAAQ;CAGtB,OADIE,EAAM,SAAS,UAAUT,EAAO,SAAe,KAC5CQ,EAAsBR,EAAO,OAAOS,CAAK;AAClD"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { poseFrameOf as e } from "./poseFrame.js";
|
|
2
|
+
import { applyToPoint as t } from "@weasel-js/geom";
|
|
1
3
|
//#region src/core/geometry/unionBounds.ts
|
|
2
|
-
function
|
|
4
|
+
function n(e) {
|
|
3
5
|
let t = Infinity, n = Infinity, r = -Infinity, i = -Infinity, a = !1;
|
|
4
6
|
for (let o of e) {
|
|
5
7
|
a = !0, o.x < t && (t = o.x), o.y < n && (n = o.y);
|
|
@@ -13,48 +15,48 @@ function e(e) {
|
|
|
13
15
|
height: i - n
|
|
14
16
|
} : null;
|
|
15
17
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
-
if (!
|
|
19
|
-
x:
|
|
20
|
-
y:
|
|
21
|
-
width:
|
|
22
|
-
height:
|
|
18
|
+
function r(n) {
|
|
19
|
+
let r = e(n);
|
|
20
|
+
if (!r) return {
|
|
21
|
+
x: n.x,
|
|
22
|
+
y: n.y,
|
|
23
|
+
width: n.width,
|
|
24
|
+
height: n.height
|
|
23
25
|
};
|
|
24
|
-
let
|
|
25
|
-
[
|
|
26
|
-
[
|
|
27
|
-
[
|
|
28
|
-
[
|
|
26
|
+
let i = Infinity, a = Infinity, o = -Infinity, s = -Infinity, c = [
|
|
27
|
+
[n.x, n.y],
|
|
28
|
+
[n.x + n.width, n.y],
|
|
29
|
+
[n.x + n.width, n.y + n.height],
|
|
30
|
+
[n.x, n.y + n.height]
|
|
29
31
|
];
|
|
30
|
-
for (let [e,
|
|
31
|
-
let
|
|
32
|
-
|
|
32
|
+
for (let [e, n] of c) {
|
|
33
|
+
let [c, l] = t(r, e, n);
|
|
34
|
+
c < i && (i = c), c > o && (o = c), l < a && (a = l), l > s && (s = l);
|
|
33
35
|
}
|
|
34
36
|
return {
|
|
35
|
-
x:
|
|
36
|
-
y:
|
|
37
|
-
width:
|
|
38
|
-
height:
|
|
37
|
+
x: i,
|
|
38
|
+
y: a,
|
|
39
|
+
width: o - i,
|
|
40
|
+
height: s - a
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
|
-
function
|
|
42
|
-
let
|
|
43
|
+
function i(e) {
|
|
44
|
+
let t = Infinity, n = Infinity, i = -Infinity, a = -Infinity, o = !1;
|
|
43
45
|
for (let s of e) {
|
|
44
46
|
if (!s) continue;
|
|
45
|
-
let e =
|
|
46
|
-
o = !0, e.x <
|
|
47
|
+
let e = r(s);
|
|
48
|
+
o = !0, e.x < t && (t = e.x), e.y < n && (n = e.y);
|
|
47
49
|
let c = e.x + e.width, l = e.y + e.height;
|
|
48
50
|
c > i && (i = c), l > a && (a = l);
|
|
49
51
|
}
|
|
50
52
|
return o ? {
|
|
51
|
-
x:
|
|
52
|
-
y:
|
|
53
|
-
width: i -
|
|
54
|
-
height: a -
|
|
53
|
+
x: t,
|
|
54
|
+
y: n,
|
|
55
|
+
width: i - t,
|
|
56
|
+
height: a - n
|
|
55
57
|
} : null;
|
|
56
58
|
}
|
|
57
59
|
//#endregion
|
|
58
|
-
export {
|
|
60
|
+
export { r as axisAlignedBounds, i as unionAABB, n as unionBounds };
|
|
59
61
|
|
|
60
62
|
//# sourceMappingURL=unionBounds.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unionBounds.js","names":["unionBounds","minX","minY","maxX","maxY","any","p","poses","right","bottom","axisAlignedBounds","
|
|
1
|
+
{"version":3,"file":"unionBounds.js","names":["unionBounds","minX","minY","maxX","maxY","any","p","poses","right","bottom","axisAlignedBounds","frame","poseFrameOf","b","corners","px","py","rx","ry","applyToPoint","unionAABB","part","parts"],"sources":["../../../src/core/geometry/unionBounds.ts"],"sourcesContent":["/**\n * Union math over rect-shaped poses.\n *\n * Two answers, deliberately distinct. `unionBounds` folds the *unrotated*\n * boxes and is what commit-time actions want, because they go on to write\n * poses back in that same frame. `unionAABB` expands each rotated member to\n * the extent of its ink first, and is what anything a user looks at or clicks\n * wants — selection chrome, gesture bounds, an export viewBox. Folding the\n * unrotated box there under-reports the extent of a rotated member exactly\n * when the consumer is watching it move.\n */\n\nimport { applyToPoint } from '@weasel-js/geom';\nimport type { RectPose } from 'core/scene/types';\nimport { poseFrameOf } from './poseFrame';\nexport type { RectPose };\n\n/** Compute the AABB envelope of a set of rect-shaped poses, ignoring any\n * rotation they carry. See the module docstring before reaching for this\n * over {@link unionAABB}. */\nexport function unionBounds<TPose extends RectPose>(poses: Iterable<TPose>): RectPose | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let any = false;\n for (const p of poses) {\n any = true;\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n const right = p.x + p.width;\n const bottom = p.y + p.height;\n if (right > maxX) maxX = right;\n if (bottom > maxY) maxY = bottom;\n }\n if (!any) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Axis-align a pose that carries a `rotation` or a `transform`: returns the\n * AABB of the box as drawn, its four corners through `poseFrameOf`, with both\n * fields dropped.\n *\n * A pose with neither is returned as-is.\n */\nexport function axisAlignedBounds<TPose extends RectPose>(b: TPose): RectPose {\n const frame = poseFrameOf(b);\n if (!frame) {\n // Strip an explicit `rotation: 0` so callers can rely on the absence of\n // the field meaning \"axis-aligned\".\n return { x: b.x, y: b.y, width: b.width, height: b.height };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n const corners: ReadonlyArray<readonly [number, number]> = [\n [b.x, b.y],\n [b.x + b.width, b.y],\n [b.x + b.width, b.y + b.height],\n [b.x, b.y + b.height],\n ];\n for (const [px, py] of corners) {\n const [rx, ry] = applyToPoint(frame, px, py);\n if (rx < minX) minX = rx;\n if (rx > maxX) maxX = rx;\n if (ry < minY) minY = ry;\n if (ry > maxY) maxY = ry;\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Fold every part into one world-space AABB, skipping `null` / `undefined`\n * entries. Rotated parts are expanded via {@link axisAlignedBounds} first;\n * the result never carries a `rotation` (a union of several oriented boxes\n * has no single orientation to report).\n *\n * Returns `null` when nothing was contributed.\n */\nexport function unionAABB<TPose extends RectPose>(\n parts: Iterable<TPose | null | undefined>,\n): RectPose | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let any = false;\n for (const part of parts) {\n if (!part) continue;\n const b = axisAlignedBounds(part);\n any = true;\n if (b.x < minX) minX = b.x;\n if (b.y < minY) minY = b.y;\n const right = b.x + b.width;\n const bottom = b.y + b.height;\n if (right > maxX) maxX = right;\n if (bottom > maxY) maxY = bottom;\n }\n if (!any) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n"],"mappings":";;;AAoBA,SAAgBA,EAAoC,GAAyC;CAC3F,IAAIC,IAAO,UACPC,IAAO,UACPC,IAAO,WACPC,IAAO,WACPC,IAAM;CACV,KAAK,IAAMC,KAAKC,GAAO;EAGrB,AAFA,IAAM,IACFD,EAAE,IAAIL,MAAM,IAAOK,EAAE,IACrBA,EAAE,IAAIJ,MAAM,IAAOI,EAAE;EACzB,IAAME,IAAQF,EAAE,IAAIA,EAAE,OAChBG,IAASH,EAAE,IAAIA,EAAE;EAEvB,AADIE,IAAQL,MAAM,IAAOK,IACrBC,IAASL,MAAM,IAAOK;CAC5B;CAEA,OADKJ,IACE;EAAE,GAAGJ;EAAM,GAAGC;EAAM,OAAOC,IAAOF;EAAM,QAAQG,IAAOF;CAAK,IADlD;AAEnB;AASA,SAAgBQ,EAA0C,GAAoB;CAC5E,IAAMC,IAAQC,EAAYC,CAAC;CAC3B,IAAI,CAACF,GAGH,OAAO;EAAE,GAAGE,EAAE;EAAG,GAAGA,EAAE;EAAG,OAAOA,EAAE;EAAO,QAAQA,EAAE;CAAO;CAE5D,IAAIZ,IAAO,UACPC,IAAO,UACPC,IAAO,WACPC,IAAO,WACLU,IAAoD;EACxD,CAACD,EAAE,GAAGA,EAAE,CAAC;EACT,CAACA,EAAE,IAAIA,EAAE,OAAOA,EAAE,CAAC;EACnB,CAACA,EAAE,IAAIA,EAAE,OAAOA,EAAE,IAAIA,EAAE,MAAM;EAC9B,CAACA,EAAE,GAAGA,EAAE,IAAIA,EAAE,MAAM;CACtB;CACA,KAAK,IAAM,CAACE,GAAIC,MAAOF,GAAS;EAC9B,IAAM,CAACG,GAAIC,KAAMC,EAAaR,GAAOI,GAAIC,CAAE;EAI3C,AAHIC,IAAKhB,MAAM,IAAOgB,IAClBA,IAAKd,MAAM,IAAOc,IAClBC,IAAKhB,MAAM,IAAOgB,IAClBA,IAAKd,MAAM,IAAOc;CACxB;CACA,OAAO;EAAE,GAAGjB;EAAM,GAAGC;EAAM,OAAOC,IAAOF;EAAM,QAAQG,IAAOF;CAAK;AACrE;AAUA,SAAgBkB,EACd,GACiB;CACjB,IAAInB,IAAO,UACPC,IAAO,UACPC,IAAO,WACPC,IAAO,WACPC,IAAM;CACV,KAAK,IAAMgB,KAAQC,GAAO;EACxB,IAAI,CAACD,GAAM;EACX,IAAMR,IAAIH,EAAkBW,CAAI;EAGhC,AAFA,IAAM,IACFR,EAAE,IAAIZ,MAAM,IAAOY,EAAE,IACrBA,EAAE,IAAIX,MAAM,IAAOW,EAAE;EACzB,IAAML,IAAQK,EAAE,IAAIA,EAAE,OAChBJ,IAASI,EAAE,IAAIA,EAAE;EAEvB,AADIL,IAAQL,MAAM,IAAOK,IACrBC,IAASL,MAAM,IAAOK;CAC5B;CAEA,OADKJ,IACE;EAAE,GAAGJ;EAAM,GAAGC;EAAM,OAAOC,IAAOF;EAAM,QAAQG,IAAOF;CAAK,IADlD;AAEnB"}
|
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return e === Object.prototype || e === null || Object.getPrototypeOf(e) === null;
|
|
4
|
-
}
|
|
5
|
-
function t(t) {
|
|
6
|
-
return typeof t == "object" && !!t && e(Object.getPrototypeOf(t));
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { t as isPlainObject, e as isPlainPrototype };
|
|
10
|
-
|
|
11
|
-
//# sourceMappingURL=isPlainObject.js.map
|
|
1
|
+
import { isPlainObject as e, isPlainPrototype as t } from "@weasel-js/registry";
|
|
2
|
+
export { e as isPlainObject, t as isPlainPrototype };
|
package/dist/core/ops/arrange.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arrange.js","names":["createArrangeOp","self","args","p","compute","set","write","adapter","id","pose","registerOpFactory"],"sources":["../../../src/core/ops/arrange.ts"],"sourcesContent":["import type { Op } from './types';\nimport { registerOpFactory } from './registry';\n\ninterface ArrangeAdapter {\n setPose(id: string, pose: unknown): void;\n}\n\n/** One pose write an {@link createArrangeOp} made. */\nexport interface ArrangedPose {\n id: string;\n from: unknown;\n to: unknown;\n}\n\n/** Arguments to {@link createArrangeOp}. */\nexport interface ArrangeArgs {\n /** The writes to make. Absent until a computed arrangement has run once. */\n placed?: ArrangedPose[];\n}\n\n/**\n * Op: write a set of poses decided when the op first applies, not when it is\n * built. The scene appends one to an edit that moves nodes into a container,\n * and `compute` asks the container what to do with them after the rest of\n * the edit has landed. Every later apply — redo, or a rebuild from a\n * serialized history — replays the writes it recorded, so the arrangement is\n * decided once. `write` replaces the adapter's `setPose` for this op and its\n * inverses — the scene passes its own, since not every adapter an edit is\n * applied through can write poses.\n */\nexport function createArrangeOp(\n args: ArrangeArgs,\n compute?: () => ArrangedPose[],\n write?: (id: string, pose: unknown) => void,\n): Op {\n const self: ArrangeArgs = { ...(args.placed ? { placed: args.placed } : {}) };\n return {\n name: 'arrange',\n args: self,\n label: 'Arrange',\n // Names what it moved, so a coalesced entry never undoes to a pose only\n // a later push wrote.\n get coalesceKey() {\n return self.placed === undefined ? undefined : `arrange:${self.placed.map((p) => p.id).sort().join(',')}`;\n },\n apply(adapter) {\n if (self.placed === undefined) self.placed = compute?.() ?? [];\n const set = write ?? ((id: string, pose: unknown) => (adapter as ArrangeAdapter).setPose(id, pose));\n for (const p of self.placed) set(p.id, p.to);\n return self.placed.length > 0 ? undefined : 'noop';\n },\n invert() {\n const placed = self.placed ?? [];\n return createArrangeOp({\n placed: [...placed].reverse().map((p) => ({ id: p.id, from: p.to, to: p.from })),\n }, undefined, write);\n },\n };\n}\n\nregisterOpFactory<ArrangeArgs>('arrange', (args) => createArrangeOp(args));\n"],"mappings":";;AA8BA,SAAgBA,EACd,GACA,GACA,GACI;CACJ,IAAMC,IAAoB,EAAE,GAAIC,EAAK,SAAS,EAAE,QAAQA,EAAK,OAAO,IAAI,CAAC,EAAG;CAC5E,OAAO;EACL,MAAM;EACN,MAAMD;EACN,OAAO;
|
|
1
|
+
{"version":3,"file":"arrange.js","names":["createArrangeOp","self","args","p","compute","set","write","adapter","id","pose","registerOpFactory"],"sources":["../../../src/core/ops/arrange.ts"],"sourcesContent":["import type { Op } from './types';\nimport { registerOpFactory } from './registry';\n\ninterface ArrangeAdapter {\n setPose(id: string, pose: unknown): void;\n}\n\n/** One pose write an {@link createArrangeOp} made. */\nexport interface ArrangedPose {\n id: string;\n from: unknown;\n to: unknown;\n}\n\n/** Arguments to {@link createArrangeOp}. */\nexport interface ArrangeArgs {\n /** The writes to make. Absent until a computed arrangement has run once. */\n placed?: ArrangedPose[];\n}\n\n/**\n * Op: write a set of poses decided when the op first applies, not when it is\n * built. The scene appends one to an edit that moves nodes into a container,\n * and `compute` asks the container what to do with them after the rest of\n * the edit has landed. Every later apply — redo, or a rebuild from a\n * serialized history — replays the writes it recorded, so the arrangement is\n * decided once. `write` replaces the adapter's `setPose` for this op and its\n * inverses — the scene passes its own, since not every adapter an edit is\n * applied through can write poses.\n */\nexport function createArrangeOp(\n args: ArrangeArgs,\n compute?: () => ArrangedPose[],\n write?: (id: string, pose: unknown) => void,\n): Op {\n const self: ArrangeArgs = { ...(args.placed ? { placed: args.placed } : {}) };\n return {\n name: 'arrange',\n args: self,\n label: 'Arrange',\n elideNoop: true,\n // Names what it moved, so a coalesced entry never undoes to a pose only\n // a later push wrote.\n get coalesceKey() {\n return self.placed === undefined ? undefined : `arrange:${self.placed.map((p) => p.id).sort().join(',')}`;\n },\n apply(adapter) {\n if (self.placed === undefined) self.placed = compute?.() ?? [];\n const set = write ?? ((id: string, pose: unknown) => (adapter as ArrangeAdapter).setPose(id, pose));\n for (const p of self.placed) set(p.id, p.to);\n return self.placed.length > 0 ? undefined : 'noop';\n },\n invert() {\n const placed = self.placed ?? [];\n return createArrangeOp({\n placed: [...placed].reverse().map((p) => ({ id: p.id, from: p.to, to: p.from })),\n }, undefined, write);\n },\n };\n}\n\nregisterOpFactory<ArrangeArgs>('arrange', (args) => createArrangeOp(args));\n"],"mappings":";;AA8BA,SAAgBA,EACd,GACA,GACA,GACI;CACJ,IAAMC,IAAoB,EAAE,GAAIC,EAAK,SAAS,EAAE,QAAQA,EAAK,OAAO,IAAI,CAAC,EAAG;CAC5E,OAAO;EACL,MAAM;EACN,MAAMD;EACN,OAAO;EACP,WAAW;EAGX,IAAI,cAAc;GAChB,OAAOA,EAAK,WAAW,KAAA,IAAY,KAAA,IAAY,WAAWA,EAAK,OAAO,KAAK,MAAME,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG;EACxG;EACA,MAAM,GAAS;GACb,AAAIF,EAAK,WAAW,KAAA,MAAW,EAAK,SAASG,IAAU,KAAK,CAAC;GAC7D,IAAMC,IAAMC,OAAW,GAAY,MAAmBC,EAA2B,QAAQC,GAAIC,CAAI;GACjG,KAAK,IAAMN,KAAKF,EAAK,QAAQ,EAAIE,EAAE,IAAIA,EAAE,EAAE;GAC3C,OAAOF,EAAK,OAAO,SAAS,IAAI,KAAA,IAAY;EAC9C;EACA,SAAS;GAEP,OAAOD,EAAgB,EACrB,QAAQ,CAAC,GAFIC,EAAK,UAAU,CAAC,CAEX,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,OAAO;IAAE,IAAIE,EAAE;IAAI,MAAMA,EAAE;IAAI,IAAIA,EAAE;GAAK,EAAE,EACjF,GAAG,KAAA,GAAWG,CAAK;EACrB;CACF;AACF;AAEAI,EAA+B,YAAY,MAASV,EAAgBE,CAAI,CAAC"}
|
package/dist/core/ops/create.js
CHANGED
|
@@ -3,24 +3,29 @@ import { parentOf as t, resolveSlot as n, slotFromIndex as r } from "./slot.js";
|
|
|
3
3
|
import { createDeleteOp as i } from "./delete.js";
|
|
4
4
|
//#region src/core/ops/create.ts
|
|
5
5
|
function a(e) {
|
|
6
|
-
let { node: a, label: o } = e,
|
|
6
|
+
let { node: a, label: o, cascaded: s } = e, c = e.slot ?? r(e.index);
|
|
7
7
|
return {
|
|
8
8
|
name: "insert",
|
|
9
9
|
args: {
|
|
10
10
|
node: a,
|
|
11
11
|
label: o,
|
|
12
|
-
slot:
|
|
12
|
+
slot: c,
|
|
13
|
+
...s ? { cascaded: s } : {}
|
|
13
14
|
},
|
|
14
15
|
label: o,
|
|
15
16
|
apply(e) {
|
|
16
|
-
let r = e, i =
|
|
17
|
-
|
|
17
|
+
let r = e, i = () => {
|
|
18
|
+
r.insertNode(a, n(r.getChildren?.(t(a)), c));
|
|
19
|
+
};
|
|
20
|
+
if (!s || s.length === 0) return i();
|
|
21
|
+
for (let e of s) r.getNode?.(e.node.id) || (e.node.id === a.id ? i() : r.insertNode(e.node, e.index));
|
|
18
22
|
},
|
|
19
23
|
invert() {
|
|
20
24
|
return i({
|
|
21
25
|
node: a,
|
|
22
26
|
label: o,
|
|
23
|
-
slot:
|
|
27
|
+
slot: c,
|
|
28
|
+
...s ? { cascaded: s } : {}
|
|
24
29
|
});
|
|
25
30
|
}
|
|
26
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","names":["createInsertOp","args","slot","slotFromIndex","
|
|
1
|
+
{"version":3,"file":"create.js","names":["createInsertOp","args","slot","slotFromIndex","cascaded","a","adapter","insertRoot","node","resolveSlot","parentOf","entry","createDeleteOp","registerOpFactory"],"sources":["../../../src/core/ops/create.ts"],"sourcesContent":["import type { Op } from './types';\nimport { createDeleteOp, type PlacedNode } from './delete';\nimport { registerOpFactory } from './registry';\nimport { parentOf, resolveSlot, slotFromIndex, type OrderedReader, type SiblingSlot } from './slot';\n\ninterface InsertAdapter<TNode> extends OrderedReader {\n getNode?(id: string): TNode | undefined;\n /** When `index` is supplied, insert at that position; adapters that ignore\n * the second arg (or don't expose it) fall back to their default\n * placement (typically append-to-end). */\n insertNode(node: TNode, index?: number): void;\n}\n\n/** Type alias for ops produced by `createInsertOp`. Carries no extra type info today;\n * exists so consumers can name the op type when needed. */\nexport type InsertOp = Op;\n\n/** Arguments to {@link createInsertOp}: the node to insert and where among its siblings. */\nexport interface InsertArgs<TNode extends { id: string }> {\n node: TNode;\n label?: string;\n /** Sibling ordinal to insert at. Sugar for `slot: { index }` — the weaker\n * of the two forms, and all a fresh-insert callsite can know. */\n index?: number;\n /** Full slot, anchor included. Produced only by `captureSlot` (via a\n * delete op's `invert`), and supersedes `index` when present. */\n slot?: SiblingSlot;\n /** Every node to insert, `node` itself included, each at its ordinal among\n * its own parent's children and ordered so a parent precedes its children.\n * What a delete's `cascaded` captures, and how its inverse brings the whole\n * set back; `node` still goes in at `slot`. One already present is skipped. */\n cascaded?: PlacedNode<TNode>[];\n}\n\n/** Op: insert `node`, and the rest of `cascaded` with it; inverts to a delete\n * of `node`. */\nexport function createInsertOp<TNode extends { id: string }>(args: InsertArgs<TNode>): InsertOp {\n const { node, label, cascaded } = args;\n const slot: SiblingSlot = args.slot ?? slotFromIndex(args.index);\n return {\n name: 'insert',\n args: { node, label, slot, ...(cascaded ? { cascaded } : {}) },\n label,\n apply(adapter) {\n const a = adapter as InsertAdapter<TNode>;\n const insertRoot = (): void => {\n a.insertNode(node, resolveSlot(a.getChildren?.(parentOf(node)), slot));\n };\n if (!cascaded || cascaded.length === 0) return insertRoot();\n for (const entry of cascaded) {\n // A flat adapter's removeNode doesn't cascade, so its children\n // were never gone — re-inserting them would duplicate them.\n if (a.getNode?.(entry.node.id)) continue;\n if (entry.node.id === node.id) insertRoot();\n else a.insertNode(entry.node, entry.index);\n }\n },\n invert() {\n return createDeleteOp({ node, label, slot, ...(cascaded ? { cascaded } : {}) });\n },\n };\n}\n\nregisterOpFactory<InsertArgs<{ id: string }>>('insert', (args) => createInsertOp(args));\n"],"mappings":";;;;AAoCA,SAAgBA,EAA6C,GAAmC;CAC9F,IAAM,EAAE,SAAM,UAAO,gBAAaC,GAC5BC,IAAoBD,EAAK,QAAQE,EAAcF,EAAK,KAAK;CAC/D,OAAO;EACL,MAAM;EACN,MAAM;GAAE;GAAM;GAAO;GAAM,GAAIG,IAAW,EAAE,YAAS,IAAI,CAAC;EAAG;EAC7D;EACA,MAAM,GAAS;GACb,IAAMC,IAAIC,GACJC,UAAyB;IAC7B,EAAE,WAAWC,GAAMC,EAAYJ,EAAE,cAAcK,EAASF,CAAI,CAAC,GAAGN,CAAI,CAAC;GACvE;GACA,IAAI,CAACE,KAAYA,EAAS,WAAW,GAAG,OAAOG,EAAW;GAC1D,KAAK,IAAMI,KAASP,GAGlB,AAAIC,EAAE,UAAUM,EAAM,KAAK,EAAE,MACzBA,EAAM,KAAK,OAAOH,EAAK,KAAID,EAAW,IACrCF,EAAE,WAAWM,EAAM,MAAMA,EAAM,KAAK;EAE7C;EACA,SAAS;GACP,OAAOC,EAAe;IAAE;IAAM;IAAO;IAAM,GAAIR,IAAW,EAAE,YAAS,IAAI,CAAC;GAAG,CAAC;EAChF;CACF;AACF;AAEAS,EAA8C,WAAW,MAASb,EAAeC,CAAI,CAAC"}
|
package/dist/core/ops/delete.js
CHANGED
|
@@ -44,41 +44,29 @@ function o(e, t) {
|
|
|
44
44
|
return l;
|
|
45
45
|
}
|
|
46
46
|
function s(e) {
|
|
47
|
-
let { node: a, label:
|
|
47
|
+
let { node: a, label: s } = e, c = e.slot ?? r(e.index), l = {
|
|
48
48
|
node: a,
|
|
49
|
-
label:
|
|
50
|
-
slot:
|
|
49
|
+
label: s,
|
|
50
|
+
slot: c,
|
|
51
51
|
cascaded: e.cascaded
|
|
52
|
-
},
|
|
52
|
+
}, u = e.cascaded ?? [];
|
|
53
53
|
return {
|
|
54
54
|
name: "delete",
|
|
55
|
-
args:
|
|
56
|
-
label:
|
|
55
|
+
args: l,
|
|
56
|
+
label: s,
|
|
57
57
|
apply(e) {
|
|
58
58
|
let r = e, i = t(r, n(a), a.id);
|
|
59
|
-
i && (
|
|
59
|
+
i && (c = i, l.slot = i);
|
|
60
60
|
let s = o(r, a.id);
|
|
61
|
-
s && (
|
|
61
|
+
s && (u = s, l.cascaded = s), r.removeNode(a.id);
|
|
62
62
|
},
|
|
63
63
|
invert() {
|
|
64
|
-
|
|
64
|
+
return i({
|
|
65
65
|
node: a,
|
|
66
|
-
label:
|
|
67
|
-
slot:
|
|
66
|
+
label: s,
|
|
67
|
+
slot: c,
|
|
68
|
+
...u.length > 0 ? { cascaded: u } : {}
|
|
68
69
|
});
|
|
69
|
-
return e.length === 0 ? n : {
|
|
70
|
-
label: c,
|
|
71
|
-
apply(t) {
|
|
72
|
-
let r = t;
|
|
73
|
-
for (let i of e) r.getNode?.(i.node.id) || (i.node.id === a.id ? n.apply(t) : r.insertNode(i.node, i.index));
|
|
74
|
-
},
|
|
75
|
-
invert: () => s({
|
|
76
|
-
node: a,
|
|
77
|
-
label: c,
|
|
78
|
-
slot: t,
|
|
79
|
-
cascaded: e
|
|
80
|
-
})
|
|
81
|
-
};
|
|
82
70
|
}
|
|
83
71
|
};
|
|
84
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.js","names":["indexIn","a","parentId","id","captureCascade","getChildren","getNode","closure","rootId","taken","node","walk","kid","detachRoots","p","parentOf","n","l","r","out","emitSubtree","entry","kids","i","child","createDeleteOp","args","slot","slotFromIndex","argsForSerial","captured","adapter","observed","captureSlot","snapshot","
|
|
1
|
+
{"version":3,"file":"delete.js","names":["indexIn","a","parentId","id","captureCascade","getChildren","getNode","closure","rootId","taken","node","walk","kid","detachRoots","p","parentOf","n","l","r","out","emitSubtree","entry","kids","i","child","createDeleteOp","args","slot","slotFromIndex","argsForSerial","captured","adapter","observed","captureSlot","snapshot","createInsertOp","registerOpFactory"],"sources":["../../../src/core/ops/delete.ts"],"sourcesContent":["import type { Op } from './types';\nimport { createInsertOp } from './create';\nimport { registerOpFactory } from './registry';\nimport { captureSlot, parentOf, slotFromIndex, type OrderedReader, type SiblingSlot } from './slot';\n\ninterface DeleteAdapter<TNode> extends OrderedReader {\n removeNode(id: string): void;\n /** Subtree reads, used to snapshot the cascade before it runs. Optional\n * — a flat adapter has neither, and a delete there is a single node. */\n getNode?(id: string): TNode | undefined;\n /** Every id `removeNode` would take with this one. Optional: a store whose\n * removal cascades along nothing but the subtree needs no such answer, and\n * `getChildren` is enough. A store that cascades further — the kit's scene\n * takes a deleted node's dependents too — must answer here, or the nodes it\n * cascades away are absent from the snapshot and undo brings back the named\n * node alone. */\n getRemovalClosure?(ids: readonly string[]): readonly string[];\n}\n\n/** A captured node plus its slot in its own parent's child list. */\nexport interface PlacedNode<TNode> {\n node: TNode;\n index: number;\n}\n\n/** Arguments to {@link createDeleteOp}: the node to remove, plus what undo needs to put it back. */\nexport interface DeleteArgs<TNode extends { id: string }> {\n node: TNode;\n label?: string;\n /** Sibling ordinal the node occupies at the moment of delete. Sugar for\n * `slot: { index }`, and only a seed: `apply` re-observes the node's full\n * slot through the adapter and that observation supersedes this. Kept\n * because it is the whole story for a flat adapter with no `getChildren`,\n * where nothing can be observed. */\n index?: number;\n /** Full slot, anchor included. Written by `apply`; supersedes `index`. */\n slot?: SiblingSlot;\n /** Everything `removeNode` takes, `node` itself included — its subtree, and\n * whatever else the adapter cascades. An inverse that re-inserts `node`\n * alone brings a container back empty and leaves every dependent deleted.\n * Ordered so a node's parent precedes it, which is the order they have to\n * be re-inserted in. Captured on apply; mirrored into the serialized args so\n * a rebuilt op can invert without having run. */\n cascaded?: PlacedNode<TNode>[];\n}\n\n/** `id`'s ordinal among `parentId`'s children, or `-1` when unobservable. */\nfunction indexIn(a: OrderedReader, parentId: string | null, id: string): number {\n return a.getChildren?.(parentId)?.indexOf(id) ?? -1;\n}\n\n/**\n * Snapshot everything removing `rootId` takes with it, `rootId` included.\n *\n * Returns `null` when the adapter can't enumerate, which leaves any previously\n * captured snapshot in place rather than clobbering it with an empty one.\n *\n * The order is the whole point. A cascade unlinks several disjoint subtrees, so\n * the captured set is walked as a forest: a node whose parent is not also going\n * is a detach root, and each one is emitted — ascending sibling index first, so\n * every slot still means what it meant — followed by its captured descendants\n * preorder. The closure's own order will not do: it reaches a dependent before\n * the parent it sits under whenever that parent is in the closure as a\n * dependent too, and re-inserting a child under a parent that is not back yet\n * puts it in the wrong place.\n */\nfunction captureCascade<TNode extends { id: string }>(\n a: DeleteAdapter<TNode>,\n rootId: string,\n): PlacedNode<TNode>[] | null {\n const { getChildren, getNode } = a;\n if (!getChildren || !getNode) return null;\n\n const closure = a.getRemovalClosure?.([rootId]);\n const taken = new Map<string, TNode>();\n if (closure) {\n for (const id of closure) {\n const node = getNode.call(a, id);\n if (node) taken.set(id, node);\n }\n } else {\n // No closure read: the cascade is the subtree, discovered here.\n const walk = (id: string): void => {\n const node = getNode.call(a, id);\n if (!node) return;\n taken.set(id, node);\n for (const kid of getChildren.call(a, id)) walk(kid);\n };\n walk(rootId);\n }\n\n const detachRoots = [...taken.values()]\n .filter((n) => { const p = parentOf(n); return p === null || !taken.has(p); })\n .map((n) => ({ node: n, index: indexIn(a, parentOf(n), n.id) }))\n .sort((l, r) => l.index - r.index);\n\n const out: PlacedNode<TNode>[] = [];\n const emitSubtree = (entry: PlacedNode<TNode>): void => {\n out.push(entry);\n const kids = getChildren.call(a, entry.node.id);\n for (let i = 0; i < kids.length; i++) {\n const child = taken.get(kids[i]!);\n if (child) emitSubtree({ node: child, index: i });\n }\n };\n for (const entry of detachRoots) emitSubtree(entry);\n return out;\n}\n\n/** Op: remove `node` and everything the adapter cascades with it; inverts to a\n * re-insert of the whole set at its captured slots. */\nexport function createDeleteOp<TNode extends { id: string }>(args: DeleteArgs<TNode>): Op {\n const { node, label } = args;\n let slot: SiblingSlot = args.slot ?? slotFromIndex(args.index);\n const argsForSerial: DeleteArgs<TNode> = { node, label, slot, cascaded: args.cascaded };\n let captured: PlacedNode<TNode>[] = args.cascaded ?? [];\n return {\n name: 'delete',\n args: argsForSerial,\n label,\n apply(adapter) {\n const a = adapter as DeleteAdapter<TNode>;\n const observed = captureSlot(a, parentOf(node), node.id);\n if (observed) {\n slot = observed;\n argsForSerial.slot = observed;\n }\n const snapshot = captureCascade(a, node.id);\n if (snapshot) {\n captured = snapshot;\n argsForSerial.cascaded = snapshot;\n }\n a.removeNode(node.id);\n },\n invert() {\n // The root's own placement keeps the anchor-bearing slot; the rest have\n // only an ordinal, which is all `getChildren` can observe of them.\n return createInsertOp<TNode>({\n node, label, slot,\n ...(captured.length > 0 ? { cascaded: captured } : {}),\n });\n },\n };\n}\n\nregisterOpFactory<DeleteArgs<{ id: string }>>('delete', (args) => createDeleteOp(args));\n"],"mappings":";;;;AA+CA,SAASA,EAAQ,GAAkB,GAAyB,GAAoB;CAC9E,OAAOC,EAAE,cAAcC,CAAQ,CAAC,EAAE,QAAQC,CAAE,KAAK;AACnD;AAiBA,SAASC,EACP,GACA,GAC4B;CAC5B,IAAM,EAAE,gBAAa,eAAYH;CACjC,IAAI,CAACI,KAAe,CAACC,GAAS,OAAO;CAErC,IAAMC,IAAUN,EAAE,oBAAoB,CAACO,CAAM,CAAC,GACxCC,oBAAQ,IAAI,IAAmB;CACrC,IAAIF,GACF,KAAK,IAAMJ,KAAMI,GAAS;EACxB,IAAMG,IAAOJ,EAAQ,KAAKL,GAAGE,CAAE;EAC/B,AAAIO,KAAMD,EAAM,IAAIN,GAAIO,CAAI;CAC9B;MACK;EAEL,IAAMC,KAAQ,MAAqB;GACjC,IAAMD,IAAOJ,EAAQ,KAAKL,GAAGE,CAAE;GAC/B,IAAKO,GACL;MAAM,IAAIP,GAAIO,CAAI;IAClB,KAAK,IAAME,KAAOP,EAAY,KAAKJ,GAAGE,CAAE,GAAG,EAAKS,CAAG;GADjC;EAEpB;EACA,EAAKJ,CAAM;CACb;CAEA,IAAMK,IAAc,CAAC,GAAGJ,EAAM,OAAO,CAAC,CAAC,CACpC,QAAQ,MAAM;EAAE,IAAMK,IAAIC,EAASC,CAAC;EAAG,OAAOF,MAAM,QAAQ,CAACL,EAAM,IAAIK,CAAC;CAAG,CAAC,CAAC,CAC7E,KAAK,OAAO;EAAE,MAAME;EAAG,OAAOhB,EAAQC,GAAGc,EAASC,CAAC,GAAGA,EAAE,EAAE;CAAE,EAAE,CAAC,CAC/D,MAAM,GAAG,MAAMC,EAAE,QAAQC,EAAE,KAAK,GAE7BC,IAA2B,CAAC,GAC5BC,KAAe,MAAmC;EACtD,EAAI,KAAKC,CAAK;EACd,IAAMC,IAAOjB,EAAY,KAAKJ,GAAGoB,EAAM,KAAK,EAAE;EAC9C,KAAK,IAAIE,IAAI,GAAGA,IAAID,EAAK,QAAQ,KAAK;GACpC,IAAME,IAAQf,EAAM,IAAIa,EAAKC,EAAG;GAChC,AAAIC,KAAOJ,EAAY;IAAE,MAAMI;IAAO,OAAOD;GAAE,CAAC;EAClD;CACF;CACA,KAAK,IAAMF,KAASR,GAAa,EAAYQ,CAAK;CAClD,OAAOF;AACT;AAIA,SAAgBM,EAA6C,GAA6B;CACxF,IAAM,EAAE,SAAM,aAAUC,GACpBC,IAAoBD,EAAK,QAAQE,EAAcF,EAAK,KAAK,GACvDG,IAAmC;EAAE;EAAM;EAAO;EAAM,UAAUH,EAAK;CAAS,GAClFI,IAAgCJ,EAAK,YAAY,CAAC;CACtD,OAAO;EACL,MAAM;EACN,MAAMG;EACN;EACA,MAAM,GAAS;GACb,IAAM5B,IAAI8B,GACJC,IAAWC,EAAYhC,GAAGc,EAASL,CAAI,GAAGA,EAAK,EAAE;GACvD,AAAIsB,MACF,IAAOA,GACP,EAAc,OAAOA;GAEvB,IAAME,IAAW9B,EAAeH,GAAGS,EAAK,EAAE;GAK1C,AAJIwB,MACF,IAAWA,GACX,EAAc,WAAWA,IAE3BjC,EAAE,WAAWS,EAAK,EAAE;EACtB;EACA,SAAS;GAGP,OAAOyB,EAAsB;IAC3B;IAAM;IAAO;IACb,GAAIL,EAAS,SAAS,IAAI,EAAE,UAAUA,EAAS,IAAI,CAAC;GACtD,CAAC;EACH;CACF;AACF;AAEAM,EAA8C,WAAW,MAASX,EAAeC,CAAI,CAAC"}
|