react-native-gesture-handler 2.32.0 → 2.33.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 (293) hide show
  1. package/android/build.gradle +27 -11
  2. package/android/gradle.properties +1 -1
  3. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerRootViewManagerDelegate.java +3 -0
  4. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerRootViewManagerInterface.java +2 -0
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt +1 -1
  6. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +41 -36
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +149 -23
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +1 -0
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +6 -3
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt +23 -0
  11. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +4 -7
  12. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +1 -1
  13. package/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.kt +3 -0
  14. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +2 -0
  15. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +11 -1
  16. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +8 -6
  17. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootViewManager.kt +6 -0
  18. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerTouchEvent.kt +2 -7
  19. package/apple/Handlers/RNFlingHandler.m +44 -4
  20. package/apple/Handlers/RNHoverHandler.m +24 -26
  21. package/apple/Handlers/RNLongPressHandler.m +4 -0
  22. package/apple/Handlers/RNPanHandler.m +44 -7
  23. package/apple/Handlers/RNTapHandler.m +35 -4
  24. package/apple/RNGHUIKit.h +10 -10
  25. package/apple/RNGestureHandler.h +2 -0
  26. package/apple/RNGestureHandler.mm +62 -9
  27. package/apple/RNGestureHandlerButton.mm +5 -3
  28. package/apple/RNGestureHandlerButtonComponentView.mm +6 -0
  29. package/apple/RNGestureHandlerManager.mm +63 -6
  30. package/apple/RNGestureHandlerModule.mm +20 -0
  31. package/apple/RNGestureHandlerPointerTracker.m +64 -10
  32. package/apple/RNGestureHandlerPointerType.h +1 -0
  33. package/apple/RNManualActivationRecognizer.m +25 -6
  34. package/lib/commonjs/components/GestureComponents.js +21 -1
  35. package/lib/commonjs/components/GestureComponents.js.map +1 -1
  36. package/lib/commonjs/components/GestureHandlerButton.web.js +2 -1
  37. package/lib/commonjs/components/GestureHandlerButton.web.js.map +1 -1
  38. package/lib/commonjs/components/Pressable/Pressable.js +28 -3
  39. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  40. package/lib/commonjs/components/Pressable/index.js.map +1 -1
  41. package/lib/commonjs/components/ReanimatedDrawerLayout.js +4 -2
  42. package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -1
  43. package/lib/commonjs/components/ReanimatedSwipeable/ReanimatedSwipeable.js +32 -9
  44. package/lib/commonjs/components/ReanimatedSwipeable/ReanimatedSwipeable.js.map +1 -1
  45. package/lib/commonjs/components/Swipeable.js.map +1 -1
  46. package/lib/commonjs/components/Text.js.map +1 -1
  47. package/lib/commonjs/components/touchables/TouchableHighlight.js +1 -1
  48. package/lib/commonjs/components/touchables/TouchableHighlight.js.map +1 -1
  49. package/lib/commonjs/components/touchables/TouchableNativeFeedback.android.js.map +1 -1
  50. package/lib/commonjs/components/touchables/TouchableOpacity.js +1 -0
  51. package/lib/commonjs/components/touchables/TouchableOpacity.js.map +1 -1
  52. package/lib/commonjs/getShadowNodeFromRef.js +6 -2
  53. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
  54. package/lib/commonjs/handlers/PanGestureHandler.js.map +1 -1
  55. package/lib/commonjs/handlers/createHandler.js +1 -1
  56. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  57. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js +66 -11
  58. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js.map +1 -1
  59. package/lib/commonjs/handlers/gestures/GestureDetector/attachHandlers.js +8 -1
  60. package/lib/commonjs/handlers/gestures/GestureDetector/attachHandlers.js.map +1 -1
  61. package/lib/commonjs/handlers/gestures/GestureDetector/index.js +7 -2
  62. package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
  63. package/lib/commonjs/handlers/gestures/GestureDetector/updateHandlers.js +7 -0
  64. package/lib/commonjs/handlers/gestures/GestureDetector/updateHandlers.js.map +1 -1
  65. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -1
  66. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  67. package/lib/commonjs/handlers/gestures/GestureDetector/useMountReactions.js +28 -3
  68. package/lib/commonjs/handlers/gestures/GestureDetector/useMountReactions.js.map +1 -1
  69. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +3 -2
  70. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  71. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +35 -6
  72. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -1
  73. package/lib/commonjs/handlers/gestures/gesture.js +8 -0
  74. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  75. package/lib/commonjs/handlers/gestures/gestureComposition.js +14 -2
  76. package/lib/commonjs/handlers/gestures/gestureComposition.js.map +1 -1
  77. package/lib/commonjs/handlers/gestures/gestureStateManager.web.js.map +1 -1
  78. package/lib/commonjs/handlers/gestures/panGesture.js +6 -3
  79. package/lib/commonjs/handlers/gestures/panGesture.js.map +1 -1
  80. package/lib/commonjs/handlers/gestures/reanimatedWrapper.js +23 -0
  81. package/lib/commonjs/handlers/gestures/reanimatedWrapper.js.map +1 -1
  82. package/lib/commonjs/hostInstance.js +39 -0
  83. package/lib/commonjs/hostInstance.js.map +1 -0
  84. package/lib/commonjs/index.js.map +1 -1
  85. package/lib/commonjs/mocks/mocks.js +1 -0
  86. package/lib/commonjs/mocks/mocks.js.map +1 -1
  87. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  88. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  89. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.ts +13 -4
  90. package/lib/commonjs/web/detectors/RotationGestureDetector.js +1 -1
  91. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +3 -1
  92. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  93. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +9 -1
  94. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  95. package/lib/commonjs/web/handlers/PanGestureHandler.js +8 -9
  96. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  97. package/lib/commonjs/web/handlers/TapGestureHandler.js +1 -1
  98. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +14 -0
  99. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  100. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +5 -1
  101. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  102. package/lib/commonjs/web/tools/KeyboardEventManager.js +17 -12
  103. package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -1
  104. package/lib/commonjs/web/tools/WheelEventManager.js +19 -5
  105. package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -1
  106. package/lib/module/components/GestureComponents.js +23 -2
  107. package/lib/module/components/GestureComponents.js.map +1 -1
  108. package/lib/module/components/GestureHandlerButton.web.js +2 -1
  109. package/lib/module/components/GestureHandlerButton.web.js.map +1 -1
  110. package/lib/module/components/Pressable/Pressable.js +28 -3
  111. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  112. package/lib/module/components/Pressable/index.js.map +1 -1
  113. package/lib/module/components/ReanimatedDrawerLayout.js +4 -2
  114. package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -1
  115. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js +34 -11
  116. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js.map +1 -1
  117. package/lib/module/components/Swipeable.js.map +1 -1
  118. package/lib/module/components/Text.js.map +1 -1
  119. package/lib/module/components/touchables/TouchableHighlight.js +2 -2
  120. package/lib/module/components/touchables/TouchableHighlight.js.map +1 -1
  121. package/lib/module/components/touchables/TouchableNativeFeedback.android.js.map +1 -1
  122. package/lib/module/components/touchables/TouchableOpacity.js +1 -0
  123. package/lib/module/components/touchables/TouchableOpacity.js.map +1 -1
  124. package/lib/module/getShadowNodeFromRef.js +7 -2
  125. package/lib/module/getShadowNodeFromRef.js.map +1 -1
  126. package/lib/module/handlers/PanGestureHandler.js.map +1 -1
  127. package/lib/module/handlers/createHandler.js +1 -1
  128. package/lib/module/handlers/createHandler.js.map +1 -1
  129. package/lib/module/handlers/gestures/GestureDetector/Wrap.js +67 -12
  130. package/lib/module/handlers/gestures/GestureDetector/Wrap.js.map +1 -1
  131. package/lib/module/handlers/gestures/GestureDetector/attachHandlers.js +9 -2
  132. package/lib/module/handlers/gestures/GestureDetector/attachHandlers.js.map +1 -1
  133. package/lib/module/handlers/gestures/GestureDetector/index.js +7 -2
  134. package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
  135. package/lib/module/handlers/gestures/GestureDetector/updateHandlers.js +8 -1
  136. package/lib/module/handlers/gestures/GestureDetector/updateHandlers.js.map +1 -1
  137. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -1
  138. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  139. package/lib/module/handlers/gestures/GestureDetector/useMountReactions.js +28 -3
  140. package/lib/module/handlers/gestures/GestureDetector/useMountReactions.js.map +1 -1
  141. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +3 -2
  142. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  143. package/lib/module/handlers/gestures/GestureDetector/utils.js +34 -6
  144. package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
  145. package/lib/module/handlers/gestures/gesture.js +8 -0
  146. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  147. package/lib/module/handlers/gestures/gestureComposition.js +14 -2
  148. package/lib/module/handlers/gestures/gestureComposition.js.map +1 -1
  149. package/lib/module/handlers/gestures/gestureStateManager.web.js.map +1 -1
  150. package/lib/module/handlers/gestures/panGesture.js +6 -3
  151. package/lib/module/handlers/gestures/panGesture.js.map +1 -1
  152. package/lib/module/handlers/gestures/reanimatedWrapper.js +22 -0
  153. package/lib/module/handlers/gestures/reanimatedWrapper.js.map +1 -1
  154. package/lib/module/hostInstance.js +32 -0
  155. package/lib/module/hostInstance.js.map +1 -0
  156. package/lib/module/index.js.map +1 -1
  157. package/lib/module/mocks/mocks.js +3 -2
  158. package/lib/module/mocks/mocks.js.map +1 -1
  159. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  160. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  161. package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.ts +13 -4
  162. package/lib/module/web/detectors/RotationGestureDetector.js +1 -1
  163. package/lib/module/web/handlers/LongPressGestureHandler.js +3 -1
  164. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  165. package/lib/module/web/handlers/NativeViewGestureHandler.js +9 -1
  166. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  167. package/lib/module/web/handlers/PanGestureHandler.js +8 -9
  168. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  169. package/lib/module/web/handlers/TapGestureHandler.js +1 -1
  170. package/lib/module/web/tools/GestureHandlerOrchestrator.js +14 -0
  171. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  172. package/lib/module/web/tools/GestureHandlerWebDelegate.js +5 -1
  173. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  174. package/lib/module/web/tools/KeyboardEventManager.js +17 -12
  175. package/lib/module/web/tools/KeyboardEventManager.js.map +1 -1
  176. package/lib/module/web/tools/WheelEventManager.js +19 -5
  177. package/lib/module/web/tools/WheelEventManager.js.map +1 -1
  178. package/lib/typescript/components/GestureButtons.d.ts +3 -1
  179. package/lib/typescript/components/GestureButtons.d.ts.map +1 -1
  180. package/lib/typescript/components/GestureButtonsProps.d.ts +10 -0
  181. package/lib/typescript/components/GestureButtonsProps.d.ts.map +1 -1
  182. package/lib/typescript/components/GestureComponents.d.ts +8 -7
  183. package/lib/typescript/components/GestureComponents.d.ts.map +1 -1
  184. package/lib/typescript/components/GestureComponents.web.d.ts +12 -4
  185. package/lib/typescript/components/GestureComponents.web.d.ts.map +1 -1
  186. package/lib/typescript/components/GestureHandlerButton.web.d.ts +2 -2
  187. package/lib/typescript/components/GestureHandlerButton.web.d.ts.map +1 -1
  188. package/lib/typescript/components/Pressable/Pressable.d.ts.map +1 -1
  189. package/lib/typescript/components/Pressable/PressableProps.d.ts +1 -1
  190. package/lib/typescript/components/Pressable/PressableProps.d.ts.map +1 -1
  191. package/lib/typescript/components/Pressable/index.d.ts +1 -1
  192. package/lib/typescript/components/Pressable/index.d.ts.map +1 -1
  193. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts.map +1 -1
  194. package/lib/typescript/components/ReanimatedSwipeable/ReanimatedSwipeable.d.ts.map +1 -1
  195. package/lib/typescript/components/Swipeable.d.ts.map +1 -1
  196. package/lib/typescript/components/touchables/TouchableHighlight.d.ts +1 -1
  197. package/lib/typescript/components/touchables/TouchableHighlight.d.ts.map +1 -1
  198. package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts +1 -1
  199. package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts.map +1 -1
  200. package/lib/typescript/components/touchables/TouchableOpacity.d.ts.map +1 -1
  201. package/lib/typescript/getShadowNodeFromRef.d.ts.map +1 -1
  202. package/lib/typescript/handlers/PanGestureHandler.d.ts +12 -0
  203. package/lib/typescript/handlers/PanGestureHandler.d.ts.map +1 -1
  204. package/lib/typescript/handlers/createHandler.d.ts.map +1 -1
  205. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.d.ts +12 -0
  206. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.d.ts.map +1 -1
  207. package/lib/typescript/handlers/gestures/GestureDetector/attachHandlers.d.ts.map +1 -1
  208. package/lib/typescript/handlers/gestures/GestureDetector/index.d.ts.map +1 -1
  209. package/lib/typescript/handlers/gestures/GestureDetector/types.d.ts +1 -0
  210. package/lib/typescript/handlers/gestures/GestureDetector/types.d.ts.map +1 -1
  211. package/lib/typescript/handlers/gestures/GestureDetector/updateHandlers.d.ts.map +1 -1
  212. package/lib/typescript/handlers/gestures/GestureDetector/useDetectorUpdater.d.ts.map +1 -1
  213. package/lib/typescript/handlers/gestures/GestureDetector/useMountReactions.d.ts.map +1 -1
  214. package/lib/typescript/handlers/gestures/GestureDetector/useViewRefHandler.d.ts.map +1 -1
  215. package/lib/typescript/handlers/gestures/GestureDetector/utils.d.ts +5 -4
  216. package/lib/typescript/handlers/gestures/GestureDetector/utils.d.ts.map +1 -1
  217. package/lib/typescript/handlers/gestures/gesture.d.ts +4 -0
  218. package/lib/typescript/handlers/gestures/gesture.d.ts.map +1 -1
  219. package/lib/typescript/handlers/gestures/gestureComposition.d.ts.map +1 -1
  220. package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts +8 -1
  221. package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts.map +1 -1
  222. package/lib/typescript/handlers/gestures/panGesture.d.ts +6 -3
  223. package/lib/typescript/handlers/gestures/panGesture.d.ts.map +1 -1
  224. package/lib/typescript/handlers/gestures/reanimatedWrapper.d.ts +1 -0
  225. package/lib/typescript/handlers/gestures/reanimatedWrapper.d.ts.map +1 -1
  226. package/lib/typescript/hostInstance.d.ts +10 -0
  227. package/lib/typescript/hostInstance.d.ts.map +1 -0
  228. package/lib/typescript/index.d.ts +1 -1
  229. package/lib/typescript/index.d.ts.map +1 -1
  230. package/lib/typescript/mocks/mocks.d.ts +67 -15
  231. package/lib/typescript/mocks/mocks.d.ts.map +1 -1
  232. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +6 -7
  233. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts.map +1 -1
  234. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +9 -10
  235. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts.map +1 -1
  236. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +2 -2
  237. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts.map +1 -1
  238. package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts.map +1 -1
  239. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  240. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts.map +1 -1
  241. package/lib/typescript/web/handlers/PanGestureHandler.d.ts.map +1 -1
  242. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +1 -0
  243. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts.map +1 -1
  244. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts.map +1 -1
  245. package/lib/typescript/web/tools/KeyboardEventManager.d.ts +2 -1
  246. package/lib/typescript/web/tools/KeyboardEventManager.d.ts.map +1 -1
  247. package/lib/typescript/web/tools/WheelEventManager.d.ts.map +1 -1
  248. package/package.json +7 -7
  249. package/src/components/GestureButtonsProps.ts +14 -0
  250. package/src/components/GestureComponents.tsx +38 -7
  251. package/src/components/GestureHandlerButton.web.tsx +7 -3
  252. package/src/components/Pressable/Pressable.tsx +33 -4
  253. package/src/components/Pressable/PressableProps.tsx +1 -1
  254. package/src/components/Pressable/index.ts +1 -0
  255. package/src/components/ReanimatedDrawerLayout.tsx +4 -1
  256. package/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx +49 -10
  257. package/src/components/Swipeable.tsx +6 -2
  258. package/src/components/Text.tsx +3 -3
  259. package/src/components/touchables/TouchableHighlight.tsx +4 -2
  260. package/src/components/touchables/TouchableNativeFeedback.android.tsx +8 -2
  261. package/src/components/touchables/TouchableOpacity.tsx +1 -0
  262. package/src/getShadowNodeFromRef.ts +11 -4
  263. package/src/handlers/PanGestureHandler.ts +15 -0
  264. package/src/handlers/createHandler.tsx +4 -1
  265. package/src/handlers/gestures/GestureDetector/Wrap.tsx +95 -14
  266. package/src/handlers/gestures/GestureDetector/attachHandlers.ts +11 -2
  267. package/src/handlers/gestures/GestureDetector/index.tsx +8 -1
  268. package/src/handlers/gestures/GestureDetector/types.ts +3 -0
  269. package/src/handlers/gestures/GestureDetector/updateHandlers.ts +8 -0
  270. package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +4 -1
  271. package/src/handlers/gestures/GestureDetector/useMountReactions.ts +35 -4
  272. package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +5 -2
  273. package/src/handlers/gestures/GestureDetector/utils.ts +42 -10
  274. package/src/handlers/gestures/gesture.ts +11 -0
  275. package/src/handlers/gestures/gestureComposition.ts +15 -2
  276. package/src/handlers/gestures/gestureStateManager.web.ts +9 -1
  277. package/src/handlers/gestures/panGesture.ts +6 -3
  278. package/src/handlers/gestures/reanimatedWrapper.ts +23 -0
  279. package/src/hostInstance.ts +57 -0
  280. package/src/index.ts +1 -0
  281. package/src/mocks/mocks.tsx +6 -2
  282. package/src/specs/NativeRNGestureHandlerModule.ts +16 -10
  283. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  284. package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +13 -4
  285. package/src/web/detectors/RotationGestureDetector.ts +1 -1
  286. package/src/web/handlers/LongPressGestureHandler.ts +3 -1
  287. package/src/web/handlers/NativeViewGestureHandler.ts +11 -2
  288. package/src/web/handlers/PanGestureHandler.ts +8 -11
  289. package/src/web/handlers/TapGestureHandler.ts +1 -1
  290. package/src/web/tools/GestureHandlerOrchestrator.ts +19 -0
  291. package/src/web/tools/GestureHandlerWebDelegate.ts +6 -1
  292. package/src/web/tools/KeyboardEventManager.ts +20 -18
  293. package/src/web/tools/WheelEventManager.ts +15 -5
