react-native-gesture-handler 2.20.2 → 2.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. package/RNGestureHandler.podspec +9 -0
  2. package/android/build.gradle +19 -0
  3. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +6 -2
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/RotationGestureDetector.kt +53 -21
  5. package/apple/RNGestureHandlerPointerTracker.m +4 -2
  6. package/lib/commonjs/RNGestureHandlerModule.web.js +15 -2
  7. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  8. package/lib/commonjs/components/Pressable/Pressable.js +2 -6
  9. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  10. package/lib/commonjs/components/ReanimatedDrawerLayout.js +389 -0
  11. package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -0
  12. package/lib/commonjs/components/ReanimatedSwipeable.js +117 -148
  13. package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
  14. package/lib/commonjs/findNodeHandle.js +12 -0
  15. package/lib/commonjs/findNodeHandle.js.map +1 -0
  16. package/lib/commonjs/findNodeHandle.web.js +40 -0
  17. package/lib/commonjs/findNodeHandle.web.js.map +1 -0
  18. package/lib/commonjs/handlers/createHandler.js +4 -2
  19. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  20. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js +51 -0
  21. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
  22. package/lib/commonjs/handlers/gestures/GestureDetector/index.js +3 -1
  23. package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
  24. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +5 -3
  25. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  26. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +4 -2
  27. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  28. package/lib/commonjs/web/handlers/GestureHandler.js +4 -0
  29. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  30. package/lib/commonjs/web/handlers/PanGestureHandler.js +59 -0
  31. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  32. package/lib/commonjs/web/interfaces.js +10 -1
  33. package/lib/commonjs/web/interfaces.js.map +1 -1
  34. package/lib/commonjs/web/tools/EventManager.js +6 -0
  35. package/lib/commonjs/web/tools/EventManager.js.map +1 -1
  36. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +1 -3
  37. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  38. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +5 -2
  39. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  40. package/lib/commonjs/web/tools/KeyboardEventManager.js +2 -2
  41. package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -1
  42. package/lib/commonjs/web/tools/PointerTracker.js +6 -30
  43. package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
  44. package/lib/commonjs/web/tools/WheelEventManager.js +74 -0
  45. package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -0
  46. package/lib/commonjs/web/utils.js +16 -0
  47. package/lib/commonjs/web/utils.js.map +1 -1
  48. package/lib/module/RNGestureHandlerModule.web.js +16 -3
  49. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  50. package/lib/module/components/Pressable/Pressable.js +2 -6
  51. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  52. package/lib/module/components/ReanimatedDrawerLayout.js +365 -0
  53. package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -0
  54. package/lib/module/components/ReanimatedSwipeable.js +119 -145
  55. package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
  56. package/lib/module/findNodeHandle.js +3 -0
  57. package/lib/module/findNodeHandle.js.map +1 -0
  58. package/lib/module/findNodeHandle.web.js +32 -0
  59. package/lib/module/findNodeHandle.web.js.map +1 -0
  60. package/lib/module/handlers/createHandler.js +2 -1
  61. package/lib/module/handlers/createHandler.js.map +1 -1
  62. package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js +34 -0
  63. package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
  64. package/lib/module/handlers/gestures/GestureDetector/index.js +2 -1
  65. package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
  66. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -2
  67. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  68. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +1 -1
  69. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  70. package/lib/module/web/handlers/GestureHandler.js +4 -0
  71. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  72. package/lib/module/web/handlers/PanGestureHandler.js +58 -0
  73. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  74. package/lib/module/web/interfaces.js +8 -0
  75. package/lib/module/web/interfaces.js.map +1 -1
  76. package/lib/module/web/tools/EventManager.js +6 -0
  77. package/lib/module/web/tools/EventManager.js.map +1 -1
  78. package/lib/module/web/tools/GestureHandlerOrchestrator.js +1 -3
  79. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  80. package/lib/module/web/tools/GestureHandlerWebDelegate.js +3 -1
  81. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  82. package/lib/module/web/tools/KeyboardEventManager.js +2 -2
  83. package/lib/module/web/tools/KeyboardEventManager.js.map +1 -1
  84. package/lib/module/web/tools/PointerTracker.js +6 -30
  85. package/lib/module/web/tools/PointerTracker.js.map +1 -1
  86. package/lib/module/web/tools/WheelEventManager.js +60 -0
  87. package/lib/module/web/tools/WheelEventManager.js.map +1 -0
  88. package/lib/module/web/utils.js +15 -0
  89. package/lib/module/web/utils.js.map +1 -1
  90. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts +162 -0
  91. package/lib/typescript/components/ReanimatedSwipeable.d.ts +22 -16
  92. package/lib/typescript/findNodeHandle.d.ts +2 -0
  93. package/lib/typescript/findNodeHandle.web.d.ts +2 -0
  94. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.web.d.ts +7 -0
  95. package/lib/typescript/web/handlers/GestureHandler.d.ts +2 -1
  96. package/lib/typescript/web/handlers/PanGestureHandler.d.ts +5 -0
  97. package/lib/typescript/web/interfaces.d.ts +16 -0
  98. package/lib/typescript/web/tools/EventManager.d.ts +2 -0
  99. package/lib/typescript/web/tools/PointerTracker.d.ts +2 -8
  100. package/lib/typescript/web/tools/WheelEventManager.d.ts +11 -0
  101. package/lib/typescript/web/utils.d.ts +2 -1
  102. package/package.json +2 -2
  103. package/src/RNGestureHandlerModule.web.ts +23 -4
  104. package/src/components/Pressable/Pressable.tsx +2 -6
  105. package/src/components/ReanimatedDrawerLayout.tsx +741 -0
  106. package/src/components/ReanimatedSwipeable.tsx +361 -305
  107. package/src/findNodeHandle.ts +3 -0
  108. package/src/findNodeHandle.web.ts +35 -0
  109. package/src/handlers/createHandler.tsx +2 -1
  110. package/src/handlers/gestures/GestureDetector/Wrap.web.tsx +44 -0
  111. package/src/handlers/gestures/GestureDetector/index.tsx +2 -1
  112. package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +1 -1
  113. package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +1 -1
  114. package/src/web/handlers/GestureHandler.ts +5 -1
  115. package/src/web/handlers/PanGestureHandler.ts +69 -1
  116. package/src/web/interfaces.ts +17 -0
  117. package/src/web/tools/EventManager.ts +4 -0
  118. package/src/web/tools/GestureHandlerOrchestrator.ts +1 -7
  119. package/src/web/tools/GestureHandlerWebDelegate.ts +3 -1
  120. package/src/web/tools/KeyboardEventManager.ts +2 -2
  121. package/src/web/tools/PointerTracker.ts +6 -28
  122. package/src/web/tools/WheelEventManager.ts +48 -0
  123. package/src/web/utils.ts +47 -1
@@ -0,0 +1,3 @@
1
+ import { findNodeHandle } from 'react-native';
2
+
3
+ export default findNodeHandle;
@@ -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, findNodeHandle, scheduleFlushOperations } from './utils';
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, findNodeHandle } from 'react-native';
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 { findNodeHandle } from 'react-native';
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
- private tryToSendMoveEvent(out: boolean, event: AdaptedEvent): void {
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
 
@@ -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
- const handlerPointers: number[] = handler.getTrackedPointersID();
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 { findNodeHandle } from 'react-native';
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.addEventListener('keydown', this.keyDownCallback);
61
- this.view.addEventListener('keyup', this.keyUpCallback);
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: { x: number; y: number } = { x: 0, y: 0 };
26
- private cachedRelativeAverages: { x: number; y: number } = { x: 0, y: 0 };
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
- if (pointerId !== undefined) {
125
- return {
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
- if (pointerId !== undefined) {
141
- return {
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 { Point, StylusData } from './interfaces';
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
+ }