react-native-gesture-handler 2.1.3 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -3
  3. package/RNGestureHandler.podspec +27 -3
  4. package/android/build.gradle +82 -9
  5. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +47 -12
  6. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerOrchestrator.kt +50 -14
  7. package/android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.kt +7 -4
  8. package/android/lib/src/main/java/com/swmansion/gesturehandler/PinchGestureHandler.kt +8 -8
  9. package/android/lib/src/main/java/com/swmansion/gesturehandler/RotationGestureHandler.kt +6 -4
  10. package/android/lib/src/main/java/com/swmansion/gesturehandler/ScaleGestureDetector.java +558 -0
  11. package/android/src/fabric/java/com/swmansion/gesturehandler/RNGestureHandlerComponentsRegistry.java +29 -0
  12. package/android/src/fabric/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +12 -0
  13. package/android/src/main/AndroidManifest.xml +1 -1
  14. package/android/src/main/java/com/swmansion/gesturehandler/RNGestureHandlerPackage.kt +29 -0
  15. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +40 -13
  16. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +119 -55
  17. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRegistry.kt +9 -4
  18. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +1 -1
  19. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootViewManager.kt +17 -2
  20. package/android/src/main/jni/Android.mk +53 -0
  21. package/android/src/main/jni/OnLoad.cpp +9 -0
  22. package/android/src/main/jni/RNGestureHandlerComponentsRegistry.cpp +71 -0
  23. package/android/src/main/jni/RNGestureHandlerComponentsRegistry.h +34 -0
  24. package/android/src/main/jni/cpp-adapter.cpp +41 -0
  25. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +47 -0
  26. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerInterface.java +22 -0
  27. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerRootViewManagerDelegate.java +25 -0
  28. package/android/src/paper/java/com/facebook/react/viewmanagers/RNGestureHandlerRootViewManagerInterface.java +16 -0
  29. package/android/src/paper/java/com/swmansion/gesturehandler/ReactContextExtensions.kt +13 -0
  30. package/ios/Handlers/RNFlingHandler.m +2 -0
  31. package/ios/Handlers/RNPanHandler.m +2 -0
  32. package/ios/Handlers/RNPinchHandler.m +2 -0
  33. package/ios/Handlers/RNRotationHandler.m +2 -0
  34. package/ios/RNGestureHandler.h +3 -8
  35. package/ios/RNGestureHandler.m +2 -10
  36. package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcuserdata/jakubpiasecki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  37. package/ios/RNGestureHandler.xcodeproj/xcuserdata/jakubpiasecki.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
  38. package/ios/RNGestureHandlerActionType.h +8 -0
  39. package/ios/RNGestureHandlerButtonComponentView.h +17 -0
  40. package/ios/RNGestureHandlerButtonComponentView.mm +48 -0
  41. package/ios/RNGestureHandlerButtonManager.h +5 -0
  42. package/ios/RNGestureHandlerButtonManager.m +30 -0
  43. package/ios/RNGestureHandlerManager.h +2 -4
  44. package/ios/{RNGestureHandlerManager.m → RNGestureHandlerManager.mm} +92 -20
  45. package/ios/{RNGestureHandlerModule.m → RNGestureHandlerModule.mm} +91 -36
  46. package/ios/RNGestureHandlerRegistry.h +1 -2
  47. package/ios/RNGestureHandlerRegistry.m +2 -11
  48. package/ios/RNGestureHandlerRootViewComponentView.mm +21 -0
  49. package/lib/commonjs/ActionType.js +15 -0
  50. package/lib/commonjs/ActionType.js.map +1 -0
  51. package/lib/commonjs/GestureHandlerRootView.android.js +6 -6
  52. package/lib/commonjs/GestureHandlerRootView.android.js.map +1 -1
  53. package/lib/commonjs/GestureHandlerRootView.js +2 -3
  54. package/lib/commonjs/GestureHandlerRootView.js.map +1 -1
  55. package/lib/commonjs/RNGestureHandlerModule.js +4 -2
  56. package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
  57. package/lib/commonjs/RNGestureHandlerModule.web.js +1 -1
  58. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  59. package/lib/commonjs/components/DrawerLayout.js +2 -2
  60. package/lib/commonjs/components/DrawerLayout.js.map +1 -1
  61. package/lib/commonjs/components/GestureHandlerButton.js +5 -2
  62. package/lib/commonjs/components/GestureHandlerButton.js.map +1 -1
  63. package/lib/commonjs/components/Swipeable.js +22 -20
  64. package/lib/commonjs/components/Swipeable.js.map +1 -1
  65. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js +21 -0
  66. package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -0
  67. package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js +21 -0
  68. package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -0
  69. package/lib/commonjs/getShadowNodeFromRef.js +24 -0
  70. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -0
  71. package/lib/commonjs/getShadowNodeFromRef.web.js +15 -0
  72. package/lib/commonjs/getShadowNodeFromRef.web.js.map +1 -0
  73. package/lib/commonjs/handlers/FlingGestureHandler.js +4 -2
  74. package/lib/commonjs/handlers/FlingGestureHandler.js.map +1 -1
  75. package/lib/commonjs/handlers/ForceTouchGestureHandler.js +8 -4
  76. package/lib/commonjs/handlers/ForceTouchGestureHandler.js.map +1 -1
  77. package/lib/commonjs/handlers/LongPressGestureHandler.js +4 -2
  78. package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
  79. package/lib/commonjs/handlers/NativeViewGestureHandler.js +4 -2
  80. package/lib/commonjs/handlers/NativeViewGestureHandler.js.map +1 -1
  81. package/lib/commonjs/handlers/PanGestureHandler.js +4 -2
  82. package/lib/commonjs/handlers/PanGestureHandler.js.map +1 -1
  83. package/lib/commonjs/handlers/PinchGestureHandler.js +4 -2
  84. package/lib/commonjs/handlers/PinchGestureHandler.js.map +1 -1
  85. package/lib/commonjs/handlers/RotationGestureHandler.js +4 -2
  86. package/lib/commonjs/handlers/RotationGestureHandler.js.map +1 -1
  87. package/lib/commonjs/handlers/TapGestureHandler.js +4 -2
  88. package/lib/commonjs/handlers/TapGestureHandler.js.map +1 -1
  89. package/lib/commonjs/handlers/createHandler.js +74 -8
  90. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  91. package/lib/commonjs/handlers/createNativeWrapper.js +6 -2
  92. package/lib/commonjs/handlers/createNativeWrapper.js.map +1 -1
  93. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  94. package/lib/commonjs/handlers/gestures/GestureDetector.js +84 -32
  95. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  96. package/lib/commonjs/handlers/gestures/eventReceiver.js +25 -8
  97. package/lib/commonjs/handlers/gestures/eventReceiver.js.map +1 -1
  98. package/lib/commonjs/handlers/gestures/forceTouchGesture.js.map +1 -1
  99. package/lib/commonjs/handlers/gestures/gesture.js +16 -1
  100. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  101. package/lib/commonjs/handlers/gestures/gestureStateManager.js +7 -4
  102. package/lib/commonjs/handlers/gestures/gestureStateManager.js.map +1 -1
  103. package/lib/commonjs/handlers/gestures/panGesture.js.map +1 -1
  104. package/lib/commonjs/handlers/gestures/pinchGesture.js.map +1 -1
  105. package/lib/commonjs/handlers/gestures/reanimatedWrapper.js +4 -1
  106. package/lib/commonjs/handlers/gestures/reanimatedWrapper.js.map +1 -1
  107. package/lib/commonjs/handlers/handlersRegistry.js +42 -6
  108. package/lib/commonjs/handlers/handlersRegistry.js.map +1 -1
  109. package/lib/commonjs/index.js +14 -0
  110. package/lib/commonjs/index.js.map +1 -1
  111. package/lib/commonjs/init.js +10 -0
  112. package/lib/commonjs/init.js.map +1 -1
  113. package/lib/commonjs/jestUtils.js +375 -0
  114. package/lib/commonjs/jestUtils.js.map +1 -0
  115. package/lib/commonjs/utils.js +38 -0
  116. package/lib/commonjs/utils.js.map +1 -1
  117. package/lib/module/ActionType.js +7 -0
  118. package/lib/module/ActionType.js.map +1 -0
  119. package/lib/module/GestureHandlerRootView.android.js +5 -6
  120. package/lib/module/GestureHandlerRootView.android.js.map +1 -1
  121. package/lib/module/GestureHandlerRootView.js +2 -3
  122. package/lib/module/GestureHandlerRootView.js.map +1 -1
  123. package/lib/module/RNGestureHandlerModule.js +3 -2
  124. package/lib/module/RNGestureHandlerModule.js.map +1 -1
  125. package/lib/module/RNGestureHandlerModule.web.js +1 -1
  126. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  127. package/lib/module/components/DrawerLayout.js +2 -2
  128. package/lib/module/components/DrawerLayout.js.map +1 -1
  129. package/lib/module/components/GestureHandlerButton.js +4 -2
  130. package/lib/module/components/GestureHandlerButton.js.map +1 -1
  131. package/lib/module/components/Swipeable.js +22 -20
  132. package/lib/module/components/Swipeable.js.map +1 -1
  133. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js +9 -0
  134. package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -0
  135. package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js +9 -0
  136. package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -0
  137. package/lib/module/getShadowNodeFromRef.js +17 -0
  138. package/lib/module/getShadowNodeFromRef.js.map +1 -0
  139. package/lib/module/getShadowNodeFromRef.web.js +8 -0
  140. package/lib/module/getShadowNodeFromRef.web.js.map +1 -0
  141. package/lib/module/handlers/FlingGestureHandler.js +2 -1
  142. package/lib/module/handlers/FlingGestureHandler.js.map +1 -1
  143. package/lib/module/handlers/ForceTouchGestureHandler.js +5 -3
  144. package/lib/module/handlers/ForceTouchGestureHandler.js.map +1 -1
  145. package/lib/module/handlers/LongPressGestureHandler.js +2 -1
  146. package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
  147. package/lib/module/handlers/NativeViewGestureHandler.js +2 -1
  148. package/lib/module/handlers/NativeViewGestureHandler.js.map +1 -1
  149. package/lib/module/handlers/PanGestureHandler.js +2 -1
  150. package/lib/module/handlers/PanGestureHandler.js.map +1 -1
  151. package/lib/module/handlers/PinchGestureHandler.js +2 -1
  152. package/lib/module/handlers/PinchGestureHandler.js.map +1 -1
  153. package/lib/module/handlers/RotationGestureHandler.js +2 -1
  154. package/lib/module/handlers/RotationGestureHandler.js.map +1 -1
  155. package/lib/module/handlers/TapGestureHandler.js +2 -1
  156. package/lib/module/handlers/TapGestureHandler.js.map +1 -1
  157. package/lib/module/handlers/createHandler.js +74 -9
  158. package/lib/module/handlers/createHandler.js.map +1 -1
  159. package/lib/module/handlers/createNativeWrapper.js +6 -2
  160. package/lib/module/handlers/createNativeWrapper.js.map +1 -1
  161. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  162. package/lib/module/handlers/gestures/GestureDetector.js +79 -32
  163. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  164. package/lib/module/handlers/gestures/eventReceiver.js +25 -7
  165. package/lib/module/handlers/gestures/eventReceiver.js.map +1 -1
  166. package/lib/module/handlers/gestures/forceTouchGesture.js.map +1 -1
  167. package/lib/module/handlers/gestures/gesture.js +16 -1
  168. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  169. package/lib/module/handlers/gestures/gestureStateManager.js +6 -4
  170. package/lib/module/handlers/gestures/gestureStateManager.js.map +1 -1
  171. package/lib/module/handlers/gestures/panGesture.js.map +1 -1
  172. package/lib/module/handlers/gestures/pinchGesture.js.map +1 -1
  173. package/lib/module/handlers/gestures/reanimatedWrapper.js +2 -1
  174. package/lib/module/handlers/gestures/reanimatedWrapper.js.map +1 -1
  175. package/lib/module/handlers/handlersRegistry.js +34 -6
  176. package/lib/module/handlers/handlersRegistry.js.map +1 -1
  177. package/lib/module/index.js +1 -0
  178. package/lib/module/index.js.map +1 -1
  179. package/lib/module/init.js +6 -0
  180. package/lib/module/init.js.map +1 -1
  181. package/lib/module/jestUtils.js +350 -0
  182. package/lib/module/jestUtils.js.map +1 -0
  183. package/lib/module/utils.js +28 -0
  184. package/lib/module/utils.js.map +1 -1
  185. package/lib/typescript/ActionType.d.ts +7 -0
  186. package/lib/typescript/GestureHandlerRootView.android.d.ts +5 -2
  187. package/lib/typescript/GestureHandlerRootView.d.ts +1 -1
  188. package/lib/typescript/RNGestureHandlerModule.d.ts +3 -1
  189. package/lib/typescript/RNGestureHandlerModule.web.d.ts +2 -1
  190. package/lib/typescript/components/GestureHandlerButton.d.ts +2 -2
  191. package/lib/typescript/components/Swipeable.d.ts +12 -4
  192. package/lib/typescript/getShadowNodeFromRef.d.ts +1 -0
  193. package/lib/typescript/getShadowNodeFromRef.web.d.ts +1 -0
  194. package/lib/typescript/handlers/FlingGestureHandler.d.ts +1 -0
  195. package/lib/typescript/handlers/ForceTouchGestureHandler.d.ts +1 -0
  196. package/lib/typescript/handlers/LongPressGestureHandler.d.ts +3 -2
  197. package/lib/typescript/handlers/NativeViewGestureHandler.d.ts +1 -0
  198. package/lib/typescript/handlers/PanGestureHandler.d.ts +3 -2
  199. package/lib/typescript/handlers/PinchGestureHandler.d.ts +1 -0
  200. package/lib/typescript/handlers/RotationGestureHandler.d.ts +1 -0
  201. package/lib/typescript/handlers/TapGestureHandler.d.ts +1 -0
  202. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +2 -4
  203. package/lib/typescript/handlers/gestures/GestureDetector.d.ts +4 -1
  204. package/lib/typescript/handlers/gestures/forceTouchGesture.d.ts +1 -2
  205. package/lib/typescript/handlers/gestures/gesture.d.ts +5 -0
  206. package/lib/typescript/handlers/gestures/panGesture.d.ts +1 -2
  207. package/lib/typescript/handlers/gestures/pinchGesture.d.ts +1 -2
  208. package/lib/typescript/handlers/handlersRegistry.d.ts +10 -2
  209. package/lib/typescript/index.d.ts +4 -0
  210. package/lib/typescript/jestUtils.d.ts +28 -0
  211. package/lib/typescript/utils.d.ts +6 -0
  212. package/package.json +39 -16
  213. package/src/ActionType.ts +9 -0
  214. package/src/GestureHandlerRootView.android.tsx +14 -14
  215. package/src/GestureHandlerRootView.tsx +4 -4
  216. package/src/RNGestureHandlerModule.ts +11 -6
  217. package/src/RNGestureHandlerModule.web.ts +2 -1
  218. package/src/components/DrawerLayout.tsx +8 -2
  219. package/src/components/GestureHandlerButton.tsx +7 -4
  220. package/src/components/Swipeable.tsx +28 -22
  221. package/src/fabric/RNGestureHandlerButtonNativeComponent.js +27 -0
  222. package/src/fabric/RNGestureHandlerRootViewNativeComponent.js +19 -0
  223. package/src/getShadowNodeFromRef.ts +19 -0
  224. package/src/getShadowNodeFromRef.web.ts +7 -0
  225. package/src/handlers/FlingGestureHandler.ts +3 -1
  226. package/src/handlers/ForceTouchGestureHandler.ts +8 -2
  227. package/src/handlers/LongPressGestureHandler.ts +5 -3
  228. package/src/handlers/NativeViewGestureHandler.ts +3 -1
  229. package/src/handlers/PanGestureHandler.ts +5 -3
  230. package/src/handlers/PinchGestureHandler.ts +3 -1
  231. package/src/handlers/RotationGestureHandler.ts +3 -1
  232. package/src/handlers/TapGestureHandler.ts +3 -1
  233. package/src/handlers/createHandler.ts +80 -5
  234. package/src/handlers/createNativeWrapper.tsx +7 -1
  235. package/src/handlers/gestureHandlerCommon.ts +2 -5
  236. package/src/handlers/gestures/GestureDetector.tsx +110 -37
  237. package/src/handlers/gestures/eventReceiver.ts +23 -19
  238. package/src/handlers/gestures/forceTouchGesture.ts +1 -1
  239. package/src/handlers/gestures/gesture.ts +21 -1
  240. package/src/handlers/gestures/gestureStateManager.ts +9 -12
  241. package/src/handlers/gestures/panGesture.ts +1 -1
  242. package/src/handlers/gestures/pinchGesture.ts +1 -1
  243. package/src/handlers/gestures/reanimatedWrapper.ts +4 -1
  244. package/src/handlers/handlersRegistry.ts +44 -6
  245. package/src/index.ts +4 -0
  246. package/src/init.ts +6 -0
  247. package/src/jestUtils.ts +506 -0
  248. package/src/utils.ts +38 -0
  249. package/android/lib/src/main/java/com/swmansion/gesturehandler/BaseGestureHandlerInteractionController.kt +0 -18
  250. package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandlerRegistryImpl.kt +0 -21
  251. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerPackage.kt +0 -17
