react-native-gesture-handler 3.0.0 → 3.0.2

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 (100) hide show
  1. package/README.md +4 -0
  2. package/RNGestureHandler.podspec +1 -1
  3. package/android/build.gradle +6 -5
  4. package/android/gradle.properties +1 -1
  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 +28 -32
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +44 -6
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +4 -3
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt +0 -13
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +1 -1
  11. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +1 -1
  12. package/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.kt +3 -0
  13. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +30 -3
  14. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt +4 -0
  15. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +8 -6
  16. package/apple/Handlers/RNNativeViewHandler.mm +4 -1
  17. package/apple/RNGestureHandlerButton.h +5 -0
  18. package/apple/RNGestureHandlerButtonComponentView.mm +38 -0
  19. package/apple/RNGestureHandlerDetector.h +0 -2
  20. package/apple/RNGestureHandlerDetector.mm +6 -6
  21. package/apple/RNGestureHandlerManager.h +5 -0
  22. package/apple/RNGestureHandlerManager.mm +14 -12
  23. package/lib/module/components/Pressable/Pressable.js +6 -2
  24. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  25. package/lib/module/components/Pressable/StateMachine.js +10 -1
  26. package/lib/module/components/Pressable/StateMachine.js.map +1 -1
  27. package/lib/module/components/Pressable/stateDefinitions.js +3 -2
  28. package/lib/module/components/Pressable/stateDefinitions.js.map +1 -1
  29. package/lib/module/components/Pressable/utils.js +32 -1
  30. package/lib/module/components/Pressable/utils.js.map +1 -1
  31. package/lib/module/components/ReanimatedDrawerLayout.js +5 -4
  32. package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -1
  33. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js +8 -2
  34. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js.map +1 -1
  35. package/lib/module/components/utils.js +14 -0
  36. package/lib/module/components/utils.js.map +1 -1
  37. package/lib/module/handlers/gestures/GestureDetector/utils.js +6 -6
  38. package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
  39. package/lib/module/handlers/gestures/gesture.js +8 -0
  40. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  41. package/lib/module/handlers/gestures/gestureComposition.js +14 -2
  42. package/lib/module/handlers/gestures/gestureComposition.js.map +1 -1
  43. package/lib/module/v3/components/GestureButtons.js +3 -0
  44. package/lib/module/v3/components/GestureButtons.js.map +1 -1
  45. package/lib/module/v3/components/Pressable.js +24 -5
  46. package/lib/module/v3/components/Pressable.js.map +1 -1
  47. package/lib/module/v3/components/Touchable/Touchable.js +3 -0
  48. package/lib/module/v3/components/Touchable/Touchable.js.map +1 -1
  49. package/lib/module/v3/hooks/utils/configUtils.js +3 -3
  50. package/lib/module/v3/hooks/utils/configUtils.js.map +1 -1
  51. package/lib/module/v3/hooks/utils/propsWhiteList.js +7 -6
  52. package/lib/module/v3/hooks/utils/propsWhiteList.js.map +1 -1
  53. package/lib/module/v3/hooks/utils/reanimatedUtils.js +8 -10
  54. package/lib/module/v3/hooks/utils/reanimatedUtils.js.map +1 -1
  55. package/lib/module/web/tools/GestureHandlerWebDelegate.js +5 -4
  56. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  57. package/lib/typescript/components/Pressable/Pressable.d.ts.map +1 -1
  58. package/lib/typescript/components/Pressable/StateMachine.d.ts +1 -0
  59. package/lib/typescript/components/Pressable/StateMachine.d.ts.map +1 -1
  60. package/lib/typescript/components/Pressable/stateDefinitions.d.ts.map +1 -1
  61. package/lib/typescript/components/Pressable/utils.d.ts +2 -1
  62. package/lib/typescript/components/Pressable/utils.d.ts.map +1 -1
  63. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts +14 -2
  64. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts.map +1 -1
  65. package/lib/typescript/components/ReanimatedSwipeable/ReanimatedSwipeable.d.ts.map +1 -1
  66. package/lib/typescript/components/utils.d.ts +11 -0
  67. package/lib/typescript/components/utils.d.ts.map +1 -1
  68. package/lib/typescript/handlers/gestures/GestureDetector/utils.d.ts +4 -4
  69. package/lib/typescript/handlers/gestures/GestureDetector/utils.d.ts.map +1 -1
  70. package/lib/typescript/handlers/gestures/gesture.d.ts +4 -0
  71. package/lib/typescript/handlers/gestures/gesture.d.ts.map +1 -1
  72. package/lib/typescript/handlers/gestures/gestureComposition.d.ts.map +1 -1
  73. package/lib/typescript/v3/components/GestureButtons.d.ts.map +1 -1
  74. package/lib/typescript/v3/components/Pressable.d.ts.map +1 -1
  75. package/lib/typescript/v3/components/Touchable/Touchable.d.ts.map +1 -1
  76. package/lib/typescript/v3/hooks/utils/configUtils.d.ts.map +1 -1
  77. package/lib/typescript/v3/hooks/utils/propsWhiteList.d.ts.map +1 -1
  78. package/lib/typescript/v3/hooks/utils/reanimatedUtils.d.ts.map +1 -1
  79. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts.map +1 -1
  80. package/package.json +6 -6
  81. package/scripts/gesture_handler_utils.rb +23 -17
  82. package/shared/shadowNodes/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.cpp +19 -0
  83. package/shared/shadowNodes/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.h +1 -0
  84. package/src/components/Pressable/Pressable.tsx +9 -1
  85. package/src/components/Pressable/StateMachine.tsx +16 -1
  86. package/src/components/Pressable/stateDefinitions.ts +3 -2
  87. package/src/components/Pressable/utils.ts +37 -0
  88. package/src/components/ReanimatedDrawerLayout.tsx +27 -8
  89. package/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx +8 -2
  90. package/src/components/utils.ts +22 -0
  91. package/src/handlers/gestures/GestureDetector/utils.ts +6 -10
  92. package/src/handlers/gestures/gesture.ts +11 -0
  93. package/src/handlers/gestures/gestureComposition.ts +15 -2
  94. package/src/v3/components/GestureButtons.tsx +4 -0
  95. package/src/v3/components/Pressable.tsx +33 -3
  96. package/src/v3/components/Touchable/Touchable.tsx +4 -0
  97. package/src/v3/hooks/utils/configUtils.ts +4 -5
  98. package/src/v3/hooks/utils/propsWhiteList.ts +6 -6
  99. package/src/v3/hooks/utils/reanimatedUtils.ts +9 -10
  100. package/src/web/tools/GestureHandlerWebDelegate.ts +10 -4
