react-native-gesture-handler 2.3.2 → 2.4.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.
- package/RNGestureHandler.podspec +2 -1
- package/android/build.gradle +38 -6
- package/android/lib/src/main/java/com/swmansion/gesturehandler/GestureHandler.kt +14 -2
- package/android/noreanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +10 -0
- package/android/reanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +17 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEnabledRootView.kt +3 -41
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEvent.kt +6 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +10 -54
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +2 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerStateChangeEvent.kt +6 -0
- package/ios/RNGHTouchEventType.h +9 -0
- package/ios/RNGestureHandler.h +2 -2
- package/ios/RNGestureHandler.m +21 -8
- package/ios/RNGestureHandlerButton.h +1 -0
- package/ios/RNGestureHandlerButton.m +9 -1
- package/ios/RNGestureHandlerButtonComponentView.mm +14 -1
- package/ios/RNGestureHandlerButtonManager.m +4 -1
- package/ios/RNGestureHandlerEvents.h +2 -2
- package/ios/RNGestureHandlerEvents.m +2 -2
- package/ios/RNGestureHandlerManager.h +2 -0
- package/ios/RNGestureHandlerManager.mm +30 -20
- package/ios/RNGestureHandlerModule.mm +18 -0
- package/ios/RNGestureHandlerPointerTracker.h +2 -2
- package/ios/RNGestureHandlerPointerTracker.m +9 -6
- package/ios/RNGestureHandlerRegistry.h +1 -0
- package/ios/RNGestureHandlerRegistry.m +10 -0
- package/lib/commonjs/GestureHandlerRootView.android.js +7 -1
- package/lib/commonjs/GestureHandlerRootView.android.js.map +1 -1
- package/lib/commonjs/GestureHandlerRootView.js +6 -0
- package/lib/commonjs/GestureHandlerRootView.js.map +1 -1
- package/lib/commonjs/GestureHandlerRootView.web.js +19 -0
- package/lib/commonjs/GestureHandlerRootView.web.js.map +1 -0
- package/lib/commonjs/RNGestureHandlerModule.js +5 -0
- package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/RNGestureHandlerModule.web.js +4 -1
- package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/commonjs/{EventType.js → TouchEventType.js} +4 -4
- package/lib/commonjs/TouchEventType.js.map +1 -0
- package/lib/commonjs/components/DrawerLayout.js +38 -11
- package/lib/commonjs/components/DrawerLayout.js.map +1 -1
- package/lib/commonjs/components/GestureButtons.js.map +1 -1
- package/lib/commonjs/components/GestureHandlerButton.js +1 -1
- package/lib/commonjs/components/GestureHandlerButton.js.map +1 -1
- package/lib/commonjs/components/touchables/GenericTouchable.js +2 -0
- package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js +4 -6
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js +4 -6
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/commonjs/getShadowNodeFromRef.js +12 -9
- package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
- package/lib/commonjs/handlers/ForceTouchGestureHandler.js +2 -1
- package/lib/commonjs/handlers/ForceTouchGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/createHandler.js +25 -20
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestureHandlerCommon.js +18 -1
- package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector.js +120 -80
- package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/commonjs/handlers/gestures/eventReceiver.js +6 -5
- package/lib/commonjs/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/commonjs/handlers/gestures/gesture.js +24 -4
- package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
- package/lib/commonjs/init.js +10 -1
- package/lib/commonjs/init.js.map +1 -1
- package/lib/commonjs/mocks.js +2 -0
- package/lib/commonjs/mocks.js.map +1 -1
- package/lib/commonjs/utils.js +23 -1
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/commonjs/web/GestureHandler.js +4 -1
- package/lib/commonjs/web/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/utils.js.map +1 -1
- package/lib/module/GestureHandlerRootView.android.js +7 -2
- package/lib/module/GestureHandlerRootView.android.js.map +1 -1
- package/lib/module/GestureHandlerRootView.js +5 -0
- package/lib/module/GestureHandlerRootView.js.map +1 -1
- package/lib/module/GestureHandlerRootView.web.js +6 -0
- package/lib/module/GestureHandlerRootView.web.js.map +1 -0
- package/lib/module/RNGestureHandlerModule.js +5 -0
- package/lib/module/RNGestureHandlerModule.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.web.js +4 -1
- package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/module/{EventType.js → TouchEventType.js} +2 -2
- package/lib/module/TouchEventType.js.map +1 -0
- package/lib/module/components/DrawerLayout.js +38 -11
- package/lib/module/components/DrawerLayout.js.map +1 -1
- package/lib/module/components/GestureButtons.js.map +1 -1
- package/lib/module/components/GestureHandlerButton.js +2 -2
- package/lib/module/components/GestureHandlerButton.js.map +1 -1
- package/lib/module/components/touchables/GenericTouchable.js +2 -0
- package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js +5 -7
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js +5 -8
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/module/getShadowNodeFromRef.js +11 -8
- package/lib/module/getShadowNodeFromRef.js.map +1 -1
- package/lib/module/handlers/ForceTouchGestureHandler.js +1 -1
- package/lib/module/handlers/ForceTouchGestureHandler.js.map +1 -1
- package/lib/module/handlers/createHandler.js +25 -22
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/handlers/gestureHandlerCommon.js +11 -1
- package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector.js +120 -81
- package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/module/handlers/gestures/eventReceiver.js +6 -7
- package/lib/module/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/module/handlers/gestures/gesture.js +23 -4
- package/lib/module/handlers/gestures/gesture.js.map +1 -1
- package/lib/module/init.js +6 -1
- package/lib/module/init.js.map +1 -1
- package/lib/module/mocks.js +2 -0
- package/lib/module/mocks.js.map +1 -1
- package/lib/module/utils.js +17 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/module/web/GestureHandler.js +4 -1
- package/lib/module/web/GestureHandler.js.map +1 -1
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/GestureHandlerRootView.web.d.ts +5 -0
- package/lib/typescript/RNGestureHandlerModule.d.ts +1 -0
- package/lib/typescript/RNGestureHandlerModule.web.d.ts +1 -0
- package/lib/typescript/{EventType.d.ts → TouchEventType.d.ts} +2 -2
- package/lib/typescript/components/DrawerLayout.d.ts +3 -0
- package/lib/typescript/components/GestureButtons.d.ts +18 -6
- package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +13 -0
- package/lib/typescript/fabric/RNGestureHandlerRootViewNativeComponent.d.ts +5 -0
- package/lib/typescript/handlers/ForceTouchGestureHandler.d.ts +2 -2
- package/lib/typescript/handlers/NativeViewGestureHandler.d.ts +1 -1
- package/lib/typescript/handlers/gestureHandlerCommon.d.ts +6 -3
- package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -4
- package/lib/typescript/handlers/gestures/eventReceiver.d.ts +2 -0
- package/lib/typescript/handlers/gestures/gesture.d.ts +5 -0
- package/lib/typescript/init.d.ts +1 -0
- package/lib/typescript/mocks.d.ts +1 -0
- package/lib/typescript/utils.d.ts +2 -0
- package/lib/typescript/web/GestureHandler.d.ts +1 -1
- package/package.json +4 -2
- package/src/GestureHandlerRootView.android.tsx +8 -2
- package/src/GestureHandlerRootView.tsx +6 -0
- package/src/GestureHandlerRootView.web.tsx +12 -0
- package/src/RNGestureHandlerModule.ts +7 -0
- package/src/RNGestureHandlerModule.web.ts +2 -0
- package/src/{EventType.ts → TouchEventType.ts} +2 -2
- package/src/components/DrawerLayout.tsx +34 -10
- package/src/components/GestureButtons.tsx +21 -7
- package/src/components/GestureHandlerButton.tsx +2 -2
- package/src/components/touchables/GenericTouchable.tsx +2 -0
- package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +27 -0
- package/src/fabric/RNGestureHandlerRootViewNativeComponent.ts +12 -0
- package/src/getShadowNodeFromRef.ts +12 -9
- package/src/handlers/ForceTouchGestureHandler.ts +3 -2
- package/src/handlers/createHandler.ts +30 -26
- package/src/handlers/gestureHandlerCommon.ts +21 -2
- package/src/handlers/gestures/GestureDetector.tsx +164 -105
- package/src/handlers/gestures/eventReceiver.ts +6 -6
- package/src/handlers/gestures/gesture.ts +29 -2
- package/src/init.ts +8 -1
- package/src/mocks.ts +2 -0
- package/src/utils.ts +20 -0
- package/src/web/GestureHandler.ts +7 -1
- package/src/web/utils.ts +1 -1
- package/ios/RNTouchEventType.h +0 -9
- package/lib/commonjs/EventType.js.map +0 -1
- package/lib/module/EventType.js.map +0 -1
- package/src/fabric/RNGestureHandlerButtonNativeComponent.js +0 -27
- package/src/fabric/RNGestureHandlerRootViewNativeComponent.js +0 -19
|
@@ -6,16 +6,18 @@ import * as React from 'react';
|
|
|
6
6
|
import { Platform, findNodeHandle as findNodeHandleRN } from 'react-native';
|
|
7
7
|
|
|
8
8
|
import { State } from '../State';
|
|
9
|
-
import {
|
|
9
|
+
import { TouchEventType } from '../TouchEventType';
|
|
10
10
|
import { ValueOf } from '../typeUtils';
|
|
11
11
|
import { handlerIDToTag } from './handlersRegistry';
|
|
12
12
|
import { toArray } from '../utils';
|
|
13
|
+
import RNGestureHandlerModule from '../RNGestureHandlerModule';
|
|
13
14
|
|
|
14
15
|
const commonProps = [
|
|
15
16
|
'id',
|
|
16
17
|
'enabled',
|
|
17
18
|
'shouldCancelWhenOutside',
|
|
18
19
|
'hitSlop',
|
|
20
|
+
'cancelsTouchesInView',
|
|
19
21
|
] as const;
|
|
20
22
|
|
|
21
23
|
const componentInteractionProps = ['waitFor', 'simultaneousHandlers'] as const;
|
|
@@ -83,7 +85,7 @@ export type GestureTouchEvent = {
|
|
|
83
85
|
handlerTag: number;
|
|
84
86
|
numberOfTouches: number;
|
|
85
87
|
state: ValueOf<typeof State>;
|
|
86
|
-
eventType:
|
|
88
|
+
eventType: TouchEventType;
|
|
87
89
|
allTouches: TouchData[];
|
|
88
90
|
changedTouches: TouchData[];
|
|
89
91
|
};
|
|
@@ -111,6 +113,7 @@ export type BaseGestureHandlerProps<
|
|
|
111
113
|
waitFor?: React.Ref<unknown> | React.Ref<unknown>[];
|
|
112
114
|
simultaneousHandlers?: React.Ref<unknown> | React.Ref<unknown>[];
|
|
113
115
|
testID?: string;
|
|
116
|
+
cancelsTouchesInView?: boolean;
|
|
114
117
|
// TODO(TS) - fix event types
|
|
115
118
|
onBegan?: (event: HandlerStateChangeEvent) => void;
|
|
116
119
|
onFailed?: (event: HandlerStateChangeEvent) => void;
|
|
@@ -123,6 +126,8 @@ export type BaseGestureHandlerProps<
|
|
|
123
126
|
onHandlerStateChange?: (
|
|
124
127
|
event: HandlerStateChangeEvent<ExtraEventPayloadT>
|
|
125
128
|
) => void;
|
|
129
|
+
// implicit `children` prop has been removed in @types/react^18.0.0
|
|
130
|
+
children?: React.ReactNode;
|
|
126
131
|
};
|
|
127
132
|
|
|
128
133
|
function isConfigParam(param: unknown, name: string) {
|
|
@@ -180,3 +185,17 @@ export function findNodeHandle(
|
|
|
180
185
|
if (Platform.OS === 'web') return node;
|
|
181
186
|
return findNodeHandleRN(node);
|
|
182
187
|
}
|
|
188
|
+
|
|
189
|
+
let scheduledFlushOperationsId: ReturnType<
|
|
190
|
+
typeof requestAnimationFrame
|
|
191
|
+
> | null = null;
|
|
192
|
+
|
|
193
|
+
export function scheduleFlushOperations() {
|
|
194
|
+
if (scheduledFlushOperationsId === null) {
|
|
195
|
+
scheduledFlushOperationsId = requestAnimationFrame(() => {
|
|
196
|
+
RNGestureHandlerModule.flushOperations();
|
|
197
|
+
|
|
198
|
+
scheduledFlushOperationsId = null;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
GestureTouchEvent,
|
|
17
17
|
GestureUpdateEvent,
|
|
18
18
|
GestureStateChangeEvent,
|
|
19
|
+
HandlerStateChangeEvent,
|
|
20
|
+
scheduleFlushOperations,
|
|
19
21
|
} from '../gestureHandlerCommon';
|
|
20
22
|
import {
|
|
21
23
|
GestureStateManager,
|
|
@@ -30,15 +32,18 @@ import {
|
|
|
30
32
|
} from '../PanGestureHandler';
|
|
31
33
|
import { tapGestureHandlerProps } from '../TapGestureHandler';
|
|
32
34
|
import { State } from '../../State';
|
|
33
|
-
import {
|
|
35
|
+
import { TouchEventType } from '../../TouchEventType';
|
|
34
36
|
import { ComposedGesture } from './gestureComposition';
|
|
35
37
|
import { ActionType } from '../../ActionType';
|
|
36
38
|
import { isFabric, tagMessage } from '../../utils';
|
|
37
39
|
import { getShadowNodeFromRef } from '../../getShadowNodeFromRef';
|
|
40
|
+
import { Platform } from 'react-native';
|
|
41
|
+
import type RNGestureHandlerModuleWeb from '../../RNGestureHandlerModule.web';
|
|
42
|
+
import { onGestureHandlerEvent } from './eventReceiver';
|
|
38
43
|
|
|
39
|
-
declare global {
|
|
40
|
-
|
|
41
|
-
}
|
|
44
|
+
declare const global: {
|
|
45
|
+
isFormsStackingContext: (node: unknown) => boolean | null; // JSI function
|
|
46
|
+
};
|
|
42
47
|
|
|
43
48
|
const ALLOWED_PROPS = [
|
|
44
49
|
...baseGestureHandlerWithMonitorProps,
|
|
@@ -84,6 +89,8 @@ function dropHandlers(preparedGesture: GestureConfigReference) {
|
|
|
84
89
|
|
|
85
90
|
unregisterHandler(handler.handlerTag, handler.config.testId);
|
|
86
91
|
}
|
|
92
|
+
|
|
93
|
+
scheduleFlushOperations();
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
function checkGestureCallbacksForWorklets(gesture: GestureType) {
|
|
@@ -107,11 +114,16 @@ function checkGestureCallbacksForWorklets(gesture: GestureType) {
|
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
116
|
|
|
117
|
+
interface WebEventHandler {
|
|
118
|
+
onGestureHandlerEvent: (event: HandlerStateChangeEvent<unknown>) => void;
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
interface AttachHandlersConfig {
|
|
111
122
|
preparedGesture: GestureConfigReference;
|
|
112
123
|
gestureConfig: ComposedGesture | GestureType | undefined;
|
|
113
124
|
gesture: GestureType[];
|
|
114
125
|
viewTag: number;
|
|
126
|
+
webEventHandlersRef: React.RefObject<WebEventHandler>;
|
|
115
127
|
}
|
|
116
128
|
|
|
117
129
|
function attachHandlers({
|
|
@@ -119,6 +131,7 @@ function attachHandlers({
|
|
|
119
131
|
gestureConfig,
|
|
120
132
|
gesture,
|
|
121
133
|
viewTag,
|
|
134
|
+
webEventHandlersRef,
|
|
122
135
|
}: AttachHandlersConfig) {
|
|
123
136
|
if (!preparedGesture.firstExecution) {
|
|
124
137
|
gestureConfig?.initialize();
|
|
@@ -142,10 +155,12 @@ function attachHandlers({
|
|
|
142
155
|
);
|
|
143
156
|
|
|
144
157
|
registerHandler(handler.handlerTag, handler, handler.config.testId);
|
|
158
|
+
}
|
|
145
159
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
// use setImmediate to extract handlerTags, because all refs should be initialized
|
|
161
|
+
// when it's ran
|
|
162
|
+
setImmediate(() => {
|
|
163
|
+
for (const handler of gesture) {
|
|
149
164
|
let requireToFail: number[] = [];
|
|
150
165
|
if (handler.config.requireToFail) {
|
|
151
166
|
requireToFail = extractValidHandlerTags(handler.config.requireToFail);
|
|
@@ -165,8 +180,11 @@ function attachHandlers({
|
|
|
165
180
|
waitFor: requireToFail,
|
|
166
181
|
})
|
|
167
182
|
);
|
|
168
|
-
}
|
|
169
|
-
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
scheduleFlushOperations();
|
|
186
|
+
});
|
|
187
|
+
|
|
170
188
|
preparedGesture.config = gesture;
|
|
171
189
|
|
|
172
190
|
for (const gesture of preparedGesture.config) {
|
|
@@ -174,11 +192,20 @@ function attachHandlers({
|
|
|
174
192
|
? ActionType.REANIMATED_WORKLET
|
|
175
193
|
: ActionType.JS_FUNCTION_NEW_API;
|
|
176
194
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
195
|
+
if (Platform.OS === 'web') {
|
|
196
|
+
(RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler)(
|
|
197
|
+
gesture.handlerTag,
|
|
198
|
+
viewTag,
|
|
199
|
+
ActionType.JS_FUNCTION_OLD_API, // ignored on web
|
|
200
|
+
webEventHandlersRef
|
|
201
|
+
);
|
|
202
|
+
} else {
|
|
203
|
+
RNGestureHandlerModule.attachGestureHandler(
|
|
204
|
+
gesture.handlerTag,
|
|
205
|
+
viewTag,
|
|
206
|
+
actionType
|
|
207
|
+
);
|
|
208
|
+
}
|
|
182
209
|
}
|
|
183
210
|
|
|
184
211
|
if (preparedGesture.animatedHandlers) {
|
|
@@ -241,12 +268,37 @@ function updateHandlers(
|
|
|
241
268
|
}
|
|
242
269
|
|
|
243
270
|
if (preparedGesture.animatedHandlers) {
|
|
244
|
-
|
|
271
|
+
const previousHandlersValue =
|
|
272
|
+
preparedGesture.animatedHandlers.value ?? [];
|
|
273
|
+
const newHandlersValue = (preparedGesture.config
|
|
245
274
|
.filter((g) => g.shouldUseReanimated) // ignore gestures that shouldn't run on UI
|
|
246
275
|
.map((g) => g.handlers) as unknown) as HandlerCallbacks<
|
|
247
276
|
Record<string, unknown>
|
|
248
277
|
>[];
|
|
278
|
+
|
|
279
|
+
// if amount of gesture configs changes, we need to update the callbacks in shared value
|
|
280
|
+
let shouldUpdateSharedValue =
|
|
281
|
+
previousHandlersValue.length !== newHandlersValue.length;
|
|
282
|
+
|
|
283
|
+
if (!shouldUpdateSharedValue) {
|
|
284
|
+
// if the amount is the same, we need to check if any of the configs inside has changed
|
|
285
|
+
for (let i = 0; i < newHandlersValue.length; i++) {
|
|
286
|
+
if (
|
|
287
|
+
// we can use the `gestureId` prop as it's unique for every config instance
|
|
288
|
+
newHandlersValue[i].gestureId !== previousHandlersValue[i].gestureId
|
|
289
|
+
) {
|
|
290
|
+
shouldUpdateSharedValue = true;
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (shouldUpdateSharedValue) {
|
|
297
|
+
preparedGesture.animatedHandlers.value = newHandlersValue;
|
|
298
|
+
}
|
|
249
299
|
}
|
|
300
|
+
|
|
301
|
+
scheduleFlushOperations();
|
|
250
302
|
});
|
|
251
303
|
}
|
|
252
304
|
|
|
@@ -270,88 +322,90 @@ function needsToReattach(
|
|
|
270
322
|
return false;
|
|
271
323
|
}
|
|
272
324
|
|
|
273
|
-
function
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
325
|
+
function isStateChangeEvent(
|
|
326
|
+
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
|
327
|
+
): event is GestureStateChangeEvent {
|
|
328
|
+
'worklet';
|
|
329
|
+
// @ts-ignore Yes, the oldState prop is missing on GestureTouchEvent, that's the point
|
|
330
|
+
return event.oldState != null;
|
|
331
|
+
}
|
|
280
332
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
333
|
+
function isTouchEvent(
|
|
334
|
+
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
|
335
|
+
): event is GestureTouchEvent {
|
|
336
|
+
'worklet';
|
|
337
|
+
return event.eventType != null;
|
|
338
|
+
}
|
|
288
339
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
340
|
+
function getHandler(
|
|
341
|
+
type: CALLBACK_TYPE,
|
|
342
|
+
gesture: HandlerCallbacks<Record<string, unknown>>
|
|
343
|
+
) {
|
|
344
|
+
'worklet';
|
|
345
|
+
switch (type) {
|
|
346
|
+
case CALLBACK_TYPE.BEGAN:
|
|
347
|
+
return gesture.onBegin;
|
|
348
|
+
case CALLBACK_TYPE.START:
|
|
349
|
+
return gesture.onStart;
|
|
350
|
+
case CALLBACK_TYPE.UPDATE:
|
|
351
|
+
return gesture.onUpdate;
|
|
352
|
+
case CALLBACK_TYPE.CHANGE:
|
|
353
|
+
return gesture.onChange;
|
|
354
|
+
case CALLBACK_TYPE.END:
|
|
355
|
+
return gesture.onEnd;
|
|
356
|
+
case CALLBACK_TYPE.FINALIZE:
|
|
357
|
+
return gesture.onFinalize;
|
|
358
|
+
case CALLBACK_TYPE.TOUCHES_DOWN:
|
|
359
|
+
return gesture.onTouchesDown;
|
|
360
|
+
case CALLBACK_TYPE.TOUCHES_MOVE:
|
|
361
|
+
return gesture.onTouchesMove;
|
|
362
|
+
case CALLBACK_TYPE.TOUCHES_UP:
|
|
363
|
+
return gesture.onTouchesUp;
|
|
364
|
+
case CALLBACK_TYPE.TOUCHES_CANCELLED:
|
|
365
|
+
return gesture.onTouchesCancelled;
|
|
294
366
|
}
|
|
367
|
+
}
|
|
295
368
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return gesture.onChange;
|
|
310
|
-
case CALLBACK_TYPE.END:
|
|
311
|
-
return gesture.onEnd;
|
|
312
|
-
case CALLBACK_TYPE.FINALIZE:
|
|
313
|
-
return gesture.onFinalize;
|
|
314
|
-
case CALLBACK_TYPE.TOUCHES_DOWN:
|
|
315
|
-
return gesture.onTouchesDown;
|
|
316
|
-
case CALLBACK_TYPE.TOUCHES_MOVE:
|
|
317
|
-
return gesture.onTouchesMove;
|
|
318
|
-
case CALLBACK_TYPE.TOUCHES_UP:
|
|
319
|
-
return gesture.onTouchesUp;
|
|
320
|
-
case CALLBACK_TYPE.TOUCHES_CANCELLED:
|
|
321
|
-
return gesture.onTouchesCancelled;
|
|
322
|
-
}
|
|
369
|
+
function touchEventTypeToCallbackType(
|
|
370
|
+
eventType: TouchEventType
|
|
371
|
+
): CALLBACK_TYPE {
|
|
372
|
+
'worklet';
|
|
373
|
+
switch (eventType) {
|
|
374
|
+
case TouchEventType.TOUCHES_DOWN:
|
|
375
|
+
return CALLBACK_TYPE.TOUCHES_DOWN;
|
|
376
|
+
case TouchEventType.TOUCHES_MOVE:
|
|
377
|
+
return CALLBACK_TYPE.TOUCHES_MOVE;
|
|
378
|
+
case TouchEventType.TOUCHES_UP:
|
|
379
|
+
return CALLBACK_TYPE.TOUCHES_UP;
|
|
380
|
+
case TouchEventType.TOUCHES_CANCELLED:
|
|
381
|
+
return CALLBACK_TYPE.TOUCHES_CANCELLED;
|
|
323
382
|
}
|
|
383
|
+
return CALLBACK_TYPE.UNDEFINED;
|
|
384
|
+
}
|
|
324
385
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
386
|
+
function runWorklet(
|
|
387
|
+
type: CALLBACK_TYPE,
|
|
388
|
+
gesture: HandlerCallbacks<Record<string, unknown>>,
|
|
389
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
|
390
|
+
...args: any[]
|
|
391
|
+
) {
|
|
392
|
+
'worklet';
|
|
393
|
+
const handler = getHandler(type, gesture);
|
|
394
|
+
if (gesture.isWorklet[type]) {
|
|
395
|
+
// @ts-ignore Logic below makes sure the correct event is send to the
|
|
396
|
+
// correct handler.
|
|
397
|
+
handler?.(event, ...args);
|
|
398
|
+
} else if (handler) {
|
|
399
|
+
console.warn(tagMessage('Animated gesture callback must be a worklet'));
|
|
338
400
|
}
|
|
401
|
+
}
|
|
339
402
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
'worklet';
|
|
347
|
-
const handler = getHandler(type, gesture);
|
|
348
|
-
if (gesture.isWorklet[type]) {
|
|
349
|
-
// @ts-ignore Logic below makes sure the correct event is send to the
|
|
350
|
-
// correct handler.
|
|
351
|
-
handler?.(event, ...args);
|
|
352
|
-
} else if (handler) {
|
|
353
|
-
console.warn(tagMessage('Animated gesture callback must be a worklet'));
|
|
354
|
-
}
|
|
403
|
+
function useAnimatedGesture(
|
|
404
|
+
preparedGesture: GestureConfigReference,
|
|
405
|
+
needsRebuild: boolean
|
|
406
|
+
) {
|
|
407
|
+
if (!Reanimated) {
|
|
408
|
+
return;
|
|
355
409
|
}
|
|
356
410
|
|
|
357
411
|
// Hooks are called conditionally, but the condition is whether the
|
|
@@ -418,7 +472,7 @@ function useAnimatedGesture(
|
|
|
418
472
|
stateControllers[i] = GestureStateManager.create(event.handlerTag);
|
|
419
473
|
}
|
|
420
474
|
|
|
421
|
-
if (event.eventType !==
|
|
475
|
+
if (event.eventType !== TouchEventType.UNDETERMINED) {
|
|
422
476
|
runWorklet(
|
|
423
477
|
touchEventTypeToCallbackType(event.eventType),
|
|
424
478
|
gesture,
|
|
@@ -459,15 +513,19 @@ function useAnimatedGesture(
|
|
|
459
513
|
|
|
460
514
|
interface GestureDetectorProps {
|
|
461
515
|
gesture?: ComposedGesture | GestureType;
|
|
516
|
+
children?: React.ReactNode;
|
|
462
517
|
}
|
|
463
|
-
export const GestureDetector:
|
|
464
|
-
props
|
|
465
|
-
) => {
|
|
518
|
+
export const GestureDetector = (props: GestureDetectorProps) => {
|
|
466
519
|
const gestureConfig = props.gesture;
|
|
467
520
|
const gesture = gestureConfig?.toGestureArray?.() ?? [];
|
|
468
521
|
const useReanimatedHook = gesture.some((g) => g.shouldUseReanimated);
|
|
469
522
|
const viewRef = useRef(null);
|
|
470
523
|
const firstRenderRef = useRef(true);
|
|
524
|
+
const webEventHandlersRef = useRef<WebEventHandler>({
|
|
525
|
+
onGestureHandlerEvent: (e: HandlerStateChangeEvent<unknown>) => {
|
|
526
|
+
onGestureHandlerEvent(e.nativeEvent);
|
|
527
|
+
},
|
|
528
|
+
});
|
|
471
529
|
|
|
472
530
|
const preparedGesture = React.useRef<GestureConfigReference>({
|
|
473
531
|
config: gesture,
|
|
@@ -508,6 +566,7 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
|
508
566
|
gestureConfig,
|
|
509
567
|
gesture,
|
|
510
568
|
viewTag,
|
|
569
|
+
webEventHandlersRef,
|
|
511
570
|
});
|
|
512
571
|
|
|
513
572
|
return () => {
|
|
@@ -526,6 +585,7 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
|
526
585
|
gestureConfig,
|
|
527
586
|
gesture,
|
|
528
587
|
viewTag,
|
|
588
|
+
webEventHandlersRef,
|
|
529
589
|
});
|
|
530
590
|
} else {
|
|
531
591
|
updateHandlers(preparedGesture, gestureConfig, gesture);
|
|
@@ -543,17 +603,12 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
|
543
603
|
if (isFabric()) {
|
|
544
604
|
const node = getShadowNodeFromRef(ref);
|
|
545
605
|
if (global.isFormsStackingContext(node) === false) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
'GestureDetector has received a child that may get view-flattened. ' +
|
|
553
|
-
'\nTo prevent it from misbehaving you need to wrap the child with a `<View collapsable={false}>`.'
|
|
554
|
-
)
|
|
555
|
-
);
|
|
556
|
-
});
|
|
606
|
+
console.error(
|
|
607
|
+
tagMessage(
|
|
608
|
+
'GestureDetector has received a child that may get view-flattened. ' +
|
|
609
|
+
'\nTo prevent it from misbehaving you need to wrap the child with a `<View collapsable={false}>`.'
|
|
610
|
+
)
|
|
611
|
+
);
|
|
557
612
|
}
|
|
558
613
|
}
|
|
559
614
|
}
|
|
@@ -572,7 +627,11 @@ export const GestureDetector: React.FunctionComponent<GestureDetectorProps> = (
|
|
|
572
627
|
}
|
|
573
628
|
};
|
|
574
629
|
|
|
575
|
-
class Wrap extends React.Component<{
|
|
630
|
+
class Wrap extends React.Component<{
|
|
631
|
+
onGestureHandlerEvent?: unknown;
|
|
632
|
+
// implicit `children` prop has been removed in @types/react^18.0.0
|
|
633
|
+
children?: React.ReactNode;
|
|
634
|
+
}> {
|
|
576
635
|
render() {
|
|
577
636
|
// I don't think that fighting with types over such a simple function is worth it
|
|
578
637
|
// The only thing it does is add 'collapsable: false' to the child component
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DeviceEventEmitter, EmitterSubscription } from 'react-native';
|
|
2
2
|
import { State } from '../../State';
|
|
3
|
-
import {
|
|
3
|
+
import { TouchEventType } from '../../TouchEventType';
|
|
4
4
|
import {
|
|
5
5
|
GestureTouchEvent,
|
|
6
6
|
GestureUpdateEvent,
|
|
@@ -48,7 +48,7 @@ function isTouchEvent(
|
|
|
48
48
|
return event.eventType != null;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function onGestureHandlerEvent(
|
|
51
|
+
export function onGestureHandlerEvent(
|
|
52
52
|
event: GestureUpdateEvent | GestureStateChangeEvent | GestureTouchEvent
|
|
53
53
|
) {
|
|
54
54
|
const handler = findHandler(event.handlerTag) as BaseGesture<
|
|
@@ -87,16 +87,16 @@ function onGestureHandlerEvent(
|
|
|
87
87
|
}
|
|
88
88
|
} else if (isTouchEvent(event)) {
|
|
89
89
|
switch (event.eventType) {
|
|
90
|
-
case
|
|
90
|
+
case TouchEventType.TOUCHES_DOWN:
|
|
91
91
|
handler.handlers?.onTouchesDown?.(event, dummyStateManager);
|
|
92
92
|
break;
|
|
93
|
-
case
|
|
93
|
+
case TouchEventType.TOUCHES_MOVE:
|
|
94
94
|
handler.handlers?.onTouchesMove?.(event, dummyStateManager);
|
|
95
95
|
break;
|
|
96
|
-
case
|
|
96
|
+
case TouchEventType.TOUCHES_UP:
|
|
97
97
|
handler.handlers?.onTouchesUp?.(event, dummyStateManager);
|
|
98
98
|
break;
|
|
99
|
-
case
|
|
99
|
+
case TouchEventType.TOUCHES_CANCELLED:
|
|
100
100
|
handler.handlers?.onTouchesCancelled?.(event, dummyStateManager);
|
|
101
101
|
break;
|
|
102
102
|
}
|
|
@@ -15,6 +15,7 @@ import { PinchGestureHandlerEventPayload } from '../PinchGestureHandler';
|
|
|
15
15
|
import { RotationGestureHandlerEventPayload } from '../RotationGestureHandler';
|
|
16
16
|
import { TapGestureHandlerEventPayload } from '../TapGestureHandler';
|
|
17
17
|
import { NativeViewGestureHandlerPayload } from '../NativeViewGestureHandler';
|
|
18
|
+
import { isRemoteDebuggingEnabled } from '../../utils';
|
|
18
19
|
|
|
19
20
|
export type GestureType =
|
|
20
21
|
| BaseGesture<Record<string, unknown>>
|
|
@@ -43,6 +44,7 @@ export interface BaseGestureConfig
|
|
|
43
44
|
manualActivation?: boolean;
|
|
44
45
|
runOnJS?: boolean;
|
|
45
46
|
testId?: string;
|
|
47
|
+
cancelsTouchesInView?: boolean;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
type TouchEventHandlerType = (
|
|
@@ -51,6 +53,7 @@ type TouchEventHandlerType = (
|
|
|
51
53
|
) => void;
|
|
52
54
|
|
|
53
55
|
export type HandlerCallbacks<EventPayloadT extends Record<string, unknown>> = {
|
|
56
|
+
gestureId: number;
|
|
54
57
|
handlerTag: number;
|
|
55
58
|
onBegin?: (event: GestureStateChangeEvent<EventPayloadT>) => void;
|
|
56
59
|
onStart?: (event: GestureStateChangeEvent<EventPayloadT>) => void;
|
|
@@ -113,17 +116,32 @@ export abstract class Gesture {
|
|
|
113
116
|
abstract prepare(): void;
|
|
114
117
|
}
|
|
115
118
|
|
|
119
|
+
let nextGestureId = 0;
|
|
116
120
|
export abstract class BaseGesture<
|
|
117
121
|
EventPayloadT extends Record<string, unknown>
|
|
118
122
|
> extends Gesture {
|
|
123
|
+
private gestureId = -1;
|
|
119
124
|
public handlerTag = -1;
|
|
120
125
|
public handlerName = '';
|
|
121
126
|
public config: BaseGestureConfig = {};
|
|
122
127
|
public handlers: HandlerCallbacks<EventPayloadT> = {
|
|
128
|
+
gestureId: -1,
|
|
123
129
|
handlerTag: -1,
|
|
124
130
|
isWorklet: [],
|
|
125
131
|
};
|
|
126
132
|
|
|
133
|
+
constructor() {
|
|
134
|
+
super();
|
|
135
|
+
|
|
136
|
+
// Used to check whether the gesture config has been updated when wrapping it
|
|
137
|
+
// with `useMemo`. Since every config will have a unique id, when the dependencies
|
|
138
|
+
// don't change, the config won't be recreated and the id will stay the same.
|
|
139
|
+
// If the id is different, it means that the config has changed and the gesture
|
|
140
|
+
// needs to be updated.
|
|
141
|
+
this.gestureId = nextGestureId++;
|
|
142
|
+
this.handlers.gestureId = this.gestureId;
|
|
143
|
+
}
|
|
144
|
+
|
|
127
145
|
private addDependency(
|
|
128
146
|
key: 'simultaneousWith' | 'requireToFail',
|
|
129
147
|
gesture: Exclude<GestureRef, number>
|
|
@@ -260,6 +278,11 @@ export abstract class BaseGesture<
|
|
|
260
278
|
return this;
|
|
261
279
|
}
|
|
262
280
|
|
|
281
|
+
cancelsTouchesInView(value: boolean) {
|
|
282
|
+
this.config.cancelsTouchesInView = value;
|
|
283
|
+
return this;
|
|
284
|
+
}
|
|
285
|
+
|
|
263
286
|
initialize() {
|
|
264
287
|
this.handlerTag = getNextHandlerTag();
|
|
265
288
|
|
|
@@ -278,9 +301,13 @@ export abstract class BaseGesture<
|
|
|
278
301
|
prepare() {}
|
|
279
302
|
|
|
280
303
|
get shouldUseReanimated(): boolean {
|
|
281
|
-
// use Reanimated when runOnJS isn't set explicitly
|
|
304
|
+
// use Reanimated when runOnJS isn't set explicitly,
|
|
305
|
+
// and all defined callbacks are worklets,
|
|
306
|
+
// and remote debugging is disabled
|
|
282
307
|
return (
|
|
283
|
-
this.config.runOnJS !== true &&
|
|
308
|
+
this.config.runOnJS !== true &&
|
|
309
|
+
!this.handlers.isWorklet.includes(false) &&
|
|
310
|
+
!isRemoteDebuggingEnabled()
|
|
284
311
|
);
|
|
285
312
|
}
|
|
286
313
|
}
|
package/src/init.ts
CHANGED
|
@@ -2,10 +2,17 @@ import { startListening } from './handlers/gestures/eventReceiver';
|
|
|
2
2
|
import RNGestureHandlerModule from './RNGestureHandlerModule';
|
|
3
3
|
import { isFabric } from './utils';
|
|
4
4
|
|
|
5
|
+
let fabricInitialized = false;
|
|
6
|
+
|
|
5
7
|
export function initialize() {
|
|
6
8
|
startListening();
|
|
9
|
+
}
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
// since isFabric() may give wrong results before the first render, we call this
|
|
12
|
+
// method during render of GestureHandlerRootView
|
|
13
|
+
export function maybeInitializeFabric() {
|
|
14
|
+
if (isFabric() && !fabricInitialized) {
|
|
9
15
|
RNGestureHandlerModule.install();
|
|
16
|
+
fabricInitialized = true;
|
|
10
17
|
}
|
|
11
18
|
}
|
package/src/mocks.ts
CHANGED
|
@@ -21,6 +21,7 @@ const attachGestureHandler = NOOP;
|
|
|
21
21
|
const createGestureHandler = NOOP;
|
|
22
22
|
const dropGestureHandler = NOOP;
|
|
23
23
|
const updateGestureHandler = NOOP;
|
|
24
|
+
const flushOperations = NOOP;
|
|
24
25
|
const NativeViewGestureHandler = View;
|
|
25
26
|
const TapGestureHandler = View;
|
|
26
27
|
const ForceTouchGestureHandler = View;
|
|
@@ -59,6 +60,7 @@ export default {
|
|
|
59
60
|
createGestureHandler,
|
|
60
61
|
dropGestureHandler,
|
|
61
62
|
updateGestureHandler,
|
|
63
|
+
flushOperations,
|
|
62
64
|
// probably can be removed
|
|
63
65
|
Directions,
|
|
64
66
|
State,
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { version as rnVersion } from 'react-native/package.json';
|
|
2
|
+
|
|
1
3
|
export function toArray<T>(object: T | T[]): T[] {
|
|
2
4
|
if (!Array.isArray(object)) {
|
|
3
5
|
return [object];
|
|
@@ -32,6 +34,7 @@ export function hasProperty(object: object, key: string) {
|
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export function isJestEnv(): boolean {
|
|
37
|
+
// @ts-ignore Do not use `@types/node` because it will prioritise Node types over RN types which breaks the types (ex. setTimeout) in React Native projects.
|
|
35
38
|
return hasProperty(global, 'process') && !!process.env.JEST_WORKER_ID;
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -39,7 +42,24 @@ export function tagMessage(msg: string) {
|
|
|
39
42
|
return `[react-native-gesture-handler] ${msg}`;
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
// helper method to check whether Fabric is enabled, however global.nativeFabricUIManager
|
|
46
|
+
// may not be initialized before the first render
|
|
42
47
|
export function isFabric(): boolean {
|
|
43
48
|
// @ts-expect-error nativeFabricUIManager is not yet included in the RN types
|
|
44
49
|
return !!global?.nativeFabricUIManager;
|
|
45
50
|
}
|
|
51
|
+
|
|
52
|
+
export function shouldUseCodegenNativeComponent(): boolean {
|
|
53
|
+
const [majorStr, minorStr] = rnVersion.split('.');
|
|
54
|
+
const major = Number.parseInt(majorStr);
|
|
55
|
+
const minor = Number.parseInt(minorStr);
|
|
56
|
+
|
|
57
|
+
// use codegenNativeComponent starting with RN 0.68
|
|
58
|
+
return minor >= 68 || major > 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function isRemoteDebuggingEnabled(): boolean {
|
|
62
|
+
// react-native-reanimated checks if in remote debugging in the same way
|
|
63
|
+
// @ts-ignore global is available but node types are not included
|
|
64
|
+
return !(global as any).nativeCallSyncHook || (global as any).__REMOTEDEV__;
|
|
65
|
+
}
|
|
@@ -182,7 +182,13 @@ abstract class GestureHandler {
|
|
|
182
182
|
// onHandlerStateChange only
|
|
183
183
|
handlerTag: this.handlerTag,
|
|
184
184
|
target: this.ref,
|
|
185
|
-
oldState
|
|
185
|
+
// send oldState only when the state was changed, or is different than ACTIVE
|
|
186
|
+
// GestureDetector relies on the presence of `oldState` to differentiate between
|
|
187
|
+
// update events and state change events
|
|
188
|
+
oldState:
|
|
189
|
+
state !== this.previousState || state != 4
|
|
190
|
+
? this.oldState
|
|
191
|
+
: undefined,
|
|
186
192
|
},
|
|
187
193
|
timeStamp: Date.now(),
|
|
188
194
|
};
|