UNPKG

react-native-gesture-handler

Version:

Declarative API exposing native platform touch and gesture system to React Native

148 lines (116 loc) 6.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GestureDetector = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _findNodeHandle = _interopRequireDefault(require("../../../findNodeHandle")); var _utils = require("../../../utils"); var _GestureHandlerRootViewContext = _interopRequireDefault(require("../../../GestureHandlerRootViewContext")); var _useAnimatedGesture = require("./useAnimatedGesture"); var _attachHandlers = require("./attachHandlers"); var _needsToReattach = require("./needsToReattach"); var _dropHandlers = require("./dropHandlers"); var _utils2 = require("./utils"); var _Wrap = require("./Wrap"); var _useDetectorUpdater = require("./useDetectorUpdater"); var _useViewRefHandler = require("./useViewRefHandler"); var _useMountReactions = require("./useMountReactions"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* eslint-disable react/no-unused-prop-types */ function propagateDetectorConfig(props, gesture) { const keysToPropagate = ['userSelect', 'enableContextMenu', 'touchAction']; for (const key of keysToPropagate) { const value = props[key]; if (value === undefined) { continue; } for (const g of gesture.toGestureArray()) { const config = g.config; config[key] = value; } } } /** * `GestureDetector` is responsible for creating and updating native gesture handlers based on the config of provided gesture. * * ### Props * - `gesture` * - `userSelect` (**Web only**) * - `enableContextMenu` (**Web only**) * - `touchAction` (**Web only**) * * ### Remarks * - Gesture Detector will use first native view in its subtree to recognize gestures, however if this view is used only to group its children it may get automatically collapsed. * - Using the same instance of a gesture across multiple Gesture Detectors is not possible. * * @see https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture-detector */ const GestureDetector = props => { const rootViewContext = (0, _react.useContext)(_GestureHandlerRootViewContext.default); if (__DEV__ && !rootViewContext && !(0, _utils.isJestEnv)() && _reactNative.Platform.OS !== 'web') { throw new Error('GestureDetector must be used as a descendant of GestureHandlerRootView. Otherwise the gestures will not be recognized. See https://docs.swmansion.com/react-native-gesture-handler/docs/installation for more details.'); } // Gesture config should be wrapped with useMemo to prevent unnecessary re-renders const gestureConfig = props.gesture; propagateDetectorConfig(props, gestureConfig); const gesturesToAttach = (0, _react.useMemo)(() => gestureConfig.toGestureArray(), [gestureConfig]); const shouldUseReanimated = gesturesToAttach.some(g => g.shouldUseReanimated); const webEventHandlersRef = (0, _utils2.useWebEventHandlers)(); // Store state in ref to prevent unnecessary renders const state = (0, _react.useRef)({ firstRender: true, viewRef: null, previousViewTag: -1, forceRebuildReanimatedEvent: false }).current; const preparedGesture = _react.default.useRef({ attachedGestures: [], animatedEventHandler: null, animatedHandlers: null, shouldUseReanimated: shouldUseReanimated, isMounted: false }).current; const updateAttachedGestures = (0, _useDetectorUpdater.useDetectorUpdater)(state, preparedGesture, gesturesToAttach, gestureConfig, webEventHandlersRef); const refHandler = (0, _useViewRefHandler.useViewRefHandler)(state, updateAttachedGestures); // Reanimated event should be rebuilt only when gestures are reattached, otherwise // config update will be enough as all necessary items are stored in shared values anyway const needsToRebuildReanimatedEvent = state.firstRender || state.forceRebuildReanimatedEvent || (0, _needsToReattach.needsToReattach)(preparedGesture, gesturesToAttach); state.forceRebuildReanimatedEvent = false; (0, _useAnimatedGesture.useAnimatedGesture)(preparedGesture, needsToRebuildReanimatedEvent); (0, _react.useLayoutEffect)(() => { const viewTag = (0, _findNodeHandle.default)(state.viewRef); preparedGesture.isMounted = true; (0, _attachHandlers.attachHandlers)({ preparedGesture, gestureConfig, gesturesToAttach, webEventHandlersRef, viewTag }); return () => { preparedGesture.isMounted = false; (0, _dropHandlers.dropHandlers)(preparedGesture); }; }, []); (0, _react.useEffect)(() => { if (state.firstRender) { state.firstRender = false; } else { updateAttachedGestures(); } }, [props]); (0, _useMountReactions.useMountReactions)(updateAttachedGestures, preparedGesture); if (shouldUseReanimated) { return /*#__PURE__*/_react.default.createElement(_Wrap.AnimatedWrap, { ref: refHandler, onGestureHandlerEvent: preparedGesture.animatedEventHandler }, props.children); } else { return /*#__PURE__*/_react.default.createElement(_Wrap.Wrap, { ref: refHandler }, props.children); } }; exports.GestureDetector = GestureDetector; //# sourceMappingURL=index.js.map