Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
daa017c
Separate Reanimated from JS in NativeDetector
m-bert Aug 21, 2025
1e17cf8
Separate Reanimated on Android
m-bert Aug 21, 2025
08d1e2b
Separate Reanimated on iOS
m-bert Aug 21, 2025
256f707
Reorganize structure
m-bert Aug 21, 2025
19fd985
Create ceparate hooks for Reanimated
m-bert Aug 21, 2025
133319b
Add checks in useGesture
m-bert Aug 22, 2025
e50f6cc
use isAnimatedEvent
m-bert Aug 22, 2025
b3ef022
Extract handlers in separate function
m-bert Aug 22, 2025
952fbe1
Pass correct touch event callback
m-bert Aug 22, 2025
ec9eaa7
Merge branch 'next' into @mbert/extract-reanimated-handlers
m-bert Aug 22, 2025
60a56e6
Merge branch 'next' into @mbert/extract-reanimated-handlers
m-bert Aug 25, 2025
fda23cc
Fix crash when onUpdate is Animated.Event
m-bert Aug 25, 2025
e46554b
Unify lateinit
m-bert Aug 25, 2025
13f3af4
Rename EventTarget on Android
m-bert Aug 25, 2025
d7a2b1a
Rename EventTarget on iOS
m-bert Aug 25, 2025
1b04d3c
Add reset for animated and reanimated events flags
m-bert Aug 25, 2025
b8df015
Rename getter for event handlers
m-bert Aug 25, 2025
93343da
Correctly handle disableReanimated
m-bert Aug 26, 2025
d1d3efb
Unpack nativeEvent
m-bert Aug 26, 2025
03a1e64
Bring back hooks
m-bert Aug 26, 2025
cc1313a
Use old name
m-bert Aug 26, 2025
dac39cf
Disable coalescing on Android
m-bert Aug 7, 2025
51b5a86
Implement DFS for gesture relations
m-bert Aug 13, 2025
92b4a3a
Implement module method for updating relations
m-bert Aug 14, 2025
e73ee57
Add blocksHandlers array
m-bert Aug 14, 2025
432aee0
Handle Simultaneous as root
m-bert Aug 14, 2025
b09d746
Change name to enum
m-bert Aug 14, 2025
db5d261
Move DFS to other file
m-bert Aug 14, 2025
43212af
Do not traverse single gestures
m-bert Aug 18, 2025
4ec26c0
Handle external relations
m-bert Aug 18, 2025
fa599af
Use operation block
m-bert Aug 20, 2025
42fc8c2
Move flushOperations into JS
m-bert Aug 20, 2025
f62a6df
Add exports for type
m-bert Aug 20, 2025
504feae
Add composed handler
m-bert Aug 26, 2025
122613f
Merge branch 'next' into @mbert/extract-reanimated-handlers
m-bert Aug 26, 2025
246f096
Merge branch '@mbert/extract-reanimated-handlers' into @mbert/relatio…
m-bert Aug 26, 2025
e229d84
Rename dfs
m-bert Aug 26, 2025
fac31e2
Split utils
m-bert Aug 26, 2025
53ce245
Merge branch 'next' into @mbert/extract-reanimated-handlers
m-bert Sep 4, 2025
fb88c8c
Change hook eslint rule to warning
m-bert Sep 4, 2025
8e5f07e
Extract choosing handler type into function
m-bert Sep 4, 2025
feaa167
Rename event handlers
m-bert Sep 4, 2025
3f2ea8c
Improve error message
m-bert Sep 4, 2025
4022b96
Move for loop inside function
m-bert Sep 4, 2025
8d9fc49
Merge branch '@mbert/extract-reanimated-handlers' into @mbert/relatio…
m-bert Sep 4, 2025
2dc44b8
Do not drop relataions on config change
m-bert Sep 4, 2025
fab60e5
Rename method
m-bert Sep 5, 2025
31c0e8b
Merge branch '@mbert/extract-reanimated-handlers' into @mbert/relatio…
m-bert Sep 5, 2025
832ffb0
Rename files to camelCase
m-bert Sep 5, 2025
bea99ab
Merge branch 'next' into @mbert/relations-v2
m-bert Sep 5, 2025
fb8c8e3
Rename files to camelCase
m-bert Sep 5, 2025
192556e
Remove todo
m-bert Sep 5, 2025
7c7876b
Make simultaneousWithExternalGesture symmetric
m-bert Sep 5, 2025
3e2b661
Fix crash with animated
m-bert Sep 5, 2025
8cd19ff
Add todo
m-bert Sep 5, 2025
619aed9
Use enums
m-bert Sep 8, 2025
b12824b
Use named type
m-bert Sep 8, 2025
4ad7f5b
Extract dfs call to utils
m-bert Sep 8, 2025
a6f1ecb
Pass composed type as argument
m-bert Sep 8, 2025
761e22a
Move function to global scope
m-bert Sep 8, 2025
648f862
Update comment
m-bert Sep 8, 2025
ce2de67
Assign instead of only push
m-bert Sep 9, 2025
ec85bb5
Add warning about the same gesture passed multiple times
m-bert Sep 9, 2025
2e99481
Do not store set in variable
m-bert Sep 9, 2025
adfada7
Change warning to error
m-bert Sep 9, 2025
7ab9b3b
Use warn about multiple animated events
m-bert Sep 9, 2025
c2c88cc
Do not add repeating tags with external relations into simultaneous h…
m-bert Sep 10, 2025
4baf2cb
Do not mark gesture as simultaneous with itself
m-bert Sep 10, 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
3 changes: 2 additions & 1 deletion apps/basic-example/src/NativeDetector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Animated, Button, useAnimatedValue } from 'react-native';
import {
GestureHandlerRootView,
NativeDetector,
SingleGestureType,
useGesture,
} from 'react-native-gesture-handler';

