UNPKG

react-native-swipeable-up-down

Version:
145 lines (132 loc) 3.87 kB
import React, { Component } from 'react' import { View, Animated, TouchableWithoutFeedback, StatusBar, Dimensions } from 'react-native' import Interactable from 'react-native-interactable' import styles from './styles' // README: When you're using this components with new content, // you should create new component with View absolute and pointerEvents='box-none' const DEVICE_HEIGHT = Dimensions.get('screen').height const DEFAULT_MAX_HEIGHT = 5 + (StatusBar.currentHeight || 0) type Props = { snapPoints: Array, onStateChange: Function, initialPosition: Object, boundaries: Object, isList: Boolean, childrenRef: Function, // If you're using list in SwipeableBox, you need pass your Reference of List, extraHeight: Number // Should extra height is Navigation bar height (Header.HEIGHT - Header from react-naviagtion) } type State = { scrollEnabled: Boolean, boxVisible: Boolean } export default class SwipeableBox extends Component<Props, State> { static defaultProps = { snapPoints: [ { y: DEFAULT_MAX_HEIGHT }, { y: DEVICE_HEIGHT * 0.4 }, { y: DEVICE_HEIGHT } ], initialPosition: { y: DEVICE_HEIGHT }, boundaries: { top: DEFAULT_MAX_HEIGHT, bottom: DEVICE_HEIGHT }, isList: false, extraHeight: 0 } constructor(props) { super(props) this.state = { scrollEnabled: false, boxVisible: false, snapPoints: props.snapPoints, initialPosition: props.initialPosition, boundaries: props.boundaries } this._deltaY = new Animated.Value(0) this.MAX_HEIGHT = DEFAULT_MAX_HEIGHT + props.extraHeight } render() { const { boxVisible, snapPoints, initialPosition, boundaries } = this.state return ( <View style={styles.panelContainer} pointerEvents='box-none'> {boxVisible && ( <TouchableWithoutFeedback onPress={this.hide}> <Animated.View pointerEvents={boxVisible ? 'auto' : 'box-none'} style={[ styles.panelContainer, { backgroundColor: 'black', opacity: this._deltaY.interpolate({ inputRange: [0, snapPoints[snapPoints.length - 1].y], outputRange: [0.5, 0], extrapolateRight: 'clamp' }) } ]} /> </TouchableWithoutFeedback> )} <Interactable.View style={styles.panelContainer} ref='swipeable' verticalOnly snapPoints={snapPoints} boundaries={boundaries} initialPosition={initialPosition} onSnap={this._onSnap} dragEnabled={true} animatedValueY={this._deltaY} > <View style={{ height: DEVICE_HEIGHT - DEFAULT_MAX_HEIGHT }} > {this.props.children} </View> </Interactable.View> </View> ) } _onSnap = ({ nativeEvent }) => { const { isList, childrenRef } = this.props if (isList) { const scrollEnabled = nativeEvent.index === 0 childrenRef.setNativeProps({ scrollEnabled }) } const isOpened = nativeEvent.index !== this.state.snapPoints.length - 1 if (!isOpened) { this._toggleVisible(false) } this.props.onStateChange && this.props.onStateChange(isOpened) } _toggleVisible = val => { if (this.state.boxVisible === val) { return } this.setState({ boxVisible: val }) } show = () => { this.refs.swipeable.snapTo({ index: 1 }) this._toggleVisible(true) } hide = () => { this.refs.swipeable.snapTo({ index: this.state.snapPoints.length - 1 }) this._toggleVisible(false) } isVisble = () => this.state.boxVisible }