react-native-gesture-handler 2.6.0 → 2.6.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 (177) hide show
  1. package/android/build.gradle +2 -2
  2. package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  3. package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcuserdata/jakubpiasecki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  4. package/ios/RNGestureHandler.xcodeproj/xcuserdata/jakubpiasecki.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  5. package/lib/commonjs/EnableExperimentalWebImplementation.js +7 -0
  6. package/lib/commonjs/EnableExperimentalWebImplementation.js.map +1 -1
  7. package/lib/commonjs/RNGestureHandlerModule.js +1 -1
  8. package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
  9. package/lib/commonjs/RNGestureHandlerModule.macos.js +20 -9
  10. package/lib/commonjs/RNGestureHandlerModule.macos.js.map +1 -1
  11. package/lib/commonjs/RNGestureHandlerModule.web.js +23 -10
  12. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  13. package/lib/commonjs/components/GestureComponents.web.js +1 -1
  14. package/lib/commonjs/components/GestureComponents.web.js.map +1 -1
  15. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js +1 -5
  16. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  17. package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js +1 -5
  18. package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  19. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  20. package/lib/commonjs/handlers/gestures/eventReceiver.js +14 -20
  21. package/lib/commonjs/handlers/gestures/eventReceiver.js.map +1 -1
  22. package/lib/commonjs/handlers/gestures/gestureStateManager.web.js +32 -0
  23. package/lib/commonjs/handlers/gestures/gestureStateManager.web.js.map +1 -0
  24. package/lib/commonjs/web/detectors/RotationGestureDetector.js +13 -17
  25. package/lib/commonjs/web/detectors/RotationGestureDetector.js.map +1 -1
  26. package/lib/commonjs/web/detectors/ScaleGestureDetector.js +3 -14
  27. package/lib/commonjs/web/detectors/ScaleGestureDetector.js.map +1 -1
  28. package/lib/commonjs/web/handlers/FlingGestureHandler.js +37 -12
  29. package/lib/commonjs/web/handlers/FlingGestureHandler.js.map +1 -1
  30. package/lib/commonjs/web/handlers/GestureHandler.js +282 -79
  31. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  32. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +23 -18
  33. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  34. package/lib/commonjs/web/handlers/ManualGestureHandler.js +51 -0
  35. package/lib/commonjs/web/handlers/ManualGestureHandler.js.map +1 -0
  36. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +81 -22
  37. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  38. package/lib/commonjs/web/handlers/PanGestureHandler.js +57 -40
  39. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  40. package/lib/commonjs/web/handlers/PinchGestureHandler.js +43 -34
  41. package/lib/commonjs/web/handlers/PinchGestureHandler.js.map +1 -1
  42. package/lib/commonjs/web/handlers/RotationGestureHandler.js +45 -39
  43. package/lib/commonjs/web/handlers/RotationGestureHandler.js.map +1 -1
  44. package/lib/commonjs/web/handlers/TapGestureHandler.js +52 -50
  45. package/lib/commonjs/web/handlers/TapGestureHandler.js.map +1 -1
  46. package/lib/commonjs/web/interfaces.js +22 -1
  47. package/lib/commonjs/web/interfaces.js.map +1 -1
  48. package/lib/commonjs/web/tools/EventManager.js +40 -96
  49. package/lib/commonjs/web/tools/EventManager.js.map +1 -1
  50. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +109 -30
  51. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  52. package/lib/commonjs/web/tools/InteractionManager.js +24 -10
  53. package/lib/commonjs/web/tools/InteractionManager.js.map +1 -1
  54. package/lib/commonjs/web/tools/NodeManager.js.map +1 -1
  55. package/lib/commonjs/web/tools/PointerEventManager.js +130 -0
  56. package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -0
  57. package/lib/commonjs/web/tools/PointerTracker.js +97 -7
  58. package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
  59. package/lib/commonjs/web/tools/TouchEventManager.js +138 -0
  60. package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -0
  61. package/lib/commonjs/web/utils.js +15 -0
  62. package/lib/commonjs/web/utils.js.map +1 -0
  63. package/lib/module/EnableExperimentalWebImplementation.js +5 -0
  64. package/lib/module/EnableExperimentalWebImplementation.js.map +1 -1
  65. package/lib/module/RNGestureHandlerModule.js +1 -1
  66. package/lib/module/RNGestureHandlerModule.js.map +1 -1
  67. package/lib/module/RNGestureHandlerModule.macos.js +19 -10
  68. package/lib/module/RNGestureHandlerModule.macos.js.map +1 -1
  69. package/lib/module/RNGestureHandlerModule.web.js +22 -11
  70. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  71. package/lib/module/components/GestureComponents.web.js +1 -1
  72. package/lib/module/components/GestureComponents.web.js.map +1 -1
  73. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js +1 -5
  74. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  75. package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js +1 -4
  76. package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  77. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  78. package/lib/module/handlers/gestures/eventReceiver.js +14 -20
  79. package/lib/module/handlers/gestures/eventReceiver.js.map +1 -1
  80. package/lib/module/handlers/gestures/gestureStateManager.web.js +21 -0
  81. package/lib/module/handlers/gestures/gestureStateManager.web.js.map +1 -0
  82. package/lib/module/web/detectors/RotationGestureDetector.js +13 -17
  83. package/lib/module/web/detectors/RotationGestureDetector.js.map +1 -1
  84. package/lib/module/web/detectors/ScaleGestureDetector.js +3 -14
  85. package/lib/module/web/detectors/ScaleGestureDetector.js.map +1 -1
  86. package/lib/module/web/handlers/FlingGestureHandler.js +37 -12
  87. package/lib/module/web/handlers/FlingGestureHandler.js.map +1 -1
  88. package/lib/module/web/handlers/GestureHandler.js +276 -79
  89. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  90. package/lib/module/web/handlers/LongPressGestureHandler.js +23 -18
  91. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  92. package/lib/module/web/handlers/ManualGestureHandler.js +39 -0
  93. package/lib/module/web/handlers/ManualGestureHandler.js.map +1 -0
  94. package/lib/module/web/handlers/NativeViewGestureHandler.js +80 -22
  95. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  96. package/lib/module/web/handlers/PanGestureHandler.js +57 -41
  97. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  98. package/lib/module/web/handlers/PinchGestureHandler.js +43 -33
  99. package/lib/module/web/handlers/PinchGestureHandler.js.map +1 -1
  100. package/lib/module/web/handlers/RotationGestureHandler.js +45 -38
  101. package/lib/module/web/handlers/RotationGestureHandler.js.map +1 -1
  102. package/lib/module/web/handlers/TapGestureHandler.js +52 -50
  103. package/lib/module/web/handlers/TapGestureHandler.js.map +1 -1
  104. package/lib/module/web/interfaces.js +19 -0
  105. package/lib/module/web/interfaces.js.map +1 -1
  106. package/lib/module/web/tools/EventManager.js +39 -95
  107. package/lib/module/web/tools/EventManager.js.map +1 -1
  108. package/lib/module/web/tools/GestureHandlerOrchestrator.js +107 -30
  109. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  110. package/lib/module/web/tools/InteractionManager.js +24 -10
  111. package/lib/module/web/tools/InteractionManager.js.map +1 -1
  112. package/lib/module/web/tools/NodeManager.js.map +1 -1
  113. package/lib/module/web/tools/PointerEventManager.js +116 -0
  114. package/lib/module/web/tools/PointerEventManager.js.map +1 -0
  115. package/lib/module/web/tools/PointerTracker.js +97 -7
  116. package/lib/module/web/tools/PointerTracker.js.map +1 -1
  117. package/lib/module/web/tools/TouchEventManager.js +124 -0
  118. package/lib/module/web/tools/TouchEventManager.js.map +1 -0
  119. package/lib/module/web/utils.js +8 -0
  120. package/lib/module/web/utils.js.map +1 -0
  121. package/lib/typescript/RNGestureHandlerModule.macos.d.ts +5 -2
  122. package/lib/typescript/RNGestureHandlerModule.web.d.ts +5 -2
  123. package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts +1 -1
  124. package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +3 -3
  125. package/lib/typescript/fabric/RNGestureHandlerRootViewNativeComponent.d.ts +3 -2
  126. package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts +4 -0
  127. package/lib/typescript/web/detectors/RotationGestureDetector.d.ts +7 -7
  128. package/lib/typescript/web/detectors/ScaleGestureDetector.d.ts +6 -7
  129. package/lib/typescript/web/handlers/FlingGestureHandler.d.ts +12 -10
  130. package/lib/typescript/web/handlers/GestureHandler.d.ts +41 -32
  131. package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +6 -9
  132. package/lib/typescript/web/handlers/ManualGestureHandler.d.ts +11 -0
  133. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +15 -6
  134. package/lib/typescript/web/handlers/PanGestureHandler.d.ts +15 -23
  135. package/lib/typescript/web/handlers/PinchGestureHandler.d.ts +11 -12
  136. package/lib/typescript/web/handlers/RotationGestureHandler.d.ts +12 -12
  137. package/lib/typescript/web/handlers/TapGestureHandler.d.ts +11 -14
  138. package/lib/typescript/web/interfaces.d.ts +50 -10
  139. package/lib/typescript/web/tools/EventManager.d.ts +28 -26
  140. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +4 -2
  141. package/lib/typescript/web/tools/InteractionManager.d.ts +3 -0
  142. package/lib/typescript/web/tools/NodeManager.d.ts +3 -3
  143. package/lib/typescript/web/tools/PointerEventManager.d.ts +6 -0
  144. package/lib/typescript/web/tools/PointerTracker.d.ts +29 -5
  145. package/lib/typescript/web/tools/TouchEventManager.d.ts +6 -0
  146. package/lib/typescript/web/utils.d.ts +4 -0
  147. package/package.json +2 -2
  148. package/src/EnableExperimentalWebImplementation.ts +9 -0
  149. package/src/RNGestureHandlerModule.macos.ts +25 -10
  150. package/src/RNGestureHandlerModule.ts +4 -1
  151. package/src/RNGestureHandlerModule.web.ts +20 -7
  152. package/src/components/GestureComponents.web.tsx +1 -1
  153. package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +2 -12
  154. package/src/fabric/RNGestureHandlerRootViewNativeComponent.ts +2 -8
  155. package/src/handlers/gestures/GestureDetector.tsx +0 -1
  156. package/src/handlers/gestures/eventReceiver.ts +23 -24
  157. package/src/handlers/gestures/gestureStateManager.web.ts +24 -0
  158. package/src/web/detectors/RotationGestureDetector.ts +20 -52
  159. package/src/web/detectors/ScaleGestureDetector.ts +9 -45
  160. package/src/web/handlers/FlingGestureHandler.ts +45 -22
  161. package/src/web/handlers/GestureHandler.ts +306 -97
  162. package/src/web/handlers/LongPressGestureHandler.ts +30 -24
  163. package/src/web/handlers/ManualGestureHandler.ts +39 -0
  164. package/src/web/handlers/NativeViewGestureHandler.ts +81 -24
  165. package/src/web/handlers/PanGestureHandler.ts +68 -53
  166. package/src/web/handlers/PinchGestureHandler.ts +47 -44
  167. package/src/web/handlers/RotationGestureHandler.ts +52 -51
  168. package/src/web/handlers/TapGestureHandler.ts +74 -56
  169. package/src/web/interfaces.ts +57 -10
  170. package/src/web/tools/EventManager.ts +58 -148
  171. package/src/web/tools/GestureHandlerOrchestrator.ts +115 -47
  172. package/src/web/tools/InteractionManager.ts +25 -9
  173. package/src/web/tools/NodeManager.ts +6 -6
  174. package/src/web/tools/PointerEventManager.ts +134 -0
  175. package/src/web/tools/PointerTracker.ts +120 -10
  176. package/src/web/tools/TouchEventManager.ts +167 -0
  177. package/src/web/utils.ts +8 -0
