Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
7d9de2e
logic detector web
akwasniewski Aug 25, 2025
4ccf49e
avoiding propsRef
akwasniewski Aug 25, 2025
69e1c5d
refactor
akwasniewski Aug 27, 2025
9959d8b
logicChildren in specs
akwasniewski Aug 27, 2025
1f1f681
ios
akwasniewski Sep 1, 2025
a982767
merge with next
akwasniewski Sep 1, 2025
81bf405
fix reanimated version
akwasniewski Sep 1, 2025
a90b83c
yarn lock
akwasniewski Sep 1, 2025
8c03f58
worklets
akwasniewski Sep 1, 2025
a3256d4
detach handlers
akwasniewski Sep 2, 2025
6f45a33
worklets fix
akwasniewski Sep 3, 2025
66390ab
android
akwasniewski Sep 4, 2025
1ef1969
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Sep 4, 2025
3379714
yarn lock fix
akwasniewski Sep 4, 2025
e9795cc
removed circular dependency
akwasniewski Sep 4, 2025
7fb8ea9
simplify ios
akwasniewski Sep 5, 2025
5c24151
removed logic events web/android
akwasniewski Sep 8, 2025
593c44f
android and web refactor
akwasniewski Sep 8, 2025
fe1d67d
one path
akwasniewski Sep 8, 2025
b147c7b
merge with next
akwasniewski Sep 8, 2025
4e718b3
merge fix
akwasniewski Sep 8, 2025
8e9d2dc
adjust for reanimated/animated separation
akwasniewski Sep 9, 2025
97b7369
general refactor
akwasniewski Sep 9, 2025
8b6df8c
simplified attaching
akwasniewski Sep 9, 2025
dab9e5f
tag in callback
akwasniewski Sep 10, 2025
089bbf2
not sharing web invoke
akwasniewski Sep 10, 2025
5fbe993
renamed logic props
akwasniewski Sep 10, 2025
ddce1fb
logic animated event
akwasniewski Sep 11, 2025
50c1af4
removed child tag from web
akwasniewski Sep 11, 2025
5f3f1eb
safe detaching
akwasniewski Sep 11, 2025
1f22ef4
typo fix
akwasniewski Sep 11, 2025
3e7bc43
more typos
akwasniewski Sep 11, 2025
cd4d158
comment styling
akwasniewski Sep 12, 2025
164c4e8
moved detector context
akwasniewski Sep 12, 2025
84bdf3d
renamed helper function
akwasniewski Sep 12, 2025
4365e3e
explained invoke method
akwasniewski Sep 12, 2025
33fe818
isV3Api helper function
akwasniewski Sep 12, 2025
6c42eae
renamed logic children
akwasniewski Sep 12, 2025
a11b6d3
renamed var containing logic handlers
akwasniewski Sep 12, 2025
a70f868
action type helper on android
akwasniewski Sep 12, 2025
c0c9bb0
simplify logic children to delete creation
akwasniewski Sep 12, 2025
a2ee13d
removed redundant check
akwasniewski Sep 12, 2025
f0f24b8
renamed parent tag to host detector tag
akwasniewski Sep 12, 2025
f0fb458
removed unnecessary variable
akwasniewski Sep 12, 2025
5e5e917
renamed set
akwasniewski Sep 12, 2025
abcac98
separate function to detach all handlers
akwasniewski Sep 15, 2025
5c367b5
fix testing remnant
akwasniewski Sep 15, 2025
b1d620a
non default useDetectorContext
akwasniewski Sep 15, 2025
157d87b
android action type whitespace
akwasniewski Sep 15, 2025
a1b94d5
clean up extension
akwasniewski Sep 15, 2025
75f218b
removed remnants
akwasniewski Sep 15, 2025
344617a
renamed logic children web
akwasniewski Sep 15, 2025
03b37c7
android whitespace
akwasniewski Sep 15, 2025
9420ead
removed unnecessary annotation
akwasniewski Sep 15, 2025
06bb0e1
whitespace
akwasniewski Sep 15, 2025
474e301
delete obsolete
akwasniewski Sep 15, 2025
1fef44a
Fallthrough comment
akwasniewski Sep 15, 2025
cb9ab7a
defining registry outside of loop
akwasniewski Sep 15, 2025
76fd9ff
merge with next
akwasniewski Sep 15, 2025
2a727cb
cleaner extension function
akwasniewski Sep 16, 2025
e6fbdba
extract repetition
akwasniewski Sep 16, 2025
6fa67e3
moved file
akwasniewski Sep 16, 2025
31fad02
fix bad merge
akwasniewski Sep 16, 2025
c9ffbdb
better error
akwasniewski Sep 16, 2025
f00e0dd
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Sep 16, 2025
72e7813
updating logic children
akwasniewski Sep 16, 2025
79f1d96
removed unnecessary return
akwasniewski Sep 16, 2025
86ff725
hostGestureDetector property
akwasniewski Sep 17, 2025
7213108
extracted update logic children
akwasniewski Sep 17, 2025
8015ea5
rename logic children deleton set
akwasniewski Sep 17, 2025
e589043
move invoke detector event
akwasniewski Sep 17, 2025
57b6b57
auto type
akwasniewski Sep 17, 2025
a8fa637
rename isv3api
akwasniewski Sep 17, 2025
468e23f
no put
akwasniewski Sep 17, 2025
63d44f7
simplify mapping
akwasniewski Sep 17, 2025
0b362be
better web detaching
akwasniewski Sep 17, 2025
20038b1
typing
akwasniewski Sep 17, 2025
f3f985c
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Sep 17, 2025
832a039
passing helper function directly
akwasniewski Sep 18, 2025
1d96fa1
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Sep 18, 2025
590a5cd
resolved workaround
akwasniewski Sep 19, 2025
f25cd9e
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Sep 19, 2025
0f58258
empty set array
akwasniewski Sep 22, 2025
93412f4
avoiding indentation
akwasniewski Sep 22, 2025
df8c9b7
reformated native children detach
akwasniewski Sep 22, 2025
0cabeb7
fix logic error
akwasniewski Sep 22, 2025
adc3c22
send event refactor
akwasniewski Sep 29, 2025
149c323
moved empty set to utils
akwasniewski Sep 29, 2025
1bcda3c
fix can coalesce check to v3
akwasniewski Sep 29, 2025
f0ea23f
coalesce check in touch event
akwasniewski Sep 29, 2025
153385c
simplify logic props creation
akwasniewski Oct 1, 2025
765e326
Merge branch 'next' into @akwasniewski/logic-detector
akwasniewski Oct 1, 2025
fae6478
added delegate detector
akwasniewski Oct 3, 2025
f084754
extract common
akwasniewski Oct 3, 2025
c9b90f0
Merge branch 'next' into @akwasniewski/separate-logic-native-detector
akwasniewski Oct 3, 2025
3a994b0
Merge branch 'next' into @akwasniewski/separate-logic-native-detector
akwasniewski Oct 6, 2025
94d9079
merge could have been better
akwasniewski Oct 6, 2025
a9ab3a5
changed folder structure
akwasniewski Oct 6, 2025
743124e
extracted common
akwasniewski Oct 6, 2025
88d4290
renamed detectors folder
akwasniewski Oct 9, 2025
b7e9fcd
detector index
akwasniewski Oct 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { tagMessage } from '../utils';
import { useExclusive, useRace, useSimultaneous } from '../v3/hooks/relations';
import { useGesture } from '../v3/hooks/useGesture';
import { configureRelations } from '../v3/NativeDetector/utils';
import { configureRelations } from '../v3/detectors/utils';
import { SingleGesture, SingleGestureName } from '../v3/types';
import { renderHook } from '@testing-library/react-native';

