react-native-gesture-handler 2.20.2 → 2.21.1
Sign up to get free protection for your applications and to get access to all the features.
- package/RNGestureHandler.podspec +9 -0
- package/ReanimatedDrawerLayout/package.json +6 -0
- package/android/build.gradle +19 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +6 -2
- package/android/src/main/java/com/swmansion/gesturehandler/core/RotationGestureDetector.kt +53 -21
- package/apple/RNGestureHandlerPointerTracker.m +4 -2
- package/lib/commonjs/RNGestureHandlerModule.web.js +15 -2
- package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/commonjs/components/Pressable/Pressable.js +2 -6
- package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
- package/lib/commonjs/components/ReanimatedDrawerLayout.js +389 -0
- package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -0
- package/lib/commonjs/components/ReanimatedSwipeable.js +117 -148
- package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/commonjs/findNodeHandle.js +12 -0
- package/lib/commonjs/findNodeHandle.js.map +1 -0
- package/lib/commonjs/findNodeHandle.web.js +40 -0
- package/lib/commonjs/findNodeHandle.web.js.map +1 -0
- package/lib/commonjs/handlers/createHandler.js +4 -2
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js +51 -0
- package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
- package/lib/commonjs/handlers/gestures/GestureDetector/index.js +3 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +5 -3
- package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +4 -2
- package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +4 -0
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +59 -0
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js +10 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/EventManager.js +6 -0
- package/lib/commonjs/web/tools/EventManager.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +1 -3
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +5 -2
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/commonjs/web/tools/KeyboardEventManager.js +2 -2
- package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -1
- package/lib/commonjs/web/tools/PointerTracker.js +6 -30
- package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
- package/lib/commonjs/web/tools/WheelEventManager.js +74 -0
- package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -0
- package/lib/commonjs/web/utils.js +16 -0
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.web.js +16 -3
- package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/module/components/Pressable/Pressable.js +2 -6
- package/lib/module/components/Pressable/Pressable.js.map +1 -1
- package/lib/module/components/ReanimatedDrawerLayout.js +365 -0
- package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -0
- package/lib/module/components/ReanimatedSwipeable.js +119 -145
- package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/module/findNodeHandle.js +3 -0
- package/lib/module/findNodeHandle.js.map +1 -0
- package/lib/module/findNodeHandle.web.js +32 -0
- package/lib/module/findNodeHandle.web.js.map +1 -0
- package/lib/module/handlers/createHandler.js +2 -1
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js +34 -0
- package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
- package/lib/module/handlers/gestures/GestureDetector/index.js +2 -1
- package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -2
- package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +1 -1
- package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +4 -0
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +58 -0
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js +8 -0
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/EventManager.js +6 -0
- package/lib/module/web/tools/EventManager.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerOrchestrator.js +1 -3
- package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js +3 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/module/web/tools/KeyboardEventManager.js +2 -2
- package/lib/module/web/tools/KeyboardEventManager.js.map +1 -1
- package/lib/module/web/tools/PointerTracker.js +6 -30
- package/lib/module/web/tools/PointerTracker.js.map +1 -1
- package/lib/module/web/tools/WheelEventManager.js +60 -0
- package/lib/module/web/tools/WheelEventManager.js.map +1 -0
- package/lib/module/web/utils.js +15 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/components/ReanimatedDrawerLayout.d.ts +162 -0
- package/lib/typescript/components/ReanimatedSwipeable.d.ts +22 -16
- package/lib/typescript/findNodeHandle.d.ts +2 -0
- package/lib/typescript/findNodeHandle.web.d.ts +2 -0
- package/lib/typescript/handlers/gestures/GestureDetector/Wrap.web.d.ts +7 -0
- package/lib/typescript/web/handlers/GestureHandler.d.ts +2 -1
- package/lib/typescript/web/handlers/PanGestureHandler.d.ts +5 -0
- package/lib/typescript/web/interfaces.d.ts +16 -0
- package/lib/typescript/web/tools/EventManager.d.ts +2 -0
- package/lib/typescript/web/tools/PointerTracker.d.ts +2 -8
- package/lib/typescript/web/tools/WheelEventManager.d.ts +11 -0
- package/lib/typescript/web/utils.d.ts +2 -1
- package/package.json +3 -2
- package/src/RNGestureHandlerModule.web.ts +23 -4
- package/src/components/Pressable/Pressable.tsx +2 -6
- package/src/components/ReanimatedDrawerLayout.tsx +741 -0
- package/src/components/ReanimatedSwipeable.tsx +361 -305
- package/src/findNodeHandle.ts +3 -0
- package/src/findNodeHandle.web.ts +35 -0
- package/src/handlers/createHandler.tsx +2 -1
- package/src/handlers/gestures/GestureDetector/Wrap.web.tsx +44 -0
- package/src/handlers/gestures/GestureDetector/index.tsx +2 -1
- package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +1 -1
- package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +1 -1
- package/src/web/handlers/GestureHandler.ts +5 -1
- package/src/web/handlers/PanGestureHandler.ts +69 -1
- package/src/web/interfaces.ts +17 -0
- package/src/web/tools/EventManager.ts +4 -0
- package/src/web/tools/GestureHandlerOrchestrator.ts +1 -7
- package/src/web/tools/GestureHandlerWebDelegate.ts +3 -1
- package/src/web/tools/KeyboardEventManager.ts +2 -2
- package/src/web/tools/PointerTracker.ts +6 -28
- package/src/web/tools/WheelEventManager.ts +48 -0
- package/src/web/utils.ts +47 -1
@@ -0,0 +1,35 @@
|
|
1
|
+
import type { GestureHandlerRef, SVGRef } from './web/interfaces';
|
2
|
+
import { isRNSVGElement } from './web/utils';
|
3
|
+
|
4
|
+
export default function findNodeHandle(
|
5
|
+
viewRef: GestureHandlerRef | SVGRef | HTMLElement | SVGElement
|
6
|
+
): HTMLElement | SVGElement | number {
|
7
|
+
// Old API assumes that child handler is HTMLElement.
|
8
|
+
// However, if we nest handlers, we will get ref to another handler.
|
9
|
+
// In that case, we want to recursively call findNodeHandle with new handler viewTag (which can also be ref to another handler).
|
10
|
+
if ((viewRef as GestureHandlerRef)?.viewTag !== undefined) {
|
11
|
+
return findNodeHandle((viewRef as GestureHandlerRef).viewTag);
|
12
|
+
}
|
13
|
+
|
14
|
+
if (viewRef instanceof Element) {
|
15
|
+
if (viewRef.style.display === 'contents') {
|
16
|
+
return findNodeHandle(viewRef.firstChild as HTMLElement);
|
17
|
+
}
|
18
|
+
|
19
|
+
return viewRef;
|
20
|
+
}
|
21
|
+
|
22
|
+
if (isRNSVGElement(viewRef)) {
|
23
|
+
return (viewRef as SVGRef).elementRef.current;
|
24
|
+
}
|
25
|
+
|
26
|
+
// In new API, we receive ref object which `current` field points to wrapper `div` with `display: contents;`.
|
27
|
+
// We want to return the first descendant (in DFS order) that doesn't have this property.
|
28
|
+
let element = (viewRef as GestureHandlerRef)?.current;
|
29
|
+
|
30
|
+
while (element && element.style.display === 'contents') {
|
31
|
+
element = element.firstChild as HTMLElement;
|
32
|
+
}
|
33
|
+
|
34
|
+
return element;
|
35
|
+
}
|
@@ -16,7 +16,8 @@ import {
|
|
16
16
|
GestureEvent,
|
17
17
|
HandlerStateChangeEvent,
|
18
18
|
} from './gestureHandlerCommon';
|
19
|
-
import { filterConfig,
|
19
|
+
import { filterConfig, scheduleFlushOperations } from './utils';
|
20
|
+
import findNodeHandle from '../findNodeHandle';
|
20
21
|
import { ValueOf } from '../typeUtils';
|
21
22
|
import { deepEqual, isFabric, isJestEnv, tagMessage } from '../utils';
|
22
23
|
import { ActionType } from '../ActionType';
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import React, { forwardRef } from 'react';
|
2
|
+
import type { LegacyRef, PropsWithChildren } from 'react';
|
3
|
+
import { tagMessage } from '../../../utils';
|
4
|
+
|
5
|
+
export const Wrap = forwardRef<HTMLDivElement, PropsWithChildren<{}>>(
|
6
|
+
({ children }, ref) => {
|
7
|
+
try {
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
9
|
+
const child: any = React.Children.only(children);
|
10
|
+
|
11
|
+
const isRNSVGNode =
|
12
|
+
Object.getPrototypeOf(child?.type)?.name === 'WebShape';
|
13
|
+
|
14
|
+
if (isRNSVGNode) {
|
15
|
+
const clone = React.cloneElement(
|
16
|
+
child,
|
17
|
+
{ ref },
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
19
|
+
child.props.children
|
20
|
+
);
|
21
|
+
|
22
|
+
return clone;
|
23
|
+
}
|
24
|
+
|
25
|
+
return (
|
26
|
+
<div
|
27
|
+
ref={ref as LegacyRef<HTMLDivElement>}
|
28
|
+
style={{ display: 'contents' }}>
|
29
|
+
{child}
|
30
|
+
</div>
|
31
|
+
);
|
32
|
+
} catch (e) {
|
33
|
+
throw new Error(
|
34
|
+
tagMessage(
|
35
|
+
`GestureDetector got more than one view as a child. If you want the gesture to work on multiple views, wrap them with a common parent and attach the gesture to that view.`
|
36
|
+
)
|
37
|
+
);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
);
|
41
|
+
|
42
|
+
// On web we never take a path with Reanimated,
|
43
|
+
// therefore we can simply export Wrap
|
44
|
+
export const AnimatedWrap = Wrap;
|
@@ -6,7 +6,8 @@ import React, {
|
|
6
6
|
useMemo,
|
7
7
|
useRef,
|
8
8
|
} from 'react';
|
9
|
-
import { Platform
|
9
|
+
import { Platform } from 'react-native';
|
10
|
+
import findNodeHandle from '../../../findNodeHandle';
|
10
11
|
import { GestureType } from '../gesture';
|
11
12
|
import { UserSelect, TouchAction } from '../../gestureHandlerCommon';
|
12
13
|
import { ComposedGesture } from '../gestureComposition';
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import React, { useCallback } from 'react';
|
2
|
-
import { findNodeHandle } from 'react-native';
|
3
2
|
import { GestureType } from '../gesture';
|
4
3
|
import { ComposedGesture } from '../gestureComposition';
|
5
4
|
|
@@ -13,6 +12,7 @@ import { updateHandlers } from './updateHandlers';
|
|
13
12
|
import { needsToReattach } from './needsToReattach';
|
14
13
|
import { dropHandlers } from './dropHandlers';
|
15
14
|
import { useForceRender, validateDetectorChildren } from './utils';
|
15
|
+
import findNodeHandle from '../../../findNodeHandle';
|
16
16
|
|
17
17
|
// Returns a function that's responsible for updating the attached gestures
|
18
18
|
// If the view has changed, it will reattach the handlers to the new view
|
@@ -3,7 +3,7 @@ import { getShadowNodeFromRef } from '../../../getShadowNodeFromRef';
|
|
3
3
|
|
4
4
|
import { GestureDetectorState } from './types';
|
5
5
|
import React, { useCallback } from 'react';
|
6
|
-
import
|
6
|
+
import findNodeHandle from '../../../findNodeHandle';
|
7
7
|
|
8
8
|
declare const global: {
|
9
9
|
isFormsStackingContext: (node: unknown) => boolean | null; // JSI function
|
@@ -74,6 +74,7 @@ export default abstract class GestureHandler implements IGestureHandler {
|
|
74
74
|
manager.setOnPointerOutOfBounds(this.onPointerOutOfBounds.bind(this));
|
75
75
|
manager.setOnPointerMoveOver(this.onPointerMoveOver.bind(this));
|
76
76
|
manager.setOnPointerMoveOut(this.onPointerMoveOut.bind(this));
|
77
|
+
manager.setOnWheel(this.onWheel.bind(this));
|
77
78
|
|
78
79
|
manager.registerListeners();
|
79
80
|
}
|
@@ -338,7 +339,10 @@ export default abstract class GestureHandler implements IGestureHandler {
|
|
338
339
|
protected onPointerMoveOut(_event: AdaptedEvent): void {
|
339
340
|
// Used only by hover gesture handler atm
|
340
341
|
}
|
341
|
-
|
342
|
+
protected onWheel(_event: AdaptedEvent): void {
|
343
|
+
// Used only by pan gesture handler
|
344
|
+
}
|
345
|
+
protected tryToSendMoveEvent(out: boolean, event: AdaptedEvent): void {
|
342
346
|
if ((out && this.shouldCancelWhenOutside) || !this.enabled) {
|
343
347
|
return;
|
344
348
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { State } from '../../State';
|
2
2
|
import { DEFAULT_TOUCH_SLOP } from '../constants';
|
3
|
-
import { AdaptedEvent, Config, StylusData } from '../interfaces';
|
3
|
+
import { AdaptedEvent, Config, StylusData, WheelDevice } from '../interfaces';
|
4
4
|
|
5
5
|
import GestureHandler from './GestureHandler';
|
6
6
|
|
@@ -57,6 +57,10 @@ export default class PanGestureHandler extends GestureHandler {
|
|
57
57
|
private activateAfterLongPress = 0;
|
58
58
|
private activationTimeout = 0;
|
59
59
|
|
60
|
+
private enableTrackpadTwoFingerGesture = false;
|
61
|
+
private endWheelTimeout = 0;
|
62
|
+
private wheelDevice = WheelDevice.UNDETERMINED;
|
63
|
+
|
60
64
|
public init(ref: number, propsRef: React.RefObject<unknown>): void {
|
61
65
|
super.init(ref, propsRef);
|
62
66
|
}
|
@@ -161,6 +165,11 @@ export default class PanGestureHandler extends GestureHandler {
|
|
161
165
|
this.failOffsetYStart = Number.MIN_SAFE_INTEGER;
|
162
166
|
}
|
163
167
|
}
|
168
|
+
|
169
|
+
if (this.config.enableTrackpadTwoFingerGesture !== undefined) {
|
170
|
+
this.enableTrackpadTwoFingerGesture =
|
171
|
+
this.config.enableTrackpadTwoFingerGesture;
|
172
|
+
}
|
164
173
|
}
|
165
174
|
|
166
175
|
protected resetConfig(): void {
|
@@ -351,6 +360,65 @@ export default class PanGestureHandler extends GestureHandler {
|
|
351
360
|
}
|
352
361
|
}
|
353
362
|
|
363
|
+
private scheduleWheelEnd(event: AdaptedEvent) {
|
364
|
+
clearTimeout(this.endWheelTimeout);
|
365
|
+
|
366
|
+
this.endWheelTimeout = setTimeout(() => {
|
367
|
+
if (this.currentState === State.ACTIVE) {
|
368
|
+
this.end();
|
369
|
+
this.tracker.removeFromTracker(event.pointerId);
|
370
|
+
this.currentState = State.UNDETERMINED;
|
371
|
+
}
|
372
|
+
|
373
|
+
this.wheelDevice = WheelDevice.UNDETERMINED;
|
374
|
+
}, 30);
|
375
|
+
}
|
376
|
+
|
377
|
+
protected onWheel(event: AdaptedEvent): void {
|
378
|
+
if (
|
379
|
+
this.wheelDevice === WheelDevice.MOUSE ||
|
380
|
+
!this.enableTrackpadTwoFingerGesture
|
381
|
+
) {
|
382
|
+
return;
|
383
|
+
}
|
384
|
+
|
385
|
+
if (this.currentState === State.UNDETERMINED) {
|
386
|
+
this.wheelDevice =
|
387
|
+
event.wheelDeltaY! % 120 !== 0
|
388
|
+
? WheelDevice.TOUCHPAD
|
389
|
+
: WheelDevice.MOUSE;
|
390
|
+
|
391
|
+
if (this.wheelDevice === WheelDevice.MOUSE) {
|
392
|
+
this.scheduleWheelEnd(event);
|
393
|
+
return;
|
394
|
+
}
|
395
|
+
|
396
|
+
this.tracker.addToTracker(event);
|
397
|
+
|
398
|
+
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
399
|
+
this.lastX = lastCoords.x;
|
400
|
+
this.lastY = lastCoords.y;
|
401
|
+
|
402
|
+
this.startX = this.lastX;
|
403
|
+
this.startY = this.lastY;
|
404
|
+
|
405
|
+
this.begin();
|
406
|
+
this.activate();
|
407
|
+
}
|
408
|
+
this.tracker.track(event);
|
409
|
+
|
410
|
+
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
|
411
|
+
this.lastX = lastCoords.x;
|
412
|
+
this.lastY = lastCoords.y;
|
413
|
+
|
414
|
+
const velocity = this.tracker.getVelocity(event.pointerId);
|
415
|
+
this.velocityX = velocity.x;
|
416
|
+
this.velocityY = velocity.y;
|
417
|
+
|
418
|
+
this.tryToSendMoveEvent(false, event);
|
419
|
+
this.scheduleWheelEnd(event);
|
420
|
+
}
|
421
|
+
|
354
422
|
private shouldActivate(): boolean {
|
355
423
|
const dx: number = this.getTranslationX();
|
356
424
|
|
package/src/web/interfaces.ts
CHANGED
@@ -78,6 +78,7 @@ export interface Config extends Record<string, ConfigArgs> {
|
|
78
78
|
shouldActivateOnStart?: boolean;
|
79
79
|
disallowInterruption?: boolean;
|
80
80
|
direction?: Directions;
|
81
|
+
enableTrackpadTwoFingerGesture?: boolean;
|
81
82
|
}
|
82
83
|
|
83
84
|
type NativeEventArgs = number | State | boolean | undefined;
|
@@ -151,6 +152,7 @@ export interface AdaptedEvent {
|
|
151
152
|
time: number;
|
152
153
|
button?: MouseButton;
|
153
154
|
stylusData?: StylusData;
|
155
|
+
wheelDeltaY?: number;
|
154
156
|
}
|
155
157
|
|
156
158
|
export enum EventTypes {
|
@@ -171,3 +173,18 @@ export enum TouchEventType {
|
|
171
173
|
UP,
|
172
174
|
CANCELLED,
|
173
175
|
}
|
176
|
+
|
177
|
+
export enum WheelDevice {
|
178
|
+
UNDETERMINED,
|
179
|
+
MOUSE,
|
180
|
+
TOUCHPAD,
|
181
|
+
}
|
182
|
+
|
183
|
+
export type GestureHandlerRef = {
|
184
|
+
viewTag: GestureHandlerRef;
|
185
|
+
current: HTMLElement;
|
186
|
+
};
|
187
|
+
|
188
|
+
export type SVGRef = {
|
189
|
+
elementRef: { current: SVGElement };
|
190
|
+
};
|
@@ -37,6 +37,7 @@ export default abstract class EventManager<T> {
|
|
37
37
|
protected onPointerOutOfBounds(_event: AdaptedEvent): void {}
|
38
38
|
protected onPointerMoveOver(_event: AdaptedEvent): void {}
|
39
39
|
protected onPointerMoveOut(_event: AdaptedEvent): void {}
|
40
|
+
protected onWheel(_event: AdaptedEvent): void {}
|
40
41
|
|
41
42
|
public setOnPointerDown(callback: PointerEventCallback): void {
|
42
43
|
this.onPointerDown = callback;
|
@@ -71,6 +72,9 @@ export default abstract class EventManager<T> {
|
|
71
72
|
public setOnPointerMoveOut(callback: PointerEventCallback): void {
|
72
73
|
this.onPointerMoveOut = callback;
|
73
74
|
}
|
75
|
+
public setOnWheel(callback: PointerEventCallback): void {
|
76
|
+
this.onWheel = callback;
|
77
|
+
}
|
74
78
|
|
75
79
|
protected markAsInBounds(pointerId: number): void {
|
76
80
|
if (this.pointersInBounds.indexOf(pointerId) >= 0) {
|
@@ -343,13 +343,7 @@ export default class GestureHandlerOrchestrator {
|
|
343
343
|
);
|
344
344
|
};
|
345
345
|
|
346
|
-
|
347
|
-
const otherPointers: number[] = otherHandler.getTrackedPointersID();
|
348
|
-
|
349
|
-
return (
|
350
|
-
handlerPointers.some(isPointerWithinBothBounds) ||
|
351
|
-
otherPointers.some(isPointerWithinBothBounds)
|
352
|
-
);
|
346
|
+
return handler.getTrackedPointersID().some(isPointerWithinBothBounds);
|
353
347
|
}
|
354
348
|
|
355
349
|
private isFinished(state: State): boolean {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import findNodeHandle from '../../findNodeHandle';
|
2
2
|
import type IGestureHandler from '../handlers/IGestureHandler';
|
3
3
|
import {
|
4
4
|
GestureHandlerDelegate,
|
@@ -11,6 +11,7 @@ import EventManager from './EventManager';
|
|
11
11
|
import { Config } from '../interfaces';
|
12
12
|
import { MouseButton } from '../../handlers/gestureHandlerCommon';
|
13
13
|
import KeyboardEventManager from './KeyboardEventManager';
|
14
|
+
import WheelEventManager from './WheelEventManager';
|
14
15
|
|
15
16
|
interface DefaultViewStyles {
|
16
17
|
userSelect: string;
|
@@ -58,6 +59,7 @@ export class GestureHandlerWebDelegate
|
|
58
59
|
|
59
60
|
this.eventManagers.push(new PointerEventManager(this.view));
|
60
61
|
this.eventManagers.push(new KeyboardEventManager(this.view));
|
62
|
+
this.eventManagers.push(new WheelEventManager(this.view));
|
61
63
|
|
62
64
|
this.eventManagers.forEach((manager) =>
|
63
65
|
this.gestureHandler.attachEventManager(manager)
|
@@ -57,8 +57,8 @@ export default class KeyboardEventManager extends EventManager<HTMLElement> {
|
|
57
57
|
}
|
58
58
|
|
59
59
|
public unregisterListeners(): void {
|
60
|
-
this.view.
|
61
|
-
this.view.
|
60
|
+
this.view.removeEventListener('keydown', this.keyDownCallback);
|
61
|
+
this.view.removeEventListener('keyup', this.keyUpCallback);
|
62
62
|
}
|
63
63
|
|
64
64
|
protected mapEvent(
|
@@ -22,8 +22,8 @@ export default class PointerTracker {
|
|
22
22
|
|
23
23
|
private lastMovedPointerId: number;
|
24
24
|
|
25
|
-
private cachedAbsoluteAverages:
|
26
|
-
private cachedRelativeAverages:
|
25
|
+
private cachedAbsoluteAverages: Point = { x: 0, y: 0 };
|
26
|
+
private cachedRelativeAverages: Point = { x: 0, y: 0 };
|
27
27
|
|
28
28
|
public constructor() {
|
29
29
|
this.lastMovedPointerId = NaN;
|
@@ -121,35 +121,13 @@ export default class PointerTracker {
|
|
121
121
|
}
|
122
122
|
|
123
123
|
public getLastAbsoluteCoords(pointerId?: number) {
|
124
|
-
|
125
|
-
|
126
|
-
x: this.trackedPointers.get(pointerId)?.abosoluteCoords.x as number,
|
127
|
-
y: this.trackedPointers.get(pointerId)?.abosoluteCoords.y as number,
|
128
|
-
};
|
129
|
-
} else {
|
130
|
-
return {
|
131
|
-
x: this.trackedPointers.get(this.lastMovedPointerId)?.abosoluteCoords
|
132
|
-
.x as number,
|
133
|
-
y: this.trackedPointers.get(this.lastMovedPointerId)?.abosoluteCoords
|
134
|
-
.y as number,
|
135
|
-
};
|
136
|
-
}
|
124
|
+
return this.trackedPointers.get(pointerId ?? this.lastMovedPointerId)
|
125
|
+
?.abosoluteCoords as Point;
|
137
126
|
}
|
138
127
|
|
139
128
|
public getLastRelativeCoords(pointerId?: number) {
|
140
|
-
|
141
|
-
|
142
|
-
x: this.trackedPointers.get(pointerId)?.relativeCoords.x as number,
|
143
|
-
y: this.trackedPointers.get(pointerId)?.relativeCoords.y as number,
|
144
|
-
};
|
145
|
-
} else {
|
146
|
-
return {
|
147
|
-
x: this.trackedPointers.get(this.lastMovedPointerId)?.relativeCoords
|
148
|
-
.x as number,
|
149
|
-
y: this.trackedPointers.get(this.lastMovedPointerId)?.relativeCoords
|
150
|
-
.y as number,
|
151
|
-
};
|
152
|
-
}
|
129
|
+
return this.trackedPointers.get(pointerId ?? this.lastMovedPointerId)
|
130
|
+
?.relativeCoords as Point;
|
153
131
|
}
|
154
132
|
|
155
133
|
// Some handlers use these methods to send average values in native event.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import EventManager from './EventManager';
|
2
|
+
import { AdaptedEvent, EventTypes } from '../interfaces';
|
3
|
+
import { PointerType } from '../../PointerType';
|
4
|
+
|
5
|
+
export default class WheelEventManager extends EventManager<HTMLElement> {
|
6
|
+
private wheelDelta = { x: 0, y: 0 };
|
7
|
+
|
8
|
+
private resetDelta = (_event: PointerEvent) => {
|
9
|
+
this.wheelDelta = { x: 0, y: 0 };
|
10
|
+
};
|
11
|
+
|
12
|
+
private wheelCallback = (event: WheelEvent) => {
|
13
|
+
this.wheelDelta.x += event.deltaX;
|
14
|
+
this.wheelDelta.y += event.deltaY;
|
15
|
+
|
16
|
+
const adaptedEvent = this.mapEvent(event);
|
17
|
+
this.onWheel(adaptedEvent);
|
18
|
+
};
|
19
|
+
|
20
|
+
public registerListeners(): void {
|
21
|
+
this.view.addEventListener('pointermove', this.resetDelta);
|
22
|
+
this.view.addEventListener('wheel', this.wheelCallback);
|
23
|
+
}
|
24
|
+
|
25
|
+
public unregisterListeners(): void {
|
26
|
+
this.view.removeEventListener('pointermove', this.resetDelta);
|
27
|
+
this.view.removeEventListener('wheel', this.wheelCallback);
|
28
|
+
}
|
29
|
+
|
30
|
+
protected mapEvent(event: WheelEvent): AdaptedEvent {
|
31
|
+
return {
|
32
|
+
x: event.clientX + this.wheelDelta.x,
|
33
|
+
y: event.clientY + this.wheelDelta.y,
|
34
|
+
offsetX: event.offsetX - event.deltaX,
|
35
|
+
offsetY: event.offsetY - event.deltaY,
|
36
|
+
pointerId: -1,
|
37
|
+
eventType: EventTypes.MOVE,
|
38
|
+
pointerType: PointerType.OTHER,
|
39
|
+
time: event.timeStamp,
|
40
|
+
// @ts-ignore It does exist, but it's deprecated
|
41
|
+
wheelDeltaY: event.wheelDeltaY,
|
42
|
+
};
|
43
|
+
}
|
44
|
+
|
45
|
+
public resetManager(): void {
|
46
|
+
super.resetManager();
|
47
|
+
}
|
48
|
+
}
|
package/src/web/utils.ts
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
import { PointerType } from '../PointerType';
|
2
|
-
import type {
|
2
|
+
import type {
|
3
|
+
GestureHandlerRef,
|
4
|
+
Point,
|
5
|
+
StylusData,
|
6
|
+
SVGRef,
|
7
|
+
} from './interfaces';
|
3
8
|
|
4
9
|
export function isPointerInBounds(view: HTMLElement, { x, y }: Point): boolean {
|
5
10
|
const rect: DOMRect = view.getBoundingClientRect();
|
@@ -227,3 +232,44 @@ function spherical2tilt(altitudeAngle: number, azimuthAngle: number) {
|
|
227
232
|
|
228
233
|
return { tiltX, tiltY };
|
229
234
|
}
|
235
|
+
|
236
|
+
const RNSVGElements = [
|
237
|
+
'Circle',
|
238
|
+
'ClipPath',
|
239
|
+
'Ellipse',
|
240
|
+
'ForeignObject',
|
241
|
+
'G',
|
242
|
+
'Image',
|
243
|
+
'Line',
|
244
|
+
'Marker',
|
245
|
+
'Mask',
|
246
|
+
'Path',
|
247
|
+
'Pattern',
|
248
|
+
'Polygon',
|
249
|
+
'Polyline',
|
250
|
+
'Rect',
|
251
|
+
'Svg',
|
252
|
+
'Symbol',
|
253
|
+
'TSpan',
|
254
|
+
'Text',
|
255
|
+
'TextPath',
|
256
|
+
'Use',
|
257
|
+
];
|
258
|
+
|
259
|
+
// This function helps us determine whether given node is SVGElement or not. In our implementation of
|
260
|
+
// findNodeHandle, we can encounter such element in 2 forms - SVG tag or ref to SVG Element. Since Gesture Handler
|
261
|
+
// does not depend on SVG, we use our simplified SVGRef type that has `elementRef` field. This is something that is present
|
262
|
+
// in actual SVG ref object.
|
263
|
+
//
|
264
|
+
// In order to make sure that node passed into this function is in fact SVG element, first we check if its constructor name
|
265
|
+
// corresponds to one of the possible SVG elements. Then we also check if `elementRef` field exists.
|
266
|
+
// By doing both steps we decrease probability of detecting situations where, for example, user makes custom `Circle` and
|
267
|
+
// we treat it as SVG.
|
268
|
+
export function isRNSVGElement(viewRef: SVGRef | GestureHandlerRef) {
|
269
|
+
const componentClassName = Object.getPrototypeOf(viewRef).constructor.name;
|
270
|
+
|
271
|
+
return (
|
272
|
+
RNSVGElements.indexOf(componentClassName) >= 0 &&
|
273
|
+
Object.hasOwn(viewRef, 'elementRef')
|
274
|
+
);
|
275
|
+
}
|