react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
75 lines (73 loc) • 3.03 kB
JavaScript
;
import { useCallback, useEffect, useRef, useState } from 'react';
import { findNodeHandle, Platform } from 'react-native';
import { Wrap } from '../../../handlers/gestures/GestureDetector/Wrap';
import { tagMessage } from '../../../utils';
import { isComposedGesture } from '../../hooks/utils/relationUtils';
import { useGestureRelationsUpdater } from '../useGestureRelationsUpdater';
import { useNativeGestureRole } from '../useNativeGestureRole';
import { InterceptingDetectorMode, useInterceptingDetectorContext } from './useInterceptingDetectorContext';
import { jsx as _jsx } from "react/jsx-runtime";
function useRequiredInterceptingDetectorContext() {
const context = useInterceptingDetectorContext();
if (!context) {
throw new Error(tagMessage('VirtualGestureDetector must be a descendant of an InterceptingGestureDetector'));
}
return context;
}
export function VirtualDetector(props) {
// Don't memoize virtual detectors to be able to listen to changes in children
// TODO: replace with MutationObserver when it rolls out in React Native
'use no memo';
const {
register,
unregister,
setMode
} = useRequiredInterceptingDetectorContext();
const viewRef = useRef(null);
const [viewTag, setViewTag] = useState(-1);
const handleRef = useCallback(node => {
viewRef.current = node;
if (node) {
const tag = Platform.OS === 'web' ? node : findNodeHandle(node);
setViewTag(tag ?? -1);
} else {
setViewTag(-1);
}
},
// Invalid dependency array to change the function when children change
// eslint-disable-next-line react-hooks/exhaustive-deps
[props.children]);
useNativeGestureRole(viewRef, props.children);
useEffect(() => {
if (viewTag === -1) {
return;
}
const handlerTags = isComposedGesture(props.gesture) ? props.gesture.handlerTags : [props.gesture.handlerTag];
if (props.gesture.config.dispatchesAnimatedEvents) {
throw new Error(tagMessage('VirtualGestureDetector cannot handle Animated events with native driver when used inside InterceptingGestureDetector. Use Reanimated or Animated events without native driver instead.'));
} else if (props.gesture.config.shouldUseReanimatedDetector) {
setMode(InterceptingDetectorMode.REANIMATED);
}
const virtualChild = {
viewTag,
handlerTags,
methods: props.gesture.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, props.userSelect, props.touchAction, props.enableContextMenu, register, unregister, setMode]);
useGestureRelationsUpdater(props.gesture);
return /*#__PURE__*/_jsx(Wrap, {
ref: handleRef,
children: props.children
});
}
//# sourceMappingURL=VirtualDetector.js.map