@@ -554,6 +554,8 @@ class RNGestureHandlerButtonViewManager :
554
554
  // by default Viewgroup would pass hotspot change events
555
555
  }
556
556
 
557
+ override fun shouldDelayChildPressedState(): Boolean = false
558
+
557
559
  private fun findGestureHandlerRootView(): RNGestureHandlerRootView? {
558
560
  var parent: ViewParent? = this.parent
559
561
  var gestureHandlerRootView: RNGestureHandlerRootView? = null
@@ -19,6 +19,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
19
19
  private val jsGestureHandler: GestureHandler?
20
20
  val rootView: ViewGroup
21
21
  private var shouldIntercept = false
22
+ private var wasIntercepting = false
22
23
  private var passingTouch = false
23
24
 
24
25
  init {
@@ -118,6 +119,14 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
118
119
  passingTouch = true
119
120
  orchestrator!!.onTouchEvent(event)
120
121
  passingTouch = false
122
+
123
+ // On the transition into interception, cancel the native views the pointers landed on - the
124
+ // framework's ACTION_CANCEL never reaches them since RNGH ignores `onInterceptTouchEvent`
125
+ if (shouldIntercept && !wasIntercepting) {
126
+ orchestrator!!.cancelTouchesInInterceptedViews(event)
127
+ }
128
+ wasIntercepting = shouldIntercept
129
+
121
130
  return shouldIntercept
122
131
  }
123
132
 
@@ -146,7 +155,8 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
146
155
  }
