[add] ProgressBar component

Ref #91
This commit is contained in:
Nicolas Gallagher
2016-09-01 16:49:39 -07:00
parent 977d8729f5
commit 0aef117733
5 changed files with 260 additions and 0 deletions
@@ -0,0 +1,20 @@
/* eslint-env mocha */
import assert from 'assert';
import React from 'react';
import { shallow } from 'enzyme';
import ProgressBar from '..';
suite('components/ProgressBar', () => {
suite('progress', () => {
test('value as percentage is set to "aria-valuenow"', () => {
const component = shallow(<ProgressBar progress={0.5} />);
assert(component.prop('aria-valuenow') === 50);
});
test('is ignored when "indeterminate" is "true"', () => {
const component = shallow(<ProgressBar indeterminate progress={0.5} />);
assert(component.prop('aria-valuenow') === null);
});
});
});
+119
View File
@@ -0,0 +1,119 @@
import Animated from '../../apis/Animated';
import applyNativeMethods from '../../modules/applyNativeMethods';
import ColorPropType from '../../propTypes/ColorPropType';
import StyleSheet from '../../apis/StyleSheet';
import View from '../View';
import React, { Component, PropTypes } from 'react';
const indeterminateWidth = '25%';
const translateInterpolation = { inputRange: [ 0, 1 ], outputRange: [ '-100%', '400%' ] };
class ProgressBar extends Component {
static propTypes = {
...View.propTypes,
color: ColorPropType,
indeterminate: PropTypes.bool,
progress: PropTypes.number,
trackColor: ColorPropType
};
static defaultProps = {
color: '#1976D2',
indeterminate: false,
progress: 0,
trackColor: 'transparent'
};
constructor(props) {
super(props);
this.state = {
animationScale: new Animated.Value(0),
animationTranslate: new Animated.Value(0)
};
}
componentDidMount() {
this._manageAnimation();
}
componentDidUpdate() {
this._manageAnimation();
}
render() {
const {
color,
indeterminate,
progress,
trackColor,
style,
...other
} = this.props;
const { animationTranslate } = this.state;
const percentageProgress = indeterminate ? 50 : progress * 100;
return (
<View {...other}
accessibilityRole='progressbar'
aria-valuemax='100'
aria-valuemin='0'
aria-valuenow={indeterminate ? null : percentageProgress}
style={[
styles.track,
style,
{ backgroundColor: trackColor }
]}
>
<Animated.View style={[
styles.progress,
{ backgroundColor: color },
indeterminate ? {
transform: [
{ translateX: animationTranslate.interpolate(translateInterpolation) }
],
width: indeterminateWidth
} : {
width: `${percentageProgress}%`
}
]} />
</View>
);
}
_manageAnimation() {
const { animationTranslate } = this.state;
const cycleAnimation = (animation) => {
animation.setValue(0);
Animated.timing(animation, {
duration: 1000,
toValue: 1
}).start((event) => {
if (event.finished) {
cycleAnimation(animation);
}
});
};
if (this.props.indeterminate) {
cycleAnimation(animationTranslate);
} else {
animationTranslate.stopAnimation();
}
}
}
const styles = StyleSheet.create({
track: {
height: 5,
overflow: 'hidden',
userSelect: 'none'
},
progress: {
height: '100%'
}
});
module.exports = applyNativeMethods(ProgressBar);
+2
View File
@@ -25,6 +25,7 @@ import Vibration from './apis/Vibration';
import ActivityIndicator from './components/ActivityIndicator';
import Image from './components/Image';
import ListView from './components/ListView';
import ProgressBar from './components/ProgressBar';
import ScrollView from './components/ScrollView';
import Switch from './components/Switch';
import Text from './components/Text';
@@ -75,6 +76,7 @@ const ReactNative = {
ActivityIndicator,
Image,
ListView,
ProgressBar,
ScrollView,
Switch,
Text,