@oh-just-another/state 0.58.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +158 -0
- package/README.md +78 -27
- package/dist/.tsbuildinfo +1 -1
- package/dist/actions/actionArrange.d.ts +13 -0
- package/dist/actions/actionArrange.d.ts.map +1 -0
- package/dist/actions/actionArrange.js +130 -0
- package/dist/actions/actionArrange.js.map +1 -0
- package/dist/actions/actionClipboard.d.ts +2 -0
- package/dist/actions/actionClipboard.d.ts.map +1 -1
- package/dist/actions/actionClipboard.js +32 -1
- package/dist/actions/actionClipboard.js.map +1 -1
- package/dist/actions/actionKeyboard.d.ts.map +1 -1
- package/dist/actions/actionKeyboard.js +77 -9
- package/dist/actions/actionKeyboard.js.map +1 -1
- package/dist/actions/actionMode.d.ts +4 -0
- package/dist/actions/actionMode.d.ts.map +1 -1
- package/dist/actions/actionMode.js +54 -0
- package/dist/actions/actionMode.js.map +1 -1
- package/dist/actions/actionSelection.d.ts.map +1 -1
- package/dist/actions/actionSelection.js +1 -0
- package/dist/actions/actionSelection.js.map +1 -1
- package/dist/actions/actionText.d.ts +5 -0
- package/dist/actions/actionText.d.ts.map +1 -0
- package/dist/actions/actionText.js +37 -0
- package/dist/actions/actionText.js.map +1 -0
- package/dist/actions/actionView.d.ts +6 -0
- package/dist/actions/actionView.d.ts.map +1 -1
- package/dist/actions/actionView.js +20 -2
- package/dist/actions/actionView.js.map +1 -1
- package/dist/actions/actionZoom.d.ts.map +1 -1
- package/dist/actions/actionZoom.js +5 -0
- package/dist/actions/actionZoom.js.map +1 -1
- package/dist/actions/index.d.ts +6 -4
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +6 -4
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/registry.d.ts.map +1 -1
- package/dist/actions/registry.js +17 -0
- package/dist/actions/registry.js.map +1 -1
- package/dist/actions/types.d.ts +10 -1
- package/dist/actions/types.d.ts.map +1 -1
- package/dist/actions/types.js.map +1 -1
- package/dist/auto-layout-scheduler.d.ts +1 -3
- package/dist/auto-layout-scheduler.d.ts.map +1 -1
- package/dist/auto-layout-scheduler.js +1 -2
- package/dist/auto-layout-scheduler.js.map +1 -1
- package/dist/built-in-handlers.d.ts.map +1 -1
- package/dist/built-in-handlers.js +14 -1
- package/dist/built-in-handlers.js.map +1 -1
- package/dist/clipboard.d.ts +0 -14
- package/dist/clipboard.d.ts.map +1 -1
- package/dist/clipboard.js +1 -1
- package/dist/clipboard.js.map +1 -1
- package/dist/constants.d.ts +208 -41
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +210 -25
- package/dist/constants.js.map +1 -1
- package/dist/dom-events.d.ts +8 -2
- package/dist/dom-events.d.ts.map +1 -1
- package/dist/dom-events.js +12 -0
- package/dist/dom-events.js.map +1 -1
- package/dist/editor/animation-scene.d.ts +36 -0
- package/dist/editor/animation-scene.d.ts.map +1 -0
- package/dist/editor/animation-scene.js +194 -0
- package/dist/editor/animation-scene.js.map +1 -0
- package/dist/editor/animation.d.ts +43 -0
- package/dist/editor/animation.d.ts.map +1 -0
- package/dist/editor/animation.js +80 -0
- package/dist/editor/animation.js.map +1 -0
- package/dist/editor/applies/arrange.d.ts +46 -0
- package/dist/editor/applies/arrange.d.ts.map +1 -0
- package/dist/editor/applies/arrange.js +162 -0
- package/dist/editor/applies/arrange.js.map +1 -0
- package/dist/editor/applies/create.d.ts +0 -6
- package/dist/editor/applies/create.d.ts.map +1 -1
- package/dist/editor/applies/create.js +1 -1
- package/dist/editor/applies/create.js.map +1 -1
- package/dist/editor/applies/edge.d.ts +8 -1
- package/dist/editor/applies/edge.d.ts.map +1 -1
- package/dist/editor/applies/edge.js +31 -1
- package/dist/editor/applies/edge.js.map +1 -1
- package/dist/editor/applies/link-move.d.ts +0 -8
- package/dist/editor/applies/link-move.d.ts.map +1 -1
- package/dist/editor/applies/link-move.js +1 -1
- package/dist/editor/applies/link-move.js.map +1 -1
- package/dist/editor/applies/move.d.ts +6 -0
- package/dist/editor/applies/move.d.ts.map +1 -1
- package/dist/editor/applies/move.js +6 -0
- package/dist/editor/applies/move.js.map +1 -1
- package/dist/editor/applies/resize.d.ts +26 -5
- package/dist/editor/applies/resize.d.ts.map +1 -1
- package/dist/editor/applies/resize.js +91 -13
- package/dist/editor/applies/resize.js.map +1 -1
- package/dist/editor/caret-blink.d.ts +18 -0
- package/dist/editor/caret-blink.d.ts.map +1 -0
- package/dist/editor/caret-blink.js +42 -0
- package/dist/editor/caret-blink.js.map +1 -0
- package/dist/editor/container-ops.d.ts.map +1 -1
- package/dist/editor/container-ops.js +2 -2
- package/dist/editor/container-ops.js.map +1 -1
- package/dist/editor/dirty-rect.d.ts +23 -0
- package/dist/editor/dirty-rect.d.ts.map +1 -0
- package/dist/editor/dirty-rect.js +115 -0
- package/dist/editor/dirty-rect.js.map +1 -0
- package/dist/editor/gif-playback.d.ts +45 -0
- package/dist/editor/gif-playback.d.ts.map +1 -0
- package/dist/editor/gif-playback.js +125 -0
- package/dist/editor/gif-playback.js.map +1 -0
- package/dist/editor/hit-test.d.ts +3 -3
- package/dist/editor/hit-test.d.ts.map +1 -1
- package/dist/editor/hit-test.js +40 -15
- package/dist/editor/hit-test.js.map +1 -1
- package/dist/editor/interaction-state.d.ts +184 -0
- package/dist/editor/interaction-state.d.ts.map +1 -0
- package/dist/editor/interaction-state.js +139 -0
- package/dist/editor/interaction-state.js.map +1 -0
- package/dist/editor/link-handle-drag.d.ts +152 -0
- package/dist/editor/link-handle-drag.d.ts.map +1 -0
- package/dist/editor/link-handle-drag.js +300 -0
- package/dist/editor/link-handle-drag.js.map +1 -0
- package/dist/editor/long-press.d.ts.map +1 -1
- package/dist/editor/long-press.js +2 -2
- package/dist/editor/long-press.js.map +1 -1
- package/dist/editor/pinch.d.ts.map +1 -1
- package/dist/editor/pinch.js +6 -6
- package/dist/editor/pinch.js.map +1 -1
- package/dist/editor/pointer-binding.d.ts +9 -11
- package/dist/editor/pointer-binding.d.ts.map +1 -1
- package/dist/editor/pointer-binding.js +1191 -890
- package/dist/editor/pointer-binding.js.map +1 -1
- package/dist/editor/public/arrange-group.d.ts +3 -9
- package/dist/editor/public/arrange-group.d.ts.map +1 -1
- package/dist/editor/public/arrange-group.js +4 -6
- package/dist/editor/public/arrange-group.js.map +1 -1
- package/dist/editor/public/brush.d.ts +31 -12
- package/dist/editor/public/brush.d.ts.map +1 -1
- package/dist/editor/public/brush.js +66 -17
- package/dist/editor/public/brush.js.map +1 -1
- package/dist/editor/public/clipboard.d.ts +2 -4
- package/dist/editor/public/clipboard.d.ts.map +1 -1
- package/dist/editor/public/clipboard.js +2 -4
- package/dist/editor/public/clipboard.js.map +1 -1
- package/dist/editor/public/cursor.d.ts +29 -0
- package/dist/editor/public/cursor.d.ts.map +1 -0
- package/dist/editor/public/cursor.js +146 -0
- package/dist/editor/public/cursor.js.map +1 -0
- package/dist/editor/public/eraser.d.ts +55 -0
- package/dist/editor/public/eraser.d.ts.map +1 -0
- package/dist/editor/public/eraser.js +65 -0
- package/dist/editor/public/eraser.js.map +1 -0
- package/dist/editor/public/frame-name.d.ts +20 -0
- package/dist/editor/public/frame-name.d.ts.map +1 -0
- package/dist/editor/public/frame-name.js +54 -0
- package/dist/editor/public/frame-name.js.map +1 -0
- package/dist/editor/public/image-insert.d.ts +1 -1
- package/dist/editor/public/image-insert.d.ts.map +1 -1
- package/dist/editor/public/laser.d.ts +38 -0
- package/dist/editor/public/laser.d.ts.map +1 -0
- package/dist/editor/public/laser.js +42 -0
- package/dist/editor/public/laser.js.map +1 -0
- package/dist/editor/public/layers.d.ts.map +1 -1
- package/dist/editor/public/layers.js +2 -2
- package/dist/editor/public/layers.js.map +1 -1
- package/dist/editor/public/link.d.ts +11 -2
- package/dist/editor/public/link.d.ts.map +1 -1
- package/dist/editor/public/link.js +70 -2
- package/dist/editor/public/link.js.map +1 -1
- package/dist/editor/public/placement.d.ts +60 -2
- package/dist/editor/public/placement.d.ts.map +1 -1
- package/dist/editor/public/placement.js +193 -2
- package/dist/editor/public/placement.js.map +1 -1
- package/dist/editor/public/selection-ops.d.ts +35 -1
- package/dist/editor/public/selection-ops.d.ts.map +1 -1
- package/dist/editor/public/selection-ops.js +97 -2
- package/dist/editor/public/selection-ops.js.map +1 -1
- package/dist/editor/public/stroke-eraser-coverage.d.ts +37 -0
- package/dist/editor/public/stroke-eraser-coverage.d.ts.map +1 -0
- package/dist/editor/public/stroke-eraser-coverage.js +168 -0
- package/dist/editor/public/stroke-eraser-coverage.js.map +1 -0
- package/dist/editor/public/stroke-eraser.d.ts +50 -0
- package/dist/editor/public/stroke-eraser.d.ts.map +1 -0
- package/dist/editor/public/stroke-eraser.js +176 -0
- package/dist/editor/public/stroke-eraser.js.map +1 -0
- package/dist/editor/public/stroke-smoothing.d.ts +21 -0
- package/dist/editor/public/stroke-smoothing.d.ts.map +1 -0
- package/dist/editor/public/stroke-smoothing.js +37 -0
- package/dist/editor/public/stroke-smoothing.js.map +1 -0
- package/dist/editor/public/text-edit.d.ts +1 -10
- package/dist/editor/public/text-edit.d.ts.map +1 -1
- package/dist/editor/public/text-edit.js +2 -16
- package/dist/editor/public/text-edit.js.map +1 -1
- package/dist/editor/public/tool-ops.d.ts +130 -0
- package/dist/editor/public/tool-ops.d.ts.map +1 -0
- package/dist/editor/public/tool-ops.js +392 -0
- package/dist/editor/public/tool-ops.js.map +1 -0
- package/dist/editor/public/z-order.d.ts +1 -12
- package/dist/editor/public/z-order.d.ts.map +1 -1
- package/dist/editor/public/z-order.js +5 -5
- package/dist/editor/public/z-order.js.map +1 -1
- package/dist/editor/public/zoom-pan.d.ts +15 -4
- package/dist/editor/public/zoom-pan.d.ts.map +1 -1
- package/dist/editor/public/zoom-pan.js +39 -7
- package/dist/editor/public/zoom-pan.js.map +1 -1
- package/dist/editor/render-orchestrator.d.ts +177 -5
- package/dist/editor/render-orchestrator.d.ts.map +1 -1
- package/dist/editor/render-orchestrator.js +519 -358
- package/dist/editor/render-orchestrator.js.map +1 -1
- package/dist/editor/resize-helpers.d.ts +21 -5
- package/dist/editor/resize-helpers.d.ts.map +1 -1
- package/dist/editor/resize-helpers.js +59 -19
- package/dist/editor/resize-helpers.js.map +1 -1
- package/dist/editor/text-edit.d.ts +136 -0
- package/dist/editor/text-edit.d.ts.map +1 -0
- package/dist/editor/text-edit.js +328 -0
- package/dist/editor/text-edit.js.map +1 -0
- package/dist/editor/viewport-helpers.d.ts.map +1 -1
- package/dist/editor/viewport-helpers.js +3 -3
- package/dist/editor/viewport-helpers.js.map +1 -1
- package/dist/editor-events.d.ts +1 -1
- package/dist/editor-events.d.ts.map +1 -1
- package/dist/editor.d.ts +603 -346
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +1843 -1630
- package/dist/editor.js.map +1 -1
- package/dist/file-drop.d.ts.map +1 -1
- package/dist/file-drop.js +1 -2
- package/dist/file-drop.js.map +1 -1
- package/dist/frame-helpers.d.ts.map +1 -1
- package/dist/frame-helpers.js +5 -5
- package/dist/frame-helpers.js.map +1 -1
- package/dist/group-helpers.d.ts.map +1 -1
- package/dist/group-helpers.js +4 -4
- package/dist/group-helpers.js.map +1 -1
- package/dist/handle.d.ts +59 -6
- package/dist/handle.d.ts.map +1 -1
- package/dist/handle.js +99 -7
- package/dist/handle.js.map +1 -1
- package/dist/hotkeys-binding.d.ts +26 -0
- package/dist/hotkeys-binding.d.ts.map +1 -0
- package/dist/hotkeys-binding.js +35 -0
- package/dist/hotkeys-binding.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/link-selection.d.ts +3 -5
- package/dist/link-selection.d.ts.map +1 -1
- package/dist/link-selection.js +3 -12
- package/dist/link-selection.js.map +1 -1
- package/dist/machine.d.ts +27 -1
- package/dist/machine.d.ts.map +1 -1
- package/dist/machine.js +38 -0
- package/dist/machine.js.map +1 -1
- package/dist/modes.d.ts +15 -1
- package/dist/modes.d.ts.map +1 -1
- package/dist/modes.js.map +1 -1
- package/dist/overlay.d.ts +92 -6
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +582 -125
- package/dist/overlay.js.map +1 -1
- package/dist/search.d.ts +37 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +45 -0
- package/dist/search.js.map +1 -0
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +2 -10
- package/dist/selection.js.map +1 -1
- package/dist/util.d.ts +8 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +17 -0
- package/dist/util.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ephemeral interaction / gesture state for a single {@link Editor}.
|
|
3
|
+
*
|
|
4
|
+
* Collects the short-lived preview and gesture-origin fields that the pointer
|
|
5
|
+
* handlers, render orchestrator and container-ops helpers read and write while
|
|
6
|
+
* a gesture is in flight. Long-lived state (scene, selection, history,
|
|
7
|
+
* viewport, mode) lives on the editor itself — never here.
|
|
8
|
+
*
|
|
9
|
+
* The editor owns one instance and exposes thin delegate accessors for the
|
|
10
|
+
* fields external writers already reference by name, so this consolidation is
|
|
11
|
+
* behaviour-preserving.
|
|
12
|
+
*/
|
|
13
|
+
export class InteractionState {
|
|
14
|
+
// --- Visual previews (cleared by resetPreviews) ---
|
|
15
|
+
/** Live preview while drawing a new shape; null when not drawing. */
|
|
16
|
+
drawingPreview = null;
|
|
17
|
+
/** Live preview of an edge being drawn. */
|
|
18
|
+
edgePreview = null;
|
|
19
|
+
/** Live lasso bounds during a rubber-band select gesture. */
|
|
20
|
+
lassoPreview = null;
|
|
21
|
+
/** Element hovered in draw-edge mode (drives the port overlay). */
|
|
22
|
+
hoveredLinkTarget = null;
|
|
23
|
+
/** Last idle cursor position (world) in select mode — grows the nearest dot. */
|
|
24
|
+
hoverCursorWorld = null;
|
|
25
|
+
// --- Other gesture / interaction state ---
|
|
26
|
+
/** In-progress annotation-pin drag. */
|
|
27
|
+
annotationDrag = null;
|
|
28
|
+
/** Active drag-a-link-from-anchor gesture. */
|
|
29
|
+
linkDragFromAnchor = null;
|
|
30
|
+
/** Pending link-drop shape-picker. */
|
|
31
|
+
pendingLinkDropMenu = null;
|
|
32
|
+
/**
|
|
33
|
+
* Selection captured at lasso-press time — lets `add`-mode marquee start
|
|
34
|
+
* from the pre-press selection instead of empty.
|
|
35
|
+
*/
|
|
36
|
+
lassoBaseSelection = null;
|
|
37
|
+
/** Link-selection counterpart of `lassoBaseSelection`. */
|
|
38
|
+
lassoBaseLinks = null;
|
|
39
|
+
/** Per-shape `position` snapshot at press-down for a multi-shape drag. */
|
|
40
|
+
groupMoveOrigin = null;
|
|
41
|
+
/** Press-time snapshot of connectors that follow a multi-element drag rigidly. */
|
|
42
|
+
groupLinkMoveOrigin = null;
|
|
43
|
+
/** Per-shape snapshot for a group-resize gesture. */
|
|
44
|
+
groupResizeOrigin = null;
|
|
45
|
+
/** Press-time snapshot for a rotate gesture. */
|
|
46
|
+
rotateGestureOrigin = null;
|
|
47
|
+
/** Pristine shape snapshot for a single-shape text resize. */
|
|
48
|
+
resizeOriginElement = null;
|
|
49
|
+
/** Host-mirrored snap-suppress modifier (Cmd/Ctrl) held during a drag. */
|
|
50
|
+
snapSuppressed = false;
|
|
51
|
+
/** Host-mirrored transform-modifier: symmetric resize about centre. */
|
|
52
|
+
transformAltKey = false;
|
|
53
|
+
/** Host-mirrored transform-modifier: aspect-lock resize / axis-lock move. */
|
|
54
|
+
transformShiftKey = false;
|
|
55
|
+
/** Timestamp of the last non-drag pointer-up (double-click detection). */
|
|
56
|
+
lastClickAt = 0;
|
|
57
|
+
/** World point of the last non-drag pointer-up (double-click detection). */
|
|
58
|
+
lastClickWorldPoint = null;
|
|
59
|
+
/** In-progress brush stroke (live overlay preview). */
|
|
60
|
+
brushStroke = null;
|
|
61
|
+
/** In-progress eraser stroke (pending-delete set + last sample point). */
|
|
62
|
+
eraseStroke = null;
|
|
63
|
+
/** Ephemeral laser-pointer trails — fade by TTL, never touch the scene. */
|
|
64
|
+
laserStrokes = [];
|
|
65
|
+
/**
|
|
66
|
+
* Ephemeral eraser drag trail — a laser-style fading trail laid while an
|
|
67
|
+
* erase stroke is active. Reuses {@link LaserStroke} so the same TTL fade /
|
|
68
|
+
* prune tick drives it; painted in a neutral grey, never the laser red.
|
|
69
|
+
*/
|
|
70
|
+
eraserTrail = [];
|
|
71
|
+
/** True only while the pointer is DOWN in laser mode (a trail is being laid). */
|
|
72
|
+
laserDrawing = false;
|
|
73
|
+
/** Last world-space pointer position observed by the host's onMove handler. */
|
|
74
|
+
lastPointerWorld = null;
|
|
75
|
+
/** Element id the user started dragging on press-down. */
|
|
76
|
+
dragElementId = null;
|
|
77
|
+
/** Element the current press added to the selection additively. */
|
|
78
|
+
additivePressAdded = null;
|
|
79
|
+
/** Live container highlight for the shape being dragged. */
|
|
80
|
+
containerHover = null;
|
|
81
|
+
/** Active screen-space pointer positions keyed by `pointerId`. */
|
|
82
|
+
activePointers = new Map();
|
|
83
|
+
/** One-finger-pan candidate (screen-space origin) set at touch press-down. */
|
|
84
|
+
touchPanCandidate = null;
|
|
85
|
+
/** Space-bar held → next pointer drag pans the canvas. */
|
|
86
|
+
spaceHeld = false;
|
|
87
|
+
/** Active pan gesture, or null between gestures. */
|
|
88
|
+
panGesture = null;
|
|
89
|
+
/** Set on right-click pointerdown so the next native contextmenu is suppressed. */
|
|
90
|
+
suppressNextContextMenu = false;
|
|
91
|
+
/** Link whose caption is being inline-edited, or null. */
|
|
92
|
+
editingLinkCaption = null;
|
|
93
|
+
/**
|
|
94
|
+
* Reset ONLY the visual-preview fields (draw / edge / lasso previews and the
|
|
95
|
+
* draw-edge hover overlay). Leaves gesture origins and modifier state intact.
|
|
96
|
+
*/
|
|
97
|
+
resetPreviews() {
|
|
98
|
+
this.drawingPreview = null;
|
|
99
|
+
this.edgePreview = null;
|
|
100
|
+
this.lassoPreview = null;
|
|
101
|
+
this.hoveredLinkTarget = null;
|
|
102
|
+
this.hoverCursorWorld = null;
|
|
103
|
+
}
|
|
104
|
+
/** Full teardown — return every ephemeral field to its default. */
|
|
105
|
+
reset() {
|
|
106
|
+
this.resetPreviews();
|
|
107
|
+
this.annotationDrag = null;
|
|
108
|
+
this.linkDragFromAnchor = null;
|
|
109
|
+
this.pendingLinkDropMenu = null;
|
|
110
|
+
this.lassoBaseSelection = null;
|
|
111
|
+
this.lassoBaseLinks = null;
|
|
112
|
+
this.groupMoveOrigin = null;
|
|
113
|
+
this.groupLinkMoveOrigin = null;
|
|
114
|
+
this.groupResizeOrigin = null;
|
|
115
|
+
this.rotateGestureOrigin = null;
|
|
116
|
+
this.resizeOriginElement = null;
|
|
117
|
+
this.snapSuppressed = false;
|
|
118
|
+
this.transformAltKey = false;
|
|
119
|
+
this.transformShiftKey = false;
|
|
120
|
+
this.lastClickAt = 0;
|
|
121
|
+
this.lastClickWorldPoint = null;
|
|
122
|
+
this.brushStroke = null;
|
|
123
|
+
this.eraseStroke = null;
|
|
124
|
+
this.laserStrokes = [];
|
|
125
|
+
this.eraserTrail = [];
|
|
126
|
+
this.laserDrawing = false;
|
|
127
|
+
this.lastPointerWorld = null;
|
|
128
|
+
this.dragElementId = null;
|
|
129
|
+
this.additivePressAdded = null;
|
|
130
|
+
this.containerHover = null;
|
|
131
|
+
this.activePointers.clear();
|
|
132
|
+
this.touchPanCandidate = null;
|
|
133
|
+
this.spaceHeld = false;
|
|
134
|
+
this.panGesture = null;
|
|
135
|
+
this.suppressNextContextMenu = false;
|
|
136
|
+
this.editingLinkCaption = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=interaction-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction-state.js","sourceRoot":"","sources":["../../src/editor/interaction-state.ts"],"names":[],"mappings":"AA2FA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,gBAAgB;IAC3B,qDAAqD;IAErD,qEAAqE;IACrE,cAAc,GAAkB,IAAI,CAAC;IACrC,2CAA2C;IAC3C,WAAW,GAAuB,IAAI,CAAC;IACvC,6DAA6D;IAC7D,YAAY,GAAkB,IAAI,CAAC;IACnC,mEAAmE;IACnE,iBAAiB,GAA6B,IAAI,CAAC;IACnD,gFAAgF;IAChF,gBAAgB,GAAgB,IAAI,CAAC;IAErC,4CAA4C;IAE5C,uCAAuC;IACvC,cAAc,GAA0B,IAAI,CAAC;IAC7C,8CAA8C;IAC9C,kBAAkB,GAA8B,IAAI,CAAC;IACrD,sCAAsC;IACtC,mBAAmB,GAA+B,IAAI,CAAC;IAEvD;;;OAGG;IACH,kBAAkB,GAA+B,IAAI,CAAC;IACtD,0DAA0D;IAC1D,cAAc,GAAuC,IAAI,CAAC;IAE1D,0EAA0E;IAC1E,eAAe,GAAwC,IAAI,CAAC;IAC5D,kFAAkF;IAClF,mBAAmB,GAAqC,IAAI,CAAC;IAC7D,qDAAqD;IACrD,iBAAiB,GAA6B,IAAI,CAAC;IACnD,gDAAgD;IAChD,mBAAmB,GAA+B,IAAI,CAAC;IACvD,8DAA8D;IAC9D,mBAAmB,GAAmB,IAAI,CAAC;IAE3C,0EAA0E;IAC1E,cAAc,GAAG,KAAK,CAAC;IACvB,uEAAuE;IACvE,eAAe,GAAG,KAAK,CAAC;IACxB,6EAA6E;IAC7E,iBAAiB,GAAG,KAAK,CAAC;IAE1B,0EAA0E;IAC1E,WAAW,GAAG,CAAC,CAAC;IAChB,4EAA4E;IAC5E,mBAAmB,GAAgB,IAAI,CAAC;IAExC,uDAAuD;IACvD,WAAW,GAA4B,IAAI,CAAC;IAC5C,0EAA0E;IAC1E,WAAW,GAA4B,IAAI,CAAC;IAC5C,2EAA2E;IAC3E,YAAY,GAAkB,EAAE,CAAC;IACjC;;;;OAIG;IACH,WAAW,GAAkB,EAAE,CAAC;IAChC,iFAAiF;IACjF,YAAY,GAAG,KAAK,CAAC;IACrB,+EAA+E;IAC/E,gBAAgB,GAAgB,IAAI,CAAC;IAErC,0DAA0D;IAC1D,aAAa,GAAqB,IAAI,CAAC;IACvC,mEAAmE;IACnE,kBAAkB,GAAqB,IAAI,CAAC;IAC5C,4DAA4D;IAC5D,cAAc,GAA0B,IAAI,CAAC;IAE7C,kEAAkE;IACzD,cAAc,GAAG,IAAI,GAAG,EAAgB,CAAC;IAClD,8EAA8E;IAC9E,iBAAiB,GAAgB,IAAI,CAAC;IACtC,0DAA0D;IAC1D,SAAS,GAAG,KAAK,CAAC;IAClB,oDAAoD;IACpD,UAAU,GAAsB,IAAI,CAAC;IACrC,mFAAmF;IACnF,uBAAuB,GAAG,KAAK,CAAC;IAEhC,0DAA0D;IAC1D,kBAAkB,GAAkB,IAAI,CAAC;IAEzC;;;OAGG;IACH,aAAa;QACX,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,mEAAmE;IACnE,KAAK;QACH,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC;QACrC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type LinkEndpoint, type Patch, type Scene } from "@oh-just-another/scene";
|
|
2
|
+
import type { ElementId, LinkId, Vec2 } from "@oh-just-another/types";
|
|
3
|
+
import type { InteractionEmit, PressTarget } from "../machine.js";
|
|
4
|
+
/**
|
|
5
|
+
* Editor capabilities the link handle drags need. Keeps the controller off
|
|
6
|
+
* the god-class: scene access, gesture transaction lifecycle, endpoint
|
|
7
|
+
* snapping and hover feedback are delegated back to the Editor through this
|
|
8
|
+
* narrow interface.
|
|
9
|
+
*/
|
|
10
|
+
export interface LinkHandleDragHost {
|
|
11
|
+
/** Current scene (read + replace — live drags mutate through the gesture tx). */
|
|
12
|
+
scene: Scene;
|
|
13
|
+
/** Record a patch as one undo step (double-click delete / reset paths). */
|
|
14
|
+
pushHistory(patch: Patch): void;
|
|
15
|
+
/** Apply a live-drag patch into the open gesture transaction. */
|
|
16
|
+
recordGesturePatch(patch: Patch): void;
|
|
17
|
+
/** Commit the gesture transaction (one undo step for the whole drag). */
|
|
18
|
+
commitGesture(): void;
|
|
19
|
+
/** Cancel the gesture transaction (revert the live drag). */
|
|
20
|
+
cancelGesture(): void;
|
|
21
|
+
/** True while a gesture transaction is open (an endpoint move happened). */
|
|
22
|
+
hasGestureTx(): boolean;
|
|
23
|
+
/** Repaint + listener fan-out. */
|
|
24
|
+
notify(): void;
|
|
25
|
+
/** Attach target under the cursor (same resolution the drop uses). */
|
|
26
|
+
linkAttachTargetAt(worldPoint: Vec2): PressTarget | undefined;
|
|
27
|
+
/** Snap an endpoint to a target element / free point. */
|
|
28
|
+
snapLinkEndpoint(targetId: ElementId | null, worldPoint: Vec2): LinkEndpoint;
|
|
29
|
+
/** Drive the attach-point highlight (candidate dots + halo). */
|
|
30
|
+
updateHoveredLinkTarget(worldPoint: Vec2): void;
|
|
31
|
+
/** Drop the attach-point highlight. */
|
|
32
|
+
clearHoveredLinkTarget(): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Owns the link edit-handle drags: waypoint (bend point) drags, elbow
|
|
36
|
+
* segment drags, endpoint rebind drags and the handle double-click
|
|
37
|
+
* detector (delete waypoint / reset segment pin). Extracted from the
|
|
38
|
+
* Editor god-class; the Editor keeps thin delegate wrappers so its public
|
|
39
|
+
* API is unchanged.
|
|
40
|
+
*/
|
|
41
|
+
export declare class LinkHandleDragController {
|
|
42
|
+
private readonly host;
|
|
43
|
+
/**
|
|
44
|
+
* Mid-drag preview state when the user is dragging an edge endpoint.
|
|
45
|
+
* Drawn as an overlay line + handle dot so the user sees the target.
|
|
46
|
+
*/
|
|
47
|
+
private _endpointDrag;
|
|
48
|
+
/**
|
|
49
|
+
* Host-managed waypoint (bend-point) drag of the selected link. `index`
|
|
50
|
+
* is the position in `edge.waypoints`. `pendingInsert` means the gesture
|
|
51
|
+
* began on a segment midpoint and will splice a new waypoint on the
|
|
52
|
+
* first move (so a no-move click adds nothing). Live-mutated through the
|
|
53
|
+
* gesture transaction → one undo step per drag.
|
|
54
|
+
*/
|
|
55
|
+
private _waypointDrag;
|
|
56
|
+
/**
|
|
57
|
+
* Host-managed elbow segment drag. `axis` is the segment's orientation.
|
|
58
|
+
* Dragging pins the segment's perpendicular coordinate into
|
|
59
|
+
* `Link.fixedSegments`; the reroute pass re-flows the rest. One undo
|
|
60
|
+
* step via the gesture tx.
|
|
61
|
+
*/
|
|
62
|
+
private _segmentDrag;
|
|
63
|
+
/** Wall-clock of the previous handle press — drives `isHandleDoubleClick`. */
|
|
64
|
+
private lastHandleClickAt;
|
|
65
|
+
private lastHandleClickWorld;
|
|
66
|
+
constructor(host: LinkHandleDragHost);
|
|
67
|
+
get endpointDrag(): {
|
|
68
|
+
linkId: LinkId;
|
|
69
|
+
side: "from" | "to";
|
|
70
|
+
toPoint: Vec2;
|
|
71
|
+
} | null;
|
|
72
|
+
get waypointDrag(): {
|
|
73
|
+
linkId: LinkId;
|
|
74
|
+
index: number;
|
|
75
|
+
pendingInsert: boolean;
|
|
76
|
+
} | null;
|
|
77
|
+
get segmentDrag(): {
|
|
78
|
+
linkId: LinkId;
|
|
79
|
+
axis: "h" | "v";
|
|
80
|
+
at: number;
|
|
81
|
+
} | null;
|
|
82
|
+
/** Drop all drag state without committing (Escape / cancelInteraction). */
|
|
83
|
+
reset(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Live endpoint-rebind move: re-point the dragged end to the cursor in the
|
|
86
|
+
* scene (a free `point` endpoint), recorded in the gesture transaction so the
|
|
87
|
+
* WHOLE link redraws under the cursor with full fidelity — real style,
|
|
88
|
+
* arrowhead, curved bow, and (via `rerouteElbows` in `render`) a live elbow
|
|
89
|
+
* re-route. One undo step on commit; Escape cancels the transaction and the
|
|
90
|
+
* link snaps back to where it was. The handle dot follows via `endpointDrag`.
|
|
91
|
+
*/
|
|
92
|
+
applyEndpointMove(linkId: LinkId, side: "from" | "to", toPoint: Vec2): void;
|
|
93
|
+
applyEndpointUpdate(emit: Extract<InteractionEmit, {
|
|
94
|
+
type: "UPDATE_EDGE_ENDPOINT";
|
|
95
|
+
}>): void;
|
|
96
|
+
/** True while a waypoint of the selected link is being dragged. */
|
|
97
|
+
get isDraggingWaypoint(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Begin a host-managed waypoint drag. `insert` splices a new waypoint at
|
|
100
|
+
* `index` on the first move (segment-midpoint "add" handle); otherwise an
|
|
101
|
+
* existing waypoint at `index` is moved. Live-mutated through the gesture
|
|
102
|
+
* transaction so the whole drag is one undo step.
|
|
103
|
+
*/
|
|
104
|
+
beginWaypointDrag(linkId: LinkId, index: number, insert: boolean): void;
|
|
105
|
+
/** Live update of the dragged waypoint to `world`. */
|
|
106
|
+
updateWaypointDrag(world: Vec2): void;
|
|
107
|
+
/**
|
|
108
|
+
* Finish the waypoint drag. If the dragged waypoint landed within
|
|
109
|
+
* `WAYPOINT_COLLAPSE_RADIUS` of an adjacent path point, it is removed
|
|
110
|
+
* (drag-onto-the-line to delete). A no-move insert adds nothing.
|
|
111
|
+
*/
|
|
112
|
+
endWaypointDrag(): void;
|
|
113
|
+
/** True while an elbow segment is being dragged. */
|
|
114
|
+
get isDraggingSegment(): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Begin a host-managed elbow segment drag. `axis` is the segment's
|
|
117
|
+
* orientation; `at` is its centre along its own axis (used to re-identify it
|
|
118
|
+
* across re-routes).
|
|
119
|
+
*/
|
|
120
|
+
beginSegmentDrag(linkId: LinkId, axis: "h" | "v", at: number): void;
|
|
121
|
+
/**
|
|
122
|
+
* Move the dragged elbow segment perpendicular to its axis: pin its
|
|
123
|
+
* perpendicular coordinate to the cursor. The reroute pass re-flows the
|
|
124
|
+
* rest around the pin (one undo step via the gesture transaction).
|
|
125
|
+
*/
|
|
126
|
+
updateSegmentDrag(world: Vec2): void;
|
|
127
|
+
/** Finish the elbow segment drag (commit the gesture as one undo step). */
|
|
128
|
+
endSegmentDrag(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Double-click detector for link edit handles (waypoint / segment).
|
|
131
|
+
* Returns true when this press follows the previous handle press within
|
|
132
|
+
* the double-click window + tolerance. Updates state every call. Kept
|
|
133
|
+
* separate from the up-side double-click path (handles return early in
|
|
134
|
+
* `onDown`, so that path never sees them).
|
|
135
|
+
*/
|
|
136
|
+
isHandleDoubleClick(world: Vec2): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Delete a free bend point (waypoint) from a straight / bezier link by
|
|
139
|
+
* index — double-click a waypoint handle to remove it. One undo step.
|
|
140
|
+
*/
|
|
141
|
+
deleteWaypoint(linkId: LinkId, index: number): void;
|
|
142
|
+
/**
|
|
143
|
+
* Remove the pinned (fixed) elbow segment that matches the given
|
|
144
|
+
* geometry — double-click a segment handle to return it to the auto
|
|
145
|
+
* route. Matches by axis + nearest pinned perpendicular `pos` (exact for
|
|
146
|
+
* a pinned segment), `at` as tiebreak. The reroute pass re-flows on the
|
|
147
|
+
* next render (fixedSegments is part of the elbow signature). One undo
|
|
148
|
+
* step.
|
|
149
|
+
*/
|
|
150
|
+
resetSegmentPin(linkId: LinkId, axis: "h" | "v", pos: number, at: number): void;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=link-handle-drag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-handle-drag.d.ts","sourceRoot":"","sources":["../../src/editor/link-handle-drag.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { getLink, getLinkPath, isNoop, updateLink, } from "@oh-just-another/scene";
|
|
2
|
+
import { hitTest, vec2 } from "@oh-just-another/math";
|
|
3
|
+
import { DOUBLE_CLICK_MS, DOUBLE_CLICK_TOLERANCE_PX, WAYPOINT_COLLAPSE_RADIUS, } from "../constants.js";
|
|
4
|
+
import { req } from "../util.js";
|
|
5
|
+
import { computeLinkEndpointUpdate } from "./applies/edge.js";
|
|
6
|
+
/**
|
|
7
|
+
* Owns the link edit-handle drags: waypoint (bend point) drags, elbow
|
|
8
|
+
* segment drags, endpoint rebind drags and the handle double-click
|
|
9
|
+
* detector (delete waypoint / reset segment pin). Extracted from the
|
|
10
|
+
* Editor god-class; the Editor keeps thin delegate wrappers so its public
|
|
11
|
+
* API is unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export class LinkHandleDragController {
|
|
14
|
+
host;
|
|
15
|
+
/**
|
|
16
|
+
* Mid-drag preview state when the user is dragging an edge endpoint.
|
|
17
|
+
* Drawn as an overlay line + handle dot so the user sees the target.
|
|
18
|
+
*/
|
|
19
|
+
_endpointDrag = null;
|
|
20
|
+
/**
|
|
21
|
+
* Host-managed waypoint (bend-point) drag of the selected link. `index`
|
|
22
|
+
* is the position in `edge.waypoints`. `pendingInsert` means the gesture
|
|
23
|
+
* began on a segment midpoint and will splice a new waypoint on the
|
|
24
|
+
* first move (so a no-move click adds nothing). Live-mutated through the
|
|
25
|
+
* gesture transaction → one undo step per drag.
|
|
26
|
+
*/
|
|
27
|
+
_waypointDrag = null;
|
|
28
|
+
/**
|
|
29
|
+
* Host-managed elbow segment drag. `axis` is the segment's orientation.
|
|
30
|
+
* Dragging pins the segment's perpendicular coordinate into
|
|
31
|
+
* `Link.fixedSegments`; the reroute pass re-flows the rest. One undo
|
|
32
|
+
* step via the gesture tx.
|
|
33
|
+
*/
|
|
34
|
+
_segmentDrag = null;
|
|
35
|
+
/** Wall-clock of the previous handle press — drives `isHandleDoubleClick`. */
|
|
36
|
+
lastHandleClickAt = 0;
|
|
37
|
+
lastHandleClickWorld = null;
|
|
38
|
+
constructor(host) {
|
|
39
|
+
this.host = host;
|
|
40
|
+
}
|
|
41
|
+
get endpointDrag() {
|
|
42
|
+
return this._endpointDrag;
|
|
43
|
+
}
|
|
44
|
+
get waypointDrag() {
|
|
45
|
+
return this._waypointDrag;
|
|
46
|
+
}
|
|
47
|
+
get segmentDrag() {
|
|
48
|
+
return this._segmentDrag;
|
|
49
|
+
}
|
|
50
|
+
/** Drop all drag state without committing (Escape / cancelInteraction). */
|
|
51
|
+
reset() {
|
|
52
|
+
this._waypointDrag = null;
|
|
53
|
+
this._segmentDrag = null;
|
|
54
|
+
this._endpointDrag = null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Live endpoint-rebind move: re-point the dragged end to the cursor in the
|
|
58
|
+
* scene (a free `point` endpoint), recorded in the gesture transaction so the
|
|
59
|
+
* WHOLE link redraws under the cursor with full fidelity — real style,
|
|
60
|
+
* arrowhead, curved bow, and (via `rerouteElbows` in `render`) a live elbow
|
|
61
|
+
* re-route. One undo step on commit; Escape cancels the transaction and the
|
|
62
|
+
* link snaps back to where it was. The handle dot follows via `endpointDrag`.
|
|
63
|
+
*/
|
|
64
|
+
applyEndpointMove(linkId, side, toPoint) {
|
|
65
|
+
const edge = getLink(this.host.scene, linkId);
|
|
66
|
+
if (!edge)
|
|
67
|
+
return;
|
|
68
|
+
// A real drag breaks the handle double-click chain (mirrors waypoint /
|
|
69
|
+
// segment drags) so a quick click after dropping isn't read as a delete.
|
|
70
|
+
this.lastHandleClickAt = 0;
|
|
71
|
+
// Resolve the attach target under the cursor and snap the endpoint to it
|
|
72
|
+
// with the SAME logic the drop uses, so the link attaches LIVE exactly as it
|
|
73
|
+
// will commit — lands on the dot (fixed), floats on the body, or stays a
|
|
74
|
+
// free point over empty space.
|
|
75
|
+
const target = this.host.linkAttachTargetAt(toPoint);
|
|
76
|
+
const targetId = target?.kind === "element" ? target.id : null;
|
|
77
|
+
const ep = this.host.snapLinkEndpoint(targetId, toPoint);
|
|
78
|
+
const r = updateLink(this.host.scene, linkId, (e) => side === "from" ? { ...e, from: ep } : { ...e, to: ep });
|
|
79
|
+
this.host.scene = r.scene;
|
|
80
|
+
this.host.recordGesturePatch(r.patch);
|
|
81
|
+
this._endpointDrag = { linkId, side, toPoint };
|
|
82
|
+
// Attach-point highlight — the SAME feedback as drawing a new link
|
|
83
|
+
// (candidate dots + float-element halo), driven by `hoveredLinkTarget`.
|
|
84
|
+
this.host.updateHoveredLinkTarget(toPoint);
|
|
85
|
+
this.host.notify();
|
|
86
|
+
}
|
|
87
|
+
applyEndpointUpdate(emit) {
|
|
88
|
+
// A move opened a gesture transaction (live re-point per tick). The final
|
|
89
|
+
// snapped endpoint goes into the SAME transaction so the net history step is
|
|
90
|
+
// original → final (one undo). A pure click (no move, no tx) that resolves
|
|
91
|
+
// to a no-op change must not leave a junk undo entry.
|
|
92
|
+
const moved = this.host.hasGestureTx();
|
|
93
|
+
const result = computeLinkEndpointUpdate(this.host.scene, emit, (toElement, toPoint) => this.host.snapLinkEndpoint(toElement, toPoint));
|
|
94
|
+
if (result === null) {
|
|
95
|
+
this.host.cancelGesture();
|
|
96
|
+
this._endpointDrag = null;
|
|
97
|
+
this.host.clearHoveredLinkTarget();
|
|
98
|
+
this.host.notify();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!moved && isNoop(result.patch)) {
|
|
102
|
+
this._endpointDrag = null;
|
|
103
|
+
this.host.clearHoveredLinkTarget();
|
|
104
|
+
this.host.notify();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.host.scene = result.scene;
|
|
108
|
+
this.host.recordGesturePatch(result.patch);
|
|
109
|
+
this.host.commitGesture();
|
|
110
|
+
this._endpointDrag = null;
|
|
111
|
+
this.host.clearHoveredLinkTarget();
|
|
112
|
+
}
|
|
113
|
+
/** True while a waypoint of the selected link is being dragged. */
|
|
114
|
+
get isDraggingWaypoint() {
|
|
115
|
+
return this._waypointDrag !== null;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Begin a host-managed waypoint drag. `insert` splices a new waypoint at
|
|
119
|
+
* `index` on the first move (segment-midpoint "add" handle); otherwise an
|
|
120
|
+
* existing waypoint at `index` is moved. Live-mutated through the gesture
|
|
121
|
+
* transaction so the whole drag is one undo step.
|
|
122
|
+
*/
|
|
123
|
+
beginWaypointDrag(linkId, index, insert) {
|
|
124
|
+
if (!getLink(this.host.scene, linkId))
|
|
125
|
+
return;
|
|
126
|
+
this._waypointDrag = { linkId, index, pendingInsert: insert };
|
|
127
|
+
}
|
|
128
|
+
/** Live update of the dragged waypoint to `world`. */
|
|
129
|
+
updateWaypointDrag(world) {
|
|
130
|
+
const drag = this._waypointDrag;
|
|
131
|
+
if (!drag)
|
|
132
|
+
return;
|
|
133
|
+
// A real drag breaks the handle double-click chain (see updateSegmentDrag).
|
|
134
|
+
this.lastHandleClickAt = 0;
|
|
135
|
+
const edge = getLink(this.host.scene, drag.linkId);
|
|
136
|
+
if (!edge)
|
|
137
|
+
return;
|
|
138
|
+
const wps = [...(edge.waypoints ?? [])];
|
|
139
|
+
if (drag.pendingInsert) {
|
|
140
|
+
wps.splice(drag.index, 0, world);
|
|
141
|
+
drag.pendingInsert = false;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
if (drag.index < 0 || drag.index >= wps.length)
|
|
145
|
+
return;
|
|
146
|
+
wps[drag.index] = world;
|
|
147
|
+
}
|
|
148
|
+
const r = updateLink(this.host.scene, drag.linkId, (e) => ({ ...e, waypoints: wps }));
|
|
149
|
+
this.host.scene = r.scene;
|
|
150
|
+
this.host.recordGesturePatch(r.patch);
|
|
151
|
+
this.host.notify();
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Finish the waypoint drag. If the dragged waypoint landed within
|
|
155
|
+
* `WAYPOINT_COLLAPSE_RADIUS` of an adjacent path point, it is removed
|
|
156
|
+
* (drag-onto-the-line to delete). A no-move insert adds nothing.
|
|
157
|
+
*/
|
|
158
|
+
endWaypointDrag() {
|
|
159
|
+
const drag = this._waypointDrag;
|
|
160
|
+
this._waypointDrag = null;
|
|
161
|
+
if (!drag)
|
|
162
|
+
return;
|
|
163
|
+
if (drag.pendingInsert) {
|
|
164
|
+
// Never moved → it was a click on a midpoint; nothing inserted.
|
|
165
|
+
this.host.commitGesture();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const edge = getLink(this.host.scene, drag.linkId);
|
|
169
|
+
if (edge?.waypoints && drag.index >= 0 && drag.index < edge.waypoints.length) {
|
|
170
|
+
const path = getLinkPath(this.host.scene, edge);
|
|
171
|
+
const wp = req(edge.waypoints[drag.index]);
|
|
172
|
+
// Neighbours in the [from, ...waypoints, to] chain: path[index] and
|
|
173
|
+
// path[index + 2] (path[0] = from, so waypoint i sits at path[i + 1]).
|
|
174
|
+
// Dropping the waypoint back onto the straight segment between its
|
|
175
|
+
// neighbours removes the bend ("drag onto the line to delete").
|
|
176
|
+
const collapse = WAYPOINT_COLLAPSE_RADIUS / (this.host.scene.viewport.zoom || 1);
|
|
177
|
+
const a = path?.[drag.index];
|
|
178
|
+
const b = path?.[drag.index + 2];
|
|
179
|
+
if (a && b && hitTest.distanceToSegment(wp, a, b) <= collapse) {
|
|
180
|
+
const wps = edge.waypoints.filter((_, i) => i !== drag.index);
|
|
181
|
+
const r = updateLink(this.host.scene, drag.linkId, (e) => ({ ...e, waypoints: wps }));
|
|
182
|
+
this.host.scene = r.scene;
|
|
183
|
+
this.host.recordGesturePatch(r.patch);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.host.commitGesture();
|
|
187
|
+
}
|
|
188
|
+
/** True while an elbow segment is being dragged. */
|
|
189
|
+
get isDraggingSegment() {
|
|
190
|
+
return this._segmentDrag !== null;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Begin a host-managed elbow segment drag. `axis` is the segment's
|
|
194
|
+
* orientation; `at` is its centre along its own axis (used to re-identify it
|
|
195
|
+
* across re-routes).
|
|
196
|
+
*/
|
|
197
|
+
beginSegmentDrag(linkId, axis, at) {
|
|
198
|
+
if (!getLink(this.host.scene, linkId))
|
|
199
|
+
return;
|
|
200
|
+
this._segmentDrag = { linkId, axis, at };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Move the dragged elbow segment perpendicular to its axis: pin its
|
|
204
|
+
* perpendicular coordinate to the cursor. The reroute pass re-flows the
|
|
205
|
+
* rest around the pin (one undo step via the gesture transaction).
|
|
206
|
+
*/
|
|
207
|
+
updateSegmentDrag(world) {
|
|
208
|
+
const drag = this._segmentDrag;
|
|
209
|
+
if (!drag)
|
|
210
|
+
return;
|
|
211
|
+
// A real drag breaks the handle double-click chain, so a single click
|
|
212
|
+
// right after pinning can't be misread as a double-click (= delete).
|
|
213
|
+
this.lastHandleClickAt = 0;
|
|
214
|
+
const edge = getLink(this.host.scene, drag.linkId);
|
|
215
|
+
if (!edge)
|
|
216
|
+
return;
|
|
217
|
+
const pos = drag.axis === "h" ? world.y : world.x;
|
|
218
|
+
const fixed = [...(edge.fixedSegments ?? [])];
|
|
219
|
+
const entry = { axis: drag.axis, pos, at: drag.at };
|
|
220
|
+
const at = fixed.findIndex((f) => f.axis === drag.axis && Math.abs(f.at - drag.at) < 0.5);
|
|
221
|
+
if (at >= 0)
|
|
222
|
+
fixed[at] = entry;
|
|
223
|
+
else
|
|
224
|
+
fixed.push(entry);
|
|
225
|
+
const r = updateLink(this.host.scene, drag.linkId, (e) => ({ ...e, fixedSegments: fixed }));
|
|
226
|
+
this.host.scene = r.scene;
|
|
227
|
+
this.host.recordGesturePatch(r.patch);
|
|
228
|
+
this.host.notify();
|
|
229
|
+
}
|
|
230
|
+
/** Finish the elbow segment drag (commit the gesture as one undo step). */
|
|
231
|
+
endSegmentDrag() {
|
|
232
|
+
if (!this._segmentDrag)
|
|
233
|
+
return;
|
|
234
|
+
this._segmentDrag = null;
|
|
235
|
+
this.host.commitGesture();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Double-click detector for link edit handles (waypoint / segment).
|
|
239
|
+
* Returns true when this press follows the previous handle press within
|
|
240
|
+
* the double-click window + tolerance. Updates state every call. Kept
|
|
241
|
+
* separate from the up-side double-click path (handles return early in
|
|
242
|
+
* `onDown`, so that path never sees them).
|
|
243
|
+
*/
|
|
244
|
+
isHandleDoubleClick(world) {
|
|
245
|
+
const now = performance.now();
|
|
246
|
+
const isDouble = now - this.lastHandleClickAt < DOUBLE_CLICK_MS &&
|
|
247
|
+
this.lastHandleClickWorld !== null &&
|
|
248
|
+
vec2.distance(this.lastHandleClickWorld, world) <= DOUBLE_CLICK_TOLERANCE_PX;
|
|
249
|
+
this.lastHandleClickAt = now;
|
|
250
|
+
this.lastHandleClickWorld = world;
|
|
251
|
+
return isDouble;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Delete a free bend point (waypoint) from a straight / bezier link by
|
|
255
|
+
* index — double-click a waypoint handle to remove it. One undo step.
|
|
256
|
+
*/
|
|
257
|
+
deleteWaypoint(linkId, index) {
|
|
258
|
+
const edge = getLink(this.host.scene, linkId);
|
|
259
|
+
if (!edge?.waypoints || index < 0 || index >= edge.waypoints.length)
|
|
260
|
+
return;
|
|
261
|
+
const wps = edge.waypoints.filter((_, i) => i !== index);
|
|
262
|
+
const r = updateLink(this.host.scene, linkId, (e) => ({ ...e, waypoints: wps }));
|
|
263
|
+
this.host.scene = r.scene;
|
|
264
|
+
this.host.pushHistory(r.patch);
|
|
265
|
+
this.host.notify();
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Remove the pinned (fixed) elbow segment that matches the given
|
|
269
|
+
* geometry — double-click a segment handle to return it to the auto
|
|
270
|
+
* route. Matches by axis + nearest pinned perpendicular `pos` (exact for
|
|
271
|
+
* a pinned segment), `at` as tiebreak. The reroute pass re-flows on the
|
|
272
|
+
* next render (fixedSegments is part of the elbow signature). One undo
|
|
273
|
+
* step.
|
|
274
|
+
*/
|
|
275
|
+
resetSegmentPin(linkId, axis, pos, at) {
|
|
276
|
+
const edge = getLink(this.host.scene, linkId);
|
|
277
|
+
if (!edge?.fixedSegments || edge.fixedSegments.length === 0)
|
|
278
|
+
return;
|
|
279
|
+
let bestIdx = -1;
|
|
280
|
+
let bestD = Infinity;
|
|
281
|
+
for (let i = 0; i < edge.fixedSegments.length; i++) {
|
|
282
|
+
const f = req(edge.fixedSegments[i]);
|
|
283
|
+
if (f.axis !== axis)
|
|
284
|
+
continue;
|
|
285
|
+
const d = Math.abs(f.pos - pos) + Math.abs(f.at - at) * 0.001;
|
|
286
|
+
if (d < bestD) {
|
|
287
|
+
bestD = d;
|
|
288
|
+
bestIdx = i;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (bestIdx < 0)
|
|
292
|
+
return;
|
|
293
|
+
const fixed = edge.fixedSegments.filter((_, i) => i !== bestIdx);
|
|
294
|
+
const r = updateLink(this.host.scene, linkId, (e) => ({ ...e, fixedSegments: fixed }));
|
|
295
|
+
this.host.scene = r.scene;
|
|
296
|
+
this.host.pushHistory(r.patch);
|
|
297
|
+
this.host.notify();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=link-handle-drag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-handle-drag.js","sourceRoot":"","sources":["../../src/editor/link-handle-drag.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"long-press.d.ts","sourceRoot":"","sources":["../../src/editor/long-press.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"long-press.d.ts","sourceRoot":"","sources":["../../src/editor/long-press.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAInD,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,MAAM,CAAqB;gBAGhB,aAAa,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,IAAI,EAChC,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI;IAG3D,uEAAuE;IACvE,KAAK,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI;IAe9B,0CAA0C;IAC1C,MAAM,IAAI,IAAI;IAQd;;;;;OAKG;IACH,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAIrD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { vec2 } from "@oh-just-another/math";
|
|
1
2
|
import { LONG_PRESS_DELAY_MS } from "../constants.js";
|
|
2
|
-
const distance = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
3
3
|
/**
|
|
4
4
|
* Long-press timer with start / cancel + a single fire callback.
|
|
5
5
|
*
|
|
@@ -51,7 +51,7 @@ export class LongPressController {
|
|
|
51
51
|
cancelIfMovedBeyond(point, slop) {
|
|
52
52
|
if (!this.origin)
|
|
53
53
|
return;
|
|
54
|
-
if (distance(this.origin, point) > slop)
|
|
54
|
+
if (vec2.distance(this.origin, point) > slop)
|
|
55
55
|
this.cancel();
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"long-press.js","sourceRoot":"","sources":["../../src/editor/long-press.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"long-press.js","sourceRoot":"","sources":["../../src/editor/long-press.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAQtD;;;;;;;;GAQG;AACH,MAAM,OAAO,mBAAmB;IAKX;IACA;IALX,KAAK,GAAyC,IAAI,CAAC;IACnD,MAAM,GAAgB,IAAI,CAAC;IAEnC,YACmB,aAAgC,EAChC,MAAwC;QADxC,kBAAa,GAAb,aAAa,CAAmB;QAChC,WAAM,GAAN,MAAM,CAAkC;IACxD,CAAC;IAEJ,uEAAuE;IACvE,KAAK,CAAC,WAAiB;QACrB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC9C,+DAA+D;YAC/D,0DAA0D;YAC1D,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACnD,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAC1B,CAAC;IAED,0CAA0C;IAC1C,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,KAAW,EAAE,IAAY;QAC3C,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI;YAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAC9D,CAAC;CACF"}
|