147
156
 
148
157
  companion object {
149
- private const val MIN_ALPHA_FOR_TOUCH = 0.1f
158
+ // Same threshold as UIKit / RCTViewComponentView hit testing on iOS.
159
+ private const val MIN_ALPHA_FOR_TOUCH = 0.01f
150
160
  private fun findRootViewTag(viewGroup: ViewGroup): ViewGroup {
151
161
  UiThreadUtil.assertOnUiThread()
152
162
  var parent: ViewParent? = viewGroup
@@ -40,12 +40,14 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
40
40
  super.dispatchTouchEvent(event)
41
41
  }
42
42
 
43
- override fun dispatchGenericMotionEvent(ev: MotionEvent) =
44
- if (rootViewEnabled && ev.isHoverAction() && rootHelper!!.dispatchTouchEvent(ev)) {
45
- true
46
- } else {
47
- super.dispatchGenericMotionEvent(ev)
48
- }
43
+ override fun dispatchGenericMotionEvent(ev: MotionEvent) = if (rootViewEnabled &&
44
+ (ev.isHoverAction() || ev.isButtonAction()) &&
45
+ rootHelper!!.dispatchTouchEvent(ev)
46
+ ) {
47
+ true
48
+ } else {
49
+ super.dispatchGenericMotionEvent(ev)
50
+ }
49
51
 
50
52
  override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
51
53
  if (rootViewEnabled) {
@@ -1,6 +1,7 @@
1
1
  package com.swmansion.gesturehandler.react
2
2
 
3
3
  import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.PointerEvents.Companion.parsePointerEvents
4
5
  import com.facebook.react.uimanager.ThemedReactContext
5
6
  import com.facebook.react.uimanager.ViewGroupManager
6
7
  import com.facebook.react.uimanager.ViewManagerDelegate
@@ -33,6 +34,11 @@ class RNGestureHandlerRootViewManager :
33
34
  view.tearDown()
34
35
  }
35
36
 
37
+ @ReactProp(name = "pointerEvents")
38
+ override fun setPointerEvents(view: RNGestureHandlerRootView, pointerEventsStr: String?) {
39
+ view.pointerEvents = parsePointerEvents(pointerEventsStr)
40
+ }
41
+
36
42
  @ReactProp(name = "unstable_forceActive")
37
43
  override fun setUnstable_forceActive(view: RNGestureHandlerRootView, active: Boolean) {
38
44
  view.setUnstableForceActive(active)
@@ -54,13 +54,8 @@ class RNGestureHandlerTouchEvent private constructor() : Event<RNGestureHandlerT
54
54
  putInt("eventType", handler.touchEventType)
55
55
  putInt("pointerType", handler.pointerType)
56
56
 
57
- handler.consumeChangedTouchesPayload()?.let {
58
- putArray("changedTouches", it)
59
- }
60
-
61
- handler.consumeAllTouchesPayload()?.let {
62
- putArray("allTouches", it)
63
- }
57
+ putArray("changedTouches", handler.consumeChangedTouchesPayload() ?: Arguments.createArray())
58
+ putArray("allTouches", handler.consumeAllTouchesPayload() ?: Arguments.createArray())
64
59
 
65
60
  if (handler.isAwaiting && handler.state == GestureHandler.STATE_ACTIVE) {
66
61
  putInt("state", GestureHandler.STATE_BEGAN)
@@ -95,7 +95,8 @@
95
95
  #else
96
96
 
97
97
  @interface RNBetterSwipeGestureRecognizer : NSGestureRecognizer {
98
- dispatch_block_t failFlingAction;
98
+ // scheduled on mouseDown; fails the gesture if the fling doesn't complete within maxDuration
99
+ dispatch_block_t maxDurationTimeout;
99
100
  int maxDuration;
100
101
  int minVelocity;
101
102
  double defaultAlignmentCone;
@@ -137,18 +138,34 @@
137
138
  [_gestureHandler handleGesture:self];
138
139
  }
139
140
 
141
+ - (void)triggerAction
142
+ {
143
+ [_gestureHandler handleGesture:self fromReset:NO];
144
+ }
145
+
146
+ - (void)triggerActionFromReset
147
+ {
148
+ [_gestureHandler handleGesture:self fromReset:YES];
149
+ }
150
+
140
151
  - (void)mouseDown:(NSEvent *)event
141
152
  {
153
+ [_gestureHandler setCurrentPointerTypeToMouse];
154
+ [_gestureHandler reset];
142
155
  [super mouseDown:event];
143
156
 
144
157
  startPosition = [self locationInView:self.view];
145
158
  startTime = CACurrentMediaTime();
146
159
 
160
+ [_gestureHandler.pointerTracker touchesBegan:[NSSet setWithObject:event] withEvent:event];
161
+ // Send the BEGAN event, mirroring what the iOS recognizer does in touchesBegan.
162
+ [self triggerAction];
163
+
147
164
  self.state = NSGestureRecognizerStatePossible;
148
165
 
149
166
  __weak typeof(self) weakSelf = self;
150
167
 
151
- failFlingAction = dispatch_block_create(0, ^{
168
+ maxDurationTimeout = dispatch_block_create(0, ^{
152
169
  __strong typeof(self) strongSelf = weakSelf;
153
170
 
154
171
  if (strongSelf) {
@@ -159,13 +176,15 @@
159
176
  dispatch_after(
160
177
  dispatch_time(DISPATCH_TIME_NOW, (int64_t)(maxDuration * NSEC_PER_SEC)),
161
178
  dispatch_get_main_queue(),
162
- failFlingAction);
179
+ maxDurationTimeout);
163
180
  }
164
181
 
165
182
  - (void)mouseDragged:(NSEvent *)event
166
183
  {
167
184
  [super mouseDragged:event];
168
185
 
186
+ [_gestureHandler.pointerTracker touchesMoved:[NSSet setWithObject:event] withEvent:event];
187
+
169
188
  NSPoint currentPosition = [self locationInView:self.view];
170
189
  double currentTime = CACurrentMediaTime();
171
190
 
@@ -180,16 +199,37 @@
180
199
  [self tryActivate:velocityVector];
181
200
  }
182
201
 
202
+ - (void)cancelMaxDurationTimeout
203
+ {
204
+ if (maxDurationTimeout != nil) {
205
+ dispatch_block_cancel(maxDurationTimeout);
206
+ maxDurationTimeout = nil;
207
+ }
208
+ }
209
+
183
210
  - (void)mouseUp:(NSEvent *)event
184
211
  {
185
212
  [super mouseUp:event];
186
213
 
187
- dispatch_block_cancel(failFlingAction);
214
+ [_gestureHandler.pointerTracker touchesEnded:[NSSet setWithObject:event] withEvent:event];
215
+
216
+ [self cancelMaxDurationTimeout];
188
217
 
189
218
  self.state =
190
219
  self.state == NSGestureRecognizerStateChanged ? NSGestureRecognizerStateEnded : NSGestureRecognizerStateFailed;
191
220
  }
192
221
 
222
+ - (void)reset
223
+ {
224
+ [self triggerActionFromReset];
225
+ [_gestureHandler.pointerTracker reset];
226
+ // The gesture may end without a mouse-up (view unmount, cancellation) — a still-scheduled
227
+ // timeout would fire later and set the state to Failed during the next gesture.
228
+ [self cancelMaxDurationTimeout];
229
+ [super reset];
230
+ [_gestureHandler reset];
231
+ }
232
+
193
233
  - (void)tryActivate:(Vector *)velocityVector
194
234
  {
195
235
  bool isAligned = NO;
@@ -132,8 +132,9 @@ API_AVAILABLE(ios(13.4))
132
132
  {
133
133
  #if CHECK_TARGET(13_4)
134
134
  if (@available(iOS 13.4, *)) {
135
- [super unbindFromView];
135
+ // Remove the interaction before [super unbindFromView] detaches the recognizer and nils recognizer.view.
136
136
  [self.recognizer.view removeInteraction:_pointerInteraction];
137
+ [super unbindFromView];
137
138
  }
138
139
  #endif
139
140
  }
@@ -218,33 +219,30 @@ API_AVAILABLE(ios(13.4))
218
219
  _view = nil;
219
220
  }
220
221
 
222
+ - (RNGestureHandlerEventExtraData *)extraDataForEvent:(NSEvent *)event
223
+ {
224
+ CGPoint windowLocation = [event locationInWindow];
225
+ CGPoint relativePos = [_view convertPoint:windowLocation fromView:nil];
226
+ CGPoint absolutePos = [_view.window.contentView convertPoint:windowLocation fromView:nil];
227
+
228
+ return [RNGestureHandlerEventExtraData forPosition:relativePos
229
+ withAbsolutePosition:absolutePos
230
+ withNumberOfTouches:1
231
+ withPointerType:_pointerType];
232
+ }
233
+
221
234
  - (void)mouseEntered:(NSEvent *)event
222
235
  {
223
- [self sendEventsInState:RNGestureHandlerStateBegan
224
- forViewWithTag:_view.reactTag
225
- withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
226
- withNumberOfTouches:1
227
- withPointerType:_pointerType]];
228
- [self sendEventsInState:RNGestureHandlerStateActive
229
- forViewWithTag:_view.reactTag
230
- withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
231
- withNumberOfTouches:1
232
- withPointerType:_pointerType]];
233
- }
234
-
235
- - (void)mouseExited:(NSEvent *)theEvent
236
- {
237
- [self sendEventsInState:RNGestureHandlerStateEnd
238
- forViewWithTag:_view.reactTag
239
- withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
240
- withNumberOfTouches:1
241
- withPointerType:_pointerType]];
242
-
243
- [self sendEventsInState:RNGestureHandlerStateUndetermined
244
- forViewWithTag:_view.reactTag
245
- withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
246
- withNumberOfTouches:1
247
- withPointerType:_pointerType]];
236
+ RNGestureHandlerEventExtraData *extraData = [self extraDataForEvent:event];
237
+ [self sendEventsInState:RNGestureHandlerStateBegan forViewWithTag:_view.reactTag withExtraData:extraData];
238
+ [self sendEventsInState:RNGestureHandlerStateActive forViewWithTag:_view.reactTag withExtraData:extraData];
239
+ }
240
+
241
+ - (void)mouseExited:(NSEvent *)event
242
+ {
243
+ RNGestureHandlerEventExtraData *extraData = [self extraDataForEvent:event];
244
+ [self sendEventsInState:RNGestureHandlerStateEnd forViewWithTag:_view.reactTag withExtraData:extraData];
245
+ [self sendEventsInState:RNGestureHandlerStateUndetermined forViewWithTag:_view.reactTag withExtraData:extraData];
248
246
  }
249
247
 
250
248
  @end
@@ -225,6 +225,10 @@
225
225
 
226
226
  recognizer.minimumPressDuration = 0.5;
227
227
  recognizer.allowableMovement = 10;
228
+
229
+ #if !TARGET_OS_TV
230
+ recognizer.numberOfTouchesRequired = 1;
231
+ #endif
228
232
  }
229
233
 
230
234
  - (void)configure:(NSDictionary *)config
@@ -42,7 +42,9 @@
42
42
 
43
43
  @implementation RNBetterPanGestureRecognizer {
44
44
  __weak RNGestureHandler *_gestureHandler;
45
- #if !TARGET_OS_OSX
45
+ #if TARGET_OS_OSX
46
+ BOOL _blockAutomaticActivation;
47
+ #else
46
48
  NSUInteger _realMinimumNumberOfTouches;
47
49
  #endif
48
50
  BOOL _hasCustomActivationCriteria;
@@ -114,6 +116,9 @@
114
116
 
115
117
  - (void)activateAfterLongPress
116
118
  {
119
+ #if TARGET_OS_OSX
120
+ _blockAutomaticActivation = NO;
121
+ #endif
117
122
  self.state = UIGestureRecognizerStateBegan;
118
123
  // Send event in ACTIVE state because UIGestureRecognizerStateBegan is mapped to RNGestureHandlerStateBegan
119
124
  [_gestureHandler handleGesture:self inState:RNGestureHandlerStateActive];
@@ -139,6 +144,11 @@
139
144
  #endif
140
145
 
141
146
  #if TARGET_OS_OSX
147
+ // NSPanGestureRecognizer transitions to the Began state on mouse-down, without any
148
+ // built-in movement hysteresis. To honor the custom activation criteria (minDist,
149
+ // activeOffsets, minVelocity) we hold the recognizer in the Possible state until
150
+ // they are met in interactionsMoved.
151
+ _blockAutomaticActivation = _hasCustomActivationCriteria;
142
152
  [super mouseDown:event];
143
153
  #else
144
154
  [super touchesBegan:touches withEvent:event];
@@ -176,7 +186,14 @@
176
186
  }
177
187
  }
178
188
 
179
- #if !TARGET_OS_TV && !TARGET_OS_OSX
189
+ #if TARGET_OS_OSX
190
+ if (_hasCustomActivationCriteria && self.state == UIGestureRecognizerStatePossible &&
191
+ [self shouldActivateUnderCustomCriteria]) {
192
+ _blockAutomaticActivation = NO;
193
+ self.state = UIGestureRecognizerStateBegan;
194
+ [self setTranslation:CGPointMake(0, 0) inView:self.view];
195
+ }
196
+ #elif !TARGET_OS_TV
180
197
  if (_hasCustomActivationCriteria && self.state == UIGestureRecognizerStatePossible &&
181
198
  [self shouldActivateUnderCustomCriteria]) {
182
199
  super.minimumNumberOfTouches = _realMinimumNumberOfTouches;
@@ -209,6 +226,23 @@
209
226
 
210
227
  #if TARGET_OS_OSX
211
228
 
229
+ - (void)setState:(NSGestureRecognizerState)state
230
+ {
231
+ if (_blockAutomaticActivation) {
232
+ if (state == NSGestureRecognizerStateBegan || state == NSGestureRecognizerStateChanged) {
233
+ // Hold the recognizer in the Possible state until the custom activation criteria
234
+ // are met — the superclass keeps tracking the mouse regardless, so translation
235
+ // and velocity stay valid for the criteria checks.
236
+ return;
237
+ }
238
+ if (state == NSGestureRecognizerStateEnded) {
239
+ // Mouse released before the activation criteria were met — the gesture failed.
240
+ state = NSGestureRecognizerStateFailed;
241
+ }
242
+ }
243
+ [super setState:state];
244
+ }
245
+
212
246
  - (void)mouseDown:(NSEvent *)event
213
247
  {
214
248
  [_gestureHandler setCurrentPointerTypeToMouse];
@@ -265,6 +299,9 @@
265
299
  [_gestureHandler.pointerTracker reset];
266
300
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(activateAfterLongPress) object:nil];
267
301
  self.enabled = YES;
302
+ #if TARGET_OS_OSX
303
+ _blockAutomaticActivation = NO;
304
+ #endif
268
305
  [super reset];
269
306
  [_gestureHandler reset];
270
307
 
@@ -333,10 +370,10 @@
333
370
  }
334
371
 
335
372
  CGPoint velocity = [self velocityInView:self.view];
336
- if (TEST_MIN_IF_NOT_NAN(velocity.x, _minVelocityX)) {
373
+ if (TEST_ABS_MIN_IF_NOT_NAN(velocity.x, _minVelocityX)) {
337
374
  return YES;
338
375
  }
339
- if (TEST_MIN_IF_NOT_NAN(velocity.y, _minVelocityY)) {
376
+ if (TEST_ABS_MIN_IF_NOT_NAN(velocity.y, _minVelocityY)) {
340
377
  return YES;
341
378
  }
342
379
  if (TEST_MIN_IF_NOT_NAN(VEC_LEN_SQ(velocity), _minVelocitySq)) {
@@ -405,9 +442,9 @@
405
442
 
406
443
  #if !TARGET_OS_OSX && !TARGET_OS_TV && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130400
407
444
  if (@available(iOS 13.4, *)) {
408
- bool enableTrackpadTwoFingerGesture = [RCTConvert BOOL:config[@"enableTrackpadTwoFingerGesture"]];
409
- if (enableTrackpadTwoFingerGesture) {
410
- recognizer.allowedScrollTypesMask = UIScrollTypeMaskAll;
445
+ id enableTrackpadTwoFingerGesture = config[@"enableTrackpadTwoFingerGesture"];
446
+ if (enableTrackpadTwoFingerGesture != nil) {
447
+ recognizer.allowedScrollTypesMask = [RCTConvert BOOL:enableTrackpadTwoFingerGesture] ? UIScrollTypeMaskAll : 0;
411
448
  }
412
449
  }
413
450
 
@@ -38,6 +38,12 @@
38
38
  NSUInteger _tapsSoFar;
39
39
  CGPoint _initPosition;
40
40
  NSInteger _maxNumberOfTouches;
41
+ // Pending `cancel` invocations scheduled via dispatch_after. We use dispatch blocks instead of
42
+ // performSelector:afterDelay: because the latter schedules its timer in NSDefaultRunLoopMode only,
43
+ // which means it is starved while a sibling UIScrollView keeps the run loop in UITrackingRunLoopMode
44
+ // (during a drag or momentum deceleration). dispatch_after fires regardless of run loop mode, so the
45
+ // tap can still fail/finalize on time while a list is scrolling. See issue #3471.
46
+ NSMutableArray<dispatch_block_t> *_pendingCancellations;
41
47
  }
42
48
 
43
49
  static const NSUInteger defaultNumberOfTaps = 1;
@@ -57,10 +63,33 @@ static const NSTimeInterval defaultMaxDuration = 0.5;
57
63
  _maxDeltaX = NAN;
58
64
  _maxDeltaY = NAN;
59
65
  _maxDistSq = NAN;
66
+ _pendingCancellations = [NSMutableArray array];
60
67
  }
61
68
  return self;
62
69
  }
63
70
 
71
+ - (void)scheduleCancelAfterDelay:(NSTimeInterval)delay
72
+ {
73
+ __weak typeof(self) weakSelf = self;
74
+
75
+ dispatch_block_t block = dispatch_block_create(0, ^{
76
+ [weakSelf cancel];
77
+ });
78
+
79
+ [_pendingCancellations addObject:block];
80
+
81
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), block);
82
+ }
83
+
84
+ - (void)cancelPendingCancellations
85
+ {
86
+ for (dispatch_block_t block in _pendingCancellations) {
87
+ dispatch_block_cancel(block);
88
+ }
89
+
90
+ [_pendingCancellations removeAllObjects];
91
+ }
92
+
64
93
  - (void)triggerAction
65
94
  {
66
95
  [_gestureHandler handleGesture:self fromReset:NO];
@@ -93,14 +122,14 @@ static const NSTimeInterval defaultMaxDuration = 0.5;
93
122
  }
94
123
  _tapsSoFar++;
95
124
  if (_tapsSoFar) {
96
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancel) object:nil];
125
+ [self cancelPendingCancellations];
97
126
  }