Expand All @@ -17,7 +18,7 @@ export default function App() {
}
);

const gesture = useGesture('PanGestureHandler', {
const gesture = useGesture(SingleGestureType.Pan, {
onUpdate: event,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
val handler = registry.getHandler(handlerTag) ?: return
val factory = RNGestureHandlerFactoryUtil.findFactoryForHandler<GestureHandler>(handler) ?: return

interactionManager.dropRelationsForHandlerWithTag(handlerTag)
interactionManager.configureInteractions(handler, config)
factory.setConfig(handler, config)
}

Expand All @@ -111,6 +109,15 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
factory.updateConfig(handler, config)
}

@ReactMethod
override fun configureRelations(handlerTagDouble: Double, relations: ReadableMap) {
val handlerTag = handlerTagDouble.toInt()
val handler = registry.getHandler(handlerTag) ?: return

interactionManager.dropRelationsForHandlerWithTag(handlerTag)
interactionManager.configureInteractions(handler, relations)
}

@ReactMethod
override fun dropGestureHandler(handlerTagDouble: Double) {
val handlerTag = handlerTagDouble.toInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class RNGestureHandlerEvent private constructor() : Event<RNGestureHandlerEvent>
EVENT_NAME
}

override fun canCoalesce() = true
// Unfortunately getCoalescingKey is not considered when sending event to C++, therefore we have to disable coalescing in v3
override fun canCoalesce() = actionType != GestureHandler.ACTION_TYPE_NATIVE_DETECTOR

override fun getCoalescingKey() = coalescingKey

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
- (void)resetConfig NS_REQUIRES_SUPER;
- (void)setConfig:(nullable NSDictionary *)config NS_REQUIRES_SUPER;
- (void)updateConfig:(nullable NSDictionary *)config NS_REQUIRES_SUPER;
- (void)updateRelations:(nonnull NSDictionary *)relations;
- (void)handleGesture:(nonnull id)recognizer;
- (void)handleGesture:(nonnull id)recognizer inState:(RNGestureHandlerState)state;
- (BOOL)containsPointInView;
Expand Down
14 changes: 7 additions & 7 deletions packages/react-native-gesture-handler/apple/RNGestureHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ - (void)resetConfig
self.enabled = YES;
self.manualActivation = NO;
_shouldCancelWhenOutside = NO;
_handlersToWaitFor = nil;
_simultaneousHandlers = nil;
_handlersThatShouldWait = nil;
Comment on lines -106 to -108
Copy link
Member

Choose a reason for hiding this comment

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

  1. Why don't we want to reset it?
  2. Why only on iOS?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why don't we want to reset it?

Doing so in resetConfig resulted in relations not working on iOS since it was reset after setting those relations. Also now they are not part of the config so it is not the best place to do it. Given that calling updateRelations sets, not updates this array:

  _handlersToWaitFor = [RCTConvert NSNumberArray:relations[@"waitFor"]];

I'm not sure if reset is necessary in that case. If so, let me know.

Why only on iOS?

On android it is handled in InteractionsManager, so it is a bit different flow and everything worked out of the box.

_hitSlop = RNGHHitSlopEmpty;
_needsPointerData = NO;
_dispatchesAnimatedEvents = NO;
Expand All @@ -123,10 +120,6 @@ - (void)setConfig:(NSDictionary *)config

- (void)updateConfig:(NSDictionary *)config
{
_handlersToWaitFor = [RCTConvert NSNumberArray:config[@"waitFor"]];
_simultaneousHandlers = [RCTConvert NSNumberArray:config[@"simultaneousHandlers"]];
_handlersThatShouldWait = [RCTConvert NSNumberArray:config[@"blocksHandlers"]];

id prop = config[@"enabled"];
if (prop != nil) {
self.enabled = [RCTConvert BOOL:prop];
Expand Down Expand Up @@ -191,6 +184,13 @@ - (void)updateConfig:(NSDictionary *)config
}
}

- (void)updateRelations:(NSDictionary *)relations
{
_handlersToWaitFor = [RCTConvert NSNumberArray:relations[@"waitFor"]];
_simultaneousHandlers = [RCTConvert NSNumberArray:relations[@"simultaneousHandlers"]];
_handlersThatShouldWait = [RCTConvert NSNumberArray:relations[@"blocksHandlers"]];
}

- (void)setEnabled:(BOOL)enabled
{
_enabled = enabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

- (void)updateGestureHandlerConfig:(nonnull NSNumber *)handlerTag config:(nonnull NSDictionary *)config;

- (void)updateGestureHandlerRelations:(nonnull NSNumber *)handlerTag relations:(nonnull NSDictionary *)relations;

- (void)dropGestureHandler:(nonnull NSNumber *)handlerTag;

- (void)dropAllGestureHandlers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ - (void)updateGestureHandlerConfig:(NSNumber *)handlerTag config:(NSDictionary *
[handler updateConfig:config];
}

- (void)updateGestureHandlerRelations:(NSNumber *)handlerTag relations:(NSDictionary *)relations
{
RNGestureHandler *handler = [_registry handlerWithTag:handlerTag];
[handler updateRelations:relations];
}

- (void)dropGestureHandler:(NSNumber *)handlerTag
{
[_registry dropHandlerWithTag:handlerTag];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ - (void)updateGestureHandlerConfig:(double)handlerTag newConfig:(NSDictionary *)
}];
}

- (void)configureRelations:(double)handlerTag relations:(NSDictionary *)relations
{
RNGestureHandlerManager *manager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];
[manager updateGestureHandlerRelations:[NSNumber numberWithDouble:handlerTag] relations:relations];
}

