text: import React, { Component } from 'react';
  import { PanResponder, StyleSheet, View } from 'react-native';
  
  export const swipeDirections = {
    SWIPE_UP: 'SWIPE_UP',
    SWIPE_DOWN: 'SWIPE_DOWN',
    SWIPE_LEFT: 'SWIPE_LEFT',
    SWIPE_RIGHT: 'SWIPE_RIGHT',
  };
  
  const swipeConfig = {
    velocityThreshold: 0.3,
    directionalOffsetThreshold: 80,
  };
  
  function isValidSwipe(
    velocity,
    velocityThreshold,
    directionalOffset,
    directionalOffsetThreshold,
  ) {
    return (
      Math.abs(velocity) > velocityThreshold &&
      Math.abs(directionalOffset) < directionalOffsetThreshold
    );
  }
  
  class GestureView extends Component {
    constructor(props, context) {
      super(props, context);
      this.swipeConfig = Object.assign(swipeConfig, props.config);
      this._panResponder = PanResponder.create({
        onResponderGrant: props.onResponderGrant,
        onStartShouldSetPanResponder: this._handleShouldSetPanResponder,
        onMoveShouldSetPanResponder: this._handleShouldSetPanResponder,
        onPanResponderRelease: this._handlePanResponderEnd,
        onPanResponderTerminate: this._handlePanResponderEnd,
      });
    }
  
    componentWillReceiveProps(props) {
      this.swipeConfig = Object.assign(swipeConfig, props.config);
    }
  
    _handleShouldSetPanResponder = (evt, gestureState) => {
      evt.preventDefault();
      return evt.nativeEvent.touches.length === 1;
    };
  
    _gestureIsClick = gestureState => {
      return Math.abs(gestureState.dx) < 5 && Math.abs(gestureState.dy) < 5;
    };
  
    _handlePanResponderEnd = (evt, gestureState) => {
      evt.preventDefault();
      const swipeDirection = this._getSwipeDirection(gestureState);
      this._triggerSwipeHandlers(swipeDirection, gestureState);
    };
  
    _triggerSwipeHandlers = (swipeDirection, gestureState) => {
      const {
        onSwipe,
        onSwipeUp,
        onSwipeDown,
        onSwipeLeft,
        onSwipeRight,
        onTap,
      } = this.props;
      const { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_UP, SWIPE_DOWN } = swipeDirections;
      onSwipe && onSwipe(swipeDirection, gestureState);
      switch (swipeDirection) {
        case SWIPE_LEFT:
          onSwipeLeft && onSwipeLeft(gestureState);
          break;
        case SWIPE_RIGHT:
          onSwipeRight && onSwipeRight(gestureState);
          break;
        case SWIPE_UP:
          onSwipeUp && onSwipeUp(gestureState);
          break;
        case SWIPE_DOWN:
          onSwipeDown && onSwipeDown(gestureState);
          break;
        default:
          onTap && onTap(gestureState);
          break;
      }
    };
  
    _getSwipeDirection = gestureState => {
      const { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_UP, SWIPE_DOWN } = swipeDirections;
      const { dx, dy } = gestureState;
      if (this._isValidHorizontalSwipe(gestureState)) {
        return dx > 0 ? SWIPE_RIGHT : SWIPE_LEFT;
      } else if (this._isValidVerticalSwipe(gestureState)) {
        return dy > 0 ? SWIPE_DOWN : SWIPE_UP;
      }
      return null;
    };
  
    _isValidHorizontalSwipe = gestureState => {
      const { vx, dy } = gestureState;
      const { velocityThreshold, directionalOffsetThreshold } = this.swipeConfig;
      return isValidSwipe(vx, velocityThreshold, dy, directionalOffsetThreshold);
    };
  
    _isValidVerticalSwipe = gestureState => {
      const { vy, dx } = gestureState;
      const { velocityThreshold, directionalOffsetThreshold } = this.swipeConfig;
      return isValidSwipe(vy, velocityThreshold, dx, directionalOffsetThreshold);
    };
  
    render() {
      const { style = {}, ...props } = this.props;
  
      return (
        <View
          style={StyleSheet.flatten([{ flex: 1 }, style])}
          {...props}
          {...this._panResponder.panHandlers}
        />
      );
    }
  }
  
  export default GestureView;
  