react-native-ui-lib
Version:
<p align="center"> <img src="https://user-images.githubusercontent.com/1780255/105469025-56759000-5ca0-11eb-993d-3568c1fd54f4.png" height="250px" style="display:block"/> </p> <p align="center">UI Toolset & Components Library for React Native</p> <p a
194 lines (175 loc) • 4.93 kB
JavaScript
import _pt from "prop-types";
import isUndefined from 'lodash/isUndefined';
import React, { PureComponent } from 'react';
import { Animated, Easing, StyleSheet } from 'react-native';
import { Constants, asBaseComponent } from "../../commons/new";
import { extractAccessibilityProps } from "../../commons/modifiers";
import View from "../view";
import { Colors, BorderRadiuses, Spacings } from "../../style";
const CONTAINER_HEIGHT = Spacings.s2;
const FULL_WIDTH_CONTAINER_HEIGHT = Spacings.s1;
const TABLET_CONTAINER_HEIGHT = 6;
const TABLET_FULL_WIDTH_CONTAINER_HEIGHT = 10;
const DEFAULT_COLOR = Colors.primary;
/**
* @description: Progress bar
* @example:https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/ProgressBarScreen.js
*/
class ProgressBar extends PureComponent {
static propTypes = {
/**
* The progress of the bar from 0 to 100
*/
progress: _pt.number,
/**
* FullWidth Ui preset
*/
fullWidth: _pt.bool,
/**
* Progress color
*/
progressColor: _pt.string,
/**
* Custom element to render on top of the animated progress
*/
customElement: _pt.element,
testID: _pt.string
};
static displayName = 'ProgressBar';
static defaultProps = {
progress: 0
};
constructor(props) {
super(props);
this.progressAnimation = new Animated.Value(props.progress || 0);
this.state = {
containerWidth: undefined
};
}
componentDidUpdate(prevProps) {
const {
progress
} = this.props;
if (prevProps.progress !== progress) {
this.animateProgress(progress);
}
}
getContainerWidth = event => {
if (!this.state.containerWidth) {
this.setState({
containerWidth: event.nativeEvent.layout.width
});
}
};
animateProgress(toValue) {
if (!isUndefined(toValue)) {
Animated.timing(this.progressAnimation, {
duration: 220,
easing: Easing.ease,
toValue,
useNativeDriver: true
}).start();
}
}
getAccessibilityProps() {
const {
progress
} = this.props;
if (progress) {
return {
accessible: true,
accessibilityLabel: `progress bar. ${Math.round(progress)}%`,
...extractAccessibilityProps()
};
}
}
getContainerStyle() {
const {
fullWidth
} = this.props;
const containerHeight = fullWidth ? FULL_WIDTH_CONTAINER_HEIGHT : CONTAINER_HEIGHT;
const tabletContainerHeight = fullWidth ? TABLET_FULL_WIDTH_CONTAINER_HEIGHT : TABLET_CONTAINER_HEIGHT;
const inlineStyle = fullWidth ? null : styles.inlineContainer;
return { ...inlineStyle,
height: Constants.isTablet ? tabletContainerHeight : containerHeight
};
}
getProgressStyle() {
const {
fullWidth,
progressColor
} = this.props;
const borderRadius = fullWidth ? styles.fullWidthProgressBorderRadius : styles.inlineBorderRadius;
const progressStyle = {
right: Constants.isRTL ? undefined : this.state.containerWidth,
backgroundColor: progressColor || DEFAULT_COLOR
};
return { ...borderRadius,
...progressStyle
};
}
renderCustomElement() {
const {
customElement
} = this.props;
if (customElement) {
return React.cloneElement(customElement, {
style: [customElement.props.style, styles.customElement]
});
}
}
render() {
const {
style,
testID
} = this.props;
const {
containerWidth = 0
} = this.state;
const outputRange = Constants.isRTL ? [containerWidth, 0] : [0, containerWidth];
const newProgress = this.progressAnimation.interpolate({
inputRange: [0, 100],
outputRange
});
return <View onLayout={this.getContainerWidth} style={[styles.container, this.getContainerStyle(), style]} {...this.getAccessibilityProps()} testID={testID}>
{!!containerWidth && <Animated.View style={[styles.progress, this.getProgressStyle(), {
transform: [{
translateX: newProgress
}]
}]}>
{this.renderCustomElement()}
</Animated.View>}
</View>;
}
}
export { ProgressBar }; // For tests
export default asBaseComponent(ProgressBar);
const styles = StyleSheet.create({
container: {
backgroundColor: Colors.grey60,
overflow: 'hidden',
borderRadius: BorderRadiuses.br100
},
inlineContainer: {
borderRadius: BorderRadiuses.br100
},
progress: {
position: 'absolute',
height: '100%',
width: '100%',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden'
},
customElement: {
height: '100%',
width: '100%'
},
inlineBorderRadius: {
borderRadius: BorderRadiuses.br100
},
fullWidthProgressBorderRadius: {
borderBottomRightRadius: BorderRadiuses.br100,
borderTopRightRadius: BorderRadiuses.br100
}
});