react-native-gesture-handler 2.16.2 → 2.17.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 (212) hide show
  1. package/README.md +9 -3
  2. package/android/build.gradle +103 -0
  3. package/android/gradle.properties +7 -0
  4. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +7 -7
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt +16 -8
  6. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +9 -5
  7. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerInteractionManager.kt +4 -0
  8. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +1 -1
  9. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerTouchEvent.kt +1 -0
  10. package/apple/RNGestureHandlerButtonComponentView.mm +10 -0
  11. package/apple/RNGestureHandlerModule.mm +2 -3
  12. package/lib/commonjs/components/GestureButtons.js +27 -12
  13. package/lib/commonjs/components/GestureButtons.js.map +1 -1
  14. package/lib/commonjs/handlers/createHandler.js +1 -3
  15. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  16. package/lib/commonjs/handlers/gestureHandlerCommon.js +3 -3
  17. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  18. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js +42 -0
  19. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js.map +1 -0
  20. package/lib/commonjs/handlers/gestures/GestureDetector/attachHandlers.js +83 -0
  21. package/lib/commonjs/handlers/gestures/GestureDetector/attachHandlers.js.map +1 -0
  22. package/lib/commonjs/handlers/gestures/GestureDetector/dropHandlers.js +25 -0
  23. package/lib/commonjs/handlers/gestures/GestureDetector/dropHandlers.js.map +1 -0
  24. package/lib/commonjs/handlers/gestures/GestureDetector/index.js +143 -0
  25. package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -0
  26. package/lib/commonjs/handlers/gestures/GestureDetector/needsToReattach.js +25 -0
  27. package/lib/commonjs/handlers/gestures/GestureDetector/needsToReattach.js.map +1 -0
  28. package/lib/commonjs/handlers/gestures/GestureDetector/types.js +6 -0
  29. package/lib/commonjs/handlers/gestures/GestureDetector/types.js.map +1 -0
  30. package/lib/commonjs/handlers/gestures/GestureDetector/updateHandlers.js +80 -0
  31. package/lib/commonjs/handlers/gestures/GestureDetector/updateHandlers.js.map +1 -0
  32. package/lib/commonjs/handlers/gestures/GestureDetector/useAnimatedGesture.js +180 -0
  33. package/lib/commonjs/handlers/gestures/GestureDetector/useAnimatedGesture.js.map +1 -0
  34. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +55 -0
  35. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -0
  36. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +47 -0
  37. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -0
  38. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +176 -0
  39. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -0
  40. package/lib/commonjs/handlers/gestures/gestureComposition.js +3 -1
  41. package/lib/commonjs/handlers/gestures/gestureComposition.js.map +1 -1
  42. package/lib/commonjs/handlers/gestures/gestureStateManager.js +8 -0
  43. package/lib/commonjs/handlers/gestures/gestureStateManager.js.map +1 -1
  44. package/lib/commonjs/handlers/gestures/reanimatedWrapper.js.map +1 -1
  45. package/lib/commonjs/utils.js +36 -0
  46. package/lib/commonjs/utils.js.map +1 -1
  47. package/lib/commonjs/web/detectors/RotationGestureDetector.js +6 -8
  48. package/lib/commonjs/web/detectors/RotationGestureDetector.js.map +1 -1
  49. package/lib/commonjs/web/detectors/ScaleGestureDetector.js +5 -6
  50. package/lib/commonjs/web/detectors/ScaleGestureDetector.js.map +1 -1
  51. package/lib/commonjs/web/handlers/FlingGestureHandler.js +1 -0
  52. package/lib/commonjs/web/handlers/FlingGestureHandler.js.map +1 -1
  53. package/lib/commonjs/web/handlers/GestureHandler.js +56 -64
  54. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  55. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +1 -0
  56. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  57. package/lib/commonjs/web/handlers/ManualGestureHandler.js +1 -0
  58. package/lib/commonjs/web/handlers/ManualGestureHandler.js.map +1 -1
  59. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +7 -4
  60. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  61. package/lib/commonjs/web/handlers/PanGestureHandler.js +28 -18
  62. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  63. package/lib/commonjs/web/handlers/PinchGestureHandler.js +1 -0
  64. package/lib/commonjs/web/handlers/PinchGestureHandler.js.map +1 -1
  65. package/lib/commonjs/web/handlers/RotationGestureHandler.js +1 -0
  66. package/lib/commonjs/web/handlers/RotationGestureHandler.js.map +1 -1
  67. package/lib/commonjs/web/handlers/TapGestureHandler.js +18 -12
  68. package/lib/commonjs/web/handlers/TapGestureHandler.js.map +1 -1
  69. package/lib/commonjs/web/interfaces.js.map +1 -1
  70. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +1 -6
  71. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  72. package/lib/commonjs/web/tools/PointerEventManager.js +7 -2
  73. package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
  74. package/lib/commonjs/web/tools/PointerTracker.js +89 -57
  75. package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
  76. package/lib/commonjs/web/tools/TouchEventManager.js +6 -2
  77. package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -1
  78. package/lib/commonjs/web/tools/Vector.js +2 -1
  79. package/lib/commonjs/web/tools/Vector.js.map +1 -1
  80. package/lib/commonjs/web/utils.js +31 -0
  81. package/lib/commonjs/web/utils.js.map +1 -1
  82. package/lib/module/components/GestureButtons.js +24 -6
  83. package/lib/module/components/GestureButtons.js.map +1 -1
  84. package/lib/module/handlers/createHandler.js +2 -4
  85. package/lib/module/handlers/createHandler.js.map +1 -1
  86. package/lib/module/handlers/gestureHandlerCommon.js +1 -1
  87. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  88. package/lib/module/handlers/gestures/GestureDetector/Wrap.js +26 -0
  89. package/lib/module/handlers/gestures/GestureDetector/Wrap.js.map +1 -0
  90. package/lib/module/handlers/gestures/GestureDetector/attachHandlers.js +65 -0
  91. package/lib/module/handlers/gestures/GestureDetector/attachHandlers.js.map +1 -0
  92. package/lib/module/handlers/gestures/GestureDetector/dropHandlers.js +12 -0
  93. package/lib/module/handlers/gestures/GestureDetector/dropHandlers.js.map +1 -0
  94. package/lib/module/handlers/gestures/GestureDetector/index.js +115 -0
  95. package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -0
  96. package/lib/module/handlers/gestures/GestureDetector/needsToReattach.js +18 -0
  97. package/lib/module/handlers/gestures/GestureDetector/needsToReattach.js.map +1 -0
  98. package/lib/module/handlers/gestures/GestureDetector/types.js +2 -0
  99. package/lib/module/handlers/gestures/GestureDetector/types.js.map +1 -0
  100. package/lib/module/handlers/gestures/GestureDetector/updateHandlers.js +64 -0
  101. package/lib/module/handlers/gestures/GestureDetector/updateHandlers.js.map +1 -0
  102. package/lib/module/handlers/gestures/GestureDetector/useAnimatedGesture.js +165 -0
  103. package/lib/module/handlers/gestures/GestureDetector/useAnimatedGesture.js.map +1 -0
  104. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +41 -0
  105. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -0
  106. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +36 -0
  107. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -0
  108. package/lib/module/handlers/gestures/GestureDetector/utils.js +142 -0
  109. package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -0
  110. package/lib/module/handlers/gestures/gestureComposition.js +3 -1
  111. package/lib/module/handlers/gestures/gestureComposition.js.map +1 -1
  112. package/lib/module/handlers/gestures/gestureStateManager.js +8 -0
  113. package/lib/module/handlers/gestures/gestureStateManager.js.map +1 -1
  114. package/lib/module/handlers/gestures/reanimatedWrapper.js.map +1 -1
  115. package/lib/module/utils.js +34 -0
  116. package/lib/module/utils.js.map +1 -1
  117. package/lib/module/web/detectors/RotationGestureDetector.js +6 -8
  118. package/lib/module/web/detectors/RotationGestureDetector.js.map +1 -1
  119. package/lib/module/web/detectors/ScaleGestureDetector.js +5 -6
  120. package/lib/module/web/detectors/ScaleGestureDetector.js.map +1 -1
  121. package/lib/module/web/handlers/FlingGestureHandler.js +1 -0
  122. package/lib/module/web/handlers/FlingGestureHandler.js.map +1 -1
  123. package/lib/module/web/handlers/GestureHandler.js +56 -64
  124. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  125. package/lib/module/web/handlers/LongPressGestureHandler.js +1 -0
  126. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  127. package/lib/module/web/handlers/ManualGestureHandler.js +1 -0
  128. package/lib/module/web/handlers/ManualGestureHandler.js.map +1 -1
  129. package/lib/module/web/handlers/NativeViewGestureHandler.js +7 -4
  130. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  131. package/lib/module/web/handlers/PanGestureHandler.js +28 -18
  132. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  133. package/lib/module/web/handlers/PinchGestureHandler.js +1 -0
  134. package/lib/module/web/handlers/PinchGestureHandler.js.map +1 -1
  135. package/lib/module/web/handlers/RotationGestureHandler.js +1 -0
  136. package/lib/module/web/handlers/RotationGestureHandler.js.map +1 -1
  137. package/lib/module/web/handlers/TapGestureHandler.js +18 -12
  138. package/lib/module/web/handlers/TapGestureHandler.js.map +1 -1
  139. package/lib/module/web/interfaces.js.map +1 -1
  140. package/lib/module/web/tools/GestureHandlerOrchestrator.js +1 -6
  141. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  142. package/lib/module/web/tools/PointerEventManager.js +8 -3
  143. package/lib/module/web/tools/PointerEventManager.js.map +1 -1
  144. package/lib/module/web/tools/PointerTracker.js +89 -57
  145. package/lib/module/web/tools/PointerTracker.js.map +1 -1
  146. package/lib/module/web/tools/TouchEventManager.js +7 -3
  147. package/lib/module/web/tools/TouchEventManager.js.map +1 -1
  148. package/lib/module/web/tools/Vector.js +2 -1
  149. package/lib/module/web/tools/Vector.js.map +1 -1
  150. package/lib/module/web/utils.js +29 -0
  151. package/lib/module/web/utils.js.map +1 -1
  152. package/lib/typescript/components/GestureButtons.d.ts +3 -34
  153. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +3 -2
  154. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.d.ts +13 -0
  155. package/lib/typescript/handlers/gestures/GestureDetector/attachHandlers.d.ts +13 -0
  156. package/lib/typescript/handlers/gestures/GestureDetector/dropHandlers.d.ts +2 -0
  157. package/lib/typescript/handlers/gestures/{GestureDetector.d.ts → GestureDetector/index.d.ts} +4 -12
  158. package/lib/typescript/handlers/gestures/GestureDetector/needsToReattach.d.ts +3 -0
  159. package/lib/typescript/handlers/gestures/GestureDetector/types.d.ts +20 -0
  160. package/lib/typescript/handlers/gestures/GestureDetector/updateHandlers.d.ts +4 -0
  161. package/lib/typescript/handlers/gestures/GestureDetector/useAnimatedGesture.d.ts +2 -0
  162. package/lib/typescript/handlers/gestures/GestureDetector/useDetectorUpdater.d.ts +5 -0
  163. package/lib/typescript/handlers/gestures/GestureDetector/useViewRefHandler.d.ts +3 -0
  164. package/lib/typescript/handlers/gestures/GestureDetector/utils.d.ts +12 -0
  165. package/lib/typescript/handlers/gestures/reanimatedWrapper.d.ts +1 -1
  166. package/lib/typescript/utils.d.ts +10 -0
  167. package/lib/typescript/web/handlers/GestureHandler.d.ts +1 -0
  168. package/lib/typescript/web/interfaces.d.ts +1 -0
  169. package/lib/typescript/web/tools/PointerTracker.d.ts +34 -31
  170. package/lib/typescript/web/utils.d.ts +4 -0
  171. package/package.json +5 -5
  172. package/src/components/GestureButtons.tsx +36 -4
  173. package/src/handlers/createHandler.tsx +1 -3
  174. package/src/handlers/gestureHandlerCommon.ts +4 -1
  175. package/src/handlers/gestures/GestureDetector/Wrap.tsx +35 -0
  176. package/src/handlers/gestures/GestureDetector/attachHandlers.ts +112 -0
  177. package/src/handlers/gestures/GestureDetector/dropHandlers.ts +14 -0
  178. package/src/handlers/gestures/GestureDetector/index.tsx +187 -0
  179. package/src/handlers/gestures/GestureDetector/needsToReattach.ts +27 -0
  180. package/src/handlers/gestures/GestureDetector/types.ts +32 -0
  181. package/src/handlers/gestures/GestureDetector/updateHandlers.ts +94 -0
  182. package/src/handlers/gestures/GestureDetector/useAnimatedGesture.ts +206 -0
  183. package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +69 -0
  184. package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +54 -0
  185. package/src/handlers/gestures/GestureDetector/utils.ts +185 -0
  186. package/src/handlers/gestures/gestureComposition.ts +2 -0
  187. package/src/handlers/gestures/gestureStateManager.ts +12 -4
  188. package/src/handlers/gestures/reanimatedWrapper.ts +19 -17
  189. package/src/utils.ts +39 -0
  190. package/src/web/detectors/RotationGestureDetector.ts +6 -8
  191. package/src/web/detectors/ScaleGestureDetector.ts +5 -6
  192. package/src/web/handlers/FlingGestureHandler.ts +2 -0
  193. package/src/web/handlers/GestureHandler.ts +53 -62
  194. package/src/web/handlers/LongPressGestureHandler.ts +2 -0
  195. package/src/web/handlers/ManualGestureHandler.ts +2 -0
  196. package/src/web/handlers/NativeViewGestureHandler.ts +8 -4
  197. package/src/web/handlers/PanGestureHandler.ts +32 -19
  198. package/src/web/handlers/PinchGestureHandler.ts +2 -0
  199. package/src/web/handlers/RotationGestureHandler.ts +2 -0
  200. package/src/web/handlers/TapGestureHandler.ts +20 -12
  201. package/src/web/interfaces.ts +1 -0
  202. package/src/web/tools/GestureHandlerOrchestrator.ts +1 -7
  203. package/src/web/tools/PointerEventManager.ts +10 -3
  204. package/src/web/tools/PointerTracker.ts +81 -74
  205. package/src/web/tools/TouchEventManager.ts +5 -3
  206. package/src/web/tools/Vector.ts +2 -4
  207. package/src/web/utils.ts +34 -0
  208. package/lib/commonjs/handlers/gestures/GestureDetector.js +0 -704
  209. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +0 -1
  210. package/lib/module/handlers/gestures/GestureDetector.js +0 -654
  211. package/lib/module/handlers/gestures/GestureDetector.js.map +0 -1
  212. package/src/handlers/gestures/GestureDetector.tsx +0 -889
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { Reanimated } from '../reanimatedWrapper';
3
+ import { tagMessage } from '../../../utils';
4
+
5
+ export class Wrap extends React.Component<{
6
+ onGestureHandlerEvent?: unknown;
7
+ // implicit `children` prop has been removed in @types/react^18.0.0
8
+ children?: React.ReactNode;
9
+ }> {
10
+ render() {
11
+ try {
12
+ // I don't think that fighting with types over such a simple function is worth it
13
+ // The only thing it does is add 'collapsable: false' to the child component
14
+ // to make sure it is in the native view hierarchy so the detector can find
15
+ // correct viewTag to attach to.
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const child: any = React.Children.only(this.props.children);
18
+ return React.cloneElement(
19
+ child,
20
+ { collapsable: false },
21
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
22
+ child.props.children
23
+ );
24
+ } catch (e) {
25
+ throw new Error(
26
+ tagMessage(
27
+ `GestureDetector got more than one view as a child. If you want the gesture to work on multiple views, wrap them with a common parent and attach the gesture to that view.`
28
+ )
29
+ );
30
+ }
31
+ }
32
+ }
33
+
34
+ export const AnimatedWrap =
35
+ Reanimated?.default?.createAnimatedComponent(Wrap) ?? Wrap;
@@ -0,0 +1,112 @@
1
+ import React from 'react';
2
+ import { GestureType, HandlerCallbacks } from '../gesture';
3
+ import { registerHandler } from '../../handlersRegistry';
4
+ import RNGestureHandlerModule from '../../../RNGestureHandlerModule';
5
+ import {
6
+ filterConfig,
7
+ scheduleFlushOperations,
8
+ } from '../../gestureHandlerCommon';
9
+ import { ComposedGesture } from '../gestureComposition';
10
+ import { ActionType } from '../../../ActionType';
11
+ import { Platform } from 'react-native';
12
+ import type RNGestureHandlerModuleWeb from '../../../RNGestureHandlerModule.web';
13
+ import { ghQueueMicrotask } from '../../../ghQueueMicrotask';
14
+ import { AttachedGestureState, WebEventHandler } from './types';
15
+ import {
16
+ extractGestureRelations,
17
+ checkGestureCallbacksForWorklets,
18
+ ALLOWED_PROPS,
19
+ } from './utils';
20
+
21
+ interface AttachHandlersConfig {
22
+ preparedGesture: AttachedGestureState;
23
+ gestureConfig: ComposedGesture | GestureType;
24
+ gesturesToAttach: GestureType[];
25
+ viewTag: number;
26
+ webEventHandlersRef: React.RefObject<WebEventHandler>;
27
+ }
28
+
29
+ export function attachHandlers({
30
+ preparedGesture,
31
+ gestureConfig,
32
+ gesturesToAttach,
33
+ viewTag,
34
+ webEventHandlersRef,
35
+ }: AttachHandlersConfig) {
36
+ gestureConfig.initialize();
37
+
38
+ // use queueMicrotask to extract handlerTags, because all refs should be initialized
39
+ // when it's ran
40
+ ghQueueMicrotask(() => {
41
+ if (!preparedGesture.isMounted) {
42
+ return;
43
+ }
44
+ gestureConfig.prepare();
45
+ });
46
+
47
+ for (const handler of gesturesToAttach) {
48
+ checkGestureCallbacksForWorklets(handler);
49
+ RNGestureHandlerModule.createGestureHandler(
50
+ handler.handlerName,
51
+ handler.handlerTag,
52
+ filterConfig(handler.config, ALLOWED_PROPS)
53
+ );
54
+
55
+ registerHandler(handler.handlerTag, handler, handler.config.testId);
56
+ }
57
+
58
+ // use queueMicrotask to extract handlerTags, because all refs should be initialized
59
+ // when it's ran
60
+ ghQueueMicrotask(() => {
61
+ if (!preparedGesture.isMounted) {
62
+ return;
63
+ }
64
+ for (const handler of gesturesToAttach) {
65
+ RNGestureHandlerModule.updateGestureHandler(
66
+ handler.handlerTag,
67
+ filterConfig(
68
+ handler.config,
69
+ ALLOWED_PROPS,
70
+ extractGestureRelations(handler)
71
+ )
72
+ );
73
+ }
74
+
75
+ scheduleFlushOperations();
76
+ });
77
+
78
+ for (const gesture of gesturesToAttach) {
79
+ const actionType = gesture.shouldUseReanimated
80
+ ? ActionType.REANIMATED_WORKLET
81
+ : ActionType.JS_FUNCTION_NEW_API;
82
+
83
+ if (Platform.OS === 'web') {
84
+ (
85
+ RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler
86
+ )(
87
+ gesture.handlerTag,
88
+ viewTag,
89
+ ActionType.JS_FUNCTION_OLD_API, // ignored on web
90
+ webEventHandlersRef
91
+ );
92
+ } else {
93
+ RNGestureHandlerModule.attachGestureHandler(
94
+ gesture.handlerTag,
95
+ viewTag,
96
+ actionType
97
+ );
98
+ }
99
+ }
100
+
101
+ preparedGesture.attachedGestures = gesturesToAttach;
102
+
103
+ if (preparedGesture.animatedHandlers) {
104
+ const isAnimatedGesture = (g: GestureType) => g.shouldUseReanimated;
105
+
106
+ preparedGesture.animatedHandlers.value = gesturesToAttach
107
+ .filter(isAnimatedGesture)
108
+ .map((g) => g.handlers) as unknown as HandlerCallbacks<
109
+ Record<string, unknown>
110
+ >[];
111
+ }
112
+ }
@@ -0,0 +1,14 @@
1
+ import { unregisterHandler } from '../../handlersRegistry';
2
+ import RNGestureHandlerModule from '../../../RNGestureHandlerModule';
3
+ import { scheduleFlushOperations } from '../../gestureHandlerCommon';
4
+ import { AttachedGestureState } from './types';
5
+
6
+ export function dropHandlers(preparedGesture: AttachedGestureState) {
7
+ for (const handler of preparedGesture.attachedGestures) {
8
+ RNGestureHandlerModule.dropGestureHandler(handler.handlerTag);
9
+
10
+ unregisterHandler(handler.handlerTag, handler.config.testId);
11
+ }
12
+
13
+ scheduleFlushOperations();
14
+ }
@@ -0,0 +1,187 @@
1
+ /* eslint-disable react/no-unused-prop-types */
2
+ import React, {
3
+ useContext,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useMemo,
7
+ useRef,
8
+ } from 'react';
9
+ import { Platform, findNodeHandle } from 'react-native';
10
+ import { GestureType } from '../gesture';
11
+ import { UserSelect, TouchAction } from '../../gestureHandlerCommon';
12
+ import { ComposedGesture } from '../gestureComposition';
13
+ import { isJestEnv } from '../../../utils';
14
+
15
+ import GestureHandlerRootViewContext from '../../../GestureHandlerRootViewContext';
16
+ import { AttachedGestureState, GestureDetectorState } from './types';
17
+ import { useAnimatedGesture } from './useAnimatedGesture';
18
+ import { attachHandlers } from './attachHandlers';
19
+ import { needsToReattach } from './needsToReattach';
20
+ import { dropHandlers } from './dropHandlers';
21
+ import { useWebEventHandlers } from './utils';
22
+ import { Wrap, AnimatedWrap } from './Wrap';
23
+ import { useDetectorUpdater } from './useDetectorUpdater';
24
+ import { useViewRefHandler } from './useViewRefHandler';
25
+
26
+ function propagateDetectorConfig(
27
+ props: GestureDetectorProps,
28
+ gesture: ComposedGesture | GestureType
29
+ ) {
30
+ const keysToPropagate: (keyof GestureDetectorProps)[] = [
31
+ 'userSelect',
32
+ 'enableContextMenu',
33
+ 'touchAction',
34
+ ];
35
+
36
+ for (const key of keysToPropagate) {
37
+ const value = props[key];
38
+ if (value === undefined) {
39
+ continue;
40
+ }
41
+
42
+ for (const g of gesture.toGestureArray()) {
43
+ const config = g.config as { [key: string]: unknown };
44
+ config[key] = value;
45
+ }
46
+ }
47
+ }
48
+
49
+ interface GestureDetectorProps {
50
+ children?: React.ReactNode;
51
+ /**
52
+ * A gesture object containing the configuration and callbacks.
53
+ * Can be any of:
54
+ * - base gestures (`Tap`, `Pan`, ...)
55
+ * - `ComposedGesture` (`Race`, `Simultaneous`, `Exclusive`)
56
+ */
57
+ gesture: ComposedGesture | GestureType;
58
+ /**
59
+ * #### Web only
60
+ * This parameter allows to specify which `userSelect` property should be applied to underlying view.
61
+ * Possible values are `"none" | "auto" | "text"`. Default value is set to `"none"`.
62
+ */
63
+ userSelect?: UserSelect;
64
+ /**
65
+ * #### Web only
66
+ * Specifies whether context menu should be enabled after clicking on underlying view with right mouse button.
67
+ * Default value is set to `false`.
68
+ */
69
+ enableContextMenu?: boolean;
70
+ /**
71
+ * #### Web only
72
+ * This parameter allows to specify which `touchAction` property should be applied to underlying view.
73
+ * Supports all CSS touch-action values (e.g. `"none"`, `"pan-y"`). Default value is set to `"none"`.
74
+ */
75
+ touchAction?: TouchAction;
76
+ }
77
+
78
+ /**
79
+ * `GestureDetector` is responsible for creating and updating native gesture handlers based on the config of provided gesture.
80
+ *
81
+ * ### Props
82
+ * - `gesture`
83
+ * - `userSelect` (**Web only**)
84
+ * - `enableContextMenu` (**Web only**)
85
+ * - `touchAction` (**Web only**)
86
+ *
87
+ * ### Remarks
88
+ * - Gesture Detector will use first native view in its subtree to recognize gestures, however if this view is used only to group its children it may get automatically collapsed.
89
+ * - Using the same instance of a gesture across multiple Gesture Detectors is not possible.
90
+ *
91
+ * @see https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture-detector
92
+ */
93
+ export const GestureDetector = (props: GestureDetectorProps) => {
94
+ const rootViewContext = useContext(GestureHandlerRootViewContext);
95
+ if (__DEV__ && !rootViewContext && !isJestEnv() && Platform.OS !== 'web') {
96
+ throw new Error(
97
+ 'GestureDetector must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'
98
+ );
99
+ }
100
+
101
+ // Gesture config should be wrapped with useMemo to prevent unnecessary re-renders
102
+ const gestureConfig = props.gesture;
103
+ propagateDetectorConfig(props, gestureConfig);
104
+
105
+ const gesturesToAttach = useMemo(
106
+ () => gestureConfig.toGestureArray(),
107
+ [gestureConfig]
108
+ );
109
+ const shouldUseReanimated = gesturesToAttach.some(
110
+ (g) => g.shouldUseReanimated
111
+ );
112
+
113
+ const webEventHandlersRef = useWebEventHandlers();
114
+ // store state in ref to prevent unnecessary renders
115
+ const state = useRef<GestureDetectorState>({
116
+ firstRender: true,
117
+ viewRef: null,
118
+ previousViewTag: -1,
119
+ forceRebuildReanimatedEvent: false,
120
+ }).current;
121
+
122
+ const preparedGesture = React.useRef<AttachedGestureState>({
123
+ attachedGestures: [],
124
+ animatedEventHandler: null,
125
+ animatedHandlers: null,
126
+ shouldUseReanimated: shouldUseReanimated,
127
+ isMounted: false,
128
+ }).current;
129
+
130
+ const updateAttachedGestures = useDetectorUpdater(
131
+ state,
132
+ preparedGesture,
133
+ gesturesToAttach,
134
+ gestureConfig,
135
+ webEventHandlersRef
136
+ );
137
+
138
+ const refHandler = useViewRefHandler(state, updateAttachedGestures);
139
+
140
+ // Reanimated event should be rebuilt only when gestures are reattached, otherwise
141
+ // config update will be enough as all necessary items are stored in shared values anyway
142
+ const needsToRebuildReanimatedEvent =
143
+ state.firstRender ||
144
+ state.forceRebuildReanimatedEvent ||
145
+ needsToReattach(preparedGesture, gesturesToAttach);
146
+ state.forceRebuildReanimatedEvent = false;
147
+
148
+ useAnimatedGesture(preparedGesture, needsToRebuildReanimatedEvent);
149
+
150
+ useLayoutEffect(() => {
151
+ const viewTag = findNodeHandle(state.viewRef) as number;
152
+ preparedGesture.isMounted = true;
153
+
154
+ attachHandlers({
155
+ preparedGesture,
156
+ gestureConfig,
157
+ gesturesToAttach,
158
+ webEventHandlersRef,
159
+ viewTag,
160
+ });
161
+
162
+ return () => {
163
+ preparedGesture.isMounted = false;
164
+ dropHandlers(preparedGesture);
165
+ };
166
+ }, []);
167
+
168
+ useEffect(() => {
169
+ if (state.firstRender) {
170
+ state.firstRender = false;
171
+ } else {
172
+ updateAttachedGestures();
173
+ }
174
+ }, [props]);
175
+
176
+ if (shouldUseReanimated) {
177
+ return (
178
+ <AnimatedWrap
179
+ ref={refHandler}
180
+ onGestureHandlerEvent={preparedGesture.animatedEventHandler}>
181
+ {props.children}
182
+ </AnimatedWrap>
183
+ );
184
+ } else {
185
+ return <Wrap ref={refHandler}>{props.children}</Wrap>;
186
+ }
187
+ };
@@ -0,0 +1,27 @@
1
+ import { GestureType } from '../gesture';
2
+ import { AttachedGestureState } from './types';
3
+
4
+ // Checks whether the gesture should be reattached to the view, this will happen when:
5
+ // - The number of gestures in the preparedGesture is different than the number of gestures in the gesture
6
+ // - The handlerName is different in any of the gestures
7
+ // - At least one of the gestures changed the thread it runs on
8
+ export function needsToReattach(
9
+ preparedGesture: AttachedGestureState,
10
+ newGestures: GestureType[]
11
+ ) {
12
+ if (newGestures.length !== preparedGesture.attachedGestures.length) {
13
+ return true;
14
+ }
15
+ for (let i = 0; i < newGestures.length; i++) {
16
+ if (
17
+ newGestures[i].handlerName !==
18
+ preparedGesture.attachedGestures[i].handlerName ||
19
+ newGestures[i].shouldUseReanimated !==
20
+ preparedGesture.attachedGestures[i].shouldUseReanimated
21
+ ) {
22
+ return true;
23
+ }
24
+ }
25
+
26
+ return false;
27
+ }
@@ -0,0 +1,32 @@
1
+ import { GestureType, HandlerCallbacks } from '../gesture';
2
+ import { SharedValue } from '../reanimatedWrapper';
3
+ import { HandlerStateChangeEvent } from '../../gestureHandlerCommon';
4
+
5
+ export interface AttachedGestureState {
6
+ // Array of gestures that should be attached to the view under that gesture detector
7
+ attachedGestures: GestureType[];
8
+ // Event handler for the gesture, returned by `useEvent` from Reanimated
9
+ animatedEventHandler: unknown;
10
+ // Shared value that's responsible for transferring the callbacks to the UI thread handler
11
+ animatedHandlers: SharedValue<
12
+ HandlerCallbacks<Record<string, unknown>>[] | null
13
+ > | null;
14
+ // Whether `useAnimatedGesture` should be called inside detector
15
+ shouldUseReanimated: boolean;
16
+ // Whether the GestureDetector is mounted
17
+ isMounted: boolean;
18
+ }
19
+
20
+ export interface GestureDetectorState {
21
+ firstRender: boolean;
22
+ viewRef: React.Component | null;
23
+ previousViewTag: number;
24
+ forceRebuildReanimatedEvent: boolean;
25
+ }
26
+
27
+ export interface WebEventHandler {
28
+ onGestureHandlerEvent: (event: HandlerStateChangeEvent<unknown>) => void;
29
+ onGestureHandlerStateChange?: (
30
+ event: HandlerStateChangeEvent<unknown>
31
+ ) => void;
32
+ }
@@ -0,0 +1,94 @@
1
+ import { GestureType, HandlerCallbacks } from '../gesture';
2
+ import { registerHandler } from '../../handlersRegistry';
3
+ import RNGestureHandlerModule from '../../../RNGestureHandlerModule';
4
+ import {
5
+ filterConfig,
6
+ scheduleFlushOperations,
7
+ } from '../../gestureHandlerCommon';
8
+ import { ComposedGesture } from '../gestureComposition';
9
+ import { ghQueueMicrotask } from '../../../ghQueueMicrotask';
10
+ import { AttachedGestureState } from './types';
11
+ import {
12
+ extractGestureRelations,
13
+ checkGestureCallbacksForWorklets,
14
+ ALLOWED_PROPS,
15
+ } from './utils';
16
+
17
+ export function updateHandlers(
18
+ preparedGesture: AttachedGestureState,
19
+ gestureConfig: ComposedGesture | GestureType,
20
+ newGestures: GestureType[]
21
+ ) {
22
+ gestureConfig.prepare();
23
+
24
+ for (let i = 0; i < newGestures.length; i++) {
25
+ const handler = preparedGesture.attachedGestures[i];
26
+ checkGestureCallbacksForWorklets(handler);
27
+
28
+ // only update handlerTag when it's actually different, it may be the same
29
+ // if gesture config object is wrapped with useMemo
30
+ if (newGestures[i].handlerTag !== handler.handlerTag) {
31
+ newGestures[i].handlerTag = handler.handlerTag;
32
+ newGestures[i].handlers.handlerTag = handler.handlerTag;
33
+ }
34
+ }
35
+
36
+ // use queueMicrotask to extract handlerTags, because when it's ran, all refs should be updated
37
+ // and handlerTags in BaseGesture references should be updated in the loop above (we need to wait
38
+ // in case of external relations)
39
+ ghQueueMicrotask(() => {
40
+ if (!preparedGesture.isMounted) {
41
+ return;
42
+ }
43
+ for (let i = 0; i < newGestures.length; i++) {
44
+ const handler = preparedGesture.attachedGestures[i];
45
+
46
+ handler.config = newGestures[i].config;
47
+ handler.handlers = newGestures[i].handlers;
48
+
49
+ RNGestureHandlerModule.updateGestureHandler(
50
+ handler.handlerTag,
51
+ filterConfig(
52
+ handler.config,
53
+ ALLOWED_PROPS,
54
+ extractGestureRelations(handler)
55
+ )
56
+ );
57
+
58
+ registerHandler(handler.handlerTag, handler, handler.config.testId);
59
+ }
60
+
61
+ if (preparedGesture.animatedHandlers) {
62
+ const previousHandlersValue =
63
+ preparedGesture.animatedHandlers.value ?? [];
64
+ const newHandlersValue = preparedGesture.attachedGestures
65
+ .filter((g) => g.shouldUseReanimated) // ignore gestures that shouldn't run on UI
66
+ .map((g) => g.handlers) as unknown as HandlerCallbacks<
67
+ Record<string, unknown>
68
+ >[];
69
+
70
+ // if amount of gesture configs changes, we need to update the callbacks in shared value
71
+ let shouldUpdateSharedValue =
72
+ previousHandlersValue.length !== newHandlersValue.length;
73
+
74
+ if (!shouldUpdateSharedValue) {
75
+ // if the amount is the same, we need to check if any of the configs inside has changed
76
+ for (let i = 0; i < newHandlersValue.length; i++) {
77
+ if (
78
+ // we can use the `gestureId` prop as it's unique for every config instance
79
+ newHandlersValue[i].gestureId !== previousHandlersValue[i].gestureId
80
+ ) {
81
+ shouldUpdateSharedValue = true;
82
+ break;
83
+ }
84
+ }
85
+ }
86
+
87
+ if (shouldUpdateSharedValue) {
88
+ preparedGesture.animatedHandlers.value = newHandlersValue;
89
+ }
90
+ }
91
+
92
+ scheduleFlushOperations();
93
+ });
94
+ }