From 05f9296558228a0fe5cf65b8b469baba0ce9aa72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Wed, 18 Feb 2026 11:35:07 +0100 Subject: [PATCH 1/8] handle common props --- .../v3/detectors/HostGestureDetector.web.tsx | 10 ++++++++++ .../InterceptingGestureDetector.tsx | 19 ++++++++++++++----- .../VirtualDetector/VirtualDetector.tsx | 16 +++++++++++++--- .../src/v3/detectors/common.ts | 3 ++- .../src/v3/types/DetectorTypes.ts | 4 ++++ 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx b/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx index f822fee97a..a9461fef84 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx @@ -20,6 +20,9 @@ export interface VirtualChildrenWeb { viewTag: number; handlerTags: number[]; viewRef: RefObject; + userSelect?: UserSelect; + touchAction?: TouchAction; + enableContextMenu?: boolean; } const EMPTY_HANDLERS = new Set(); @@ -174,6 +177,13 @@ const HostGestureDetector = (props: GestureHandlerDetectorProps) => { attachedVirtualHandlers.current.get(child.viewTag)!, ActionType.VIRTUAL_DETECTOR ); + currentHandlerTags.forEach((tag) => { + RNGestureHandlerModule.updateGestureHandlerConfig(tag, { + userSelect: child.userSelect, + touchAction: child.touchAction, + enableContextMenu: child.enableContextMenu, + }); + }); }); }, [props.virtualChildren]); diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index 2e77501c02..47c0ef67b1 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -43,11 +43,20 @@ export function InterceptingGestureDetector({ ); const virtualChildrenForNativeComponent: VirtualChildrenForNative[] = useMemo( () => - Array.from(virtualChildren).map((child) => ({ - viewTag: child.viewTag, - handlerTags: child.handlerTags, - viewRef: child.viewRef, - })), + Platform.OS === 'web' + ? Array.from(virtualChildren).map((child) => ({ + viewTag: child.viewTag, + handlerTags: child.handlerTags, + viewRef: child.viewRef, + userSelect: child.userSelect, + touchAction: child.touchAction, + enableContextMenu: child.enableContextMenu, + })) + : Array.from(virtualChildren).map((child) => ({ + viewTag: child.viewTag, + handlerTags: child.handlerTags, + viewRef: child.viewRef, + })), [virtualChildren] ); const [mode, setMode] = useState( diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx index 3840ad9db0..42379a6e9d 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/VirtualDetector.tsx @@ -76,14 +76,24 @@ export function VirtualDetector( methods: props.gesture.detectorCallbacks as DetectorCallbacks, // used by HostGestureDetector on web viewRef: Platform.OS === 'web' ? viewRef : undefined, + userSelect: props.userSelect, + touchAction: props.touchAction, + enableContextMenu: props.enableContextMenu, }; - register(virtualChild); - return () => { unregister(virtualChild); }; - }, [viewTag, props.gesture, register, unregister, setMode]); + }, [ + viewTag, + props.gesture, + props.userSelect, + props.touchAction, + props.enableContextMenu, + register, + unregister, + setMode, + ]); configureRelations(props.gesture); diff --git a/packages/react-native-gesture-handler/src/v3/detectors/common.ts b/packages/react-native-gesture-handler/src/v3/detectors/common.ts index 1315fe0fbc..1eeb71e086 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/common.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/common.ts @@ -29,7 +29,8 @@ export interface InterceptingGestureDetectorProps } // TODO: Handle CommonGestureDetectorProps inside VirtualGestureDetector -export interface VirtualDetectorProps { +export interface VirtualDetectorProps + extends CommonGestureDetectorProps { children?: React.ReactNode; gesture: Gesture; } diff --git a/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts b/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts index dca181be8d..e0b59b62ae 100644 --- a/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts +++ b/packages/react-native-gesture-handler/src/v3/types/DetectorTypes.ts @@ -3,6 +3,7 @@ import { GestureUpdateEventWithHandlerData, GestureHandlerEventWithHandlerData, } from './EventTypes'; +import { TouchAction, UserSelect } from '../../handlers/gestureHandlerCommon'; export type DetectorCallbacks = { jsEventHandler: @@ -24,4 +25,7 @@ export type VirtualChild = { // only set on web viewRef: unknown; + userSelect?: UserSelect; + touchAction?: TouchAction; + enableContextMenu?: boolean; }; From 60922d79af4e59455f5f562e7dc4063e93b24926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Wed, 18 Feb 2026 12:12:56 +0100 Subject: [PATCH 2/8] update name --- .../VirtualDetector/InterceptingGestureDetector.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index 47c0ef67b1..71dcf9c98c 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -22,6 +22,7 @@ import { tagMessage } from '../../../utils'; import { useEnsureGestureHandlerRootView } from '../useEnsureGestureHandlerRootView'; import { ReanimatedNativeDetector } from '../ReanimatedNativeDetector'; import { Platform } from 'react-native'; +import { VirtualChildrenWeb } from '../HostGestureDetector.web'; interface VirtualChildrenForNative { viewTag: number; @@ -41,7 +42,10 @@ export function InterceptingGestureDetector({ const [virtualChildren, setVirtualChildren] = useState>( () => new Set() ); - const virtualChildrenForNativeComponent: VirtualChildrenForNative[] = useMemo( + const strippedVirtualChildren: ( + | VirtualChildrenForNative + | VirtualChildrenWeb + )[] = useMemo( () => Platform.OS === 'web' ? Array.from(virtualChildren).map((child) => ({ @@ -270,7 +274,7 @@ export function InterceptingGestureDetector({ } handlerTags={handlerTags} style={nativeDetectorStyles.detector} - virtualChildren={virtualChildrenForNativeComponent} + virtualChildren={strippedVirtualChildren} moduleId={globalThis._RNGH_MODULE_ID}> {children} From b2556187e7c4bd45745eed8ab1b8f889a0ffa0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Wed, 18 Feb 2026 12:14:38 +0100 Subject: [PATCH 3/8] not duplicating children --- packages/react-native-gesture-handler/src/v3/detectors/common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/common.ts b/packages/react-native-gesture-handler/src/v3/detectors/common.ts index 1eeb71e086..b48d5a4f01 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/common.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/common.ts @@ -31,7 +31,6 @@ export interface InterceptingGestureDetectorProps // TODO: Handle CommonGestureDetectorProps inside VirtualGestureDetector export interface VirtualDetectorProps extends CommonGestureDetectorProps { - children?: React.ReactNode; gesture: Gesture; } From aa95d5de0485f2f8f643afd0e5aed424590c8449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Wed, 18 Feb 2026 12:15:07 +0100 Subject: [PATCH 4/8] remove todo --- packages/react-native-gesture-handler/src/v3/detectors/common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/common.ts b/packages/react-native-gesture-handler/src/v3/detectors/common.ts index b48d5a4f01..cf2c6ccf7d 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/common.ts +++ b/packages/react-native-gesture-handler/src/v3/detectors/common.ts @@ -28,7 +28,6 @@ export interface InterceptingGestureDetectorProps gesture?: Gesture; } -// TODO: Handle CommonGestureDetectorProps inside VirtualGestureDetector export interface VirtualDetectorProps extends CommonGestureDetectorProps { gesture: Gesture; From 2ab669d58b62efc6b48c0700041849c26a19157f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= <81448793+akwasniewski@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:15:08 +0100 Subject: [PATCH 5/8] Update packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: MichaƂ Bert <63123542+m-bert@users.noreply.github.com> --- .../src/v3/detectors/HostGestureDetector.web.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx b/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx index a9461fef84..22c52ded2c 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx @@ -177,6 +177,7 @@ const HostGestureDetector = (props: GestureHandlerDetectorProps) => { attachedVirtualHandlers.current.get(child.viewTag)!, ActionType.VIRTUAL_DETECTOR ); + currentHandlerTags.forEach((tag) => { RNGestureHandlerModule.updateGestureHandlerConfig(tag, { userSelect: child.userSelect, From 400a84c673ded49d99545ddbbd913217309e9a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Mon, 23 Feb 2026 10:27:12 +0100 Subject: [PATCH 6/8] supertype --- .../VirtualDetector/InterceptingGestureDetector.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index 71dcf9c98c..ef21c71ffa 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -22,12 +22,18 @@ import { tagMessage } from '../../../utils'; import { useEnsureGestureHandlerRootView } from '../useEnsureGestureHandlerRootView'; import { ReanimatedNativeDetector } from '../ReanimatedNativeDetector'; import { Platform } from 'react-native'; -import { VirtualChildrenWeb } from '../HostGestureDetector.web'; +import { + TouchAction, + UserSelect, +} from '../../../handlers/gestureHandlerCommon'; interface VirtualChildrenForNative { viewTag: number; handlerTags: number[]; viewRef: unknown; + userSelect?: UserSelect; + touchAction?: TouchAction; + enableContextMenu?: boolean; } export function InterceptingGestureDetector({ @@ -42,10 +48,7 @@ export function InterceptingGestureDetector({ const [virtualChildren, setVirtualChildren] = useState>( () => new Set() ); - const strippedVirtualChildren: ( - | VirtualChildrenForNative - | VirtualChildrenWeb - )[] = useMemo( + const strippedVirtualChildren: VirtualChildrenForNative[] = useMemo( () => Platform.OS === 'web' ? Array.from(virtualChildren).map((child) => ({ From 19d0a232dbc961b442ce1aab6d2ff87d90c07322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Mon, 23 Feb 2026 10:30:15 +0100 Subject: [PATCH 7/8] update name --- .../detectors/VirtualDetector/InterceptingGestureDetector.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index ef21c71ffa..43f14bbe24 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -27,7 +27,7 @@ import { UserSelect, } from '../../../handlers/gestureHandlerCommon'; -interface VirtualChildrenForNative { +interface StrippedVirtualChildren { viewTag: number; handlerTags: number[]; viewRef: unknown; @@ -48,7 +48,7 @@ export function InterceptingGestureDetector({ const [virtualChildren, setVirtualChildren] = useState>( () => new Set() ); - const strippedVirtualChildren: VirtualChildrenForNative[] = useMemo( + const strippedVirtualChildren: StrippedVirtualChildren[] = useMemo( () => Platform.OS === 'web' ? Array.from(virtualChildren).map((child) => ({ From a6da14a303016831be265e0d2262267dffd16c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Antoni=20Kwa=C5=9Bniewski?= Date: Tue, 24 Feb 2026 10:01:49 +0100 Subject: [PATCH 8/8] not passing viewRef to native --- .../detectors/VirtualDetector/InterceptingGestureDetector.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx index 43f14bbe24..54de97d439 100644 --- a/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx +++ b/packages/react-native-gesture-handler/src/v3/detectors/VirtualDetector/InterceptingGestureDetector.tsx @@ -30,7 +30,7 @@ import { interface StrippedVirtualChildren { viewTag: number; handlerTags: number[]; - viewRef: unknown; + viewRef?: unknown; userSelect?: UserSelect; touchAction?: TouchAction; enableContextMenu?: boolean; @@ -62,7 +62,6 @@ export function InterceptingGestureDetector({ : Array.from(virtualChildren).map((child) => ({ viewTag: child.viewTag, handlerTags: child.handlerTags, - viewRef: child.viewRef, })), [virtualChildren] );