canvasengine 2.0.0-beta.4 → 2.0.0-beta.40
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/dist/DebugRenderer-DgECR3yZ.js +172 -0
- package/dist/DebugRenderer-DgECR3yZ.js.map +1 -0
- package/dist/components/Button.d.ts +183 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Canvas.d.ts +18 -0
- package/dist/components/Canvas.d.ts.map +1 -0
- package/dist/components/DOMElement.d.ts +44 -0
- package/dist/components/DOMElement.d.ts.map +1 -0
- package/dist/components/Graphic.d.ts +65 -0
- package/dist/components/Graphic.d.ts.map +1 -0
- package/dist/components/Joystick.d.ts +36 -0
- package/dist/components/Joystick.d.ts.map +1 -0
- package/dist/components/NineSliceSprite.d.ts +17 -0
- package/dist/components/NineSliceSprite.d.ts.map +1 -0
- package/dist/components/ParticleEmitter.d.ts +5 -0
- package/dist/components/ParticleEmitter.d.ts.map +1 -0
- package/dist/components/Scene.d.ts +2 -0
- package/dist/components/Scene.d.ts.map +1 -0
- package/dist/components/Text.d.ts +26 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/TilingSprite.d.ts +18 -0
- package/dist/components/TilingSprite.d.ts.map +1 -0
- package/dist/components/Video.d.ts +15 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/index.d.ts +18 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/types/DisplayObject.d.ts +110 -0
- package/dist/components/types/DisplayObject.d.ts.map +1 -0
- package/dist/components/types/MouseEvent.d.ts +4 -0
- package/dist/components/types/MouseEvent.d.ts.map +1 -0
- package/dist/components/types/Spritesheet.d.ts +248 -0
- package/dist/components/types/Spritesheet.d.ts.map +1 -0
- package/dist/components/types/index.d.ts +5 -0
- package/dist/components/types/index.d.ts.map +1 -0
- package/dist/directives/Controls.d.ts +113 -0
- package/dist/directives/Controls.d.ts.map +1 -0
- package/dist/directives/ControlsBase.d.ts +198 -0
- package/dist/directives/ControlsBase.d.ts.map +1 -0
- package/dist/directives/Drag.d.ts +70 -0
- package/dist/directives/Drag.d.ts.map +1 -0
- package/dist/directives/Flash.d.ts +117 -0
- package/dist/directives/Flash.d.ts.map +1 -0
- package/dist/directives/GamepadControls.d.ts +225 -0
- package/dist/directives/GamepadControls.d.ts.map +1 -0
- package/dist/directives/JoystickControls.d.ts +172 -0
- package/dist/directives/JoystickControls.d.ts.map +1 -0
- package/dist/directives/KeyboardControls.d.ts +219 -0
- package/dist/directives/KeyboardControls.d.ts.map +1 -0
- package/dist/directives/Scheduler.d.ts +36 -0
- package/dist/directives/Scheduler.d.ts.map +1 -0
- package/dist/directives/Shake.d.ts +98 -0
- package/dist/directives/Shake.d.ts.map +1 -0
- package/dist/directives/Sound.d.ts +26 -0
- package/dist/directives/Sound.d.ts.map +1 -0
- package/dist/directives/Transition.d.ts +11 -0
- package/dist/directives/Transition.d.ts.map +1 -0
- package/dist/directives/ViewportCull.d.ts +12 -0
- package/dist/directives/ViewportCull.d.ts.map +1 -0
- package/dist/directives/ViewportFollow.d.ts +19 -0
- package/dist/directives/ViewportFollow.d.ts.map +1 -0
- package/dist/directives/index.d.ts +13 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/engine/animation.d.ts +73 -0
- package/dist/engine/animation.d.ts.map +1 -0
- package/dist/engine/bootstrap.d.ts +16 -0
- package/dist/engine/bootstrap.d.ts.map +1 -0
- package/dist/engine/directive.d.ts +14 -0
- package/dist/engine/directive.d.ts.map +1 -0
- package/dist/engine/reactive.d.ts +105 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +72 -0
- package/dist/engine/signal.d.ts.map +1 -0
- package/dist/engine/trigger.d.ts +50 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +90 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/hooks/addContext.d.ts +2 -0
- package/dist/hooks/addContext.d.ts.map +1 -0
- package/dist/hooks/useProps.d.ts +42 -0
- package/dist/hooks/useProps.d.ts.map +1 -0
- package/dist/hooks/useRef.d.ts +5 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/index-gb763Hyx.js +12560 -0
- package/dist/index-gb763Hyx.js.map +1 -0
- package/dist/index.d.ts +15 -1083
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +29 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +81 -3041
- package/dist/index.js.map +1 -1
- package/dist/utils/Ease.d.ts +17 -0
- package/dist/utils/Ease.d.ts.map +1 -0
- package/dist/utils/GlobalAssetLoader.d.ts +141 -0
- package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
- package/dist/utils/RadialGradient.d.ts +58 -0
- package/dist/utils/RadialGradient.d.ts.map +1 -0
- package/dist/utils/functions.d.ts +2 -0
- package/dist/utils/functions.d.ts.map +1 -0
- package/package.json +13 -7
- package/src/components/Button.ts +396 -0
- package/src/components/Canvas.ts +61 -45
- package/src/components/Container.ts +21 -2
- package/src/components/DOMContainer.ts +123 -0
- package/src/components/DOMElement.ts +421 -0
- package/src/components/DisplayObject.ts +350 -197
- package/src/components/Graphic.ts +200 -34
- package/src/components/Joystick.ts +361 -0
- package/src/components/Mesh.ts +222 -0
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +306 -30
- package/src/components/Text.ts +125 -18
- package/src/components/Video.ts +110 -0
- package/src/components/Viewport.ts +59 -43
- package/src/components/index.ts +8 -2
- package/src/components/types/DisplayObject.ts +34 -0
- package/src/components/types/Spritesheet.ts +0 -118
- package/src/directives/Controls.ts +254 -0
- package/src/directives/ControlsBase.ts +266 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/Flash.ts +409 -0
- package/src/directives/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +66 -424
- package/src/directives/Shake.ts +282 -0
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +35 -7
- package/src/directives/index.ts +12 -6
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +23 -3
- package/src/engine/directive.ts +2 -2
- package/src/engine/reactive.ts +780 -177
- package/src/engine/signal.ts +35 -4
- package/src/engine/trigger.ts +21 -4
- package/src/engine/utils.ts +19 -3
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +4 -2
- package/src/utils/GlobalAssetLoader.ts +257 -0
- package/src/utils/functions.ts +7 -0
- package/testing/index.ts +12 -0
- package/tsconfig.json +17 -0
- package/vite.config.ts +39 -0
package/src/directives/Drag.ts
CHANGED
|
@@ -1,84 +1,389 @@
|
|
|
1
|
-
import { effect, isSignal } from '@signe/reactive';
|
|
2
|
-
import { Container, Rectangle } from 'pixi.js';
|
|
1
|
+
import { effect, isComputed, isSignal, signal } from '@signe/reactive';
|
|
2
|
+
import { Container, Rectangle, Point, FederatedPointerEvent } from 'pixi.js';
|
|
3
3
|
import { Directive, registerDirective } from '../engine/directive';
|
|
4
4
|
import { Element } from '../engine/reactive';
|
|
5
5
|
import { snap } from 'popmotion';
|
|
6
6
|
import { addContext } from '../hooks/addContext';
|
|
7
|
+
import { Subscription } from 'rxjs';
|
|
8
|
+
import { useProps } from '../hooks/useProps';
|
|
9
|
+
import { SignalOrPrimitive } from '../components/types';
|
|
10
|
+
|
|
11
|
+
export type DragProps = {
|
|
12
|
+
move?: (event: FederatedPointerEvent) => void;
|
|
13
|
+
start?: () => void;
|
|
14
|
+
end?: () => void;
|
|
15
|
+
snap?: SignalOrPrimitive<number>;
|
|
16
|
+
direction?: SignalOrPrimitive<'x' | 'y' | 'all'>;
|
|
17
|
+
keyToPress?: SignalOrPrimitive<string[]>;
|
|
18
|
+
viewport?: {
|
|
19
|
+
edgeThreshold?: SignalOrPrimitive<number>;
|
|
20
|
+
maxSpeed?: SignalOrPrimitive<number>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
7
23
|
|
|
8
24
|
export class Drop extends Directive {
|
|
9
|
-
|
|
25
|
+
private elementRef: Element<Container> | null = null;
|
|
26
|
+
|
|
27
|
+
onInit(element: Element<Container>) {
|
|
28
|
+
this.elementRef = element;
|
|
29
|
+
}
|
|
10
30
|
|
|
11
31
|
onMount(element: Element<Container>) {
|
|
12
|
-
addContext(element, 'drop', element)
|
|
32
|
+
addContext(element, 'drop', element);
|
|
13
33
|
}
|
|
14
34
|
|
|
15
35
|
onUpdate() {}
|
|
16
36
|
|
|
17
|
-
onDestroy() {
|
|
37
|
+
onDestroy() {
|
|
38
|
+
this.elementRef = null;
|
|
39
|
+
}
|
|
18
40
|
}
|
|
19
41
|
|
|
20
42
|
export class Drag extends Directive {
|
|
21
|
-
|
|
43
|
+
private elementRef: Element<Container> | null = null;
|
|
44
|
+
private stageRef: Container | null = null;
|
|
45
|
+
private offsetInParent = new Point();
|
|
46
|
+
private isDragging = false;
|
|
47
|
+
private viewport: any | null = null;
|
|
48
|
+
private animationFrameId: number | null = null;
|
|
49
|
+
private lastPointerPosition: Point = new Point();
|
|
50
|
+
private pressedKeys: Set<string> = new Set();
|
|
51
|
+
private pointerIsDown = false;
|
|
52
|
+
|
|
53
|
+
private onDragMoveHandler: (event: FederatedPointerEvent) => void = () => {};
|
|
54
|
+
private onDragEndHandler: () => void = () => {};
|
|
55
|
+
private onDragStartHandler: (event: FederatedPointerEvent) => void = () => {};
|
|
56
|
+
private onKeyDownHandler: (event: KeyboardEvent) => void = () => {};
|
|
57
|
+
private onKeyUpHandler: (event: KeyboardEvent) => void = () => {};
|
|
58
|
+
|
|
59
|
+
private subscriptions: Subscription[] = [];
|
|
60
|
+
|
|
61
|
+
onInit(element: Element<Container>) {
|
|
62
|
+
this.elementRef = element;
|
|
63
|
+
this.onDragMoveHandler = this.onDragMove.bind(this);
|
|
64
|
+
this.onDragEndHandler = this.onDragEnd.bind(this);
|
|
65
|
+
this.onDragStartHandler = this.onPointerDown.bind(this);
|
|
66
|
+
this.onKeyDownHandler = this.onKeyDown.bind(this);
|
|
67
|
+
this.onKeyUpHandler = this.onKeyUp.bind(this);
|
|
68
|
+
}
|
|
22
69
|
|
|
23
70
|
onMount(element: Element<Container>) {
|
|
24
|
-
const { rootElement, canvasSize } = element.props.context
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (drag?.snap) {
|
|
46
|
-
instance.position.x = snapTo(x)
|
|
47
|
-
instance.position.y = snapTo(y)
|
|
48
|
-
} else {
|
|
49
|
-
instance.position.x = x
|
|
50
|
-
instance.position.y = y
|
|
71
|
+
const { rootElement, canvasSize, viewport, tick } = element.props.context;
|
|
72
|
+
const instance = element.componentInstance;
|
|
73
|
+
const dragProps = this.dragProps;
|
|
74
|
+
const haveNotProps = Object.keys(dragProps).length === 0;
|
|
75
|
+
|
|
76
|
+
if (haveNotProps) {
|
|
77
|
+
this.onDestroy();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!instance) return;
|
|
82
|
+
this.stageRef = rootElement.componentInstance;
|
|
83
|
+
if (!this.stageRef) return;
|
|
84
|
+
this.viewport = viewport;
|
|
85
|
+
|
|
86
|
+
instance.eventMode = 'static';
|
|
87
|
+
this.stageRef.eventMode = 'static';
|
|
88
|
+
|
|
89
|
+
const _effect = effect(() => {
|
|
90
|
+
if (this.stageRef) {
|
|
91
|
+
this.stageRef.hitArea = new Rectangle(0, 0, canvasSize().width, canvasSize().height);
|
|
51
92
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
instance.on('pointerdown', this.onDragStartHandler);
|
|
96
|
+
this.stageRef.on('pointerup', this.onDragEndHandler);
|
|
97
|
+
this.stageRef.on('pointerupoutside', this.onDragEndHandler);
|
|
98
|
+
|
|
99
|
+
const keysToPress = dragProps.keyToPress ? dragProps.keyToPress : [];
|
|
100
|
+
|
|
101
|
+
// Always add keyboard event listeners to track pressed keys
|
|
102
|
+
window.addEventListener('keydown', this.onKeyDownHandler);
|
|
103
|
+
window.addEventListener('keyup', this.onKeyUpHandler);
|
|
104
|
+
|
|
105
|
+
this.subscriptions = [
|
|
106
|
+
tick.observable.subscribe(() => {
|
|
107
|
+
if (this.isDragging && this.viewport) {
|
|
108
|
+
this.updateViewportPosition(this.lastPointerPosition);
|
|
109
|
+
}
|
|
110
|
+
}),
|
|
111
|
+
_effect.subscription
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get dragProps() {
|
|
116
|
+
const drag = this.elementRef?.props.drag
|
|
117
|
+
const options = useProps(drag?.value ?? drag, {
|
|
118
|
+
snap: 0,
|
|
119
|
+
viewport: {},
|
|
120
|
+
direction: 'all',
|
|
121
|
+
keyToPress: []
|
|
122
|
+
});
|
|
123
|
+
options.viewport = useProps(options.viewport, {
|
|
124
|
+
edgeThreshold: 300,
|
|
125
|
+
maxSpeed: 40
|
|
126
|
+
});
|
|
127
|
+
return options;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get axis() {
|
|
131
|
+
const direction = this.dragProps.direction();
|
|
132
|
+
const axis = {
|
|
133
|
+
x: true,
|
|
134
|
+
y: true,
|
|
135
|
+
}
|
|
136
|
+
if (direction === 'x') {
|
|
137
|
+
axis.y = false;
|
|
138
|
+
}
|
|
139
|
+
if (direction === 'y') {
|
|
140
|
+
axis.x = false;
|
|
141
|
+
}
|
|
142
|
+
return axis;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Updates element position when dragging and starts continuous viewport movement
|
|
147
|
+
* @param event The pointer event that triggered the drag move
|
|
148
|
+
*/
|
|
149
|
+
private onDragMove(event: FederatedPointerEvent) {
|
|
150
|
+
if (!this.isDragging || !this.elementRef?.componentInstance || !this.elementRef.componentInstance.parent) return;
|
|
151
|
+
|
|
152
|
+
const instance = this.elementRef.componentInstance;
|
|
153
|
+
const parent = instance.parent;
|
|
154
|
+
const dragProps = this.dragProps;
|
|
155
|
+
const propObservables = this.elementRef.propObservables;
|
|
156
|
+
const snapTo = snap(dragProps?.snap() ?? 0);
|
|
157
|
+
|
|
158
|
+
dragProps?.move?.(event);
|
|
159
|
+
|
|
160
|
+
const currentParentLocalPointer = parent.toLocal(event.global);
|
|
161
|
+
|
|
162
|
+
const newX = currentParentLocalPointer.x - this.offsetInParent.x;
|
|
163
|
+
const newY = currentParentLocalPointer.y - this.offsetInParent.y;
|
|
164
|
+
|
|
165
|
+
if (dragProps?.snap()) {
|
|
166
|
+
instance.position.x = snapTo(newX);
|
|
167
|
+
instance.position.y = snapTo(newY);
|
|
168
|
+
} else {
|
|
169
|
+
if (this.axis.x) instance.position.x = newX;
|
|
170
|
+
if (this.axis.y) instance.position.y = newY;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Store the last pointer position for continuous viewport movement
|
|
174
|
+
this.lastPointerPosition.copyFrom(event.global);
|
|
175
|
+
|
|
176
|
+
const { x: xProp, y: yProp } = propObservables as any;
|
|
177
|
+
|
|
178
|
+
const updatePosition = (prop: any, value: number) => {
|
|
179
|
+
if (isComputed(prop)) {
|
|
180
|
+
prop.dependencies.forEach(dependency => {
|
|
181
|
+
dependency.set(value)
|
|
182
|
+
})
|
|
183
|
+
} else if (isSignal(prop)) {
|
|
184
|
+
prop.set(value)
|
|
55
185
|
}
|
|
56
|
-
|
|
57
|
-
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (xProp !== undefined) updatePosition(xProp, instance.position.x)
|
|
189
|
+
if (yProp !== undefined) updatePosition(yProp, instance.position.y)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Moves the viewport if the dragged element is near screen edges
|
|
194
|
+
* @param globalPosition The global pointer position
|
|
195
|
+
*/
|
|
196
|
+
private updateViewportPosition(globalPosition: Point) {
|
|
197
|
+
if (!this.viewport || !this.elementRef) return;
|
|
198
|
+
|
|
199
|
+
const dragProps = this.dragProps;
|
|
200
|
+
const edgeThreshold = dragProps?.viewport?.edgeThreshold(); // Distance from edge to trigger viewport movement
|
|
201
|
+
const maxSpeed = dragProps?.viewport?.maxSpeed(); // Maximum speed when element is at the very edge
|
|
202
|
+
|
|
203
|
+
// Calculate screen boundaries
|
|
204
|
+
const screenLeft = 0;
|
|
205
|
+
const screenRight = this.viewport.screenWidth;
|
|
206
|
+
const screenTop = 0;
|
|
207
|
+
const screenBottom = this.viewport.screenHeight;
|
|
208
|
+
const instance = this.elementRef.componentInstance;
|
|
209
|
+
|
|
210
|
+
// Calculate distances from element to screen edges
|
|
211
|
+
const distanceFromLeft = globalPosition.x - screenLeft;
|
|
212
|
+
const distanceFromRight = screenRight - globalPosition.x;
|
|
213
|
+
const distanceFromTop = globalPosition.y - screenTop;
|
|
214
|
+
const distanceFromBottom = screenBottom - globalPosition.y;
|
|
215
|
+
|
|
216
|
+
let moveX = 0;
|
|
217
|
+
let moveY = 0;
|
|
218
|
+
|
|
219
|
+
// Calculate horizontal movement with dynamic velocity
|
|
220
|
+
if (distanceFromLeft < edgeThreshold) {
|
|
221
|
+
// Velocity increases as distance decreases
|
|
222
|
+
// When distance = 0, velocity = maxSpeed
|
|
223
|
+
// When distance = threshold, velocity = 0
|
|
224
|
+
const velocity = maxSpeed * (1 - (distanceFromLeft / edgeThreshold));
|
|
225
|
+
moveX = -velocity;
|
|
226
|
+
} else if (distanceFromRight < edgeThreshold) {
|
|
227
|
+
const velocity = maxSpeed * (1 - (distanceFromRight / edgeThreshold));
|
|
228
|
+
moveX = velocity;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Calculate vertical movement with dynamic velocity
|
|
232
|
+
if (distanceFromTop < edgeThreshold) {
|
|
233
|
+
const velocity = maxSpeed * (1 - (distanceFromTop / edgeThreshold));
|
|
234
|
+
moveY = -velocity;
|
|
235
|
+
} else if (distanceFromBottom < edgeThreshold) {
|
|
236
|
+
const velocity = maxSpeed * (1 - (distanceFromBottom / edgeThreshold));
|
|
237
|
+
moveY = velocity;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Apply movement with velocity-based displacement
|
|
241
|
+
if (moveX !== 0 || moveY !== 0) {
|
|
242
|
+
const lastViewValue = this.viewport.center;
|
|
243
|
+
this.viewport.moveCenter(
|
|
244
|
+
this.viewport.center.x + moveX,
|
|
245
|
+
this.viewport.center.y + moveY
|
|
246
|
+
);
|
|
247
|
+
if (this.axis.x && lastViewValue.x !== this.viewport.center.x) {
|
|
248
|
+
instance.position.x += moveX;
|
|
249
|
+
}
|
|
250
|
+
if (this.axis.y && lastViewValue.y !== this.viewport.center.y) {
|
|
251
|
+
instance.position.y += moveY;
|
|
58
252
|
}
|
|
59
253
|
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Handles drag end event and stops viewport movement
|
|
258
|
+
*/
|
|
259
|
+
private onDragEnd() {
|
|
260
|
+
this.pointerIsDown = false;
|
|
261
|
+
|
|
262
|
+
if (!this.isDragging) return;
|
|
60
263
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
264
|
+
const dragProps = this.dragProps;
|
|
265
|
+
this.isDragging = false;
|
|
266
|
+
|
|
267
|
+
dragProps?.end?.();
|
|
268
|
+
|
|
269
|
+
if (this.stageRef) {
|
|
270
|
+
this.stageRef.off('pointermove', this.onDragMoveHandler);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
onKeyDown(event: KeyboardEvent) {
|
|
275
|
+
this.pressedKeys.add(event.code);
|
|
276
|
+
this.pressedKeys.add(event.key.toLowerCase());
|
|
277
|
+
|
|
278
|
+
if (this.pointerIsDown && !this.isDragging && this.areRequiredKeysPressed()) {
|
|
279
|
+
this.startDrag();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
onKeyUp(event: KeyboardEvent) {
|
|
284
|
+
this.pressedKeys.delete(event.code);
|
|
285
|
+
this.pressedKeys.delete(event.key.toLowerCase());
|
|
286
|
+
if (this.isDragging && !this.areRequiredKeysPressed()) {
|
|
287
|
+
this.onDragEnd();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
66
290
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
291
|
+
private areRequiredKeysPressed(): boolean {
|
|
292
|
+
const keyToPress = this.dragProps.keyToPress ? this.dragProps.keyToPress : [];
|
|
293
|
+
if (!keyToPress || keyToPress.length === 0) {
|
|
294
|
+
return true; // No keys required, always return true
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return keyToPress.some(key => {
|
|
298
|
+
// Check if the key is pressed directly
|
|
299
|
+
if (this.pressedKeys.has(key)) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Check common alternative formats
|
|
304
|
+
// Space key can be "Space", " ", or "space"
|
|
305
|
+
if (key.toLowerCase() === 'space') {
|
|
306
|
+
return this.pressedKeys.has('Space') || this.pressedKeys.has(' ');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Shift key can be "ShiftLeft", "ShiftRight", or "shift"
|
|
310
|
+
if (key.toLowerCase() === 'shift') {
|
|
311
|
+
return this.pressedKeys.has('ShiftLeft') || this.pressedKeys.has('ShiftRight');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Control key can be "ControlLeft", "ControlRight", or "control"
|
|
315
|
+
if (key.toLowerCase() === 'control' || key.toLowerCase() === 'ctrl') {
|
|
316
|
+
return this.pressedKeys.has('ControlLeft') || this.pressedKeys.has('ControlRight');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Alt key can be "AltLeft", "AltRight", or "alt"
|
|
320
|
+
if (key.toLowerCase() === 'alt') {
|
|
321
|
+
return this.pressedKeys.has('AltLeft') || this.pressedKeys.has('AltRight');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return false;
|
|
70
325
|
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private onPointerDown(event: FederatedPointerEvent) {
|
|
329
|
+
if (!this.elementRef?.componentInstance || !this.stageRef || !this.elementRef.componentInstance.parent) return;
|
|
330
|
+
|
|
331
|
+
this.pointerIsDown = true;
|
|
332
|
+
|
|
333
|
+
const instance = this.elementRef.componentInstance;
|
|
334
|
+
const parent = instance.parent;
|
|
335
|
+
|
|
336
|
+
const parentLocalPointer = parent.toLocal(event.global);
|
|
71
337
|
|
|
72
|
-
|
|
73
|
-
|
|
338
|
+
this.offsetInParent.x = parentLocalPointer.x - instance.position.x;
|
|
339
|
+
this.offsetInParent.y = parentLocalPointer.y - instance.position.y;
|
|
340
|
+
|
|
341
|
+
// Store initial pointer position
|
|
342
|
+
this.lastPointerPosition.copyFrom(event.global);
|
|
343
|
+
|
|
344
|
+
if (this.areRequiredKeysPressed()) {
|
|
345
|
+
this.startDrag();
|
|
346
|
+
}
|
|
74
347
|
}
|
|
75
348
|
|
|
76
|
-
|
|
349
|
+
private startDrag() {
|
|
350
|
+
if (this.isDragging || !this.stageRef) return;
|
|
77
351
|
|
|
78
|
-
|
|
352
|
+
this.isDragging = true;
|
|
353
|
+
const dragProps = this.dragProps;
|
|
354
|
+
dragProps?.start?.();
|
|
355
|
+
this.stageRef.on('pointermove', this.onDragMoveHandler);
|
|
356
|
+
}
|
|
79
357
|
|
|
358
|
+
onUpdate(props) {
|
|
359
|
+
if (props.type && props.type === 'reset') {
|
|
360
|
+
this.onDestroy();
|
|
361
|
+
this.onMount(this.elementRef);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
onDestroy() {
|
|
366
|
+
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
367
|
+
const instance = this.elementRef?.componentInstance;
|
|
368
|
+
if (instance) {
|
|
369
|
+
instance.off('pointerdown', this.onDragStartHandler);
|
|
370
|
+
}
|
|
371
|
+
if (this.stageRef) {
|
|
372
|
+
this.stageRef.off('pointermove', this.onDragMoveHandler);
|
|
373
|
+
this.stageRef.off('pointerup', this.onDragEndHandler);
|
|
374
|
+
this.stageRef.off('pointerupoutside', this.onDragEndHandler);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Remove keyboard event listeners
|
|
378
|
+
window.removeEventListener('keydown', this.onKeyDownHandler);
|
|
379
|
+
window.removeEventListener('keyup', this.onKeyUpHandler);
|
|
380
|
+
|
|
381
|
+
this.stageRef = null;
|
|
382
|
+
this.viewport = null;
|
|
383
|
+
this.pressedKeys.clear();
|
|
384
|
+
this.pointerIsDown = false;
|
|
80
385
|
}
|
|
81
386
|
}
|
|
82
387
|
|
|
83
|
-
|
|
84
|
-
|
|
388
|
+
registerDirective('drag', Drag);
|
|
389
|
+
registerDirective('drop', Drop);
|