@weasel-js/core 1.7.1 → 1.7.2

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +7 -0
  3. package/dist/{autoPoseDescriptor-BT_vp9FO.d.ts → autoPoseDescriptor-vCdt55xm.d.ts} +1 -1
  4. package/dist/{builtins-BSUfH8nU.d.ts → builtins-C-gRyVRx.d.ts} +7 -3
  5. package/dist/canvas/CursorCoordsHud.js +56 -29
  6. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  7. package/dist/canvas/hud.module.js +3 -3
  8. package/dist/canvas/hud.module.js.map +1 -1
  9. package/dist/clipboard.d.ts +1 -1
  10. package/dist/clone.d.ts +2 -2
  11. package/dist/core/geometry/poseDescriptor.js +10 -15
  12. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  13. package/dist/{cornerHandles-CDcZOV8h.d.ts → cornerHandles-BCrDp_mH.d.ts} +1 -1
  14. package/dist/features/paths/poseDescriptor.js +6 -11
  15. package/dist/features/paths/poseDescriptor.js.map +1 -1
  16. package/dist/index.d.ts +22 -17
  17. package/dist/interactions/actions/defaults/clone.js +64 -53
  18. package/dist/interactions/actions/defaults/clone.js.map +1 -1
  19. package/dist/interactions/actions/defaults/move.js +426 -322
  20. package/dist/interactions/actions/defaults/move.js.map +1 -1
  21. package/dist/interactions/actions/defaults/resize.js +75 -72
  22. package/dist/interactions/actions/defaults/resize.js.map +1 -1
  23. package/dist/interactions/actions/defaults/rotate.js +88 -85
  24. package/dist/interactions/actions/defaults/rotate.js.map +1 -1
  25. package/dist/interactions/actions/planeInput.js +82 -69
  26. package/dist/interactions/actions/planeInput.js.map +1 -1
  27. package/dist/interactions/actions/resize/autoPoseDescriptor.js +0 -1
  28. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +1 -1
  29. package/dist/{math-CUMxmZzn.d.ts → math-Drrw4ewZ.d.ts} +2 -2
  30. package/dist/math.d.ts +3 -3
  31. package/dist/move.d.ts +4 -4
  32. package/dist/{originProjection-BSn4xiEy.d.ts → originProjection-DEklpDc_.d.ts} +1 -1
  33. package/dist/{poseDescriptor-CjSXMf8X.d.ts → poseDescriptor-D-OH-tu5.d.ts} +0 -4
  34. package/dist/renderer.d.ts +4 -4
  35. package/dist/resize.d.ts +5 -5
  36. package/dist/style.css +2 -0
  37. package/dist/{types-CA54-mAZ.d.ts → types-A37hYkeR.d.ts} +4 -2
  38. package/dist/{types-DSjd6W3n.d.ts → types-B_9g6hMM.d.ts} +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +16 -14
  41. package/dist/index.css +0 -2
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { s as RenderLayer, u as Dims, w as RedrawSource, x as Scene, y as RectPose, z as InertiaConfig, V as ViewAnimationOptions, A as PoseComposition, B as PoseAdapter, N as Node$1, F as GestureLifecycleOptions, H as SliceDep, J as ToolsApi, K as Tool, L as Contribution, M as LayerHit, D as DrawCommand, O as ChromeState, Q as VertexColorChannel, U as LayerGroup, X as InsertExtras, Y as SerializedScene, Z as GeometryProjection, _ as ContentHandlerEntry, $ as SvgIngestOptions, a0 as AnyTool, a1 as PanBounds, a2 as Animator, a3 as ColorOverrideRegistry, a4 as UseSceneOptions, a5 as SceneRegistry, a6 as RegisteredOp, a7 as PoseOverrides, a8 as DerivedDep, a9 as ViewportDims, P as PathDrawCommand, aa as ViewApi, ab as Affordance, ac as AffordanceRegion, ad as AffordanceBinding, ae as CommonAffordanceScratch, T as TextDrawCommand, af as DerivePoseFn, ag as BooleansAdapter, ah as CreateOutlinesAdapter, ai as UseAnimatorOptions, aj as AnimationHandle, ak as SampledTrack, al as SceneArrivalHandler } from './builtins-BSUfH8nU.js';
2
- export { am as AddLayerSpec, an as AddNodeSpec, ao as AnimateToBoundsOptions, ap as AnimationInfo, aq as AnimationKind, ar as AnimatorEvent, as as AnimatorListener, at as AreaSelectDep, au as BooleanOp, av as BooleanOpResult, aw as ClipboardDep, ax as ClipboardIngestCtx, ay as ColorOverride, az as ColorOverrideFn, aA as ContainerNode, aB as ContributionChrome, aC as CreateOutlinesResult, C as CullRect, aD as CustomPaintContext, aE as DecayLoopConfig, aF as DecayOptions, aG as DerivePathFn, aH as EditAnchorsDep, E as Effect, aI as EventBooking, aJ as EventBookingHandle, aK as EventTrack, aL as FitViewToBoundsOptions, G as GroupDrawCommand, aM as HitTestView, aN as IDENTITY_POSE_COMPOSITION, a as ImageDrawCommand, b as ImageMinification, aO as IngestCtx, aP as IngestionDep, aQ as InsertDep, aR as Interpolate, aS as InterpolatorFactory, aT as Keyframe, aU as LassoSelectDep, aV as LayerCommandCache, aW as LayerDrawFailure, aX as LayerDrawSpan, aY as LayerRecord, aZ as LayoutDep, a_ as LayoutFrame, a$ as LayoutMove, b0 as LeafNode, b1 as LiveAnimation, b2 as LoopFactory, b3 as LoopOptions, b4 as NestedTimeline, b5 as NodeAtPointDep, b6 as OutlinePathSpec, b7 as Overlay, b8 as PathInWorldPose, b9 as PhysicsHandle, ba as PhysicsOptions, bb as PointerContextProvider, bc as PointerContextValue, bd as PointerWorldPos, be as PoseClosure, bf as PoseOverride, f as RenderTarget, bg as ResizePolicy, S as SPRITE_STRIDE, bh as SerializedLayer, bi as SerializedNode, g as ShaderDrawCommand, bj as SnapDep, bk as SpringOptions, i as SpriteSheet, j as SpritesDrawCommand, bl as StaggerBuilder, bm as StaggerDelay, bn as StaggerFactory, bo as StaggerOptions, bp as StaggerPerItem, bq as StaggerSpringPoseOptions, br as StaggerTweenOptions, bs as SvgUnpacker, bt as SystemLayerRecord, bu as SystemLayerSpec, bv as TextEditDep, bw as TextNodeSource, bx as TextOutlineSource, by as TextOutlinesError, bz as TextOutlinesFailure, bA as TextPaintPath, bB as TextToPathOptions, bC as TimelineClock, bD as TimelineEvent, bE as TimelineHandle, bF as TimelineOptions, bG as TimelineTrack, bH as ToolDef, bI as Track, bJ as TweenLoopOptions, bK as TweenOptions, bL as UseToolsOptions, bM as UserLayerRecord, bN as VIEW_ANIMATION_KEY, bO as ViewAnimationApi, bP as ViewChannel, bQ as applyBooleanOp, bR as applyCreateOutlines, bS as asNodeId, m as blur, bT as composeWorldPose, bU as createPointerStore, o as cullDrawCommands, bV as depsUnchanged, bW as drawLayers, bX as drawOneLayer, bY as fitViewToBounds, p as frameRect, bZ as isLayerPainted, b_ as isLayerVisible, b$ as loadTextOutlines, c0 as pathInPoseFrame, c1 as pathInWorld, c2 as rebaseLocalPose, c3 as registerContentHandler, r as registerEffect, c4 as resolveStrokeWidth, c5 as subscribeToSources, c6 as textToPath, c7 as textToPathsByPaint, c8 as useDecayLoop, c9 as usePointerContext, ca as usePointerPosition, cb as useTools, cc as useViewAnimation, cd as useViewAnimationOn, v as viewToMat3, q as vignette, ce as worldEditToStorage } from './builtins-BSUfH8nU.js';
1
+ import { s as RenderLayer, u as Dims, w as RedrawSource, x as Scene, y as RectPose, z as InertiaConfig, V as ViewAnimationOptions, A as PoseComposition, B as PoseAdapter, N as Node$1, F as GestureLifecycleOptions, H as SliceDep, J as ToolsApi, K as Tool, L as Contribution, M as LayerHit, D as DrawCommand, O as ChromeState, Q as VertexColorChannel, U as LayerGroup, X as InsertExtras, Y as SerializedScene, Z as GeometryProjection, _ as ContentHandlerEntry, $ as SvgIngestOptions, a0 as AnyTool, a1 as PanBounds, a2 as Animator, a3 as ColorOverrideRegistry, a4 as UseSceneOptions, a5 as SceneRegistry, a6 as RegisteredOp, a7 as PoseOverrides, a8 as DerivedDep, a9 as ViewportDims, P as PathDrawCommand, aa as ViewApi, ab as Affordance, ac as AffordanceRegion, ad as AffordanceBinding, ae as CommonAffordanceScratch, T as TextDrawCommand, af as DerivePoseFn, ag as BooleansAdapter, ah as CreateOutlinesAdapter, ai as UseAnimatorOptions, aj as AnimationHandle, ak as SampledTrack, al as SceneArrivalHandler } from './builtins-C-gRyVRx.js';
2
+ export { am as AddLayerSpec, an as AddNodeSpec, ao as AnimateToBoundsOptions, ap as AnimationInfo, aq as AnimationKind, ar as AnimatorEvent, as as AnimatorListener, at as AreaSelectDep, au as BooleanOp, av as BooleanOpResult, aw as ClipboardDep, ax as ClipboardIngestCtx, ay as ColorOverride, az as ColorOverrideFn, aA as ContainerNode, aB as ContributionChrome, aC as CreateOutlinesResult, C as CullRect, aD as CustomPaintContext, aE as DecayLoopConfig, aF as DecayOptions, aG as DerivePathFn, aH as EditAnchorsDep, E as Effect, aI as EventBooking, aJ as EventBookingHandle, aK as EventTrack, aL as FitViewToBoundsOptions, G as GroupDrawCommand, aM as HitTestView, aN as IDENTITY_POSE_COMPOSITION, a as ImageDrawCommand, b as ImageMinification, aO as IngestCtx, aP as IngestionDep, aQ as InsertDep, aR as Interpolate, aS as InterpolatorFactory, aT as Keyframe, aU as LassoSelectDep, aV as LayerCommandCache, aW as LayerDrawFailure, aX as LayerDrawSpan, aY as LayerRecord, aZ as LayoutDep, a_ as LayoutFrame, a$ as LayoutMove, b0 as LeafNode, b1 as LiveAnimation, b2 as LoopFactory, b3 as LoopOptions, b4 as NestedTimeline, b5 as NodeAtPointDep, b6 as OutlinePathSpec, b7 as Overlay, b8 as PathInWorldPose, b9 as PhysicsHandle, ba as PhysicsOptions, bb as PointerContextProvider, bc as PointerContextValue, bd as PointerWorldPos, be as PoseClosure, bf as PoseOverride, f as RenderTarget, bg as ResizePolicy, S as SPRITE_STRIDE, bh as SerializedLayer, bi as SerializedNode, g as ShaderDrawCommand, bj as SnapDep, bk as SpringOptions, i as SpriteSheet, j as SpritesDrawCommand, bl as StaggerBuilder, bm as StaggerDelay, bn as StaggerFactory, bo as StaggerOptions, bp as StaggerPerItem, bq as StaggerSpringPoseOptions, br as StaggerTweenOptions, bs as SvgUnpacker, bt as SystemLayerRecord, bu as SystemLayerSpec, bv as TextEditDep, bw as TextNodeSource, bx as TextOutlineSource, by as TextOutlinesError, bz as TextOutlinesFailure, bA as TextPaintPath, bB as TextToPathOptions, bC as TimelineClock, bD as TimelineEvent, bE as TimelineHandle, bF as TimelineOptions, bG as TimelineTrack, bH as ToolDef, bI as Track, bJ as TweenLoopOptions, bK as TweenOptions, bL as UseToolsOptions, bM as UserLayerRecord, bN as VIEW_ANIMATION_KEY, bO as ViewAnimationApi, bP as ViewChannel, bQ as applyBooleanOp, bR as applyCreateOutlines, bS as asNodeId, m as blur, bT as composeWorldPose, bU as createPointerStore, o as cullDrawCommands, bV as depsUnchanged, bW as drawLayers, bX as drawOneLayer, bY as fitViewToBounds, p as frameRect, bZ as isLayerPainted, b_ as isLayerVisible, b$ as loadTextOutlines, c0 as pathInPoseFrame, c1 as pathInWorld, c2 as rebaseLocalPose, c3 as registerContentHandler, r as registerEffect, c4 as resolveStrokeWidth, c5 as subscribeToSources, c6 as textToPath, c7 as textToPathsByPaint, c8 as useDecayLoop, c9 as usePointerContext, ca as usePointerPosition, cb as useTools, cc as useViewAnimation, cd as useViewAnimationOn, v as viewToMat3, q as vignette, ce as worldEditToStorage } from './builtins-C-gRyVRx.js';
3
3
  import { View as View$1, NodeId, PointerSessionCancelReason, DeviceProfile, Bounds, Action, ActionDeps, AffordanceHit, SelectionMode, SelectionExtendKey, SelectionApi, DepSchema, GestureBinding, ToolKeybinding, HotkeyTrigger, ModifierState, RuleCtx, Rule, DebugSink, HitShape, HandleKind, ViewportGestureKind, IngestItem, OngoingOverlay, DepName, ActionsProp, OverlayRole, ResizeAnchor } from '@weasel-js/routing';