@@ -2,19 +2,26 @@ import GestureHandler from '../handlers/GestureHandler';
2
2
  import { Config, Handler } from '../interfaces';
3
3
 
4
4
  export default class InteractionManager {
5
+ private static instance: InteractionManager;
5
6
  private readonly waitForRelations: Map<number, number[]> = new Map();
6
7
  private readonly simultaneousRelations: Map<number, number[]> = new Map();
7
8
 
9
+ // Private becaues of singleton
10
+ // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
11
+ private constructor() {}
12
+
8
13
  public configureInteractions(handler: GestureHandler, config: Config) {
9
14
  this.dropRelationsForHandlerWithTag(handler.getTag());
10
15
 
11
16
  if (config.waitFor) {
12
17
  const waitFor: number[] = [];
13
- config.waitFor.forEach((handler: Handler): void => {
14
- if (typeof handler === 'number') {
15
- waitFor.push(handler);
18
+ config.waitFor.forEach((otherHandler: Handler): void => {
19
+ // New API reference
20
+ if (typeof otherHandler === 'number') {
21
+ waitFor.push(otherHandler);
16
22
  } else {
17
- waitFor.push(handler.handlerTag);
23
+ // Old API reference
24
+ waitFor.push(otherHandler.handlerTag);
18
25
  }
19
26
  });
20
27
 
@@ -23,17 +30,16 @@ export default class InteractionManager {
23
30
 
24
31
  if (config.simultaneousHandlers) {
25
32
  const simultaneousHandlers: number[] = [];
26
- config.simultaneousHandlers.forEach((handler: Handler): void => {
27
- if (typeof handler === 'number') {
28
- simultaneousHandlers.push(handler);
33
+ config.simultaneousHandlers.forEach((otherHandler: Handler): void => {
34
+ if (typeof otherHandler === 'number') {
35
+ simultaneousHandlers.push(otherHandler);
29
36
  } else {
30
- simultaneousHandlers.push(handler.handlerTag);
37
+ simultaneousHandlers.push(otherHandler.handlerTag);
31
38
  }
32
39
  });
33
40
 
34
41
  this.simultaneousRelations.set(handler.getTag(), simultaneousHandlers);
35
42
  }
36
- handler.setInteractionManager(this);
37
43
  }
38
44
 
39
45
  public shouldWaitForHandlerFailure(
@@ -86,6 +92,7 @@ export default class InteractionManager {
86
92
  _handler: GestureHandler,
87
93
  _otherHandler: GestureHandler
88
94
  ): boolean {
95
+ //TODO: Implement logic
89
96
  return false;
90
97
  }
91
98
 
@@ -93,6 +100,7 @@ export default class InteractionManager {
93
100
  _handler: GestureHandler,
94
101
  _otherHandler: GestureHandler
95
102
  ): boolean {
103
+ //TODO: Implement logic
96
104
  return false;
97
105
  }
98
106
 
@@ -105,4 +113,12 @@ export default class InteractionManager {
105
113
  this.waitForRelations.clear();
106
114
  this.simultaneousRelations.clear();
107
115
  }
116
+
117
+ public static getInstance(): InteractionManager {
118
+ if (!this.instance) {
119
+ this.instance = new InteractionManager();
120
+ }
121
+
122
+ return this.instance;
123
+ }
108
124
  }
@@ -2,13 +2,13 @@ import { ValueOf } from '../../typeUtils';
2
2
  import { Gestures } from '../../RNGestureHandlerModule.web';
3
3
 
4
4
  // eslint-disable-next-line @typescript-eslint/no-extraneous-class
5
- export default class NodeManager {
5
+ export default abstract class NodeManager {
6
6
  private static gestures: Record<
7
7
  number,
8
8
  InstanceType<ValueOf<typeof Gestures>>
9
9
  > = {};
10
10
 
11
- static getHandler(tag: number) {
11
+ public static getHandler(tag: number) {
12
12
  if (tag in this.gestures) {
13
13
  return this.gestures[tag];
14
14
  }
@@ -16,10 +16,10 @@ export default class NodeManager {
16
16
  throw new Error(`No handler for tag ${tag}`);
17
17
  }
18
18
 
19
- static createGestureHandler(
19
+ public static createGestureHandler(
20
20
  handlerTag: number,
21
21
  handler: InstanceType<ValueOf<typeof Gestures>>
22
- ) {
22
+ ): void {
23
23
  if (handlerTag in this.gestures) {
24
24
  throw new Error(`Handler with tag ${handlerTag} already exists`);
25
25
  }
@@ -28,7 +28,7 @@ export default class NodeManager {
28
28
  this.gestures[handlerTag].setTag(handlerTag);
29
29
  }
30
30
 
31
- static dropGestureHandler(handlerTag: number) {
31
+ public static dropGestureHandler(handlerTag: number): void {
32
32
  if (!(handlerTag in this.gestures)) {
33
33
  return;
34
34
  }
@@ -37,7 +37,7 @@ export default class NodeManager {
37
37
  delete this.gestures[handlerTag];
38
38
  }
39
39
 
40
- static getNodes() {
40
+ public static getNodes() {
41
41
  return { ...this.gestures };
42
42
  }
43
43
  }
@@ -0,0 +1,134 @@
1
+ import {
2
+ AdaptedEvent,
3
+ EventTypes,
4
+ MouseButtons,
5
+ PointerType,
6
+ } from '../interfaces';
7
+ import EventManager from './EventManager';
8
+ import { isPointerInBounds } from '../utils';
9
+
10
+ export default class PointerEventManager extends EventManager {
11
+ public setListeners(): void {
12
+ this.view.addEventListener('pointerdown', (event: PointerEvent): void => {
13
+ if (event.pointerType === PointerType.TOUCH) {
14
+ return;
15
+ }
16
+ if (
17
+ !isPointerInBounds(this.view, { x: event.clientX, y: event.clientY })
18
+ ) {
19
+ return;
20
+ }
21
+
22
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.DOWN);
23
+ const target = event.target as HTMLElement;
24
+
25
+ target.setPointerCapture(adaptedEvent.pointerId);
26
+ this.markAsInBounds(adaptedEvent.pointerId);
27
+
28
+ if (++this.activePointersCounter > 1) {
29
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
30
+ this.onPointerAdd(adaptedEvent);
31
+ } else {
32
+ this.onPointerDown(adaptedEvent);
33
+ }
34
+ });
35
+
36
+ this.view.addEventListener('pointerup', (event: PointerEvent): void => {
37
+ if (event.pointerType === PointerType.TOUCH) {
38
+ return;
39
+ }
40
+
41
+ // When we call reset on gesture handlers, it also resets their event managers
42
+ // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
43
+ // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
44
+ // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
45
+ if (this.activePointersCounter === 0) {
46
+ return;
47
+ }
48
+
49
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.UP);
50
+ const target = event.target as HTMLElement;
51
+
52
+ target.releasePointerCapture(adaptedEvent.pointerId);
53
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
54
+
55
+ if (--this.activePointersCounter > 0) {
56
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
57
+ this.onPointerRemove(adaptedEvent);
58
+ } else {
59
+ this.onPointerUp(adaptedEvent);
60
+ }
61
+ });
62
+
63
+ this.view.addEventListener('pointermove', (event: PointerEvent): void => {
64
+ if (event.pointerType === PointerType.TOUCH) {
65
+ return;
66
+ }
67
+
68
+ if (
69
+ event.pointerType === PointerType.MOUSE &&
70
+ event.buttons !== MouseButtons.LEFT
71
+ ) {
72
+ return;
73
+ }
74
+
75
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.MOVE);
76
+
77
+ const inBounds: boolean = isPointerInBounds(this.view, {
78
+ x: adaptedEvent.x,
79
+ y: adaptedEvent.y,
80
+ });
81
+
82
+ const pointerIndex: number = this.pointersInBounds.indexOf(
83
+ adaptedEvent.pointerId
84
+ );
85
+
86
+ if (inBounds) {
87
+ if (pointerIndex < 0) {
88
+ adaptedEvent.eventType = EventTypes.ENTER;
89
+ this.onPointerEnter(adaptedEvent);
90
+ this.markAsInBounds(adaptedEvent.pointerId);
91
+ } else {
92
+ this.onPointerMove(adaptedEvent);
93
+ }
94
+ } else {
95
+ if (pointerIndex >= 0) {
96
+ adaptedEvent.eventType = EventTypes.OUT;
97
+ this.onPointerOut(adaptedEvent);
98
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
99
+ } else {
100
+ this.onPointerOutOfBounds(adaptedEvent);
101
+ }
102
+ }
103
+ });
104
+
105
+ this.view.addEventListener('pointercancel', (event: PointerEvent): void => {
106
+ if (event.pointerType === PointerType.TOUCH) {
107
+ return;
108
+ }
109
+
110
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
111
+ event,
112
+ EventTypes.CANCEL
113
+ );
114
+
115
+ this.onPointerCancel(adaptedEvent);
116
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
117
+ this.activePointersCounter = 0;
118
+ });
119
+ }
120
+
121
+ protected mapEvent(event: PointerEvent, eventType: EventTypes): AdaptedEvent {
122
+ return {
123
+ x: event.clientX,
124
+ y: event.clientY,
125
+ offsetX: event.offsetX,
126
+ offsetY: event.offsetY,
127
+ pointerId: event.pointerId,
128
+ eventType: eventType,
129
+ pointerType: event.pointerType as PointerType,
130
+ buttons: event.buttons,
131
+ time: event.timeStamp,
132
+ };
133
+ }
134
+ }
@@ -1,6 +1,6 @@
1
- import { AdaptedPointerEvent } from '../interfaces';
1
+ import { AdaptedEvent } from '../interfaces';
2
2
 
3
- interface TrackerElement {
3
+ export interface TrackerElement {
4
4
  lastX: number;
5
5
  lastY: number;
6
6
 
@@ -10,7 +10,9 @@ interface TrackerElement {
10
10
  velocityY: number;
11
11
  }
12
12
 
13
+ // Used to scale velocity so that it is similar to velocity in Android/iOS
13
14
  const VELOCITY_FACTOR = 0.2;
15
+ const MAX_POINTERS = 20;
14
16
 
15
17
  export default class PointerTracker {
16
18
  private trackedPointers: Map<number, TrackerElement> = new Map<
@@ -18,11 +20,27 @@ export default class PointerTracker {
18
20
  TrackerElement
19
21
  >();
20
22
 
21
- public addToTracker(event: AdaptedPointerEvent): void {
23
+ private touchEventsIds: Map<number, number> = new Map<number, number>();
24
+
25
+ private lastMovedPointerId: number;
26
+
27
+ private cachedAverages: { x: number; y: number } = { x: 0, y: 0 };
28
+
29
+ public constructor() {
30
+ this.lastMovedPointerId = NaN;
31
+
32
+ for (let i = 0; i < MAX_POINTERS; ++i) {
33
+ this.touchEventsIds.set(i, NaN);
34
+ }
35
+ }
36
+
37
+ public addToTracker(event: AdaptedEvent): void {
22
38
  if (this.trackedPointers.has(event.pointerId)) {
23
39
  return;
24
40
  }
25
41
 
42
+ this.lastMovedPointerId = event.pointerId;
43
+
26
44
  const newElement: TrackerElement = {
27
45
  lastX: event.x,
28
46
  lastY: event.y,
@@ -32,13 +50,20 @@ export default class PointerTracker {
32
50
  };
33
51
 
34
52
  this.trackedPointers.set(event.pointerId, newElement);
53
+ this.mapTouchEventId(event.pointerId);
54
+
55
+ this.cachedAverages = {
56
+ x: this.getLastAvgX(),
57
+ y: this.getLastAvgY(),
58
+ };
35
59
  }
36
60
 
37
61
  public removeFromTracker(pointerId: number): void {
38
62
  this.trackedPointers.delete(pointerId);
63
+ this.removeMappedTouchId(pointerId);
39
64
  }
40
65
 
41
- public track(event: AdaptedPointerEvent): void {
66
+ public track(event: AdaptedEvent): void {
42
67
  const element: TrackerElement = this.trackedPointers.get(
43
68
  event.pointerId
44
69
  ) as TrackerElement;
@@ -47,6 +72,8 @@ export default class PointerTracker {
47
72
  return;
48
73
  }
49
74
 
75
+ this.lastMovedPointerId = event.pointerId;
76
+
50
77
  const dx = event.x - element.lastX;
51
78
  const dy = event.y - element.lastY;
52
79
  const dt = event.time - element.timeStamp;
@@ -58,6 +85,41 @@ export default class PointerTracker {
58
85
  element.lastY = event.y;
59
86
 
60
87
  this.trackedPointers.set(event.pointerId, element);
88
+
89
+ const avgX: number = this.getLastAvgX();
90
+ const avgY: number = this.getLastAvgY();
91
+
92
+ this.cachedAverages = {
93
+ x: avgX,
94
+ y: avgY,
95
+ };
96
+ }
97
+
98
+ //Mapping TouchEvents ID
99
+ private mapTouchEventId(id: number): void {
100
+ for (const [mappedId, touchId] of this.touchEventsIds) {
101
+ if (isNaN(touchId)) {
102
+ this.touchEventsIds.set(mappedId, id);
103
+ break;
104
+ }
105
+ }
106
+ }
107
+
108
+ private removeMappedTouchId(id: number): void {
109
+ const mappedId: number = this.getMappedTouchEventId(id);
110
+ if (!isNaN(mappedId)) {
111
+ this.touchEventsIds.set(mappedId, NaN);
112
+ }
113
+ }
114
+
115
+ public getMappedTouchEventId(touchEventId: number): number {
116
+ for (const [key, value] of this.touchEventsIds.entries()) {
117
+ if (value === touchEventId) {
118
+ return key;
119
+ }
120
+ }
121
+
122
+ return NaN;
61
123
  }
62
124
 
63
125
  public getVelocityX(pointerId: number): number {
@@ -66,17 +128,60 @@ export default class PointerTracker {
66
128
  public getVelocityY(pointerId: number): number {
67
129
  return this.trackedPointers.get(pointerId)?.velocityY as number;
68
130
  }
69
- public getLastX(pointerId: number): number {
70
- return this.trackedPointers.get(pointerId)?.lastX as number;
131
+
132
+ /**
133
+ * Returns X coordinate of last moved pointer
134
+ */
135
+ public getLastX(): number;
136
+
137
+ /**
138
+ *
139
+ * @param pointerId
140
+ * Returns X coordinate of given pointer
141
+ */
142
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
143
+ public getLastX(pointerId: number): number;
144
+
145
+ public getLastX(pointerId?: number): number {
146
+ if (pointerId) {
147
+ return this.trackedPointers.get(pointerId)?.lastX as number;
148
+ } else {
149
+ return this.trackedPointers.get(this.lastMovedPointerId)?.lastX as number;
150
+ }
71
151
  }
72
- public getLastY(pointerId: number): number {
73
- return this.trackedPointers.get(pointerId)?.lastY as number;
152
+
153
+ /**
154
+ * Returns Y coordinate of last moved pointer
155
+ */
156
+ public getLastY(): number;
157
+
158
+ /**
159
+ *
160
+ * @param pointerId
161
+ * Returns Y coordinate of given pointer
162
+ */
163
+ // eslint-disable-next-line @typescript-eslint/unified-signatures
164
+ public getLastY(pointerId: number): number;
165
+
166
+ public getLastY(pointerId?: number): number {
167
+ if (pointerId) {
168
+ return this.trackedPointers.get(pointerId)?.lastY as number;
169
+ } else {
170
+ return this.trackedPointers.get(this.lastMovedPointerId)?.lastY as number;
171
+ }
74
172
  }
173
+
174
+ // Some handlers use these methods to send average values in native event.
175
+ // This may happen when pointers have already been removed from tracker (i.e. pointerup event).
176
+ // In situation when NaN would be sent as a response, we return cached value.
177
+ // That prevents handlers from crashing
75
178
  public getLastAvgX(): number {
76
- return this.getSumX() / this.trackedPointers.size;
179
+ const avgX: number = this.getSumX() / this.trackedPointers.size;
180
+ return isNaN(avgX) ? this.cachedAverages.x : avgX;
77
181
  }
78
182
  public getLastAvgY(): number {
79
- return this.getSumY() / this.trackedPointers.size;
183
+ const avgY: number = this.getSumY() / this.trackedPointers.size;
184
+ return isNaN(avgY) ? this.cachedAverages.y : avgY;
80
185
  }
81
186
  public getSumX(ignoredPointer?: number): number {
82
187
  let sumX = 0;
@@ -119,6 +224,11 @@ export default class PointerTracker {
119
224
 
120
225
  public resetTracker(): void {
121
226
  this.trackedPointers.clear();
227
+ this.lastMovedPointerId = NaN;
228
+
229
+ for (let i = 0; i < MAX_POINTERS; ++i) {
230
+ this.touchEventsIds.set(i, NaN);
231
+ }
122
232
  }
123
233
 
124
234
  public static shareCommonPointers(
@@ -0,0 +1,167 @@
1
+ import {
2
+ AdaptedEvent,
3
+ EventTypes,
4
+ MouseButtons,
5
+ PointerType,
6
+ TouchEventType,
7
+ } from '../interfaces';
8
+ import EventManager from './EventManager';
9
+ import { isPointerInBounds } from '../utils';
10
+
11
+ export default class TouchEventManager extends EventManager {
12
+ public setListeners(): void {
13
+ this.view.addEventListener('touchstart', (event: TouchEvent) => {
14
+ for (let i = 0; i < event.changedTouches.length; ++i) {
15
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
16
+ event,
17
+ EventTypes.DOWN,
18
+ i,
19
+ TouchEventType.DOWN
20
+ );
21
+
22
+ // Here we skip stylus, because in case of anything different than touch we want to handle it by using PointerEvents
23
+ // If we leave stylus to send touch events, handlers will receive every action twice
24
+ if (
25
+ !isPointerInBounds(this.view, {
26
+ x: adaptedEvent.x,
27
+ y: adaptedEvent.y,
28
+ }) ||
29
+ //@ts-ignore touchType field does exist
30
+ event.changedTouches[i].touchType === 'stylus'
31
+ ) {
32
+ continue;
33
+ }
34
+
35
+ this.markAsInBounds(adaptedEvent.pointerId);
36
+
37
+ if (++this.activePointersCounter > 1) {
38
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
39
+ this.onPointerAdd(adaptedEvent);
40
+ } else {
41
+ this.onPointerDown(adaptedEvent);
42
+ }
43
+ }
44
+ });
45
+
46
+ this.view.addEventListener('touchmove', (event: TouchEvent) => {
47
+ for (let i = 0; i < event.changedTouches.length; ++i) {
48
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
49
+ event,
50
+ EventTypes.MOVE,
51
+ i,
52
+ TouchEventType.MOVE
53
+ );
54
+ //@ts-ignore touchType field does exist
55
+ if (event.changedTouches[i].touchType === 'stylus') {
56
+ continue;
57
+ }
58
+
59
+ const inBounds: boolean = isPointerInBounds(this.view, {
60
+ x: adaptedEvent.x,
61
+ y: adaptedEvent.y,
62
+ });
63
+
64
+ const pointerIndex: number = this.pointersInBounds.indexOf(
65
+ adaptedEvent.pointerId
66
+ );
67
+
68
+ if (inBounds) {
69
+ if (pointerIndex < 0) {
70
+ adaptedEvent.eventType = EventTypes.ENTER;
71
+ this.onPointerEnter(adaptedEvent);
72
+ this.markAsInBounds(adaptedEvent.pointerId);
73
+ } else {
74
+ this.onPointerMove(adaptedEvent);
75
+ }
76
+ } else {
77
+ if (pointerIndex >= 0) {
78
+ adaptedEvent.eventType = EventTypes.OUT;
79
+ this.onPointerOut(adaptedEvent);
80
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
81
+ } else {
82
+ this.onPointerOutOfBounds(adaptedEvent);
83
+ }
84
+ }
85
+ }
86
+ });
87
+
88
+ this.view.addEventListener('touchend', (event: TouchEvent) => {
89
+ for (let i = 0; i < event.changedTouches.length; ++i) {
90
+ // When we call reset on gesture handlers, it also resets their event managers
91
+ // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
92
+ // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
93
+ // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
94
+ if (this.activePointersCounter === 0) {
95
+ break;
96
+ }
97
+
98
+ //@ts-ignore touchType field does exist
99
+ if (event.changedTouches[i].touchType === 'stylus') {
100
+ continue;
101
+ }
102
+
103
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
104
+ event,
105
+ EventTypes.UP,
106
+ i,
107
+ TouchEventType.UP
108
+ );
109
+
110
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
111
+
112
+ if (--this.activePointersCounter > 0) {
113
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
114
+ this.onPointerRemove(adaptedEvent);
115
+ } else {
116
+ this.onPointerUp(adaptedEvent);
117
+ }
118
+ }
119
+ });
120
+
121
+ this.view.addEventListener('touchcancel', (event: TouchEvent) => {
122
+ for (let i = 0; i < event.changedTouches.length; ++i) {
123
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
124
+ event,
125
+ EventTypes.CANCEL,
126
+ i,
127
+ TouchEventType.CANCELLED
128
+ );
129
+
130
+ //@ts-ignore touchType field does exist
131
+ if (event.changedTouches[i].touchType === 'stylus') {
132
+ continue;
133
+ }
134
+
135
+ this.onPointerCancel(adaptedEvent);
136
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
137
+ this.activePointersCounter = 0;
138
+ }
139
+ });
140
+ }
141
+
142
+ protected mapEvent(
143
+ event: TouchEvent,
144
+ eventType: EventTypes,
145
+ index: number,
146
+ touchEventType: TouchEventType
147
+ ): AdaptedEvent {
148
+ const rect = this.view.getBoundingClientRect();
149
+ const clientX = event.changedTouches[index].clientX;
150
+ const clientY = event.changedTouches[index].clientY;
151
+
152
+ return {
153
+ x: clientX,
154
+ y: clientY,
155
+ offsetX: clientX - rect.left,
156
+ offsetY: clientY - rect.top,
157
+ pointerId: event.changedTouches[index].identifier,
158
+ eventType: eventType,
159
+ pointerType: PointerType.TOUCH,
160
+ buttons: MouseButtons.NONE,
161
+ time: event.timeStamp,
162
+ allTouches: event.touches,
163
+ changedTouches: event.changedTouches,
164
+ touchEventType: touchEventType,
165
+ };
166
+ }
167
+ }
@@ -0,0 +1,8 @@
1
+ export function isPointerInBounds(
2
+ view: HTMLElement,
3
+ { x, y }: { x: number; y: number }
4
+ ): boolean {
5
+ const rect: DOMRect = view.getBoundingClientRect();
6
+
7
+ return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
8
+ }