react-native-gesture-handler 2.18.0 → 2.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. package/README.md +1 -0
  2. package/android/build.gradle +4 -17
  3. package/android/src/main/AndroidManifest.xml +1 -3
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +21 -21
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +2 -2
  6. package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +5 -0
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +80 -4
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/PinchGestureHandler.kt +2 -1
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/ScaleGestureDetector.java +10 -0
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +2 -2
  11. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +3 -0
  12. package/android/src/main/jni/cpp-adapter.cpp +2 -4
  13. package/apple/Handlers/RNFlingHandler.h +1 -0
  14. package/apple/Handlers/RNFlingHandler.m +153 -19
  15. package/apple/Handlers/RNHoverHandler.m +44 -2
  16. package/apple/Handlers/RNLongPressHandler.m +109 -20
  17. package/apple/Handlers/RNManualHandler.m +53 -29
  18. package/apple/Handlers/RNNativeViewHandler.mm +22 -15
  19. package/apple/RNGHUIKit.h +2 -0
  20. package/apple/RNGHVector.h +31 -0
  21. package/apple/RNGHVector.m +67 -0
  22. package/apple/RNGestureHandler.h +7 -0
  23. package/apple/{RNGestureHandler.m → RNGestureHandler.mm} +63 -1
  24. package/apple/RNGestureHandlerButtonComponentView.mm +6 -0
  25. package/apple/RNGestureHandlerDirection.h +25 -0
  26. package/apple/RNGestureHandlerModule.mm +2 -4
  27. package/lib/commonjs/PointerType.js +2 -1
  28. package/lib/commonjs/PointerType.js.map +1 -1
  29. package/lib/commonjs/components/Pressable/Pressable.js +67 -70
  30. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  31. package/lib/commonjs/components/Pressable/index.js +0 -8
  32. package/lib/commonjs/components/Pressable/index.js.map +1 -1
  33. package/lib/commonjs/components/ReanimatedSwipeable.js +60 -41
  34. package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
  35. package/lib/commonjs/components/Swipeable.js +5 -0
  36. package/lib/commonjs/components/Swipeable.js.map +1 -1
  37. package/lib/commonjs/handlers/LongPressGestureHandler.js +1 -1
  38. package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
  39. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +1 -1
  40. package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -1
  41. package/lib/commonjs/handlers/gestures/longPressGesture.js +10 -0
  42. package/lib/commonjs/handlers/gestures/longPressGesture.js.map +1 -1
  43. package/lib/commonjs/mocks.js +16 -3
  44. package/lib/commonjs/mocks.js.map +1 -1
  45. package/lib/commonjs/utils.js +4 -0
  46. package/lib/commonjs/utils.js.map +1 -1
  47. package/lib/commonjs/web/constants.js +3 -3
  48. package/lib/commonjs/web/constants.js.map +1 -1
  49. package/lib/commonjs/web/handlers/GestureHandler.js +1 -0
  50. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  51. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +43 -9
  52. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  53. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +14 -3
  54. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  55. package/lib/commonjs/web/handlers/PanGestureHandler.js +4 -0
  56. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  57. package/lib/commonjs/web/interfaces.js.map +1 -1
  58. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +55 -8
  59. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  60. package/lib/commonjs/web/tools/KeyboardEventManager.js +110 -0
  61. package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -0
  62. package/lib/commonjs/web/tools/Vector.js +4 -2
  63. package/lib/commonjs/web/tools/Vector.js.map +1 -1
  64. package/lib/commonjs/web/utils.js +14 -13
  65. package/lib/commonjs/web/utils.js.map +1 -1
  66. package/lib/module/PointerType.js +2 -1
  67. package/lib/module/PointerType.js.map +1 -1
  68. package/lib/module/components/Pressable/Pressable.js +66 -70
  69. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  70. package/lib/module/components/Pressable/index.js +0 -1
  71. package/lib/module/components/Pressable/index.js.map +1 -1
  72. package/lib/module/components/ReanimatedSwipeable.js +58 -37
  73. package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
  74. package/lib/module/components/Swipeable.js +6 -0
  75. package/lib/module/components/Swipeable.js.map +1 -1
  76. package/lib/module/handlers/LongPressGestureHandler.js +1 -1
  77. package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
  78. package/lib/module/handlers/gestures/GestureDetector/utils.js +2 -2
  79. package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
  80. package/lib/module/handlers/gestures/longPressGesture.js +10 -0
  81. package/lib/module/handlers/gestures/longPressGesture.js.map +1 -1
  82. package/lib/module/mocks.js +13 -3
  83. package/lib/module/mocks.js.map +1 -1
  84. package/lib/module/utils.js +1 -0
  85. package/lib/module/utils.js.map +1 -1
  86. package/lib/module/web/constants.js +1 -1
  87. package/lib/module/web/constants.js.map +1 -1
  88. package/lib/module/web/handlers/GestureHandler.js +1 -0
  89. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  90. package/lib/module/web/handlers/LongPressGestureHandler.js +43 -9
  91. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  92. package/lib/module/web/handlers/NativeViewGestureHandler.js +14 -3
  93. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  94. package/lib/module/web/handlers/PanGestureHandler.js +4 -0
  95. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  96. package/lib/module/web/interfaces.js.map +1 -1
  97. package/lib/module/web/tools/GestureHandlerWebDelegate.js +54 -8
  98. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  99. package/lib/module/web/tools/KeyboardEventManager.js +96 -0
  100. package/lib/module/web/tools/KeyboardEventManager.js.map +1 -0
  101. package/lib/module/web/tools/Vector.js +5 -3
  102. package/lib/module/web/tools/Vector.js.map +1 -1
  103. package/lib/module/web/utils.js +14 -13
  104. package/lib/module/web/utils.js.map +1 -1
  105. package/lib/typescript/PointerType.d.ts +2 -1
  106. package/lib/typescript/components/Pressable/index.d.ts +1 -1
  107. package/lib/typescript/components/Swipeable.d.ts +5 -0
  108. package/lib/typescript/handlers/LongPressGestureHandler.d.ts +5 -1
  109. package/lib/typescript/handlers/gestures/longPressGesture.d.ts +5 -0
  110. package/lib/typescript/mocks.d.ts +4 -3
  111. package/lib/typescript/utils.d.ts +1 -0
  112. package/lib/typescript/web/constants.d.ts +1 -1
  113. package/lib/typescript/web/handlers/GestureHandler.d.ts +1 -1
  114. package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +3 -0
  115. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  116. package/lib/typescript/web/interfaces.d.ts +1 -1
  117. package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +1 -0
  118. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +6 -0
  119. package/lib/typescript/web/tools/KeyboardEventManager.d.ts +13 -0
  120. package/package.json +3 -3
  121. package/src/PointerType.ts +1 -0
  122. package/src/components/Pressable/Pressable.tsx +70 -50
  123. package/src/components/Pressable/index.ts +1 -1
  124. package/src/components/ReanimatedSwipeable.tsx +70 -47
  125. package/src/components/Swipeable.tsx +6 -0
  126. package/src/handlers/LongPressGestureHandler.ts +6 -0
  127. package/src/handlers/gestures/GestureDetector/utils.ts +2 -2
  128. package/src/handlers/gestures/longPressGesture.ts +9 -0
  129. package/src/{mocks.ts → mocks.tsx} +8 -3
  130. package/src/utils.ts +2 -0
  131. package/src/web/constants.ts +1 -1
  132. package/src/web/handlers/GestureHandler.ts +3 -1
  133. package/src/web/handlers/LongPressGestureHandler.ts +49 -10
  134. package/src/web/handlers/NativeViewGestureHandler.ts +14 -4
  135. package/src/web/handlers/PanGestureHandler.ts +4 -0
  136. package/src/web/interfaces.ts +1 -1
  137. package/src/web/tools/GestureHandlerDelegate.ts +1 -0
  138. package/src/web/tools/GestureHandlerWebDelegate.ts +67 -8
  139. package/src/web/tools/KeyboardEventManager.ts +91 -0
  140. package/src/web/tools/Vector.ts +4 -3
  141. package/src/web/utils.ts +15 -13