98
127
  NSInteger numberOfTouches = [touches count];
99
128
  if (numberOfTouches > _maxNumberOfTouches) {
100
129
  _maxNumberOfTouches = numberOfTouches;
101
130
  }
102
131
  if (!isnan(_maxDuration)) {
103
- [self performSelector:@selector(cancel) withObject:nil afterDelay:_maxDuration];
132
+ [self scheduleCancelAfterDelay:_maxDuration];
104
133
  }
105
134
  self.state = UIGestureRecognizerStatePossible;
106
135
  [self triggerAction];
@@ -132,10 +161,12 @@ static const NSTimeInterval defaultMaxDuration = 0.5;
132
161
  {
133
162
  [_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
134
163
 
164
+ [self cancelPendingCancellations];
165
+
135
166
  if (_numberOfTaps == _tapsSoFar && _maxNumberOfTouches >= _minPointers) {
136
167
  self.state = UIGestureRecognizerStateEnded;
137
168
  } else {
138
- [self performSelector:@selector(cancel) withObject:nil afterDelay:_maxDelay];
169
+ [self scheduleCancelAfterDelay:_maxDelay];
139
170
  }
140
171
  }
141
172
 
@@ -250,7 +281,7 @@ static const NSTimeInterval defaultMaxDuration = 0.5;
250
281
 
251
282
  [_gestureHandler.pointerTracker reset];
252
283
 
253
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(cancel) object:nil];
284
+ [self cancelPendingCancellations];
254
285
  _tapsSoFar = 0;