4
4
  export { ALWAYS, Action, ActionDeps, ActionDisabledReason, ActionDispatch, ActionEnabledResult, ActionEntry, ActionItem, ActionPresentation, ActionVariant, ActionsProp, ActionsRegistry, AffordanceHit, BindingOpts, BindingScope, BindingSource, BoundGesture, Bounds, BuildRuleCtxArgs, COARSE_TARGET_SCALE, ContributionDeps, ContributionRouting, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_DEVICE_PROFILE, DRAG_THRESHOLD_PX, DebugSink, DepName, DepRegistry, DepSchema, DetectedDeviceFacts, DeviceProfile, DispatchRecord, DispatchRecordInput, Dispatcher, DispatcherContext, DragSample, DroppedCandidate, Eligibility, EligibilityState, GestureBinding, HandleKind, HitShape, HotkeyTrigger, ImmediateInvoker, IngestItem, InputEvent, InvocationCtx, Invoker, KeyBinding, LONG_PRESS_MS, LongPressOptions, LongPressState, LongPressStore, MatchResult, ModeShortcutHandlers, ModifierState, NEVER, NodeId, OngoingHandle, OngoingInvoker, OngoingOverlay, OverlayPosition, OverlayRole, PendingLongPress, PlacedBy, Point2, PointerSession, PointerSessionCallbacks, PointerSessionCancelReason, PointerSessionOptions, RankedCandidate, RecordCandidate, ResizeAnchor, ResolveAllOptions, ResolveOnlyResult, ResolvedCandidate, Rule, RuleCtx, ScopedBinding, ScratchKey, ScratchStore, SelectionApi, SelectionExtendKey, SelectionMode, Selector, SpecificityPart, ToolCtx, ToolKeybinding, ToolLifecycleCtx, ToolModifiers, ToolPresentation, ToolSlot, UiOngoingControl, Point2 as Vec2, View, ViewportGestureKind, WalkStep, actionBindings, actionItems, buildDepsFromRequires, buildRuleCtx, clientToCanvas, createDepRegistry, createDispatcher, createLongPressStore, defineTool, deleteScratch, describeRule, evaluate, evaluateEnabled, getScratch, isEditableTarget, liveScope, matchesKeyBinding, modeShortcutSpec, modeShortcuts, openPointerSession, pastDragThreshold, resolveDeviceProfile, resolveParams, scopeBindings, scratchKey, setScratch, specificity } from '@weasel-js/routing';
