You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
7.6 KiB
206 lines
7.6 KiB
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
|
|
import _createClass from 'babel-runtime/helpers/createClass';
|
|
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
|
|
import _inherits from 'babel-runtime/helpers/inherits';
|
|
import React from 'react';
|
|
import { View, Modal, Animated, TouchableWithoutFeedback, StyleSheet, Dimensions, Easing } from 'react-native';
|
|
var styles = StyleSheet.create({
|
|
wrap: {
|
|
flex: 1,
|
|
backgroundColor: 'rgba(0,0,0,0)'
|
|
},
|
|
mask: {
|
|
backgroundColor: 'black',
|
|
opacity: .5
|
|
},
|
|
content: {
|
|
backgroundColor: 'white'
|
|
},
|
|
absolute: {
|
|
position: 'absolute',
|
|
top: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0
|
|
}
|
|
});
|
|
var screen = Dimensions.get('window');
|
|
|
|
var RCModal = function (_React$Component) {
|
|
_inherits(RCModal, _React$Component);
|
|
|
|
function RCModal(props) {
|
|
_classCallCheck(this, RCModal);
|
|
|
|
var _this = _possibleConstructorReturn(this, (RCModal.__proto__ || Object.getPrototypeOf(RCModal)).call(this, props));
|
|
|
|
_this.animateMask = function (visible) {
|
|
_this.stopMaskAnim();
|
|
_this.state.opacity.setValue(_this.getOpacity(!visible));
|
|
_this.animMask = Animated.timing(_this.state.opacity, {
|
|
toValue: _this.getOpacity(visible),
|
|
duration: _this.props.animationDuration
|
|
});
|
|
_this.animMask.start(function () {
|
|
_this.animMask = null;
|
|
});
|
|
};
|
|
_this.stopMaskAnim = function () {
|
|
if (_this.animMask) {
|
|
_this.animMask.stop();
|
|
_this.animMask = null;
|
|
}
|
|
};
|
|
_this.stopDialogAnim = function () {
|
|
if (_this.animDialog) {
|
|
_this.animDialog.stop();
|
|
_this.animDialog = null;
|
|
}
|
|
};
|
|
_this.animateDialog = function (visible) {
|
|
_this.stopDialogAnim();
|
|
_this.animateMask(visible);
|
|
var _this$props = _this.props,
|
|
animationType = _this$props.animationType,
|
|
animationDuration = _this$props.animationDuration;
|
|
|
|
animationDuration = animationDuration;
|
|
if (animationType !== 'none') {
|
|
if (animationType === 'slide-up' || animationType === 'slide-down') {
|
|
_this.state.position.setValue(_this.getPosition(!visible));
|
|
_this.animDialog = Animated.timing(_this.state.position, {
|
|
toValue: _this.getPosition(visible),
|
|
duration: animationDuration,
|
|
easing: visible ? Easing.elastic(0.8) : undefined
|
|
});
|
|
} else if (animationType === 'fade') {
|
|
_this.animDialog = Animated.parallel([Animated.timing(_this.state.opacity, {
|
|
toValue: _this.getOpacity(visible),
|
|
duration: animationDuration,
|
|
easing: visible ? Easing.elastic(0.8) : undefined
|
|
}), Animated.spring(_this.state.scale, {
|
|
toValue: _this.getScale(visible)
|
|
})]);
|
|
}
|
|
_this.animDialog.start(function () {
|
|
_this.animDialog = null;
|
|
if (!visible) {
|
|
_this.setState({
|
|
modalVisible: false
|
|
});
|
|
}
|
|
if (_this.props.onAnimationEnd) {
|
|
_this.props.onAnimationEnd(visible);
|
|
}
|
|
});
|
|
} else {
|
|
if (!visible) {
|
|
_this.setState({
|
|
modalVisible: false
|
|
});
|
|
}
|
|
}
|
|
};
|
|
_this.close = function () {
|
|
_this.animateDialog(false);
|
|
};
|
|
_this.onMaskClose = function () {
|
|
if (_this.props.maskClosable && _this.props.onClose) {
|
|
_this.props.onClose();
|
|
}
|
|
};
|
|
_this.getPosition = function (visible) {
|
|
if (visible) {
|
|
return 0;
|
|
}
|
|
return _this.props.animationType === 'slide-down' ? -screen.height : screen.height;
|
|
};
|
|
_this.getScale = function (visible) {
|
|
return visible ? 1 : 1.05;
|
|
};
|
|
_this.getOpacity = function (visible) {
|
|
return visible ? 1 : 0;
|
|
};
|
|
var visible = props.visible;
|
|
|
|
_this.state = {
|
|
position: new Animated.Value(_this.getPosition(visible)),
|
|
scale: new Animated.Value(_this.getScale(visible)),
|
|
opacity: new Animated.Value(_this.getOpacity(visible)),
|
|
modalVisible: visible
|
|
};
|
|
return _this;
|
|
}
|
|
|
|
_createClass(RCModal, [{
|
|
key: 'componentWillReceiveProps',
|
|
value: function componentWillReceiveProps(nextProps) {
|
|
if (this.shouldComponentUpdate(nextProps, null)) {
|
|
this.setState({
|
|
modalVisible: true
|
|
});
|
|
}
|
|
}
|
|
}, {
|
|
key: 'shouldComponentUpdate',
|
|
value: function shouldComponentUpdate(nextProps, nextState) {
|
|
if (this.props.visible || this.props.visible !== nextProps.visible) {
|
|
return true;
|
|
}
|
|
if (nextState) {
|
|
if (nextState.modalVisible !== this.state.modalVisible) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}, {
|
|
key: 'componentDidMount',
|
|
value: function componentDidMount() {
|
|
if (this.props.animateAppear && this.props.animationType !== 'none') {
|
|
this.componentDidUpdate({});
|
|
}
|
|
}
|
|
}, {
|
|
key: 'componentDidUpdate',
|
|
value: function componentDidUpdate(prevProps) {
|
|
var props = this.props;
|
|
|
|
if (prevProps.visible !== props.visible) {
|
|
this.animateDialog(props.visible);
|
|
}
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
var props = this.props;
|
|
|
|
if (!this.state.modalVisible) {
|
|
return null;
|
|
}
|
|
var animationStyleMap = {
|
|
none: {},
|
|
'slide-up': { transform: [{ translateY: this.state.position }] },
|
|
'slide-down': { transform: [{ translateY: this.state.position }] },
|
|
fade: { transform: [{ scale: this.state.scale }], opacity: this.state.opacity }
|
|
};
|
|
return React.createElement(Modal, { visible: true, transparent: true, onRequestClose: this.props.onClose, supportedOrientations: ['portrait', 'landscape'] }, React.createElement(View, { style: [styles.wrap, props.wrapStyle] }, React.createElement(TouchableWithoutFeedback, { onPress: this.onMaskClose }, React.createElement(Animated.View, { style: [styles.absolute, { opacity: this.state.opacity }] }, React.createElement(View, { style: [styles.absolute, props.maskStyle] }))), React.createElement(Animated.View, { style: [styles.content, props.style, animationStyleMap[props.animationType]] }, this.props.children)));
|
|
}
|
|
}]);
|
|
|
|
return RCModal;
|
|
}(React.Component);
|
|
|
|
export default RCModal;
|
|
|
|
RCModal.defaultProps = {
|
|
wrapStyle: styles.wrap,
|
|
maskStyle: styles.mask,
|
|
animationType: 'slide-up',
|
|
animateAppear: false,
|
|
animationDuration: 300,
|
|
visible: false,
|
|
maskClosable: true,
|
|
onClose: function onClose() {},
|
|
onAnimationEnd: function onAnimationEnd(_visible) {}
|
|
}; |