react-native-gesture-handler 2.6.0 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -30,7 +30,17 @@ export interface Config extends Record<string, ConfigArgs> {
30
30
  simultaneousHandlers?: Handler[] | null;
31
31
  waitFor?: Handler[] | null;
32
32
  hitSlop?: HitSlop;
33
+ shouldCancelWhenOutside?: boolean;
33
34
 
35
+ activateAfterLongPress?: number;
36
+ failOffsetXStart?: number;
37
+ failOffsetYStart?: number;
38
+ failOffsetXEnd?: number;
39
+ failOffsetYEnd?: number;
40
+ activeOffsetXStart?: number;
41
+ activeOffsetXEnd?: number;
42
+ activeOffsetYStart?: number;
43
+ activeOffsetYEnd?: number;
34
44
  minPointers?: number;
35
45
  maxPointers?: number;
36
46
  minDist?: number;
@@ -41,14 +51,6 @@ export interface Config extends Record<string, ConfigArgs> {
41
51
  minVelocitySq?: number;
42
52
  maxDist?: number;
43
53
  maxDistSq?: number;
44
- failOffsetXStart?: number;
45
- failOffsetYStart?: number;
46
- failOffsetXEnd?: number;
47
- failOffsetYEnd?: number;
48
- activeOffsetXStart?: number;
49
- activeOffsetXEnd?: number;
50
- activeOffsetYStart?: number;
51
- activeOffsetYEnd?: number;
52
54
  numberOfPointers?: number;
53
55
  minDurationMs?: number;
54
56
  numberOfTaps?: number;
@@ -56,6 +58,8 @@ export interface Config extends Record<string, ConfigArgs> {
56
58
  maxDelayMs?: number;
57
59
  maxDeltaX?: number;
58
60
  maxDeltaY?: number;
61
+ shouldActivateOnStart?: boolean;
62
+ disallowInterruption?: boolean;
59
63
  direction?: Directions;
60
64
  }
61
65
 
@@ -69,26 +73,54 @@ interface NativeEvent extends Record<string, NativeEventArgs> {
69
73
  oldState?: State;
70
74
  }
71
75
 
76
+ export interface PointerData {
77
+ id: number;
78
+ x: number;
79
+ y: number;
80
+ absoluteX: number;
81
+ absoluteY: number;
82
+ }
83
+
84
+ type TouchNativeArgs = number | State | TouchEventType | PointerData[];
85
+
86
+ interface NativeTouchEvent extends Record<string, TouchNativeArgs> {
87
+ handlerTag: number;
88
+ state: State;
89
+ eventType: TouchEventType;
90
+ changedTouches: PointerData[];
91
+ allTouches: PointerData[];
92
+ numberOfTouches: number;
93
+ }
94
+
72
95
  export interface ResultEvent extends Record<string, NativeEvent | number> {
73
96
  nativeEvent: NativeEvent;
74
97
  timeStamp: number;
75
98
  }
76
99
 
100
+ export interface ResultTouchEvent
101
+ extends Record<string, NativeTouchEvent | number> {
102
+ nativeEvent: NativeTouchEvent;
103
+ timeStamp: number;
104
+ }
105
+
77
106
  export interface PropsRef {
78
107
  onGestureHandlerEvent: () => void;
79
108
  onGestureHandlerStateChange: () => void;
80
109
  }
81
110
 
82
- export interface AdaptedPointerEvent {
111
+ export interface AdaptedEvent {
83
112
  x: number;
84
113
  y: number;
85
114
  offsetX: number;
86
115
  offsetY: number;
87
116
  pointerId: number;
88
117
  eventType: EventTypes;
89
- pointerType: string;
118
+ pointerType: PointerType;
90
119
  buttons: number;
91
120
  time: number;
121
+ allTouches?: TouchList;
122
+ changedTouches?: TouchList;
123
+ touchEventType?: TouchEventType;
92
124
  }
93
125
 
94
126
  export enum MouseButtons {
@@ -112,3 +144,18 @@ export enum EventTypes {
112
144
  OUT,
113
145
  CANCEL,
114
146
  }
147
+
148
+ export enum TouchEventType {
149
+ UNDETERMINED,
150
+ DOWN,
151
+ MOVE,
152
+ UP,
153
+ CANCELLED,
154
+ }
155
+
156
+ export enum PointerType {
157
+ NONE = 'none',
158
+ MOUSE = 'mouse',
159
+ TOUCH = 'touch',
160
+ PEN = 'pen',
161
+ }
@@ -1,186 +1,96 @@
1
1
  /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import { AdaptedEvent, EventTypes, TouchEventType } from '../interfaces';
2
3
 
3
- import { EventTypes, AdaptedPointerEvent, MouseButtons } from '../interfaces';
4
-
5
- export default class EventManager {
6
- private activePointers: number[] = [];
7
- private readonly view: HTMLElement;
4
+ export default abstract class EventManager {
5
+ protected readonly view: HTMLElement;
6
+ protected pointersInBounds: number[] = [];
7
+ protected activePointersCounter: number;
8
8
 
9
9
  constructor(view: HTMLElement) {
10
10
  this.view = view;
11
+ this.activePointersCounter = 0;
11
12
  }
12
13
 
13
- public setListeners() {
14
- this.view.addEventListener('pointerdown', (event: PointerEvent): void => {
15
- if (
16
- !this.isPointerInBounds({
17
- x: event.clientX,
18
- y: event.clientY,
19
- })
20
- ) {
21
- return;
22
- }
23
-
24
- const adaptedEvent: AdaptedPointerEvent = this.mapEvent(
25
- event,
26
- EventTypes.DOWN
27
- );
28
- const target = event.target as HTMLElement;
29
-
30
- target.setPointerCapture(adaptedEvent.pointerId);
31
- this.addActivePointer(adaptedEvent.pointerId);
32
- this.onPointerDown(adaptedEvent);
33
- });
34
-
35
- this.view.addEventListener('pointerup', (event: PointerEvent): void => {
36
- const adaptedEvent: AdaptedPointerEvent = this.mapEvent(
37
- event,
38
- EventTypes.UP
39
- );
40
- const target = event.target as HTMLElement;
41
-
42
- this.onPointerUp(adaptedEvent);
43
- target.releasePointerCapture(adaptedEvent.pointerId);
44
- this.removeActivePointer(adaptedEvent.pointerId);
45
- });
46
-
47
- this.view.addEventListener('pointermove', (event: PointerEvent): void => {
48
- if (
49
- event.pointerType === 'mouse' &&
50
- event.buttons !== MouseButtons.LEFT
51
- ) {
52
- return;
53
- }
54
-
55
- const adaptedEvent: AdaptedPointerEvent = this.mapEvent(
56
- event,
57
- EventTypes.MOVE
58
- );
59
-
60
- const inBounds: boolean = this.isPointerInBounds({
61
- x: adaptedEvent.x,
62
- y: adaptedEvent.y,
63
- });
64
-
65
- const pointerIndex: number = this.activePointers.indexOf(
66
- adaptedEvent.pointerId
67
- );
68
-
69
- if (inBounds) {
70
- if (pointerIndex < 0) {
71
- adaptedEvent.eventType = EventTypes.ENTER;
72
- this.onPointerEnter(adaptedEvent);
73
- this.addActivePointer(adaptedEvent.pointerId);
74
- } else {
75
- this.onPointerMove(adaptedEvent);
76
- }
77
- } else {
78
- if (pointerIndex >= 0) {
79
- adaptedEvent.eventType = EventTypes.OUT;
80
- this.onPointerOut(adaptedEvent);
81
- this.removeActivePointer(adaptedEvent.pointerId);
82
- } else {
83
- this.onPointerOutOfBounds(adaptedEvent);
84
- }
85
- }
86
- });
87
-
88
- this.view.addEventListener('pointercancel', (event: PointerEvent): void => {
89
- event.preventDefault();
90
-
91
- const adaptedEvent: AdaptedPointerEvent = this.mapEvent(
92
- event,
93
- EventTypes.CANCEL
94
- );
95
-
96
- this.onPointerCancel(adaptedEvent);
97
- });
14
+ public abstract setListeners(): void;
15
+ protected abstract mapEvent(
16
+ event: Event,
17
+ eventType: EventTypes,
18
+ index?: number,
19
+ touchEventType?: TouchEventType
20
+ ): AdaptedEvent;
21
+
22
+ protected onPointerDown(_event: AdaptedEvent): void {}
23
+ protected onPointerAdd(_event: AdaptedEvent): void {}
24
+ protected onPointerUp(_event: AdaptedEvent): void {}
25
+ protected onPointerRemove(_event: AdaptedEvent): void {}
26
+ protected onPointerMove(_event: AdaptedEvent): void {}
27
+ protected onPointerOut(_event: AdaptedEvent): void {}
28
+ protected onPointerEnter(_event: AdaptedEvent): void {}
29
+ protected onPointerCancel(_event: AdaptedEvent): void {
30
+ // When pointer cancel is triggered and there are more pointers on the view, only one pointer is cancelled
31
+ // Because we want all pointers to be cancelled by that event, we are doing it manually by reseting handler and changing activePointersCounter to 0
32
+ // Events that correspond to removing the pointer (pointerup, touchend) have condition, that they don't perform any action when activePointersCounter
33
+ // is equal to 0. This prevents counter from going to negative values, when pointers are removed from view after one of them has been cancelled
98
34
  }
35
+ protected onPointerOutOfBounds(_event: AdaptedEvent): void {}
99
36
 
100
- private onPointerDown(_event: AdaptedPointerEvent): void {}
101
- private onPointerUp(_event: AdaptedPointerEvent): void {}
102
- private onPointerMove(_event: AdaptedPointerEvent): void {}
103
- private onPointerOut(_event: AdaptedPointerEvent): void {}
104
- private onPointerEnter(_event: AdaptedPointerEvent): void {}
105
- private onPointerCancel(_event: AdaptedPointerEvent): void {}
106
- private onPointerOutOfBounds(_event: AdaptedPointerEvent): void {}
107
-
108
- public setOnPointerDown(
109
- callback: (event: AdaptedPointerEvent) => void
110
- ): void {
37
+ public setOnPointerDown(callback: (event: AdaptedEvent) => void): void {
111
38
  this.onPointerDown = callback;
112
39
  }
113
- public setOnPointerUp(callback: (event: AdaptedPointerEvent) => void): void {
40
+ public setOnPointerAdd(callback: (event: AdaptedEvent) => void): void {
41
+ this.onPointerAdd = callback;
42
+ }
43
+ public setOnPointerUp(callback: (event: AdaptedEvent) => void): void {
114
44
  this.onPointerUp = callback;
115
45
  }
116
- public setOnPointerMove(
117
- callback: (event: AdaptedPointerEvent) => void
118
- ): void {
46
+ public setOnPointerRemove(callback: (event: AdaptedEvent) => void): void {
47
+ this.onPointerRemove = callback;
48
+ }
49
+ public setOnPointerMove(callback: (event: AdaptedEvent) => void): void {
119
50
  this.onPointerMove = callback;
120
51
  }
121
- public setOnPointerOut(callback: (event: AdaptedPointerEvent) => void): void {
52
+ public setOnPointerOut(callback: (event: AdaptedEvent) => void): void {
122
53
  this.onPointerOut = callback;
123
54
  }
124
- public setOnPointerEnter(
125
- callback: (event: AdaptedPointerEvent) => void
126
- ): void {
55
+ public setOnPointerEnter(callback: (event: AdaptedEvent) => void): void {
127
56
  this.onPointerEnter = callback;
128
57
  }
129
- public setOnPointerCancel(
130
- callback: (event: AdaptedPointerEvent) => void
131
- ): void {
58
+ public setOnPointerCancel(callback: (event: AdaptedEvent) => void): void {
132
59
  this.onPointerCancel = callback;
133
60
  }
134
61
  public setOnPointerOutOfBounds(
135
- callback: (event: AdaptedPointerEvent) => void
62
+ callback: (event: AdaptedEvent) => void
136
63
  ): void {
137
64
  this.onPointerOutOfBounds = callback;
138
65
  }
139
66
 
140
- private mapEvent(
141
- event: PointerEvent,
142
- eventType: EventTypes
143
- ): AdaptedPointerEvent {
144
- return {
145
- x: event.clientX,
146
- y: event.clientY,
147
- offsetX: event.offsetX,
148
- offsetY: event.offsetY,
149
- pointerId: event.pointerId,
150
- eventType: eventType,
151
- pointerType: event.pointerType,
152
- buttons: event.buttons,
153
- time: event.timeStamp,
154
- };
155
- }
156
-
157
- public isPointerInBounds({ x, y }: { x: number; y: number }): boolean {
158
- if (!this.view) {
159
- return false;
160
- }
161
-
162
- const rect: DOMRect = this.view.getBoundingClientRect();
163
-
164
- return (
165
- x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
166
- );
167
- }
168
-
169
- private addActivePointer(pointerId: number): void {
170
- if (this.activePointers.indexOf(pointerId) >= 0) {
67
+ protected markAsInBounds(pointerId: number): void {
68
+ if (this.pointersInBounds.indexOf(pointerId) >= 0) {
171
69
  return;
172
70
  }
173
71
 
174
- this.activePointers.push(pointerId);
72
+ this.pointersInBounds.push(pointerId);
175
73
  }
176
74
 
177
- private removeActivePointer(pointerId: number): void {
178
- const index: number = this.activePointers.indexOf(pointerId);
75
+ protected markAsOutOfBounds(pointerId: number): void {
76
+ const index: number = this.pointersInBounds.indexOf(pointerId);
179
77
 
180
78
  if (index < 0) {
181
79
  return;
182
80
  }
183
81
 
184
- this.activePointers.splice(index, 1);
82
+ this.pointersInBounds.splice(index, 1);
83
+ }
84
+
85
+ public resetManager(): void {
86
+ // Reseting activePointersCounter is necessary to make gestures such as pinch work properly
87
+ // There are gestures that end when there is still one active pointer (like pinch/rotation)
88
+ // When these gestures end, they are reset, but they still receive events from pointer that is active
89
+ // This causes trouble, since only onPointerDown registers gesture in orchestrator, and while gestures receive
90
+ // Events from active pointer after they finished, next pointerdown event will be registered as additional pointer, not the first one
91
+ // This casues trouble like gestures getting stuck in END state, even though they should have gone to UNDETERMINED
92
+
93
+ this.activePointersCounter = 0;
94
+ this.pointersInBounds = [];
185
95
  }
186
96
  }
@@ -1,8 +1,9 @@
1
1
  import { State } from '../../State';
2
- import { AdaptedPointerEvent } from '../interfaces';
2
+ import { PointerType } from '../interfaces';
3
3
 
4
4
  import GestureHandler from '../handlers/GestureHandler';
5
5
  import PointerTracker from './PointerTracker';
6
+ import { isPointerInBounds } from '../utils';
6
7
 
7
8
  export default class GestureHandlerOrchestrator {
8
9
  private static instance: GestureHandlerOrchestrator;
@@ -31,13 +32,19 @@ export default class GestureHandlerOrchestrator {
31
32
  handler.setActivationIndex(Number.MAX_VALUE);
32
33
  }
33
34
 
35
+ public removeHandlerFromOrchestrator(handler: GestureHandler): void {
36
+ this.gestureHandlers.splice(this.gestureHandlers.indexOf(handler), 1);
37
+ this.awaitingHandlers.splice(this.awaitingHandlers.indexOf(handler), 1);
38
+ this.handlersToCancel.splice(this.handlersToCancel.indexOf(handler), 1);
39
+ }
40
+
34
41
  private cleanupFinishedHandlers(): void {
35
42
  for (let i = this.gestureHandlers.length - 1; i >= 0; --i) {
36
43
  const handler = this.gestureHandlers[i];
44
+
37
45
  if (!handler) {
38
46
  continue;
39
47
  }
40
-
41
48
  if (this.isFinished(handler.getState()) && !handler.isAwaiting()) {
42
49
  this.gestureHandlers.splice(i, 1);
43
50
 
@@ -62,15 +69,35 @@ export default class GestureHandlerOrchestrator {
62
69
  return hasToWait;
63
70
  }
64
71
 
65
- private tryActivate(
66
- handler: GestureHandler,
67
- event: AdaptedPointerEvent
68
- ): void {
72
+ private tryActivate(handler: GestureHandler): void {
69
73
  if (this.hasOtherHandlerToWaitFor(handler)) {
70
74
  this.addAwaitingHandler(handler);
71
- } else {
72
- this.makeActive(handler, event);
75
+ } else if (
76
+ handler.getState() !== State.CANCELLED &&
77
+ handler.getState() !== State.FAILED
78
+ ) {
79
+ if (this.shouldActivate(handler)) {
80
+ this.makeActive(handler);
81
+ } else {
82
+ switch (handler.getState()) {
83
+ case State.ACTIVE:
84
+ handler.fail();
85
+ break;
86
+ case State.BEGAN:
87
+ handler.cancel();
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ private shouldActivate(handler: GestureHandler): boolean {
94
+ for (const otherHandler of this.gestureHandlers) {
95
+ if (this.shouldHandlerBeCancelledBy(handler, otherHandler)) {
96
+ return false;
97
+ }
73
98
  }
99
+
100
+ return true;
74
101
  }
75
102
 
76
103
  private cleanupAwaitingHandlers(handler: GestureHandler): void {
@@ -89,36 +116,50 @@ export default class GestureHandlerOrchestrator {
89
116
  handler: GestureHandler,
90
117
  newState: State,
91
118
  oldState: State,
92
- event: AdaptedPointerEvent
119
+ sendIfDisabled?: boolean
93
120
  ): void {
121
+ if (!handler.isEnabled() && !sendIfDisabled) {
122
+ return;
123
+ }
124
+
94
125
  this.handlingChangeSemaphore += 1;
95
126
 
96
127
  if (this.isFinished(newState)) {
97
128
  this.awaitingHandlers.forEach((otherHandler) => {
98
129
  if (this.shouldHandlerWaitForOther(otherHandler, handler)) {
99
130
  if (newState === State.END) {
100
- otherHandler?.cancel(event);
131
+ otherHandler?.cancel();
132
+ if (otherHandler.getState() === State.END) {
133
+ // Handle edge case, where discrete gestures end immediately after activation thus
134
+ // their state is set to END and when the gesture they are waiting for activates they
135
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
136
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
137
+ otherHandler.sendEvent(State.CANCELLED, State.BEGAN);
138
+ }
101
139
  otherHandler?.setAwaiting(false);
102
140
  } else {
103
- this.tryActivate(otherHandler, event);
141
+ this.tryActivate(otherHandler);
104
142
  }
105
143
  }
106
144
  });
107
145
  }
108
146
 
109
147
  if (newState === State.ACTIVE) {
110
- this.tryActivate(handler, event);
148
+ this.tryActivate(handler);
111
149
  } else if (oldState === State.ACTIVE || oldState === State.END) {
112
150
  if (handler.isActive()) {
113
- handler.sendEvent(event, newState, oldState);
114
- } else if (oldState === State.ACTIVE) {
115
- handler.sendEvent(event, newState, State.BEGAN);
151
+ handler.sendEvent(newState, oldState);
152
+ } else if (
153
+ oldState === State.ACTIVE &&
154
+ (newState === State.CANCELLED || newState === State.FAILED)
155
+ ) {
156
+ handler.sendEvent(newState, State.BEGAN);
116
157
  }
117
158
  } else if (
118
159
  oldState !== State.UNDETERMINED ||
119
160
  newState !== State.CANCELLED
120
161
  ) {
121
- handler.sendEvent(event, newState, oldState);
162
+ handler.sendEvent(newState, oldState);
122
163
  }
123
164
 
124
165
  this.handlingChangeSemaphore -= 1;
@@ -130,10 +171,7 @@ export default class GestureHandlerOrchestrator {
130
171
  }
131
172
  }
132
173
 
133
- private makeActive(
134
- handler: GestureHandler,
135
- event: AdaptedPointerEvent
136
- ): void {
174
+ private makeActive(handler: GestureHandler): void {
137
175
  const currentState = handler.getState();
138
176
 
139
177
  handler.setActive(true);
@@ -142,33 +180,38 @@ export default class GestureHandlerOrchestrator {
142
180
 
143
181
  this.gestureHandlers.forEach((otherHandler) => {
144
182
  // Order of arguments is correct - we check whether current handler should cancel existing handlers
183
+
145
184
  if (this.shouldHandlerBeCancelledBy(otherHandler, handler)) {
146
185
  this.handlersToCancel.push(otherHandler);
147
186
  }
148
187
  });
149
188
 
150
189
  for (let i = this.handlersToCancel.length - 1; i >= 0; --i) {
151
- this.handlersToCancel[i]?.cancel(event);
190
+ this.handlersToCancel[i]?.cancel();
152
191
  }
153
192
  this.awaitingHandlers.forEach((otherHandler) => {
154
193
  if (this.shouldHandlerBeCancelledBy(otherHandler, handler)) {
155
- otherHandler?.cancel(event);
194
+ otherHandler?.cancel();
156
195
  otherHandler?.setAwaiting(true);
157
196
  }
158
197
  });
159
198
 
160
- handler.sendEvent(event, State.ACTIVE, State.BEGAN);
199
+ handler.sendEvent(State.ACTIVE, State.BEGAN);
161
200
 
162
201
  if (currentState !== State.ACTIVE) {
163
- handler.sendEvent(event, State.END, State.ACTIVE);
202
+ handler.sendEvent(State.END, State.ACTIVE);
164
203
  if (currentState !== State.END) {
165
- handler.sendEvent(event, State.UNDETERMINED, State.END);
204
+ handler.sendEvent(State.UNDETERMINED, State.END);
166
205
  }
167
206
  }
168
207
 
169
208
  if (handler.isAwaiting()) {
170
209
  handler.setAwaiting(false);
171
- handler.end(event);
210
+ for (let i = 0; i < this.awaitingHandlers.length; ++i) {
211
+ if (this.awaitingHandlers[i] === handler) {
212
+ this.awaitingHandlers.splice(i, 1);
213
+ }
214
+ }
172
215
  }
173
216
 
174
217
  this.handlersToCancel = [];
@@ -241,16 +284,6 @@ export default class GestureHandlerOrchestrator {
241
284
  handler: GestureHandler,
242
285
  otherHandler: GestureHandler
243
286
  ): boolean {
244
- const handlerPointers: number[] = handler.getTrackedPointersID();
245
- const otherPointers: number[] = otherHandler.getTrackedPointersID();
246
-
247
- if (
248
- !PointerTracker.shareCommonPointers(handlerPointers, otherPointers) &&
249
- handler.getView() !== otherHandler.getView()
250
- ) {
251
- return this.checkOverlap(handler, otherHandler);
252
- }
253
-
254
287
  if (this.canRunSimultaneously(handler, otherHandler)) {
255
288
  return false;
256
289
  }
@@ -263,6 +296,16 @@ export default class GestureHandlerOrchestrator {
263
296
  return handler.shouldBeCancelledByOther(otherHandler);
264
297
  }
265
298
 
299
+ const handlerPointers: number[] = handler.getTrackedPointersID();
300
+ const otherPointers: number[] = otherHandler.getTrackedPointersID();
301
+
302
+ if (
303
+ !PointerTracker.shareCommonPointers(handlerPointers, otherPointers) &&
304
+ handler.getView() !== otherHandler.getView()
305
+ ) {
306
+ return this.checkOverlap(handler, otherHandler);
307
+ }
308
+
266
309
  return true;
267
310
  }
268
311
 
@@ -286,12 +329,8 @@ export default class GestureHandlerOrchestrator {
286
329
  const handlerY: number = handler.getTracker().getLastY(pointer);
287
330
 
288
331
  if (
289
- handler
290
- .getEventManager()
291
- .isPointerInBounds({ x: handlerX, y: handlerY }) &&
292
- otherHandler
293
- .getEventManager()
294
- .isPointerInBounds({ x: handlerX, y: handlerY })
332
+ isPointerInBounds(handler.getView(), { x: handlerX, y: handlerY }) &&
333
+ isPointerInBounds(otherHandler.getView(), { x: handlerX, y: handlerY })
295
334
  ) {
296
335
  overlap = true;
297
336
  }
@@ -302,10 +341,8 @@ export default class GestureHandlerOrchestrator {
302
341
  const otherY: number = otherHandler.getTracker().getLastY(pointer);
303
342
 
304
343
  if (
305
- handler.getEventManager().isPointerInBounds({ x: otherX, y: otherY }) &&
306
- otherHandler
307
- .getEventManager()
308
- .isPointerInBounds({ x: otherX, y: otherY })
344
+ isPointerInBounds(handler.getView(), { x: otherX, y: otherY }) &&
345
+ isPointerInBounds(otherHandler.getView(), { x: otherX, y: otherY })
309
346
  ) {
310
347
  overlap = true;
311
348
  }
@@ -320,9 +357,40 @@ export default class GestureHandlerOrchestrator {
320
357
  );
321
358
  }
322
359
 
360
+ // This function is called when handler receives touchdown event
361
+ // If handler is using mouse or pen as a pointer and any handler receives touch event,
362
+ // mouse/pen event dissappears - it doesn't send onPointerCancel nor onPointerUp (and others)
363
+ // This became a problem because handler was left at active state without any signal to end or fail
364
+ // To handle this, when new touch event is received, we loop through active handlers and check which type of
365
+ // pointer they're using. If there are any handler with mouse/pen as a pointer, we cancel them
366
+ public cancelMouseAndPenGestures(currentHandler: GestureHandler): void {
367
+ this.gestureHandlers.forEach((handler: GestureHandler) => {
368
+ if (
369
+ handler.getPointerType() !== PointerType.MOUSE &&
370
+ handler.getPointerType() !== PointerType.PEN
371
+ ) {
372
+ return;
373
+ }
374
+
375
+ if (handler !== currentHandler) {
376
+ handler.cancel();
377
+ } else {
378
+ // Handler that received touch event should have its pointer tracker reset
379
+ // This allows handler to smoothly change from mouse/pen to touch
380
+ // The drawback is, that when we try to use mouse/pen one more time, it doesn't send onPointerDown at the first time
381
+ // so it is required to click two times to get handler to work
382
+ //
383
+ // However, handler will receive manually created onPointerEnter that is triggered in EventManager in onPointerMove method.
384
+ // There may be possibility to use that fact to make handler respond properly to first mouse click
385
+ handler.getTracker().resetTracker();
386
+ }
387
+ });
388
+ }
389
+
323
390
  public static getInstance(): GestureHandlerOrchestrator {
324
- if (!GestureHandlerOrchestrator.instance)
391
+ if (!GestureHandlerOrchestrator.instance) {
325
392
  GestureHandlerOrchestrator.instance = new GestureHandlerOrchestrator();
393
+ }
326
394
 
327
395
  return GestureHandlerOrchestrator.instance;
328
396
  }