commit
ae1cab3a77
|
@ -0,0 +1,10 @@
|
|||
capitalized = (prop) ->
|
||||
prop[0].toUpperCase() + prop[1..-1].toLowerCase()
|
||||
|
||||
vendorNoMoz = (prop, args) ->
|
||||
"Webkit#{capitalized(prop)}": args
|
||||
"Ms#{capitalized(prop)}": args
|
||||
"#{prop}": args
|
||||
|
||||
module.exports =
|
||||
transform: (value) -> vendorNoMoz('transform', value)
|
|
@ -1,12 +1,5 @@
|
|||
###
|
||||
@todo
|
||||
v2
|
||||
- can set different sizes for circular progress
|
||||
- maybe a multicolor indeterminate circular progress bar
|
||||
- refactor vendor prefixes adding to a module
|
||||
###
|
||||
|
||||
require './style'
|
||||
localCSS = require './style'
|
||||
prefixer = require "../prefixer"
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
|
@ -17,6 +10,7 @@ module.exports = React.createClass
|
|||
max : React.PropTypes.number
|
||||
min : React.PropTypes.number
|
||||
mode : React.PropTypes.string
|
||||
multicolor : React.PropTypes.bool
|
||||
type : React.PropTypes.string
|
||||
value : React.PropTypes.number
|
||||
|
||||
|
@ -26,6 +20,7 @@ module.exports = React.createClass
|
|||
max : 100
|
||||
min : 0
|
||||
mode : 'indeterminate'
|
||||
multicolor : false
|
||||
type : 'linear'
|
||||
value : 0
|
||||
|
||||
|
@ -35,9 +30,11 @@ module.exports = React.createClass
|
|||
|
||||
# -- Render
|
||||
render: ->
|
||||
className = "#{@props.type} #{@props.className} #{@props.mode}"
|
||||
<div data-component-progressbar role="progressbar"
|
||||
className={className}
|
||||
className = if @props.type == 'linear' then localCSS.linearBar else localCSS.circularBar
|
||||
className += " #{localCSS.root} #{@props.mode} #{@props.className}"
|
||||
className += " multicolor" if @props.multicolor
|
||||
|
||||
<div className={className} role="progressbar"
|
||||
aria-valuenow={@props.value}
|
||||
aria-valuemin={@props.min}
|
||||
aria-valuemax={@props.max}>
|
||||
|
@ -45,25 +42,21 @@ module.exports = React.createClass
|
|||
</div>
|
||||
|
||||
renderCircular: ->
|
||||
style = transformDasharray(@calculateRatio(@props.value)) unless @props.mode == 'indeterminate'
|
||||
<svg data-component-progressbar-circle>
|
||||
<circle style={style} data-component-progressbar-circle-path cx="50" cy="50" r="45"/>
|
||||
unless @props.mode == 'indeterminate'
|
||||
style = _transformDasharray(@calculateRatio(@props.value))
|
||||
<svg className={localCSS.circle}>
|
||||
<circle id="circle" className={localCSS.circlePath} style={style} cx="30" cy="30" r="25"/>
|
||||
</svg>
|
||||
|
||||
renderLinear: ->
|
||||
unless @props.mode == 'indeterminate'
|
||||
bufferStyle = transformProgress(@calculateRatio(@props.buffer))
|
||||
valueStyle = transformProgress(@calculateRatio(@props.value))
|
||||
bufferStyle = prefixer.transform("scaleX(#{@calculateRatio(@props.buffer)})")
|
||||
valueStyle = prefixer.transform("scaleX(#{@calculateRatio(@props.value)})")
|
||||
<div>
|
||||
<span data-component-progressbar-buffer style={bufferStyle}></span>
|
||||
<span data-component-progressbar-value style={valueStyle}></span>
|
||||
<span id="buffer" className={localCSS.bufferBar} style={bufferStyle}></span>
|
||||
<span id="value" className={localCSS.valueBar} style={valueStyle}></span>
|
||||
</div>
|
||||
|
||||
# -- Private methods
|
||||
transformDasharray = (ratio) ->
|
||||
_transformDasharray = (ratio) ->
|
||||
strokeDasharray: "#{2 * Math.PI * 45 * ratio}, 400"
|
||||
|
||||
transformProgress = (ratio) ->
|
||||
WebkitTransform: "scaleX(#{ratio})"
|
||||
MsTransform: "scaleX(#{ratio})"
|
||||
transform: "scaleX(#{ratio})"
|
||||
|
|
|
@ -1,89 +1,105 @@
|
|||
@import '../constants.styl'
|
||||
|
||||
// -- NOTE: Parameters depend on the component SVG Markup too
|
||||
CIRCLE_WRAPPER_WIDTH = 100
|
||||
CIRCLE_RADIUS = 45
|
||||
SCALE_RATIO = CIRCLE_RADIUS/20
|
||||
CIRCLE_WRAPPER_WIDTH = 60 // You need to change cx and cy in markup too
|
||||
CIRCLE_RADIUS = 25 // You need to change r in the markup too
|
||||
SCALE_RATIO = CIRCLE_RADIUS/20
|
||||
|
||||
[data-component-progressbar]
|
||||
display : inline-block
|
||||
// -- Linear progress bar
|
||||
:local(.linearBar)
|
||||
display : inline-block
|
||||
position : relative
|
||||
height : PROGRESS_BAR_HEIGHT
|
||||
width : 100%
|
||||
background : darken(BACKGROUND, 7.5%)
|
||||
overflow : hidden
|
||||
|
||||
&.linear
|
||||
position : relative
|
||||
height : PROGRESS_BAR_HEIGHT
|
||||
width : 100%
|
||||
background : darken(BACKGROUND, 7.5%)
|
||||
overflow : hidden
|
||||
:local(.valueBar), :local(.bufferBar)
|
||||
position : absolute
|
||||
bottom : 0
|
||||
left : 0
|
||||
right : 0
|
||||
top : 0
|
||||
transform : scaleX(0)
|
||||
transform-origin : left center
|
||||
transition-duration : ANIMATION_DURATION
|
||||
transition-timing-function : ANIMATION_EASE
|
||||
|
||||
[data-component-progressbar-value], [data-component-progressbar-buffer]
|
||||
position : absolute
|
||||
bottom : 0
|
||||
left : 0
|
||||
right : 0
|
||||
top : 0
|
||||
transform scaleX(0)
|
||||
transform-origin left center
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
:local(.valueBar)
|
||||
background-color : ACCENT
|
||||
|
||||
[data-component-progressbar-value]
|
||||
background-color : ACCENT
|
||||
:local(.bufferBar)
|
||||
background-color : alpha(ACCENT, 15%)
|
||||
|
||||
[data-component-progressbar-buffer]
|
||||
background-color : alpha(ACCENT, 15%)
|
||||
:local(.linearBar).indeterminate :local(.valueBar)
|
||||
transform-origin : center center
|
||||
animation : linear-indeterminate-bar 1s linear infinite
|
||||
|
||||
&.indeterminate [data-component-progressbar-value]
|
||||
transform-origin center center
|
||||
animation linear-indeterminate-bar 1s linear infinite
|
||||
// -- Circular progress bar
|
||||
:local(.circularBar)
|
||||
display : inline-block
|
||||
position : relative
|
||||
height : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
width : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
transform : rotate(-90deg)
|
||||
|
||||
&.circular
|
||||
position : relative
|
||||
height : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
width : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
transform rotate(-90deg)
|
||||
:local(.circle)
|
||||
height : 100%
|
||||
width : 100%
|
||||
|
||||
[data-component-progressbar-circle]
|
||||
height : 100%
|
||||
width : 100%
|
||||
:local(.circlePath)
|
||||
stroke-dasharray : 0, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
stroke-linecap : round
|
||||
stroke-miterlimit : 20
|
||||
stroke-width : 4
|
||||
stroke : ACCENT
|
||||
fill : none
|
||||
transition : stroke-dasharray ANIMATION_DURATION ANIMATION_EASE
|
||||
|
||||
[data-component-progressbar-circle-path]
|
||||
stroke-dasharray : 0, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
stroke-linecap : round
|
||||
stroke-miterlimit : 20
|
||||
stroke-width : 4
|
||||
stroke : ACCENT
|
||||
fill : none
|
||||
transition stroke-dasharray ANIMATION_DURATION ANIMATION_EASE
|
||||
:local(.circularBar).indeterminate
|
||||
:local(.circle)
|
||||
animation : circular-indeterminate-bar-rotate 2s linear infinite
|
||||
|
||||
&.indeterminate
|
||||
[data-component-progressbar-circle]
|
||||
animation circular-indeterminate-bar-rotate 2s linear infinite
|
||||
:local(.circlePath)
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite
|
||||
|
||||
[data-component-progressbar-circle-path]
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
animation circular-indeterminate-bar-dash 1.5s ease-in-out infinite
|
||||
&.multicolor :local(.circlePath)
|
||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite, colors (1.5s*4) ease-in-out infinite
|
||||
|
||||
// -- Animations
|
||||
@keyframes linear-indeterminate-bar
|
||||
0%
|
||||
transform translate(-50%) scaleX(0)
|
||||
transform : translate(-50%) scaleX(0)
|
||||
50%
|
||||
transform translate(-0%) scaleX(0.3)
|
||||
transform : translate(-0%) scaleX(0.3)
|
||||
100%
|
||||
transform translate(50%) scaleX(0)
|
||||
transform : translate(50%) scaleX(0)
|
||||
|
||||
@keyframes circular-indeterminate-bar-rotate
|
||||
100%
|
||||
transform : rotate(360deg)
|
||||
transform : rotate(360deg)
|
||||
|
||||
@keyframes circular-indeterminate-bar-dash
|
||||
0%
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * 0
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * 0
|
||||
50%
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -35
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -35
|
||||
100%
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -124
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -124
|
||||
|
||||
@keyframes colors
|
||||
0%
|
||||
stroke: #4285F4
|
||||
25%
|
||||
stroke: #DE3E35
|
||||
50%
|
||||
stroke: #F7C223
|
||||
75%
|
||||
stroke: #1B9A59
|
||||
100%
|
||||
stroke: #4285F4
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
prefixer = require "../prefixer"
|
||||
ProgressBar = require "../progress_bar"
|
||||
Input = require "../input"
|
||||
localCSS = require './style'
|
||||
|
||||
module.exports = React.createClass
|
||||
|
||||
# -- States & Properties
|
||||
propTypes:
|
||||
className : React.PropTypes.string
|
||||
editable : React.PropTypes.bool
|
||||
max : React.PropTypes.number
|
||||
min : React.PropTypes.number
|
||||
onChange : React.PropTypes.func
|
||||
pinned : React.PropTypes.bool
|
||||
snaps : React.PropTypes.bool
|
||||
step : React.PropTypes.number
|
||||
value : React.PropTypes.number
|
||||
|
||||
getDefaultProps: ->
|
||||
className : ""
|
||||
editable : false
|
||||
max : 100
|
||||
min : 0
|
||||
pinned : false
|
||||
snaps : false
|
||||
step : 0.01
|
||||
value : 0
|
||||
|
||||
getInitialState: ->
|
||||
sliderStart : 0
|
||||
sliderLength : 0
|
||||
value : @props.value
|
||||
|
||||
# -- Lifecycle
|
||||
componentDidMount: ->
|
||||
@onResize()
|
||||
window.addEventListener('resize', @onResize)
|
||||
|
||||
componentWillUnmount: ->
|
||||
window.removeEventListener('resize', @onResize)
|
||||
|
||||
componentDidUpdate: (prevProps, prevState) ->
|
||||
if prevState.value != @state.value
|
||||
@props.onChange? @
|
||||
if @state.value != parseFloat(@refs.input?.getValue())
|
||||
@refs.input?.setValue(@valueForInput(@state.value))
|
||||
|
||||
# -- Events
|
||||
onResize: (event) ->
|
||||
sliderBounds = @refs.progressbar.getDOMNode().getBoundingClientRect()
|
||||
@setState
|
||||
sliderStart: sliderBounds['left'],
|
||||
sliderLength: (sliderBounds['right'] - sliderBounds['left'])
|
||||
|
||||
onSliderMouseDown: (event) ->
|
||||
position = _getMousePosition(event)
|
||||
value = @positionToValue(position)
|
||||
@setState value: value, =>
|
||||
@start(position)
|
||||
_addEventsToDocument(@getMouseEventMap())
|
||||
_pauseEvent(event)
|
||||
|
||||
onSliderTouchStart: (event) ->
|
||||
position = _getTouchPosition(event)
|
||||
value = @positionToValue(position)
|
||||
@setState value: value, =>
|
||||
@start(position)
|
||||
_addEventsToDocument(@getTouchEventMap())
|
||||
_pauseEvent(e)
|
||||
|
||||
onSliderFocus: (event) ->
|
||||
_addEventsToDocument(@getKeyboardEvents())
|
||||
|
||||
onSliderBlur: (event) ->
|
||||
_removeEventsFromDocument(@getKeyboardEvents())
|
||||
|
||||
onInputChange: ->
|
||||
@setState value: @trimValue(@refs.input.getValue())
|
||||
|
||||
onKeyDown: (event) ->
|
||||
event.stopPropagation()
|
||||
@refs.slider.getDOMNode().blur() if event.keyCode in [13, 27]
|
||||
@addToValue(@props.step) if event.keyCode == 38
|
||||
@addToValue(-@props.step) if event.keyCode == 40
|
||||
|
||||
onMouseDown: (event) ->
|
||||
@start(_getMousePosition(event))
|
||||
_addEventsToDocument(@getMouseEventMap())
|
||||
|
||||
onTouchStart: (event) ->
|
||||
event.stopPropagation()
|
||||
@start(_getTouchPosition(event))
|
||||
_addEventsToDocument(@getTouchEventMap())
|
||||
|
||||
onMouseMove: (event) ->
|
||||
_pauseEvent(event)
|
||||
@move(_getMousePosition(event))
|
||||
|
||||
onTouchMove: (event) ->
|
||||
@move(_getTouchPosition(event))
|
||||
|
||||
onMouseUp: ->
|
||||
@end(@getMouseEventMap())
|
||||
|
||||
onTouchEnd: ->
|
||||
@end(@getTouchEventMap())
|
||||
|
||||
# -- Internal methods
|
||||
getMouseEventMap: ->
|
||||
mousemove: @onMouseMove
|
||||
mouseup: @onMouseUp
|
||||
|
||||
getTouchEventMap: ->
|
||||
touchmove: @onTouchMove
|
||||
touchend: @onTouchEnd
|
||||
|
||||
getKeyboardEvents: ->
|
||||
keydown: @onKeyDown
|
||||
|
||||
positionToValue: (position) ->
|
||||
offset = position.x - @state.sliderStart
|
||||
@trimValue(offset / @state.sliderLength * (@props.max - @props.min))
|
||||
|
||||
start: (position) ->
|
||||
@setState
|
||||
pressed: true
|
||||
startPosition: position.x
|
||||
startValue: @state.value
|
||||
|
||||
move: (position) ->
|
||||
value = @endPositionToValue(position)
|
||||
@setState value: value
|
||||
|
||||
end: (events) ->
|
||||
_removeEventsFromDocument(events)
|
||||
@setState pressed: false
|
||||
|
||||
endPositionToValue: (position) ->
|
||||
offset = position.x - @state.startPosition
|
||||
diffValue = offset / @state.sliderLength * (@props.max - @props.min)
|
||||
@trimValue(diffValue + @state.startValue)
|
||||
|
||||
trimValue: (value) ->
|
||||
value = @props.min if (value < @props.min)
|
||||
value = @props.max if (value > @props.max)
|
||||
@nearest(value)
|
||||
|
||||
nearest: (value) ->
|
||||
steps = (@props.max - @props.min) / @props.step
|
||||
zerone = Math.round((value - @props.min) * steps / (@props.max - @props.min))/steps
|
||||
return zerone * (@props.max - @props.min) + @props.min
|
||||
|
||||
addToValue: (value) ->
|
||||
@setState value: @trimValue(@state.value + value)
|
||||
|
||||
valueForInput: (value) ->
|
||||
decimals = (@props.step.toString().split('.')[1] || []).length
|
||||
if decimals > 0 then value.toFixed(decimals) else value.toString()
|
||||
|
||||
calculateKnobOffset: ->
|
||||
@state.sliderLength * (@state.value - @props.min) / (@props.max - @props.min)
|
||||
|
||||
render: ->
|
||||
className = @props.className
|
||||
className += " editable" if @props.editable
|
||||
className += " pinned" if @props.pinned
|
||||
className += " pressed" if @state.pressed
|
||||
className += " ring" if @state.value == @props.min
|
||||
knobStyles = prefixer.transform("translateX(#{@calculateKnobOffset()}px)")
|
||||
|
||||
<div className={localCSS.root + className}
|
||||
tabIndex="0" ref="slider"
|
||||
onFocus={@onSliderFocus}
|
||||
onBlur={@onSliderBlur} >
|
||||
|
||||
<div className={localCSS.container}
|
||||
onTouchStart={@onSliderTouchStart}
|
||||
onMouseDown={@onSliderMouseDown} >
|
||||
|
||||
<div className={localCSS.knob} style={knobStyles}
|
||||
onMouseDown={@onMouseDown}
|
||||
onTouchStart={@onTouchStart} >
|
||||
<div className={localCSS.knobInner} data-value={parseInt(@state.value)}></div>
|
||||
</div>
|
||||
|
||||
<div className={localCSS.progress} >
|
||||
<ProgressBar ref="progressbar" mode="determinate"
|
||||
className={localCSS.progressInner}
|
||||
value={@state.value}
|
||||
max={@props.max}
|
||||
min={@props.min}/>
|
||||
{
|
||||
if @props.snaps
|
||||
<div className={localCSS.snaps}>
|
||||
{
|
||||
for i in [1..((@props.max - @props.min) / @props.step)]
|
||||
<div key="span-#{i}" className={localCSS.snap}></div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
if @props.editable
|
||||
<Input ref="input" className={localCSS.input}
|
||||
onChange={@onInputChange}
|
||||
value={@valueForInput(@state.value)} />
|
||||
}
|
||||
</div>
|
||||
|
||||
# -- Extends
|
||||
getValue: ->
|
||||
@state.value
|
||||
|
||||
setValue: (value) ->
|
||||
@setState value: value
|
||||
|
||||
# -- Private methods
|
||||
_pauseEvent = (event) ->
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
event.returnValue = false
|
||||
event.cancelBubble = true
|
||||
return null
|
||||
|
||||
_getMousePosition = (event) ->
|
||||
x: event.pageX
|
||||
y: event.pageY
|
||||
|
||||
_getTouchPosition = (event) ->
|
||||
x: event.touches[0]['pageX']
|
||||
y: event.touches[0]['pageY']
|
||||
|
||||
_addEventsToDocument = (events) ->
|
||||
document.addEventListener(key, events[key], false) for key of events
|
||||
|
||||
_removeEventsFromDocument = (events) ->
|
||||
document.removeEventListener(key, events[key], false) for key of events
|
|
@ -0,0 +1,162 @@
|
|||
@import "../constants"
|
||||
|
||||
RANGE_SIDE_SEPARATION = 20px
|
||||
|
||||
:local(.container)
|
||||
height : 32px
|
||||
margin-right : 32px
|
||||
position : relative
|
||||
user-select : none
|
||||
width : calc(100% - 32px)
|
||||
&:not(:last-child)
|
||||
margin-right : RANGE_SIDE_SEPARATION + 32px
|
||||
&:not(:first-child)
|
||||
margin-left : RANGE_SIDE_SEPARATION
|
||||
|
||||
:local(.knob)
|
||||
align-items : center
|
||||
background-color : transparent
|
||||
display : flex
|
||||
flex-direction : row
|
||||
height : 32px
|
||||
justify-content : center
|
||||
left : 0
|
||||
position : relative
|
||||
top : 0
|
||||
width : 32px
|
||||
z-index : 5
|
||||
|
||||
:local(.knobInner)
|
||||
background-color : ACCENT
|
||||
border-radius : 50%
|
||||
height : 12px
|
||||
transition-duration : 0.1s
|
||||
transition-property : height, width, background-color, border
|
||||
transition-timing-function : ease
|
||||
width : 12px
|
||||
z-index : 4
|
||||
|
||||
:local(.snaps)
|
||||
display : flex
|
||||
flex-direction : row
|
||||
height : 2px
|
||||
left : 0
|
||||
pointer-events : none
|
||||
position : absolute
|
||||
top : 15px
|
||||
width : calc(100% + 2px)
|
||||
&:after
|
||||
background-color : black
|
||||
border-radius : 50%
|
||||
content : ""
|
||||
display : block
|
||||
height : 2px
|
||||
width : 2px
|
||||
|
||||
:local(.snap)
|
||||
flex : 1
|
||||
&:after
|
||||
background-color : black
|
||||
border-radius : 50%
|
||||
content : ""
|
||||
display : block
|
||||
height : 2px
|
||||
width : 2px
|
||||
|
||||
:local(.input)
|
||||
margin-bottom : 0
|
||||
text-align : center
|
||||
width : 40px
|
||||
|
||||
:local(.progress)
|
||||
height : 100%
|
||||
left : 16px
|
||||
position : absolute
|
||||
top : 0
|
||||
width : 100%
|
||||
|
||||
:local(.progressInner)
|
||||
height : 2px
|
||||
position : absolute
|
||||
top : 15px
|
||||
#value
|
||||
transition-duration : 0s
|
||||
|
||||
// When its focused
|
||||
:local(.root):focus :local(.knob):before
|
||||
background-color : ACCENT
|
||||
border-radius : 50%
|
||||
bottom : 0
|
||||
content : ""
|
||||
left : 0
|
||||
position : absolute
|
||||
right : 0
|
||||
top : 0
|
||||
opacity : .26
|
||||
z-index : 2
|
||||
|
||||
:local(.root).editable
|
||||
display : flex
|
||||
align-items : center
|
||||
flex-direction : row
|
||||
|
||||
// When its pinned
|
||||
:local(.root).pinned :local(.knobInner)
|
||||
&:before
|
||||
content : ""
|
||||
position : absolute
|
||||
top : 0
|
||||
background-color : ACCENT
|
||||
left : 0
|
||||
width : 26px
|
||||
height : 26px
|
||||
margin-left : 3px
|
||||
border-radius : 50% 50% 50% 0
|
||||
transition-delay : 1s
|
||||
transform : rotate(-45deg) scale(0) translate(0)
|
||||
transition : transform .2s ease, background-color .18s ease
|
||||
|
||||
&:after
|
||||
color : white
|
||||
content : attr(data-value)
|
||||
font-size : 10px
|
||||
height : 26px
|
||||
left : 0
|
||||
position : absolute
|
||||
text-align : center
|
||||
top : 0
|
||||
transform : scale(0) translate(0)
|
||||
transition : transform .2s ease, background-color .18s ease
|
||||
width : 32px
|
||||
|
||||
// When the knob is pressed
|
||||
:local(.root).pressed.pinned :local(.knobInner)
|
||||
&:before
|
||||
transition-delay : 100ms
|
||||
transform : rotate(-45deg) scale(1) translate(17px, -17px)
|
||||
|
||||
&:after
|
||||
transition-delay : 100ms
|
||||
transform : scale(1) translate(0, -17px)
|
||||
|
||||
:local(.root).pressed:not(.pinned) :local(.knobInner)
|
||||
height : 100%
|
||||
transform : translateZ(0)
|
||||
width : 100%
|
||||
|
||||
:local(.root).pressed:not(.pinned).ring :local(.progress)
|
||||
left : 30px
|
||||
width : calc(100% - 14px)
|
||||
|
||||
// When there is no current value
|
||||
:local(.root).ring :local(.knobInner)
|
||||
background-color : transparent
|
||||
border : 2px solid #c8c8c8
|
||||
|
||||
:local(.root).ring :local(.knobInner):before
|
||||
background-color : #c8c8c8
|
||||
|
||||
:local(.root).ring :local(.progress)
|
||||
left : 20px
|
||||
transition : left 0.18s ease, width 0.18s ease
|
||||
width : calc(100% - 4px)
|
|
@ -26,10 +26,12 @@
|
|||
"react" : "^0.13.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer-core" : "^5.1.11",
|
||||
"coffee-jsx-loader" : "^0.1.2",
|
||||
"css-loader" : "^0.14.5",
|
||||
"extract-text-webpack-plugin" : "^0.8.1",
|
||||
"node-libs-browser" : "^0.5.2",
|
||||
"postcss-loader" : "^0.4.3",
|
||||
"style-loader" : "^0.12.3",
|
||||
"stylus-loader" : "^1.2.0",
|
||||
"webpack" : "^1.9.10",
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Slider = require '../../components/slider'
|
||||
|
||||
module.exports = React.createClass
|
||||
test: ->
|
||||
marginTop: "1rem"
|
||||
|
||||
render: ->
|
||||
<section>
|
||||
<h2 style={@test()}>Sliders</h2>
|
||||
<p>Normal slider</p>
|
||||
<Slider />
|
||||
<p>With steps, initial value and editable</p>
|
||||
<Slider value={5} min={0} max={10} editable />
|
||||
<p>Pinned and with snaps</p>
|
||||
|
||||
<Slider pinned value={1} min={0} max={10} step={1} editable />
|
||||
</section>
|
|
@ -10,6 +10,7 @@ Dropdown = require './components/dropdown'
|
|||
FontIcon = require './components/font_icon'
|
||||
Form = require './components/form'
|
||||
Progress = require './components/progress'
|
||||
Slider = require './components/slider'
|
||||
Switch = require './components/switch'
|
||||
|
||||
Test = React.createClass
|
||||
|
@ -29,6 +30,7 @@ Test = React.createClass
|
|||
<FontIcon />
|
||||
<Form />
|
||||
<Progress />
|
||||
<Slider />
|
||||
</app>
|
||||
|
||||
React.render <Test/>, document.body
|
||||
|
|
|
@ -22,7 +22,7 @@ module.exports =
|
|||
|
||||
devServer:
|
||||
# contentBase : './build'
|
||||
host : 'localhost'
|
||||
host : '0.0.0.0'
|
||||
port : 8080
|
||||
# colors : true
|
||||
# progress : true
|
||||
|
@ -38,9 +38,13 @@ module.exports =
|
|||
,
|
||||
test : /\.coffee$/, loader: 'coffee-jsx-loader'
|
||||
,
|
||||
test : /\.styl$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader!stylus-loader!')
|
||||
test : /\.styl$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!stylus-loader!')
|
||||
]
|
||||
|
||||
postcss: [
|
||||
require('autoprefixer-core')
|
||||
],
|
||||
|
||||
plugins: [
|
||||
new ExtractTextPlugin pkg.name + '.[name].css', allChunks: false
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue