@@ -3,16 +3,24 @@ import styled from 'styled-components';
3
3
4
4
const RangeHeader = styled . div `
5
5
display: flex;
6
- justify-content: flex-end ;
6
+ justify-content: space-between ;
7
7
` ;
8
8
9
9
const StyledRange = styled . div `
10
+ position: relative;
10
11
border-radius: 3px;
11
12
background: #dddddd;
12
- margin: 5px;
13
13
height: 15px;
14
14
` ;
15
15
16
+ const StyledRangeProgress = styled . div `
17
+ border-radius: 3px;
18
+ position: absolute;
19
+ height: 100%;
20
+ opacity: 0.5;
21
+ background: #823eb7;
22
+ ` ;
23
+
16
24
const StyledThumb = styled . div `
17
25
width: 10px;
18
26
height: 25px;
@@ -24,26 +32,41 @@ const StyledThumb = styled.div`
24
32
cursor: pointer;
25
33
` ;
26
34
27
- const getPercentage = ( current , max ) => ( 100 * current ) / max ;
35
+ const getPercentage = ( current , min , max ) =>
36
+ ( ( current - min ) / ( max - min ) ) * 100 ;
28
37
29
- const getValue = ( percentage , max ) => ( max / 100 ) * percentage ;
38
+ const getValue = ( percentage , min , max ) =>
39
+ ( ( max - min ) / 100 ) * percentage + min ;
30
40
31
41
const getLeft = percentage => `calc(${ percentage } % - 5px)` ;
32
42
43
+ const getWidth = percentage => `${ percentage } %` ;
44
+
33
45
const Range = ( {
34
46
initial,
47
+ min = 0 ,
35
48
max,
36
49
formatFn = number => number . toFixed ( 0 ) ,
37
50
onChange,
38
51
} ) => {
39
- const initialPercentage = getPercentage ( initial , max ) ;
52
+ const initialPercentage = getPercentage ( initial , min , max ) ;
40
53
41
54
const rangeRef = React . useRef ( ) ;
55
+ const rangeProgressRef = React . useRef ( ) ;
42
56
const thumbRef = React . useRef ( ) ;
43
57
const currentRef = React . useRef ( ) ;
44
58
45
59
const diff = React . useRef ( ) ;
46
60
61
+ const handleUpdate = React . useCallback (
62
+ ( value , percentage ) => {
63
+ thumbRef . current . style . left = getLeft ( percentage ) ;
64
+ rangeProgressRef . current . style . width = getWidth ( percentage ) ;
65
+ currentRef . current . textContent = formatFn ( value ) ;
66
+ } ,
67
+ [ formatFn ]
68
+ ) ;
69
+
47
70
const handleMouseMove = event => {
48
71
let newX =
49
72
event . clientX -
@@ -63,11 +86,10 @@ const Range = ({
63
86
newX = end ;
64
87
}
65
88
66
- const newPercentage = getPercentage ( newX , end ) ;
67
- const newValue = getValue ( newPercentage , max ) ;
89
+ const newPercentage = getPercentage ( newX , start , end ) ;
90
+ const newValue = getValue ( newPercentage , min , max ) ;
68
91
69
- thumbRef . current . style . left = getLeft ( newPercentage ) ;
70
- currentRef . current . textContent = formatFn ( newValue ) ;
92
+ handleUpdate ( newValue , newPercentage ) ;
71
93
72
94
onChange ( newValue ) ;
73
95
} ;
@@ -85,19 +107,23 @@ const Range = ({
85
107
document . addEventListener ( 'mouseup' , handleMouseUp ) ;
86
108
} ;
87
109
110
+ React . useLayoutEffect ( ( ) => {
111
+ handleUpdate ( initial , initialPercentage ) ;
112
+ } , [ initial , initialPercentage , handleUpdate ] ) ;
113
+
88
114
return (
89
115
< >
90
116
< RangeHeader >
91
- < strong ref = { currentRef } > { formatFn ( initial ) } </ strong >
92
- /
93
- { max }
117
+ < div > { formatFn ( min ) } </ div >
118
+ < div >
119
+ < strong ref = { currentRef } />
120
+ /
121
+ { formatFn ( max ) }
122
+ </ div >
94
123
</ RangeHeader >
95
124
< StyledRange ref = { rangeRef } >
96
- < StyledThumb
97
- style = { { left : getLeft ( initialPercentage ) } }
98
- ref = { thumbRef }
99
- onMouseDown = { handleMouseDown }
100
- />
125
+ < StyledRangeProgress ref = { rangeProgressRef } />
126
+ < StyledThumb ref = { thumbRef } onMouseDown = { handleMouseDown } />
101
127
</ StyledRange >
102
128
</ >
103
129
) ;
@@ -107,6 +133,7 @@ const App = () => (
107
133
< div >
108
134
< Range
109
135
initial = { 10 }
136
+ min = { 5 }
110
137
max = { 25 }
111
138
formatFn = { number => number . toFixed ( 2 ) }
112
139
onChange = { value => console . log ( value ) }
0 commit comments