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