}
+ />
+ )
+);
diff --git a/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx b/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx
new file mode 100644
index 0000000000..05f43c3ba5
--- /dev/null
+++ b/packages/react-native-gesture-handler/src/v3/createNativeWrapper.tsx
@@ -0,0 +1,74 @@
+import React, { useImperativeHandle, useRef } from 'react';
+
+import { NativeWrapperProps } from './hooks/utils';
+import { useNative } from './hooks/gestures';
+import { NativeDetector } from './detectors/NativeDetector';
+import type { NativeWrapperProperties } from './types/NativeWrapperType';
+import {
+ NativeViewGestureConfig,
+ NativeViewHandlerData,
+} from './hooks/gestures/native/useNative';
+import { Gesture } from './types';
+
+export type ComponentWrapperRef = {
+ componentRef: React.ComponentType
;
+ gestureRef: Gesture;
+};
+
+export default function createNativeWrapper(
+ Component: React.ComponentType
,
+ config: Readonly = {}
+) {
+ const ComponentWrapper = (
+ props: P & NativeWrapperProperties & { ref?: React.RefObject }
+ ) => {
+ // Filter out props that should be passed to gesture handler wrapper
+ const { gestureHandlerProps, childProps } = Object.keys(props).reduce(
+ (res, key) => {
+ // @ts-ignore TS being overly protective with it's types, see https://github.com/microsoft/TypeScript/issues/26255#issuecomment-458013731 for more info
+ if (NativeWrapperProps.has(key)) {
+ // @ts-ignore FIXME(TS)
+ res.gestureHandlerProps[key] = props[key];
+ } else {
+ // @ts-ignore FIXME(TS)
+ res.childProps[key] = props[key];
+ }
+ return res;
+ },
+ {
+ gestureHandlerProps: { ...config }, // Watch out not to modify config
+ childProps: {
+ enabled: props.enabled,
+ hitSlop: props.hitSlop,
+ // testID: props.testID,
+ } as P,
+ }
+ );
+
+ const native = useNative(gestureHandlerProps);
+
+ const componentRef = useRef>(null);
+ const gestureRef = useRef(native);
+
+ useImperativeHandle(props.ref, () => ({
+ componentRef: componentRef.current,
+ gestureRef: gestureRef.current,
+ }));
+
+ return (
+
+
+
+ );
+ };
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ ComponentWrapper.displayName =
+ Component?.displayName ||
+ // @ts-ignore if render doesn't exist it will return undefined and go further
+ Component?.render?.name ||
+ (typeof Component === 'string' && Component) ||
+ 'ComponentWrapper';
+
+ return ComponentWrapper;
+}
diff --git a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts
index 85edd466d1..aafd30906a 100644
--- a/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts
+++ b/packages/react-native-gesture-handler/src/v3/hooks/gestures/native/useNative.ts
@@ -11,7 +11,7 @@ import { useGesture } from '../../useGesture';
import { useClonedAndRemappedConfig } from '../../utils';
import { NativeGestureNativeProperties } from './NativeProperties';
-type NativeViewHandlerData = {
+export type NativeViewHandlerData = {
pointerInside: boolean;
};
diff --git a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts
index 1091cbe8ce..fdb65c1f93 100644
--- a/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts
+++ b/packages/react-native-gesture-handler/src/v3/hooks/utils/propsWhiteList.ts
@@ -1,11 +1,13 @@
import {
BaseGestureConfig,
CommonGestureConfig,
+ ExternalRelations,
GestureCallbacks,
HandlersPropsWhiteList,
InternalConfigProps,
SingleGestureName,
} from '../../types';
+import { NativeWrapperProperties } from '../../types/NativeWrapperType';
import { FlingNativeProperties } from '../gestures/fling/FlingProperties';
import { HoverNativeProperties } from '../gestures/hover/HoverProperties';
import { LongPressNativeProperties } from '../gestures/longPress/LongPressProperties';
@@ -13,10 +15,7 @@ import { NativeHandlerNativeProperties } from '../gestures/native/NativeProperti
import { PanNativeProperties } from '../gestures/pan/PanProperties';
import { TapNativeProperties } from '../gestures/tap/TapProperties';
-export const allowedNativeProps = new Set<
- keyof CommonGestureConfig | keyof InternalConfigProps
->([
- // CommonGestureConfig
+const CommonConfig = new Set([
'enabled',
'shouldCancelWhenOutside',
'hitSlop',
@@ -25,6 +24,18 @@ export const allowedNativeProps = new Set<
'mouseButton',
'enableContextMenu',
'touchAction',
+]);
+
+const ExternalRelationsConfig = new Set([
+ 'simultaneousWith',
+ 'requireToFail',
+ 'block',
+]);
+
+export const allowedNativeProps = new Set<
+ keyof CommonGestureConfig | keyof InternalConfigProps
+>([
+ ...CommonConfig,
// InternalConfigProps
'dispatchesReanimatedEvents',
@@ -48,16 +59,12 @@ export const HandlerCallbacks = new Set<
export const PropsToFilter = new Set>([
...HandlerCallbacks,
+ ...ExternalRelationsConfig,
// Config props
'changeEventCalculator',
'disableReanimated',
'shouldUseReanimatedDetector',
-
- // Relations
- 'simultaneousWithExternalGesture',
- 'requireExternalGestureToFail',
- 'blocksExternalGesture',
]);
export const PropsWhiteLists = new Map<
@@ -73,3 +80,11 @@ export const PropsWhiteLists = new Map<
]);
export const EMPTY_WHITE_LIST = new Set();
+
+export const NativeWrapperProps = new Set([
+ ...CommonConfig,
+ ...HandlerCallbacks,
+ ...NativeHandlerNativeProperties,
+ ...ExternalRelationsConfig,
+ 'disableReanimated',
+]);
diff --git a/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts b/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts
index 776ad7d694..5673c4c789 100644
--- a/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts
+++ b/packages/react-native-gesture-handler/src/v3/types/GestureTypes.ts
@@ -10,9 +10,9 @@ import { FilterNeverProperties } from './UtilityTypes';
// Unfortunately, this type cannot be moved into ConfigTypes.ts because of circular dependency
export type ExternalRelations = {
- simultaneousWith?: Gesture | Gesture[];
- requireToFail?: Gesture | Gesture[];
- block?: Gesture | Gesture[];
+ simultaneousWith?: AnyGesture | AnyGesture[];
+ requireToFail?: AnyGesture | AnyGesture[];
+ block?: AnyGesture | AnyGesture[];
};
// Similarly, this type cannot be moved into ConfigTypes.ts because it depends on `ExternalRelations`
diff --git a/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts
new file mode 100644
index 0000000000..0f38ab57c3
--- /dev/null
+++ b/packages/react-native-gesture-handler/src/v3/types/NativeWrapperType.ts
@@ -0,0 +1,8 @@
+import { CommonGestureConfig, ExternalRelations, GestureCallbacks } from '.';
+import { NativeGestureNativeProperties } from '../hooks/gestures/native/NativeProperties';
+import { NativeViewHandlerData } from '../hooks/gestures/native/useNative';
+
+export type NativeWrapperProperties = CommonGestureConfig &
+ GestureCallbacks &
+ NativeGestureNativeProperties &
+ ExternalRelations;