Skip to main content

euv_ui/component/slider/view/
impl.rs

1use super::*;
2
3/// Inherent implementation of [`EuvSliderHelpers`].
4impl EuvSliderHelpers {
5    /// Maps `value` onto the `0.0..=100.0` percentage range spanned by
6    /// `min..=max`.
7    ///
8    /// A degenerate range (`min == max`) reports `0.0` instead of
9    /// dividing by zero, and values outside the range are clamped so a
10    /// mis-typed signal can never produce a nonsensical percentage.
11    ///
12    /// # Arguments
13    ///
14    /// - `f64` - The value to map.
15    ///
16    /// # Returns
17    ///
18    /// - `f64` - The percentage position of `value` within the range.
19    pub fn percent(value: f64, min: f64, max: f64) -> f64 {
20        if max <= min {
21            return 0.0;
22        }
23        let ratio: f64 = (value - min) / (max - min);
24        let clamped: f64 = ratio.clamp(0.0, 1.0);
25        clamped * PERCENT_SCALE
26    }
27
28    /// Builds an input handler that writes the range value into `signal`.
29    ///
30    /// The parsed value is clamped to the `[min, max]` window so a
31    /// keyboard-driven overshoot cannot push the signal outside the
32    /// range the component advertises.
33    ///
34    /// # Arguments
35    ///
36    /// - `Signal<f64>` - The signal updated with the new value.
37    /// - `f64` - The low end of the accepted range.
38    ///
39    /// # Returns
40    ///
41    /// - `Option<Rc<dyn Fn(Event)>>` - An input handler writing the
42    ///   clamped range value into the signal.
43    pub fn on_slider_input(signal: Signal<f64>, min: f64, max: f64) -> Option<Rc<dyn Fn(Event)>> {
44        Some(Rc::new(move |event: Event| {
45            let raw: Option<f64> = event.target().and_then(|target: EventTarget| {
46                if let Ok(input) = target.dyn_into::<HtmlInputElement>() {
47                    return input.value().parse::<f64>().ok();
48                }
49                None
50            });
51            if let Some(parsed) = raw {
52                signal.set(parsed.clamp(min, max));
53            }
54        }))
55    }
56}