UNPKG

react-native-ui-lib

Version:

[![Build Status](https://travis-ci.org/wix/react-native-ui-lib.svg?branch=master)](https://travis-ci.org/wix/react-native-ui-lib) [![npm](https://img.shields.io/npm/v/react-native-ui-lib.svg)](https://www.npmjs.com/package/react-native-ui-lib) [![NPM Down

165 lines (151 loc) 4.87 kB
import _ from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; import {StyleSheet, TouchableWithoutFeedback, SafeAreaView} from 'react-native'; import * as Animatable from 'react-native-animatable'; import GestureRecognizer, {swipeDirections} from 'react-native-swipe-gestures'; import {BaseComponent} from '../../commons'; import {Colors} from '../../style'; import Modal from '../../screensComponents/modal'; import View from '../view'; import {Constants} from '../../helpers'; /*eslint-disable*/ /** * @description: Dialog component for displaying custom content inside a popup dialog * @notes: Use alignment modifiers to control the dialog positon (top, bottom, centerV, centerH, etc... by default the dialog is align to center) * @modifiers: alignment * @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/DialogScreen.js * @gif: https://media.giphy.com/media/9S58XdLCoUiLzAc1b1/giphy.gif */ /*eslint-enable*/ const SWIPE_DIRECTIONS = { UP: 'up', DOWN: 'down', }; class Dialog extends BaseComponent { static displayName = 'Dialog' static propTypes = { /** * Control visibility of the dialog */ visible: PropTypes.bool, /** * dismiss callback for when clicking on the background */ onDismiss: PropTypes.func, /** * the direction of the swipe to dismiss the dialog (default is 'down') */ dismissSwipeDirection: PropTypes.oneOf(Object.values(SWIPE_DIRECTIONS)), /** * The color of the overlay background */ overlayBackgroundColor: PropTypes.string, /** * The dialog width (default: 90%) */ width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** * The dialog height (default: 70%) */ height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), /** * the animation configuration to pass to the dialog (based on react-native-animatable, * ex. {animation, duration, easing,..}) */ animationConfig: PropTypes.object, /** * The dialog container style */ containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]), }; static defaultProps = { overlayBackgroundColor: Colors.rgba(Colors.dark10, 0.6), width: '90%', height: '70%', dismissSwipeDirection: SWIPE_DIRECTIONS.DOWN, }; static swipeDirections = SWIPE_DIRECTIONS; generateStyles() { this.styles = createStyles(this.props); } getAnimationConfig() { const {animationConfig} = this.props; return { animation: 'slideInUp', duration: 400, useNativeDriver: true, ...animationConfig, }; } onSwipe(gestureName) { const {SWIPE_UP, SWIPE_DOWN} = swipeDirections; const {dismissSwipeDirection} = this.props; switch (gestureName) { case SWIPE_UP: if (dismissSwipeDirection === SWIPE_DIRECTIONS.UP) { _.invoke(this.props, 'onDismiss'); } break; case SWIPE_DOWN: if (dismissSwipeDirection === SWIPE_DIRECTIONS.DOWN) { _.invoke(this.props, 'onDismiss'); } break; default: break; } } render() { const {visible, overlayBackgroundColor, style, onDismiss, bottom} = this.getThemeProps(); const {alignments} = this.state; const centerByDefault = _.isEmpty(alignments); const config = { velocityThreshold: 0.3, directionalOffsetThreshold: 80, }; const bottomInsets = Constants.getSafeAreaInsets().paddingBottom; return ( <Modal transparent visible={visible} animationType={'fade'} onBackgroundPress={onDismiss} onRequestClose={onDismiss} overlayBackgroundColor={overlayBackgroundColor} > <View center={centerByDefault} style={[this.styles.overlay, alignments]} pointerEvents="box-none"> <Animatable.View style={[this.styles.dialogContainer, style]} {...this.getAnimationConfig()}> <GestureRecognizer onSwipe={(direction, state) => this.onSwipe(direction, state)} config={config} style={this.styles.gestureContainer} > <TouchableWithoutFeedback> <SafeAreaView style={{flexGrow: 1}}> {this.props.children} {Constants.isIphoneX && bottom && <View style={{height: bottomInsets}}/>} </SafeAreaView> </TouchableWithoutFeedback> </GestureRecognizer> </Animatable.View> </View> </Modal> ); } } function createStyles({width, height}) { return StyleSheet.create({ overlay: { flex: 1, }, dialogContainer: { width, height, }, gestureContainer: { flexGrow: 1, }, }); } export default Dialog;