255
286
  _maxNumberOfTouches = 0;
256
287
  self.enabled = YES;
package/apple/RNGHUIKit.h CHANGED
@@ -6,11 +6,11 @@ typedef UIView RNGHUIView;
6
6
  typedef UITouch RNGHUITouch;
7
7
  typedef UIScrollView RNGHUIScrollView;
8
8
 
9
- #define RNGHGestureRecognizerStateFailed UIGestureRecognizerStateFailed;
10
- #define RNGHGestureRecognizerStatePossible UIGestureRecognizerStatePossible;
11
- #define RNGHGestureRecognizerStateCancelled UIGestureRecognizerStateCancelled;
12
- #define RNGHGestureRecognizerStateBegan UIGestureRecognizerStateBegan;
13
- #define RNGHGestureRecognizerStateEnded UIGestureRecognizerStateEnded;
9
+ #define RNGHGestureRecognizerStateFailed UIGestureRecognizerStateFailed
10
+ #define RNGHGestureRecognizerStatePossible UIGestureRecognizerStatePossible
11
+ #define RNGHGestureRecognizerStateCancelled UIGestureRecognizerStateCancelled
12
+ #define RNGHGestureRecognizerStateBegan UIGestureRecognizerStateBegan
13
+ #define RNGHGestureRecognizerStateEnded UIGestureRecognizerStateEnded
14
14
 
