diff --git a/src/UI_Components/Slider.re b/src/UI_Components/Slider.re index a7ab909d4..8fef50dd1 100644 --- a/src/UI_Components/Slider.re +++ b/src/UI_Components/Slider.re @@ -34,16 +34,16 @@ let createElement = ~thumbColor=Colors.gray, (), ) => - component(slots => { - let (slideRef, setSlideRefOption, slots) = - React.Hooks.state(None, slots); - let (thumbRef, setThumbRefOption, slots) = - React.Hooks.state(None, slots); - let (isActive, setActive, slots) = React.Hooks.state(false, slots); + component(hooks => { + let (slideRef, setSlideRefOption, hooks) = + React.Hooks.state(None, hooks); + let (thumbRef, setThumbRefOption, hooks) = + React.Hooks.state(None, hooks); + let (isActive, setActive, hooks) = React.Hooks.state(false, hooks); /* Initial value is used to detect if the 'value' parameter ever changes */ - let (initialValue, setInitialValue, slots) = - React.Hooks.state(value, slots); - let (v, setV, slots) = React.Hooks.state(value, slots); + let (initialValue, setInitialValue, hooks) = + React.Hooks.state(value, hooks); + let (v, setV, hooks) = React.Hooks.state(value, hooks); /* * If the slider value is updated (controlled), @@ -86,6 +86,65 @@ let createElement = | _ => None }; + let sliderUpdate = (w, startPosition, endPosition, mouseX, mouseY) => { + let mousePosition = vertical ? mouseY : mouseX; + let thumbPosition = + clamp(mousePosition, startPosition, endPosition) -. startPosition; + + let normalizedValue = + thumbPosition /. w *. (maximumValue -. minimumValue) +. minimumValue; + setV(normalizedValue); + onValueChanged(normalizedValue); + }; + + let sliderComplete = () => { + setActive(false); + }; + + let hooks = + React.Hooks.effect( + Always, + () => { + let isCaptured = isActive; + + if (isCaptured) { + switch (slideRef, availableWidth) { + | (Some(slider), Some(w)) => + let sliderDimensions: BoundingBox2d.t = slider#getBoundingBox(); + + let startPosition = + vertical + ? Vec2.get_y(sliderDimensions.min) + : Vec2.get_x(sliderDimensions.min); + let endPosition = startPosition +. w; + + Mouse.setCapture( + ~onMouseMove= + evt => + sliderUpdate( + w, + startPosition, + endPosition, + evt.mouseX, + evt.mouseY, + ), + ~onMouseUp=_evt => sliderComplete(), + (), + ); + | _ => () + }; + }; + + Some( + () => + if (isCaptured) { + Mouse.releaseCapture(); + }, + ); + }, + hooks, + ); + let onMouseDown = (evt: NodeEvents.mouseButtonEventParams) => switch (slideRef, availableWidth) { | (Some(slider), Some(w)) => @@ -97,40 +156,8 @@ let createElement = : Vec2.get_x(sliderDimensions.min); let endPosition = startPosition +. w; - let getValue = x => - if (x < startPosition) { - startPosition; - } else if (x > endPosition) { - endPosition; - } else { - x; - }; - - let update = (mouseX, mouseY) => { - let mousePosition = vertical ? mouseY : mouseX; - let thumbPosition = getValue(mousePosition) -. startPosition; - - let normalizedValue = - thumbPosition - /. w - *. (maximumValue -. minimumValue) - +. minimumValue; - setV(normalizedValue); - onValueChanged(normalizedValue); - }; - - update(evt.mouseX, evt.mouseY); + sliderUpdate(w, startPosition, endPosition, evt.mouseX, evt.mouseY); setActive(true); - - Mouse.setCapture( - ~onMouseMove=evt => update(evt.mouseX, evt.mouseY), - ~onMouseUp= - _evt => { - Mouse.releaseCapture(); - setActive(false); - }, - (), - ); | _ => () }; @@ -185,7 +212,7 @@ let createElement = ]; ( - slots, + hooks, setSlideRef(r)}>