UNPKG

5.06 kBJavaScriptView Raw
1function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
3import * as React from 'react';
4import { Animated, Platform, StyleSheet, View, I18nManager } from 'react-native';
5import setColor from 'color';
6import { withTheme } from '../core/theming';
7const INDETERMINATE_DURATION = 2000;
8const INDETERMINATE_MAX_WIDTH = 0.6;
9const {
10 isRTL
11} = I18nManager;
12/**
13 * Progress bar is an indicator used to present progress of some activity in the app.
14 *
15 * <div class="screenshots">
16 * <img src="screenshots/progress-bar.png" />
17 * </div>
18 *
19 * ## Usage
20 * ```js
21 * import * as React from 'react';
22 * import { ProgressBar, Colors } from 'react-native-paper';
23 *
24 * const MyComponent = () => (
25 * <ProgressBar progress={0.5} color={Colors.red800} />
26 * );
27 *
28 * export default MyComponent;
29 * ```
30 */
31
32const ProgressBar = _ref => {
33 let {
34 color,
35 indeterminate,
36 style,
37 progress = 0,
38 visible = true,
39 theme,
40 ...rest
41 } = _ref;
42 const {
43 current: timer
44 } = React.useRef(new Animated.Value(0));
45 const {
46 current: fade
47 } = React.useRef(new Animated.Value(0));
48 const [width, setWidth] = React.useState(0);
49 const [prevWidth, setPrevWidth] = React.useState(0);
50 const indeterminateAnimation = React.useRef(null);
51 const {
52 scale
53 } = theme.animation;
54 const startAnimation = React.useCallback(() => {
55 // Show progress bar
56 Animated.timing(fade, {
57 duration: 200 * scale,
58 toValue: 1,
59 useNativeDriver: true,
60 isInteraction: false
61 }).start(); // Animate progress bar
62
63 if (indeterminate) {
64 if (!indeterminateAnimation.current) {
65 indeterminateAnimation.current = Animated.timing(timer, {
66 duration: INDETERMINATE_DURATION,
67 toValue: 1,
68 // Animated.loop does not work if useNativeDriver is true on web
69 useNativeDriver: Platform.OS !== 'web',
70 isInteraction: false
71 });
72 } // Reset timer to the beginning
73
74
75 timer.setValue(0);
76 Animated.loop(indeterminateAnimation.current).start();
77 } else {
78 Animated.timing(timer, {
79 duration: 200 * scale,
80 toValue: progress ? progress : 0,
81 useNativeDriver: true,
82 isInteraction: false
83 }).start();
84 }
85 }, [scale, timer, progress, indeterminate, fade]);
86 const stopAnimation = React.useCallback(() => {
87 // Stop indeterminate animation
88 if (indeterminateAnimation.current) {
89 indeterminateAnimation.current.stop();
90 }
91
92 Animated.timing(fade, {
93 duration: 200 * scale,
94 toValue: 0,
95 useNativeDriver: true,
96 isInteraction: false
97 }).start();
98 }, [fade, scale]);
99 React.useEffect(() => {
100 if (visible) startAnimation();else stopAnimation();
101 }, [visible, startAnimation, stopAnimation]);
102 React.useEffect(() => {
103 // Start animation the very first time when previously the width was unclear
104 if (visible && prevWidth === 0) {
105 startAnimation();
106 }
107 }, [prevWidth, startAnimation, visible]);
108
109 const onLayout = event => {
110 setPrevWidth(width);
111 setWidth(event.nativeEvent.layout.width);
112 };
113
114 const tintColor = color || theme.colors.primary;
115 const trackTintColor = setColor(tintColor).alpha(0.38).rgb().string();
116 return /*#__PURE__*/React.createElement(View, _extends({
117 onLayout: onLayout
118 }, rest, {
119 accessible: true,
120 accessibilityRole: "progressbar",
121 accessibilityState: {
122 busy: visible
123 },
124 accessibilityValue: indeterminate ? {} : {
125 min: 0,
126 max: 100,
127 now: progress * 100
128 }
129 }), /*#__PURE__*/React.createElement(Animated.View, {
130 style: [styles.container, {
131 backgroundColor: trackTintColor,
132 opacity: fade
133 }, style]
134 }, width ? /*#__PURE__*/React.createElement(Animated.View, {
135 style: [styles.progressBar, {
136 width,
137 backgroundColor: tintColor,
138 transform: [{
139 translateX: timer.interpolate(indeterminate ? {
140 inputRange: [0, 0.5, 1],
141 outputRange: [(isRTL ? 1 : -1) * 0.5 * width, (isRTL ? 1 : -1) * 0.5 * INDETERMINATE_MAX_WIDTH * width, (isRTL ? -1 : 1) * 0.7 * width]
142 } : {
143 inputRange: [0, 1],
144 outputRange: [(isRTL ? 1 : -1) * 0.5 * width, 0]
145 })
146 }, {
147 // Workaround for workaround for https://github.com/facebook/react-native/issues/6278
148 scaleX: timer.interpolate(indeterminate ? {
149 inputRange: [0, 0.5, 1],
150 outputRange: [0.0001, INDETERMINATE_MAX_WIDTH, 0.0001]
151 } : {
152 inputRange: [0, 1],
153 outputRange: [0.0001, 1]
154 })
155 }]
156 }]
157 }) : null));
158};
159
160const styles = StyleSheet.create({
161 container: {
162 height: 4,
163 overflow: 'hidden'
164 },
165 progressBar: {
166 flex: 1
167 }
168});
169export default withTheme(ProgressBar);
170//# sourceMappingURL=ProgressBar.js.map
\No newline at end of file