@@ -2,6 +2,7 @@ import React, { useRef } from 'react';
2
2
  import { Animated, Platform, StyleSheet } from 'react-native';
3
3
 
4
4
  import GestureHandlerButton from '../../components/GestureHandlerButton';
5
+ import { getTVProps } from '../../components/utils';
5
6
  import createNativeWrapper from '../createNativeWrapper';
6
7
  import type { NativeHandlerData } from '../hooks/gestures/native/NativeTypes';
7
8
  import type { GestureEndEvent, GestureEvent } from '../types';
@@ -95,10 +96,13 @@ export const BaseButton = (props: BaseButtonProps) => {
95
96
  props.onFinalize?.(e);
96
97
  };
97
98
 
99
+ const tvProps = getTVProps(rest);
100
+
98
101
  return (
99
102
  <RawButton
100
103
  style={[style, Platform.OS === 'ios' && { cursor: undefined }]}
101
104
  {...rest}
105
+ {...tvProps}
102
106
  onBegin={onBegin}
103
107
  onActivate={onActivate}
104
108
  onDeactivate={onDeactivate}
@@ -29,7 +29,9 @@ import {
29
29
  gestureTouchToPressableEvent,
30
30
  isTouchWithinInset,
31
31
  numberAsInset,
32
+ viewCenterToPressableEvent,
32
33
  } from '../../components/Pressable/utils';
34
+ import { getTVProps } from '../../components/utils';
33
35
  import { PressabilityDebugView } from '../../handlers/PressabilityDebugView';
34
36
  import { useIsScreenReaderEnabled } from '../../useIsScreenReaderEnabled';
35
37
  import { INT32_MAX, isTestEnv } from '../../utils';
@@ -151,8 +153,9 @@ const Pressable = (props: PressableProps) => {
151
153
  }, [cancelDelayedPress, cancelLongPress]);
152
154
 
