import React from 'react'; import { Animated, Dimensions, LayoutChangeEvent, StyleProp, View, ViewStyle } from 'react-native'; import { WithTheme, WithThemeStyles } from '../style'; import ProgressStyles, { ProgressStyle } from './style'; export interface ProgressProps extends WithThemeStyles { wrapWidth?: number; style?: StyleProp; barStyle?: StyleProp; percent?: number; position?: 'fixed' | 'normal'; unfilled?: boolean; appearTransition?: boolean; } export default class Progress extends React.Component { static defaultProps = { percent: 0, position: 'normal', unfilled: true, appearTransition: false, }; constructor(props: ProgressProps) { super(props); this.state = { wrapWidth: props.wrapWidth || Dimensions.get('window').width, percentage: new Animated.Value(0), }; } componentWillReceiveProps(nextProps: ProgressProps) { if (nextProps.wrapWidth !== this.props.wrapWidth) { this.setState({ wrapWidth: nextProps.wrapWidth }); } if ( this.props.appearTransition && nextProps.percent !== this.props.percent ) { this.setState({ percentage: new Animated.Value(this.getWidth(nextProps.percent)), }); } } componentDidMount() { if (this.props.appearTransition) { this.state.percentage.setValue(0); Animated.timing(this.state.percentage, { toValue: this.getWidth(), duration: 1000, useNativeDriver: true }).start(); } } onLayout = (e: LayoutChangeEvent) => { this.setState({ wrapWidth: e.nativeEvent.layout.width, }); }; normalPercent = (percent?: number) => { let widthPercent: any = 0; if (percent !== undefined && percent > 0) { widthPercent = percent > 100 ? 100 : percent; } return widthPercent; }; getWidth = (percent = this.props.percent) => { return this.state.wrapWidth * (this.normalPercent(percent) / 100); }; render() { const { position, unfilled, style, barStyle } = this.props; const percentStyle = { width: this.getWidth(), height: 0, }; return ( {styles => { let child = ( ); if (this.props.appearTransition) { percentStyle.width = this.state.percentage; child = ( ); } const outerStyle = [ styles.progressOuter, position === 'fixed' ? { position: 'absolute', top: 0 } : {}, !unfilled ? { backgroundColor: 'transparent' } : {}, style, ] as ViewStyle; return ( {child} ); }} ); } }