15
15
  #else // TARGET_OS_OSX [
16
16
 
@@ -20,10 +20,10 @@ typedef RCTUIView RNGHUIView;
20
20
  typedef RCTUITouch RNGHUITouch;
21
21
  typedef NSScrollView RNGHUIScrollView;
22
22
 
23
- #define RNGHGestureRecognizerStateFailed NSGestureRecognizerStateFailed;
24
- #define RNGHGestureRecognizerStatePossible NSGestureRecognizerStatePossible;
25
- #define RNGHGestureRecognizerStateCancelled NSGestureRecognizerStateCancelled;
26
- #define RNGHGestureRecognizerStateBegan NSGestureRecognizerStateBegan;
27
- #define RNGHGestureRecognizerStateEnded NSGestureRecognizerStateEnded;
23
+ #define RNGHGestureRecognizerStateFailed NSGestureRecognizerStateFailed
24
+ #define RNGHGestureRecognizerStatePossible NSGestureRecognizerStatePossible
25
+ #define RNGHGestureRecognizerStateCancelled NSGestureRecognizerStateCancelled
26
+ #define RNGHGestureRecognizerStateBegan NSGestureRecognizerStateBegan
27
+ #define RNGHGestureRecognizerStateEnded NSGestureRecognizerStateEnded
28
28
 
