1- import { useCallback , useEffect , useRef } from " preact/hooks" ;
2- import { cn } from " ~web/utils/helpers" ;
1+ import { useCallback , useEffect , useRef } from ' preact/hooks' ;
2+ import { cn } from ' ~web/utils/helpers' ;
33
44interface SliderProps {
55 className ?: string ;
@@ -21,15 +21,26 @@ export const Slider = ({
2121 const refThumb = useRef < HTMLSpanElement > ( null ) ;
2222 const refLastValue = useRef < number > ( value ) ;
2323
24- const updateThumbPosition = useCallback ( ( value : number ) => {
25- if ( ! refThumb . current ) return ;
24+ // TODO(Alexis): This one needs some rework.
25+ // Aside the fact that this needs to be a computed value
26+ // rather than a side-effect, we need this component
27+ // to be "controlled" rather than uncontrolled at the same time
28+ // Basically we want to either use value or lastValue but not both.
29+ const updateThumbPosition = useCallback (
30+ ( value : number ) => {
31+ if ( ! refThumb . current ) return ;
2632
27- const range = Math . max ( 1 , max - min ) ;
28- const valueOffset = value - min ;
29- const percentage = min === max ? 0 : Math . min ( 100 , Math . round ( ( valueOffset / range ) * 100 ) ) ;
33+ const range = Math . max ( 1 , max - min ) ;
34+ const valueOffset = value - min ;
35+ const percentage =
36+ min === max
37+ ? 0
38+ : Math . min ( 100 , Math . round ( ( valueOffset / range ) * 100 ) ) ;
3039
31- refThumb . current . style . setProperty ( 'left' , `${ percentage } %` ) ;
32- } , [ min , max ] ) ;
40+ refThumb . current . style . setProperty ( 'left' , `${ percentage } %` ) ;
41+ } ,
42+ [ min , max ] ,
43+ ) ;
3344
3445 /**
3546 * biome-ignore lint/correctness/useExhaustiveDependencies:
@@ -39,31 +50,30 @@ export const Slider = ({
3950 updateThumbPosition ( value ) ;
4051 } , [ min , max , value ] ) ;
4152
42- const handleChange = useCallback ( ( e : Event ) => {
43- const target = e . target as HTMLInputElement ;
44- const newValue = Number . parseInt ( target . value , 10 ) ;
53+ const handleChange = useCallback (
54+ ( e : Event ) => {
55+ const target = e . target as HTMLInputElement ;
56+ const newValue = Number . parseInt ( target . value , 10 ) ;
4557
46- if ( newValue >= totalUpdates ) {
47- return ;
48- }
58+ if ( newValue >= totalUpdates ) {
59+ return ;
60+ }
4961
50- if ( refLastValue . current !== newValue ) {
51- refLastValue . current = newValue ;
52- updateThumbPosition ( newValue ) ;
53- onChange ( e ) ;
54- }
55- } , [ onChange , updateThumbPosition , totalUpdates ] ) ;
62+ if ( refLastValue . current !== newValue ) {
63+ refLastValue . current = newValue ;
64+ updateThumbPosition ( newValue ) ;
65+ onChange ( e ) ;
66+ }
67+ } ,
68+ [ onChange , updateThumbPosition , totalUpdates ] ,
69+ ) ;
5670
5771 return (
5872 < div
5973 onMouseDown = { ( e ) => {
6074 e . stopPropagation ( ) ;
6175 } }
62- className = { cn (
63- 'react-scan-slider relative' ,
64- 'flex-1' ,
65- className
66- ) }
76+ className = { cn ( 'react-scan-slider relative' , 'flex-1' , className ) }
6777 >
6878 < input
6979 type = "range"
@@ -79,15 +89,10 @@ export const Slider = ({
7989 'rounded-lg' ,
8090 'appearance-none' ,
8191 'cursor-pointer' ,
82- className
92+ className ,
8393 ) }
8494 />
85- < div
86- className = { cn (
87- 'absolute inset-0 right-2' ,
88- 'pointer-events-none' ,
89- ) }
90- >
95+ < div className = { cn ( 'absolute inset-0 right-2' , 'pointer-events-none' ) } >
9196 < span ref = { refThumb } />
9297 </ div >
9398 </ div >
0 commit comments