text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.getIsModalPresentation = exports.default = void 0;
  
  var _color = _interopRequireDefault(require("color"));
  
  var React = _interopRequireWildcard(require("react"));
  
  var _reactNative = require("react-native");
  
  var _CardStyleInterpolators = require("../../TransitionConfigs/CardStyleInterpolators");
  
  var _CardAnimationContext = _interopRequireDefault(require("../../utils/CardAnimationContext"));
  
  var _getDistanceForDirection = _interopRequireDefault(require("../../utils/getDistanceForDirection"));
  
  var _getInvertedMultiplier = _interopRequireDefault(require("../../utils/getInvertedMultiplier"));
  
  var _memoize = _interopRequireDefault(require("../../utils/memoize"));
  
  var _GestureHandler = require("../GestureHandler");
  
  var _ModalStatusBarManager = _interopRequireDefault(require("../ModalStatusBarManager"));
  
  var _CardSheet = _interopRequireDefault(require("./CardSheet"));
  
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  const GESTURE_VELOCITY_IMPACT = 0.3;
  const TRUE = 1;
  const FALSE = 0;
  /**
   * The distance of touch start from the edge of the screen where the gesture will be recognized
   */
  
  const GESTURE_RESPONSE_DISTANCE_HORIZONTAL = 50;
  const GESTURE_RESPONSE_DISTANCE_VERTICAL = 135;
  const useNativeDriver = _reactNative.Platform.OS !== 'web';
  
  const hasOpacityStyle = style => {
    if (style) {
      const flattenedStyle = _reactNative.StyleSheet.flatten(style);
  
      return flattenedStyle.opacity != null;
    }
  
    return false;
  };
  
  class Card extends React.Component {
    constructor() {
      super(...arguments);
  
      _defineProperty(this, "isCurrentlyMounted", false);
  
      _defineProperty(this, "isClosing", new _reactNative.Animated.Value(FALSE));
  
      _defineProperty(this, "inverted", new _reactNative.Animated.Value((0, _getInvertedMultiplier.default)(this.props.gestureDirection)));
  
      _defineProperty(this, "layout", {
        width: new _reactNative.Animated.Value(this.props.layout.width),
        height: new _reactNative.Animated.Value(this.props.layout.height)
      });
  
      _defineProperty(this, "isSwiping", new _reactNative.Animated.Value(FALSE));
  
      _defineProperty(this, "interactionHandle", void 0);
  
      _defineProperty(this, "pendingGestureCallback", void 0);
  
      _defineProperty(this, "lastToValue", void 0);
  
      _defineProperty(this, "animate", _ref => {
        let {
          closing,
          velocity
        } = _ref;
        const {
          gesture,
          transitionSpec,
          onOpen,
          onClose,
          onTransition
        } = this.props;
        const toValue = this.getAnimateToValue({ ...this.props,
          closing
        });
        this.lastToValue = toValue;
        this.isClosing.setValue(closing ? TRUE : FALSE);
        const spec = closing ? transitionSpec.close : transitionSpec.open;
        const animation = spec.animation === 'spring' ? _reactNative.Animated.spring : _reactNative.Animated.timing;
        this.setPointerEventsEnabled(!closing);
        this.handleStartInteraction();
        clearTimeout(this.pendingGestureCallback);
        onTransition === null || onTransition === void 0 ? void 0 : onTransition({
          closing,
          gesture: velocity !== undefined
        });
        animation(gesture, { ...spec.config,
          velocity,
          toValue,
          useNativeDriver,
          isInteraction: false
        }).start(_ref2 => {
          let {
            finished
          } = _ref2;
          this.handleEndInteraction();
          clearTimeout(this.pendingGestureCallback);
  
          if (finished) {
            if (closing) {
              onClose();
            } else {
              onOpen();
            }
  
            if (this.isCurrentlyMounted) {
              // Make sure to re-open screen if it wasn't removed
              this.forceUpdate();
            }
          }
        });
      });
  
      _defineProperty(this, "getAnimateToValue", _ref3 => {
        let {
          closing,
          layout,
          gestureDirection
        } = _ref3;
  
        if (!closing) {
          return 0;
        }
  
        return (0, _getDistanceForDirection.default)(layout, gestureDirection);
      });
  
      _defineProperty(this, "setPointerEventsEnabled", enabled => {
        var _this$contentRef$curr;
  
        const pointerEvents = enabled ? 'box-none' : 'none';
        (_this$contentRef$curr = this.contentRef.current) === null || _this$contentRef$curr === void 0 ? void 0 : _this$contentRef$curr.setNativeProps({
          pointerEvents
        });
      });
  
      _defineProperty(this, "handleStartInteraction", () => {
        if (this.interactionHandle === undefined) {
          this.interactionHandle = _reactNative.InteractionManager.createInteractionHandle();
        }
      });
  
      _defineProperty(this, "handleEndInteraction", () => {
        if (this.interactionHandle !== undefined) {
          _reactNative.InteractionManager.clearInteractionHandle(this.interactionHandle);
  
          this.interactionHandle = undefined;
        }
      });
  
      _defineProperty(this, "handleGestureStateChange", _ref4 => {
        let {
          nativeEvent
        } = _ref4;
        const {
          layout,
          onClose,
          onGestureBegin,
          onGestureCanceled,
          onGestureEnd,
          gestureDirection,
          gestureVelocityImpact
        } = this.props;
  
        switch (nativeEvent.state) {
          case _GestureHandler.GestureState.ACTIVE:
            this.isSwiping.setValue(TRUE);
            this.handleStartInteraction();
            onGestureBegin === null || onGestureBegin === void 0 ? void 0 : onGestureBegin();
            break;
  
          case _GestureHandler.GestureState.CANCELLED:
            {
              this.isSwiping.setValue(FALSE);
              this.handleEndInteraction();
              const velocity = gestureDirection === 'vertical' || gestureDirection === 'vertical-inverted' ? nativeEvent.velocityY : nativeEvent.velocityX;
              this.animate({
                closing: this.props.closing,
                velocity
              });
              onGestureCanceled === null || onGestureCanceled === void 0 ? void 0 : onGestureCanceled();
              break;
            }
  
          case _GestureHandler.GestureState.END:
            {
              this.isSwiping.setValue(FALSE);
              let distance;
              let translation;
              let velocity;
  
              if (gestureDirection === 'vertical' || gestureDirection === 'vertical-inverted') {
                distance = layout.height;
                translation = nativeEvent.translationY;
                velocity = nativeEvent.velocityY;
              } else {
                distance = layout.width;
                translation = nativeEvent.translationX;
                velocity = nativeEvent.velocityX;
              }
  
              const closing = (translation + velocity * gestureVelocityImpact) * (0, _getInvertedMultiplier.default)(gestureDirection) > distance / 2 ? velocity !== 0 || translation !== 0 : this.props.closing;
              this.animate({
                closing,
                velocity
              });
  
              if (closing) {
                // We call onClose with a delay to make sure that the animation has already started
                // This will make sure that the state update caused by this doesn't affect start of animation
                this.pendingGestureCallback = setTimeout(() => {
                  onClose(); // Trigger an update after we dispatch the action to remove the screen
                  // This will make sure that we check if the screen didn't get removed so we can cancel the animation
  
                  this.forceUpdate();
                }, 32);
              }
  
              onGestureEnd === null || onGestureEnd === void 0 ? void 0 : onGestureEnd();
              break;
            }
        }
      });
  
      _defineProperty(this, "getInterpolatedStyle", (0, _memoize.default)((styleInterpolator, animation) => styleInterpolator(animation)));
  
      _defineProperty(this, "getCardAnimation", (0, _memoize.default)((interpolationIndex, current, next, layout, insetTop, insetRight, insetBottom, insetLeft) => ({
        index: interpolationIndex,
        current: {
          progress: current
        },
        next: next && {
          progress: next
        },
        closing: this.isClosing,
        swiping: this.isSwiping,
        inverted: this.inverted,
        layouts: {
          screen: layout
        },
        insets: {
          top: insetTop,
          right: insetRight,
          bottom: insetBottom,
          left: insetLeft
        }
      })));
  
      _defineProperty(this, "contentRef", /*#__PURE__*/React.createRef());
    }
  
    componentDidMount() {
      this.animate({
        closing: this.props.closing
      });
      this.isCurrentlyMounted = true;
    }
  
    componentDidUpdate(prevProps) {
      const {
        layout,
        gestureDirection,
        closing
      } = this.props;
      const {
        width,
        height
      } = layout;
  
      if (width !== prevProps.layout.width) {
        this.layout.width.setValue(width);
      }
  
      if (height !== prevProps.layout.height) {
        this.layout.height.setValue(height);
      }
  
      if (gestureDirection !== prevProps.gestureDirection) {
        this.inverted.setValue((0, _getInvertedMultiplier.default)(gestureDirection));
      }
  
      const toValue = this.getAnimateToValue(this.props);
  
      if (this.getAnimateToValue(prevProps) !== toValue || this.lastToValue !== toValue) {
        // We need to trigger the animation when route was closed
        // Thr route might have been closed by a `POP` action or by a gesture
        // When route was closed due to a gesture, the animation would've happened already
        // It's still important to trigger the animation so that `onClose` is called
        // If `onClose` is not called, cleanup step won't be performed for gestures
        this.animate({
          closing
        });
      }
    }
  
    componentWillUnmount() {
      this.props.gesture.stopAnimation();
      this.isCurrentlyMounted = false;
      this.handleEndInteraction();
    }
  
    gestureActivationCriteria() {
      const {
        layout,
        gestureDirection,
        gestureResponseDistance
      } = this.props;
      const enableTrackpadTwoFingerGesture = true;
      const distance = gestureResponseDistance !== undefined ? gestureResponseDistance : gestureDirection === 'vertical' || gestureDirection === 'vertical-inverted' ? GESTURE_RESPONSE_DISTANCE_VERTICAL : GESTURE_RESPONSE_DISTANCE_HORIZONTAL;
  
      if (gestureDirection === 'vertical') {
        return {
          maxDeltaX: 15,
          minOffsetY: 5,
          hitSlop: {
            bottom: -layout.height + distance
          },
          enableTrackpadTwoFingerGesture
        };
      } else if (gestureDirection === 'vertical-inverted') {
        return {
          maxDeltaX: 15,
          minOffsetY: -5,
          hitSlop: {
            top: -layout.height + distance
          },
          enableTrackpadTwoFingerGesture
        };
      } else {
        const hitSlop = -layout.width + distance;
        const invertedMultiplier = (0, _getInvertedMultiplier.default)(gestureDirection);
  
        if (invertedMultiplier === 1) {
          return {
            minOffsetX: 5,
            maxDeltaY: 20,
            hitSlop: {
              right: hitSlop
            },
            enableTrackpadTwoFingerGesture
          };
        } else {
          return {
            minOffsetX: -5,
            maxDeltaY: 20,
            hitSlop: {
              left: hitSlop
            },
            enableTrackpadTwoFingerGesture
          };
        }
      }
    }
  
    render() {
      const {
        styleInterpolator,
        interpolationIndex,
        current,
        gesture,
        next,
        layout,
        insets,
        overlay,
        overlayEnabled,
        shadowEnabled,
        gestureEnabled,
        gestureDirection,
        pageOverflowEnabled,
        headerDarkContent,
        children,
        containerStyle: customContainerStyle,
        contentStyle,
        ...rest
      } = this.props;
      const interpolationProps = this.getCardAnimation(interpolationIndex, current, next, layout, insets.top, insets.right, insets.bottom, insets.left);
      const interpolatedStyle = this.getInterpolatedStyle(styleInterpolator, interpolationProps);
      const {
        containerStyle,
        cardStyle,
        overlayStyle,
        shadowStyle
      } = interpolatedStyle;
      const handleGestureEvent = gestureEnabled ? _reactNative.Animated.event([{
        nativeEvent: gestureDirection === 'vertical' || gestureDirection === 'vertical-inverted' ? {
          translationY: gesture
        } : {
          translationX: gesture
        }
      }], {
        useNativeDriver
      }) : undefined;
  
      const {
        backgroundColor
      } = _reactNative.StyleSheet.flatten(contentStyle || {});
  
      const isTransparent = typeof backgroundColor === 'string' ? (0, _color.default)(backgroundColor).alpha() === 0 : false;
      return /*#__PURE__*/React.createElement(_CardAnimationContext.default.Provider, {
        value: interpolationProps
      }, // StatusBar messes with translucent status bar on Android
      // So we should only enable it on iOS
      _reactNative.Platform.OS === 'ios' && overlayEnabled && next && getIsModalPresentation(styleInterpolator) ? /*#__PURE__*/React.createElement(_ModalStatusBarManager.default, {
        dark: headerDarkContent,
        layout: layout,
        insets: insets,
        style: cardStyle
      }) : null, /*#__PURE__*/React.createElement(_reactNative.Animated.View, {
        style: {
          // This is a dummy style that doesn't actually change anything visually.
          // Animated needs the animated value to be used somewhere, otherwise things don't update properly.
          // If we disable animations and hide header, it could end up making the value unused.
          // So we have this dummy style that will always be used regardless of what else changed.
          opacity: current
        } // Make sure that this view isn't removed. If this view is removed, our style with animated value won't apply
        ,
        collapsable: false
      }), /*#__PURE__*/React.createElement(_reactNative.View, _extends({
        pointerEvents: "box-none"
      }, rest), overlayEnabled ? /*#__PURE__*/React.createElement(_reactNative.View, {
        pointerEvents: "box-none",
        style: _reactNative.StyleSheet.absoluteFill
      }, overlay({
        style: overlayStyle
      })) : null, /*#__PURE__*/React.createElement(_reactNative.Animated.View, {
        style: [styles.container, containerStyle, customContainerStyle],
        pointerEvents: "box-none"
      }, /*#__PURE__*/React.createElement(_GestureHandler.PanGestureHandler, _extends({
        enabled: layout.width !== 0 && gestureEnabled,
        onGestureEvent: handleGestureEvent,
        onHandlerStateChange: this.handleGestureStateChange
      }, this.gestureActivationCriteria()), /*#__PURE__*/React.createElement(_reactNative.Animated.View, {
        needsOffscreenAlphaCompositing: hasOpacityStyle(cardStyle),
        style: [styles.container, cardStyle]
      }, shadowEnabled && shadowStyle && !isTransparent ? /*#__PURE__*/React.createElement(_reactNative.Animated.View, {
        style: [styles.shadow, gestureDirection === 'horizontal' ? [styles.shadowHorizontal, styles.shadowLeft] : gestureDirection === 'horizontal-inverted' ? [styles.shadowHorizontal, styles.shadowRight] : gestureDirection === 'vertical' ? [styles.shadowVertical, styles.shadowTop] : [styles.shadowVertical, styles.shadowBottom], {
          backgroundColor
        }, shadowStyle],
        pointerEvents: "none"
      }) : null, /*#__PURE__*/React.createElement(_CardSheet.default, {
        ref: this.contentRef,
        enabled: pageOverflowEnabled,
        layout: layout,
        style: contentStyle
      }, children))))));
    }
  
  }
  
  exports.default = Card;
  
  _defineProperty(Card, "defaultProps", {
    shadowEnabled: false,
    gestureEnabled: true,
    gestureVelocityImpact: GESTURE_VELOCITY_IMPACT,
    overlay: _ref5 => {
      let {
        style
      } = _ref5;
      return style ? /*#__PURE__*/React.createElement(_reactNative.Animated.View, {
        pointerEvents: "none",
        style: [styles.overlay, style]
      }) : null;
    }
  });
  
  const getIsModalPresentation = cardStyleInterpolator => {
    return cardStyleInterpolator === _CardStyleInterpolators.forModalPresentationIOS || // Handle custom modal presentation interpolators as well
    cardStyleInterpolator.name === 'forModalPresentationIOS';
  };
  
  exports.getIsModalPresentation = getIsModalPresentation;
  
  const styles = _reactNative.StyleSheet.create({
    container: {
      flex: 1
    },
    overlay: {
      flex: 1,
      backgroundColor: '#000'
    },
    shadow: {
      position: 'absolute',
      shadowRadius: 5,
      shadowColor: '#000',
      shadowOpacity: 0.3
    },
    shadowHorizontal: {
      top: 0,
      bottom: 0,
      width: 3,
      shadowOffset: {
        width: -1,
        height: 1
      }
    },
    shadowLeft: {
      left: 0
    },
    shadowRight: {
      right: 0
    },
    shadowVertical: {
      left: 0,
      right: 0,
      height: 3,
      shadowOffset: {
        width: 1,
        height: -1
      }
    },
    shadowTop: {
      top: 0
    },
    shadowBottom: {
      bottom: 0
    }
  });
  //# sourceMappingURL=Card.js.map