UNPKG

tuya-panel-kit

Version:

a functional component library for developing tuya device panels!

212 lines (195 loc) 4.44 kB
import React from 'react'; import PropTypes from 'prop-types'; import { Animated, Text, View, Image, StyleSheet, Easing, ViewPropTypes, Platform, } from 'react-native'; import { RatioUtils } from '../../utils'; const { winWidth } = RatioUtils; class ToastView extends React.PureComponent { static propTypes = { /** * toast样式 */ style: ViewPropTypes.style, /** * toast内容样式 */ contentStyle: ViewPropTypes.style, /** * toast文字样式 */ textStyle: Text.propTypes.style, /** * toast图标样式 */ imageStyle: Image.propTypes.style, /** * 提示文字 */ text: PropTypes.string, /** * 是否显示 */ show: PropTypes.bool.isRequired, /** * 即将消失的回调 */ onFinish: PropTypes.func.isRequired, /** * 显示位置 */ showPosition: PropTypes.oneOf(['top', 'bottom', 'center']), /** * 图标 */ image: PropTypes.number, /** * 嵌套子元素 */ children: PropTypes.any, }; static defaultProps = { style: null, contentStyle: null, textStyle: null, imageStyle: null, text: '', showPosition: 'bottom', image: null, children: null, }; constructor(props) { super(props); this._timerId = null; this.state = { fadeValue: new Animated.Value(0), text: props.text, show: props.show, }; } componentDidMount() { const { show, text } = this.props; if (typeof show !== 'undefined') { this.setState({ show, text }); if (show) { this.startShowAnimation(); } } } componentWillReceiveProps(nextProps) { const { show, text } = nextProps; if (typeof show !== 'undefined' && show !== this.state.show) { this.setState({ show, text }); if (show) { this.startShowAnimation(); } else { this.startHideAnimation(); } } } componentWillUnmount() { this._timerId && clearTimeout(this._timerId); } startShowAnimation = () => { this.state.fadeValue.setValue(0); Animated.timing(this.state.fadeValue, { toValue: 1, duration: 250, easing: Easing.linear, }).start(() => this.timer()); }; startHideAnimation = () => { this.state.fadeValue.setValue(1); Animated.timing(this.state.fadeValue, { toValue: 0, duration: 250, easing: Easing.linear, }).start(); }; timer = () => { clearTimeout(this._timerId); this._timerId = setTimeout(() => this.props.onFinish(), 1200); }; render() { const { style, contentStyle, textStyle, imageStyle, showPosition = 'bottom', image, children, } = this.props; const { text } = this.state; let position = { justifyContent: 'flex-end' }; if (showPosition === 'top') { position = { justifyContent: 'flex-start' }; } else if (showPosition === 'center') { position = { justifyContent: 'center' }; } const isValidElement = React.isValidElement(children); return ( <View style={[Platform.OS === 'web' && { width: winWidth }, styles.container, style, position]} pointerEvents="none" > <Animated.View style={[ styles.textBg, contentStyle, { opacity: this.state.fadeValue, }, ]} > {typeof image === 'number' && <Image style={[styles.image, imageStyle]} source={image} />} {isValidElement && children} {text ? ( <Text style={[styles.text, isValidElement && { marginTop: 12 }, textStyle]}> {text} </Text> ) : null} </Animated.View> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, position: 'absolute', bottom: 0, left: 0, right: 0, alignItems: 'center', top: 0, }, textBg: { alignItems: 'center', justifyContent: 'center', backgroundColor: `rgba(0, 0, 0, 0.7)`, borderRadius: 26, marginBottom: 64, marginHorizontal: 44, paddingHorizontal: 24, paddingVertical: 16, }, image: { marginBottom: 12, }, text: { fontSize: 14, lineHeight: 20, color: '#FFFFFF', textAlign: 'center', flexWrap: 'wrap', }, }); export default ToastView;