UNPKG

react-native-swipe-up-panel

Version:
394 lines (350 loc) 12.3 kB
import { createElement, Component } from 'react'; import { StyleSheet, View, TouchableOpacity, Dimensions, Animated, TouchableWithoutFeedback, PanResponder } from 'react-native'; 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 _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } var Bar = function Bar(_ref) { var barStyle = _ref.barStyle; return /*#__PURE__*/createElement(View, { style: BarStyles.barContainer }, /*#__PURE__*/createElement(View, { style: [BarStyles.bar, barStyle] })); }; var BarStyles = StyleSheet.create({ barContainer: { display: 'flex', justifyContent: 'center', alignItems: 'center' }, bar: { width: '10%', height: 5, borderRadius: 5, marginTop: 10, marginBottom: 10, backgroundColor: '#e2e2e2' } }); var Close = function Close(_ref) { var onPress = _ref.onPress, rootStyle = _ref.rootStyle, iconStyle = _ref.iconStyle; return /*#__PURE__*/createElement(TouchableOpacity, { activeOpacity: 0.5, onPress: onPress, style: [CloseStyles.closeButton, rootStyle] }, /*#__PURE__*/createElement(View, { style: [CloseStyles.iconLine, iconStyle, { transform: [{ rotateZ: '45deg' }] }] }), /*#__PURE__*/createElement(View, { style: [CloseStyles.iconLine, iconStyle, { transform: [{ rotateZ: '135deg' }] }] })); }; var CloseStyles = StyleSheet.create({ closeButton: { width: 30, height: 30, borderRadius: 15, position: 'absolute', right: 15, top: 15, backgroundColor: '#e2e2e2', zIndex: 3, display: 'flex', justifyContent: 'center', alignItems: 'center' }, iconLine: { position: 'absolute', width: 18, height: 2, borderRadius: 2, backgroundColor: 'white' } }); var FULL_HEIGHT = Dimensions.get('window').height; var FULL_WIDTH = Dimensions.get('window').width; var PANEL_HEIGHT = FULL_HEIGHT - 100; var STATUS; (function (STATUS) { STATUS[STATUS["CLOSED"] = 0] = "CLOSED"; STATUS[STATUS["SMALL"] = 1] = "SMALL"; STATUS[STATUS["LARGE"] = 2] = "LARGE"; })(STATUS || (STATUS = {})); var SwipeablePanel = /*#__PURE__*/function (_React$Component) { _inheritsLoose(SwipeablePanel, _React$Component); function SwipeablePanel(props) { var _this; _this = _React$Component.call(this, props) || this; _this.SMALL_PANEL_CONTENT_HEIGHT = PANEL_HEIGHT - (FULL_HEIGHT - 400) - 25; _this.LARGE_PANEL_CONTENT_HEIGHT = PANEL_HEIGHT - 25; _this.componentDidMount = function () { var _this$props = _this.props, isActive = _this$props.isActive, openLarge = _this$props.openLarge, onlyLarge = _this$props.onlyLarge, onlySmall = _this$props.onlySmall; _this.animatedValueY = 0; _this.state.pan.y.addListener(function (value) { return _this.animatedValueY = value.value; }); _this.setState({ isActive: isActive }); if (isActive) _this._animateTo(onlySmall ? STATUS.SMALL : openLarge ? STATUS.LARGE : onlyLarge ? STATUS.LARGE : STATUS.SMALL); Dimensions.addEventListener('change', _this._onOrientationChange); }; _this._onOrientationChange = function () { var dimesions = Dimensions.get('screen'); FULL_HEIGHT = dimesions.height; FULL_WIDTH = dimesions.width; PANEL_HEIGHT = FULL_HEIGHT - 100; _this.setState({ orientation: dimesions.height >= dimesions.width ? 'portrait' : 'landscape', deviceWidth: FULL_WIDTH, deviceHeight: FULL_HEIGHT, panelHeight: PANEL_HEIGHT }); if (_this.props.onClose) _this.props.onClose(); }; _this._animateTo = function (newStatus) { if (newStatus === void 0) { newStatus = 0; } var newY = 0; if (_this.props.canClose && newStatus === STATUS.CLOSED) { newY = PANEL_HEIGHT; } else if (newStatus === STATUS.SMALL) { newY = _this.props.smallPanelHeight ? FULL_HEIGHT - _this.props.smallPanelHeight : _this.state.orientation === 'portrait' ? FULL_HEIGHT - 400 : FULL_HEIGHT / 3; } else if (newStatus === STATUS.LARGE) { newY = _this.props.largePanelHeight ? FULL_HEIGHT - _this.props.largePanelHeight : 0; } _this.setState({ showComponent: true, status: newStatus, currentHeight: PANEL_HEIGHT - newY }); Animated.spring(_this.state.pan, { toValue: { x: 0, y: newY }, tension: 40, friction: 25, useNativeDriver: true, restDisplacementThreshold: 10, restSpeedThreshold: 10 }).start(function () { var _this$props$onChangeS, _this$props2; (_this$props$onChangeS = (_this$props2 = _this.props).onChangeStatus) === null || _this$props$onChangeS === void 0 ? void 0 : _this$props$onChangeS.call(_this$props2, newStatus); if (newStatus === 0) { if (_this.props.onClose) _this.props.onClose(); _this.setState({ showComponent: false }); } else { _this.setState({ canScroll: newStatus === STATUS.LARGE }); } }); }; _this.state = { status: STATUS.CLOSED, isActive: false, showComponent: false, canScroll: false, opacity: new Animated.Value(0), pan: new Animated.ValueXY({ x: 0, y: FULL_HEIGHT }), orientation: FULL_HEIGHT >= FULL_WIDTH ? 'portrait' : 'landscape', deviceWidth: FULL_WIDTH, deviceHeight: FULL_HEIGHT, panelHeight: PANEL_HEIGHT, currentHeight: _this.props.smallPanelHeight ? FULL_HEIGHT - _this.props.smallPanelHeight : _this.state.orientation === 'portrait' ? FULL_HEIGHT - 400 : FULL_HEIGHT / 3 }; _this.pan = new Animated.ValueXY({ x: 0, y: FULL_HEIGHT }); _this.isClosing = false; _this.animatedValueY = 0; _this._panResponder = PanResponder.create({ onStartShouldSetPanResponder: function onStartShouldSetPanResponder() { return true; }, onPanResponderGrant: function onPanResponderGrant() { _this.state.pan.setOffset({ x: 0, y: _this.animatedValueY }); _this.state.pan.setValue({ x: 0, y: 0 }); }, onPanResponderMove: function onPanResponderMove(evt, gestureState) { if (_this.state.status === STATUS.SMALL && Math.abs(_this.state.pan.y._value) <= _this.state.pan.y._offset || _this.state.status === STATUS.LARGE && _this.state.pan.y._value > -1) _this.state.pan.setValue({ x: 0, y: _this.state.status === STATUS.LARGE ? Math.max(0, gestureState.dy) : gestureState.dy }); }, onPanResponderRelease: function onPanResponderRelease(evt, gestureState) { var _this$props3 = _this.props, onlyLarge = _this$props3.onlyLarge, onlySmall = _this$props3.onlySmall; _this.state.pan.flattenOffset(); if (gestureState.dy === 0) { _this._animateTo(_this.state.status); } else if (gestureState.dy < -100 || gestureState.vy < -0.5) { if (_this.state.status === STATUS.SMALL) _this._animateTo(onlySmall ? STATUS.SMALL : STATUS.LARGE);else _this._animateTo(STATUS.LARGE); } else if (gestureState.dy > 100 || gestureState.vy > 0.5) { if (_this.state.status === STATUS.LARGE) _this._animateTo(onlyLarge && _this.props.canClose ? STATUS.CLOSED : STATUS.SMALL);else _this._animateTo(_this.state.status); } else { _this._animateTo(_this.state.status); } } }); return _this; } var _proto = SwipeablePanel.prototype; _proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) { var _this$props4 = this.props, isActive = _this$props4.isActive, openLarge = _this$props4.openLarge, onlyLarge = _this$props4.onlyLarge, onlySmall = _this$props4.onlySmall; if (onlyLarge && onlySmall) console.warn('Ops. You are using both onlyLarge and onlySmall options. onlySmall will override the onlyLarge in this situation. Please select one of them or none.'); if (prevProps.isActive !== isActive) { this.setState({ isActive: isActive }); if (isActive) { this._animateTo(onlySmall ? STATUS.SMALL : openLarge ? STATUS.LARGE : onlyLarge ? STATUS.LARGE : STATUS.SMALL); } else { this._animateTo(); } } if (prevState.orientation !== this.state.orientation) this._animateTo(this.state.status); }; _proto.render = function render() { var _this$state = this.state, showComponent = _this$state.showComponent, deviceWidth = _this$state.deviceWidth, deviceHeight = _this$state.deviceHeight, panelHeight = _this$state.panelHeight, currentHeight = _this$state.currentHeight; var _this$props5 = this.props, noBackgroundOpacity = _this$props5.noBackgroundOpacity, style = _this$props5.style, barStyle = _this$props5.barStyle, closeRootStyle = _this$props5.closeRootStyle, closeIconStyle = _this$props5.closeIconStyle, onClose = _this$props5.onClose, allowTouchOutside = _this$props5.allowTouchOutside, closeOnTouchOutside = _this$props5.closeOnTouchOutside; return showComponent ? /*#__PURE__*/createElement(Animated.View, { style: [SwipeablePanelStyles.background, { backgroundColor: noBackgroundOpacity ? 'rgba(0,0,0,0)' : 'rgba(0,0,0,0.5)', height: allowTouchOutside ? currentHeight : deviceHeight, width: deviceWidth }] }, closeOnTouchOutside && /*#__PURE__*/createElement(TouchableWithoutFeedback, { onPress: onClose }, /*#__PURE__*/createElement(View, { style: [SwipeablePanelStyles.background, { width: deviceWidth, backgroundColor: 'rgba(0,0,0,0)', height: allowTouchOutside ? currentHeight : deviceHeight }] })), /*#__PURE__*/createElement(Animated.View, _extends({ style: [SwipeablePanelStyles.panel, { width: this.props.fullWidth ? deviceWidth : deviceWidth - 50, height: panelHeight }, { transform: this.state.pan.getTranslateTransform() }, style] }, this._panResponder.panHandlers), !this.props.noBar && /*#__PURE__*/createElement(Bar, { barStyle: barStyle }), this.props.showCloseButton && /*#__PURE__*/createElement(Close, { rootStyle: closeRootStyle, iconStyle: closeIconStyle, onPress: this.props.onClose }), this.props.children)) : null; }; return SwipeablePanel; }(Component); var SwipeablePanelStyles = StyleSheet.create({ background: { position: 'absolute', zIndex: 1, bottom: 0, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.5)' }, panel: { position: 'absolute', height: PANEL_HEIGHT, width: FULL_WIDTH - 50, transform: [{ translateY: FULL_HEIGHT - 100 }], display: 'flex', flexDirection: 'column', backgroundColor: 'white', bottom: 0, borderTopLeftRadius: 20, borderTopRightRadius: 20, borderBottomLeftRadius: 0, borderBottomRightRadius: 0, overflow: 'hidden', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.18, shadowRadius: 1.0, elevation: 1, zIndex: 2 }, scrollViewContentContainerStyle: { width: '100%' } }); export { SwipeablePanel }; //# sourceMappingURL=index.modern.js.map