153
155
  const handlePressIn = useCallback(
154
- (event: PressableEvent) => {
156
+ (event: PressableEvent, skipBoundsCheck = false) => {
155
157
  if (
158
+ !skipBoundsCheck &&
156
159
  !isTouchWithinInset(
157
160
  dimensions.current,
158
161
  normalizedHitSlop,
@@ -305,11 +308,25 @@ const Pressable = (props: PressableProps) => {
305
308
  }
306
309
  },
307
310
  onBegin: () => {
311
+ if (Platform.isTV) {
312
+ // tvOS drives this native gesture from the focus-engine Select press.
313
+ // The press state machine is touch-based and never
314
+ // receives LONG_PRESS_TOUCHES_DOWN here, so bypass it and drive the press handlers directly.
315
+ // A focus-driven press has no coordinates, so skip the hit-slop bounds check entirely.
316
+ handlePressIn(viewCenterToPressableEvent(dimensions.current), true);
317
+ return;
318
+ }
319
+ if (Platform.OS === 'android' && isScreenReaderEnabled) {
320
+ stateMachine.handleEvent(
321
+ StateMachineEvent.NATIVE_BEGIN,
322
+ viewCenterToPressableEvent(dimensions.current)
323
+ );
324
+ return;
325
+ }
308
326
  stateMachine.handleEvent(StateMachineEvent.NATIVE_BEGIN);
309
327
  },
310
328
  onActivate: () => {
311
- if (Platform.OS !== 'android') {
312
- // Native.onActivate is broken with Android + hitSlop
329
+ if (!Platform.isTV && Platform.OS !== 'android') {
313
330
  stateMachine.handleEvent(StateMachineEvent.NATIVE_START);
314
331
  }
315
332
  },
@@ -319,6 +336,16 @@ const Pressable = (props: PressableProps) => {
319
336
  if (Platform.OS === 'web') {
320
337
  return;
321
338
  }
339
+
340
+ if (Platform.isTV) {
341
+ handlePressOut(
342
+ viewCenterToPressableEvent(dimensions.current),
343
+ !event.canceled
344
+ );
345
+ handleFinalize();
346
+ return;
347
+ }
348
+
322
349
  stateMachine.handleEvent(
323
350
  event.canceled ? StateMachineEvent.CANCEL : StateMachineEvent.FINALIZE
324
351
  );
@@ -365,10 +392,13 @@ const Pressable = (props: PressableProps) => {
365
392
  [onLayout]
366
393
  );
367
394
 
395
+ const tvProps = getTVProps(remainingProps);
396
+
368
397
  return (
369
398
  <GestureDetector gesture={gesture}>
370
399
  <PureNativeButton
371
400
  {...remainingProps}
401
+ {...tvProps}
372
402
  onLayout={setDimensions}
373
403
  accessible={accessible !== false}
374
404
  hitSlop={appliedHitSlop}
@@ -2,6 +2,7 @@ import React, { useCallback, useRef } from 'react';
2
2
  import { Platform } from 'react-native';
3
3
 
4
4
  import GestureHandlerButton from '../../../components/GestureHandlerButton';
5
+ import { getTVProps } from '../../../components/utils';
5
6
  import { NativeDetector } from '../../detectors/NativeDetector';
6
7
  import { useNativeGesture } from '../../hooks';
7
8
  import type {
@@ -208,10 +209,13 @@ export const Touchable = (props: TouchableProps) => {
208
209
  }
209
210
  : TRANSPARENT_RIPPLE;
210
211
 
212
+ const tvProps = getTVProps(rest);
213
+
211
214
  return (
212
215
  <NativeDetector gesture={nativeGesture}>
213
216
  <GestureHandlerButton
214
217
  {...rest}
218
+ {...tvProps}
215
219
  {...rippleProps}
216
220
  {...resolvedDurations}
217
221
  ref={ref ?? null}
@@ -21,8 +21,6 @@ export function resolveInternalConfigProps<
21
21
  THandlerData,
22
22
  TExtendedHandlerData extends THandlerData,
23
23
  >(config: BaseGestureConfig<TConfig, THandlerData, TExtendedHandlerData>) {
24
- const runOnJS = maybeUnpackValue(config.runOnJS);
25
-
26
24
  if (
27
25
  __DEV__ &&
28
26
  isNativeAnimatedEvent(config.onUpdate) &&
@@ -63,8 +61,6 @@ export function resolveInternalConfigProps<
63
61
  hasWorkletEventHandlers(config) &&
64
62
  !config.dispatchesAnimatedEvents;
65
63
  config.needsPointerData = shouldHandleTouchEvents(config);
66
- config.dispatchesReanimatedEvents =
67
- config.shouldUseReanimatedDetector && !runOnJS;
68
64
  }
69
65
 
70
66
  export function prepareConfigForNativeSide<
@@ -80,7 +76,10 @@ export function prepareConfigForNativeSide<
80
76
  TConfig,
81
77
  THandlerData,
82
78
  TExtendedHandlerData
83
- > = {};
79
+ > = {
80
+ dispatchesReanimatedEvents:
81
+ config.shouldUseReanimatedDetector && !maybeUnpackValue(config.runOnJS),
82
+ };
84
83
  const handlerPropsWhiteList =
85
84
  PropsWhiteLists.get(handlerType) ?? EMPTY_WHITE_LIST;
86
85
 
@@ -42,16 +42,10 @@ export const allowedNativeProps = new Set<
42
42
  'userSelect',
43
43
  'enableContextMenu',
44
44
  'touchAction',
45
- 'dispatchesReanimatedEvents',
46
45
  'dispatchesAnimatedEvents',
47
46
  'needsPointerData',
48
47
  ]);
49
48
 
50
- // Don't pass testID to the native side in production
51
- if (!__DEV__) {
52
- allowedNativeProps.delete('testID');
53
- }
54
-
55
49
  export const HandlerCallbacks = new Set<
56
50
  keyof Required<GestureCallbacks<unknown, unknown>>
57
51
  >([
@@ -87,6 +81,12 @@ export const PropsToFilter = new Set<
87
81
  'activeOffsetX',
88
82
  ]);
89
83
 
84
+ // Don't pass testID to the native side in production
85
+ if (!__DEV__) {
86
+ allowedNativeProps.delete('testID');
87
+ PropsToFilter.add('testID');
88
+ }
89
+
90
90
  export const PropsWhiteLists = new Map<
91
91
  SingleGestureName,
92
92
  HandlersPropsWhiteList
@@ -38,6 +38,7 @@ export function bindSharedValues<
38
38
  }
39
39
 
40
40
  const baseListenerId = handlerTag + SHARED_VALUE_OFFSET;
41
+ const { shouldUseReanimatedDetector } = config;
41
42
 
42
43
  const attachListener = (sharedValue: SharedValue, configKey: string) => {
43
44
  'worklet';
@@ -45,16 +46,14 @@ export function bindSharedValues<
45
46
  const listenerId = baseListenerId + keyHash;
46
47
 
47
48
  sharedValue.addListener(listenerId, (value) => {
48
- if (configKey === 'runOnJS') {
49
- config.dispatchesReanimatedEvents =
50
- config.shouldUseReanimatedDetector && !value;
51
-
52
- updateGestureHandlerConfig(handlerTag, {
53
- dispatchesReanimatedEvents: config.dispatchesReanimatedEvents,
54
- });
55
- } else {
56
- updateGestureHandlerConfig(handlerTag, { [configKey]: value });
57
- }
49
+ updateGestureHandlerConfig(
50
+ handlerTag,
51
+ configKey === 'runOnJS'
52
+ ? {
53
+ dispatchesReanimatedEvents: shouldUseReanimatedDetector && !value,
54
+ }
55
+ : { [configKey]: value }
56
+ );
58
57
  });
59
58
  };
60
59
 
@@ -141,8 +141,14 @@ export class GestureHandlerWebDelegate
141
141
  throw new Error(tagMessage('Cannot convert coords on a null view'));
142
142
  }
143
143
 
144
- const rect = getEffectiveBoundingRect(this.view);
145
- const transform = getComputedStyle(this.view).transform;
144
+ const localView =
145
+ this.gestureHandler.usesNativeOrVirtualDetector() &&
146
+ this.view.style.display === 'contents'
147
+ ? (this.view.children[0] as HTMLElement)
148
+ : this.view;
149
+
150
+ const rect = getEffectiveBoundingRect(localView);
151
+ const transform = getComputedStyle(localView).transform;
146
152
  const matrix =
147
153
  transform && transform !== 'none'
148
154
  ? new DOMMatrix(transform)
@@ -164,8 +170,8 @@ export class GestureHandlerWebDelegate
164
170
  const localOffset = inverse.transformPoint(new DOMPoint(dx, dy));
165
171
 
166
172
  // Add back the local center (untransformed dimensions)
167
- const localCenterX = this.view.offsetWidth / 2;
168
- const localCenterY = this.view.offsetHeight / 2;
173
+ const localCenterX = localView.offsetWidth / 2;
174
+ const localCenterY = localView.offsetHeight / 2;
169
175
 
170
176
  return {
171
177
  x: localCenterX + localOffset.x,