react-native-gesture-handler 2.18.1 → 2.19.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -0
- package/android/build.gradle +4 -17
- package/android/src/main/AndroidManifest.xml +1 -3
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +21 -21
- package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +2 -2
- package/android/src/main/java/com/swmansion/gesturehandler/core/HoverGestureHandler.kt +5 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +80 -4
- package/android/src/main/java/com/swmansion/gesturehandler/core/PinchGestureHandler.kt +2 -1
- package/android/src/main/java/com/swmansion/gesturehandler/core/ScaleGestureDetector.java +10 -0
- package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +2 -2
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +3 -0
- package/apple/Handlers/RNFlingHandler.h +1 -0
- package/apple/Handlers/RNFlingHandler.m +153 -19
- package/apple/Handlers/RNHoverHandler.m +44 -2
- package/apple/Handlers/RNLongPressHandler.m +109 -20
- package/apple/Handlers/RNManualHandler.m +53 -29
- package/apple/Handlers/RNNativeViewHandler.mm +22 -15
- package/apple/RNGHUIKit.h +2 -0
- package/apple/RNGHVector.h +31 -0
- package/apple/RNGHVector.m +67 -0
- package/apple/RNGestureHandler.h +7 -0
- package/apple/{RNGestureHandler.m → RNGestureHandler.mm} +63 -1
- package/apple/RNGestureHandlerButtonComponentView.mm +6 -0
- package/apple/RNGestureHandlerDirection.h +25 -0
- package/lib/commonjs/PointerType.js +2 -1
- package/lib/commonjs/PointerType.js.map +1 -1
- package/lib/commonjs/components/Pressable/Pressable.js +67 -70
- package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
- package/lib/commonjs/components/Pressable/index.js +0 -8
- package/lib/commonjs/components/Pressable/index.js.map +1 -1
- package/lib/commonjs/components/ReanimatedSwipeable.js +60 -41
- package/lib/commonjs/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/commonjs/handlers/LongPressGestureHandler.js +1 -1
- package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/utils.js +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector/utils.js.map +1 -1
- package/lib/commonjs/handlers/gestures/longPressGesture.js +10 -0
- package/lib/commonjs/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/commonjs/mocks.js +16 -3
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/utils.js +4 -0
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/web/constants.js +3 -3
- package/lib/commonjs/web/constants.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +1 -0
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js +43 -9
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +14 -3
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +4 -0
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +55 -8
- package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/commonjs/web/tools/KeyboardEventManager.js +110 -0
- package/lib/commonjs/web/tools/KeyboardEventManager.js.map +1 -0
- package/lib/commonjs/web/tools/Vector.js +4 -2
- package/lib/commonjs/web/tools/Vector.js.map +1 -1
- package/lib/commonjs/web/utils.js +14 -13
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/PointerType.js +2 -1
- package/lib/module/PointerType.js.map +1 -1
- package/lib/module/components/Pressable/Pressable.js +66 -70
- package/lib/module/components/Pressable/Pressable.js.map +1 -1
- package/lib/module/components/Pressable/index.js +0 -1
- package/lib/module/components/Pressable/index.js.map +1 -1
- package/lib/module/components/ReanimatedSwipeable.js +58 -37
- package/lib/module/components/ReanimatedSwipeable.js.map +1 -1
- package/lib/module/handlers/LongPressGestureHandler.js +1 -1
- package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector/utils.js +2 -2
- package/lib/module/handlers/gestures/GestureDetector/utils.js.map +1 -1
- package/lib/module/handlers/gestures/longPressGesture.js +10 -0
- package/lib/module/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/module/mocks.js +13 -3
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/utils.js +1 -0
- package/lib/module/utils.js.map +1 -1
- package/lib/module/web/constants.js +1 -1
- package/lib/module/web/constants.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +1 -0
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/LongPressGestureHandler.js +43 -9
- package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/NativeViewGestureHandler.js +14 -3
- package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +4 -0
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerWebDelegate.js +54 -8
- package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
- package/lib/module/web/tools/KeyboardEventManager.js +96 -0
- package/lib/module/web/tools/KeyboardEventManager.js.map +1 -0
- package/lib/module/web/tools/Vector.js +5 -3
- package/lib/module/web/tools/Vector.js.map +1 -1
- package/lib/module/web/utils.js +14 -13
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/PointerType.d.ts +2 -1
- package/lib/typescript/components/Pressable/index.d.ts +1 -1
- package/lib/typescript/handlers/LongPressGestureHandler.d.ts +5 -1
- package/lib/typescript/handlers/gestures/longPressGesture.d.ts +5 -0
- package/lib/typescript/mocks.d.ts +4 -3
- package/lib/typescript/utils.d.ts +1 -0
- package/lib/typescript/web/constants.d.ts +1 -1
- package/lib/typescript/web/handlers/GestureHandler.d.ts +1 -1
- package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +3 -0
- package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
- package/lib/typescript/web/interfaces.d.ts +1 -1
- package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +1 -0
- package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +6 -0
- package/lib/typescript/web/tools/KeyboardEventManager.d.ts +13 -0
- package/package.json +3 -3
- package/src/PointerType.ts +1 -0
- package/src/components/Pressable/Pressable.tsx +70 -50
- package/src/components/Pressable/index.ts +1 -1
- package/src/components/ReanimatedSwipeable.tsx +70 -47
- package/src/handlers/LongPressGestureHandler.ts +6 -0
- package/src/handlers/gestures/GestureDetector/utils.ts +2 -2
- package/src/handlers/gestures/longPressGesture.ts +9 -0
- package/src/{mocks.ts → mocks.tsx} +8 -3
- package/src/utils.ts +2 -0
- package/src/web/constants.ts +1 -1
- package/src/web/handlers/GestureHandler.ts +3 -1
- package/src/web/handlers/LongPressGestureHandler.ts +49 -10
- package/src/web/handlers/NativeViewGestureHandler.ts +14 -4
- package/src/web/handlers/PanGestureHandler.ts +4 -0
- package/src/web/interfaces.ts +1 -1
- package/src/web/tools/GestureHandlerDelegate.ts +1 -0
- package/src/web/tools/GestureHandlerWebDelegate.ts +67 -8
- package/src/web/tools/KeyboardEventManager.ts +91 -0
- package/src/web/tools/Vector.ts +4 -3
- package/src/web/utils.ts +15 -13
@@ -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
|
20
|
+
enabled: boolean;
|
21
21
|
simultaneousHandlers?: Handler[] | null;
|
22
22
|
waitFor?: Handler[] | null;
|
23
23
|
blocksHandlers?: Handler[] | null;
|
@@ -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.
|
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:
|
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:
|
117
|
+
"apple/**/*.{h,m,mm,cpp}": "yarn format:apple",
|
118
118
|
"src/specs/*.ts": "yarn sync-architectures"
|
119
119
|
},
|
120
120
|
"release-it": {
|
package/src/PointerType.ts
CHANGED
@@ -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
|
30
|
-
|
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
|
43
|
-
|
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
|
51
|
-
? numberAsInset(
|
52
|
-
:
|
53
|
-
[
|
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 (
|
87
|
+
if (delayHoverIn) {
|
69
88
|
hoverInTimeout.current = setTimeout(
|
70
|
-
() =>
|
71
|
-
|
89
|
+
() => onHoverIn?.(gestureToPressableEvent(event)),
|
90
|
+
delayHoverIn
|
72
91
|
);
|
73
92
|
return;
|
74
93
|
}
|
75
|
-
|
94
|
+
onHoverIn?.(gestureToPressableEvent(event));
|
76
95
|
})
|
77
96
|
.onFinalize((event) => {
|
78
97
|
if (hoverInTimeout.current) {
|
79
98
|
clearTimeout(hoverInTimeout.current);
|
80
99
|
}
|
81
|
-
if (
|
100
|
+
if (delayHoverOut) {
|
82
101
|
hoverOutTimeout.current = setTimeout(
|
83
|
-
() =>
|
84
|
-
|
102
|
+
() => onHoverOut?.(gestureToPressableEvent(event)),
|
103
|
+
delayHoverOut
|
85
104
|
);
|
86
105
|
return;
|
87
106
|
}
|
88
|
-
|
107
|
+
onHoverOut?.(gestureToPressableEvent(event));
|
89
108
|
}),
|
90
|
-
[
|
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
|
-
|
130
|
+
onPressIn?.(event);
|
112
131
|
isPressCallbackEnabled.current = true;
|
113
132
|
pressDelayTimeoutRef.current = null;
|
114
133
|
setPressedState(true);
|
115
134
|
},
|
116
|
-
[
|
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 (
|
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
|
-
|
157
|
+
onPressIn?.(deferredEventPayload.current);
|
139
158
|
deferredEventPayload.current = null;
|
140
159
|
}
|
141
160
|
|
142
|
-
|
161
|
+
onPressOut?.(event);
|
143
162
|
|
144
163
|
if (isPressCallbackEnabled.current) {
|
145
|
-
|
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,
|
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
|
-
|
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
|
-
[
|
200
|
+
[onLongPress]
|
182
201
|
);
|
183
202
|
|
184
203
|
const longPressTimeoutRef = useRef<number | null>(null);
|
185
204
|
const longPressMinDuration =
|
186
|
-
(
|
187
|
-
(
|
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(
|
193
|
-
.maxDistance(
|
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 (
|
246
|
+
if (unstable_pressDelay) {
|
228
247
|
pressDelayTimeoutRef.current = setTimeout(() => {
|
229
248
|
pressInHandler(gestureTouchToPressableEvent(event));
|
230
|
-
},
|
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
|
-
|
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 =
|
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 =
|
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
|
364
|
-
? props.style({ pressed: pressedState })
|
365
|
-
: props.style;
|
382
|
+
typeof style === 'function' ? style({ pressed: pressedState }) : style;
|
366
383
|
|
367
384
|
const childrenProp =
|
368
|
-
typeof
|
369
|
-
?
|
370
|
-
:
|
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={
|
400
|
+
touchSoundDisabled={android_disableSound ?? undefined}
|
385
401
|
rippleColor={processColor(
|
386
|
-
|
402
|
+
android_ripple?.color ?? defaultRippleColor
|
387
403
|
)}
|
388
|
-
rippleRadius={
|
389
|
-
style={[
|
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 =
|
244
|
-
const overshootRightProp =
|
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 &&
|
321
|
-
|
322
|
-
} else if (toValue < 0 &&
|
323
|
-
|
324
|
-
} else if (
|
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
|
-
|
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 &&
|
340
|
-
|
341
|
-
} else if (toValue < 0 &&
|
342
|
-
|
343
|
-
} else if (
|
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
|
-
|
360
|
+
onSwipeableClose(closingDirection, swipeableMethods.current);
|
346
361
|
}
|
347
362
|
},
|
348
|
-
[
|
363
|
+
[onSwipeableClose, onSwipeableOpen]
|
349
364
|
);
|
350
365
|
|
351
|
-
const animationOptionsProp =
|
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
|
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
|
-
|
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
|
400
|
+
leftWidth.value > 0
|
401
|
+
? withSpring(progressTarget, progressSpringConfig)
|
402
|
+
: 0;
|
384
403
|
showRightProgress.value =
|
385
|
-
rightWidth.value > 0
|
404
|
+
rightWidth.value > 0
|
405
|
+
? withSpring(progressTarget, progressSpringConfig)
|
406
|
+
: 0;
|
386
407
|
|
387
408
|
runOnJS(dispatchImmediateEvents)(fromValue, toValue);
|
388
409
|
},
|
389
410
|
[
|
390
|
-
|
411
|
+
rowState,
|
412
|
+
animationOptionsProp,
|
391
413
|
appliedTranslation,
|
392
|
-
|
414
|
+
showLeftProgress,
|
415
|
+
leftWidth.value,
|
416
|
+
showRightProgress,
|
417
|
+
rightWidth.value,
|
393
418
|
dispatchImmediateEvents,
|
394
|
-
|
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 =
|
487
|
-
const rightThresholdProp =
|
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 (
|
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(
|
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
|
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
|
|
@@ -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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Platform } from 'react-native';
|
2
2
|
|
3
|
-
import { tagMessage } from '../../../utils';
|
3
|
+
import { isJestEnv, tagMessage } from '../../../utils';
|
4
4
|
import { GestureRef, BaseGesture, GestureType } from '../gesture';
|
5
5
|
|
6
6
|
import { flingGestureHandlerProps } from '../../FlingGestureHandler';
|
@@ -100,7 +100,7 @@ export function checkGestureCallbacksForWorklets(gesture: GestureType) {
|
|
100
100
|
const areAllNotWorklets = !areSomeWorklets && areSomeNotWorklets;
|
101
101
|
// If none of the callbacks are worklets and the gesture is not explicitly marked with
|
102
102
|
// `.runOnJS(true)` show a warning
|
103
|
-
if (areAllNotWorklets) {
|
103
|
+
if (areAllNotWorklets && !isJestEnv()) {
|
104
104
|
console.warn(
|
105
105
|
tagMessage(
|
106
106
|
`None of the callbacks in the gesture are worklets. If you wish to run them on the JS thread use '.runOnJS(true)' modifier on the gesture to make this explicit. Otherwise, mark the callbacks as 'worklet' to run them on the UI thread.`
|