Skip to content

Commit d434239

Browse files
committed
Merge pull request react-bootstrap#794 from AlexKVal/progressBar
ProgressBar. Assert that chilren can be ProgressBar only.
2 parents 5e4ff2f + 551f0a0 commit d434239

2 files changed

Lines changed: 80 additions & 54 deletions

File tree

src/ProgressBar.js

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import React, { cloneElement } from 'react';
1+
/* eslint react/prop-types: [1, {ignore: ["className", "bsStyle"]}]*/
2+
/* BootstrapMixin contains `bsStyle` type validation */
3+
4+
import React, { cloneElement, PropTypes } from 'react';
25
import Interpolate from './Interpolate';
36
import BootstrapMixin from './BootstrapMixin';
47
import classNames from 'classnames';
@@ -7,13 +10,16 @@ import ValidComponentChildren from './utils/ValidComponentChildren';
710

811
const ProgressBar = React.createClass({
912
propTypes: {
10-
min: React.PropTypes.number,
11-
now: React.PropTypes.number,
12-
max: React.PropTypes.number,
13-
label: React.PropTypes.node,
14-
srOnly: React.PropTypes.bool,
15-
striped: React.PropTypes.bool,
16-
active: React.PropTypes.bool
13+
min: PropTypes.number,
14+
now: PropTypes.number,
15+
max: PropTypes.number,
16+
label: PropTypes.node,
17+
srOnly: PropTypes.bool,
18+
striped: PropTypes.bool,
19+
active: PropTypes.bool,
20+
children: onlyProgressBar,
21+
interpolateClass: PropTypes.node,
22+
isChild: PropTypes.bool
1723
},
1824

1925
mixins: [BootstrapMixin],
@@ -27,41 +33,34 @@ const ProgressBar = React.createClass({
2733
},
2834

2935
getPercentage(now, min, max) {
30-
let roundPrecision = 1000;
36+
const roundPrecision = 1000;
3137
return Math.round(((now - min) / (max - min) * 100) * roundPrecision) / roundPrecision;
3238
},
3339

3440
render() {
35-
let classes = {
36-
progress: true
37-
};
38-
39-
if (this.props.active) {
40-
classes['progress-striped'] = true;
41-
classes.active = true;
42-
} else if (this.props.striped) {
43-
classes['progress-striped'] = true;
41+
if (this.props.isChild) {
42+
return this.renderProgressBar();
4443
}
4544

46-
if (!ValidComponentChildren.hasValidComponent(this.props.children)) {
47-
if (!this.props.isChild) {
48-
return (
49-
<div {...this.props} className={classNames(this.props.className, classes)}>
50-
{this.renderProgressBar()}
51-
</div>
52-
);
53-
} else {
54-
return (
55-
this.renderProgressBar()
56-
);
57-
}
45+
const classes = {
46+
active: this.props.active,
47+
progress: true,
48+
'progress-striped': this.props.active || this.props.striped
49+
};
50+
51+
let content;
52+
53+
if (this.props.children) {
54+
content = ValidComponentChildren.map(this.props.children, this.renderChildBar);
5855
} else {
59-
return (
60-
<div {...this.props} className={classNames(this.props.className, classes)}>
61-
{ValidComponentChildren.map(this.props.children, this.renderChildBar)}
62-
</div>
63-
);
56+
content = this.renderProgressBar();
6457
}
58+
59+
return (
60+
<div {...this.props} className={classNames(this.props.className, classes)}>
61+
{content}
62+
</div>
63+
);
6564
},
6665

6766
renderChildBar(child, index) {
@@ -72,28 +71,33 @@ const ProgressBar = React.createClass({
7271
},
7372

7473
renderProgressBar() {
75-
let percentage = this.getPercentage(
76-
this.props.now,
77-
this.props.min,
78-
this.props.max
79-
);
74+
const percentage = this.getPercentage(
75+
this.props.now,
76+
this.props.min,
77+
this.props.max
78+
);
8079

8180
let label;
8281

8382
if (typeof this.props.label === 'string') {
8483
label = this.renderLabel(percentage);
85-
} else if (this.props.label) {
84+
} else {
8685
label = this.props.label;
8786
}
8887

8988
if (this.props.srOnly) {
90-
label = this.renderScreenReaderOnlyLabel(label);
89+
label = (
90+
<span className="sr-only">
91+
{label}
92+
</span>
93+
);
9194
}
9295

93-
let classes = this.getBsClassSet();
94-
9596
return (
96-
<div {...this.props} className={classNames(this.props.className, classes)} role="progressbar"
97+
<div
98+
{...this.props}
99+
className={classNames(this.props.className, this.getBsClassSet())}
100+
role="progressbar"
97101
style={{width: percentage + '%'}}
98102
aria-valuenow={this.props.now}
99103
aria-valuemin={this.props.min}
@@ -104,7 +108,7 @@ const ProgressBar = React.createClass({
104108
},
105109

106110
renderLabel(percentage) {
107-
let InterpolateClass = this.props.interpolateClass || Interpolate;
111+
const InterpolateClass = this.props.interpolateClass || Interpolate;
108112

109113
return (
110114
<InterpolateClass
@@ -116,15 +120,25 @@ const ProgressBar = React.createClass({
116120
{this.props.label}
117121
</InterpolateClass>
118122
);
119-
},
120-
121-
renderScreenReaderOnlyLabel(label) {
122-
return (
123-
<span className="sr-only">
124-
{label}
125-
</span>
126-
);
127123
}
128124
});
129125

126+
/**
127+
* Custom propTypes checker
128+
*/
129+
function onlyProgressBar(props, propName, componentName) {
130+
if (props[propName]) {
131+
let error, childIdentifier;
132+
133+
React.Children.forEach(props[propName], (child) => {
134+
if (child.type !== ProgressBar) {
135+
childIdentifier = (child.type.displayName ? child.type.displayName : child.type);
136+
error = new Error(`Children of ${componentName} can contain only ProgressBar components. Found ${childIdentifier}`);
137+
}
138+
});
139+
140+
return error;
141+
}
142+
}
143+
130144
export default ProgressBar;

test/ProgressBarSpec.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import ReactTestUtils from 'react/lib/ReactTestUtils';
33
import ProgressBar from '../src/ProgressBar';
4+
import {shouldWarn} from './helpers';
45

56
const getProgressBarNode = function (wrapper) {
67
return React.findDOMNode(ReactTestUtils.findRenderedDOMComponentWithClass(wrapper, 'progress-bar'));
@@ -181,4 +182,15 @@ describe('ProgressBar', function () {
181182
assert.equal(bar2.style.width, '30%');
182183
});
183184

185+
it('allows only ProgressBar in children', function () {
186+
ReactTestUtils.renderIntoDocument(
187+
<ProgressBar>
188+
<ProgressBar key={1} />
189+
<div />
190+
<ProgressBar key={2} />
191+
</ProgressBar>
192+
);
193+
194+
shouldWarn('Failed propType');
195+
});
184196
});

0 commit comments

Comments
 (0)