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