UNPKG

react-native-animated-modal-old

Version:

A simple React-Native animated modal

129 lines (116 loc) 3.94 kB
/* eslint-disable no-return-assign, no-unused-vars */ import React, { Component } from 'react' import PropTypes from 'prop-types' import { Dimensions, Modal } from 'react-native' import { View } from 'react-native-animatable' import styles from './index.style.js' export class AnimatedModal extends Component { static propTypes = { animationIn: PropTypes.string, animationInTiming: PropTypes.number, animationOut: PropTypes.string, animationOutTiming: PropTypes.number, backdropColor: PropTypes.string, backdropOpacity: PropTypes.number, backdropTransitionInTiming: PropTypes.number, backdropTransitionOutTiming: PropTypes.number, children: PropTypes.node.isRequired, isVisible: PropTypes.bool.isRequired, onModalShow: PropTypes.func, onModalHide: PropTypes.func, hideOnBack: PropTypes.bool, style: PropTypes.any } static defaultProps = { animationIn: 'slideInUp', animationInTiming: 300, animationOut: 'slideOutDown', animationOutTiming: 300, backdropColor: 'black', backdropOpacity: 0.70, backdropTransitionInTiming: 300, backdropTransitionOutTiming: 300, onModalShow: () => null, onModalHide: () => null, isVisible: false, hideOnBack: true, } state = { isVisible: false, deviceWidth: Dimensions.get('window').width, deviceHeight: Dimensions.get('window').height } componentWillReceiveProps (nextProps) { if (!this.state.isVisible && nextProps.isVisible) { this.setState({ isVisible: true }) } } componentDidUpdate (prevProps, prevState) { // On modal open request slide the view up and fade in the backdrop if (this.state.isVisible && !prevState.isVisible) { this._open() // On modal close request slide the view down and fade out the backdrop } else if (!this.props.isVisible && prevProps.isVisible) { this._close() } } _open = () => { this.backdropRef.transitionTo({ opacity: this.props.backdropOpacity }, this.props.backdropTransitionInTiming) this.contentRef[this.props.animationIn](this.props.animationInTiming) .then(() => { this.props.onModalShow() }) } _close = async () => { this.backdropRef.transitionTo({ opacity: 0 }, this.props.backdropTransitionOutTiming) this.contentRef[this.props.animationOut](this.props.animationOutTiming) .then(() => { this.setState({ isVisible: false }) this.props.onModalHide() }) } _closeOnBack = () => { if (this.props.hideOnBack) { this._close(); } } _handleLayout = (event) => { const deviceWidth = Dimensions.get('window').width const deviceHeight = Dimensions.get('window').height if (deviceWidth !== this.state.deviceWidth || deviceHeight !== this.state.deviceHeight) { this.setState({ deviceWidth, deviceHeight }) } } render () { const { animationIn, animationInTiming, animationOut, animationOutTiming, backdropColor, backdropOpacity, backdropTransitionInTiming, backdropTransitionOutTiming, children, isVisible, onModalShow, onModalHide, style, ...otherProps } = this.props const { deviceWidth, deviceHeight } = this.state return ( <Modal transparent={true} animationType={'none'} visible={this.state.isVisible} onRequestClose={this._closeOnBack} {...otherProps} > <View onLayout={this._handleLayout} ref={(ref) => this.backdropRef = ref} style={[ styles.backdrop, { backgroundColor: backdropColor, width: deviceWidth, height: deviceHeight } ]} /> <View ref={(ref) => this.contentRef = ref} style={[{ margin: deviceWidth * 0.05 }, styles.content, style]} {...otherProps} > {children} </View> </Modal> ) } } export default AnimatedModal