1+ import React from 'react' ;
2+ import PropTypes from 'prop-types' ;
3+ import { forceNumber } from './utils' ;
4+ /**
5+ * This is an <input type=range> that steps up and down on click
6+ * instead of jumping immediately to the new value.
7+ *
8+ * Based on zcorpan's solution here:
9+ * https://stackoverflow.com/a/51988783/173630
10+ */
11+
12+ export default class RangeStepInput extends React . Component {
13+ constructor ( props ) {
14+ super ( props ) ;
15+ this . state = {
16+ isMouseDown : false ,
17+ isDragging : false
18+ } ;
19+ this . onInput = this . onInput . bind ( this ) ;
20+ this . onMouseDown = this . onMouseDown . bind ( this ) ;
21+ this . onMouseUp = this . onMouseUp . bind ( this ) ;
22+ this . onMouseMove = this . onMouseMove . bind ( this ) ;
23+ }
24+
25+ render ( ) {
26+ return React . createElement ( "input" , {
27+ type : "range" ,
28+ className : this . props . className ,
29+ min : this . props . min ,
30+ max : this . props . max ,
31+ step : this . props . step ,
32+ value : this . props . value ,
33+ name : this . props . name ,
34+ id : this . props . id ,
35+ onChange : this . props . onChange ,
36+ onMouseDown : this . onMouseDown ,
37+ onMouseUp : this . onMouseUp ,
38+ onMouseMove : this . onMouseMove ,
39+ onClick : this . onClick ,
40+ onInput : this . onInput
41+ } ) ;
42+ }
43+
44+ onMouseDown ( ) {
45+ this . setState ( {
46+ isMouseDown : true
47+ } ) ;
48+ }
49+
50+ onMouseUp ( ) {
51+ this . setState ( {
52+ isMouseDown : false ,
53+ isDragging : false
54+ } ) ;
55+ }
56+
57+ onMouseMove ( ) {
58+ if ( this . state . isMouseDown ) {
59+ this . setState ( {
60+ isDragging : true
61+ } ) ;
62+ }
63+ }
64+
65+ onInput ( e ) {
66+ const step = forceNumber ( e . target . step ) ;
67+ const newVal = forceNumber ( e . target . value ) ;
68+ const oldVal = this . props . value ;
69+
70+ if ( // Disable the oninput filter with the user is dragging
71+ // the slider's knob.
72+ ! ( this . state . isMouseDown && this . state . isDragging ) && oldVal ) {
73+ e . target . value = newVal > oldVal ? oldVal + step : oldVal - step ;
74+ }
75+ }
76+
77+ }
78+ RangeStepInput . propTypes = {
79+ value : PropTypes . number . isRequired ,
80+ onChange : PropTypes . func . isRequired ,
81+ step : PropTypes . number . isRequired ,
82+ className : PropTypes . string ,
83+ min : PropTypes . number ,
84+ max : PropTypes . number ,
85+ id : PropTypes . string ,
86+ name : PropTypes . string
87+ } ;
0 commit comments