react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
94 lines (82 loc) • 2.6 kB
text/typescript
import { Reanimated } from '../../../handlers/gestures/reanimatedWrapper';
import { tagMessage } from '../../../utils';
import type {
AnyGesture,
ComposedGesture,
ComposedGestureConfig,
ComposedGestureName,
GestureHandlerEventWithHandlerData,
} from '../../types';
import { containsDuplicates, isComposedGesture } from '../utils';
// TODO: Simplify repeated relations (Simultaneous with Simultaneous, Exclusive with Exclusive, etc.)
export function useComposedGesture(
type: ComposedGestureName,
...gestures: AnyGesture[]
): ComposedGesture {
const handlerTags = gestures.flatMap((gesture) =>
isComposedGesture(gesture) ? gesture.handlerTags : [gesture.handlerTag]
);
if (containsDuplicates(handlerTags)) {
throw new Error(
tagMessage(
'Each gesture can be used only once in the gesture composition.'
)
);
}
const config: ComposedGestureConfig = {
shouldUseReanimatedDetector: gestures.some(
(gesture) => gesture.config.shouldUseReanimatedDetector
),
dispatchesAnimatedEvents: gestures.some(
(gesture) => gesture.config.dispatchesAnimatedEvents
),
};
if (config.shouldUseReanimatedDetector && config.dispatchesAnimatedEvents) {
throw new Error(
tagMessage(
'Composed gestures cannot use both Reanimated and Animated events at the same time.'
)
);
}
const jsEventHandler = (
event: GestureHandlerEventWithHandlerData<unknown, unknown>
) => {
for (const gesture of gestures) {
if (gesture.detectorCallbacks.jsEventHandler) {
gesture.detectorCallbacks.jsEventHandler(event);
}
}
};
const reanimatedEventHandler = Reanimated?.useComposedEventHandler(
gestures.map(
(gesture) => gesture.detectorCallbacks.reanimatedEventHandler || null
)
);
let animatedEventHandler;
const gesturesWithAnimatedEvent = gestures.filter(
(gesture) => gesture.detectorCallbacks.animatedEventHandler !== undefined
);
if (gesturesWithAnimatedEvent.length > 0) {
animatedEventHandler =
gesturesWithAnimatedEvent[0].detectorCallbacks.animatedEventHandler;
if (__DEV__ && gesturesWithAnimatedEvent.length > 1) {
console.warn(
tagMessage(
'Composed gesture can handle only one Animated event. The first one will be used, others will be ignored.'
)
);
}
}
return {
handlerTags,
type,
config,
detectorCallbacks: {
jsEventHandler,
reanimatedEventHandler,
animatedEventHandler,
},
externalSimultaneousHandlers: [],
gestures,
};
}