react-native-gesture-handler 2.20.2 → 2.21.1

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.
Files changed (124) hide show
  1. package/RNGestureHandler.podspec +9 -0
  2. package/ReanimatedDrawerLayout/package.json +6 -0
  3. package/android/build.gradle +19 -0
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +6 -2
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/RotationGestureDetector.kt +53 -21
  6. package/apple/RNGestureHandlerPointerTracker.m +4 -2
  7. package/lib/commonjs/RNGestureHandlerModule.web.js +15 -2
  8. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  9. package/lib/commonjs/components/Pressable/Pressable.js +2 -6
  10. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  11. package/lib/commonjs/components/ReanimatedDrawerLayout.js +389 -0
  12. package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -0
  13. package/lib/commonjs/components/ReanimatedSwipeable.js +117 -148
  14. package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
  15. package/lib/commonjs/findNodeHandle.js +12 -0
  16. package/lib/commonjs/findNodeHandle.js.map +1 -0
  17. package/lib/commonjs/findNodeHandle.web.js +40 -0
  18. package/lib/commonjs/findNodeHandle.web.js.map +1 -0
  19. package/lib/commonjs/handlers/createHandler.js +4 -2
  20. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  21. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js +51 -0
  22. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
  23. package/lib/commonjs/handlers/gestures/GestureDetector/index.js +3 -1
  24. package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
  25. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +5 -3
  26. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  27. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +4 -2
  28. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  29. package/lib/commonjs/web/handlers/GestureHandler.js +4 -0
  30. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  31. package/lib/commonjs/web/handlers/PanGestureHandler.js +59 -0
  32. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  33. package/lib/commonjs/web/interfaces.js +10 -1
  34. package/lib/commonjs/web/interfaces.js.map +1 -1
  35. package/lib/commonjs/web/tools/EventManager.js +6 -0
  36. package/lib/commonjs/web/tools/EventManager.js.map +1 -1
  37. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +1 -3
  38. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  39. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +5 -2
  40. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  41. package/lib/commonjs/web/tools/KeyboardEventManager.js +2 -2
  42. package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -1
  43. package/lib/commonjs/web/tools/PointerTracker.js +6 -30
  44. package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
  45. package/lib/commonjs/web/tools/WheelEventManager.js +74 -0
  46. package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -0
  47. package/lib/commonjs/web/utils.js +16 -0
  48. package/lib/commonjs/web/utils.js.map +1 -1
  49. package/lib/module/RNGestureHandlerModule.web.js +16 -3
  50. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  51. package/lib/module/components/Pressable/Pressable.js +2 -6
  52. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  53. package/lib/module/components/ReanimatedDrawerLayout.js +365 -0
  54. package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -0
  55. package/lib/module/components/ReanimatedSwipeable.js +119 -145
  56. package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
  57. package/lib/module/findNodeHandle.js +3 -0
  58. package/lib/module/findNodeHandle.js.map +1 -0
  59. package/lib/module/findNodeHandle.web.js +32 -0
  60. package/lib/module/findNodeHandle.web.js.map +1 -0
  61. package/lib/module/handlers/createHandler.js +2 -1
  62. package/lib/module/handlers/createHandler.js.map +1 -1
  63. package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js +34 -0
  64. package/lib/module/handlers/gestures/GestureDetector/Wrap.web.js.map +1 -0
  65. package/lib/module/handlers/gestures/GestureDetector/index.js +2 -1
  66. package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
  67. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -2
  68. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  69. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +1 -1
  70. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  71. package/lib/module/web/handlers/GestureHandler.js +4 -0
  72. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  73. package/lib/module/web/handlers/PanGestureHandler.js +58 -0
  74. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  75. package/lib/module/web/interfaces.js +8 -0
  76. package/lib/module/web/interfaces.js.map +1 -1
  77. package/lib/module/web/tools/EventManager.js +6 -0
  78. package/lib/module/web/tools/EventManager.js.map +1 -1
  79. package/lib/module/web/tools/GestureHandlerOrchestrator.js +1 -3
  80. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  81. package/lib/module/web/tools/GestureHandlerWebDelegate.js +3 -1
  82. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  83. package/lib/module/web/tools/KeyboardEventManager.js +2 -2
  84. package/lib/module/web/tools/KeyboardEventManager.js.map +1 -1
  85. package/lib/module/web/tools/PointerTracker.js +6 -30
  86. package/lib/module/web/tools/PointerTracker.js.map +1 -1
  87. package/lib/module/web/tools/WheelEventManager.js +60 -0
  88. package/lib/module/web/tools/WheelEventManager.js.map +1 -0
  89. package/lib/module/web/utils.js +15 -0
  90. package/lib/module/web/utils.js.map +1 -1
  91. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts +162 -0
  92. package/lib/typescript/components/ReanimatedSwipeable.d.ts +22 -16
  93. package/lib/typescript/findNodeHandle.d.ts +2 -0
  94. package/lib/typescript/findNodeHandle.web.d.ts +2 -0
  95. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.web.d.ts +7 -0
  96. package/lib/typescript/web/handlers/GestureHandler.d.ts +2 -1
  97. package/lib/typescript/web/handlers/PanGestureHandler.d.ts +5 -0
  98. package/lib/typescript/web/interfaces.d.ts +16 -0
  99. package/lib/typescript/web/tools/EventManager.d.ts +2 -0
  100. package/lib/typescript/web/tools/PointerTracker.d.ts +2 -8
  101. package/lib/typescript/web/tools/WheelEventManager.d.ts +11 -0
  102. package/lib/typescript/web/utils.d.ts +2 -1
  103. package/package.json +3 -2
  104. package/src/RNGestureHandlerModule.web.ts +23 -4
  105. package/src/components/Pressable/Pressable.tsx +2 -6
  106. package/src/components/ReanimatedDrawerLayout.tsx +741 -0
  107. package/src/components/ReanimatedSwipeable.tsx +361 -305
  108. package/src/findNodeHandle.ts +3 -0
  109. package/src/findNodeHandle.web.ts +35 -0
  110. package/src/handlers/createHandler.tsx +2 -1
  111. package/src/handlers/gestures/GestureDetector/Wrap.web.tsx +44 -0
  112. package/src/handlers/gestures/GestureDetector/index.tsx +2 -1
  113. package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +1 -1
  114. package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +1 -1
  115. package/src/web/handlers/GestureHandler.ts +5 -1
  116. package/src/web/handlers/PanGestureHandler.ts +69 -1
  117. package/src/web/interfaces.ts +17 -0
  118. package/src/web/tools/EventManager.ts +4 -0
  119. package/src/web/tools/GestureHandlerOrchestrator.ts +1 -7
  120. package/src/web/tools/GestureHandlerWebDelegate.ts +3 -1
  121. package/src/web/tools/KeyboardEventManager.ts +2 -2
  122. package/src/web/tools/PointerTracker.ts +6 -28
  123. package/src/web/tools/WheelEventManager.ts +48 -0
  124. 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
+ }