5
- import { a as ParallaxOpts, L as LayoutStrategy, M as MoveAdapter, A as AreaSelectAdapter, e as LayerEnumerableAdapter, f as LassoHitMode, g as LassoSelectAdapter, h as ResizeAdapter, i as RotateAdapter, I as InsertAdapter, j as ClipboardSnapshot, c as LayoutDropTargetMode, d as ReflowTransition, O as OrderedAdapter, P as PlaneMap, b as SceneAdapter } from './types-CA54-mAZ.js';
6
- export { C as ContainerBounds, D as DropRegion, k as DropTarget, l as LayoutArrival, m as LayoutChild, n as LayoutContainer, o as LayoutDragged, p as LayoutSnap, q as ReflowGlideOptions, R as RegionPickView, r as ScalarOrXY, S as SnapTarget, s as deriveParallaxView, t as fromPlane, u as planeMap, v as planeMatrix, w as planeToPlane, x as rectFromPlane, y as rectToPlane, z as toPlane } from './types-CA54-mAZ.js';
7
- import { S as SimulationNode, U as UseSimulationOptions, a as Simulation } from './math-CUMxmZzn.js';
8
- export { D as DEFAULT_ALPHA_DECAY, b as DEFAULT_ALPHA_MIN, c as DEFAULT_VELOCITY_DECAY, d as SimulationCore, e as SimulationForce, f as SimulationOptions, g as aabbCenter, h as createSimulation, p as pointInRotatedRect, r as rectCorners, i as rotatePoint, j as rotatedRectCorners } from './math-CUMxmZzn.js';
5
+ import { a as ParallaxOpts, L as LayoutStrategy, M as MoveAdapter, A as AreaSelectAdapter, e as LayerEnumerableAdapter, f as LassoHitMode, g as LassoSelectAdapter, h as ResizeAdapter, i as RotateAdapter, I as InsertAdapter, j as ClipboardSnapshot, c as LayoutDropTargetMode, d as ReflowTransition, O as OrderedAdapter, P as PlaneMap, b as SceneAdapter } from './types-A37hYkeR.js';
6
+ export { C as ContainerBounds, D as DropRegion, k as DropTarget, l as LayoutArrival, m as LayoutChild, n as LayoutContainer, o as LayoutDragged, p as LayoutSnap, q as ReflowGlideOptions, R as RegionPickView, r as ScalarOrXY, S as SnapTarget, s as deriveParallaxView, t as fromPlane, u as planeMap, v as planeMatrix, w as planeToPlane, x as rectFromPlane, y as rectToPlane, z as toPlane } from './types-A37hYkeR.js';
7
+ import { S as SimulationNode, U as UseSimulationOptions, a as Simulation } from './math-Drrw4ewZ.js';
8
+ export { D as DEFAULT_ALPHA_DECAY, b as DEFAULT_ALPHA_MIN, c as DEFAULT_VELOCITY_DECAY, d as SimulationCore, e as SimulationForce, f as SimulationOptions, g as aabbCenter, h as createSimulation, p as pointInRotatedRect, r as rectCorners, i as rotatePoint, j as rotatedRectCorners } from './math-Drrw4ewZ.js';
9
9
  import * as react from 'react';
10
10
  import react__default, { RefObject, ReactNode, Ref, MouseEvent, MutableRefObject } from 'react';
11
11
  import { Yoke } from '@weasel-js/routing/react';