29
29
  #endif // ] TARGET_OS_OSX
@@ -14,6 +14,8 @@
14
14
  #define TEST_MIN_IF_NOT_NAN(value, limit) \
15
15
  (!isnan(limit) && ((limit < 0 && value <= limit) || (limit >= 0 && value >= limit)))
16
16
 
17
+ #define TEST_ABS_MIN_IF_NOT_NAN(value, limit) (!isnan(limit) && fabs(value) >= fabs(limit))
18
+
17
19
  #define TEST_MAX_IF_NOT_NAN(value, max) (!isnan(max) && ((max < 0 && value < max) || (max >= 0 && value > max)))
18
20
 
19
21
  #define APPLY_PROP(recognizer, config, type, prop, propName) \
@@ -105,7 +105,7 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
105
105
  - (void)resetConfig
106
106
  {
107
107
  self.enabled = YES;
108
- self.manualActivation = NO;
108
+ _manualActivation = NO;
109
109
  _shouldCancelWhenOutside = NO;
110
110
  _handlersToWaitFor = nil;
111
111
  _simultaneousHandlers = nil;
@@ -176,6 +176,8 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
176
176
  RCTLogError(@"Cannot have all of top, bottom and height defined");
177
177
  }
178
178
  }
179
+
180
+ [self syncManualActivationRecognizer];
179
181
  }
180
182
 
181
183
  - (void)setEnabled:(BOOL)enabled
@@ -253,6 +255,24 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
253
255
 
254
256
  - (void)unbindFromView
