import { useEffect, useMemo, useRef } from 'react'; import { findNodeHandle } from 'react-native'; import type { NativeEventsManager } from '../../handlers/gestures/reanimatedWrapper'; import { Reanimated } from '../../handlers/gestures/reanimatedWrapper'; import HostGestureDetector, { type RNGestureHandlerDetectorNativeComponentProps, } from './HostGestureDetector'; let NativeEventsManagerImpl = Reanimated?.NativeEventsManager; if (!NativeEventsManagerImpl) { // When Reanimated.NativeEventsManager is undefined, it may be that an older // Reanimated version is used which doesn't export NativeEventsManager, or // Reanimated is not installed at all. For the older versions, try to import // NativeEventsManager by a subpath. Otherwise, it will stay undefined. try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment NativeEventsManagerImpl = // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access require('react-native-reanimated/src/createAnimatedComponent/NativeEventsManager').NativeEventsManager; } catch { // fail silently } } type WorkletProps = Pick< RNGestureHandlerDetectorNativeComponentProps, | 'onGestureHandlerReanimatedStateChange' | 'onGestureHandlerReanimatedEvent' | 'onGestureHandlerReanimatedTouchEvent' >; function LeanReanimatedNativeDetector( props: RNGestureHandlerDetectorNativeComponentProps ) { const prevProps = useRef(null); const eventManager = useRef | null>(null); const viewRef = useRef(null); const { onGestureHandlerReanimatedStateChange, onGestureHandlerReanimatedEvent, onGestureHandlerReanimatedTouchEvent, ...restProps } = props; const reaProps: WorkletProps = useMemo( () => ({ onGestureHandlerReanimatedStateChange, // @ts-ignore This is a type mismatch between RNGH types and RN Codegen types onGestureHandlerReanimatedEvent, // @ts-ignore This is a type mismatch between RNGH types and RN Codegen types onGestureHandlerReanimatedTouchEvent, }), [ onGestureHandlerReanimatedEvent, onGestureHandlerReanimatedStateChange, onGestureHandlerReanimatedTouchEvent, ] ); useEffect(() => { const nativeTag = findNodeHandle(viewRef.current) ?? -1; // @ts-expect-error Reanimated expects __nativeTag to be present on the ref viewRef.__nativeTag = nativeTag; // @ts-expect-error NativeEventsManager should be defined here, if it isn't, we should // go the fallback way and use Reanimated's createAnimatedComponent eventManager.current = new NativeEventsManagerImpl({ props: reaProps, _componentRef: viewRef, _componentViewTag: nativeTag, getComponentViewTag: () => nativeTag, }); eventManager.current.attachEvents(); return () => { eventManager.current?.detachEvents(); }; }, []); useEffect(() => { if (prevProps.current) { eventManager.current?.updateEvents(prevProps.current); } prevProps.current = reaProps; }, [reaProps]); return ; } export const ReanimatedNativeDetector = NativeEventsManagerImpl ? LeanReanimatedNativeDetector : Reanimated?.default.createAnimatedComponent(HostGestureDetector);