From 2ef7756f70580dc929940f6a6d0a93c2b88573c9 Mon Sep 17 00:00:00 2001 From: Lochlan Wansbrough Date: Sat, 25 Jun 2016 02:37:47 -0700 Subject: [PATCH] [Slider] Added Y axis and reverse sliders Allow Y axis sliding Enable vertical slider Added reversible axis [Slider] Changed orientation of the normal y-axis. Added tests and examples. [Slider] Removed unnecessary function invocations Updated docs Added tests to test category --- .../pages/components/Slider/ExampleAxis.js | 15 + .../components/Slider/ExampleControlled.js | 4 + .../pages/components/Slider/ExampleSimple.js | 4 + .../pages/components/Slider/ExampleStep.js | 3 + .../pages/components/Slider/Page.js | 21 +- src/Slider/Slider.js | 190 ++++++-- src/Slider/Slider.spec.js | 431 +++++++++++++----- 7 files changed, 521 insertions(+), 147 deletions(-) create mode 100644 docs/src/app/components/pages/components/Slider/ExampleAxis.js diff --git a/docs/src/app/components/pages/components/Slider/ExampleAxis.js b/docs/src/app/components/pages/components/Slider/ExampleAxis.js new file mode 100644 index 00000000000000..94388c2ad14cb0 --- /dev/null +++ b/docs/src/app/components/pages/components/Slider/ExampleAxis.js @@ -0,0 +1,15 @@ +import React from 'react'; +import Slider from 'material-ui/Slider'; + +/** + * The orientation of the slider can be reversed and rotated using the `axis` prop. + */ +const SliderExampleAxis = () => ( +
+ + + +
+); + +export default SliderExampleAxis; diff --git a/docs/src/app/components/pages/components/Slider/ExampleControlled.js b/docs/src/app/components/pages/components/Slider/ExampleControlled.js index 114f0f90aced1c..60dabd404f74d7 100644 --- a/docs/src/app/components/pages/components/Slider/ExampleControlled.js +++ b/docs/src/app/components/pages/components/Slider/ExampleControlled.js @@ -1,6 +1,10 @@ import React from 'react'; import Slider from 'material-ui/Slider'; +/** + * The slider bar can have a set minimum and maximum, and the value can be + * obtained through the value parameter fired on an onChange event. + */ export default class SliderExampleControlled extends React.Component { state = { diff --git a/docs/src/app/components/pages/components/Slider/ExampleSimple.js b/docs/src/app/components/pages/components/Slider/ExampleSimple.js index 177fc8dddb24cd..d4235ce88a1d7a 100644 --- a/docs/src/app/components/pages/components/Slider/ExampleSimple.js +++ b/docs/src/app/components/pages/components/Slider/ExampleSimple.js @@ -1,6 +1,10 @@ import React from 'react'; import Slider from 'material-ui/Slider'; +/** + * The `defaultValue` property sets the initial position of the slider. The slider + * appearance changes when not at the starting position. + */ const SliderExampleSimple = () => (
diff --git a/docs/src/app/components/pages/components/Slider/ExampleStep.js b/docs/src/app/components/pages/components/Slider/ExampleStep.js index be841e62af8b86..7046dcc7870816 100644 --- a/docs/src/app/components/pages/components/Slider/ExampleStep.js +++ b/docs/src/app/components/pages/components/Slider/ExampleStep.js @@ -1,6 +1,9 @@ import React from 'react'; import Slider from 'material-ui/Slider'; +/** + * By default, the slider is continuous. The `step` property causes the slider to move in discrete increments. + */ const SliderExampleStep = () => ( ); diff --git a/docs/src/app/components/pages/components/Slider/Page.js b/docs/src/app/components/pages/components/Slider/Page.js index a17c57d6b513e8..27a3286d43215b 100644 --- a/docs/src/app/components/pages/components/Slider/Page.js +++ b/docs/src/app/components/pages/components/Slider/Page.js @@ -14,24 +14,16 @@ import SliderExampleStep from './ExampleStep'; import sliderExampleStepCode from '!raw!./ExampleStep'; import SliderExampleControlled from './ExampleControlled'; import sliderExampleControlledCode from '!raw!./ExampleControlled'; +import SliderExampleAxis from './ExampleAxis'; +import sliderExampleAxisCode from '!raw!./ExampleAxis'; import sliderCode from '!raw!material-ui/Slider/Slider'; -const descriptions = { - simple: 'The `defaultValue` property sets the initial position of the slider. The slider appearance changes when ' + - 'not at the starting position.', - stepped: 'By default, the slider is continuous. The `step` property causes the slider to move in discrete ' + - 'increments.', - value: 'The slider bar can have a set minimum and maximum, and the value can be ' + - 'obtained through the value parameter fired on an onChange event.', -}; - const SliderPage = () => (
`Slider - ${previousTitle}`} /> <MarkdownElement text={sliderReadmeText} /> <CodeExample title="Simple examples" - description={descriptions.simple} code={sliderExampleSimpleCode} > <SliderExampleSimple /> @@ -44,19 +36,24 @@ const SliderPage = () => ( </CodeExample> <CodeExample title="Stepped example" - description={descriptions.stepped} code={sliderExampleStepCode} > <SliderExampleStep /> </CodeExample> <CodeExample title="Controlled Examples" - description={descriptions.value} code={sliderExampleControlledCode} > <SliderExampleControlled /> </CodeExample> + <CodeExample + title="Alternative Axis Examples" + code={sliderExampleAxisCode} + > + <SliderExampleAxis /> + </CodeExample> + <PropTypeDescription code={sliderCode} /> </div> ); diff --git a/src/Slider/Slider.js b/src/Slider/Slider.js index 2607d3de29955b..7f06f9c595decf 100644 --- a/src/Slider/Slider.js +++ b/src/Slider/Slider.js @@ -37,33 +37,100 @@ const valueInRangePropType = (props, propName, componentName) => { } }; +const crossAxisProperty = { + x: 'height', + 'x-reverse': 'height', + y: 'width', + 'y-reverse': 'width', +}; + +const crossAxisOffsetProperty = { + x: 'top', + 'x-reverse': 'top', + y: 'left', + 'y-reverse': 'left', +}; + +const mainAxisProperty = { + x: 'width', + 'x-reverse': 'width', + y: 'height', + 'y-reverse': 'height', +}; + +const mainAxisMarginFromEnd = { + x: 'marginRight', + 'x-reverse': 'marginLeft', + y: 'marginTop', + 'y-reverse': 'marginBottom', +}; + +const mainAxisMarginFromStart = { + x: 'marginLeft', + 'x-reverse': 'marginRight', + y: 'marginBottom', + 'y-reverse': 'marginTop', +}; + +const mainAxisOffsetProperty = { + x: 'left', + 'x-reverse': 'right', + y: 'bottom', + 'y-reverse': 'top', +}; + +const mainAxisClientProperty = { + x: 'clientWidth', + 'x-reverse': 'clientWidth', + y: 'clientHeight', + 'y-reverse': 'clientHeight', +}; + +const mainAxisClientOffsetProperty = { + x: 'clientX', + 'x-reverse': 'clientX', + y: 'clientY', + 'y-reverse': 'clientY', +}; + +const reverseMainAxisOffsetProperty = { + x: 'right', + 'x-reverse': 'left', + y: 'top', + 'y-reverse': 'bottom', +}; + +const isMouseControlInverted = (axis) => axis === 'x-reverse' || axis === 'y'; + const getStyles = (props, context, state) => { const {slider} = context.muiTheme; const fillGutter = slider.handleSize / 2; const disabledGutter = slider.trackSize + slider.handleSizeDisabled / 2; const calcDisabledSpacing = props.disabled ? ` - ${disabledGutter}px` : ''; + const axis = props.axis; const styles = { slider: { touchCallout: 'none', userSelect: 'none', cursor: 'default', - height: slider.handleSizeActive, + [crossAxisProperty[axis]]: slider.handleSizeActive, + [mainAxisProperty[axis]]: '100%', position: 'relative', marginTop: 24, marginBottom: 48, }, track: { position: 'absolute', - top: (slider.handleSizeActive - slider.trackSize) / 2, - left: 0, - width: '100%', - height: slider.trackSize, + [crossAxisOffsetProperty[axis]]: (slider.handleSizeActive - slider.trackSize) / 2, + [mainAxisOffsetProperty[axis]]: 0, + [mainAxisProperty[axis]]: '100%', + [crossAxisProperty[axis]]: slider.trackSize, }, filledAndRemaining: { position: 'absolute', - top: 0, - height: '100%', + [crossAxisOffsetProperty]: 0, + [crossAxisProperty[axis]]: '100%', transition: transitions.easeOut(null, 'margin'), }, handle: { @@ -71,17 +138,27 @@ const getStyles = (props, context, state) => { position: 'absolute', cursor: 'pointer', pointerEvents: 'inherit', - top: 0, - left: state.percent === 0 ? '0%' : `${(state.percent * 100)}%`, + [crossAxisOffsetProperty[axis]]: 0, + [mainAxisOffsetProperty[axis]]: state.percent === 0 ? '0%' : `${(state.percent * 100)}%`, zIndex: 1, - margin: `${(slider.trackSize / 2)}px 0 0 0`, + margin: ({ + x: `${(slider.trackSize / 2)}px 0 0 0`, + 'x-reverse': `${(slider.trackSize / 2)}px 0 0 0`, + y: `0 0 0 ${(slider.trackSize / 2)}px`, + 'y-reverse': `0 0 0 ${(slider.trackSize / 2)}px`, + })[props.axis], width: slider.handleSize, height: slider.handleSize, backgroundColor: slider.selectionColor, backgroundClip: 'padding-box', border: '0px solid transparent', borderRadius: '50%', - transform: 'translate(-50%, -50%)', + transform: ({ + x: 'translate(-50%, -50%)', + 'x-reverse': 'translate(50%, -50%)', + y: 'translate(-50%, 50%)', + 'y-reverse': 'translate(-50%, -50%)', + })[props.axis], transition: `${transitions.easeOut('450ms', 'background')}, ${ transitions.easeOut('450ms', 'border-color')}, ${ @@ -135,17 +212,17 @@ const getStyles = (props, context, state) => { }, }; styles.filled = Object.assign({}, styles.filledAndRemaining, { - left: 0, + [mainAxisOffsetProperty[axis]]: 0, backgroundColor: (props.disabled) ? slider.trackColor : slider.selectionColor, - marginRight: fillGutter, - width: `calc(${(state.percent * 100)}%${calcDisabledSpacing})`, + [mainAxisMarginFromEnd[axis]]: fillGutter, + [mainAxisProperty[axis]]: `calc(${(state.percent * 100)}%${calcDisabledSpacing})`, }); styles.remaining = Object.assign({}, styles.filledAndRemaining, { - right: 0, + [reverseMainAxisOffsetProperty[axis]]: 0, backgroundColor: (state.hovered || state.focused) && !props.disabled ? slider.trackColorSelected : slider.trackColor, - marginLeft: fillGutter, - width: `calc(${((1 - state.percent) * 100)}%${calcDisabledSpacing})`, + [mainAxisMarginFromStart[axis]]: fillGutter, + [mainAxisProperty[axis]]: `calc(${((1 - state.percent) * 100)}%${calcDisabledSpacing})`, }); return styles; @@ -153,6 +230,10 @@ const getStyles = (props, context, state) => { class Slider extends Component { static propTypes = { + /** + * The axis on which the slider will slide. + */ + axis: PropTypes.oneOf(['x', 'x-reverse', 'y', 'y-reverse']), /** * The default value of the slider. */ @@ -223,6 +304,7 @@ class Slider extends Component { }; static defaultProps = { + axis: 'x', disabled: false, disableFocusRipple: false, max: 1, @@ -293,19 +375,39 @@ class Slider extends Component { }; onHandleKeyDown = (event) => { - const {min, max, step} = this.props; + const {axis, min, max, step} = this.props; let action; switch (keycode(event)) { case 'page down': - case 'left': case 'down': - action = 'decrease'; + if (axis === 'y-reverse') { + action = 'increase'; + } else { + action = 'decrease'; + } + break; + case 'left': + if (axis === 'x-reverse') { + action = 'increase'; + } else { + action = 'decrease'; + } break; case 'page up': - case 'right': case 'up': - action = 'increase'; + if (axis === 'y-reverse') { + action = 'decrease'; + } else { + action = 'increase'; + } + break; + case 'right': + if (axis === 'x-reverse') { + action = 'decrease'; + } else { + action = 'increase'; + } break; case 'home': action = 'home'; @@ -362,7 +464,13 @@ class Slider extends Component { } this.dragRunning = true; requestAnimationFrame(() => { - this.onDragUpdate(event, event.clientX - this.getTrackLeft()); + let pos; + if (isMouseControlInverted(this.props.axis)) { + pos = this.getTrackOffset() - event[mainAxisClientOffsetProperty[this.props.axis]]; + } else { + pos = event[mainAxisClientOffsetProperty[this.props.axis]] - this.getTrackOffset(); + } + this.onDragUpdate(event, pos); this.dragRunning = false; }); }; @@ -373,7 +481,13 @@ class Slider extends Component { } this.dragRunning = true; requestAnimationFrame(() => { - this.onDragUpdate(event, event.touches[0].clientX - this.getTrackLeft()); + let pos; + if (isMouseControlInverted(this.props.axis)) { + pos = this.getTrackOffset() - event.touches[0][mainAxisClientOffsetProperty[this.props.axis]]; + } else { + pos = event.touches[0][mainAxisClientOffsetProperty[this.props.axis]] - this.getTrackOffset(); + } + this.onDragUpdate(event, pos); this.dragRunning = false; }); }; @@ -438,8 +552,13 @@ class Slider extends Component { handleTouchStart = (event) => { if (!this.props.disabled && !this.state.dragging) { - const pos = event.touches[0].clientX - this.getTrackLeft(); - this.dragX(event, pos); + let pos; + if (isMouseControlInverted(this.props.axis)) { + pos = this.getTrackOffset() - event.touches[0][mainAxisClientOffsetProperty[this.props.axis]]; + } else { + pos = event.touches[0][mainAxisClientOffsetProperty[this.props.axis]] - this.getTrackOffset(); + } + this.dragTo(event, pos); // Since the touch event fired for the track and handle is child of // track, we need to manually propagate the event to the handle. @@ -459,8 +578,13 @@ class Slider extends Component { handleMouseDown = (event) => { if (!this.props.disabled && !this.state.dragging) { - const pos = event.clientX - this.getTrackLeft(); - this.dragX(event, pos); + let pos; + if (isMouseControlInverted(this.props.axis)) { + pos = this.getTrackOffset() - event[mainAxisClientOffsetProperty[this.props.axis]]; + } else { + pos = event[mainAxisClientOffsetProperty[this.props.axis]] - this.getTrackOffset(); + } + this.dragTo(event, pos); // Since the click event fired for the track and handle is child of // track, we need to manually propagate the event to the handle. @@ -480,8 +604,8 @@ class Slider extends Component { this.setState({hovered: false}); }; - getTrackLeft() { - return this.refs.track.getBoundingClientRect().left; + getTrackOffset() { + return this.refs.track.getBoundingClientRect()[mainAxisOffsetProperty[this.props.axis]]; } onDragStart(event) { @@ -502,11 +626,11 @@ class Slider extends Component { onDragUpdate(event, pos) { if (!this.state.dragging) return; - if (!this.props.disabled) this.dragX(event, pos); + if (!this.props.disabled) this.dragTo(event, pos); } - dragX(event, pos) { - const max = this.refs.track.clientWidth; + dragTo(event, pos) { + const max = this.refs.track[mainAxisClientProperty[this.props.axis]]; if (pos < 0) pos = 0; else if (pos > max) pos = max; this.updateWithChangeEvent(event, pos / max); } diff --git a/src/Slider/Slider.spec.js b/src/Slider/Slider.spec.js index 8441c580ae84a7..399dc00acd9b64 100644 --- a/src/Slider/Slider.spec.js +++ b/src/Slider/Slider.spec.js @@ -174,107 +174,334 @@ describe('<Slider />', () => { assert.isFalse(wrapper.state().hovered); }); - it('simulates keydown event with a non tracked key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const event = { - keyCode: keycode('enter'), - preventDefault: sinon.spy(), - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.notCalled(event.preventDefault); - }); - - it('simulates keydown event for the end key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const event = { - keyCode: keycode('end'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.calledOnce(handleChange); - assert.strictEqual(wrapper.state().percent, 1); - }); - - it('simulates keydown event for the up arrow key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext(<Slider name="slider" onChange={handleChange} />); - const previousPercent = wrapper.state().percent; - const event = { - keyCode: keycode('up'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.calledOnce(handleChange); - assert.isAbove(wrapper.state().percent, previousPercent); - }); - - it('simulates keydown event for the right arrow key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const previousPercent = wrapper.state().percent; - const event = { - keyCode: keycode('right'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.calledOnce(handleChange); - assert.isAbove(wrapper.state().percent, previousPercent); - }); - - it('simulates keydown event for the home key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const event = { - keyCode: keycode('home'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.notCalled(handleChange); - assert.strictEqual(wrapper.state().percent, 0); - }); - - it('simulates keydown event for the down arrow key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const event = { - keyCode: keycode('down'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.notCalled(handleChange); - assert.strictEqual(wrapper.state().percent, 0); - }); - - it('simulates keydown event for the left arrow key', () => { - const handleChange = sinon.spy(); - const wrapper = shallowWithContext( - <Slider name="slider" onChange={handleChange} /> - ); - const event = { - keyCode: keycode('left'), - preventDefault: function() {}, - }; - - getThumbElement(wrapper).simulate('keydown', event); - assert.notCalled(handleChange); - assert.strictEqual(wrapper.state().percent, 0); + describe('keydown', () => { + it('simulates keydown event with a non tracked key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('enter'), + preventDefault: sinon.spy(), + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(event.preventDefault); + }); + + it('simulates the end key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('end'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.strictEqual(wrapper.state().percent, 1); + }); + + it('simulates the up arrow key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext(<Slider name="slider" onChange={handleChange} />); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('up'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the up arrow key on an x-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext(<Slider name="slider" axis="x-reverse" onChange={handleChange} />); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('up'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the up arrow key on a y axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext(<Slider name="slider" axis="y" onChange={handleChange} />); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('up'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the up arrow key on a y-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext(<Slider name="slider" axis="y-reverse" onChange={handleChange} />); + const event = { + keyCode: keycode('up'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the right arrow key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('right'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the right arrow key on an x-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="x-reverse" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('right'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the right arrow key on an y axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y" onChange={handleChange} /> + ); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('right'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the right arrow key on an y-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y-reverse" onChange={handleChange} /> + ); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('right'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the home key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('home'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the home key on a x-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="x-reverse" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('home'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the home key on a y axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('home'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the home key on a y-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('home'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the down arrow key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('down'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the down arrow key on a x-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="x-reverse" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('down'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the down arrow key on a y axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('down'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the down arrow key on a y-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y-reverse" onChange={handleChange} /> + ); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('down'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the left arrow key', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('left'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the left arrow key for an x-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="x-reverse" onChange={handleChange} /> + ); + const previousPercent = wrapper.state().percent; + const event = { + keyCode: keycode('left'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.calledOnce(handleChange); + assert.isAbove(wrapper.state().percent, previousPercent); + }); + + it('simulates the left arrow key for a y axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('left'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); + + it('simulates the left arrow key for a y-reverse axis slider', () => { + const handleChange = sinon.spy(); + const wrapper = shallowWithContext( + <Slider name="slider" axis="y-reverse" onChange={handleChange} /> + ); + const event = { + keyCode: keycode('left'), + preventDefault: function() {}, + }; + + getThumbElement(wrapper).simulate('keydown', event); + assert.notCalled(handleChange); + assert.strictEqual(wrapper.state().percent, 0); + }); }); });