1
- import React from 'react' ;
1
+ import React , { cloneElement } from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
+ import classNames from 'classnames' ;
4
+ import { map } from 'react-bootstrap/ElementChildren' ;
3
5
import { omit } from 'ramda' ;
4
- import RBProgressBar from 'react-bootstrap/ProgressBar' ;
6
+
5
7
import { bootstrapColors } from '../../private/BootstrapColors' ;
6
8
7
- /**
8
- * A component for creating progress bars just with CSS. Control the current
9
- * progress with a callback and the `value` prop.
9
+ /*
10
+ * Bulk of this file is vendored from react-bootstrap/src/ProgressBar, but we
11
+ * add the ability to style the bar which is needed for setting colors more
12
+ * freely.
10
13
*/
14
+ const ROUND_PRECISION = 1000 ;
15
+
16
+ function getPercentage ( now , min , max ) {
17
+ const percentage = ( ( now - min ) / ( max - min ) ) * 100 ;
18
+ return Math . round ( percentage * ROUND_PRECISION ) / ROUND_PRECISION ;
19
+ }
20
+
21
+ function renderProgressBar (
22
+ {
23
+ min,
24
+ now,
25
+ max,
26
+ label,
27
+ visuallyHidden,
28
+ striped,
29
+ animated,
30
+ className,
31
+ style,
32
+ variant,
33
+ barStyle,
34
+ ...props
35
+ } ,
36
+ ref
37
+ ) {
38
+ return (
39
+ < div
40
+ ref = { ref }
41
+ { ...props }
42
+ role = "progressbar"
43
+ className = { classNames ( className , `progress-bar` , {
44
+ [ `bg-${ variant } ` ] : variant ,
45
+ [ `progress-bar-animated` ] : animated ,
46
+ [ `progress-bar-striped` ] : animated || striped
47
+ } ) }
48
+ style = { { width : `${ getPercentage ( now , min , max ) } %` , ...style , ...barStyle } }
49
+ aria-valuenow = { now }
50
+ aria-valuemin = { min }
51
+ aria-valuemax = { max }
52
+ >
53
+ { visuallyHidden ? (
54
+ < span className = "visually-hidden" > { label } </ span >
55
+ ) : (
56
+ label
57
+ ) }
58
+ </ div >
59
+ ) ;
60
+ }
61
+
62
+ const ProgressBar = React . forwardRef ( ( { isChild, ...props } , ref ) => {
63
+ if ( isChild ) {
64
+ return renderProgressBar ( props , ref ) ;
65
+ }
66
+
67
+ const {
68
+ min,
69
+ now,
70
+ max,
71
+ label,
72
+ visuallyHidden,
73
+ striped,
74
+ animated,
75
+ variant,
76
+ className,
77
+ children,
78
+ barStyle,
79
+ ...wrapperProps
80
+ } = props ;
81
+
82
+ return (
83
+ < div
84
+ ref = { ref }
85
+ { ...wrapperProps }
86
+ className = { classNames ( className , 'progress' ) }
87
+ >
88
+ { children
89
+ ? map ( children , child => cloneElement ( child , { isChild : true } ) )
90
+ : renderProgressBar (
91
+ {
92
+ min,
93
+ now,
94
+ max,
95
+ label,
96
+ visuallyHidden,
97
+ striped,
98
+ animated,
99
+ variant,
100
+ barStyle
101
+ } ,
102
+ ref
103
+ ) }
104
+ </ div >
105
+ ) ;
106
+ } ) ;
107
+
108
+ ProgressBar . defaultProps = {
109
+ min : 0 ,
110
+ max : 100 ,
111
+ animated : false ,
112
+ isChild : false ,
113
+ visuallyHidden : false ,
114
+ striped : false
115
+ } ;
116
+
11
117
const Progress = props => {
12
118
const {
13
119
children,
@@ -22,7 +128,7 @@ const Progress = props => {
22
128
} = props ;
23
129
const isBootstrapColor = bootstrapColors . has ( color ) ;
24
130
return (
25
- < RBProgressBar
131
+ < ProgressBar
26
132
className = { class_name || className }
27
133
{ ...omit ( [ 'setProps' ] , otherProps ) }
28
134
data-dash-is-loading = {
@@ -32,9 +138,10 @@ const Progress = props => {
32
138
isChild = { bar }
33
139
variant = { isBootstrapColor ? color : null }
34
140
visuallyHidden = { hide_label }
141
+ barStyle = { isBootstrapColor ? { } : { backgroundColor : color } }
35
142
>
36
143
{ children }
37
- </ RBProgressBar >
144
+ </ ProgressBar >
38
145
) ;
39
146
} ;
40
147
0 commit comments