255
257
  {
258
+ // If the gesture is still in flight - e.g. the view is being unmounted mid-gesture - deliver
259
+ // the final event now, while the recognizer is still attached and the target view is known.
260
+ // Otherwise the onBegin/onFinalize and onActivate/onDeactivate guarantees would be broken
261
+ // and `_lastState` would never be cleared by `reset`.
262
+ if (self.recognizer.view != nil &&
263
+ (_lastState == RNGestureHandlerStateBegan || _lastState == RNGestureHandlerStateActive)) {
264
+ if ([self eventTagForRecognizer:self.recognizer] != nil) {
265
+ [self handleGesture:self.recognizer
266
+ inState:_lastState == RNGestureHandlerStateActive ? RNGestureHandlerStateCancelled
267
+ : RNGestureHandlerStateFailed];
268
+ } else {
269
+ // The event has no tag to be dispatched with, so it cannot be delivered on any path - reset
270
+ // the bookkeeping so the handler doesn't stay in-flight forever.
271
+ _lastState = RNGestureHandlerStateUndetermined;
272
+ _state = RNGestureHandlerStateBegan;
273
+ }
274
+ }
275
+
256
276
  [self.recognizer.view removeGestureRecognizer:self.recognizer];
257
277
  self.recognizer.delegate = nil;
258
278
  self.viewTag = nil;
@@ -314,21 +334,38 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
314
334
  //
315
335
  // While this solution is not great, we decided to check whether sending events was triggered from `reset` method.
316
336
  // This way we can detect double Began mapping by checking previous sent state and current state of recognizer.
317
- if (fromReset && _lastState == RNGestureHandlerStateBegan &&
318
- self.recognizer.state == UIGestureRecognizerStatePossible) {
319
- _state = RNGestureHandlerStateFailed;
337
+ //
338
+ // The same applies to gestures interrupted mid-flight, e.g. when the view is unmounted during an active
339
+ // gesture the recognizer may be reset without its cancel action ever firing.
340
+ // If the last sent state is not final, synthesize the missing final event so that the
341
+ // `onBegin`/`onFinalize` and `onActivate`/`onDeactivate` guarantees hold.
342
+ if (fromReset && self.recognizer.state == UIGestureRecognizerStatePossible) {
343
+ if (_lastState == RNGestureHandlerStateBegan) {
344
+ _state = RNGestureHandlerStateFailed;
345
+ } else if (_lastState == RNGestureHandlerStateActive) {
346
+ _state = RNGestureHandlerStateCancelled;
347
+ } else {
348
+ // The final event was already delivered; mapping Possible to Began here would emit a stray
349
+ // BEGAN event after the gesture has finished.
350
+ return;
351
+ }
320
352
  }
321
353
 
322
354
  [self handleGesture:recognizer inState:_state];
323
355
  }
324
356
 
357
+ - (nullable NSNumber *)eventTagForRecognizer:(UIGestureRecognizer *)recognizer
358
+ {
359
+ return [self chooseViewForInteraction:recognizer].reactTag;
360
+ }
361
+
325
362
  - (void)handleGesture:(UIGestureRecognizer *)recognizer inState:(RNGestureHandlerState)state
326
363
  {
327
364
  _state = state;
328
365
  RNGestureHandlerEventExtraData *eventData = [self eventExtraData:recognizer];
329
- RNGHUIView *view = [self chooseViewForInteraction:recognizer];
366
+ NSNumber *tag = [self eventTagForRecognizer:recognizer];
330
367
 
331
- [self sendEventsInState:self.state forViewWithTag:view.reactTag withExtraData:eventData];
368
+ [self sendEventsInState:self.state forViewWithTag:tag withExtraData:eventData];
332
369
  }
333
370
 
334
371
  - (void)sendEventsInState:(RNGestureHandlerState)state
@@ -445,14 +482,24 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
445
482
  - (void)setManualActivation:(BOOL)manualActivation
446
483
  {
447
484
  _manualActivation = manualActivation;
485
+ [self syncManualActivationRecognizer];
486
+ }
448
487
 
449
- if (manualActivation) {
488
+ - (void)syncManualActivationRecognizer
489
+ {
490
+ BOOL hasRecognizer = _manualActivationRecognizer != nil;
491
+
492
+ if (hasRecognizer == _manualActivation) {
493
+ return;
494
+ }
495
+
496
+ if (_manualActivation) {
450
497
  _manualActivationRecognizer = [[RNManualActivationRecognizer alloc] initWithGestureHandler:self];
451
498
 
452
499
  if (_recognizer.view != nil) {
453
500
  [_recognizer.view addGestureRecognizer:_manualActivationRecognizer];
454
501
  }
455
- } else if (_manualActivationRecognizer != nil) {
502
+ } else {
456
503
  [_manualActivationRecognizer.view removeGestureRecognizer:_manualActivationRecognizer];
457
504
  _manualActivationRecognizer = nil;
458
505
  }
@@ -636,7 +683,13 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
636
683
  // might be called after some pointers are down, and after state manipulation by the user.
637
684
  // Pointer tracker calls this method when it resets, and in that case it no longer tracks
638
685
  // any pointers, thus entering this if
639
- if (!_needsPointerData || _pointerTracker.trackedPointersCount == 0) {
686
+ //
687
+ // Also do not clear _lastState while the gesture is in flight (BEGAN/ACTIVE) - the final
688
+ // state-change event hasn't been dispatched yet. When the view is removed mid-gesture,
689
+ // the pointer tracker resets before the recognizer's cancel action fires; clearing _lastState
690
+ // here would corrupt the prevState of the outgoing CANCELLED event and break the onActivate/onDeactivate guarantee.
691
+ if ((!_needsPointerData || _pointerTracker.trackedPointersCount == 0) && _lastState != RNGestureHandlerStateBegan &&
692
+ _lastState != RNGestureHandlerStateActive) {
640
693
  _lastState = RNGestureHandlerStateUndetermined;
641
694
  _state = RNGestureHandlerStateBegan;
642
695
  }
@@ -62,7 +62,8 @@
62
62
  {
63
63
  if ([view isKindOfClass:[RNGestureHandlerButton class]]) {
64
64
  RNGestureHandlerButton *button = (RNGestureHandlerButton *)view;
65
- return button.userEnabled;
65
+ return button.userEnabled && button.pointerEvents != RNGestureHandlerPointerEventsBoxNone &&
66
+ button.pointerEvents != RNGestureHandlerPointerEventsNone;
66
67
  }
67
68
 
68
69
  // Certain subviews such as RCTViewComponentView have been observed to have disabled
@@ -105,7 +106,8 @@
105
106
  if (!subview.isHidden && subview.alpha > 0) {
106
107
  CGPoint convertedPoint = [subview convertPoint:point fromView:self];
107
108
  UIView *hitView = [subview hitTest:convertedPoint withEvent:event];
108
- if (hitView != nil && [self shouldHandleTouch:hitView]) {
109
+ if (hitView != nil &&
110
+ ([hitView isKindOfClass:[RNGestureHandlerButton class]] || [self shouldHandleTouch:hitView])) {
109
111
  return hitView;
110
112
  }
111
113
  }
@@ -118,7 +120,7 @@
118
120
  }
119
121
 
120
122
  RNGHUIView *inner = [super hitTest:point withEvent:event];
121
- while (inner && ![self shouldHandleTouch:inner]) {
123
+ while (inner && inner != self && ![self shouldHandleTouch:inner]) {
122
124
  inner = inner.superview;
123
125
  }
124
126
  return inner;