react-native-gesture-handler 2.18.0 → 2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. package/README.md +1 -0
  2. package/android/build.gradle +4 -17
  3. package/android/src/main/AndroidManifest.xml +1 -3
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +21 -21
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +2 -2
  6. package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +5 -0
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +80 -4
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/PinchGestureHandler.kt +2 -1
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/ScaleGestureDetector.java +10 -0
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +2 -2
  11. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +3 -0
  12. package/android/src/main/jni/cpp-adapter.cpp +2 -4
  13. package/apple/Handlers/RNFlingHandler.h +1 -0
  14. package/apple/Handlers/RNFlingHandler.m +153 -19
  15. package/apple/Handlers/RNHoverHandler.m +44 -2
  16. package/apple/Handlers/RNLongPressHandler.m +109 -20
  17. package/apple/Handlers/RNManualHandler.m +53 -29
  18. package/apple/Handlers/RNNativeViewHandler.mm +22 -15
  19. package/apple/RNGHUIKit.h +2 -0
  20. package/apple/RNGHVector.h +31 -0
  21. package/apple/RNGHVector.m +67 -0
  22. package/apple/RNGestureHandler.h +7 -0
  23. package/apple/{RNGestureHandler.m → RNGestureHandler.mm} +63 -1
  24. package/apple/RNGestureHandlerButtonComponentView.mm +6 -0
  25. package/apple/RNGestureHandlerDirection.h +25 -0
  26. package/apple/RNGestureHandlerModule.mm +2 -4
  27. package/lib/commonjs/PointerType.js +2 -1
  28. package/lib/commonjs/PointerType.js.map +1 -1
  29. package/lib/commonjs/components/Pressable/Pressable.js +67 -70
  30. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  31. package/lib/commonjs/components/Pressable/index.js +0 -8
  32. package/lib/commonjs/components/Pressable/index.js.map +1 -1
  33. package/lib/commonjs/components/ReanimatedSwipeable.js +60 -41
  34. package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
  35. package/lib/commonjs/components/Swipeable.js +5 -0
  36. package/lib/commonjs/components/Swipeable.js.map +1 -1
  37. package/lib/commonjs/handlers/LongPressGestureHandler.js +1 -1
  38. package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
  39. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +1 -1
  40. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -1
  41. package/lib/commonjs/handlers/gestures/longPressGesture.js +10 -0
  42. package/lib/commonjs/handlers/gestures/longPressGesture.js.map +1 -1
  43. package/lib/commonjs/mocks.js +16 -3
  44. package/lib/commonjs/mocks.js.map +1 -1
  45. package/lib/commonjs/utils.js +4 -0
  46. package/lib/commonjs/utils.js.map +1 -1
  47. package/lib/commonjs/web/constants.js +3 -3
  48. package/lib/commonjs/web/constants.js.map +1 -1
  49. package/lib/commonjs/web/handlers/GestureHandler.js +1 -0
  50. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  51. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +43 -9
  52. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  53. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +14 -3
  54. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  55. package/lib/commonjs/web/handlers/PanGestureHandler.js +4 -0
  56. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  57. package/lib/commonjs/web/interfaces.js.map +1 -1
  58. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +55 -8
  59. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  60. package/lib/commonjs/web/tools/KeyboardEventManager.js +110 -0
  61. package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -0
  62. package/lib/commonjs/web/tools/Vector.js +4 -2
  63. package/lib/commonjs/web/tools/Vector.js.map +1 -1
  64. package/lib/commonjs/web/utils.js +14 -13
  65. package/lib/commonjs/web/utils.js.map +1 -1
  66. package/lib/module/PointerType.js +2 -1
  67. package/lib/module/PointerType.js.map +1 -1
  68. package/lib/module/components/Pressable/Pressable.js +66 -70
  69. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  70. package/lib/module/components/Pressable/index.js +0 -1
  71. package/lib/module/components/Pressable/index.js.map +1 -1
  72. package/lib/module/components/ReanimatedSwipeable.js +58 -37
  73. package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
  74. package/lib/module/components/Swipeable.js +6 -0
  75. package/lib/module/components/Swipeable.js.map +1 -1
  76. package/lib/module/handlers/LongPressGestureHandler.js +1 -1
  77. package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
  78. package/lib/module/handlers/gestures/GestureDetector/utils.js +2 -2
  79. package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
  80. package/lib/module/handlers/gestures/longPressGesture.js +10 -0
  81. package/lib/module/handlers/gestures/longPressGesture.js.map +1 -1
  82. package/lib/module/mocks.js +13 -3
  83. package/lib/module/mocks.js.map +1 -1
  84. package/lib/module/utils.js +1 -0
  85. package/lib/module/utils.js.map +1 -1
  86. package/lib/module/web/constants.js +1 -1
  87. package/lib/module/web/constants.js.map +1 -1
  88. package/lib/module/web/handlers/GestureHandler.js +1 -0
  89. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  90. package/lib/module/web/handlers/LongPressGestureHandler.js +43 -9
  91. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  92. package/lib/module/web/handlers/NativeViewGestureHandler.js +14 -3
  93. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  94. package/lib/module/web/handlers/PanGestureHandler.js +4 -0
  95. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  96. package/lib/module/web/interfaces.js.map +1 -1
  97. package/lib/module/web/tools/GestureHandlerWebDelegate.js +54 -8
  98. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  99. package/lib/module/web/tools/KeyboardEventManager.js +96 -0
  100. package/lib/module/web/tools/KeyboardEventManager.js.map +1 -0
  101. package/lib/module/web/tools/Vector.js +5 -3
  102. package/lib/module/web/tools/Vector.js.map +1 -1
  103. package/lib/module/web/utils.js +14 -13
  104. package/lib/module/web/utils.js.map +1 -1
  105. package/lib/typescript/PointerType.d.ts +2 -1
  106. package/lib/typescript/components/Pressable/index.d.ts +1 -1
  107. package/lib/typescript/components/Swipeable.d.ts +5 -0
  108. package/lib/typescript/handlers/LongPressGestureHandler.d.ts +5 -1
  109. package/lib/typescript/handlers/gestures/longPressGesture.d.ts +5 -0
  110. package/lib/typescript/mocks.d.ts +4 -3
  111. package/lib/typescript/utils.d.ts +1 -0
  112. package/lib/typescript/web/constants.d.ts +1 -1
  113. package/lib/typescript/web/handlers/GestureHandler.d.ts +1 -1
  114. package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +3 -0
  115. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  116. package/lib/typescript/web/interfaces.d.ts +1 -1
  117. package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +1 -0
  118. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +6 -0
  119. package/lib/typescript/web/tools/KeyboardEventManager.d.ts +13 -0
  120. package/package.json +3 -3
  121. package/src/PointerType.ts +1 -0
  122. package/src/components/Pressable/Pressable.tsx +70 -50
  123. package/src/components/Pressable/index.ts +1 -1
  124. package/src/components/ReanimatedSwipeable.tsx +70 -47
  125. package/src/components/Swipeable.tsx +6 -0
  126. package/src/handlers/LongPressGestureHandler.ts +6 -0
  127. package/src/handlers/gestures/GestureDetector/utils.ts +2 -2
  128. package/src/handlers/gestures/longPressGesture.ts +9 -0
  129. package/src/{mocks.ts → mocks.tsx} +8 -3
  130. package/src/utils.ts +2 -0
  131. package/src/web/constants.ts +1 -1
  132. package/src/web/handlers/GestureHandler.ts +3 -1
  133. package/src/web/handlers/LongPressGestureHandler.ts +49 -10
  134. package/src/web/handlers/NativeViewGestureHandler.ts +14 -4
  135. package/src/web/handlers/PanGestureHandler.ts +4 -0
  136. package/src/web/interfaces.ts +1 -1
  137. package/src/web/tools/GestureHandlerDelegate.ts +1 -0
  138. package/src/web/tools/GestureHandlerWebDelegate.ts +67 -8
  139. package/src/web/tools/KeyboardEventManager.ts +91 -0
  140. package/src/web/tools/Vector.ts +4 -3
  141. package/src/web/utils.ts +15 -13