@@ -32,6 +32,13 @@ import { tapGestureHandlerProps } from '../TapGestureHandler';
32
32
  import { State } from '../../State';
33
33
  import { EventType } from '../../EventType';
34
34
  import { ComposedGesture } from './gestureComposition';
35
+ import { ActionType } from '../../ActionType';
36
+ import { isFabric, tagMessage } from '../../utils';
37
+ import { getShadowNodeFromRef } from '../../getShadowNodeFromRef';
38
+
39
+ declare global {
40
+ function isFormsStackingContext(node: unknown): boolean | null; // JSI function
41
+ }
35
42
 
36
43
  const ALLOWED_PROPS = [
37
44
  ...baseGestureHandlerWithMonitorProps,
@@ -50,7 +57,7 @@ export type GestureConfigReference = {
50
57
  HandlerCallbacks<Record<string, unknown>>[] | null
51
58
  > | null;
52
59
  firstExecution: boolean;
53
- useAnimated: boolean;
60
+ useReanimatedHook: boolean;
54
61
  };
55
62
 
56
63
  function convertToHandlerTag(ref: GestureRef): number {
@@ -75,7 +82,28 @@ function dropHandlers(preparedGesture: GestureConfigReference) {
75
82
  for (const handler of preparedGesture.config) {
76
83
  RNGestureHandlerModule.dropGestureHandler(handler.handlerTag);
77
84
 
78
- unregisterHandler(handler.handlerTag);
85
+ unregisterHandler(handler.handlerTag, handler.config.testId);
86
+ }
87
+ }
88
+
89
+ function checkGestureCallbacksForWorklets(gesture: GestureType) {
90
+ // if a gesture is explicitly marked to run on the JS thread there is no need to check
91
+ // if callbacks are worklets as the user is aware they will be ran on the JS thread
92
+ if (gesture.config.runOnJS) {
93
+ return;
94
+ }
95
+
96
+ const areSomeNotWorklets = gesture.handlers.isWorklet.includes(false);
97
+ const areSomeWorklets = gesture.handlers.isWorklet.includes(true);
98
+
99
+ // if some of the callbacks are worklets and some are not, and the gesture is not
100
+ // explicitly marked with `.runOnJS(true)` show an error
101
+ if (areSomeNotWorklets && areSomeWorklets) {
102
+ console.error(
103
+ tagMessage(
104
+ `Some of the callbacks in the gesture are worklets and some are not. Either make sure that all calbacks are marked as 'worklet' if you wish to run them on the UI thread or use '.runOnJS(true)' modifier on the gesture explicitly to run all callbacks on the JS thread.`
105
+ )
106
+ );
79
107
  }
80
108
  }
81
109
 
@@ -84,7 +112,6 @@ interface AttachHandlersConfig {
84
112
  gestureConfig: ComposedGesture | GestureType | undefined;
85
113
  gesture: GestureType[];
86
114
  viewTag: number;
87
- useAnimated: boolean;
88
115
  }
89
116
 
90
117
  function attachHandlers({
@@ -92,7 +119,6 @@ function attachHandlers({
92
119
  gestureConfig,
93
120
  gesture,
94
121
  viewTag,
95
- useAnimated,
96
122
  }: AttachHandlersConfig) {
97
123
  if (!preparedGesture.firstExecution) {
98
124
  gestureConfig?.initialize();
@@ -107,13 +133,15 @@ function attachHandlers({
107
133
  });
108
134
 
109
135
  for (const handler of gesture) {
136
+ checkGestureCallbacksForWorklets(handler);
137
+
110
138
  RNGestureHandlerModule.createGestureHandler(
111
139
  handler.handlerName,
112
140
  handler.handlerTag,
113
141
  filterConfig(handler.config, ALLOWED_PROPS)
114
142
  );
115
143
 
116
- registerHandler(handler.handlerTag, handler);
144
+ registerHandler(handler.handlerTag, handler, handler.config.testId);
117
145
 
118
146
  // use setImmediate to extract handlerTags, because all refs should be initialized
119
147
  // when it's ran
@@ -142,17 +170,25 @@ function attachHandlers({
142
170
  preparedGesture.config = gesture;
143
171
 
144
172
  for (const gesture of preparedGesture.config) {
173
+ const actionType = gesture.shouldUseReanimated
174
+ ? ActionType.REANIMATED_WORKLET
175
+ : ActionType.JS_FUNCTION_NEW_API;
176
+
145
177
  RNGestureHandlerModule.attachGestureHandler(
146
178
  gesture.handlerTag,
147
179
  viewTag,
148
- !useAnimated // send direct events when using animatedGesture, device events otherwise
180
+ actionType
149
181
  );
150
182
  }
151
183
 
152
184
  if (preparedGesture.animatedHandlers) {
153
- preparedGesture.animatedHandlers.value = (gesture.map(
154
- (g) => g.handlers
155
- ) as unknown) as HandlerCallbacks<Record<string, unknown>>[];
185
+ const isAnimatedGesture = (g: GestureType) => g.shouldUseReanimated;
186
+
187
+ preparedGesture.animatedHandlers.value = (gesture
188
+ .filter(isAnimatedGesture)
189
+ .map((g) => g.handlers) as unknown) as HandlerCallbacks<
190
+ Record<string, unknown>
191
+ >[];
156
192
  }
157
193
  }
158
194
 
@@ -165,9 +201,14 @@ function updateHandlers(
165
201
 
166
202
  for (let i = 0; i < gesture.length; i++) {
167
203
  const handler = preparedGesture.config[i];
204
+ checkGestureCallbacksForWorklets(handler);
168
205
 
169
- gesture[i].handlerTag = handler.handlerTag;
170
- gesture[i].handlers.handlerTag = handler.handlerTag;
206
+ // only update handlerTag when it's actually different, it may be the same
207
+ // if gesture config object is wrapped with useMemo
208
+ if (gesture[i].handlerTag !== handler.handlerTag) {
209
+ gesture[i].handlerTag = handler.handlerTag;
210
+ gesture[i].handlers.handlerTag = handler.handlerTag;
211
+ }
171
212
  }
172
213
 
173
214
  // use setImmediate to extract handlerTags, because when it's ran, all refs should be updated
@@ -179,7 +220,6 @@ function updateHandlers(
179
220
 
180
221
  handler.config = gesture[i].config;
181
222
  handler.handlers = gesture[i].handlers;
182
- handler.handlers.handlerTag = handler.handlerTag;
183
223
 
184
224
  const requireToFail = extractValidHandlerTags(
185
225
  handler.config.requireToFail
@@ -197,13 +237,15 @@ function updateHandlers(
197
237
  })
198
238
  );
199
239
 
200
- registerHandler(handler.handlerTag, handler);
240
+ registerHandler(handler.handlerTag, handler, handler.config.testId);
201
241
  }
202
242
 
203
243
  if (preparedGesture.animatedHandlers) {
204
- preparedGesture.animatedHandlers.value = (preparedGesture.config.map(
205
- (g) => g.handlers
206
- ) as unknown) as HandlerCallbacks<Record<string, unknown>>[];
244
+ preparedGesture.animatedHandlers.value = (preparedGesture.config
245
+ .filter((g) => g.shouldUseReanimated) // ignore gestures that shouldn't run on UI
246
+ .map((g) => g.handlers) as unknown) as HandlerCallbacks<
247
+ Record<string, unknown>
248
+ >[];
207
249
  }
208
250
  });
209
251
  }
@@ -216,7 +258,11 @@ function needsToReattach(
216
258
  return true;
217
259
  }
218
260
  for (let i = 0; i < gesture.length; i++) {
219
- if (gesture[i].handlerName !== preparedGesture.config[i].handlerName) {
261
+ if (
262
+ gesture[i].handlerName !== preparedGesture.config[i].handlerName ||
263
+ gesture[i].shouldUseReanimated !==
264
+ preparedGesture.config[i].shouldUseReanimated
265
+ ) {
220
266
  return true;
221
267
  }
222
268
  }
@@ -224,7 +270,10 @@ function needsToReattach(
224
270
  return false;
225
271
  }
226
272
 
227
- function useAnimatedGesture(preparedGesture: GestureConfigReference) {
273
+ function useAnimatedGesture(
274
+ preparedGesture: GestureConfigReference,
275
+ needsRebuild: boolean
276
+ ) {
228
277
  if (!Reanimated) {
229
278
  return;
230
279
  }
@@ -301,7 +350,7 @@ function useAnimatedGesture(preparedGesture: GestureConfigReference) {
301
350
  // correct handler.
302
351
  handler?.(event, ...args);
303
352
  } else if (handler) {
304
- console.warn('Animated gesture callback must be a worklet');
353
+ console.warn(tagMessage('Animated gesture callback must be a worklet'));
305
354
  }
306
355
  }
307
356
 
@@ -401,7 +450,7 @@ function useAnimatedGesture(preparedGesture: GestureConfigReference) {
401
450
  const event = Reanimated.useEvent(
402
451
  callback,
403
452
  ['onGestureHandlerStateChange', 'onGestureHandlerEvent'],
404
- true
453
+ needsRebuild
405
454
  );
406
455
 
407
456
  preparedGesture.animatedEventHandler = event;
@@ -416,10 +465,7 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
416
465
  ) => {
417
466
  const gestureConfig = props.gesture;
418
467
  const gesture = gestureConfig?.toGestureArray?.() ?? [];
419
- const useAnimated =
420
- gesture.find((gesture) =>
421
- gesture.handlers.isWorklet.reduce((prev, current) => prev || current)
422
- ) != null;
468
+ const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated);
423
469
  const viewRef = useRef(null);
424
470
  const firstRenderRef = useRef(true);
425
471
 
@@ -428,24 +474,30 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
428
474
  animatedEventHandler: null,
429
475
  animatedHandlers: null,
430
476
  firstExecution: true,
431
- useAnimated: useAnimated,
477
+ useReanimatedHook: useReanimatedHook,
432
478
  }).current;
433
479
 
434
- if (useAnimated !== preparedGesture.useAnimated) {
480
+ if (useReanimatedHook !== preparedGesture.useReanimatedHook) {
435
481
  throw new Error(
436
- 'You cannot change whether you are using gesture or animatedGesture while the app is running'
482
+ tagMessage(
483
+ 'You cannot change the thread the callbacks are ran on while the app is running'
484
+ )
437
485
  );
438
486
  }
439
487
 
488
+ // Reanimated event should be rebuilt only when gestures are reattached, otherwise
489
+ // config update will be enough as all necessary items are stored in shared values anyway
490
+ const needsToRebuildReanimatedEvent =
491
+ preparedGesture.firstExecution || needsToReattach(preparedGesture, gesture);
492
+
440
493
  if (preparedGesture.firstExecution) {
441
494
  gestureConfig?.initialize?.();
442
495
  }
443
496
 
444
- if (useAnimated) {
445
- // Whether animatedGesture or gesture is used shouldn't change
446
- // during while an app is running
497
+ if (useReanimatedHook) {
498
+ // Whether animatedGesture or gesture is used shouldn't change while the app is running
447
499
  // eslint-disable-next-line react-hooks/rules-of-hooks
448
- useAnimatedGesture(preparedGesture);
500
+ useAnimatedGesture(preparedGesture, needsToRebuildReanimatedEvent);
449
501
  }
450
502
 
451
503
  useEffect(() => {
@@ -456,7 +508,6 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
456
508
  gestureConfig,
457
509
  gesture,
458
510
  viewTag,
459
- useAnimated,
460
511
  });
461
512
 
462
513
  return () => {
@@ -475,7 +526,6 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
475
526
  gestureConfig,
476
527
  gesture,
477
528
  viewTag,
478
- useAnimated,
479
529
  });
480
530
  } else {
481
531
  updateHandlers(preparedGesture, gestureConfig, gesture);
@@ -485,16 +535,40 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
485
535
  }
486
536
  }, [props]);
487
537
 
488
- if (useAnimated) {
538
+ const refFunction = (ref: unknown) => {
539
+ if (ref !== null) {
540
+ //@ts-ignore Just setting the ref
541
+ viewRef.current = ref;
542
+
543
+ if (isFabric()) {
544
+ const node = getShadowNodeFromRef(ref);
545
+ if (global.isFormsStackingContext(node) === false) {
546
+ setImmediate(() => {
547
+ // For some weird reason, console.error on iOS delays
548
+ // the execution of RNGestureHandlerModule.attachGestureHandler,
549
+ // so that's why we use setImmediate here.
550
+ console.error(
551
+ tagMessage(
552
+ 'GestureDetector has received a child that may get view-flattened. ' +
553
+ '\nTo prevent it from misbehaving you need to wrap the child with a `<View collapsable={false}>`.'
554
+ )
555
+ );
556
+ });
557
+ }
558
+ }
559
+ }
560
+ };
561
+
562
+ if (useReanimatedHook) {
489
563
  return (
490
564
  <AnimatedWrap
491
- ref={viewRef}
565
+ ref={refFunction}
492
566
  onGestureHandlerEvent={preparedGesture.animatedEventHandler}>
493
567
  {props.children}
494
568
  </AnimatedWrap>
495
569
  );
496
570
  } else {
497
- return <Wrap ref={viewRef}>{props.children}</Wrap>;
571
+ return <Wrap ref={refFunction}>{props.children}</Wrap>;
498
572
  }
499
573
  };
500
574
 
@@ -506,7 +580,6 @@ class Wrap extends React.Component<{ onGestureHandlerEvent?: unknown }> {
506
580
  // correct viewTag to attach to.
507
581
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
508
582
  const child: any = React.Children.only(this.props.children);
509
-
510
583
  return React.cloneElement(
511
584
  child,
512
585
  { collapsable: false },
@@ -7,32 +7,29 @@ import {
7
7
  GestureStateChangeEvent,
8
8
  } from '../gestureHandlerCommon';
9
9
  import { GestureStateManagerType } from './gestureStateManager';
10
- import { findHandler } from '../handlersRegistry';
10
+ import { findHandler, findOldGestureHandler } from '../handlersRegistry';
11
11
  import { BaseGesture } from './gesture';
12
+ import { tagMessage } from '../../utils';
12
13
 
13
14
  let gestureHandlerEventSubscription: EmitterSubscription | null = null;
14
15
  let gestureHandlerStateChangeEventSubscription: EmitterSubscription | null = null;
15
16
 
17
+ const warningMessage = tagMessage(
18
+ 'You have to use react-native-reanimated in order to control the state of the gesture.'
19
+ );
20
+
16
21
  const dummyStateManager: GestureStateManagerType = {
17
22
  begin: () => {
18
- console.warn(
19
- 'You have to use react-native-reanimated in order to control the state of the gesture.'
20
- );
23
+ console.warn(warningMessage);
21
24
  },
22
25
  activate: () => {
23
- console.warn(
24
- 'You have to use react-native-reanimated in order to control the state of the gesture.'
25
- );
26
+ console.warn(warningMessage);
26
27
  },
27
28
  end: () => {
28
- console.warn(
29
- 'You have to use react-native-reanimated in order to control the state of the gesture.'
30
- );
29
+ console.warn(warningMessage);
31
30
  },
32
31
  fail: () => {
33
- console.warn(
34
- 'You have to use react-native-reanimated in order to control the state of the gesture.'
35
- );
32
+ console.warn(warningMessage);
36
33
  },
37
34
  };
38
35
 
@@ -117,6 +114,17 @@ function onGestureHandlerEvent(
117
114
  lastUpdateEvent[handler.handlers.handlerTag] = event;
118
115
  }
119
116
  }
117
+ } else {
118
+ const oldHandler = findOldGestureHandler(event.handlerTag);
119
+ if (oldHandler) {
120
+ const nativeEvent = { nativeEvent: event };
121
+ if (isStateChangeEvent(event)) {
122
+ oldHandler.onGestureStateChange(nativeEvent);
123
+ } else {
124
+ oldHandler.onGestureEvent(nativeEvent);
125
+ }
126
+ return;
127
+ }
120
128
  }
121
129
  }
122
130
 
@@ -136,16 +144,12 @@ export function startListening() {
136
144
 
137
145
  export function stopListening() {
138
146
  if (gestureHandlerEventSubscription) {
139
- DeviceEventEmitter.removeSubscription(gestureHandlerEventSubscription);
140
-
147
+ gestureHandlerEventSubscription.remove();
141
148
  gestureHandlerEventSubscription = null;
142
149
  }
143
150
 
144
151
  if (gestureHandlerStateChangeEventSubscription) {
145
- DeviceEventEmitter.removeSubscription(
146
- gestureHandlerStateChangeEventSubscription
147
- );
148
-
152
+ gestureHandlerStateChangeEventSubscription.remove();
149
153
  gestureHandlerStateChangeEventSubscription = null;
150
154
  }
151
155
  }
@@ -5,7 +5,7 @@ import {
5
5
  } from '../ForceTouchGestureHandler';
6
6
  import { GestureUpdateEvent } from '../gestureHandlerCommon';
7
7
 
8
- type ForceTouchGestureChangeEventPayload = {
8
+ export type ForceTouchGestureChangeEventPayload = {
9
9
  forceChange: number;
10
10
  };
11
11
 
@@ -41,6 +41,8 @@ export interface BaseGestureConfig
41
41
  simultaneousWith?: GestureRef[];
42
42
  needsPointerData?: boolean;
43
43
  manualActivation?: boolean;
44
+ runOnJS?: boolean;
45
+ testId?: string;
44
46
  }
45
47
 
46
48
  type TouchEventHandlerType = (
@@ -119,7 +121,7 @@ export abstract class BaseGesture<
119
121
  public config: BaseGestureConfig = {};
120
122
  public handlers: HandlerCallbacks<EventPayloadT> = {
121
123
  handlerTag: -1,
122
- isWorklet: [false, false, false, false],
124
+ isWorklet: [],
123
125
  };
124
126
 
125
127
  private addDependency(
@@ -234,6 +236,11 @@ export abstract class BaseGesture<
234
236
  return this;
235
237
  }
236
238
 
239
+ runOnJS(runOnJS: boolean) {
240
+ this.config.runOnJS = runOnJS;
241
+ return this;
242
+ }
243
+
237
244
  simultaneousWithExternalGesture(...gestures: Exclude<GestureRef, number>[]) {
238
245
  for (const gesture of gestures) {
239
246
  this.addDependency('simultaneousWith', gesture);
@@ -248,8 +255,14 @@ export abstract class BaseGesture<
248
255
  return this;
249
256
  }
250
257
 
258
+ withTestId(id: string) {
259
+ this.config.testId = id;
260
+ return this;
261
+ }
262
+
251
263
  initialize() {
252
264
  this.handlerTag = getNextHandlerTag();
265
+
253
266
  this.handlers = { ...this.handlers, handlerTag: this.handlerTag };
254
267
 
255
268
  if (this.config.ref) {
@@ -263,6 +276,13 @@ export abstract class BaseGesture<
263
276
 
264
277
  // eslint-disable-next-line @typescript-eslint/no-empty-function
265
278
  prepare() {}
279
+
280
+ get shouldUseReanimated(): boolean {
281
+ // use Reanimated when runOnJS isn't set explicitly and all defined callbacks are worklets
282
+ return (
283
+ this.config.runOnJS !== true && !this.handlers.isWorklet.includes(false)
284
+ );
285
+ }
266
286
  }
267
287
 
268
288
  export abstract class ContinousBaseGesture<
@@ -1,5 +1,6 @@
1
1
  import { Reanimated } from './reanimatedWrapper';
2
2
  import { State } from '../../State';
3
+ import { tagMessage } from '../../utils';
3
4
 
4
5
  export interface GestureStateManagerType {
5
6
  begin: () => void;
@@ -8,6 +9,10 @@ export interface GestureStateManagerType {
8
9
  end: () => void;
9
10
  }
10
11
 
12
+ const warningMessage = tagMessage(
13
+ 'react-native-reanimated is required in order to use synchronous state management'
14
+ );
15
+
11
16
  export const GestureStateManager = {
12
17
  create(handlerTag: number): GestureStateManagerType {
13
18
  'worklet';
@@ -17,9 +22,7 @@ export const GestureStateManager = {
17
22
  if (Reanimated) {
18
23
  Reanimated.setGestureState(handlerTag, State.BEGAN);
19
24
  } else {
20
- console.warn(
21
- 'react-native-reanimated is required in order to use synchronous state management'
22
- );
25
+ console.warn(warningMessage);
23
26
  }
24
27
  },
25
28
 
@@ -28,9 +31,7 @@ export const GestureStateManager = {
28
31
  if (Reanimated) {
29
32
  Reanimated.setGestureState(handlerTag, State.ACTIVE);
30
33
  } else {
31
- console.warn(
32
- 'react-native-reanimated is required in order to use synchronous state management'
33
- );
34
+ console.warn(warningMessage);
34
35
  }
35
36
  },
36
37
 
@@ -39,9 +40,7 @@ export const GestureStateManager = {
39
40
  if (Reanimated) {
40
41
  Reanimated.setGestureState(handlerTag, State.FAILED);
41
42
  } else {
42
- console.warn(
43
- 'react-native-reanimated is required in order to use synchronous state management'
44
- );
43
+ console.warn(warningMessage);
45
44
  }
46
45
  },
47
46
 
@@ -50,9 +49,7 @@ export const GestureStateManager = {
50
49
  if (Reanimated) {
51
50
  Reanimated.setGestureState(handlerTag, State.END);
52
51
  } else {
53
- console.warn(
54
- 'react-native-reanimated is required in order to use synchronous state management'
55
- );
52
+ console.warn(warningMessage);
56
53
  }
57
54
  },
58
55
  };
@@ -5,7 +5,7 @@ import {
5
5
  PanGestureHandlerEventPayload,
6
6
  } from '../PanGestureHandler';
7
7
 
8
- type PanGestureChangeEventPayload = {
8
+ export type PanGestureChangeEventPayload = {
9
9
  changeX: number;
10
10
  changeY: number;
11
11
  };
@@ -2,7 +2,7 @@ import { ContinousBaseGesture } from './gesture';
2
2
  import { PinchGestureHandlerEventPayload } from '../PinchGestureHandler';
3
3
  import { GestureUpdateEvent } from '../gestureHandlerCommon';
4
4
 
5
- type PinchGestureChangeEventPayload = {
5
+ export type PinchGestureChangeEventPayload = {
6
6
  scaleChange: number;
7
7
  };
8
8
 
@@ -3,6 +3,7 @@ import {
3
3
  GestureUpdateEvent,
4
4
  GestureStateChangeEvent,
5
5
  } from '../gestureHandlerCommon';
6
+ import { tagMessage } from '../../utils';
6
7
 
7
8
  export interface SharedValue<T> {
8
9
  value: T;
@@ -33,7 +34,9 @@ try {
33
34
  Reanimated.setGestureState = () => {
34
35
  'worklet';
35
36
  console.warn(
36
- 'Please use newer version of react-native-reanimated in order to control state of the gestures.'
37
+ tagMessage(
38
+ 'Please use newer version of react-native-reanimated in order to control state of the gestures.'
39
+ )
37
40
  );
38
41
  };
39
42
  }
@@ -1,7 +1,11 @@
1
+ import { isJestEnv } from '../utils';
1
2
  import { GestureType } from './gestures/gesture';
3
+ import { GestureEvent, HandlerStateChangeEvent } from './gestureHandlerCommon';
2
4
 
3
5
  export const handlerIDToTag: Record<string, number> = {};
4
- const handlers = new Map<number, GestureType>();
6
+ const gestures = new Map<number, GestureType>();
7
+ const oldHandlers = new Map<number, GestureHandlerCallbacks>();
8
+ const testIDs = new Map<string, number>();
5
9
 
6
10
  let handlerTag = 1;
7
11
 
@@ -9,14 +13,48 @@ export function getNextHandlerTag(): number {
9
13
  return handlerTag++;
10
14
  }
11
15
 
12
- export function registerHandler(handlerTag: number, handler: GestureType) {
13
- handlers.set(handlerTag, handler);
16
+ export function registerHandler(
17
+ handlerTag: number,
18
+ handler: GestureType,
19
+ testID?: string
20
+ ) {
21
+ gestures.set(handlerTag, handler);
22
+ if (isJestEnv() && testID) {
23
+ testIDs.set(testID, handlerTag);
24
+ }
14
25
  }
15
26
 
16
- export function unregisterHandler(handlerTag: number) {
17
- handlers.delete(handlerTag);
27
+ export function registerOldGestureHandler(
28
+ handlerTag: number,
29
+ handler: GestureHandlerCallbacks
30
+ ) {
31
+ oldHandlers.set(handlerTag, handler);
32
+ }
33
+
34
+ export function unregisterHandler(handlerTag: number, testID?: string) {
35
+ gestures.delete(handlerTag);
36
+ if (isJestEnv() && testID) {
37
+ testIDs.delete(testID);
38
+ }
18
39
  }
19
40
 
20
41
  export function findHandler(handlerTag: number) {
21
- return handlers.get(handlerTag);
42
+ return gestures.get(handlerTag);
43
+ }
44
+
45
+ export function findOldGestureHandler(handlerTag: number) {
46
+ return oldHandlers.get(handlerTag);
47
+ }
48
+
49
+ export function findHandlerByTestID(testID: string) {
50
+ const handlerTag = testIDs.get(testID);
51
+ if (handlerTag !== undefined) {
52
+ return findHandler(handlerTag) ?? null;
53
+ }
54
+ return null;
55
+ }
56
+
57
+ export interface GestureHandlerCallbacks {
58
+ onGestureEvent: (event: GestureEvent<any>) => void;
59
+ onGestureStateChange: (event: HandlerStateChangeEvent<any>) => void;
22
60
  }
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import { initialize } from './init';
2
2
 
3
3
  export { Directions } from './Directions';
4
4
  export { State } from './State';
5
+ export { getByGestureTestId, fireGestureHandler } from './jestUtils';
5
6
  export { default as gestureHandlerRootHOC } from './gestureHandlerRootHOC';
6
7
  export { default as GestureHandlerRootView } from './GestureHandlerRootView';
7
8
  export type {
@@ -27,6 +28,7 @@ export type {
27
28
  ForceTouchGestureHandlerEventPayload,
28
29
  ForceTouchGestureHandlerProps,
29
30
  } from './handlers/ForceTouchGestureHandler';
31
+ export type { ForceTouchGestureChangeEventPayload } from './handlers/gestures/forceTouchGesture';
30
32
  export type {
31
33
  LongPressGestureHandlerEventPayload,
32
34
  LongPressGestureHandlerProps,
@@ -35,10 +37,12 @@ export type {
35
37
  PanGestureHandlerEventPayload,
36
38
  PanGestureHandlerProps,
37
39
  } from './handlers/PanGestureHandler';
40
+ export type { PanGestureChangeEventPayload } from './handlers/gestures/panGesture';
38
41
  export type {
39
42
  PinchGestureHandlerEventPayload,
40
43
  PinchGestureHandlerProps,
41
44
  } from './handlers/PinchGestureHandler';
45
+ export type { PinchGestureChangeEventPayload } from './handlers/gestures/pinchGesture';
42
46
  export type {
43
47
  RotationGestureHandlerEventPayload,
44
48
  RotationGestureHandlerProps,
package/src/init.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { startListening } from './handlers/gestures/eventReceiver';
2
+ import RNGestureHandlerModule from './RNGestureHandlerModule';
3
+ import { isFabric } from './utils';
2
4
 
3
5
  export function initialize() {
4
6
  startListening();
7
+
8
+ if (isFabric()) {
9
+ RNGestureHandlerModule.install();
10
+ }
5
11
  }