Expand Down
4 changes: 1 addition & 3 deletions packages/react-native-gesture-handler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,8 @@ export type {
} from './components/DrawerLayout';
export { default as DrawerLayout } from './components/DrawerLayout';

export type { NativeDetectorProps } from './v3/NativeDetector/NativeDetector';
export { NativeDetector } from './v3/NativeDetector/NativeDetector';
export * from './v3/detectors';

export { LogicDetector } from './v3/LogicDetector';
export * from './v3/hooks/useGesture';
export * from './v3/hooks/relations';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,18 @@
import React, { RefObject, useCallback, useRef, useState } from 'react';
import { Animated, StyleSheet } from 'react-native';
import HostGestureDetector from './HostGestureDetector';
import { tagMessage } from '../../utils';
import {
LogicChildren,
Gesture,
GestureEvents,
GestureHandlerEvent,
} from '../types';
import HostGestureDetector from '../HostGestureDetector';
import { LogicChildren, GestureEvents, GestureHandlerEvent } from '../../types';
import { DetectorContext } from './useDetectorContext';
import { Reanimated } from '../../handlers/gestures/reanimatedWrapper';
import { configureRelations } from './utils';
import { isComposedGesture } from '../hooks/utils/relationUtils';

export interface NativeDetectorProps<THandlerData, TConfig> {
children?: React.ReactNode;
gesture: Gesture<THandlerData, TConfig>;
}