@@ -1,2 +1,2 @@
1
1
  export declare const DEFAULT_TOUCH_SLOP = 15;
2
- export declare const MINIMAL_FLING_VELOCITY = 0.1;
2
+ export declare const MINIMAL_RECOGNIZABLE_MAGNITUDE = 0.1;
@@ -3,10 +3,10 @@ import { State } from '../../State';
3
3
  import { Config, AdaptedEvent } from '../interfaces';
4
4
  import EventManager from '../tools/EventManager';
5
5
  import PointerTracker from '../tools/PointerTracker';
6
- import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
7
6
  import IGestureHandler from './IGestureHandler';
8
7
  import { MouseButton } from '../../handlers/gestureHandlerCommon';
9
8
  import { PointerType } from '../../PointerType';
9
+ import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
10
10
  export default abstract class GestureHandler implements IGestureHandler {
11
11
  private lastSentState;
12
12
  protected currentState: State;
@@ -6,6 +6,7 @@ export default class LongPressGestureHandler extends GestureHandler {
6
6
  private minDurationMs;
7
7
  private defaultMaxDistSq;
8
8
  private maxDistSq;
9
+ private numberOfPointers;
9
10
  private startX;
10
11
  private startY;
11
12
  private startTime;
@@ -19,8 +20,10 @@ export default class LongPressGestureHandler extends GestureHandler {
19
20
  protected resetConfig(): void;
20
21
  protected onStateChange(_newState: State, _oldState: State): void;
21
22
  protected onPointerDown(event: AdaptedEvent): void;
23
+ protected onPointerAdd(event: AdaptedEvent): void;
22
24
  protected onPointerMove(event: AdaptedEvent): void;
23
25
  protected onPointerUp(event: AdaptedEvent): void;
26
+ protected onPointerRemove(event: AdaptedEvent): void;
24
27
  private tryBegin;
25
28
  private tryActivate;
26
29
  private checkDistanceFail;
@@ -10,6 +10,7 @@ export default class NativeViewGestureHandler extends GestureHandler {
10
10
  private minDistSq;
11
11
  init(ref: number, propsRef: React.RefObject<unknown>): void;
12
12
  updateGestureConfig({ enabled, ...props }: Config): void;
13
+ private restoreViewStyles;
13
14
  protected resetConfig(): void;
14
15
  protected onPointerDown(event: AdaptedEvent): void;
15
16
  protected onPointerAdd(event: AdaptedEvent): void;
@@ -17,7 +17,7 @@ export interface Handler {
17
17
  }
18
18
  type ConfigArgs = number | boolean | HitSlop | UserSelect | TouchAction | ActiveCursor | Directions | Handler[] | null | undefined;
19
19
  export interface Config extends Record<string, ConfigArgs> {
20
- enabled?: boolean;
20
+ enabled: boolean;
21
21
  simultaneousHandlers?: Handler[] | null;
22
22
  waitFor?: Handler[] | null;
23
23
  blocksHandlers?: Handler[] | null;
@@ -19,5 +19,6 @@ export interface GestureHandlerDelegate<TComponent, THandler> {
19
19
  onEnd(): void;
20
20
  onCancel(): void;
21
21
  onFail(): void;
22
+ onEnabledChange(enabled: boolean): void;
22
23
  destroy(config: Config): void;
23
24
  }
@@ -2,9 +2,11 @@ import type IGestureHandler from '../handlers/IGestureHandler';
2
2
  import { GestureHandlerDelegate, MeasureResult } from './GestureHandlerDelegate';
3
3
  import { Config } from '../interfaces';
4
4
  export declare class GestureHandlerWebDelegate implements GestureHandlerDelegate<HTMLElement, IGestureHandler> {
5
+ private isInitialized;
5
6
  private view;
6
7
  private gestureHandler;
7
8
  private eventManagers;
9
+ private defaultViewStyles;
8
10
  getView(): HTMLElement;
9
11
  init(viewRef: number, handler: IGestureHandler): void;
10
12
  isPointerInBounds({ x, y }: {
@@ -19,6 +21,10 @@ export declare class GestureHandlerWebDelegate implements GestureHandlerDelegate
19
21
  private removeContextMenuListeners;
20
22
  private disableContextMenu;
21
23
  private enableContextMenu;
24
+ private setUserSelect;
25
+ private setTouchAction;
26
+ private setContextMenu;
27
+ onEnabledChange(enabled: boolean): void;
22
28
  onBegin(): void;
23
29
  onActivate(): void;
24
30
  onEnd(): void;
@@ -0,0 +1,13 @@
1
+ import { AdaptedEvent, EventTypes } from '../interfaces';
2
+ import EventManager from './EventManager';
3
+ export default class KeyboardEventManager extends EventManager<HTMLElement> {
4
+ private activationKeys;
5
+ private cancelationKeys;
6
+ private isPressed;
7
+ private keyDownCallback;
8
+ private keyUpCallback;
9
+ private dispatchEvent;
10
+ registerListeners(): void;
11
+ unregisterListeners(): void;
12
+ protected mapEvent(event: KeyboardEvent, eventType: EventTypes): AdaptedEvent;
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gesture-handler",
3
- "version": "2.18.0",
3
+ "version": "2.19.0",
4
4
  "description": "Experimental implementation of a new declarative API for gesture handling in react-native",
5
5
  "scripts": {
6
6
  "prepare": "bob build && husky install",
@@ -11,7 +11,7 @@
11
11
  "ts-check": "yarn tsc --noEmit",
12
12
  "format:js": "prettier --write --list-different './{src,example,FabricExample,MacOSExample}/**/*.{js,jsx,ts,tsx}'",
13
13
  "format:android": "node ./scripts/format-android.js",
14
- "format:ios": "find apple/ -iname *.h -o -iname *.m -o -iname *.cpp -o -iname *.mm | xargs clang-format -i",
14
+ "format:apple": "find apple/ -iname *.h -o -iname *.m -o -iname *.cpp -o -iname *.mm | xargs clang-format -i",
15
15
  "lint:js": "eslint --ext '.js,.ts,.tsx' src/ example/src FabricExample/src MacOSExample/src && yarn prettier --check './{src,example,FabricExample,MacOSExample}/**/*.{js,jsx,ts,tsx}'",
16
16
  "lint:js-root": "eslint --ext '.js,.ts,.tsx' src/ && yarn prettier --check './src/**/*.{js,jsx,ts,tsx}'",
17
17
  "lint:android": "./android/gradlew -p android spotlessCheck -q",
@@ -114,7 +114,7 @@
114
114
  "lint-staged": {
115
115
  "./{src,example,FabricExample,MacOSExample}/**/*.{ts,tsx}": "yarn format:js",
116
116
  "android/**/*.kt": "yarn format:android",
117
- "apple/**/*.{h,m,mm,cpp}": "yarn format:ios",
117
+ "apple/**/*.{h,m,mm,cpp}": "yarn format:apple",
118
118
  "src/specs/*.ts": "yarn sync-architectures"
119
119
  },
120
120
  "release-it": {
@@ -2,5 +2,6 @@ export enum PointerType {
2
2
  TOUCH,
3
3
  STYLUS,
4
4
  MOUSE,
5
+ KEY,
5
6
  OTHER,
6
7
  }
@@ -22,13 +22,34 @@ import {
22
22
  } from './utils';
23
23
  import { PressabilityDebugView } from '../../handlers/PressabilityDebugView';
24
24
  import { GestureTouchEvent } from '../../handlers/gestureHandlerCommon';
25
+ import { INT32_MAX } from '../../utils';
25
26
 
26
27
  const DEFAULT_LONG_PRESS_DURATION = 500;
27
28
 
28
29
  export default function Pressable(props: PressableProps) {
29
- const [pressedState, setPressedState] = useState(
30
- props.testOnly_pressed ?? false
31
- );
30
+ const {
31
+ testOnly_pressed,
32
+ hitSlop,
33
+ pressRetentionOffset,
34
+ delayHoverIn,
35
+ onHoverIn,
36
+ delayHoverOut,
37
+ onHoverOut,
38
+ delayLongPress,
39
+ unstable_pressDelay,
40
+ onPress,
41
+ onPressIn,
42
+ onPressOut,
43
+ onLongPress,
44
+ style,
45
+ children,
46
+ android_disableSound,
47
+ android_ripple,
48
+ disabled,
49
+ ...remainingProps
50
+ } = props;
51
+
52
+ const [pressedState, setPressedState] = useState(testOnly_pressed ?? false);
32
53
 
33
54
  const pressableRef = useRef<View>(null);
34
55
 
@@ -39,18 +60,16 @@ export default function Pressable(props: PressableProps) {
39
60
 
40
61
  const normalizedHitSlop: Insets = useMemo(
41
62
  () =>
42
- typeof props.hitSlop === 'number'
43
- ? numberAsInset(props.hitSlop)
44
- : props.hitSlop ?? {},
45
- [props.hitSlop]
63
+ typeof hitSlop === 'number' ? numberAsInset(hitSlop) : hitSlop ?? {},
64
+ [hitSlop]
46
65
  );
47
66
 
48
67
  const normalizedPressRetentionOffset: Insets = useMemo(
49
68
  () =>
50
- typeof props.pressRetentionOffset === 'number'
51
- ? numberAsInset(props.pressRetentionOffset)
52
- : props.pressRetentionOffset ?? {},
53
- [props.pressRetentionOffset]
69
+ typeof pressRetentionOffset === 'number'
70
+ ? numberAsInset(pressRetentionOffset)
71
+ : pressRetentionOffset ?? {},
72
+ [pressRetentionOffset]
54
73
  );
55
74
 
56
75
  const hoverInTimeout = useRef<number | null>(null);
@@ -65,29 +84,29 @@ export default function Pressable(props: PressableProps) {
65
84
  if (hoverOutTimeout.current) {
66
85
  clearTimeout(hoverOutTimeout.current);
67
86
  }
68
- if (props.delayHoverIn) {
87
+ if (delayHoverIn) {
69
88
  hoverInTimeout.current = setTimeout(
70
- () => props.onHoverIn?.(gestureToPressableEvent(event)),
71
- props.delayHoverIn
89
+ () => onHoverIn?.(gestureToPressableEvent(event)),
90
+ delayHoverIn
72
91
  );
73
92
  return;
74
93
  }
75
- props.onHoverIn?.(gestureToPressableEvent(event));
94
+ onHoverIn?.(gestureToPressableEvent(event));
76
95
  })
77
96
  .onFinalize((event) => {
78
97
  if (hoverInTimeout.current) {
79
98
  clearTimeout(hoverInTimeout.current);
80
99
  }
81
- if (props.delayHoverOut) {
100
+ if (delayHoverOut) {
82
101
  hoverOutTimeout.current = setTimeout(
83
- () => props.onHoverOut?.(gestureToPressableEvent(event)),
84
- props.delayHoverOut
102
+ () => onHoverOut?.(gestureToPressableEvent(event)),
103
+ delayHoverOut
85
104
  );
86
105
  return;
87
106
  }
88
- props.onHoverOut?.(gestureToPressableEvent(event));
107
+ onHoverOut?.(gestureToPressableEvent(event));
89
108
  }),
90
- [props]
109
+ [delayHoverIn, delayHoverOut, onHoverIn, onHoverOut]
91
110
  );
92
111
 
93
112
  const pressDelayTimeoutRef = useRef<number | null>(null);
@@ -108,12 +127,12 @@ export default function Pressable(props: PressableProps) {
108
127
 
109
128
  deferredEventPayload.current = null;
110
129
 
111
- props.onPressIn?.(event);
130
+ onPressIn?.(event);
112
131
  isPressCallbackEnabled.current = true;
113
132
  pressDelayTimeoutRef.current = null;
114
133
  setPressedState(true);
115
134
  },
116
- [props]
135
+ [onPressIn]
117
136
  );
118
137
 
119
138
  const pressOutHandler = useCallback(
@@ -126,7 +145,7 @@ export default function Pressable(props: PressableProps) {
126
145
  return;
127
146
  }
128
147
 
129
- if (props.unstable_pressDelay && pressDelayTimeoutRef.current !== null) {
148
+ if (unstable_pressDelay && pressDelayTimeoutRef.current !== null) {
130
149
  // When delay is preemptively finished by lifting touches,
131
150
  // we want to immediately activate it's effects - pressInHandler,
132
151
  // even though we are located at the pressOutHandler
@@ -135,14 +154,14 @@ export default function Pressable(props: PressableProps) {
135
154
  }
136
155
 
137
156
  if (deferredEventPayload.current) {
138
- props.onPressIn?.(deferredEventPayload.current);
157
+ onPressIn?.(deferredEventPayload.current);
139
158
  deferredEventPayload.current = null;
140
159
  }
141
160
 
142
- props.onPressOut?.(event);
161
+ onPressOut?.(event);
143
162
 
144
163
  if (isPressCallbackEnabled.current) {
145
- props.onPress?.(event);
164
+ onPress?.(event);
146
165
  }
147
166
 
148
167
  if (longPressTimeoutRef.current) {
@@ -155,7 +174,7 @@ export default function Pressable(props: PressableProps) {
155
174
  isPressCallbackEnabled.current = true;
156
175
  setPressedState(false);
157
176
  },
158
- [pressInHandler, props]
177
+ [onPress, onPressIn, onPressOut, pressInHandler, unstable_pressDelay]
159
178
  );
160
179
 
161
180
  const handlingOnTouchesDown = useRef<boolean>(false);
@@ -169,7 +188,7 @@ export default function Pressable(props: PressableProps) {
169
188
  }
170
189
 
171
190
  if (hasPassedBoundsChecks.current) {
172
- props.onLongPress?.(gestureTouchToPressableEvent(event));
191
+ onLongPress?.(gestureTouchToPressableEvent(event));
173
192
  isPressCallbackEnabled.current = false;
174
193
  }
175
194
 
@@ -178,19 +197,19 @@ export default function Pressable(props: PressableProps) {
178
197
  longPressTimeoutRef.current = null;
179
198
  }
180
199
  },
181
- [props]
200
+ [onLongPress]
182
201
  );
183
202
 
184
203
  const longPressTimeoutRef = useRef<number | null>(null);
185
204
  const longPressMinDuration =
186
- (props.delayLongPress ?? DEFAULT_LONG_PRESS_DURATION) +
187
- (props.unstable_pressDelay ?? 0);
205
+ (delayLongPress ?? DEFAULT_LONG_PRESS_DURATION) +
206
+ (unstable_pressDelay ?? 0);
188
207
 
189
208
  const pressAndTouchGesture = useMemo(
190
209
  () =>
191
210
  Gesture.LongPress()
192
- .minDuration(Number.MAX_SAFE_INTEGER) // Stops long press from blocking native gesture
193
- .maxDistance(Number.MAX_SAFE_INTEGER) // Stops long press from cancelling after set distance
211
+ .minDuration(INT32_MAX) // Stops long press from blocking native gesture
212
+ .maxDistance(INT32_MAX) // Stops long press from cancelling after set distance
194
213
  .cancelsTouchesInView(false)
195
214
  .onTouchesDown((event) => {
196
215
  handlingOnTouchesDown.current = true;
@@ -224,10 +243,10 @@ export default function Pressable(props: PressableProps) {
224
243
  );
225
244
  }
226
245
 
227
- if (props.unstable_pressDelay) {
246
+ if (unstable_pressDelay) {
228
247
  pressDelayTimeoutRef.current = setTimeout(() => {
229
248
  pressInHandler(gestureTouchToPressableEvent(event));
230
- }, props.unstable_pressDelay);
249
+ }, unstable_pressDelay);
231
250
  } else {
232
251
  pressInHandler(gestureTouchToPressableEvent(event));
233
252
  }
@@ -275,7 +294,7 @@ export default function Pressable(props: PressableProps) {
275
294
  normalizedHitSlop,
276
295
  pressInHandler,
277
296
  pressOutHandler,
278
- props.unstable_pressDelay,
297
+ unstable_pressDelay,
279
298
  ]
280
299
  );
281
300
 
@@ -333,7 +352,7 @@ export default function Pressable(props: PressableProps) {
333
352
  normalizedPressRetentionOffset
334
353
  );
335
354
 
336
- const isPressableEnabled = props.disabled !== true;
355
+ const isPressableEnabled = disabled !== true;
337
356
 
338
357
  const gestures = [pressAndTouchGesture, hoverGesture, buttonGesture];
339
358
 
@@ -353,40 +372,41 @@ export default function Pressable(props: PressableProps) {
353
372
 
354
373
  const gesture = Gesture.Simultaneous(...gestures);
355
374
 
356
- const defaultRippleColor = props.android_ripple ? undefined : 'transparent';
375
+ const defaultRippleColor = android_ripple ? undefined : 'transparent';
357
376
 
358
377
  // `cursor: 'pointer'` on `RNButton` crashes iOS
359
378
  const pointerStyle: StyleProp<ViewStyle> =
360
379
  Platform.OS === 'web' ? { cursor: 'pointer' } : {};
361
380
 
362
381
  const styleProp =
363
- typeof props.style === 'function'
364
- ? props.style({ pressed: pressedState })
365
- : props.style;
382
+ typeof style === 'function' ? style({ pressed: pressedState }) : style;
366
383
 
367
384
  const childrenProp =
368
- typeof props.children === 'function'
369
- ? props.children({ pressed: pressedState })
370
- : props.children;
385
+ typeof children === 'function'
386
+ ? children({ pressed: pressedState })
387
+ : children;
371
388
 
372
389
  const flattenedStyles = StyleSheet.flatten(styleProp ?? {});
373
390
 
374
391
  const [innerStyles, outerStyles] = splitStyles(flattenedStyles);
375
392
 
376
393
  return (
377
- <View style={outerStyles}>
394
+ <View {...remainingProps} style={outerStyles}>
378
395
  <GestureDetector gesture={gesture}>
379
396
  <NativeButton
380
397
  ref={pressableRef}
381
- testID={props.testID}
382
398
  hitSlop={appliedHitSlop}
383
399
  enabled={isPressableEnabled}
384
- touchSoundDisabled={props.android_disableSound ?? undefined}
400
+ touchSoundDisabled={android_disableSound ?? undefined}
385
401
  rippleColor={processColor(
386
- props.android_ripple?.color ?? defaultRippleColor
402
+ android_ripple?.color ?? defaultRippleColor
387
403
  )}
388
- rippleRadius={props.android_ripple?.radius ?? undefined}
389
- style={[StyleSheet.absoluteFill, pointerStyle, innerStyles]}>
404
+ rippleRadius={android_ripple?.radius ?? undefined}
405
+ style={[
406
+ { width: '100%', height: '100%' },
407
+ pointerStyle,
408
+ innerStyles,
409
+ ]}>
390
410
  {childrenProp}
391
411
  {__DEV__ ? (
392
412
  <PressabilityDebugView color="red" hitSlop={normalizedHitSlop} />
@@ -1,2 +1,2 @@
1
- export { PressableProps } from './PressableProps';
1
+ export type { PressableProps } from './PressableProps';
2
2
  export { default } from './Pressable';
@@ -199,6 +199,26 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
199
199
  props: SwipeableProps,
200
200
  ref: ForwardedRef<SwipeableMethods>
201
201
  ) {
202
+ const {
203
+ leftThreshold,
204
+ rightThreshold,
205
+ onSwipeableOpenStartDrag,
206
+ onSwipeableCloseStartDrag,
207
+ enableTrackpadTwoFingerGesture,
208
+ enabled,
209
+ containerStyle,
210
+ childrenContainerStyle,
211
+ animationOptions,
212
+ overshootLeft,
213
+ overshootRight,
214
+ onSwipeableWillOpen,
215
+ onSwipeableWillClose,
216
+ onSwipeableOpen,
217
+ onSwipeableClose,
218
+ testID,
219
+ ...remainingProps
220
+ } = props;
221
+
202
222
  const rowState = useSharedValue<number>(0);
203
223
 
204
224
  const userDrag = useSharedValue<number>(0);
@@ -240,8 +260,8 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
240
260
  overshootFriction = defaultProps.overshootFriction,
241
261
  } = props;
242
262
 
243
- const overshootLeftProp = props.overshootLeft;
244
- const overshootRightProp = props.overshootRight;
263
+ const overshootLeftProp = overshootLeft;
264
+ const overshootRightProp = overshootRight;
245
265
 
246
266
  const calculateCurrentOffset = useCallback(() => {
247
267
  'worklet';
@@ -317,45 +337,40 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
317
337
 
318
338
  const dispatchImmediateEvents = useCallback(
319
339
  (fromValue: number, toValue: number) => {
320
- if (toValue > 0 && props.onSwipeableWillOpen) {
321
- props.onSwipeableWillOpen('left');
322
- } else if (toValue < 0 && props.onSwipeableWillOpen) {
323
- props.onSwipeableWillOpen('right');
324
- } else if (props.onSwipeableWillClose) {
340
+ if (toValue > 0 && onSwipeableWillOpen) {
341
+ onSwipeableWillOpen('left');
342
+ } else if (toValue < 0 && onSwipeableWillOpen) {
343
+ onSwipeableWillOpen('right');
344
+ } else if (onSwipeableWillClose) {
325
345
  const closingDirection = fromValue > 0 ? 'left' : 'right';
326
- props.onSwipeableWillClose(closingDirection);
346
+ onSwipeableWillClose(closingDirection);
327
347
  }
328
348
  },
329
- [
330
- props,
331
- props.onSwipeableWillClose,
332
- props.onSwipeableWillOpen,
333
- swipeableMethods,
334
- ]
349
+ [onSwipeableWillClose, onSwipeableWillOpen]
335
350
  );
336
351
 
337
352
  const dispatchEndEvents = useCallback(
338
353
  (fromValue: number, toValue: number) => {
339
- if (toValue > 0 && props.onSwipeableOpen) {
340
- props.onSwipeableOpen('left', swipeableMethods.current);
341
- } else if (toValue < 0 && props.onSwipeableOpen) {
342
- props.onSwipeableOpen('right', swipeableMethods.current);
343
- } else if (props.onSwipeableClose) {
354
+ if (toValue > 0 && onSwipeableOpen) {
355
+ onSwipeableOpen('left', swipeableMethods.current);
356
+ } else if (toValue < 0 && onSwipeableOpen) {
357
+ onSwipeableOpen('right', swipeableMethods.current);
358
+ } else if (onSwipeableClose) {
344
359
  const closingDirection = fromValue > 0 ? 'left' : 'right';
345
- props.onSwipeableClose(closingDirection, swipeableMethods.current);
360
+ onSwipeableClose(closingDirection, swipeableMethods.current);
346
361
  }
347
362
  },
348
- [props, props.onSwipeableClose, props.onSwipeableOpen, swipeableMethods]
363
+ [onSwipeableClose, onSwipeableOpen]
349
364
  );
350
365
 
351
- const animationOptionsProp = props.animationOptions;
366
+ const animationOptionsProp = animationOptions;
352
367
 
353
368
  const animateRow = useCallback(
354
369
  (fromValue: number, toValue: number, velocityX?: number) => {
355
370
  'worklet';
356
371
  rowState.value = Math.sign(toValue);
357
372
 
358
- const springConfig = {
373
+ const translationSpringConfig = {
359
374
  duration: 1000,
360
375
  dampingRatio: 0.9,
361
376
  stiffness: 500,
@@ -364,9 +379,14 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
364
379
  ...animationOptionsProp,
365
380
  };
366
381
 
382
+ const progressSpringConfig = {
383
+ ...translationSpringConfig,
384
+ velocity: 0,
385
+ };
386
+
367
387
  appliedTranslation.value = withSpring(
368
388
  toValue,
369
- springConfig,
389
+ translationSpringConfig,
370
390
  (isFinished) => {
371
391
  if (isFinished) {
372
392
  runOnJS(dispatchEndEvents)(fromValue, toValue);
@@ -376,23 +396,27 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
376
396
 
377
397
  const progressTarget = toValue === 0 ? 0 : 1;
378
398
 
379
- // Velocity is in px, while progress is in %
380
- springConfig.velocity = 0;
381
-
382
399
  showLeftProgress.value =
383
- leftWidth.value > 0 ? withSpring(progressTarget, springConfig) : 0;
400
+ leftWidth.value > 0
401
+ ? withSpring(progressTarget, progressSpringConfig)
402
+ : 0;
384
403
  showRightProgress.value =
385
- rightWidth.value > 0 ? withSpring(progressTarget, springConfig) : 0;
404
+ rightWidth.value > 0
405
+ ? withSpring(progressTarget, progressSpringConfig)
406
+ : 0;
386
407
 
387
408
  runOnJS(dispatchImmediateEvents)(fromValue, toValue);
388
409
  },
389
410
  [
390
- showLeftProgress,
411
+ rowState,
412
+ animationOptionsProp,
391
413
  appliedTranslation,
392
- dispatchEndEvents,
414
+ showLeftProgress,
415
+ leftWidth.value,
416
+ showRightProgress,
417
+ rightWidth.value,
393
418
  dispatchImmediateEvents,
394
- animationOptionsProp,
395
- rowState,
419
+ dispatchEndEvents,
396
420
  ]
397
421
  );
398
422
 
@@ -483,8 +507,8 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
483
507
  </Animated.View>
484
508
  );
485
509
 
486
- const leftThresholdProp = props.leftThreshold;
487
- const rightThresholdProp = props.rightThreshold;
510
+ const leftThresholdProp = leftThreshold;
511
+ const rightThresholdProp = rightThreshold;
488
512
 
489
513
  const handleRelease = (
490
514
  event: GestureStateChangeEvent<PanGestureHandlerEventPayload>
@@ -535,9 +559,6 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
535
559
  }
536
560
  });
537
561
 
538
- const onSwipeableOpenStartDrag = props.onSwipeableOpenStartDrag;
539
- const onSwipeableCloseStartDrag = props.onSwipeableCloseStartDrag;
540
-
541
562
  const panGesture = Gesture.Pan()
542
563
  .onUpdate((event: GestureUpdateEvent<PanGestureHandlerEventPayload>) => {
543
564
  userDrag.value = event.translationX;
@@ -564,10 +585,8 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
564
585
  }
565
586
  );
566
587
 
567
- if (props.enableTrackpadTwoFingerGesture) {
568
- panGesture.enableTrackpadTwoFingerGesture(
569
- props.enableTrackpadTwoFingerGesture
570
- );
588
+ if (enableTrackpadTwoFingerGesture) {
589
+ panGesture.enableTrackpadTwoFingerGesture(enableTrackpadTwoFingerGesture);
571
590
  }
572
591
 
573
592
  panGesture.activeOffsetX([
@@ -580,7 +599,7 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
580
599
  swipeableMethods,
581
600
  ]);
582
601
 
583
- panGesture.enabled(props.enabled !== false);
602
+ panGesture.enabled(enabled !== false);
584
603
 
585
604
  const animatedStyle = useAnimatedStyle(
586
605
  () => ({
@@ -590,12 +609,10 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
590
609
  [appliedTranslation, rowState]
591
610
  );
592
611
 
593
- const containerStyle = props.containerStyle;
594
- const childrenContainerStyle = props.childrenContainerStyle;
595
-
596
- return (
612
+ const swipeableComponent = (
597
613
  <GestureDetector gesture={panGesture} touchAction="pan-y">
598
614
  <Animated.View
615
+ {...remainingProps}
599
616
  onLayout={onRowLayout}
600
617
  style={[styles.container, containerStyle]}>
601
618
  {leftElement}
@@ -608,6 +625,12 @@ const Swipeable = forwardRef<SwipeableMethods, SwipeableProps>(
608
625
  </Animated.View>
609
626
  </GestureDetector>
610
627
  );
628
+
629
+ return testID ? (
630
+ <View testID={testID}>{swipeableComponent}</View>
631
+ ) : (
632
+ swipeableComponent
633
+ );
611
634
  }
612
635
  );
613
636
 
@@ -222,6 +222,12 @@ type SwipeableState = {
222
222
  rowWidth?: number;
223
223
  };
224
224
 
225
+ /**
226
+ * @deprecated use Reanimated version of Swipeable instead
227
+ *
228
+ * This component allows for implementing swipeable rows or similar interaction.
229
+ */
230
+
225
231
  export default class Swipeable extends Component<
226
232
  SwipeableProps,
227
233
  SwipeableState
@@ -8,6 +8,7 @@ import {
8
8
  export const longPressGestureHandlerProps = [
9
9
  'minDurationMs',
10
10
  'maxDist',
11
+ 'numberOfPointers',
11
12
  ] as const;
12
13
 
13
14
  export interface LongPressGestureConfig {
@@ -24,6 +25,11 @@ export interface LongPressGestureConfig {
24
25
  * will fail to recognize the gesture. The default value is 10.
25
26
  */
26
27
  maxDist?: number;
28
+
29
+ /**
30
+ * Determine exact number of points required to handle the long press gesture.
31
+ */
32
+ numberOfPointers?: number;
27
33
  }
28
34
 
29
35
  export interface LongPressGestureHandlerProps