@react-native-oh-tpl/react-native-gesture-handler 2.14.8-rc.1 → 2.14.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/DrawerLayout/index.ts +2 -2
  2. package/Swipeable/index.ts +2 -2
  3. package/harmony/gesture_handler/BuildProfile.ets +17 -0
  4. package/harmony/gesture_handler/build-profile.json5 +19 -0
  5. package/harmony/gesture_handler/hvigorfile.ts +2 -0
  6. package/harmony/gesture_handler/index.ets +3 -0
  7. package/harmony/gesture_handler/oh-package-lock.json5 +18 -0
  8. package/harmony/gesture_handler/oh-package.json5 +12 -0
  9. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -0
  10. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +149 -0
  11. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +21 -0
  12. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +36 -0
  13. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonJSIBinder.h +32 -0
  14. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +22 -0
  15. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +15 -0
  16. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +36 -0
  17. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewJSIBinder.h +25 -0
  18. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +27 -0
  19. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +242 -0
  20. package/harmony/gesture_handler/src/main/ets/core/CircularBuffer.ts +42 -0
  21. package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +690 -0
  22. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +335 -0
  23. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
  24. package/harmony/gesture_handler/src/main/ets/core/IncomingEvent.ts +78 -0
  25. package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
  26. package/harmony/gesture_handler/src/main/ets/core/LeastSquareSolver.ts +182 -0
  27. package/harmony/gesture_handler/src/main/ets/core/OutgoingEvent.ts +34 -0
  28. package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
  29. package/harmony/gesture_handler/src/main/ets/core/PointerTracker.ts +239 -0
  30. package/harmony/gesture_handler/src/main/ets/core/RNGHError.ts +5 -0
  31. package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +12 -0
  32. package/harmony/gesture_handler/src/main/ets/core/State.ts +47 -0
  33. package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
  34. package/harmony/gesture_handler/src/main/ets/core/VelocityTracker.ts +106 -0
  35. package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
  36. package/harmony/gesture_handler/src/main/ets/core/ViewFinder.ts +11 -0
  37. package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +8 -0
  38. package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
  39. package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
  40. package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +211 -0
  41. package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +64 -0
  42. package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +127 -0
  43. package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +42 -0
  44. package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +115 -0
  45. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +342 -0
  46. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +159 -0
  47. package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +164 -0
  48. package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +206 -0
  49. package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
  50. package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
  51. package/harmony/gesture_handler/src/main/ets/namespace/RNGestureHandlerModule.ts +24 -0
  52. package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerButton.ts +139 -0
  53. package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerRootView.ts +101 -0
  54. package/harmony/gesture_handler/src/main/ets/namespace/components/ts.ts +2 -0
  55. package/harmony/gesture_handler/src/main/ets/namespace/ts.ts +2 -0
  56. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerArkUIAdapter.ts +240 -0
  57. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +22 -0
  58. package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +49 -0
  59. package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +71 -0
  60. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +98 -0
  61. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +110 -0
  62. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerButton.ets +38 -0
  63. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +233 -0
  64. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerRootView.ets +53 -0
  65. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +24 -0
  66. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +32 -0
  67. package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +134 -0
  68. package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +97 -0
  69. package/harmony/gesture_handler/src/main/ets/rnoh/types.ts +25 -0
  70. package/harmony/gesture_handler/src/main/module.json5 +9 -0
  71. package/harmony/gesture_handler/src/main/resources/base/element/color.json +8 -0
  72. package/harmony/gesture_handler/src/main/resources/base/element/string.json +16 -0
  73. package/harmony/gesture_handler/src/main/resources/base/media/icon.png +0 -0
  74. package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -0
  75. package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +16 -0
  76. package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +16 -0
  77. package/harmony/gesture_handler/ts.ts +2 -0
  78. package/harmony/gesture_handler.har +0 -0
  79. package/lib/commonjs/RNGestureHandlerModule.js +3 -2
  80. package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
  81. package/lib/commonjs/components/GestureHandlerRootView.js +3 -3
  82. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  83. package/lib/commonjs/handlers/createHandler.js +18 -15
  84. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  85. package/lib/commonjs/index.js +36 -8
  86. package/lib/commonjs/index.js.map +1 -1
  87. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js +2 -1
  88. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  89. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js +3 -2
  90. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  91. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js +3 -2
  92. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  93. package/lib/module/RNGestureHandlerModule.js.map +1 -1
  94. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  95. package/lib/module/handlers/createHandler.js +15 -12
  96. package/lib/module/handlers/createHandler.js.map +1 -1
  97. package/lib/module/index.js +5 -7
  98. package/lib/module/index.js.map +1 -1
  99. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  100. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  101. package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  102. package/lib/typescript/RNGestureHandlerModule.d.ts +2 -2
  103. package/lib/typescript/components/GestureHandlerRootView.d.ts +6 -6
  104. package/lib/typescript/handlers/createHandler.d.ts +11 -11
  105. package/lib/typescript/index.d.ts +47 -42
  106. package/lib/typescript/index.d.ts.map +1 -1
  107. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +14 -14
  108. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +14 -14
  109. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +6 -6
  110. package/package.json +73 -69
  111. package/src/RNGestureHandlerModule.ts +4 -4
  112. package/src/components/GestureHandlerRootView.tsx +23 -23
  113. package/src/handlers/createHandler.tsx +534 -534
  114. package/src/index.ts +172 -172
  115. package/src/specs/NativeRNGestureHandlerModule.ts +26 -26
  116. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +18 -18
  117. package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +6 -6
