Migrate progress bars to es6
parent
1a7b6d187f
commit
74907a4517
|
@ -2,6 +2,7 @@
|
|||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"es6": true
|
||||
},
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
TestUtils = React.addons.TestUtils
|
||||
expect = require('expect')
|
||||
utils = require('../../utils/testing')
|
||||
ProgressBar = require('../index')
|
||||
|
||||
describe 'ProgressBar', ->
|
||||
describe '#calculateRatio', ->
|
||||
before ->
|
||||
@progressBar = utils.renderComponent(ProgressBar, { min: 100, max: 300 })
|
||||
|
||||
it 'calculates the right ratio', ->
|
||||
expect(@progressBar.calculateRatio(150)).toEqual(0.25)
|
||||
|
||||
it 'gets 0 when value is less than min', ->
|
||||
expect(@progressBar.calculateRatio(10)).toEqual(0)
|
||||
|
||||
it 'gets 1 when value is more than max', ->
|
||||
expect(@progressBar.calculateRatio(400)).toEqual(1)
|
||||
|
||||
describe '#render', ->
|
||||
it 'renders the value and buffer bars when it is linear', ->
|
||||
progressBarWrapper = utils.shallowRenderComponent(ProgressBar).props.children
|
||||
expect(progressBarWrapper.props.children.length).toEqual(2)
|
||||
expect(progressBarWrapper.props.children[0].ref).toEqual('buffer')
|
||||
expect(progressBarWrapper.props.children[1].ref).toEqual('value')
|
||||
|
||||
it 'renders the proper scaleX for buffer and value when its linear and determinate', ->
|
||||
progressBar = utils.shallowRenderComponent(ProgressBar, {mode: 'determinate', value: 30, buffer: 60})
|
||||
buffer = (progressBar.props.children.props.children[0])
|
||||
value = (progressBar.props.children.props.children[1])
|
||||
expect(buffer.props.style.transform).toEqual("scaleX(#{0.6})")
|
||||
expect(value.props.style.transform).toEqual("scaleX(#{0.3})")
|
||||
|
||||
it 'renders the svg circle when it is circular', ->
|
||||
progressBar = utils.shallowRenderComponent(ProgressBar, {type: 'circular'})
|
||||
expect(progressBar.props.children.type).toEqual('svg')
|
||||
expect(progressBar.props.children.props.children.type).toEqual('circle')
|
||||
|
||||
it 'renders the proper circle length style when it is circular and determinate', ->
|
||||
progressBar = utils.shallowRenderComponent(ProgressBar, {type: 'circular', mode: 'determinate', value: 30})
|
||||
circle = progressBar.props.children.props.children
|
||||
strokeLength = 2 * Math.PI * circle.props.r * 0.3
|
||||
expect(circle.props.style.strokeDasharray).toEqual("#{strokeLength}, 400")
|
||||
|
||||
it 'contains mode and className in its className', ->
|
||||
progressBar = utils.shallowRenderComponent(ProgressBar, {mode: 'determinate', className: 'tight'})
|
||||
expect(progressBar.props.className).toContain('determinate')
|
||||
expect(progressBar.props.className).toContain('tight')
|
|
@ -0,0 +1,63 @@
|
|||
const expect = require('expect');
|
||||
const utils = require('../../utils/testing');
|
||||
const ProgressBar = require('../index');
|
||||
|
||||
describe('ProgressBar', function () {
|
||||
describe('#calculateRatio', function () {
|
||||
before(function () {
|
||||
this.progressBar = utils.renderComponent(ProgressBar, {min: 100, max: 300});
|
||||
});
|
||||
|
||||
it('calculates the right ratio', function () {
|
||||
expect(this.progressBar.calculateRatio(150)).toEqual(0.25);
|
||||
});
|
||||
|
||||
it('gets 0 when value is less than min', function () {
|
||||
expect(this.progressBar.calculateRatio(10)).toEqual(0);
|
||||
});
|
||||
|
||||
it('gets 1 when value is more than max', function () {
|
||||
expect(this.progressBar.calculateRatio(400)).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#render', function () {
|
||||
it('renders the value and buffer bars when it is linear', function () {
|
||||
const progressBarWrapper = utils.shallowRenderComponent(ProgressBar).props.children;
|
||||
expect(progressBarWrapper.props.children.length).toEqual(2);
|
||||
expect(progressBarWrapper.props.children[0].ref).toEqual('buffer');
|
||||
expect(progressBarWrapper.props.children[1].ref).toEqual('value');
|
||||
});
|
||||
|
||||
it('renders the value and buffer bars when it is linear', function () {
|
||||
const progressBar = utils.shallowRenderComponent(ProgressBar, {
|
||||
mode: 'determinate', value: 30, buffer: 60
|
||||
});
|
||||
const buffer = (progressBar.props.children.props.children[0]);
|
||||
const value = (progressBar.props.children.props.children[1]);
|
||||
expect(buffer.props.style.transform).toEqual(`scaleX(${0.6})`);
|
||||
expect(value.props.style.transform).toEqual(`scaleX(${0.3})`);
|
||||
});
|
||||
|
||||
it('renders the svg circle when it is circular', function () {
|
||||
const progressBar = utils.shallowRenderComponent(ProgressBar, {type: 'circular'});
|
||||
expect(progressBar.props.children.type).toEqual('svg');
|
||||
expect(progressBar.props.children.props.children.type).toEqual('circle');
|
||||
});
|
||||
|
||||
it('renders the proper circle length style when it is circular and determinate', function () {
|
||||
const progressBar = utils.shallowRenderComponent(ProgressBar, {
|
||||
type: 'circular', mode: 'determinate', value: 30});
|
||||
const circle = progressBar.props.children.props.children;
|
||||
const strokeLength = 2 * Math.PI * circle.props.r * 0.3;
|
||||
expect(circle.props.style.strokeDasharray).toEqual(`${strokeLength}, 400`);
|
||||
});
|
||||
|
||||
it('contains mode and className in its className', function () {
|
||||
const progressBar = utils.shallowRenderComponent(ProgressBar, {
|
||||
mode: 'determinate', className: 'tight'});
|
||||
expect(progressBar.props.className).toContain('determinate');
|
||||
expect(progressBar.props.className).toContain('tight');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,68 +0,0 @@
|
|||
localCSS = require './style'
|
||||
prefixer = require '../utils/prefixer'
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- Properties
|
||||
propTypes:
|
||||
buffer : React.PropTypes.number
|
||||
className : React.PropTypes.string
|
||||
max : React.PropTypes.number
|
||||
min : React.PropTypes.number
|
||||
mode : React.PropTypes.string
|
||||
multicolor : React.PropTypes.bool
|
||||
type : React.PropTypes.string
|
||||
value : React.PropTypes.number
|
||||
|
||||
getDefaultProps: ->
|
||||
buffer : 0
|
||||
className : ''
|
||||
max : 100
|
||||
min : 0
|
||||
mode : 'indeterminate'
|
||||
multicolor : false
|
||||
type : 'linear'
|
||||
value : 0
|
||||
|
||||
# -- Helper methods
|
||||
calculateRatio: (value) ->
|
||||
return 0 if value < @props.min
|
||||
return 1 if value > @props.max
|
||||
return (value - @props.min) / (@props.max - @props.min)
|
||||
|
||||
# -- Render
|
||||
render: ->
|
||||
className = if @props.type == 'linear' then localCSS.linearBar else localCSS.circularBar
|
||||
className += " #{@props.className}" if @props.className
|
||||
className += " #{@props.mode}" if @props.mode
|
||||
className += " multicolor" if @props.multicolor
|
||||
|
||||
<div className={className} role="progressbar"
|
||||
aria-valuenow={@props.value}
|
||||
aria-valuemin={@props.min}
|
||||
aria-valuemax={@props.max}>
|
||||
{ if @props.type == 'circular' then @renderCircular() else @renderLinear() }
|
||||
</div>
|
||||
|
||||
renderCircular: ->
|
||||
<svg className={localCSS.circle}>
|
||||
<circle className={localCSS.circlePath} style={@circularStyle()} cx="30" cy="30" r="25"/>
|
||||
</svg>
|
||||
|
||||
circularStyle: ->
|
||||
_transformDasharray(@calculateRatio(@props.value)) unless @props.mode == 'indeterminate'
|
||||
|
||||
renderLinear: ->
|
||||
<div>
|
||||
<span ref="buffer" data-ref="buffer" className={localCSS.bufferBar} style={@linearStyles()?.buffer}></span>
|
||||
<span ref="value" data-ref="value" className={localCSS.valueBar} style={@linearStyles()?.value}></span>
|
||||
</div>
|
||||
|
||||
linearStyles: ->
|
||||
unless @props.mode == 'indeterminate'
|
||||
buffer: prefixer(transform: "scaleX(#{@calculateRatio(@props.buffer)})")
|
||||
value: prefixer(transform: "scaleX(#{@calculateRatio(@props.value)})")
|
||||
|
||||
# -- Private methods
|
||||
_transformDasharray = (ratio) ->
|
||||
strokeDasharray: "#{2 * Math.PI * 25 * ratio}, 400"
|
|
@ -0,0 +1,91 @@
|
|||
const React = window.React;
|
||||
const PureRenderMixin = require('react/addons').addons.PureRenderMixin;
|
||||
const css = require('./style');
|
||||
const prefixer = require('../utils/prefixer');
|
||||
|
||||
module.exports = React.createClass({
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
propTypes: {
|
||||
buffer: React.PropTypes.number,
|
||||
className: React.PropTypes.string,
|
||||
max: React.PropTypes.number,
|
||||
min: React.PropTypes.number,
|
||||
mode: React.PropTypes.string,
|
||||
multicolor: React.PropTypes.bool,
|
||||
type: React.PropTypes.string,
|
||||
value: React.PropTypes.number
|
||||
},
|
||||
|
||||
getDefaultProps () {
|
||||
return {
|
||||
buffer: 0,
|
||||
className: '',
|
||||
max: 100,
|
||||
min: 0,
|
||||
mode: 'indeterminate',
|
||||
multicolor: false,
|
||||
type: 'linear',
|
||||
value: 0
|
||||
};
|
||||
},
|
||||
|
||||
calculateRatio (value) {
|
||||
if (value < this.props.min) return 0;
|
||||
if (value > this.props.max) return 1;
|
||||
return (value - this.props.min) / (this.props.max - this.props.min);
|
||||
},
|
||||
|
||||
circularStyle () {
|
||||
if (this.props.mode !== 'indeterminate') {
|
||||
return {strokeDasharray: `${2 * Math.PI * 25 * this.calculateRatio(this.props.value)}, 400`};
|
||||
}
|
||||
},
|
||||
|
||||
renderCircular () {
|
||||
return (
|
||||
<svg className={css.circle}>
|
||||
<circle className={css.circlePath} style={this.circularStyle()} cx="30" cy="30" r="25" />
|
||||
</svg>
|
||||
);
|
||||
},
|
||||
|
||||
linearStyle () {
|
||||
if (this.props.mode !== 'indeterminate') {
|
||||
return {
|
||||
buffer: prefixer({transform: `scaleX(${this.calculateRatio(this.props.buffer)})`}),
|
||||
value: prefixer({transform: `scaleX(${this.calculateRatio(this.props.value)})`})
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
renderLinear () {
|
||||
const {buffer, value} = this.linearStyle();
|
||||
return (
|
||||
<div>
|
||||
<span ref="buffer" data-ref="buffer" className={css.bufferBar} style={buffer}></span>
|
||||
<span ref="value" data-ref="value" className={css.valueBar} style={value}></span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render () {
|
||||
let className = this.props.type === 'linear' ? css.linearBar : css.circularBar;
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
if (this.props.mode) className += ` ${this.props.mode}`;
|
||||
if (this.props.multicolor) className += ` multicolor`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
role="progressbar"
|
||||
aria-valuenow={this.props.value}
|
||||
aria-valuemin={this.props.min}
|
||||
aria-valuemax={this.props.max}>
|
||||
{ this.props.type === 'circular' ? this.renderCircular() : this.renderLinear() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -16,11 +16,11 @@ module.exports = (config) ->
|
|||
'tests.webpack.js' : ['webpack']
|
||||
|
||||
webpack:
|
||||
resolve : extensions: ['', '.cjsx', '.coffee', '.js', '.json', '.styl']
|
||||
resolve : extensions: ['', '.jsx', '.cjsx', '.coffee', '.js', '.json', '.styl']
|
||||
|
||||
module:
|
||||
loaders: [
|
||||
test : /\.js$/, exclude:/(node_modules)/, loader: 'babel?optional=runtime'
|
||||
test : /(\.js|\.jsx)$/, exclude:/(node_modules)/, loader: 'babel?optional=runtime'
|
||||
,
|
||||
test : /\.cjsx$/, loader: 'coffee-jsx-loader'
|
||||
,
|
||||
|
|
|
@ -25,7 +25,7 @@ Test = React.createClass
|
|||
render: ->
|
||||
<app data-toolbox={true}>
|
||||
<h1>React-Toolbox <small>New way for create</small></h1>
|
||||
<Pickers />
|
||||
<Progress />
|
||||
</app>
|
||||
|
||||
React.render <Test/>, document.body
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
var context = require.context('./components', true, /.spec\.cjsx?$/);
|
||||
var context = require.context('./components', true, /(.spec\.cjsx?|.spec\.jsx?)$/);
|
||||
context.keys().forEach(context);
|
||||
|
|
Loading…
Reference in New Issue