src/Slider.js
/**
* @file melon/Slider
* @author cxtom <[email protected]>
*/
import React, {PropTypes} from 'react';
import ReactDOM from 'react-dom';
import InputComponent from 'melon-core/InputComponent';
import Validity from 'melon-core/Validity';
import {create} from 'melon-core/classname/cxBuilder';
import domUtil from './common/util/dom';
import SliderBar from './slider/Bar';
import getNewValue from './slider/getNewValue';
const cx = create('Slider');
export default class Slider extends InputComponent {
constructor(props, context) {
super(props, context);
this.onMouseDown = this.onMouseDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onMouseChange = this.onMouseChange.bind(this);
const {maximum, minimum} = props;
const value = this.state.value;
this.state.value = value > maximum ? maximum : value;
this.state.value = value < minimum ? minimum : value;
this.state = {
...this.state,
active: false
};
}
componentWillUnmount() {
this.slider = null;
}
onMouseUp() {
domUtil.off(window, 'mouseup', this.onMouseUp);
domUtil.off(window, 'mousemove', this.onMouseChange);
this.setState({active: false});
}
onMouseChange({clientX}) {
const {maximum, minimum, step} = this.props;
const value = this.state.value;
const newValue = getNewValue(this.slider, clientX, maximum, minimum, step);
if (value === newValue || newValue > maximum || newValue < minimum) {
return;
}
this.onSliderChange(newValue);
}
onSliderChange(newValue) {
super.onChange({
type: 'change',
target: this,
value: newValue
});
}
onMouseDown(e) {
if (this.props.disable || this.props.readOnly) {
return;
}
domUtil.on(window, 'mouseup', this.onMouseUp);
domUtil.on(window, 'mousemove', this.onMouseChange);
this.onMouseChange(e);
this.setState({active: true});
}
getSliderValue() {
return this.state.value;
}
renderHiddenInput() {
const value = this.state.value;
return (
<input
type="hidden"
value={value} />
);
}
renderBar() {
return (
<SliderBar
{...this.props}
ref={slider => {
this.slider = ReactDOM.findDOMNode(slider);
}}
active={this.state.active}
onMouseDown={this.onMouseDown}
value={this.getSliderValue()} />
);
}
render() {
const validity = this.state.validity;
/* eslint-disable fecs-minimum-vars-per-destructure */
const {
width,
style = {}
} = this.props;
const className = cx(this.props)
.addStates(this.getStyleStates())
.build();
return (
<div
style={{...style, width}}
className={className}>
{this.renderHiddenInput()}
{this.renderBar()}
<Validity validity={validity} />
</div>
);
}
}
Slider.displayName = 'Slider';
Slider.defaultProps = {
...InputComponent.defaultProps,
defaultValue: 0,
maximum: 100,
minimum: 0,
step: 1,
width: '100%',
height: 2
};
Slider.propTypes = {
...InputComponent.propTypes,
defaultValue: PropTypes.number,
value: PropTypes.number,
maximum: PropTypes.number,
minimum: PropTypes.number,
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
pointerSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
};