@@ -3,16 +3,24 @@ import styled from 'styled-components';
33
44const RangeHeader = styled . div `
55 display: flex;
6- justify-content: flex-end ;
6+ justify-content: space-between ;
77` ;
88
99const StyledRange = styled . div `
10+ position: relative;
1011 border-radius: 3px;
1112 background: #dddddd;
12- margin: 5px;
1313 height: 15px;
1414` ;
1515
16+ const StyledRangeProgress = styled . div `
17+ border-radius: 3px;
18+ position: absolute;
19+ height: 100%;
20+ opacity: 0.5;
21+ background: #823eb7;
22+ ` ;
23+
1624const StyledThumb = styled . div `
1725 width: 10px;
1826 height: 25px;
@@ -24,26 +32,41 @@ const StyledThumb = styled.div`
2432 cursor: pointer;
2533` ;
2634
27- const getPercentage = ( current , max ) => ( 100 * current ) / max ;
35+ const getPercentage = ( current , min , max ) =>
36+ ( ( current - min ) / ( max - min ) ) * 100 ;
2837
29- const getValue = ( percentage , max ) => ( max / 100 ) * percentage ;
38+ const getValue = ( percentage , min , max ) =>
39+ ( ( max - min ) / 100 ) * percentage + min ;
3040
3141const getLeft = percentage => `calc(${ percentage } % - 5px)` ;
3242
43+ const getWidth = percentage => `${ percentage } %` ;
44+
3345const Range = ( {
3446 initial,
47+ min = 0 ,
3548 max,
3649 formatFn = number => number . toFixed ( 0 ) ,
3750 onChange,
3851} ) => {
39- const initialPercentage = getPercentage ( initial , max ) ;
52+ const initialPercentage = getPercentage ( initial , min , max ) ;
4053
4154 const rangeRef = React . useRef ( ) ;
55+ const rangeProgressRef = React . useRef ( ) ;
4256 const thumbRef = React . useRef ( ) ;
4357 const currentRef = React . useRef ( ) ;
4458
4559 const diff = React . useRef ( ) ;
4660
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+
4770 const handleMouseMove = event => {
4871 let newX =
4972 event . clientX -
@@ -63,11 +86,10 @@ const Range = ({
6386 newX = end ;
6487 }
6588
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 ) ;
6891
69- thumbRef . current . style . left = getLeft ( newPercentage ) ;
70- currentRef . current . textContent = formatFn ( newValue ) ;
92+ handleUpdate ( newValue , newPercentage ) ;
7193
7294 onChange ( newValue ) ;
7395 } ;
@@ -85,19 +107,23 @@ const Range = ({
85107 document . addEventListener ( 'mouseup' , handleMouseUp ) ;
86108 } ;
87109
110+ React . useLayoutEffect ( ( ) => {
111+ handleUpdate ( initial , initialPercentage ) ;
112+ } , [ initial , initialPercentage , handleUpdate ] ) ;
113+
88114 return (
89115 < >
90116 < 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 >
94123 </ RangeHeader >
95124 < 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 } />
101127 </ StyledRange >
102128 </ >
103129 ) ;
@@ -107,6 +133,7 @@ const App = () => (
107133 < div >
108134 < Range
109135 initial = { 10 }
136+ min = { 5 }
110137 max = { 25 }
111138 formatFn = { number => number . toFixed ( 2 ) }
112139 onChange = { value => console . log ( value ) }
0 commit comments