@@ -13,12 +13,12 @@ export { ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIf
13
13
  export { useLatest } from '@weasel-js/react';
14
14
  import { GestureSpec } from '@weasel-js/gestures';
15
15
  export { ClaimableGesture, ClickSpec, DragSpec, DropSpec, GestureSpec, KeyHeldSpec, KeySpec, ModSpec, MultiTouchSpec, PasteSpec, PinchSpec, TargetSpec, WheelSpec } from '@weasel-js/gestures';
16
- import { B as BoundsConstraint, P as PointSnapBehavior, R as RotateBehavior, I as InsertBehavior, L as LassoSelectBehavior, S as SnapStrategy, M as MoveBehavior, G as GestureContext } from './types-DSjd6W3n.js';
17
- export { A as ActionBehavior, a as AreaSelectOverlay, b as BehaviorEnd, c as BehaviorMoveResult, d as BehaviorResult, C as CloneBehavior, e as CloneLayer, f as ClonePose, g as GroupTransform, h as InsertMoveResult, i as InsertOverlay, j as InsertPoint, k as InsertProposed, l as LassoSelectMoveResult, m as LassoSelectOverlay, n as LassoSelectPose, o as LassoSelectProposed, p as PointSnapContext, q as PointSnapFrame, r as PointSnapResult, s as PointerState, t as ResizeMoveResult, u as ResizeOverlay, v as ResizeProposed, w as RotateMoveResult, x as RotateOverlay, y as RotateProposed } from './types-DSjd6W3n.js';
18
- import { P as PoseDescriptor, b as RotatedPose } from './poseDescriptor-CjSXMf8X.js';
19
- export { R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, p as poseDescriptorForNode, t as translatePoseViaDescriptor, v as visualBoundsViaDescriptor } from './poseDescriptor-CjSXMf8X.js';
20
- import { U as UseResizeOptions } from './cornerHandles-CDcZOV8h.js';
21
- export { C as CORNER_ANCHORS, a as CornerAnchor, e as CornerEdge, b as CornerHandle, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle } from './cornerHandles-CDcZOV8h.js';
16
+ import { B as BoundsConstraint, P as PointSnapBehavior, R as RotateBehavior, I as InsertBehavior, L as LassoSelectBehavior, S as SnapStrategy, M as MoveBehavior, G as GestureContext } from './types-B_9g6hMM.js';
17
+ export { A as ActionBehavior, a as AreaSelectOverlay, b as BehaviorEnd, c as BehaviorMoveResult, d as BehaviorResult, C as CloneBehavior, e as CloneLayer, f as ClonePose, g as GroupTransform, h as InsertMoveResult, i as InsertOverlay, j as InsertPoint, k as InsertProposed, l as LassoSelectMoveResult, m as LassoSelectOverlay, n as LassoSelectPose, o as LassoSelectProposed, p as PointSnapContext, q as PointSnapFrame, r as PointSnapResult, s as PointerState, t as ResizeMoveResult, u as ResizeOverlay, v as ResizeProposed, w as RotateMoveResult, x as RotateOverlay, y as RotateProposed } from './types-B_9g6hMM.js';
18
+ import { P as PoseDescriptor, b as RotatedPose } from './poseDescriptor-D-OH-tu5.js';
19
+ export { R as RECT_POSE_DESCRIPTOR, a as ROTATED_POSE_DESCRIPTOR, p as poseDescriptorForNode, t as translatePoseViaDescriptor, v as visualBoundsViaDescriptor } from './poseDescriptor-D-OH-tu5.js';
20
+ import { U as UseResizeOptions } from './cornerHandles-BCrDp_mH.js';
21
+ export { C as CORNER_ANCHORS, a as CornerAnchor, e as CornerEdge, b as CornerHandle, c as cornerPoint, d as cornerResizeHandles, f as fixedCornerOf, h as hitCornerHandle } from './cornerHandles-BCrDp_mH.js';
22
22
  import { Op, HistorySelection, CreateHistoryOptions, History } from '@weasel-js/history';
23
23
  export * from '@weasel-js/history';
24
24
  export { Op } from '@weasel-js/history';
@@ -26,8 +26,8 @@ import { Path, PolygonPath, PlacementAlign, Rect, SpringPresetName, EasingSpec }
26
26
  export { BezierEasing, DEFAULT_FLATTEN_TOLERANCE, EASINGS, EasingFn, EasingName, EasingSpec, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, Path, PathBuilder, PathFillRule, PathStation, PointAlongPathOptions, PointInPathOptions, PolygonPath, Rect, RectPath, SPRING_PRESETS, SpringPreset, SpringPresetName, boundsOfPath, composePath, cubicBezierEasing, decomposePath, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, ellipsePath, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, linePath, linear, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathFromD, pathIntersectsPolygon, pathIntersectsRect, pathSignedArea, pointAlongPath, pointInPath, polygonFromPoints, polylineFromPoints, rectPath, regularPolygonPath, resolveEasing, reversePath, scalePathToBounds, splitSubpaths, starPath, transformPath, translatePath, unionBoundsPath } from '@weasel-js/geom';
27
27
  import { Display, UnitEntry, UnitSystem, Unit } from '@weasel-js/quantity';
28
28
  export { ANGLE_RADIANS, IMPERIAL_INCHES, METRIC_MM, PIXELS, Unit, UnitEntry, UnitScale, UnitSystem, UnitValue, formatUnit, resolveUnit, unitScale } from '@weasel-js/quantity';
29
- import { U as UseMoveOptions, O as OriginProjection } from './originProjection-BSn4xiEy.js';
30
- export { A as AUTO_ORIGIN_PROJECTION, R as RECT_ORIGIN_PROJECTION } from './originProjection-BSn4xiEy.js';
29
+ import { U as UseMoveOptions, O as OriginProjection } from './originProjection-DEklpDc_.js';
30
+ export { A as AUTO_ORIGIN_PROJECTION, R as RECT_ORIGIN_PROJECTION } from './originProjection-DEklpDc_.js';
31
31
  import { Stroke, FillStyle, TextureHandle, TilePatternSpec, GradientKind, GradStop, GradientFill, ColorSpace, MarkerRef, Palette } from '@weasel-js/paint';
32
32
  export { ColorInterpolationSpace, ColorSpace, FillStyle, GradStop, GradientFill, GradientKind, GradientUnits, HueInterpolation, KitMarkerKey, MarkerKey, MarkerRef, OklchDeg, PatternTransform, PatternTransformParts, Region, STROKE_DASH_RATIOS, ScreenLength, Stroke, StrokeAlign, StrokeDashStyle, TextureHandle, TilePatternSpec, alignedStrokeRect, composePatternTransform, contrastLineColor, dashForStrokeStyle, decomposePatternTransform, hexToOklchDeg, hslToSrgb, interpolateSrgb, lerpColorArray, lerpOklab, lerpOklch, linearSrgbToOklab, linearToSrgb, oklabToLinearSrgb, oklabToOklch, oklabToSrgbU8, oklchDegToHex, oklchToOklab, resolveScreenLength, srgbFloatToOklab, srgbToHsl, srgbToLinear, srgbU8ToOklab, strokeDashStyleOf } from '@weasel-js/paint';
33
33
  import { a as ShaderProgramHandle, G as GlMat3 } from './registerProgram-ateHDGjw.js';
@@ -47,7 +47,7 @@ export { SplitBySegmentOptions, pathDivide, pathExclude, pathIntersect, pathSubt
47
47
  export { CURVE_REPS, CurveRepKind, CurveRepresentation, Discriminator, SharedAnchor, bezierCubic, bezierQuadratic, nurbs, spiro } from '@weasel-js/geom/curves';
48
48
  import { Polyline } from '@weasel-js/geom/tessellate';
49
49
  export { Polyline, trimPolyline } from '@weasel-js/geom/tessellate';
50
- export { A as AUTO_POSE_DESCRIPTOR, i as isPathLike, a as isRectPose } from './autoPoseDescriptor-BT_vp9FO.js';
50
+ export { A as AUTO_POSE_DESCRIPTOR, i as isPathLike, a as isRectPose } from './autoPoseDescriptor-vCdt55xm.js';
51
51
  export { ClipboardFlavors, UseClipboardOpsOptions, UseClipboardOpsReturn, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, buildWeaselClipboardText, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, parseWeaselClipboardText, sniffWeaselClipboardText, useClipboardOps } from './clipboard.js';
52
52
  export { cloneByAltDrag } from './clone.js';
53
53
 
@@ -1668,6 +1668,11 @@ declare const cloneAction: Action & {
1668
1668
  * The action sees the plane only as `view.plane()`, which it hands its snap
1669
1669
  * behaviors so they can bring the camera's guides and grid into the plane.
1670
1670
  *
1671
+ * A selection can span planes. The edit is measured in one of them, and a
1672
+ * node on another is carried into it as the gesture starts
1673
+ * (`planeOf` at press, inverted) and back out through `planeOf` as it is now,
1674
+ * so each node ends where it was drawn relative to the pointer.
1675
+ *
1671
1676
  * The map is read afresh on every call: a camera panning under a held drag, or
1672
1677
  * a plane whose factors are being animated, moves the node with the pointer.
1673
1678
  */
@@ -1685,8 +1690,8 @@ declare const insertLayer: EditedLayerOf;
1685
1690
  /** The layer of the path in anchor-edit mode. */
1686
1691
  declare const editingLayer: EditedLayerOf;
1687
1692
  /** `action`, with its input carried into the plane of the layer `layerOf`
1688
- * names. An action on a layer with no `parallax`, or invoked with no scene or
1689
- * view to read the plane from, runs exactly as it would unwrapped.
1693
+ * names. An action in a scene with no `parallax` layer, or invoked with no
1694
+ * scene or view to read a plane from, runs exactly as it would unwrapped.
1690
1695
  *
1691
1696
  * An ongoing action's drag is carried as a whole. An immediate one's world
1692
1697
  * point is `params.worldX` / `params.worldY`, the dispatcher's convention for
@@ -1,12 +1,12 @@
1
1
  import { translatePoseViaDescriptor as e } from "../../../core/geometry/poseDescriptor.js";
2
2
  import { poseDescriptorOf as t } from "../poseDescriptorDep.js";
3
- import { inPlane as n, selectionLayer as r } from "../planeInput.js";
4
- import { defaultCommitAdapter as i } from "../defaultCommitAdapter.js";
5
- import { scenePoseFrame as a } from "../poseFrame.js";
6
- import { createInsertOp as o } from "../../../core/ops/create.js";
7
- import { freshNodeId as s } from "./freshNodeId.js";
3
+ import { carryPose as n, inPlane as r, invertPlane as i, planeOf as a, selectionLayer as o } from "../planeInput.js";
4
+ import { defaultCommitAdapter as s } from "../defaultCommitAdapter.js";
5
+ import { scenePoseFrame as c } from "../poseFrame.js";
6
+ import { createInsertOp as l } from "../../../core/ops/create.js";
7
+ import { freshNodeId as u } from "./freshNodeId.js";
8
8
  //#region src/interactions/actions/defaults/clone.ts
9
- var c = n({
9
+ var d = r({
10
10
  id: "clone",
11
11
  label: "Clone",
12
12
  cursor: "copy",
@@ -21,76 +21,87 @@ var c = n({
21
21
  ],
22
22
  invoker: {
23
23
  timing: "ongoing",
24
- start(n, r) {
25
- let c = n.deps.selection, l = n.deps.scene, u = n.deps.applyOps;
26
- if (!c || !l) return {};
27
- let d = c.get();
28
- if (d.length === 0) return {};
29
- let f = a(l, n.deps.poseComposition), p = /* @__PURE__ */ new Map();
30
- for (let e of d) l.get(e) !== void 0 && p.set(e, f.world(e));
31
- if (p.size === 0) return {};
32
- let m = {
33
- ids: d,
34
- scene: l,
35
- descriptor: t(n.deps.poseDescriptor),
36
- frame: f,
37
- originPoses: p,
24
+ start(r, o) {
25
+ let d = r.deps.selection, f = r.deps.scene, p = r.deps.applyOps;
26
+ if (!d || !f) return {};
27
+ let m = d.get();
28
+ if (m.length === 0) return {};
29
+ let h = c(f, r.deps.poseComposition), g = /* @__PURE__ */ new Map(), _ = t(r.deps.poseDescriptor);
30
+ for (let e of m) {
31
+ let t = f.get(e);
32
+ if (t === void 0) continue;
33
+ let o = i(a(r.deps.view, t.layer));
34
+ g.set(e, n(_, h.world(e), o));
35
+ }
36
+ if (g.size === 0) return {};
37
+ let v = {
38
+ ids: m,
39
+ scene: f,
40
+ descriptor: _,
41
+ frame: h,
42
+ originPoses: g,
43
+ view: r.deps.view,
38
44
  currentDelta: {
39
45
  dx: 0,
40
46
  dy: 0
41
47
  },
42
48
  previews: /* @__PURE__ */ new Map(),
43
- applyOps: u
49
+ applyOps: p
50
+ }, y = (t, r, i) => {
51
+ let o = v.originPoses.get(t), s = v.scene.get(t);
52
+ if (o === void 0 || !s) return;
53
+ let c = e(o, r, i, v.descriptor);
54
+ return v.frame.local(t, n(v.descriptor, c, a(v.view, s.layer)));
44
55
  };
45
56
  return {
46
57
  kind: "clone",
47
58
  previewHidesSource: !1,
48
- onMove(t) {
49
- if (!t.drag) return;
50
- m.currentDelta = {
51
- dx: t.drag.delta.x,
52
- dy: t.drag.delta.y
53
- }, m.previews.clear();
54
- let { dx: n, dy: r } = m.currentDelta;
55
- if (n !== 0 || r !== 0) for (let [t, i] of m.originPoses) m.previews.set(t, m.frame.local(t, e(i, n, r, m.descriptor)));
59
+ onMove(e) {
60
+ if (!e.drag) return;
61
+ v.currentDelta = {
62
+ dx: e.drag.delta.x,
63
+ dy: e.drag.delta.y
64
+ }, v.previews.clear();
65
+ let { dx: t, dy: n } = v.currentDelta;
66
+ if (t !== 0 || n !== 0) for (let e of v.originPoses.keys()) v.previews.set(e, y(e, t, n));
56
67
  },
57
- onEnd(t, n) {
58
- if (n === "cancel") {
59
- m.previews.clear();
68
+ onEnd(e, t) {
69
+ if (t === "cancel") {
70
+ v.previews.clear();
60
71
  return;
61
72
  }
62
- let { dx: r, dy: a } = m.currentDelta;
63
- if (r === 0 && a === 0) {
64
- m.previews.clear();
73
+ let { dx: n, dy: r } = v.currentDelta;
74
+ if (n === 0 && r === 0) {
75
+ v.previews.clear();
65
76
  return;
66
77
  }
67
- let l = [];
68
- for (let t of m.ids) {
69
- let n = m.originPoses.get(t), i = m.scene.get(t);
70
- if (n === void 0 || !i) continue;
71
- let c = m.frame.local(t, e(n, r, a, m.descriptor)), u = {
72
- id: s(),
73
- kind: i.kind,
74
- layer: i.layer,
75
- pose: c,
76
- data: i.data,
77
- parent: i.parent ?? null
78
+ let i = [];
79
+ for (let e of v.ids) {
80
+ let t = v.scene.get(e), a = y(e, n, r);
81
+ if (a === void 0 || !t) continue;
82
+ let o = {
83
+ id: u(),
84
+ kind: t.kind,
85
+ layer: t.layer,
86
+ pose: a,
87
+ data: t.data,
88
+ parent: t.parent ?? null
78
89
  };
79
- l.push(o({
80
- node: u,
90
+ i.push(l({
91
+ node: o,
81
92
  label: "Clone"
82
93
  }));
83
94
  }
84
- l.length > 0 && (m.applyOps ? m.applyOps(l, "Clone") : m.scene.applyBatch(l, "Clone", i(m.scene, c.adapterMethods))), m.previews.clear();
95
+ i.length > 0 && (v.applyOps ? v.applyOps(i, "Clone") : v.scene.applyBatch(i, "Clone", s(v.scene, d.adapterMethods))), v.previews.clear();
85
96
  },
86
- previewIds: () => m.previews.keys(),
87
- previewPose: (e) => m.previews.get(e) ?? null
97
+ previewIds: () => v.previews.keys(),
98
+ previewPose: (e) => v.previews.get(e) ?? null
88
99
  };
89
100
  }
90
101
  },
91
102
  enabled: () => !0
92
- }, r);
103
+ }, o);
93
104
  //#endregion
94
- export { c as cloneAction };
105
+ export { d as cloneAction };
95
106
 
96
107
  //# sourceMappingURL=clone.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"clone.js","names":["cloneAction","inPlane","selection","ctx","scene","applyOps","ids","frame","scenePoseFrame","originPoses","id","scratch","poseDescriptorOf","moveCtx","dx","dy","origin","translatePoseViaDescriptor","reason","ops","originNode","newPose","node","freshNodeId","createInsertOp","defaultCommitAdapter","selectionLayer"],"sources":["../../../../src/interactions/actions/defaults/clone.ts"],"sourcesContent":["/**\n * `cloneAction` — ongoing Action descriptor for alt-drag clone.\n *\n * ## Status: REAL (scene-direct, no overlay)\n *\n * Implements the core clone-by-drag logic via insert ops committed through\n * `scene.applyBatch`:\n * - `start`: validates selection + scene; captures origin poses for all\n * selected nodes. The alt-modifier check that activates cloning in\n * `useClone` (via `CloneBehavior.activates`) is intentionally NOT applied\n * here — the descriptor fires when the dispatcher routes to it; modifier\n * discrimination is a dispatcher concern (Phase 12 TODO for alt-gating).\n * - `onMove`: tracks current drag delta in scratch (no scene writes).\n * - `onEnd('commit')`: emits one insert op per selected node (translated\n * pose) and commits them as a single batch — via the consumer `applyOps`\n * hook when present, else `scene.applyBatch(ops, 'Clone', ...)`. One\n * undo entry for the whole batch.\n * - `onEnd('cancel')`: no-op (scene never mutated during drag).\n *\n * ## What this does NOT wire (vs `useClone`)\n *\n * - Modifier gate: `useClone` only activates when `CloneBehavior.activates(mods)`\n * returns true (typically alt-held). The descriptor lacks that gate — it runs\n * whenever the dispatcher routes `clone`. Proper alt-gating requires a modifier-\n * discriminant in the dispatcher (Phase 12 TODO).\n * - Overlay: `useClone` renders a ghost via `setOverlay / clearOverlay`. The\n * descriptor has no overlay surface (deferred to Phase 7 overlay system).\n * - `expandIds`: group expansion is omitted; only leaf poses are cloned.\n * - Custom `CloneBehavior.onEnd` ops (e.g. `cloneByAltDrag`): the descriptor\n * uses a simpler `scene.add` path that does not delegate to behavior `onEnd`.\n * Behavior-pipeline cloning waits for a later phase.\n *\n * ## Pose generics\n *\n * Poses are translated through the `poseDescriptor` dep, as `moveAction` does.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { InvocationCtx, OngoingHandle } from '@weasel-js/routing';\nimport type { Node, Scene, NodeId } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { freshNodeId } from './freshNodeId';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from '../resize/geometry';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { inPlane, selectionLayer } from '../planeInput';\n\n// ---------------------------------------------------------------------------\n// Internal scratch\n// ---------------------------------------------------------------------------\n\ninterface CloneScratch {\n ids: NodeId[];\n scene: Scene<unknown, string, unknown>;\n descriptor: PoseDescriptor<unknown>;\n /** World reads and local writes over the scene's composition strategy. */\n frame: PoseFrame<unknown>;\n /** Origin poses captured at drag start, in world — the frame the drag\n * delta is expressed in. The copy keeps its source's parent, so each\n * translated result is stored back in that same frame. */\n originPoses: Map<NodeId, unknown>;\n /** Running drag delta — updated each onMove, applied once at commit. */\n currentDelta: { dx: number; dy: number };\n /** Preview poses keyed by ORIGINAL node id (the clone targets don't have\n * scene ids yet; the preview-ghost layer paints the originals' silhouette\n * at the translated pose — original stays visible at its committed home,\n * ghost appears at the drag target). */\n previews: Map<NodeId, unknown>;\n /** Optional consumer commit hook captured at gesture start. When present,\n * the insert ops route through it (consumer history) instead of\n * `scene.applyBatch`. Undefined → fall back to `scene.applyBatch`. */\n applyOps?: (ops: Op[], label: string) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Descriptor\n// ---------------------------------------------------------------------------\n\n/**\n * @experimental\n * Static descriptor for the `clone` Action.\n *\n * Requires dep-schema entries: `selection`, `scene`.\n *\n * Clones selected nodes into new scene nodes translated by the drag delta.\n * Commits insert ops via `scene.applyBatch(ops, 'Clone', ...)` (or the\n * consumer `applyOps` hook) for a single undo entry.\n *\n * @see useClone — the React hook this descriptor partially mirrors.\n */\nexport const cloneAction: Action & { requires: string[] } = inPlane({\n id: 'clone',\n label: 'Clone',\n // No default binding: a bare `{ kind: 'drag' }` would clone a non-empty\n // selection on any drag no tool claimed. Alt-drag on a body binds it\n // (`selectionMoveBindings`, the `move` preset).\n // The platform's duplicate cursor, and the whole reason this field is\n // modifier-aware: the select tool binds clone behind `mods: { alt: true }`,\n // so the pump predicts it — and shows this — only while Alt is down.\n cursor: 'copy',\n activeCursor: 'copy',\n eligible: { capability: ['edits-page', 'creates-selection'] },\n requires: ['selection', 'scene', 'applyOps', 'poseDescriptor', 'poseComposition'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, _opts): OngoingHandle {\n const selection = ctx.deps.selection as SelectionApi | undefined;\n const scene = ctx.deps.scene as Scene<unknown, string, unknown> | undefined;\n const applyOps = ctx.deps.applyOps as ((ops: Op[], label: string) => void) | undefined;\n\n if (!selection || !scene) return {};\n\n const ids = selection.get() as NodeId[];\n if (ids.length === 0) return {};\n\n // Capture origin poses once at drag start.\n const frame = scenePoseFrame(scene, ctx.deps.poseComposition);\n const originPoses = new Map<NodeId, unknown>();\n for (const id of ids) {\n if (scene.get(id) !== undefined) originPoses.set(id, frame.world(id));\n }\n\n if (originPoses.size === 0) return {};\n\n const scratch: CloneScratch = {\n ids,\n scene,\n descriptor: poseDescriptorOf(ctx.deps.poseDescriptor),\n frame,\n originPoses,\n currentDelta: { dx: 0, dy: 0 },\n previews: new Map<NodeId, unknown>(),\n applyOps,\n };\n\n return {\n kind: 'clone',\n // Clone: source stays visible at its committed pose; the ghost\n // (rendered via previewIds/previewPose below) appears at the\n // drag target. Opt out of the default \"hide source\" behavior\n // move/resize/rotate use.\n previewHidesSource: false,\n onMove(moveCtx: InvocationCtx): void {\n if (!moveCtx.drag) return;\n scratch.currentDelta = {\n dx: moveCtx.drag.delta.x,\n dy: moveCtx.drag.delta.y,\n };\n // Preview: paint each original's silhouette at the translated pose.\n // The original stays at its committed location (we don't hide it);\n // the ghost overlay shows where the new copy will land on commit.\n scratch.previews.clear();\n const { dx, dy } = scratch.currentDelta;\n if (dx === 0 && dy === 0) return;\n for (const [id, origin] of scratch.originPoses) {\n scratch.previews.set(\n id,\n scratch.frame.local(id, translatePoseViaDescriptor(origin, dx, dy, scratch.descriptor)),\n );\n }\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n if (reason === 'cancel') {\n scratch.previews.clear();\n return;\n }\n const { dx, dy } = scratch.currentDelta;\n // Zero-delta drag — no clone.\n if (dx === 0 && dy === 0) {\n scratch.previews.clear();\n return;\n }\n\n // Build one insert op per clone target — same nodes/values the old\n // direct `scene.add` loop produced (kind/layer/data/parent preserved,\n // pose translated by the drag delta), then route the batch through the\n // consumer `applyOps` hook when present (so an app with its own history\n // captures the clone as a single undo entry); otherwise commit straight\n // to the scene's own history. One applyOps / applyBatch call =\n // one undo entry, matching the prior single `scene.batch('Clone', …)`.\n const ops: Op[] = [];\n for (const id of scratch.ids) {\n const origin = scratch.originPoses.get(id);\n const originNode = scratch.scene.get(id);\n if (origin === undefined || !originNode) continue;\n const newPose = scratch.frame.local(\n id,\n translatePoseViaDescriptor(origin, dx, dy, scratch.descriptor),\n );\n // The old `scene.add` (no explicit id) minted a random id; we\n // pre-generate one so the insert op carries a full node. Id value\n // was never observable, so behavior is preserved.\n const node = {\n id: freshNodeId(),\n kind: originNode.kind,\n layer: originNode.layer,\n pose: newPose,\n data: originNode.data,\n parent: originNode.parent ?? null,\n } as Node<unknown, string, unknown>;\n ops.push(createInsertOp<Node<unknown, string, unknown>>({ node, label: 'Clone' }));\n }\n if (ops.length > 0) {\n if (scratch.applyOps) scratch.applyOps(ops, 'Clone');\n else scratch.scene.applyBatch(ops, 'Clone', defaultCommitAdapter(scratch.scene, selection.adapterMethods));\n }\n scratch.previews.clear();\n },\n previewIds: () => scratch.previews.keys(),\n previewPose: (id: string) => scratch.previews.get(id as NodeId) ?? null,\n };\n },\n },\n enabled: () => true,\n}, selectionLayer);\n"],"mappings":";;;;;;;;AA6FA,IAAaA,IAA+CC,EAAQ;CAClE,IAAI;CACJ,OAAO;CAOP,QAAQ;CACR,cAAc;CACd,UAAU,EAAE,YAAY,CAAC,cAAc,mBAAmB,EAAE;CAC5D,UAAU;EAAC;EAAa;EAAS;EAAY;EAAkB;CAAiB;CAChF,SAAS;EACP,QAAQ;EACR,MAAM,GAAoB,GAAsB;GAC9C,IAAMC,IAAYC,EAAI,KAAK,WACrBC,IAAQD,EAAI,KAAK,OACjBE,IAAWF,EAAI,KAAK;GAE1B,IAAI,CAACD,KAAa,CAACE,GAAO,OAAO,CAAC;GAElC,IAAME,IAAMJ,EAAU,IAAI;GAC1B,IAAII,EAAI,WAAW,GAAG,OAAO,CAAC;GAG9B,IAAMC,IAAQC,EAAeJ,GAAOD,EAAI,KAAK,eAAe,GACtDM,oBAAc,IAAI,IAAqB;GAC7C,KAAK,IAAMC,KAAMJ,GACf,AAAIF,EAAM,IAAIM,CAAE,MAAM,KAAA,KAAWD,EAAY,IAAIC,GAAIH,EAAM,MAAMG,CAAE,CAAC;GAGtE,IAAID,EAAY,SAAS,GAAG,OAAO,CAAC;GAEpC,IAAME,IAAwB;IAC5B;IACA;IACA,YAAYC,EAAiBT,EAAI,KAAK,cAAc;IACpD;IACA;IACA,cAAc;KAAE,IAAI;KAAG,IAAI;IAAE;IAC7B,0BAAU,IAAI,IAAqB;IACnC;GACF;GAEA,OAAO;IACL,MAAM;IAKN,oBAAoB;IACpB,OAAO,GAA8B;KACnC,IAAI,CAACU,EAAQ,MAAM;KAQnB,AAPA,EAAQ,eAAe;MACrB,IAAIA,EAAQ,KAAK,MAAM;MACvB,IAAIA,EAAQ,KAAK,MAAM;KACzB,GAIAF,EAAQ,SAAS,MAAM;KACvB,IAAM,EAAE,OAAI,UAAOA,EAAQ;KAC3B,IAAIG,MAAO,KAAKC,MAAO,GACvB,KAAK,IAAM,CAACL,GAAIM,MAAWL,EAAQ,aACjC,EAAQ,SAAS,IACfD,GACAC,EAAQ,MAAM,MAAMD,GAAIO,EAA2BD,GAAQF,GAAIC,GAAIJ,EAAQ,UAAU,CAAC,CACxF;IAEJ;IACA,MAAM,GAAwB,GAAmC;KAC/D,IAAIO,MAAW,UAAU;MACvB,EAAQ,SAAS,MAAM;MACvB;KACF;KACA,IAAM,EAAE,OAAI,UAAOP,EAAQ;KAE3B,IAAIG,MAAO,KAAKC,MAAO,GAAG;MACxB,EAAQ,SAAS,MAAM;MACvB;KACF;KASA,IAAMI,IAAY,CAAC;KACnB,KAAK,IAAMT,KAAMC,EAAQ,KAAK;MAC5B,IAAMK,IAASL,EAAQ,YAAY,IAAID,CAAE,GACnCU,IAAaT,EAAQ,MAAM,IAAID,CAAE;MACvC,IAAIM,MAAW,KAAA,KAAa,CAACI,GAAY;MACzC,IAAMC,IAAUV,EAAQ,MAAM,MAC5BD,GACAO,EAA2BD,GAAQF,GAAIC,GAAIJ,EAAQ,UAAU,CAC/D,GAIMW,IAAO;OACX,IAAIC,EAAY;OAChB,MAAMH,EAAW;OACjB,OAAOA,EAAW;OAClB,MAAMC;OACN,MAAMD,EAAW;OACjB,QAAQA,EAAW,UAAU;MAC/B;MACA,EAAI,KAAKI,EAA+C;OAAE;OAAM,OAAO;MAAQ,CAAC,CAAC;KACnF;KAKA,AAJIL,EAAI,SAAS,MACXR,EAAQ,WAAUA,EAAQ,SAASQ,GAAK,OAAO,IAC9CR,EAAQ,MAAM,WAAWQ,GAAK,SAASM,EAAqBd,EAAQ,OAAOT,EAAU,cAAc,CAAC,IAE3GS,EAAQ,SAAS,MAAM;IACzB;IACA,kBAAkBA,EAAQ,SAAS,KAAK;IACxC,cAAc,MAAeA,EAAQ,SAAS,IAAID,CAAY,KAAK;GACrE;EACF;CACF;CACA,eAAe;AACjB,GAAGgB,CAAc"}
1
+ {"version":3,"file":"clone.js","names":["cloneAction","inPlane","selection","ctx","scene","applyOps","ids","frame","scenePoseFrame","originPoses","descriptor","poseDescriptorOf","id","node","toEdited","invertPlane","planeOf","carryPose","scratch","landed","origin","moved","translatePoseViaDescriptor","dx","dy","moveCtx","reason","ops","originNode","newPose","freshNodeId","createInsertOp","defaultCommitAdapter","selectionLayer"],"sources":["../../../../src/interactions/actions/defaults/clone.ts"],"sourcesContent":["/**\n * `cloneAction` — ongoing Action descriptor for alt-drag clone.\n *\n * ## Status: REAL (scene-direct, no overlay)\n *\n * Implements the core clone-by-drag logic via insert ops committed through\n * `scene.applyBatch`:\n * - `start`: validates selection + scene; captures origin poses for all\n * selected nodes. The alt-modifier check that activates cloning in\n * `useClone` (via `CloneBehavior.activates`) is intentionally NOT applied\n * here — the descriptor fires when the dispatcher routes to it; modifier\n * discrimination is a dispatcher concern (Phase 12 TODO for alt-gating).\n * - `onMove`: tracks current drag delta in scratch (no scene writes).\n * - `onEnd('commit')`: emits one insert op per selected node (translated\n * pose) and commits them as a single batch — via the consumer `applyOps`\n * hook when present, else `scene.applyBatch(ops, 'Clone', ...)`. One\n * undo entry for the whole batch.\n * - `onEnd('cancel')`: no-op (scene never mutated during drag).\n *\n * ## What this does NOT wire (vs `useClone`)\n *\n * - Modifier gate: `useClone` only activates when `CloneBehavior.activates(mods)`\n * returns true (typically alt-held). The descriptor lacks that gate — it runs\n * whenever the dispatcher routes `clone`. Proper alt-gating requires a modifier-\n * discriminant in the dispatcher (Phase 12 TODO).\n * - Overlay: `useClone` renders a ghost via `setOverlay / clearOverlay`. The\n * descriptor has no overlay surface (deferred to Phase 7 overlay system).\n * - `expandIds`: group expansion is omitted; only leaf poses are cloned.\n * - Custom `CloneBehavior.onEnd` ops (e.g. `cloneByAltDrag`): the descriptor\n * uses a simpler `scene.add` path that does not delegate to behavior `onEnd`.\n * Behavior-pipeline cloning waits for a later phase.\n *\n * ## Pose generics\n *\n * Poses are translated through the `poseDescriptor` dep, as `moveAction` does.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { InvocationCtx, OngoingHandle } from '@weasel-js/routing';\nimport type { Node, Scene, NodeId } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { freshNodeId } from './freshNodeId';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from '../resize/geometry';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { carryPose, invertPlane, inPlane, planeOf, selectionLayer } from '../planeInput';\n\n// ---------------------------------------------------------------------------\n// Internal scratch\n// ---------------------------------------------------------------------------\n\ninterface CloneScratch {\n ids: NodeId[];\n scene: Scene<unknown, string, unknown>;\n descriptor: PoseDescriptor<unknown>;\n /** World reads and local writes over the scene's composition strategy. */\n frame: PoseFrame<unknown>;\n /** Origin poses captured at drag start, in world — the frame the drag\n * delta is expressed in, and the plane the edit is measured in. The copy\n * keeps its source's parent and layer, so each translated result is\n * carried back to that layer's plane and stored in that same frame. */\n originPoses: Map<NodeId, unknown>;\n /** The view the invocation started with, read for `planeOf`. */\n view: unknown;\n /** Running drag delta — updated each onMove, applied once at commit. */\n currentDelta: { dx: number; dy: number };\n /** Preview poses keyed by ORIGINAL node id (the clone targets don't have\n * scene ids yet; the preview-ghost layer paints the originals' silhouette\n * at the translated pose — original stays visible at its committed home,\n * ghost appears at the drag target). */\n previews: Map<NodeId, unknown>;\n /** Optional consumer commit hook captured at gesture start. When present,\n * the insert ops route through it (consumer history) instead of\n * `scene.applyBatch`. Undefined → fall back to `scene.applyBatch`. */\n applyOps?: (ops: Op[], label: string) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Descriptor\n// ---------------------------------------------------------------------------\n\n/**\n * @experimental\n * Static descriptor for the `clone` Action.\n *\n * Requires dep-schema entries: `selection`, `scene`.\n *\n * Clones selected nodes into new scene nodes translated by the drag delta.\n * Commits insert ops via `scene.applyBatch(ops, 'Clone', ...)` (or the\n * consumer `applyOps` hook) for a single undo entry.\n *\n * @see useClone — the React hook this descriptor partially mirrors.\n */\nexport const cloneAction: Action & { requires: string[] } = inPlane({\n id: 'clone',\n label: 'Clone',\n // No default binding: a bare `{ kind: 'drag' }` would clone a non-empty\n // selection on any drag no tool claimed. Alt-drag on a body binds it\n // (`selectionMoveBindings`, the `move` preset).\n // The platform's duplicate cursor, and the whole reason this field is\n // modifier-aware: the select tool binds clone behind `mods: { alt: true }`,\n // so the pump predicts it — and shows this — only while Alt is down.\n cursor: 'copy',\n activeCursor: 'copy',\n eligible: { capability: ['edits-page', 'creates-selection'] },\n requires: ['selection', 'scene', 'applyOps', 'poseDescriptor', 'poseComposition'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, _opts): OngoingHandle {\n const selection = ctx.deps.selection as SelectionApi | undefined;\n const scene = ctx.deps.scene as Scene<unknown, string, unknown> | undefined;\n const applyOps = ctx.deps.applyOps as ((ops: Op[], label: string) => void) | undefined;\n\n if (!selection || !scene) return {};\n\n const ids = selection.get() as NodeId[];\n if (ids.length === 0) return {};\n\n // Capture origin poses once at drag start.\n const frame = scenePoseFrame(scene, ctx.deps.poseComposition);\n const originPoses = new Map<NodeId, unknown>();\n const descriptor = poseDescriptorOf(ctx.deps.poseDescriptor);\n for (const id of ids) {\n const node = scene.get(id);\n if (node === undefined) continue;\n const toEdited = invertPlane(planeOf(ctx.deps.view, node.layer));\n originPoses.set(id, carryPose(descriptor, frame.world(id), toEdited));\n }\n\n if (originPoses.size === 0) return {};\n\n const scratch: CloneScratch = {\n ids,\n scene,\n descriptor,\n frame,\n originPoses,\n view: ctx.deps.view,\n currentDelta: { dx: 0, dy: 0 },\n previews: new Map<NodeId, unknown>(),\n applyOps,\n };\n\n /** Where the copy of `id` lands for a drag of `(dx, dy)`, as stored. */\n const landed = (id: NodeId, dx: number, dy: number): unknown => {\n const origin = scratch.originPoses.get(id);\n const node = scratch.scene.get(id);\n if (origin === undefined || !node) return undefined;\n const moved = translatePoseViaDescriptor(origin, dx, dy, scratch.descriptor);\n return scratch.frame.local(id, carryPose(scratch.descriptor, moved, planeOf(scratch.view, node.layer)));\n };\n\n return {\n kind: 'clone',\n // Clone: source stays visible at its committed pose; the ghost\n // (rendered via previewIds/previewPose below) appears at the\n // drag target. Opt out of the default \"hide source\" behavior\n // move/resize/rotate use.\n previewHidesSource: false,\n onMove(moveCtx: InvocationCtx): void {\n if (!moveCtx.drag) return;\n scratch.currentDelta = {\n dx: moveCtx.drag.delta.x,\n dy: moveCtx.drag.delta.y,\n };\n // Preview: paint each original's silhouette at the translated pose.\n // The original stays at its committed location (we don't hide it);\n // the ghost overlay shows where the new copy will land on commit.\n scratch.previews.clear();\n const { dx, dy } = scratch.currentDelta;\n if (dx === 0 && dy === 0) return;\n for (const id of scratch.originPoses.keys()) scratch.previews.set(id, landed(id, dx, dy)!);\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n if (reason === 'cancel') {\n scratch.previews.clear();\n return;\n }\n const { dx, dy } = scratch.currentDelta;\n // Zero-delta drag — no clone.\n if (dx === 0 && dy === 0) {\n scratch.previews.clear();\n return;\n }\n\n // Build one insert op per clone target — same nodes/values the old\n // direct `scene.add` loop produced (kind/layer/data/parent preserved,\n // pose translated by the drag delta), then route the batch through the\n // consumer `applyOps` hook when present (so an app with its own history\n // captures the clone as a single undo entry); otherwise commit straight\n // to the scene's own history. One applyOps / applyBatch call =\n // one undo entry, matching the prior single `scene.batch('Clone', …)`.\n const ops: Op[] = [];\n for (const id of scratch.ids) {\n const originNode = scratch.scene.get(id);\n const newPose = landed(id, dx, dy);\n if (newPose === undefined || !originNode) continue;\n // The old `scene.add` (no explicit id) minted a random id; we\n // pre-generate one so the insert op carries a full node. Id value\n // was never observable, so behavior is preserved.\n const node = {\n id: freshNodeId(),\n kind: originNode.kind,\n layer: originNode.layer,\n pose: newPose,\n data: originNode.data,\n parent: originNode.parent ?? null,\n } as Node<unknown, string, unknown>;\n ops.push(createInsertOp<Node<unknown, string, unknown>>({ node, label: 'Clone' }));\n }\n if (ops.length > 0) {\n if (scratch.applyOps) scratch.applyOps(ops, 'Clone');\n else scratch.scene.applyBatch(ops, 'Clone', defaultCommitAdapter(scratch.scene, selection.adapterMethods));\n }\n scratch.previews.clear();\n },\n previewIds: () => scratch.previews.keys(),\n previewPose: (id: string) => scratch.previews.get(id as NodeId) ?? null,\n };\n },\n },\n enabled: () => true,\n}, selectionLayer);\n"],"mappings":"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"}