const AnimatedNativeDetector =
Animated.createAnimatedComponent(HostGestureDetector);

const ReanimatedNativeDetector =
Reanimated?.default.createAnimatedComponent(HostGestureDetector);
import { Reanimated } from '../../../handlers/gestures/reanimatedWrapper';
import { configureRelations, ensureNativeDetectorComponent } from '../utils';
import { isComposedGesture } from '../../hooks/utils/relationUtils';
import {
AnimatedNativeDetector,
NativeDetectorProps,
nativeDetectorStyles,
ReanimatedNativeDetector,
} from '../common';

export function NativeDetector<THandlerData, TConfig>({
export function DelegateDetector<THandlerData, TConfig>({
gesture,
children,
}: NativeDetectorProps<THandlerData, TConfig>) {
Expand Down Expand Up @@ -63,17 +51,6 @@ export function NativeDetector<THandlerData, TConfig>({
setLogicChildren((prev) => prev.filter((c) => c.viewTag !== childTag));
}, []);

// It might happen only with ReanimatedNativeDetector
if (!NativeDetectorComponent) {
throw new Error(
tagMessage(
'Gesture expects to run on the UI thread, but failed to create the Reanimated NativeDetector.'
)
);
}

configureRelations(gesture);

const handleGestureEvent = (key: keyof GestureEvents<THandlerData>) => {
return (e: GestureHandlerEvent<THandlerData>) => {
if (gesture.gestureEvents[key]) {
Expand Down Expand Up @@ -125,6 +102,9 @@ export function NativeDetector<THandlerData, TConfig>({
getHandlers('onReanimatedTouchEvent')
);

ensureNativeDetectorComponent(NativeDetectorComponent);
configureRelations(gesture);

return (
<DetectorContext.Provider value={{ register, unregister }}>
<NativeDetectorComponent
Expand All @@ -150,18 +130,10 @@ export function NativeDetector<THandlerData, TConfig>({
onGestureHandlerReanimatedTouchEvent={reanimatedTouchEventHandler}
moduleId={globalThis._RNGH_MODULE_ID}
handlerTags={isComposedGesture(gesture) ? gesture.tags : [gesture.tag]}
style={styles.detector}
style={nativeDetectorStyles.detector}
logicChildren={logicChildren}>
{children}
</NativeDetectorComponent>
</DetectorContext.Provider>
);
}

const styles = StyleSheet.create({
detector: {
display: 'contents',
// TODO: remove, debug info only
backgroundColor: 'red',
},
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { RefObject, useCallback, useEffect, useRef, useState } from 'react';
import { Wrap } from '../handlers/gestures/GestureDetector/Wrap';
import { Wrap } from '../../../handlers/gestures/GestureDetector/Wrap';
import { findNodeHandle, Platform } from 'react-native';
import { useDetectorContext } from './NativeDetector/useDetectorContext';
import { NativeDetectorProps } from './NativeDetector/NativeDetector';
import { isComposedGesture } from './hooks/utils/relationUtils';
import { GestureEvents } from './types';
import { useDetectorContext } from './useDetectorContext';
import { isComposedGesture } from '../../hooks/utils/relationUtils';
import { GestureEvents } from '../../types';
import { NativeDetectorProps } from '../common';

export function LogicDetector<THandlerData, TConfig>(
props: NativeDetectorProps<THandlerData, TConfig>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext, RefObject, useContext } from 'react';
import { GestureEvents, LogicChildren } from '../types';
import { GestureEvents, LogicChildren } from '../../types';

type DetectorContextType = {
register: (
Expand All @@ -14,7 +14,9 @@ export const DetectorContext = createContext<DetectorContextType | null>(null);
export function useDetectorContext() {
const ctx = useContext(DetectorContext);
if (!ctx) {
throw new Error('Logic detector must be a descendant of a Native Detector');
throw new Error(
'Logic detector must be a descendant of a delegate detector'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Logic detector must be a descendant of a delegate detector'
tagMessage('Logic detector must be a descendant of a delegate detector')

);
}
return ctx;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import HostGestureDetector from './HostGestureDetector';
import { configureRelations, ensureNativeDetectorComponent } from './utils';
import { isComposedGesture } from '../hooks/utils/relationUtils';
import {
AnimatedNativeDetector,
NativeDetectorProps,
nativeDetectorStyles,
ReanimatedNativeDetector,
} from './common';

export function NativeDetector<THandlerData, TConfig>({
gesture,
children,
}: NativeDetectorProps<THandlerData, TConfig>) {
const NativeDetectorComponent = gesture.config.dispatchesAnimatedEvents
? AnimatedNativeDetector
: gesture.config.shouldUseReanimated
? ReanimatedNativeDetector
: HostGestureDetector;

ensureNativeDetectorComponent(NativeDetectorComponent);
configureRelations(gesture);

return (
<NativeDetectorComponent
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerStateChange={
gesture.gestureEvents.onGestureHandlerStateChange
}
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerEvent={gesture.gestureEvents.onGestureHandlerEvent}
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerTouchEvent={
gesture.gestureEvents.onGestureHandlerTouchEvent
}
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerReanimatedStateChange={
gesture.gestureEvents.onReanimatedStateChange
}
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerReanimatedEvent={
gesture.gestureEvents.onReanimatedUpdateEvent
}
// @ts-ignore This is a type mismatch between RNGH types and RN Codegen types
onGestureHandlerReanimatedTouchEvent={
gesture.gestureEvents.onReanimatedTouchEvent
}
onGestureHandlerAnimatedEvent={
gesture.gestureEvents.onGestureHandlerAnimatedEvent
}
moduleId={globalThis._RNGH_MODULE_ID}
handlerTags={isComposedGesture(gesture) ? gesture.tags : [gesture.tag]}
style={nativeDetectorStyles.detector}>
{children}
</NativeDetectorComponent>
);
}
24 changes: 24 additions & 0 deletions packages/react-native-gesture-handler/src/v3/detectors/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { Gesture } from '../types';
import { Reanimated } from '../../handlers/gestures/reanimatedWrapper';
import { Animated, StyleSheet } from 'react-native';
import HostGestureDetector from './HostGestureDetector';

export interface NativeDetectorProps<THandlerData, TConfig> {
children?: React.ReactNode;
gesture: Gesture<THandlerData, TConfig>;
}

export const AnimatedNativeDetector =
Animated.createAnimatedComponent(HostGestureDetector);

export const ReanimatedNativeDetector =
Reanimated?.default.createAnimatedComponent(HostGestureDetector);

export const nativeDetectorStyles = StyleSheet.create({
detector: {
display: 'contents',
// TODO: remove, debug info only
backgroundColor: 'red',
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type { NativeDetectorProps } from './common';
export { NativeDetector } from './NativeDetector';

export { LogicDetector } from './LogicDetector/LogicDetector';
export { DelegateDetector } from './LogicDetector/DelegateDetector';
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// For `simultaneousHandlers` we use Set as the order doesn't matter.

import RNGestureHandlerModule from '../../RNGestureHandlerModule';
import { tagMessage } from '../../utils';
import {
isComposedGesture,
prepareRelations,
Expand Down Expand Up @@ -150,4 +151,16 @@ export function configureRelations<THandlerData, TConfig>(
RNGestureHandlerModule.flushOperations();
}

export function ensureNativeDetectorComponent(
NativeDetectorComponent: unknown
): asserts NativeDetectorComponent {
if (!NativeDetectorComponent) {
throw new Error(
tagMessage(
'Gesture expects to run on the UI thread, but failed to create the Reanimated NativeDetector.'
)
);
}
}

export const EMPTY_SET = new Set<number>();
Loading