@@ -1,6 +1,6 @@
1
1
  import { Platform } from 'react-native';
2
2
 
3
- import { tagMessage } from '../../../utils';
3
+ import { isJestEnv, tagMessage } from '../../../utils';
4
4
  import { GestureRef, BaseGesture, GestureType } from '../gesture';
5
5
 
6
6
  import { flingGestureHandlerProps } from '../../FlingGestureHandler';
@@ -100,7 +100,7 @@ export function checkGestureCallbacksForWorklets(gesture: GestureType) {
100
100
  const areAllNotWorklets = !areSomeWorklets && areSomeNotWorklets;
101
101
  // If none of the callbacks are worklets and the gesture is not explicitly marked with
102
102
  // `.runOnJS(true)` show a warning
103
- if (areAllNotWorklets) {
103
+ if (areAllNotWorklets && !isJestEnv()) {
104
104
  console.warn(
105
105
  tagMessage(
106
106
  `None of the callbacks in the gesture are worklets. If you wish to run them on the JS thread use '.runOnJS(true)' modifier on the gesture to make this explicit. Otherwise, mark the callbacks as 'worklet' to run them on the UI thread.`
@@ -31,6 +31,15 @@ export class LongPressGesture extends BaseGesture<LongPressGestureHandlerEventPa
31
31
  this.config.maxDist = distance;
32
32
  return this;
33
33
  }
34
+
35
+ /**
36
+ * Determine exact number of points required to handle the long press gesture.
37
+ * @param pointers
38
+ */
39
+ numberOfPointers(pointers: number) {
40
+ this.config.numberOfPointers = pointers;
41
+ return this;
42
+ }
34
43
  }
35
44
 
36
45
  export type LongPressGestureType = InstanceType<typeof LongPressGesture>;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import {
2
3
  TouchableHighlight,
3
4
  TouchableNativeFeedback,
@@ -30,9 +31,13 @@ const LongPressGestureHandler = View;
30
31
  const PinchGestureHandler = View;
31
32
  const RotationGestureHandler = View;
32
33
  const FlingGestureHandler = View;
33
- const RawButton = TouchableNativeFeedback;
34
- const BaseButton = TouchableNativeFeedback;
35
- const RectButton = TouchableNativeFeedback;
34
+ const RawButton = ({ enabled, ...rest }: any) => (
35
+ <TouchableNativeFeedback disabled={!enabled} {...rest}>
36
+ <View />
37
+ </TouchableNativeFeedback>
38
+ );
39
+ const BaseButton = RawButton;
40
+ const RectButton = RawButton;
36
41
  const BorderlessButton = TouchableNativeFeedback;
37
42
 
38
43
  export default {
package/src/utils.ts CHANGED
@@ -98,3 +98,5 @@ export function deepEqual(obj1: any, obj2: any) {
98
98
 
99
99
  return true;
100
100
  }
101
+
102
+ export const INT32_MAX = 2 ** 31 - 1;
@@ -1,2 +1,2 @@
1
1
  export const DEFAULT_TOUCH_SLOP = 15;
2
- export const MINIMAL_FLING_VELOCITY = 0.1;
2
+ export const MINIMAL_RECOGNIZABLE_MAGNITUDE = 0.1;
@@ -14,10 +14,10 @@ import EventManager from '../tools/EventManager';
14
14
  import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator';
15
15
  import InteractionManager from '../tools/InteractionManager';
16
16
  import PointerTracker, { TrackerElement } from '../tools/PointerTracker';
17
- import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
18
17
  import IGestureHandler from './IGestureHandler';
19
18
  import { MouseButton } from '../../handlers/gestureHandlerCommon';
20
19
  import { PointerType } from '../../PointerType';
20
+ import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
21
21
 
22
22
  export default abstract class GestureHandler implements IGestureHandler {
23
23
  private lastSentState: State | null = null;
@@ -589,6 +589,8 @@ export default abstract class GestureHandler implements IGestureHandler {
589
589
  this.config = { enabled: enabled, ...props };
590
590
  this.enabled = enabled;
591
591
 
592
+ this.delegate.onEnabledChange(enabled);
593
+
592
594
  if (this.config.shouldCancelWhenOutside !== undefined) {
593
595
  this.setShouldCancelWhenOutside(this.config.shouldCancelWhenOutside);
594
596
  }
@@ -12,6 +12,7 @@ export default class LongPressGestureHandler extends GestureHandler {
12
12
  private defaultMaxDistSq = DEFAULT_MAX_DIST_DP * SCALING_FACTOR;
13
13
 
14
14
  private maxDistSq = this.defaultMaxDistSq;
15
+ private numberOfPointers = 1;
15
16
  private startX = 0;
16
17
  private startY = 0;
17
18
 
@@ -45,6 +46,10 @@ export default class LongPressGestureHandler extends GestureHandler {
45
46
  if (this.config.maxDist !== undefined) {
46
47
  this.maxDistSq = this.config.maxDist * this.config.maxDist;
47
48
  }
49
+
50
+ if (this.config.numberOfPointers !== undefined) {
51
+ this.numberOfPointers = this.config.numberOfPointers;
52
+ }
48
53
  }
49
54
 
50
55
  protected resetConfig(): void {
@@ -64,17 +69,36 @@ export default class LongPressGestureHandler extends GestureHandler {
64
69
 
65
70
  this.tracker.addToTracker(event);
66
71
  super.onPointerDown(event);
67
- this.tryBegin(event);
72
+
73
+ this.startX = event.x;
74
+ this.startY = event.y;
75
+
76
+ this.tryBegin();
68
77
  this.tryActivate();
69
- this.checkDistanceFail(event);
70
78
 
71
79
  this.tryToSendTouchEvent(event);
72
80
  }
81
+ protected onPointerAdd(event: AdaptedEvent): void {
82
+ super.onPointerAdd(event);
83
+ this.tracker.addToTracker(event);
84
+
85
+ if (this.tracker.getTrackedPointersCount() > this.numberOfPointers) {
86
+ this.fail();
87
+ return;
88
+ }
89
+
90
+ const absoluteCoordsAverage = this.tracker.getAbsoluteCoordsAverage();
91
+
92
+ this.startX = absoluteCoordsAverage.x;
93
+ this.startY = absoluteCoordsAverage.y;
94
+
95
+ this.tryActivate();
96
+ }
73
97
 
74
98
  protected onPointerMove(event: AdaptedEvent): void {
75
99
  super.onPointerMove(event);
76
100
  this.tracker.track(event);
77
- this.checkDistanceFail(event);
101
+ this.checkDistanceFail();
78
102
  }
79
103
 
80
104
  protected onPointerUp(event: AdaptedEvent): void {
@@ -88,7 +112,19 @@ export default class LongPressGestureHandler extends GestureHandler {
88
112
  }
89
113
  }
90
114
 
91
- private tryBegin(event: AdaptedEvent): void {
115
+ protected onPointerRemove(event: AdaptedEvent): void {
116
+ super.onPointerRemove(event);
117
+ this.tracker.removeFromTracker(event.pointerId);
118
+
119
+ if (
120
+ this.tracker.getTrackedPointersCount() < this.numberOfPointers &&
121
+ this.getState() !== State.ACTIVE
122
+ ) {
123
+ this.fail();
124
+ }
125
+ }
126
+
127
+ private tryBegin(): void {
92
128
  if (this.currentState !== State.UNDETERMINED) {
93
129
  return;
94
130
  }
@@ -97,12 +133,13 @@ export default class LongPressGestureHandler extends GestureHandler {
97
133
  this.startTime = this.previousTime;
98
134
 
99
135
  this.begin();
100
-
101
- this.startX = event.x;
102
- this.startY = event.y;
103
136
  }
104
137
 
105
138
  private tryActivate(): void {
139
+ if (this.tracker.getTrackedPointersCount() !== this.numberOfPointers) {
140
+ return;
141
+ }
142
+
106
143
  if (this.minDurationMs > 0) {
107
144
  this.activationTimeout = setTimeout(() => {
108
145
  this.activate();
@@ -112,9 +149,11 @@ export default class LongPressGestureHandler extends GestureHandler {
112
149
  }
113
150
  }
114
151
 
115
- private checkDistanceFail(event: AdaptedEvent): void {
116
- const dx = event.x - this.startX;
117
- const dy = event.y - this.startY;
152
+ private checkDistanceFail(): void {
153
+ const absoluteCoordsAverage = this.tracker.getAbsoluteCoordsAverage();
154
+
155
+ const dx = absoluteCoordsAverage.x - this.startX;
156
+ const dy = absoluteCoordsAverage.y - this.startY;
118
157
  const distSq = dx * dx + dy * dy;
119
158
 
120
159
  if (distSq <= this.maxDistSq) {
@@ -27,10 +27,7 @@ export default class NativeViewGestureHandler extends GestureHandler {
27
27
 
28
28
  const view = this.delegate.getView() as HTMLElement;
29
29
 
30
- view.style['touchAction'] = 'auto';
31
- // @ts-ignore Turns on defualt touch behavior on Safari
32
- view.style['WebkitTouchCallout'] = 'auto';
33
-
30
+ this.restoreViewStyles(view);
34
31
  this.buttonRole = view.getAttribute('role') === 'button';
35
32
  }
36
33
 
@@ -43,6 +40,19 @@ export default class NativeViewGestureHandler extends GestureHandler {
43
40
  if (this.config.disallowInterruption !== undefined) {
44
41
  this.disallowInterruption = this.config.disallowInterruption;
45
42
  }
43
+
44
+ const view = this.delegate.getView() as HTMLElement;
45
+ this.restoreViewStyles(view);
46
+ }
47
+
48
+ private restoreViewStyles(view: HTMLElement) {
49
+ if (!view) {
50
+ return;
51
+ }
52
+
53
+ view.style['touchAction'] = 'auto';
54
+ // @ts-ignore Turns on defualt touch behavior on Safari
55
+ view.style['WebkitTouchCallout'] = 'auto';
46
56
  }
47
57
 
48
58
  protected resetConfig(): void {
@@ -268,6 +268,10 @@ export default class PanGestureHandler extends GestureHandler {
268
268
 
269
269
  this.tracker.removeFromTracker(event.pointerId);
270
270
 
271
+ if (this.tracker.getTrackedPointersCount() === 0) {
272
+ this.clearActivationTimeout();
273
+ }
274
+
271
275
  if (this.currentState === State.ACTIVE) {
272
276
  this.end();
273
277
  } else {
@@ -36,7 +36,7 @@ type ConfigArgs =
36
36
  | undefined;
37
37
 
38
38
  export interface Config extends Record<string, ConfigArgs> {
39
- enabled?: boolean;
39
+ enabled: boolean;
40
40
  simultaneousHandlers?: Handler[] | null;
41
41
  waitFor?: Handler[] | null;
42
42
  blocksHandlers?: Handler[] | null;
@@ -20,6 +20,7 @@ export interface GestureHandlerDelegate<TComponent, THandler> {
20
20
  onEnd(): void;
21
21
  onCancel(): void;
22
22
  onFail(): void;
23
+ onEnabledChange(enabled: boolean): void;
23
24
 
24
25
  destroy(config: Config): void;
25
26
  }
@@ -11,13 +11,24 @@ import { isPointerInBounds } from '../utils';
11
11
  import EventManager from './EventManager';
12
12
  import { Config } from '../interfaces';
13
13
  import { MouseButton } from '../../handlers/gestureHandlerCommon';
14
+ import KeyboardEventManager from './KeyboardEventManager';
15
+
16
+ interface DefaultViewStyles {
17
+ userSelect: string;
18
+ touchAction: string;
19
+ }
14
20
 
15
21
  export class GestureHandlerWebDelegate
16
22
  implements GestureHandlerDelegate<HTMLElement, IGestureHandler>
17
23
  {
24
+ private isInitialized = false;
18
25
  private view!: HTMLElement;
19
26
  private gestureHandler!: IGestureHandler;
20
27
  private eventManagers: EventManager<unknown>[] = [];
28
+ private defaultViewStyles: DefaultViewStyles = {
29
+ userSelect: '',
30
+ touchAction: '',
31
+ };
21
32
 
22
33
  getView(): HTMLElement {
23
34
  return this.view;
@@ -30,22 +41,25 @@ export class GestureHandlerWebDelegate
30
41
  );
31
42
  }
32
43
 
44
+ this.isInitialized = true;
45
+
33
46
  this.gestureHandler = handler;
34
47
  this.view = findNodeHandle(viewRef) as unknown as HTMLElement;
35
48
 
36
- const config = handler.getConfig();
49
+ this.defaultViewStyles = {
50
+ userSelect: this.view.style.userSelect,
51
+ touchAction: this.view.style.touchAction,
52
+ };
37
53
 
38
- this.addContextMenuListeners(config);
54
+ const config = handler.getConfig();
39
55
 
40
- this.view.style['userSelect'] = config.userSelect ?? 'none';
41
- this.view.style['webkitUserSelect'] = config.userSelect ?? 'none';
42
-
43
- this.view.style['touchAction'] = config.touchAction ?? 'none';
44
- // @ts-ignore This one disables default events on Safari
45
- this.view.style['WebkitTouchCallout'] = 'none';
56
+ this.setUserSelect(config.enabled);
57
+ this.setTouchAction(config.enabled);
58
+ this.setContextMenu(config.enabled);
46
59
 
47
60
  this.eventManagers.push(new PointerEventManager(this.view));
48
61
  this.eventManagers.push(new TouchEventManager(this.view));
62
+ this.eventManagers.push(new KeyboardEventManager(this.view));
49
63
 
50
64
  this.eventManagers.forEach((manager) =>
51
65
  this.gestureHandler.attachEventManager(manager)
@@ -117,6 +131,51 @@ export class GestureHandlerWebDelegate
117
131
  e.stopPropagation();
118
132
  }
119
133
 
134
+ private setUserSelect(isHandlerEnabled: boolean) {
135
+ const { userSelect } = this.gestureHandler.getConfig();
136
+
137
+ this.view.style['userSelect'] = isHandlerEnabled
138
+ ? userSelect ?? 'none'
139
+ : this.defaultViewStyles.userSelect;
140
+
141
+ this.view.style['webkitUserSelect'] = isHandlerEnabled
142
+ ? userSelect ?? 'none'
143
+ : this.defaultViewStyles.userSelect;
144
+ }
145
+
146
+ private setTouchAction(isHandlerEnabled: boolean) {
147
+ const { touchAction } = this.gestureHandler.getConfig();
148
+
149
+ this.view.style['touchAction'] = isHandlerEnabled
150
+ ? touchAction ?? 'none'
151
+ : this.defaultViewStyles.touchAction;
152
+
153
+ // @ts-ignore This one disables default events on Safari
154
+ this.view.style['WebkitTouchCallout'] = isHandlerEnabled
155
+ ? touchAction ?? 'none'
156
+ : this.defaultViewStyles.touchAction;
157
+ }
158
+
159
+ private setContextMenu(isHandlerEnabled: boolean) {
160
+ const config = this.gestureHandler.getConfig();
161
+
162
+ if (isHandlerEnabled) {
163
+ this.addContextMenuListeners(config);
164
+ } else {
165
+ this.removeContextMenuListeners(config);
166
+ }
167
+ }
168
+
169
+ onEnabledChange(enabled: boolean): void {
170
+ if (!this.isInitialized) {
171
+ return;
172
+ }
173
+
174
+ this.setUserSelect(enabled);
175
+ this.setTouchAction(enabled);
176
+ this.setContextMenu(enabled);
177
+ }
178
+
120
179
  onBegin(): void {
121
180
  // no-op for now
122
181
  }
@@ -0,0 +1,91 @@
1
+ import { AdaptedEvent, EventTypes } from '../interfaces';
2
+ import EventManager from './EventManager';
3
+ import { PointerType } from '../../PointerType';
4
+
5
+ export default class KeyboardEventManager extends EventManager<HTMLElement> {
6
+ private activationKeys = ['Enter', ' '];
7
+ private cancelationKeys = ['Tab'];
8
+ private isPressed = false;
9
+
10
+ private keyDownCallback = (event: KeyboardEvent): void => {
11
+ if (this.cancelationKeys.indexOf(event.key) !== -1 && this.isPressed) {
12
+ this.dispatchEvent(event, EventTypes.CANCEL);
13
+ return;
14
+ }
15
+
16
+ if (this.activationKeys.indexOf(event.key) === -1) {
17
+ return;
18
+ }
19
+
20
+ this.dispatchEvent(event, EventTypes.DOWN);
21
+ };
22
+
23
+ private keyUpCallback = (event: KeyboardEvent): void => {
24
+ if (this.activationKeys.indexOf(event.key) === -1 || !this.isPressed) {
25
+ return;
26
+ }
27
+
28
+ this.dispatchEvent(event, EventTypes.UP);
29
+ };
30
+
31
+ private dispatchEvent(event: KeyboardEvent, eventType: EventTypes) {
32
+ if (!(event.target instanceof HTMLElement)) {
33
+ return;
34
+ }
35
+
36
+ const adaptedEvent = this.mapEvent(event, eventType);
37
+
38
+ switch (eventType) {
39
+ case EventTypes.UP:
40
+ this.isPressed = false;
41
+ this.onPointerUp(adaptedEvent);
42
+ break;
43
+ case EventTypes.DOWN:
44
+ this.isPressed = true;
45
+ this.onPointerDown(adaptedEvent);
46
+ break;
47
+ case EventTypes.CANCEL:
48
+ this.isPressed = false;
49
+ this.onPointerCancel(adaptedEvent);
50
+ break;
51
+ }
52
+ }
53
+
54
+ public registerListeners(): void {
55
+ this.view.addEventListener('keydown', this.keyDownCallback);
56
+ this.view.addEventListener('keyup', this.keyUpCallback);
57
+ }
58
+
59
+ public unregisterListeners(): void {
60
+ this.view.addEventListener('keydown', this.keyDownCallback);
61
+ this.view.addEventListener('keyup', this.keyUpCallback);
62
+ }
63
+
64
+ protected mapEvent(
65
+ event: KeyboardEvent,
66
+ eventType: EventTypes
67
+ ): AdaptedEvent {
68
+ const viewRect = (event.target as HTMLElement).getBoundingClientRect();
69
+
70
+ const viewportPosition = {
71
+ x: viewRect?.x + viewRect?.width / 2,
72
+ y: viewRect?.y + viewRect?.height / 2,
73
+ };
74
+
75
+ const relativePosition = {
76
+ x: viewRect?.width / 2,
77
+ y: viewRect?.height / 2,
78
+ };
79
+
80
+ return {
81
+ x: viewportPosition.x,
82
+ y: viewportPosition.y,
83
+ offsetX: relativePosition.x,
84
+ offsetY: relativePosition.y,
85
+ pointerId: 0,
86
+ eventType: eventType,
87
+ pointerType: PointerType.KEY,
88
+ time: event.timeStamp,
89
+ };
90
+ }
91
+ }
@@ -1,5 +1,5 @@
1
1
  import { DiagonalDirections, Directions } from '../../Directions';
2
- import { MINIMAL_FLING_VELOCITY } from '../constants';
2
+ import { MINIMAL_RECOGNIZABLE_MAGNITUDE } from '../constants';
3
3
  import PointerTracker from './PointerTracker';
4
4
 
5
5
  export default class Vector {
@@ -14,14 +14,15 @@ export default class Vector {
14
14
  this.y = y;
15
15
 
16
16
  this._magnitude = Math.hypot(this.x, this.y);
17
- const isMagnitudeSufficient = this._magnitude > MINIMAL_FLING_VELOCITY;
17
+ const isMagnitudeSufficient =
18
+ this._magnitude > MINIMAL_RECOGNIZABLE_MAGNITUDE;
18
19
 
19
20
  this.unitX = isMagnitudeSufficient ? this.x / this._magnitude : 0;
20
21
  this.unitY = isMagnitudeSufficient ? this.y / this._magnitude : 0;
21
22
  }
22
23
 
23
24
  static fromDirection(direction: Directions | DiagonalDirections): Vector {
24
- return DirectionToVectorMappings.get(direction)!;
25
+ return DirectionToVectorMappings.get(direction) ?? new Vector(0, 0);
25
26
  }
26
27
 
27
28
  static fromVelocity(tracker: PointerTracker, pointerId: number) {
package/src/web/utils.ts CHANGED
@@ -27,28 +27,30 @@ export function calculateViewScale(view: HTMLElement) {
27
27
  scaleY: 1,
28
28
  };
29
29
 
30
- const scales = styles.scale.split(' ');
30
+ // Get scales from scale property
31
+ if (styles.scale !== undefined && styles.scale !== 'none') {
32
+ const scales = styles.scale.split(' ');
31
33
 
32
- if (scales[0] !== 'none') {
33
- resultScales.scaleX = parseFloat(scales[0]);
34
- }
34
+ if (scales[0]) {
35
+ resultScales.scaleX = parseFloat(scales[0]);
36
+ }
35
37
 
36
- if (scales[1]) {
37
- resultScales.scaleY = parseFloat(scales[1]);
38
+ resultScales.scaleY = scales[1]
39
+ ? parseFloat(scales[1])
40
+ : parseFloat(scales[0]);
38
41
  }
39
42
 
43
+ // Get scales from transform property
40
44
  const matrixElements = new RegExp(/matrix\((.+)\)/).exec(
41
45
  styles.transform
42
46
  )?.[1];
43
47
 
44
- if (!matrixElements) {
45
- return resultScales;
46
- }
47
-
48
- const matrixElementsArray = matrixElements.split(', ');
48
+ if (matrixElements) {
49
+ const matrixElementsArray = matrixElements.split(', ');
49
50
 
50
- resultScales.scaleX *= parseFloat(matrixElementsArray[0]);
51
- resultScales.scaleY *= parseFloat(matrixElementsArray[3]);
51
+ resultScales.scaleX *= parseFloat(matrixElementsArray[0]);
52
+ resultScales.scaleY *= parseFloat(matrixElementsArray[3]);
53
+ }
52
54
 
53
55
  return resultScales;
54
56
  }