react-native-gesture-handler 2.18.1 → 2.20.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -0
- package/android/build.gradle +11 -29
- package/android/fabric/src/main/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +1 -1
- package/android/paper/src/main/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +1 -1
- package/android/src/main/AndroidManifest.xml +1 -3
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +21 -21
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +2 -2
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureUtils.kt +1 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +16 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +80 -4
- package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +8 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/PinchGestureHandler.kt +2 -1
- package/android/src/main/java/com/swmansion/gesturehandler/core/ScaleGestureDetector.java +10 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/StylusData.kt +103 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +2 -2
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +24 -15
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +3 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/HoverGestureHandlerEventDataBuilder.kt +7 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/PanGestureHandlerEventDataBuilder.kt +7 -0
- package/android/src/main/jni/CMakeLists.txt +18 -9
- package/apple/Handlers/RNFlingHandler.h +1 -0
- package/apple/Handlers/RNFlingHandler.m +153 -19
- package/apple/Handlers/RNHoverHandler.m +44 -2
- package/apple/Handlers/RNLongPressHandler.m +111 -20
- package/apple/Handlers/RNManualHandler.m +53 -29
- package/apple/Handlers/RNNativeViewHandler.mm +22 -15
- package/apple/Handlers/RNPanHandler.m +57 -7
- package/apple/Handlers/RNRotationHandler.m +1 -1
- package/apple/RNGHStylusData.h +77 -0
- package/apple/RNGHStylusData.m +37 -0
- package/apple/RNGHUIKit.h +2 -0
- package/apple/RNGHVector.h +31 -0
- package/apple/RNGHVector.m +67 -0
- package/apple/RNGestureHandler.h +7 -0
- package/apple/{RNGestureHandler.m → RNGestureHandler.mm} +63 -1
- package/apple/RNGestureHandlerButtonComponentView.mm +41 -0
- package/apple/RNGestureHandlerDirection.h +25 -0
- package/apple/RNGestureHandlerEvents.h +3 -1
- package/apple/RNGestureHandlerEvents.m +11 -3
- package/lib/commonjs/PointerType.js +2 -1
- package/lib/commonjs/PointerType.js.map +1 -1
- package/lib/commonjs/components/GestureButtons.js +5 -1
- package/lib/commonjs/components/GestureButtons.js.map +1 -1
- package/lib/commonjs/components/GestureComponents.js.map +1 -1
- package/lib/commonjs/components/Pressable/Pressable.js +66 -78
- package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
- package/lib/commonjs/components/Pressable/index.js +0 -8
- package/lib/commonjs/components/Pressable/index.js.map +1 -1
- package/lib/commonjs/components/Pressable/utils.js +1 -23
- package/lib/commonjs/components/Pressable/utils.js.map +1 -1
- package/lib/commonjs/components/ReanimatedSwipeable.js +60 -41
- package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/commonjs/handlers/GestureHandlerEventPayload.js +4 -0
- package/lib/commonjs/handlers/LongPressGestureHandler.js +1 -1
- package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/createHandler.js +2 -1
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -1
- package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
- package/lib/commonjs/handlers/gestures/hoverGesture.js.map +1 -1
- package/lib/commonjs/handlers/gestures/longPressGesture.js +10 -0
- package/lib/commonjs/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/commonjs/jestUtils/jestUtils.js +12 -4
- package/lib/commonjs/jestUtils/jestUtils.js.map +1 -1
- package/lib/commonjs/mocks.js +16 -3
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/utils.js +4 -0
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/web/constants.js +3 -3
- package/lib/commonjs/web/constants.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +2 -3
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/HoverGestureHandler.js +18 -1
- package/lib/commonjs/web/handlers/HoverGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js +43 -9
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +14 -3
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +12 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/EventManager.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +55 -11
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/commonjs/web/tools/KeyboardEventManager.js +110 -0
- package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -0
- package/lib/commonjs/web/tools/PointerEventManager.js +3 -37
- package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
- package/lib/commonjs/web/tools/Vector.js +4 -2
- package/lib/commonjs/web/tools/Vector.js.map +1 -1
- package/lib/commonjs/web/utils.js +187 -13
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/PointerType.js +2 -1
- package/lib/module/PointerType.js.map +1 -1
- package/lib/module/components/GestureButtons.js +5 -1
- package/lib/module/components/GestureButtons.js.map +1 -1
- package/lib/module/components/GestureComponents.js.map +1 -1
- package/lib/module/components/Pressable/Pressable.js +67 -78
- package/lib/module/components/Pressable/Pressable.js.map +1 -1
- package/lib/module/components/Pressable/index.js +0 -1
- package/lib/module/components/Pressable/index.js.map +1 -1
- package/lib/module/components/Pressable/utils.js +1 -22
- package/lib/module/components/Pressable/utils.js.map +1 -1
- package/lib/module/components/ReanimatedSwipeable.js +58 -37
- package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/module/handlers/GestureHandlerEventPayload.js +1 -1
- package/lib/module/handlers/LongPressGestureHandler.js +1 -1
- package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/handlers/createHandler.js +2 -1
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/utils.js +2 -2
- package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
- package/lib/module/handlers/gestures/gesture.js.map +1 -1
- package/lib/module/handlers/gestures/hoverGesture.js.map +1 -1
- package/lib/module/handlers/gestures/longPressGesture.js +10 -0
- package/lib/module/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/module/jestUtils/jestUtils.js +12 -4
- package/lib/module/jestUtils/jestUtils.js.map +1 -1
- package/lib/module/mocks.js +13 -3
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/utils.js +1 -0
- package/lib/module/utils.js.map +1 -1
- package/lib/module/web/constants.js +1 -1
- package/lib/module/web/constants.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +2 -3
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/HoverGestureHandler.js +18 -1
- package/lib/module/web/handlers/HoverGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/LongPressGestureHandler.js +43 -9
- package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/NativeViewGestureHandler.js +14 -3
- package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +12 -1
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/EventManager.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js +54 -10
- package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/module/web/tools/KeyboardEventManager.js +96 -0
- package/lib/module/web/tools/KeyboardEventManager.js.map +1 -0
- package/lib/module/web/tools/PointerEventManager.js +4 -38
- package/lib/module/web/tools/PointerEventManager.js.map +1 -1
- package/lib/module/web/tools/Vector.js +5 -3
- package/lib/module/web/tools/Vector.js.map +1 -1
- package/lib/module/web/utils.js +184 -13
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/PointerType.d.ts +2 -1
- package/lib/typescript/components/GestureComponents.d.ts +1 -1
- package/lib/typescript/components/Pressable/index.d.ts +1 -1
- package/lib/typescript/components/Pressable/utils.d.ts +3 -5
- package/lib/typescript/handlers/GestureHandlerEventPayload.d.ts +35 -0
- package/lib/typescript/handlers/LongPressGestureHandler.d.ts +5 -1
- package/lib/typescript/handlers/gestures/gesture.d.ts +2 -2
- package/lib/typescript/handlers/gestures/hoverGesture.d.ts +1 -6
- package/lib/typescript/handlers/gestures/longPressGesture.d.ts +5 -0
- package/lib/typescript/handlers/handlersRegistry.d.ts +1 -1
- package/lib/typescript/jestUtils/jestUtils.d.ts +1 -1
- package/lib/typescript/mocks.d.ts +4 -3
- package/lib/typescript/utils.d.ts +1 -0
- package/lib/typescript/web/constants.d.ts +1 -1
- package/lib/typescript/web/handlers/GestureHandler.d.ts +1 -1
- package/lib/typescript/web/handlers/HoverGestureHandler.d.ts +2 -0
- package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +3 -0
- package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
- package/lib/typescript/web/handlers/PanGestureHandler.d.ts +3 -1
- package/lib/typescript/web/interfaces.d.ts +9 -4
- package/lib/typescript/web/tools/EventManager.d.ts +2 -2
- package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +1 -0
- package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +6 -0
- package/lib/typescript/web/tools/KeyboardEventManager.d.ts +13 -0
- package/lib/typescript/web/utils.d.ts +2 -1
- package/package.json +3 -3
- package/src/PointerType.ts +1 -0
- package/src/components/GestureButtons.tsx +2 -1
- package/src/components/GestureComponents.tsx +1 -1
- package/src/components/Pressable/Pressable.tsx +77 -70
- package/src/components/Pressable/index.ts +1 -1
- package/src/components/Pressable/utils.ts +5 -49
- package/src/components/ReanimatedSwipeable.tsx +70 -47
- package/src/handlers/GestureHandlerEventPayload.ts +42 -0
- package/src/handlers/LongPressGestureHandler.ts +6 -0
- package/src/handlers/createHandler.tsx +1 -0
- package/src/handlers/gestures/GestureDetector/utils.ts +2 -2
- package/src/handlers/gestures/gesture.ts +3 -1
- package/src/handlers/gestures/hoverGesture.ts +1 -7
- package/src/handlers/gestures/longPressGesture.ts +9 -0
- package/src/jestUtils/jestUtils.ts +9 -1
- package/src/{mocks.ts → mocks.tsx} +8 -3
- package/src/utils.ts +2 -0
- package/src/web/constants.ts +1 -1
- package/src/web/handlers/GestureHandler.ts +4 -2
- package/src/web/handlers/HoverGestureHandler.ts +16 -2
- package/src/web/handlers/LongPressGestureHandler.ts +49 -10
- package/src/web/handlers/NativeViewGestureHandler.ts +14 -4
- package/src/web/handlers/PanGestureHandler.ts +14 -1
- package/src/web/interfaces.ts +10 -4
- package/src/web/tools/EventManager.ts +2 -4
- package/src/web/tools/GestureHandlerDelegate.ts +1 -0
- package/src/web/tools/GestureHandlerWebDelegate.ts +67 -10
- package/src/web/tools/KeyboardEventManager.ts +91 -0
- package/src/web/tools/PointerEventManager.ts +2 -38
- package/src/web/tools/Vector.ts +4 -3
- package/src/web/utils.ts +188 -13
- package/lib/commonjs/web/tools/TouchEventManager.js +0 -164
- package/lib/commonjs/web/tools/TouchEventManager.js.map +0 -1
- package/lib/module/web/tools/TouchEventManager.js +0 -149
- package/lib/module/web/tools/TouchEventManager.js.map +0 -1
- package/lib/typescript/web/tools/TouchEventManager.d.ts +0 -11
- package/src/web/tools/TouchEventManager.ts +0 -175
@@ -1,6 +1,6 @@
|
|
1
1
|
import { State } from '../../State';
|
2
2
|
import { DEFAULT_TOUCH_SLOP } from '../constants';
|
3
|
-
import { AdaptedEvent, Config } from '../interfaces';
|
3
|
+
import { AdaptedEvent, Config, StylusData } from '../interfaces';
|
4
4
|
|
5
5
|
import GestureHandler from './GestureHandler';
|
6
6
|
|
@@ -52,6 +52,8 @@ export default class PanGestureHandler extends GestureHandler {
|
|
52
52
|
private lastX = 0;
|
53
53
|
private lastY = 0;
|
54
54
|
|
55
|
+
private stylusData: StylusData | undefined;
|
56
|
+
|
55
57
|
private activateAfterLongPress = 0;
|
56
58
|
private activationTimeout = 0;
|
57
59
|
|
@@ -196,6 +198,7 @@ export default class PanGestureHandler extends GestureHandler {
|
|
196
198
|
translationY: isNaN(translationY) ? 0 : translationY,
|
197
199
|
velocityX: this.velocityX,
|
198
200
|
velocityY: this.velocityY,
|
201
|
+
stylusData: this.stylusData,
|
199
202
|
};
|
200
203
|
}
|
201
204
|
|
@@ -217,6 +220,8 @@ export default class PanGestureHandler extends GestureHandler {
|
|
217
220
|
}
|
218
221
|
|
219
222
|
this.tracker.addToTracker(event);
|
223
|
+
this.stylusData = event.stylusData;
|
224
|
+
|
220
225
|
super.onPointerDown(event);
|
221
226
|
|
222
227
|
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
@@ -259,6 +264,8 @@ export default class PanGestureHandler extends GestureHandler {
|
|
259
264
|
}
|
260
265
|
|
261
266
|
protected onPointerUp(event: AdaptedEvent): void {
|
267
|
+
this.stylusData = event.stylusData;
|
268
|
+
|
262
269
|
super.onPointerUp(event);
|
263
270
|
if (this.currentState === State.ACTIVE) {
|
264
271
|
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
@@ -268,6 +275,10 @@ export default class PanGestureHandler extends GestureHandler {
|
|
268
275
|
|
269
276
|
this.tracker.removeFromTracker(event.pointerId);
|
270
277
|
|
278
|
+
if (this.tracker.getTrackedPointersCount() === 0) {
|
279
|
+
this.clearActivationTimeout();
|
280
|
+
}
|
281
|
+
|
271
282
|
if (this.currentState === State.ACTIVE) {
|
272
283
|
this.end();
|
273
284
|
} else {
|
@@ -302,6 +313,7 @@ export default class PanGestureHandler extends GestureHandler {
|
|
302
313
|
|
303
314
|
protected onPointerMove(event: AdaptedEvent): void {
|
304
315
|
this.tracker.track(event);
|
316
|
+
this.stylusData = event.stylusData;
|
305
317
|
|
306
318
|
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
307
319
|
this.lastX = lastCoords.x;
|
@@ -322,6 +334,7 @@ export default class PanGestureHandler extends GestureHandler {
|
|
322
334
|
}
|
323
335
|
|
324
336
|
this.tracker.track(event);
|
337
|
+
this.stylusData = event.stylusData;
|
325
338
|
|
326
339
|
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
327
340
|
this.lastX = lastCoords.x;
|
package/src/web/interfaces.ts
CHANGED
@@ -36,7 +36,7 @@ type ConfigArgs =
|
|
36
36
|
| undefined;
|
37
37
|
|
38
38
|
export interface Config extends Record<string, ConfigArgs> {
|
39
|
-
enabled
|
39
|
+
enabled: boolean;
|
40
40
|
simultaneousHandlers?: Handler[] | null;
|
41
41
|
waitFor?: Handler[] | null;
|
42
42
|
blocksHandlers?: Handler[] | null;
|
@@ -132,6 +132,14 @@ export interface PropsRef {
|
|
132
132
|
onGestureHandlerStateChange: () => void;
|
133
133
|
}
|
134
134
|
|
135
|
+
export interface StylusData {
|
136
|
+
tiltX: number;
|
137
|
+
tiltY: number;
|
138
|
+
azimuthAngle: number;
|
139
|
+
altitudeAngle: number;
|
140
|
+
pressure: number;
|
141
|
+
}
|
142
|
+
|
135
143
|
export interface AdaptedEvent {
|
136
144
|
x: number;
|
137
145
|
y: number;
|
@@ -142,9 +150,7 @@ export interface AdaptedEvent {
|
|
142
150
|
pointerType: PointerType;
|
143
151
|
time: number;
|
144
152
|
button?: MouseButton;
|
145
|
-
|
146
|
-
changedTouches?: TouchList;
|
147
|
-
touchEventType?: TouchEventType;
|
153
|
+
stylusData?: StylusData;
|
148
154
|
}
|
149
155
|
|
150
156
|
export enum EventTypes {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
2
|
-
import { AdaptedEvent, EventTypes
|
2
|
+
import { AdaptedEvent, EventTypes } from '../interfaces';
|
3
3
|
|
4
4
|
type PointerEventCallback = (event: AdaptedEvent) => void;
|
5
5
|
|
@@ -18,9 +18,7 @@ export default abstract class EventManager<T> {
|
|
18
18
|
|
19
19
|
protected abstract mapEvent(
|
20
20
|
event: Event,
|
21
|
-
eventType: EventTypes
|
22
|
-
index?: number,
|
23
|
-
touchEventType?: TouchEventType
|
21
|
+
eventType: EventTypes
|
24
22
|
): AdaptedEvent;
|
25
23
|
|
26
24
|
protected onPointerDown(_event: AdaptedEvent): void {}
|
@@ -5,19 +5,29 @@ import {
|
|
5
5
|
MeasureResult,
|
6
6
|
} from './GestureHandlerDelegate';
|
7
7
|
import PointerEventManager from './PointerEventManager';
|
8
|
-
import TouchEventManager from './TouchEventManager';
|
9
8
|
import { State } from '../../State';
|
10
9
|
import { isPointerInBounds } from '../utils';
|
11
10
|
import EventManager from './EventManager';
|
12
11
|
import { Config } from '../interfaces';
|
13
12
|
import { MouseButton } from '../../handlers/gestureHandlerCommon';
|
13
|
+
import KeyboardEventManager from './KeyboardEventManager';
|
14
|
+
|
15
|
+
interface DefaultViewStyles {
|
16
|
+
userSelect: string;
|
17
|
+
touchAction: string;
|
18
|
+
}
|
14
19
|
|
15
20
|
export class GestureHandlerWebDelegate
|
16
21
|
implements GestureHandlerDelegate<HTMLElement, IGestureHandler>
|
17
22
|
{
|
23
|
+
private isInitialized = false;
|
18
24
|
private view!: HTMLElement;
|
19
25
|
private gestureHandler!: IGestureHandler;
|
20
26
|
private eventManagers: EventManager<unknown>[] = [];
|
27
|
+
private defaultViewStyles: DefaultViewStyles = {
|
28
|
+
userSelect: '',
|
29
|
+
touchAction: '',
|
30
|
+
};
|
21
31
|
|
22
32
|
getView(): HTMLElement {
|
23
33
|
return this.view;
|
@@ -30,22 +40,24 @@ export class GestureHandlerWebDelegate
|
|
30
40
|
);
|
31
41
|
}
|
32
42
|
|
43
|
+
this.isInitialized = true;
|
44
|
+
|
33
45
|
this.gestureHandler = handler;
|
34
46
|
this.view = findNodeHandle(viewRef) as unknown as HTMLElement;
|
35
47
|
|
36
|
-
|
48
|
+
this.defaultViewStyles = {
|
49
|
+
userSelect: this.view.style.userSelect,
|
50
|
+
touchAction: this.view.style.touchAction,
|
51
|
+
};
|
37
52
|
|
38
|
-
|
53
|
+
const config = handler.getConfig();
|
39
54
|
|
40
|
-
this.
|
41
|
-
this.
|
42
|
-
|
43
|
-
this.view.style['touchAction'] = config.touchAction ?? 'none';
|
44
|
-
// @ts-ignore This one disables default events on Safari
|
45
|
-
this.view.style['WebkitTouchCallout'] = 'none';
|
55
|
+
this.setUserSelect(config.enabled);
|
56
|
+
this.setTouchAction(config.enabled);
|
57
|
+
this.setContextMenu(config.enabled);
|
46
58
|
|
47
59
|
this.eventManagers.push(new PointerEventManager(this.view));
|
48
|
-
this.eventManagers.push(new
|
60
|
+
this.eventManagers.push(new KeyboardEventManager(this.view));
|
49
61
|
|
50
62
|
this.eventManagers.forEach((manager) =>
|
51
63
|
this.gestureHandler.attachEventManager(manager)
|
@@ -117,6 +129,51 @@ export class GestureHandlerWebDelegate
|
|
117
129
|
e.stopPropagation();
|
118
130
|
}
|
119
131
|
|
132
|
+
private setUserSelect(isHandlerEnabled: boolean) {
|
133
|
+
const { userSelect } = this.gestureHandler.getConfig();
|
134
|
+
|
135
|
+
this.view.style['userSelect'] = isHandlerEnabled
|
136
|
+
? userSelect ?? 'none'
|
137
|
+
: this.defaultViewStyles.userSelect;
|
138
|
+
|
139
|
+
this.view.style['webkitUserSelect'] = isHandlerEnabled
|
140
|
+
? userSelect ?? 'none'
|
141
|
+
: this.defaultViewStyles.userSelect;
|
142
|
+
}
|
143
|
+
|
144
|
+
private setTouchAction(isHandlerEnabled: boolean) {
|
145
|
+
const { touchAction } = this.gestureHandler.getConfig();
|
146
|
+
|
147
|
+
this.view.style['touchAction'] = isHandlerEnabled
|
148
|
+
? touchAction ?? 'none'
|
149
|
+
: this.defaultViewStyles.touchAction;
|
150
|
+
|
151
|
+
// @ts-ignore This one disables default events on Safari
|
152
|
+
this.view.style['WebkitTouchCallout'] = isHandlerEnabled
|
153
|
+
? touchAction ?? 'none'
|
154
|
+
: this.defaultViewStyles.touchAction;
|
155
|
+
}
|
156
|
+
|
157
|
+
private setContextMenu(isHandlerEnabled: boolean) {
|
158
|
+
const config = this.gestureHandler.getConfig();
|
159
|
+
|
160
|
+
if (isHandlerEnabled) {
|
161
|
+
this.addContextMenuListeners(config);
|
162
|
+
} else {
|
163
|
+
this.removeContextMenuListeners(config);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
onEnabledChange(enabled: boolean): void {
|
168
|
+
if (!this.isInitialized) {
|
169
|
+
return;
|
170
|
+
}
|
171
|
+
|
172
|
+
this.setUserSelect(enabled);
|
173
|
+
this.setTouchAction(enabled);
|
174
|
+
this.setContextMenu(enabled);
|
175
|
+
}
|
176
|
+
|
120
177
|
onBegin(): void {
|
121
178
|
// no-op for now
|
122
179
|
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { AdaptedEvent, EventTypes } from '../interfaces';
|
2
|
+
import EventManager from './EventManager';
|
3
|
+
import { PointerType } from '../../PointerType';
|
4
|
+
|
5
|
+
export default class KeyboardEventManager extends EventManager<HTMLElement> {
|
6
|
+
private activationKeys = ['Enter', ' '];
|
7
|
+
private cancelationKeys = ['Tab'];
|
8
|
+
private isPressed = false;
|
9
|
+
|
10
|
+
private keyDownCallback = (event: KeyboardEvent): void => {
|
11
|
+
if (this.cancelationKeys.indexOf(event.key) !== -1 && this.isPressed) {
|
12
|
+
this.dispatchEvent(event, EventTypes.CANCEL);
|
13
|
+
return;
|
14
|
+
}
|
15
|
+
|
16
|
+
if (this.activationKeys.indexOf(event.key) === -1) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
this.dispatchEvent(event, EventTypes.DOWN);
|
21
|
+
};
|
22
|
+
|
23
|
+
private keyUpCallback = (event: KeyboardEvent): void => {
|
24
|
+
if (this.activationKeys.indexOf(event.key) === -1 || !this.isPressed) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
this.dispatchEvent(event, EventTypes.UP);
|
29
|
+
};
|
30
|
+
|
31
|
+
private dispatchEvent(event: KeyboardEvent, eventType: EventTypes) {
|
32
|
+
if (!(event.target instanceof HTMLElement)) {
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
|
36
|
+
const adaptedEvent = this.mapEvent(event, eventType);
|
37
|
+
|
38
|
+
switch (eventType) {
|
39
|
+
case EventTypes.UP:
|
40
|
+
this.isPressed = false;
|
41
|
+
this.onPointerUp(adaptedEvent);
|
42
|
+
break;
|
43
|
+
case EventTypes.DOWN:
|
44
|
+
this.isPressed = true;
|
45
|
+
this.onPointerDown(adaptedEvent);
|
46
|
+
break;
|
47
|
+
case EventTypes.CANCEL:
|
48
|
+
this.isPressed = false;
|
49
|
+
this.onPointerCancel(adaptedEvent);
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
public registerListeners(): void {
|
55
|
+
this.view.addEventListener('keydown', this.keyDownCallback);
|
56
|
+
this.view.addEventListener('keyup', this.keyUpCallback);
|
57
|
+
}
|
58
|
+
|
59
|
+
public unregisterListeners(): void {
|
60
|
+
this.view.addEventListener('keydown', this.keyDownCallback);
|
61
|
+
this.view.addEventListener('keyup', this.keyUpCallback);
|
62
|
+
}
|
63
|
+
|
64
|
+
protected mapEvent(
|
65
|
+
event: KeyboardEvent,
|
66
|
+
eventType: EventTypes
|
67
|
+
): AdaptedEvent {
|
68
|
+
const viewRect = (event.target as HTMLElement).getBoundingClientRect();
|
69
|
+
|
70
|
+
const viewportPosition = {
|
71
|
+
x: viewRect?.x + viewRect?.width / 2,
|
72
|
+
y: viewRect?.y + viewRect?.height / 2,
|
73
|
+
};
|
74
|
+
|
75
|
+
const relativePosition = {
|
76
|
+
x: viewRect?.width / 2,
|
77
|
+
y: viewRect?.height / 2,
|
78
|
+
};
|
79
|
+
|
80
|
+
return {
|
81
|
+
x: viewportPosition.x,
|
82
|
+
y: viewportPosition.y,
|
83
|
+
offsetX: relativePosition.x,
|
84
|
+
offsetY: relativePosition.y,
|
85
|
+
pointerId: 0,
|
86
|
+
eventType: eventType,
|
87
|
+
pointerType: PointerType.KEY,
|
88
|
+
time: event.timeStamp,
|
89
|
+
};
|
90
|
+
}
|
91
|
+
}
|
@@ -4,15 +4,12 @@ import { AdaptedEvent, EventTypes, Point } from '../interfaces';
|
|
4
4
|
import {
|
5
5
|
PointerTypeMapping,
|
6
6
|
calculateViewScale,
|
7
|
+
tryExtractStylusData,
|
7
8
|
isPointerInBounds,
|
8
9
|
} from '../utils';
|
9
10
|
import { PointerType } from '../../PointerType';
|
10
11
|
|
11
12
|
const POINTER_CAPTURE_EXCLUDE_LIST = new Set<string>(['SELECT', 'INPUT']);
|
12
|
-
const PointerTypes = {
|
13
|
-
Touch: 'touch',
|
14
|
-
Stylus: 'pen',
|
15
|
-
};
|
16
13
|
|
17
14
|
export default class PointerEventManager extends EventManager<HTMLElement> {
|
18
15
|
private trackedPointers = new Set<number>();
|
@@ -35,9 +32,6 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
35
32
|
}
|
36
33
|
|
37
34
|
private pointerDownCallback = (event: PointerEvent) => {
|
38
|
-
if (event.pointerType === PointerTypes.Touch) {
|
39
|
-
return;
|
40
|
-
}
|
41
35
|
if (!isPointerInBounds(this.view, { x: event.clientX, y: event.clientY })) {
|
42
36
|
return;
|
43
37
|
}
|
@@ -61,10 +55,6 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
61
55
|
};
|
62
56
|
|
63
57
|
private pointerUpCallback = (event: PointerEvent) => {
|
64
|
-
if (event.pointerType === PointerTypes.Touch) {
|
65
|
-
return;
|
66
|
-
}
|
67
|
-
|
68
58
|
// When we call reset on gesture handlers, it also resets their event managers
|
69
59
|
// In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
|
70
60
|
// This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
|
@@ -92,21 +82,6 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
92
82
|
};
|
93
83
|
|
94
84
|
private pointerMoveCallback = (event: PointerEvent) => {
|
95
|
-
if (event.pointerType === PointerTypes.Touch) {
|
96
|
-
return;
|
97
|
-
}
|
98
|
-
|
99
|
-
// Stylus triggers `pointermove` event when it detects changes in pressure. Since it is very sensitive to those changes,
|
100
|
-
// it constantly sends events, even though there was no change in position. To fix that we check whether
|
101
|
-
// pointer has actually moved and if not, we do not send event.
|
102
|
-
if (
|
103
|
-
event.pointerType === PointerTypes.Stylus &&
|
104
|
-
event.x === this.lastPosition.x &&
|
105
|
-
event.y === this.lastPosition.y
|
106
|
-
) {
|
107
|
-
return;
|
108
|
-
}
|
109
|
-
|
110
85
|
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.MOVE);
|
111
86
|
const target = event.target as HTMLElement;
|
112
87
|
|
@@ -161,10 +136,6 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
161
136
|
};
|
162
137
|
|
163
138
|
private pointerCancelCallback = (event: PointerEvent) => {
|
164
|
-
if (event.pointerType === PointerTypes.Touch) {
|
165
|
-
return;
|
166
|
-
}
|
167
|
-
|
168
139
|
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.CANCEL);
|
169
140
|
|
170
141
|
this.onPointerCancel(adaptedEvent);
|
@@ -174,20 +145,12 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
174
145
|
};
|
175
146
|
|
176
147
|
private pointerEnterCallback = (event: PointerEvent) => {
|
177
|
-
if (event.pointerType === PointerTypes.Touch) {
|
178
|
-
return;
|
179
|
-
}
|
180
|
-
|
181
148
|
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.ENTER);
|
182
149
|
|
183
150
|
this.onPointerMoveOver(adaptedEvent);
|
184
151
|
};
|
185
152
|
|
186
153
|
private pointerLeaveCallback = (event: PointerEvent) => {
|
187
|
-
if (event.pointerType === PointerTypes.Touch) {
|
188
|
-
return;
|
189
|
-
}
|
190
|
-
|
191
154
|
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.LEAVE);
|
192
155
|
|
193
156
|
this.onPointerMoveOut(adaptedEvent);
|
@@ -252,6 +215,7 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
|
|
252
215
|
PointerTypeMapping.get(event.pointerType) ?? PointerType.OTHER,
|
253
216
|
button: this.mouseButtonsMapper.get(event.button),
|
254
217
|
time: event.timeStamp,
|
218
|
+
stylusData: tryExtractStylusData(event),
|
255
219
|
};
|
256
220
|
}
|
257
221
|
|
package/src/web/tools/Vector.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { DiagonalDirections, Directions } from '../../Directions';
|
2
|
-
import {
|
2
|
+
import { MINIMAL_RECOGNIZABLE_MAGNITUDE } from '../constants';
|
3
3
|
import PointerTracker from './PointerTracker';
|
4
4
|
|
5
5
|
export default class Vector {
|
@@ -14,14 +14,15 @@ export default class Vector {
|
|
14
14
|
this.y = y;
|
15
15
|
|
16
16
|
this._magnitude = Math.hypot(this.x, this.y);
|
17
|
-
const isMagnitudeSufficient =
|
17
|
+
const isMagnitudeSufficient =
|
18
|
+
this._magnitude > MINIMAL_RECOGNIZABLE_MAGNITUDE;
|
18
19
|
|
19
20
|
this.unitX = isMagnitudeSufficient ? this.x / this._magnitude : 0;
|
20
21
|
this.unitY = isMagnitudeSufficient ? this.y / this._magnitude : 0;
|
21
22
|
}
|
22
23
|
|
23
24
|
static fromDirection(direction: Directions | DiagonalDirections): Vector {
|
24
|
-
return DirectionToVectorMappings.get(direction)
|
25
|
+
return DirectionToVectorMappings.get(direction) ?? new Vector(0, 0);
|
25
26
|
}
|
26
27
|
|
27
28
|
static fromVelocity(tracker: PointerTracker, pointerId: number) {
|
package/src/web/utils.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { PointerType } from '../PointerType';
|
2
|
-
import { Point } from './interfaces';
|
2
|
+
import type { Point, StylusData } from './interfaces';
|
3
3
|
|
4
4
|
export function isPointerInBounds(view: HTMLElement, { x, y }: Point): boolean {
|
5
5
|
const rect: DOMRect = view.getBoundingClientRect();
|
@@ -27,28 +27,203 @@ export function calculateViewScale(view: HTMLElement) {
|
|
27
27
|
scaleY: 1,
|
28
28
|
};
|
29
29
|
|
30
|
-
|
30
|
+
// Get scales from scale property
|
31
|
+
if (styles.scale !== undefined && styles.scale !== 'none') {
|
32
|
+
const scales = styles.scale.split(' ');
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
if (scales[0]) {
|
35
|
+
resultScales.scaleX = parseFloat(scales[0]);
|
36
|
+
}
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
+
resultScales.scaleY = scales[1]
|
39
|
+
? parseFloat(scales[1])
|
40
|
+
: parseFloat(scales[0]);
|
38
41
|
}
|
39
42
|
|
43
|
+
// Get scales from transform property
|
40
44
|
const matrixElements = new RegExp(/matrix\((.+)\)/).exec(
|
41
45
|
styles.transform
|
42
46
|
)?.[1];
|
43
47
|
|
44
|
-
if (
|
45
|
-
|
48
|
+
if (matrixElements) {
|
49
|
+
const matrixElementsArray = matrixElements.split(', ');
|
50
|
+
|
51
|
+
resultScales.scaleX *= parseFloat(matrixElementsArray[0]);
|
52
|
+
resultScales.scaleY *= parseFloat(matrixElementsArray[3]);
|
46
53
|
}
|
47
54
|
|
48
|
-
|
55
|
+
return resultScales;
|
56
|
+
}
|
49
57
|
|
50
|
-
|
51
|
-
|
58
|
+
export function tryExtractStylusData(
|
59
|
+
event: PointerEvent
|
60
|
+
): StylusData | undefined {
|
61
|
+
const pointerType = PointerTypeMapping.get(event.pointerType);
|
52
62
|
|
53
|
-
|
63
|
+
if (pointerType !== PointerType.STYLUS) {
|
64
|
+
return;
|
65
|
+
}
|
66
|
+
|
67
|
+
// @ts-ignore This property exists (https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent#instance_properties)
|
68
|
+
const eventAzimuthAngle: number | undefined = event.azimuthAngle;
|
69
|
+
// @ts-ignore This property exists (https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent#instance_properties)
|
70
|
+
const eventAltitudeAngle: number | undefined = event.altitudeAngle;
|
71
|
+
|
72
|
+
if (event.tiltX === 0 && event.tiltY === 0) {
|
73
|
+
// If we are in this branch, it means that either tilt properties are not supported and we have to calculate them from altitude and azimuth angles,
|
74
|
+
// or stylus is perpendicular to the screen and we can use altitude / azimuth instead of tilt
|
75
|
+
|
76
|
+
// If azimuth and altitude are undefined in this branch, it means that we are either perpendicular to the screen,
|
77
|
+
// or that none of the position sets is supported. In that case, we can treat stylus as perpendicular
|
78
|
+
if (eventAzimuthAngle === undefined || eventAltitudeAngle === undefined) {
|
79
|
+
return {
|
80
|
+
tiltX: 0,
|
81
|
+
tiltY: 0,
|
82
|
+
azimuthAngle: Math.PI / 2,
|
83
|
+
altitudeAngle: Math.PI / 2,
|
84
|
+
pressure: event.pressure,
|
85
|
+
};
|
86
|
+
}
|
87
|
+
|
88
|
+
const { tiltX, tiltY } = spherical2tilt(
|
89
|
+
eventAltitudeAngle,
|
90
|
+
eventAzimuthAngle
|
91
|
+
);
|
92
|
+
|
93
|
+
return {
|
94
|
+
tiltX,
|
95
|
+
tiltY,
|
96
|
+
azimuthAngle: eventAzimuthAngle,
|
97
|
+
altitudeAngle: eventAltitudeAngle,
|
98
|
+
pressure: event.pressure,
|
99
|
+
};
|
100
|
+
}
|
101
|
+
|
102
|
+
const { altitudeAngle, azimuthAngle } = tilt2spherical(
|
103
|
+
event.tiltX,
|
104
|
+
event.tiltY
|
105
|
+
);
|
106
|
+
|
107
|
+
return {
|
108
|
+
tiltX: event.tiltX,
|
109
|
+
tiltY: event.tiltY,
|
110
|
+
azimuthAngle,
|
111
|
+
altitudeAngle,
|
112
|
+
pressure: event.pressure,
|
113
|
+
};
|
114
|
+
}
|
115
|
+
|
116
|
+
// `altitudeAngle` and `azimuthAngle` are experimental properties, which are not supported on Firefox and Safari.
|
117
|
+
// Given that, we use `tilt` properties and algorithm that converts one value to another.
|
118
|
+
//
|
119
|
+
// Source: https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
|
120
|
+
function tilt2spherical(tiltX: number, tiltY: number) {
|
121
|
+
const tiltXrad = (tiltX * Math.PI) / 180;
|
122
|
+
const tiltYrad = (tiltY * Math.PI) / 180;
|
123
|
+
|
124
|
+
// calculate azimuth angle
|
125
|
+
let azimuthAngle = 0;
|
126
|
+
|
127
|
+
if (tiltX === 0) {
|
128
|
+
if (tiltY > 0) {
|
129
|
+
azimuthAngle = Math.PI / 2;
|
130
|
+
} else if (tiltY < 0) {
|
131
|
+
azimuthAngle = (3 * Math.PI) / 2;
|
132
|
+
}
|
133
|
+
} else if (tiltY === 0) {
|
134
|
+
if (tiltX < 0) {
|
135
|
+
azimuthAngle = Math.PI;
|
136
|
+
}
|
137
|
+
} else if (Math.abs(tiltX) === 90 || Math.abs(tiltY) === 90) {
|
138
|
+
// not enough information to calculate azimuth
|
139
|
+
azimuthAngle = 0;
|
140
|
+
} else {
|
141
|
+
// Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90
|
142
|
+
const tanX = Math.tan(tiltXrad);
|
143
|
+
const tanY = Math.tan(tiltYrad);
|
144
|
+
|
145
|
+
azimuthAngle = Math.atan2(tanY, tanX);
|
146
|
+
if (azimuthAngle < 0) {
|
147
|
+
azimuthAngle += 2 * Math.PI;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
// calculate altitude angle
|
152
|
+
let altitudeAngle = 0;
|
153
|
+
|
154
|
+
if (Math.abs(tiltX) === 90 || Math.abs(tiltY) === 90) {
|
155
|
+
altitudeAngle = 0;
|
156
|
+
} else if (tiltX === 0) {
|
157
|
+
altitudeAngle = Math.PI / 2 - Math.abs(tiltYrad);
|
158
|
+
} else if (tiltY === 0) {
|
159
|
+
altitudeAngle = Math.PI / 2 - Math.abs(tiltXrad);
|
160
|
+
} else {
|
161
|
+
// Non-boundary case: neither tiltX nor tiltY is equal to 0 or +-90
|
162
|
+
altitudeAngle = Math.atan(
|
163
|
+
1.0 /
|
164
|
+
Math.sqrt(
|
165
|
+
Math.pow(Math.tan(tiltXrad), 2) + Math.pow(Math.tan(tiltYrad), 2)
|
166
|
+
)
|
167
|
+
);
|
168
|
+
}
|
169
|
+
|
170
|
+
return { altitudeAngle: altitudeAngle, azimuthAngle: azimuthAngle };
|
171
|
+
}
|
172
|
+
|
173
|
+
// If we are on a platform that doesn't support `tiltX` and `tiltY`, we have to calculate them from `altitude` and `azimuth` angles.
|
174
|
+
//
|
175
|
+
// Source: https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
|
176
|
+
function spherical2tilt(altitudeAngle: number, azimuthAngle: number) {
|
177
|
+
const radToDeg = 180 / Math.PI;
|
178
|
+
|
179
|
+
let tiltXrad = 0;
|
180
|
+
let tiltYrad = 0;
|
181
|
+
|
182
|
+
if (altitudeAngle === 0) {
|
183
|
+
// the pen is in the X-Y plane
|
184
|
+
if (azimuthAngle === 0 || azimuthAngle === 2 * Math.PI) {
|
185
|
+
// pen is on positive X axis
|
186
|
+
tiltXrad = Math.PI / 2;
|
187
|
+
}
|
188
|
+
if (azimuthAngle === Math.PI / 2) {
|
189
|
+
// pen is on positive Y axis
|
190
|
+
tiltYrad = Math.PI / 2;
|
191
|
+
}
|
192
|
+
if (azimuthAngle === Math.PI) {
|
193
|
+
// pen is on negative X axis
|
194
|
+
tiltXrad = -Math.PI / 2;
|
195
|
+
}
|
196
|
+
if (azimuthAngle === (3 * Math.PI) / 2) {
|
197
|
+
// pen is on negative Y axis
|
198
|
+
tiltYrad = -Math.PI / 2;
|
199
|
+
}
|
200
|
+
if (azimuthAngle > 0 && azimuthAngle < Math.PI / 2) {
|
201
|
+
tiltXrad = Math.PI / 2;
|
202
|
+
tiltYrad = Math.PI / 2;
|
203
|
+
}
|
204
|
+
if (azimuthAngle > Math.PI / 2 && azimuthAngle < Math.PI) {
|
205
|
+
tiltXrad = -Math.PI / 2;
|
206
|
+
tiltYrad = Math.PI / 2;
|
207
|
+
}
|
208
|
+
if (azimuthAngle > Math.PI && azimuthAngle < (3 * Math.PI) / 2) {
|
209
|
+
tiltXrad = -Math.PI / 2;
|
210
|
+
tiltYrad = -Math.PI / 2;
|
211
|
+
}
|
212
|
+
if (azimuthAngle > (3 * Math.PI) / 2 && azimuthAngle < 2 * Math.PI) {
|
213
|
+
tiltXrad = Math.PI / 2;
|
214
|
+
tiltYrad = -Math.PI / 2;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
if (altitudeAngle !== 0) {
|
219
|
+
const tanAlt = Math.tan(altitudeAngle);
|
220
|
+
|
221
|
+
tiltXrad = Math.atan(Math.cos(azimuthAngle) / tanAlt);
|
222
|
+
tiltYrad = Math.atan(Math.sin(azimuthAngle) / tanAlt);
|
223
|
+
}
|
224
|
+
|
225
|
+
const tiltX = Math.round(tiltXrad * radToDeg);
|
226
|
+
const tiltY = Math.round(tiltYrad * radToDeg);
|
227
|
+
|
228
|
+
return { tiltX, tiltY };
|
54
229
|
}
|