@@ -1,534 +1,534 @@
1
- // RNGH: patching the import to RNGestureHandlerModule
2
-
3
- import * as React from 'react';
4
- import {
5
- Platform,
6
- UIManager,
7
- DeviceEventEmitter,
8
- EmitterSubscription,
9
- } from 'react-native';
10
- // @ts-ignore - it isn't typed by TS & don't have definitelyTyped types
11
- import deepEqual from 'lodash/isEqual';
12
- import RNGestureHandlerModule from '../RNGestureHandlerModule'; // RNGH: patch
13
- import type RNGestureHandlerModuleWeb from 'react-native-gesture-handler/src/RNGestureHandlerModule.web';
14
- import { State } from 'react-native-gesture-handler/src/State';
15
- import {
16
- handlerIDToTag,
17
- getNextHandlerTag,
18
- registerOldGestureHandler,
19
- } from 'react-native-gesture-handler/src/handlers/handlersRegistry';
20
-
21
- import {
22
- BaseGestureHandlerProps,
23
- filterConfig,
24
- GestureEvent,
25
- HandlerStateChangeEvent,
26
- findNodeHandle,
27
- scheduleFlushOperations,
28
- } from "react-native-gesture-handler/src/handlers/gestureHandlerCommon";
29
- import { ValueOf } from 'react-native-gesture-handler/src/typeUtils';
30
- import { isFabric, isJestEnv, tagMessage } from 'react-native-gesture-handler/src/utils';
31
- import { ActionType } from 'react-native-gesture-handler/src/ActionType';
32
- import { PressabilityDebugView } from 'react-native-gesture-handler/src/handlers/PressabilityDebugView';
33
- import GestureHandlerRootViewContext from 'react-native-gesture-handler/src/GestureHandlerRootViewContext';
34
-
35
- const UIManagerAny = UIManager as any;
36
-
37
- const customGHEventsConfigFabricAndroid = {
38
- topOnGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' },
39
- topOnGestureHandlerStateChange: {
40
- registrationName: 'onGestureHandlerStateChange',
41
- },
42
- };
43
-
44
- const customGHEventsConfig = {
45
- onGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' },
46
- onGestureHandlerStateChange: {
47
- registrationName: 'onGestureHandlerStateChange',
48
- },
49
-
50
- // When using React Native Gesture Handler for Animated.event with useNativeDriver: true
51
- // on Android with Fabric enabled, the native part still sends the native events to JS
52
- // but prefixed with "top". We cannot simply rename the events above so they are prefixed
53
- // with "top" instead of "on" because in such case Animated.events would not be registered.
54
- // That's why we need to register another pair of event names.
55
- // The incoming events will be queued but never handled.
56
- // Without this piece of code below, you'll get the following JS error:
57
- // Unsupported top level event type "topOnGestureHandlerEvent" dispatched
58
- ...(isFabric() &&
59
- Platform.OS as string === 'harmony' && // RNGH: patch
60
- customGHEventsConfigFabricAndroid),
61
- };
62
-
63
- // Add gesture specific events to genericDirectEventTypes object exported from UIManager
64
- // native module.
65
- // Once new event types are registered with react it is possible to dispatch these
66
- // events to all kind of native views.
67
- UIManagerAny.genericDirectEventTypes = {
68
- ...UIManagerAny.genericDirectEventTypes,
69
- ...customGHEventsConfig,
70
- };
71
- // In newer versions of RN the `genericDirectEventTypes` is located in the object
72
- // returned by UIManager.getViewManagerConfig('getConstants') or in older RN UIManager.getConstants(), we need to add it there as well to make
73
- // it compatible with RN 61+
74
- const UIManagerConstants =
75
- UIManagerAny.getViewManagerConfig?.('getConstants') ??
76
- UIManagerAny.getConstants?.();
77
-
78
- if (UIManagerConstants) {
79
- UIManagerConstants.genericDirectEventTypes = {
80
- ...UIManagerConstants.genericDirectEventTypes,
81
- ...customGHEventsConfig,
82
- };
83
- }
84
-
85
- // Wrap JS responder calls and notify gesture handler manager
86
- const {
87
- setJSResponder: oldSetJSResponder = () => {
88
- //no operation
89
- },
90
- clearJSResponder: oldClearJSResponder = () => {
91
- //no operation
92
- },
93
- } = UIManagerAny;
94
- UIManagerAny.setJSResponder = (tag: number, blockNativeResponder: boolean) => {
95
- RNGestureHandlerModule.handleSetJSResponder(tag, blockNativeResponder);
96
- oldSetJSResponder(tag, blockNativeResponder);
97
- };
98
- UIManagerAny.clearJSResponder = () => {
99
- RNGestureHandlerModule.handleClearJSResponder();
100
- oldClearJSResponder();
101
- };
102
-
103
- let allowTouches = true;
104
- const DEV_ON_ANDROID = __DEV__ && Platform.OS === 'android';
105
- // Toggled inspector blocks touch events in order to allow inspecting on Android
106
- // This needs to be a global variable in order to set initial state for `allowTouches` property in Handler component
107
- if (DEV_ON_ANDROID) {
108
- DeviceEventEmitter.addListener('toggleElementInspector', () => {
109
- allowTouches = !allowTouches;
110
- });
111
- }
112
-
113
- type HandlerProps<T extends Record<string, unknown>> = Readonly<
114
- React.PropsWithChildren<BaseGestureHandlerProps<T>>
115
- >;
116
- function hasUnresolvedRefs<T extends Record<string, unknown>>(
117
- props: HandlerProps<T>
118
- ) {
119
- // TODO(TS) - add type for extract arg
120
- const extract = (refs: any | any[]) => {
121
- if (!Array.isArray(refs)) {
122
- return refs && refs.current === null;
123
- }
124
- return refs.some((r) => r && r.current === null);
125
- };
126
- return extract(props['simultaneousHandlers']) || extract(props['waitFor']);
127
- }
128
-
129
- const stateToPropMappings = {
130
- [State.UNDETERMINED]: undefined,
131
- [State.BEGAN]: 'onBegan',
132
- [State.FAILED]: 'onFailed',
133
- [State.CANCELLED]: 'onCancelled',
134
- [State.ACTIVE]: 'onActivated',
135
- [State.END]: 'onEnded',
136
- } as const;
137
-
138
- type CreateHandlerArgs<HandlerPropsT extends Record<string, unknown>> =
139
- Readonly<{
140
- name: string;
141
- allowedProps: Readonly<Extract<keyof HandlerPropsT, string>[]>;
142
- config: Readonly<Record<string, unknown>>;
143
- transformProps?: (props: HandlerPropsT) => HandlerPropsT;
144
- customNativeProps?: Readonly<string[]>;
145
- }>;
146
-
147
- // TODO(TS) fix event types
148
- type InternalEventHandlers = {
149
- onGestureHandlerEvent?: (event: any) => void;
150
- onGestureHandlerStateChange?: (event: any) => void;
151
- };
152
-
153
- const UNRESOLVED_REFS_RETRY_LIMIT = 1;
154
-
155
- // TODO(TS) - make sure that BaseGestureHandlerProps doesn't need other generic parameter to work with custom properties.
156
- export default function createHandler<
157
- T extends BaseGestureHandlerProps<U>,
158
- U extends Record<string, unknown>
159
- >({
160
- name,
161
- allowedProps = [],
162
- config = {},
163
- transformProps,
164
- customNativeProps = [],
165
- }: CreateHandlerArgs<T>): React.ComponentType<T & React.RefAttributes<any>> {
166
- interface HandlerState {
167
- allowTouches: boolean;
168
- }
169
- class Handler extends React.Component<
170
- T & InternalEventHandlers,
171
- HandlerState
172
- > {
173
- static displayName = name;
174
- static contextType = GestureHandlerRootViewContext;
175
-
176
- private handlerTag: number;
177
- private config: Record<string, unknown>;
178
- private propsRef: React.MutableRefObject<unknown>;
179
- private isMountedRef: React.MutableRefObject<boolean | null>;
180
- private viewNode: any;
181
- private viewTag?: number;
182
- private inspectorToggleListener?: EmitterSubscription;
183
-
184
- constructor(props: T & InternalEventHandlers) {
185
- super(props);
186
- this.handlerTag = getNextHandlerTag();
187
- this.config = {};
188
- this.propsRef = React.createRef();
189
- this.isMountedRef = React.createRef();
190
- this.state = { allowTouches };
191
- if (props.id) {
192
- if (handlerIDToTag[props.id] !== undefined) {
193
- throw new Error(`Handler with ID "${props.id}" already registered`);
194
- }
195
- handlerIDToTag[props.id] = this.handlerTag;
196
- }
197
- }
198
-
199
- componentDidMount() {
200
- const props: HandlerProps<U> = this.props;
201
- this.isMountedRef.current = true;
202
-
203
- if (DEV_ON_ANDROID) {
204
- this.inspectorToggleListener = DeviceEventEmitter.addListener(
205
- 'toggleElementInspector',
206
- () => {
207
- this.setState((_) => ({ allowTouches }));
208
- this.update(UNRESOLVED_REFS_RETRY_LIMIT);
209
- }
210
- );
211
- }
212
- if (hasUnresolvedRefs(props)) {
213
- // If there are unresolved refs (e.g. ".current" has not yet been set)
214
- // passed as `simultaneousHandlers` or `waitFor`, we enqueue a call to
215
- // _update method that will try to update native handler props using
216
- // queueMicrotask. This makes it so update() function gets called after all
217
- // react components are mounted and we expect the missing ref object to
218
- // be resolved by then.
219
- queueMicrotask(() => {
220
- this.update(UNRESOLVED_REFS_RETRY_LIMIT);
221
- });
222
- }
223
-
224
- this.createGestureHandler(
225
- filterConfig(
226
- transformProps ? transformProps(this.props) : this.props,
227
- [...allowedProps, ...customNativeProps],
228
- config
229
- )
230
- );
231
-
232
- this.attachGestureHandler(findNodeHandle(this.viewNode) as number); // TODO(TS) - check if this can be null
233
- }
234
-
235
- componentDidUpdate() {
236
- const viewTag = findNodeHandle(this.viewNode);
237
- if (this.viewTag !== viewTag) {
238
- this.attachGestureHandler(viewTag as number); // TODO(TS) - check interaction between _viewTag & findNodeHandle
239
- }
240
- this.update(UNRESOLVED_REFS_RETRY_LIMIT);
241
- }
242
-
243
- componentWillUnmount() {
244
- this.inspectorToggleListener?.remove();
245
- this.isMountedRef.current = false;
246
- RNGestureHandlerModule.dropGestureHandler(this.handlerTag);
247
- scheduleFlushOperations();
248
- // We can't use this.props.id directly due to TS generic type narrowing bug, see https://github.com/microsoft/TypeScript/issues/13995 for more context
249
- const handlerID: string | undefined = this.props.id;
250
- if (handlerID) {
251
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
252
- delete handlerIDToTag[handlerID];
253
- }
254
- }
255
-
256
- private onGestureHandlerEvent = (event: GestureEvent<U>) => {
257
- if (event.nativeEvent.handlerTag === this.handlerTag) {
258
- if (typeof this.props.onGestureEvent === 'function') {
259
- this.props.onGestureEvent?.(event);
260
- }
261
- } else {
262
- this.props.onGestureHandlerEvent?.(event);
263
- }
264
- };
265
-
266
- // TODO(TS) - make sure this is right type for event
267
- private onGestureHandlerStateChange = (
268
- event: HandlerStateChangeEvent<U>
269
- ) => {
270
- if (event.nativeEvent.handlerTag === this.handlerTag) {
271
- if (typeof this.props.onHandlerStateChange === 'function') {
272
- this.props.onHandlerStateChange?.(event);
273
- }
274
-
275
- const state: ValueOf<typeof State> = event.nativeEvent.state;
276
- const stateEventName = stateToPropMappings[state];
277
- const eventHandler = stateEventName && this.props[stateEventName];
278
- if (eventHandler && typeof eventHandler === 'function') {
279
- eventHandler(event);
280
- }
281
- } else {
282
- this.props.onGestureHandlerStateChange?.(event);
283
- }
284
- };
285
-
286
- private refHandler = (node: any) => {
287
- this.viewNode = node;
288
-
289
- const child = React.Children.only(this.props.children);
290
- // TODO(TS) fix ref type
291
- const { ref }: any = child;
292
- if (ref !== null) {
293
- if (typeof ref === 'function') {
294
- ref(node);
295
- } else {
296
- ref.current = node;
297
- }
298
- }
299
- };
300
-
301
- private createGestureHandler = (
302
- newConfig: Readonly<Record<string, unknown>>
303
- ) => {
304
- this.config = newConfig;
305
-
306
- RNGestureHandlerModule.createGestureHandler(
307
- name,
308
- this.handlerTag,
309
- newConfig
310
- );
311
- };
312
-
313
- private attachGestureHandler = (newViewTag: number) => {
314
- this.viewTag = newViewTag;
315
-
316
- if (Platform.OS === 'web') {
317
- // typecast due to dynamic resolution, attachGestureHandler should have web version signature in this branch
318
- (
319
- RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler
320
- )(
321
- this.handlerTag,
322
- newViewTag,
323
- ActionType.JS_FUNCTION_OLD_API, // ignored on web
324
- this.propsRef
325
- );
326
- } else {
327
- registerOldGestureHandler(this.handlerTag, {
328
- onGestureEvent: this.onGestureHandlerEvent,
329
- onGestureStateChange: this.onGestureHandlerStateChange,
330
- });
331
-
332
- const actionType = (() => {
333
- if (
334
- (this.props?.onGestureEvent &&
335
- 'current' in this.props.onGestureEvent) ||
336
- (this.props?.onHandlerStateChange &&
337
- 'current' in this.props.onHandlerStateChange)
338
- ) {
339
- // Reanimated worklet
340
- return ActionType.REANIMATED_WORKLET;
341
- } else if (
342
- this.props?.onGestureEvent &&
343
- '__isNative' in this.props.onGestureEvent
344
- ) {
345
- // Animated.event with useNativeDriver: true
346
- return ActionType.NATIVE_ANIMATED_EVENT;
347
- } else {
348
- // JS callback or Animated.event with useNativeDriver: false
349
- return ActionType.JS_FUNCTION_OLD_API;
350
- }
351
- })();
352
-
353
- RNGestureHandlerModule.attachGestureHandler(
354
- this.handlerTag,
355
- newViewTag,
356
- actionType
357
- );
358
- }
359
-
360
- scheduleFlushOperations();
361
- };
362
-
363
- private updateGestureHandler = (
364
- newConfig: Readonly<Record<string, unknown>>
365
- ) => {
366
- this.config = newConfig;
367
-
368
- RNGestureHandlerModule.updateGestureHandler(this.handlerTag, newConfig);
369
- scheduleFlushOperations();
370
- };
371
-
372
- private update(remainingTries: number) {
373
- if (!this.isMountedRef.current) {
374
- return;
375
- }
376
-
377
- const props: HandlerProps<U> = this.props;
378
-
379
- // When ref is set via a function i.e. `ref={(r) => refObject.current = r}` instead of
380
- // `ref={refObject}` it's possible that it won't be resolved in time. Seems like trying
381
- // again is easy enough fix.
382
- if (hasUnresolvedRefs(props) && remainingTries > 0) {
383
- queueMicrotask(() => {
384
- this.update(remainingTries - 1);
385
- });
386
- } else {
387
- const newConfig = filterConfig(
388
- transformProps ? transformProps(this.props) : this.props,
389
- [...allowedProps, ...customNativeProps],
390
- config
391
- );
392
- if (!deepEqual(this.config, newConfig)) {
393
- this.updateGestureHandler(newConfig);
394
- }
395
- }
396
- }
397
-
398
- setNativeProps(updates: any) {
399
- const mergedProps = { ...this.props, ...updates };
400
- const newConfig = filterConfig(
401
- transformProps ? transformProps(mergedProps) : mergedProps,
402
- [...allowedProps, ...customNativeProps],
403
- config
404
- );
405
- this.updateGestureHandler(newConfig);
406
- }
407
-
408
- render() {
409
- if (__DEV__ && !this.context && !isJestEnv() && Platform.OS !== 'web' && (Platform.OS as any) !== "harmony") { // RNOH: patch
410
- throw new Error(
411
- name +
412
- ' must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'
413
- );
414
- }
415
-
416
- let gestureEventHandler = this.onGestureHandlerEvent;
417
- // Another instance of https://github.com/microsoft/TypeScript/issues/13995
418
- type OnGestureEventHandlers = {
419
- onGestureEvent?: BaseGestureHandlerProps<U>['onGestureEvent'];
420
- onGestureHandlerEvent?: InternalEventHandlers['onGestureHandlerEvent'];
421
- };
422
- const { onGestureEvent, onGestureHandlerEvent }: OnGestureEventHandlers =
423
- this.props;
424
- if (onGestureEvent && typeof onGestureEvent !== 'function') {
425
- // If it's not a method it should be an native Animated.event
426
- // object. We set it directly as the handler for the view
427
- // In this case nested handlers are not going to be supported
428
- if (onGestureHandlerEvent) {
429
- throw new Error(
430
- 'Nesting touch handlers with native animated driver is not supported yet'
431
- );
432
- }
433
- gestureEventHandler = onGestureEvent;
434
- } else {
435
- if (
436
- onGestureHandlerEvent &&
437
- typeof onGestureHandlerEvent !== 'function'
438
- ) {
439
- throw new Error(
440
- 'Nesting touch handlers with native animated driver is not supported yet'
441
- );
442
- }
443
- }
444
-
445
- let gestureStateEventHandler = this.onGestureHandlerStateChange;
446
- // Another instance of https://github.com/microsoft/TypeScript/issues/13995
447
- type OnGestureStateChangeHandlers = {
448
- onHandlerStateChange?: BaseGestureHandlerProps<U>['onHandlerStateChange'];
449
- onGestureHandlerStateChange?: InternalEventHandlers['onGestureHandlerStateChange'];
450
- };
451
- const {
452
- onHandlerStateChange,
453
- onGestureHandlerStateChange,
454
- }: OnGestureStateChangeHandlers = this.props;
455
- if (onHandlerStateChange && typeof onHandlerStateChange !== 'function') {
456
- // If it's not a method it should be an native Animated.event
457
- // object. We set it directly as the handler for the view
458
- // In this case nested handlers are not going to be supported
459
- if (onGestureHandlerStateChange) {
460
- throw new Error(
461
- 'Nesting touch handlers with native animated driver is not supported yet'
462
- );
463
- }
464
- gestureStateEventHandler = onHandlerStateChange;
465
- } else {
466
- if (
467
- onGestureHandlerStateChange &&
468
- typeof onGestureHandlerStateChange !== 'function'
469
- ) {
470
- throw new Error(
471
- 'Nesting touch handlers with native animated driver is not supported yet'
472
- );
473
- }
474
- }
475
- const events = {
476
- onGestureHandlerEvent: this.state.allowTouches
477
- ? gestureEventHandler
478
- : undefined,
479
- onGestureHandlerStateChange: this.state.allowTouches
480
- ? gestureStateEventHandler
481
- : undefined,
482
- };
483
-
484
- this.propsRef.current = events;
485
-
486
- let child: any = null;
487
- try {
488
- child = React.Children.only(this.props.children);
489
- } catch (e) {
490
- throw new Error(
491
- tagMessage(
492
- `${name} got more than one view as a child. If you want the gesture to work on multiple views, wrap them with a common parent and attach the gesture to that view.`
493
- )
494
- );
495
- }
496
-
497
- let grandChildren = child.props.children;
498
- if (
499
- __DEV__ &&
500
- child.type &&
501
- (child.type === 'RNGestureHandlerButton' ||
502
- child.type.name === 'View' ||
503
- child.type.displayName === 'View')
504
- ) {
505
- grandChildren = React.Children.toArray(grandChildren);
506
- grandChildren.push(
507
- <PressabilityDebugView
508
- key="pressabilityDebugView"
509
- color="mediumspringgreen"
510
- hitSlop={child.props.hitSlop}
511
- />
512
- );
513
- }
514
-
515
- return React.cloneElement(
516
- child,
517
- {
518
- ref: this.refHandler,
519
- collapsable: false,
520
- ...(isJestEnv()
521
- ? {
522
- handlerType: name,
523
- handlerTag: this.handlerTag,
524
- }
525
- : {}),
526
- testID: this.props.testID ?? child.props.testID,
527
- ...events,
528
- },
529
- grandChildren
530
- );
531
- }
532
- }
533
- return Handler;
534
- }
1
+ // RNGH: patching the import to RNGestureHandlerModule
2
+
3
+ import * as React from 'react';
4
+ import {
5
+ Platform,
6
+ UIManager,
7
+ DeviceEventEmitter,
8
+ EmitterSubscription,
9
+ } from 'react-native';
10
+ // @ts-ignore - it isn't typed by TS & don't have definitelyTyped types
11
+ import deepEqual from 'lodash/isEqual';
12
+ import RNGestureHandlerModule from '../RNGestureHandlerModule'; // RNGH: patch
13
+ import type RNGestureHandlerModuleWeb from 'react-native-gesture-handler/src/RNGestureHandlerModule.web';
14
+ import { State } from 'react-native-gesture-handler/src/State';
15
+ import {
16
+ handlerIDToTag,
17
+ getNextHandlerTag,
18
+ registerOldGestureHandler,
19
+ } from 'react-native-gesture-handler/src/handlers/handlersRegistry';
20
+
21
+ import {
22
+ BaseGestureHandlerProps,
23
+ filterConfig,
24
+ GestureEvent,
25
+ HandlerStateChangeEvent,
26
+ findNodeHandle,
27
+ scheduleFlushOperations,
28
+ } from "react-native-gesture-handler/src/handlers/gestureHandlerCommon";
29
+ import { ValueOf } from 'react-native-gesture-handler/src/typeUtils';
30
+ import { isFabric, isJestEnv, tagMessage } from 'react-native-gesture-handler/src/utils';
31
+ import { ActionType } from 'react-native-gesture-handler/src/ActionType';
32
+ import { PressabilityDebugView } from 'react-native-gesture-handler/src/handlers/PressabilityDebugView';
33
+ import GestureHandlerRootViewContext from 'react-native-gesture-handler/src/GestureHandlerRootViewContext';
34
+
35
+ const UIManagerAny = UIManager as any;
36
+
37
+ const customGHEventsConfigFabricAndroid = {
38
+ topOnGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' },
39
+ topOnGestureHandlerStateChange: {
40
+ registrationName: 'onGestureHandlerStateChange',
41
+ },
42
+ };
43
+
44
+ const customGHEventsConfig = {
45
+ onGestureHandlerEvent: { registrationName: 'onGestureHandlerEvent' },
46
+ onGestureHandlerStateChange: {
47
+ registrationName: 'onGestureHandlerStateChange',
48
+ },
49
+
50
+ // When using React Native Gesture Handler for Animated.event with useNativeDriver: true
51
+ // on Android with Fabric enabled, the native part still sends the native events to JS
52
+ // but prefixed with "top". We cannot simply rename the events above so they are prefixed
53
+ // with "top" instead of "on" because in such case Animated.events would not be registered.
54
+ // That's why we need to register another pair of event names.
55
+ // The incoming events will be queued but never handled.
56
+ // Without this piece of code below, you'll get the following JS error:
57
+ // Unsupported top level event type "topOnGestureHandlerEvent" dispatched
58
+ ...(isFabric() &&
59
+ Platform.OS as string === 'harmony' && // RNGH: patch
60
+ customGHEventsConfigFabricAndroid),
61
+ };
62
+
63
+ // Add gesture specific events to genericDirectEventTypes object exported from UIManager
64
+ // native module.
65
+ // Once new event types are registered with react it is possible to dispatch these
66
+ // events to all kind of native views.
67
+ UIManagerAny.genericDirectEventTypes = {
68
+ ...UIManagerAny.genericDirectEventTypes,
69
+ ...customGHEventsConfig,
70
+ };
71
+ // In newer versions of RN the `genericDirectEventTypes` is located in the object
72
+ // returned by UIManager.getViewManagerConfig('getConstants') or in older RN UIManager.getConstants(), we need to add it there as well to make
73
+ // it compatible with RN 61+
74
+ const UIManagerConstants =
75
+ UIManagerAny.getViewManagerConfig?.('getConstants') ??
76
+ UIManagerAny.getConstants?.();
77
+
78
+ if (UIManagerConstants) {
79
+ UIManagerConstants.genericDirectEventTypes = {
80
+ ...UIManagerConstants.genericDirectEventTypes,
81
+ ...customGHEventsConfig,
82
+ };
83
+ }
84
+
85
+ // Wrap JS responder calls and notify gesture handler manager
86
+ const {
87
+ setJSResponder: oldSetJSResponder = () => {
88
+ //no operation
89
+ },
90
+ clearJSResponder: oldClearJSResponder = () => {
91
+ //no operation
92
+ },
93
+ } = UIManagerAny;
94
+ UIManagerAny.setJSResponder = (tag: number, blockNativeResponder: boolean) => {
95
+ RNGestureHandlerModule.handleSetJSResponder(tag, blockNativeResponder);
96
+ oldSetJSResponder(tag, blockNativeResponder);
97
+ };
98
+ UIManagerAny.clearJSResponder = () => {
99
+ RNGestureHandlerModule.handleClearJSResponder();
100
+ oldClearJSResponder();
101
+ };
102
+
103
+ let allowTouches = true;
104
+ const DEV_ON_ANDROID = __DEV__ && Platform.OS === 'android';
105
+ // Toggled inspector blocks touch events in order to allow inspecting on Android
106
+ // This needs to be a global variable in order to set initial state for `allowTouches` property in Handler component
107
+ if (DEV_ON_ANDROID) {
108
+ DeviceEventEmitter.addListener('toggleElementInspector', () => {
109
+ allowTouches = !allowTouches;
110
+ });
111
+ }
112
+
113
+ type HandlerProps<T extends Record<string, unknown>> = Readonly<
114
+ React.PropsWithChildren<BaseGestureHandlerProps<T>>
115
+ >;
116
+ function hasUnresolvedRefs<T extends Record<string, unknown>>(
117
+ props: HandlerProps<T>
118
+ ) {
119
+ // TODO(TS) - add type for extract arg
120
+ const extract = (refs: any | any[]) => {
121
+ if (!Array.isArray(refs)) {
122
+ return refs && refs.current === null;
123
+ }
124
+ return refs.some((r) => r && r.current === null);
125
+ };
126
+ return extract(props['simultaneousHandlers']) || extract(props['waitFor']);
127
+ }
128
+
129
+ const stateToPropMappings = {
130
+ [State.UNDETERMINED]: undefined,
131
+ [State.BEGAN]: 'onBegan',
132
+ [State.FAILED]: 'onFailed',
133
+ [State.CANCELLED]: 'onCancelled',
134
+ [State.ACTIVE]: 'onActivated',
135
+ [State.END]: 'onEnded',
136
+ } as const;
137
+
138
+ type CreateHandlerArgs<HandlerPropsT extends Record<string, unknown>> =
139
+ Readonly<{
140
+ name: string;
141
+ allowedProps: Readonly<Extract<keyof HandlerPropsT, string>[]>;
142
+ config: Readonly<Record<string, unknown>>;
143
+ transformProps?: (props: HandlerPropsT) => HandlerPropsT;
144
+ customNativeProps?: Readonly<string[]>;
145
+ }>;
146
+
147
+ // TODO(TS) fix event types
148
+ type InternalEventHandlers = {
149
+ onGestureHandlerEvent?: (event: any) => void;
150
+ onGestureHandlerStateChange?: (event: any) => void;
151
+ };
152
+
153
+ const UNRESOLVED_REFS_RETRY_LIMIT = 1;
154
+
155
+ // TODO(TS) - make sure that BaseGestureHandlerProps doesn't need other generic parameter to work with custom properties.
156
+ export default function createHandler<
157
+ T extends BaseGestureHandlerProps<U>,
158
+ U extends Record<string, unknown>
159
+ >({
160
+ name,
161
+ allowedProps = [],
162
+ config = {},
163
+ transformProps,
164
+ customNativeProps = [],
165
+ }: CreateHandlerArgs<T>): React.ComponentType<T & React.RefAttributes<any>> {
166
+ interface HandlerState {
167
+ allowTouches: boolean;
168
+ }
169
+ class Handler extends React.Component<
170
+ T & InternalEventHandlers,
171
+ HandlerState
172
+ > {
173
+ static displayName = name;
174
+ static contextType = GestureHandlerRootViewContext;
175
+
176
+ private handlerTag: number;
177
+ private config: Record<string, unknown>;
178
+ private propsRef: React.MutableRefObject<unknown>;
179
+ private isMountedRef: React.MutableRefObject<boolean | null>;
180
+ private viewNode: any;
181
+ private viewTag?: number;
182
+ private inspectorToggleListener?: EmitterSubscription;
183
+
184
+ constructor(props: T & InternalEventHandlers) {
185
+ super(props);
186
+ this.handlerTag = getNextHandlerTag();
187
+ this.config = {};
188
+ this.propsRef = React.createRef();
189
+ this.isMountedRef = React.createRef();
190
+ this.state = { allowTouches };
191
+ if (props.id) {
192
+ if (handlerIDToTag[props.id] !== undefined) {
193
+ throw new Error(`Handler with ID "${props.id}" already registered`);
194
+ }
195
+ handlerIDToTag[props.id] = this.handlerTag;
196
+ }
197
+ }
198
+
199
+ componentDidMount() {
200
+ const props: HandlerProps<U> = this.props;
201
+ this.isMountedRef.current = true;
202
+
203
+ if (DEV_ON_ANDROID) {
204
+ this.inspectorToggleListener = DeviceEventEmitter.addListener(
205
+ 'toggleElementInspector',
206
+ () => {
207
+ this.setState((_) => ({ allowTouches }));
208
+ this.update(UNRESOLVED_REFS_RETRY_LIMIT);
209
+ }
210
+ );
211
+ }
212
+ if (hasUnresolvedRefs(props)) {
213
+ // If there are unresolved refs (e.g. ".current" has not yet been set)
214
+ // passed as `simultaneousHandlers` or `waitFor`, we enqueue a call to
215
+ // _update method that will try to update native handler props using
216
+ // queueMicrotask. This makes it so update() function gets called after all
217
+ // react components are mounted and we expect the missing ref object to
218
+ // be resolved by then.
219
+ queueMicrotask(() => {
220
+ this.update(UNRESOLVED_REFS_RETRY_LIMIT);
221
+ });
222
+ }
223
+
224
+ this.createGestureHandler(
225
+ filterConfig(
226
+ transformProps ? transformProps(this.props) : this.props,
227
+ [...allowedProps, ...customNativeProps],
228
+ config
229
+ )
230
+ );
231
+
232
+ this.attachGestureHandler(findNodeHandle(this.viewNode) as number); // TODO(TS) - check if this can be null
233
+ }
234
+
235
+ componentDidUpdate() {
236
+ const viewTag = findNodeHandle(this.viewNode);
237
+ if (this.viewTag !== viewTag) {
238
+ this.attachGestureHandler(viewTag as number); // TODO(TS) - check interaction between _viewTag & findNodeHandle
239
+ }
240
+ this.update(UNRESOLVED_REFS_RETRY_LIMIT);
241
+ }
242
+
243
+ componentWillUnmount() {
244
+ this.inspectorToggleListener?.remove();
245
+ this.isMountedRef.current = false;
246
+ RNGestureHandlerModule.dropGestureHandler(this.handlerTag);
247
+ scheduleFlushOperations();
248
+ // We can't use this.props.id directly due to TS generic type narrowing bug, see https://github.com/microsoft/TypeScript/issues/13995 for more context
249
+ const handlerID: string | undefined = this.props.id;
250
+ if (handlerID) {
251
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
252
+ delete handlerIDToTag[handlerID];
253
+ }
254
+ }
255
+
256
+ private onGestureHandlerEvent = (event: GestureEvent<U>) => {
257
+ if (event.nativeEvent.handlerTag === this.handlerTag) {
258
+ if (typeof this.props.onGestureEvent === 'function') {
259
+ this.props.onGestureEvent?.(event);
260
+ }
261
+ } else {
262
+ this.props.onGestureHandlerEvent?.(event);
263
+ }
264
+ };
265
+
266
+ // TODO(TS) - make sure this is right type for event
267
+ private onGestureHandlerStateChange = (
268
+ event: HandlerStateChangeEvent<U>
269
+ ) => {
270
+ if (event.nativeEvent.handlerTag === this.handlerTag) {
271
+ if (typeof this.props.onHandlerStateChange === 'function') {
272
+ this.props.onHandlerStateChange?.(event);
273
+ }
274
+
275
+ const state: ValueOf<typeof State> = event.nativeEvent.state;
276
+ const stateEventName = stateToPropMappings[state];
277
+ const eventHandler = stateEventName && this.props[stateEventName];
278
+ if (eventHandler && typeof eventHandler === 'function') {
279
+ eventHandler(event);
280
+ }
281
+ } else {
282
+ this.props.onGestureHandlerStateChange?.(event);
283
+ }
284
+ };
285
+
286
+ private refHandler = (node: any) => {
287
+ this.viewNode = node;
288
+
289
+ const child = React.Children.only(this.props.children);
290
+ // TODO(TS) fix ref type
291
+ const { ref }: any = child;
292
+ if (ref !== null) {
293
+ if (typeof ref === 'function') {
294
+ ref(node);
295
+ } else {
296
+ ref.current = node;
297
+ }
298
+ }
299
+ };
300
+
301
+ private createGestureHandler = (
302
+ newConfig: Readonly<Record<string, unknown>>
303
+ ) => {
304
+ this.config = newConfig;
305
+
306
+ RNGestureHandlerModule.createGestureHandler(
307
+ name,
308
+ this.handlerTag,
309
+ newConfig
310
+ );
311
+ };
312
+
313
+ private attachGestureHandler = (newViewTag: number) => {
314
+ this.viewTag = newViewTag;
315
+
316
+ if (Platform.OS === 'web') {
317
+ // typecast due to dynamic resolution, attachGestureHandler should have web version signature in this branch
318
+ (
319
+ RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler
320
+ )(
321
+ this.handlerTag,
322
+ newViewTag,
323
+ ActionType.JS_FUNCTION_OLD_API, // ignored on web
324
+ this.propsRef
325
+ );
326
+ } else {
327
+ registerOldGestureHandler(this.handlerTag, {
328
+ onGestureEvent: this.onGestureHandlerEvent,
329
+ onGestureStateChange: this.onGestureHandlerStateChange,
330
+ });
331
+
332
+ const actionType = (() => {
333
+ if (
334
+ (this.props?.onGestureEvent &&
335
+ 'current' in this.props.onGestureEvent) ||
336
+ (this.props?.onHandlerStateChange &&
337
+ 'current' in this.props.onHandlerStateChange)
338
+ ) {
339
+ // Reanimated worklet
340
+ return ActionType.REANIMATED_WORKLET;
341
+ } else if (
342
+ this.props?.onGestureEvent &&
343
+ '__isNative' in this.props.onGestureEvent
344
+ ) {
345
+ // Animated.event with useNativeDriver: true
346
+ return ActionType.NATIVE_ANIMATED_EVENT;
347
+ } else {
348
+ // JS callback or Animated.event with useNativeDriver: false
349
+ return ActionType.JS_FUNCTION_OLD_API;
350
+ }
351
+ })();
352
+
353
+ RNGestureHandlerModule.attachGestureHandler(
354
+ this.handlerTag,
355
+ newViewTag,
356
+ actionType
357
+ );
358
+ }
359
+
360
+ scheduleFlushOperations();
361
+ };
362
+
363
+ private updateGestureHandler = (
364
+ newConfig: Readonly<Record<string, unknown>>
365
+ ) => {
366
+ this.config = newConfig;
367
+
368
+ RNGestureHandlerModule.updateGestureHandler(this.handlerTag, newConfig);
369
+ scheduleFlushOperations();
370
+ };
371
+
372
+ private update(remainingTries: number) {
373
+ if (!this.isMountedRef.current) {
374
+ return;
375
+ }
376
+
377
+ const props: HandlerProps<U> = this.props;
378
+
379
+ // When ref is set via a function i.e. `ref={(r) => refObject.current = r}` instead of
380
+ // `ref={refObject}` it's possible that it won't be resolved in time. Seems like trying
381
+ // again is easy enough fix.
382
+ if (hasUnresolvedRefs(props) && remainingTries > 0) {
383
+ queueMicrotask(() => {
384
+ this.update(remainingTries - 1);
385
+ });
386
+ } else {
387
+ const newConfig = filterConfig(
388
+ transformProps ? transformProps(this.props) : this.props,
389
+ [...allowedProps, ...customNativeProps],
390
+ config
391
+ );
392
+ if (!deepEqual(this.config, newConfig)) {
393
+ this.updateGestureHandler(newConfig);
394
+ }
395
+ }
396
+ }
397
+
398
+ setNativeProps(updates: any) {
399
+ const mergedProps = { ...this.props, ...updates };
400
+ const newConfig = filterConfig(
401
+ transformProps ? transformProps(mergedProps) : mergedProps,
402
+ [...allowedProps, ...customNativeProps],
403
+ config
404
+ );
405
+ this.updateGestureHandler(newConfig);
406
+ }
407
+
408
+ render() {
409
+ if (__DEV__ && !this.context && !isJestEnv() && Platform.OS !== 'web' && (Platform.OS as any) !== "harmony") { // RNOH: patch
410
+ throw new Error(
411
+ name +
412
+ ' must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'
413
+ );
414
+ }
415
+
416
+ let gestureEventHandler = this.onGestureHandlerEvent;
417
+ // Another instance of https://github.com/microsoft/TypeScript/issues/13995
418
+ type OnGestureEventHandlers = {
419
+ onGestureEvent?: BaseGestureHandlerProps<U>['onGestureEvent'];
420
+ onGestureHandlerEvent?: InternalEventHandlers['onGestureHandlerEvent'];
421
+ };
422
+ const { onGestureEvent, onGestureHandlerEvent }: OnGestureEventHandlers =
423
+ this.props;
424
+ if (onGestureEvent && typeof onGestureEvent !== 'function') {
425
+ // If it's not a method it should be an native Animated.event
426
+ // object. We set it directly as the handler for the view
427
+ // In this case nested handlers are not going to be supported
428
+ if (onGestureHandlerEvent) {
429
+ throw new Error(
430
+ 'Nesting touch handlers with native animated driver is not supported yet'
431
+ );
432
+ }
433
+ gestureEventHandler = onGestureEvent;
434
+ } else {
435
+ if (
436
+ onGestureHandlerEvent &&
437
+ typeof onGestureHandlerEvent !== 'function'
438
+ ) {
439
+ throw new Error(
440
+ 'Nesting touch handlers with native animated driver is not supported yet'
441
+ );
442
+ }
443
+ }
444
+
445
+ let gestureStateEventHandler = this.onGestureHandlerStateChange;
446
+ // Another instance of https://github.com/microsoft/TypeScript/issues/13995
447
+ type OnGestureStateChangeHandlers = {
448
+ onHandlerStateChange?: BaseGestureHandlerProps<U>['onHandlerStateChange'];
449
+ onGestureHandlerStateChange?: InternalEventHandlers['onGestureHandlerStateChange'];
450
+ };
451
+ const {
452
+ onHandlerStateChange,
453
+ onGestureHandlerStateChange,
454
+ }: OnGestureStateChangeHandlers = this.props;
455
+ if (onHandlerStateChange && typeof onHandlerStateChange !== 'function') {
456
+ // If it's not a method it should be an native Animated.event
457
+ // object. We set it directly as the handler for the view
458
+ // In this case nested handlers are not going to be supported
459
+ if (onGestureHandlerStateChange) {
460
+ throw new Error(
461
+ 'Nesting touch handlers with native animated driver is not supported yet'
462
+ );
463
+ }
464
+ gestureStateEventHandler = onHandlerStateChange;
465
+ } else {
466
+ if (
467
+ onGestureHandlerStateChange &&
468
+ typeof onGestureHandlerStateChange !== 'function'
469
+ ) {
470
+ throw new Error(
471
+ 'Nesting touch handlers with native animated driver is not supported yet'
472
+ );
473
+ }
474
+ }
475
+ const events = {
476
+ onGestureHandlerEvent: this.state.allowTouches
477
+ ? gestureEventHandler
478
+ : undefined,
479
+ onGestureHandlerStateChange: this.state.allowTouches
480
+ ? gestureStateEventHandler
481
+ : undefined,
482
+ };
483
+
484
+ this.propsRef.current = events;
485
+
486
+ let child: any = null;
487
+ try {
488
+ child = React.Children.only(this.props.children);
489
+ } catch (e) {
490
+ throw new Error(
491
+ tagMessage(
492
+ `${name} got more than one view as a child. If you want the gesture to work on multiple views, wrap them with a common parent and attach the gesture to that view.`
493
+ )
494
+ );
495
+ }
496
+
497
+ let grandChildren = child.props.children;
498
+ if (
499
+ __DEV__ &&
500
+ child.type &&
501
+ (child.type === 'RNGestureHandlerButton' ||
502
+ child.type.name === 'View' ||
503
+ child.type.displayName === 'View')
504
+ ) {
505
+ grandChildren = React.Children.toArray(grandChildren);
506
+ grandChildren.push(
507
+ <PressabilityDebugView
508
+ key="pressabilityDebugView"
509
+ color="mediumspringgreen"
510
+ hitSlop={child.props.hitSlop}
511
+ />
512
+ );
513
+ }
514
+
515
+ return React.cloneElement(
516
+ child,
517
+ {
518
+ ref: this.refHandler,
519
+ collapsable: false,
520
+ ...(isJestEnv()
521
+ ? {
522
+ handlerType: name,
523
+ handlerTag: this.handlerTag,
524
+ }
525
+ : {}),
526
+ testID: this.props.testID ?? child.props.testID,
527
+ ...events,
528
+ },
529
+ grandChildren
530
+ );
531
+ }
532
+ }
533
+ return Handler;
534
+ }