- (void)dropGestureHandler:(double)handlerTag
{
[self addOperationBlock:^(RNGestureHandlerManager *manager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ let Reanimated:
>(
value: unknown
): value is WorkletFunction<Args, ReturnValue>;
useComposedEventHandler<T>(
handlers: (((event: T) => void) | null)[]
): (event: T) => void;
runOnUI<A extends any[], R>(
fn: (...args: A) => R
): (...args: Parameters<typeof fn>) => void;
Expand Down
7 changes: 5 additions & 2 deletions packages/react-native-gesture-handler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,12 @@ export type {
} from './components/DrawerLayout';
export { default as DrawerLayout } from './components/DrawerLayout';

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

export * from './v3/hooks/useGesture';
export * from './v3/hooks/relations';

export { SingleGestureType } from './v3/types';

initialize();
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface Spec extends TurboModule {
setGestureHandlerConfig: (handlerTag: Double, newConfig: Object) => void;
// eslint-disable-next-line @typescript-eslint/ban-types
updateGestureHandlerConfig: (handlerTag: Double, newConfig: Object) => void;
// eslint-disable-next-line @typescript-eslint/ban-types
configureRelations: (handlerTag: Double, relations: Object) => void;
dropGestureHandler: (handlerTag: Double) => void;
flushOperations: () => void;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import RNGestureHandlerDetectorNativeComponent from '../../specs/RNGestureHandlerDetectorNativeComponent';
const HostGestureDetector = RNGestureHandlerDetectorNativeComponent;
export default HostGestureDetector;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { Ref, useEffect, useRef } from 'react';
import RNGestureHandlerModule from '../RNGestureHandlerModule.web';
import { ActionType } from '../ActionType';
import { PropsRef } from '../web/interfaces';
import RNGestureHandlerModule from '../../RNGestureHandlerModule.web';
import { ActionType } from '../../ActionType';
import { PropsRef } from '../../web/interfaces';
import { View } from 'react-native';
import { tagMessage } from '../utils';
import { tagMessage } from '../../utils';

export interface GestureHandlerDetectorProps extends PropsRef {
handlerTags: number[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React from 'react';
import { NativeGesture } from './hooks/useGesture';
import { Reanimated } from '../handlers/gestures/reanimatedWrapper';

import { NativeGesture, ComposedGesture } from '../types';
import { Reanimated } from '../../handlers/gestures/reanimatedWrapper';
import { Animated, StyleSheet } from 'react-native';
import HostGestureDetector from './HostGestureDetector';
import { tagMessage } from '../utils';
import { tagMessage } from '../../utils';
import { configureRelations } from './utils';
import { isComposedGesture } from '../hooks/utils/relationUtils';

export interface NativeDetectorProps {
children?: React.ReactNode;
gesture: NativeGesture;
gesture: NativeGesture | ComposedGesture;
}

const AnimatedNativeDetector =
Expand All @@ -34,29 +35,37 @@ export function NativeDetector({ gesture, children }: NativeDetectorProps) {
);
}

configureRelations(gesture);

return (
<NativeDetectorComponent
// @ts-ignore TODO: Fix types
onGestureHandlerStateChange={
gesture.gestureEvents.onGestureHandlerStateChange
}
// @ts-ignore TODO: Fix types
onGestureHandlerEvent={gesture.gestureEvents.onGestureHandlerEvent}
// @ts-ignore TODO: Fix types
onGestureHandlerTouchEvent={
gesture.gestureEvents.onGestureHandlerTouchEvent
}
// @ts-ignore TODO: Fix types
onGestureHandlerReanimatedStateChange={
gesture.gestureEvents.onReanimatedStateChange
}
// @ts-ignore TODO: Fix types
onGestureHandlerReanimatedEvent={
gesture.gestureEvents.onReanimatedUpdateEvent
}
// @ts-ignore TODO: Fix types
onGestureHandlerReanimatedTouchEvent={
gesture.gestureEvents.onReanimatedTouchEvent
}
onGestureHandlerAnimatedEvent={
gesture.gestureEvents.onGestureHandlerAnimatedEvent
}
moduleId={globalThis._RNGH_MODULE_ID}
handlerTags={[gesture.tag]}
handlerTags={isComposedGesture(gesture) ? gesture.tags : [gesture.tag]}
style={styles.detector}>
{children}
</NativeDetectorComponent>
Expand Down
150 changes: 150 additions & 0 deletions packages/react-native-gesture-handler/src/v3/NativeDetector/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// This piece of magic traverses the gesture tree and populates `waitFor` and `simultaneousHandlers`
// arrays for each gesture. It traverses the tree recursively using DFS.
// `waitFor` and `simultaneousHandlers` are global data structures that will be populated into each gesture.
// For `waitFor` we need array as order of the gestures matters.
// For `simultaneousHandlers` we use Set as the order doesn't matter.

import RNGestureHandlerModule from '../../RNGestureHandlerModule';
import {
isComposedGesture,
prepareRelations,
} from '../hooks/utils/relationUtils';
import {
ComposedGesture,
ComposedGestureType,
Gesture,
NativeGesture,
} from '../types';

// The tree consists of ComposedGestures and NativeGestures. NativeGestures are always leaf nodes.
export const traverseGestureRelations = (
Copy link
Member

Choose a reason for hiding this comment

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

Uhm, can we have tests for that 🥺 (follow-up is fine, this is quite large already)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think so 😅 Do you mean jest tests that will check result arrays after DFS?

node: NativeGesture | ComposedGesture,
simultaneousHandlers: Set<number>,
waitFor: number[] = []
) => {
// If we are in the leaf node, we want to fill gesture relations arrays with current
// waitFor and simultaneousHandlers. We also want to configure relations on the native side.
if (!isComposedGesture(node)) {
node.gestureRelations = prepareRelations(node.config, node.tag);

node.gestureRelations.simultaneousHandlers.push(...simultaneousHandlers);
node.gestureRelations.waitFor.push(...waitFor);
Comment on lines +30 to +31
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this cause the arrays to grow with duplicates on every render?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, you're right 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed it a bit in ce2de67, let me know what you think


RNGestureHandlerModule.configureRelations(node.tag, {
waitFor: node.gestureRelations.waitFor,
simultaneousHandlers: node.gestureRelations.simultaneousHandlers,
blocksHandlers: node.gestureRelations.blocksHandlers,
});
Comment on lines +33 to +37
Copy link
Member

Choose a reason for hiding this comment

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

Can this be done outside of this function? If not, can this be renamed? traverseGestureRelations in any way doesn't suggest that it updates the gestures on the native side.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it will be better to rename it, though I'm open for a discussion (cc @akwasniewski).

If we stick to rename, what about traverseAndUpdateRelations?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is most logical to leave it here. Maybe we could simply adhere to the name of configureRelations and name it traverseAndConfigureRelations?


return;
}

// If we are in the composed gesture, we want to traverse its children.
node.gestures.forEach((child) => {
// If child is composed gesture, we have to correctly fill `waitFor` and `simultaneousHandlers`.
if (isComposedGesture(child)) {
// We have to update `simultaneousHandlers` before traversing the child (going top-down).
// Simultaneous is an all-to-all relation - it needs to be prepared when entering the node.
// Exclusive is a one-to-many relation - gesture depends on the preceding ones and not on itself - it should be prepared when leaving the node (bottom-up).

// If we go from a non-simultaneous gesture to a simultaneous gesture,
// we add the tags of the simultaneous gesture to the `simultaneousHandlers`.
// This way when we traverse the child, we already have the tags of the simultaneous gestures
if (
node.type !== ComposedGestureType.Simultaneous &&
child.type === ComposedGestureType.Simultaneous
) {
child.tags.forEach((tag) => simultaneousHandlers.add(tag));
}

// If we go from a simultaneous gesture to a non-simultaneous gesture,
// we remove the tags of the child gestures from the `simultaneousHandlers`,
// as those are not simultaneous with each other.
if (
node.type === ComposedGestureType.Simultaneous &&
child.type !== ComposedGestureType.Simultaneous
) {
child.tags.forEach((tag) => simultaneousHandlers.delete(tag));
}

// We will keep the current length of `waitFor` to reset it to previous state
// after traversing the child.
const length = waitFor.length;

// We traverse the child, passing the current `waitFor` and `simultaneousHandlers`.
traverseGestureRelations(child, simultaneousHandlers, waitFor);

// After traversing the child, we need to update `waitFor` and `simultaneousHandlers`

// If we go back from a simultaneous gesture to a non-simultaneous gesture,
// we want to delete the tags of the simultaneous gesture from the `simultaneousHandlers` -
// those gestures are not simultaneous with each other anymore.
if (
child.type === ComposedGestureType.Simultaneous &&
node.type !== ComposedGestureType.Simultaneous
) {
node.tags.forEach((tag) => simultaneousHandlers.delete(tag));
}

// If we go back from a non-simultaneous gesture to a simultaneous gesture,
// we want to add the tags of the simultaneous gesture to the `simultaneousHandlers`,
// as those gestures are simultaneous with other children of the current node.
if (
child.type !== ComposedGestureType.Simultaneous &&
node.type === ComposedGestureType.Simultaneous
) {
node.tags.forEach((tag) => simultaneousHandlers.add(tag));
}

// If we go back to an exclusive gesture, we want to add the tags of the child gesture to the `waitFor` array.
// This will allow us to pass exclusive gesture tags to the right subtree of the current node.
if (node.type === ComposedGestureType.Exclusive) {
child.tags.forEach((tag) => waitFor.push(tag));
}

// If we go back from an exclusive gesture to a non-exclusive gesture, we want to reset the `waitFor` array
// to the previous state, siblings of the exclusive gesture are not exclusive with it. Since we use `push` method to
// add tags to the `waitFor` array, we can override `length` property to reset it to the previous state.
if (
child.type === ComposedGestureType.Exclusive &&
node.type !== ComposedGestureType.Exclusive
) {
waitFor.length = length;
Copy link
Member

Choose a reason for hiding this comment

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

What is this sorcery?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It resets waitFor to previous state without having to use functions like splice 😅

}
}
// This means that child is a leaf node.
else {
// We don't want to mark gesture as simultaneous with itself, so we remove its tag from the set.
const hasRemovedTag = simultaneousHandlers.delete(child.tag);

traverseGestureRelations(child, simultaneousHandlers, waitFor);

if (hasRemovedTag) {
simultaneousHandlers.add(child.tag);
}

// In the leaf node, we only care about filling `waitFor` array.
if (node.type === ComposedGestureType.Exclusive) {
waitFor.push(child.tag);
}
}
});
};

export function configureRelations(gesture: Gesture) {
if (isComposedGesture(gesture)) {
traverseGestureRelations(
gesture,
new Set(
// If root is simultaneous, we want to add its tags to the set
gesture.type === ComposedGestureType.Simultaneous ? gesture.tags : []
)
);
} else {
const relations = prepareRelations(gesture.config, gesture.tag);

gesture.gestureRelations = relations;

RNGestureHandlerModule.configureRelations(gesture.tag, relations);
}
}
Loading
Loading