Skip to main content

euv_ui/component/progress/view/
fn.rs

1use super::*;
2
3/// A determinate progress bar component bound to a percentage signal.
4///
5/// Renders a `c_progress_container` track holding a
6/// `c_progress_bar_fill` element whose inline `width` is driven by the
7/// `percent` signal, plus the label and a numeric readout. A running bar
8/// adds the animated `c_progress_bar_running` class; a settled one falls
9/// back to `c_progress_bar_stopped` so the fill keeps its inline width
10/// without re-running the keyframe animation.
11///
12/// # Arguments
13///
14/// - `VirtualNode<EuvProgressProps>` - The props node containing bar configuration.
15///
16/// # Returns
17///
18/// - `VirtualNode` - A styled progress bar.
19#[component]
20pub fn euv_progress(node: VirtualNode<EuvProgressProps>) -> VirtualNode {
21    let EuvProgressProps {
22        percent,
23        label: label_text,
24        active,
25    }: EuvProgressProps = node.try_get_props().unwrap_or_default();
26    let clamped: f64 = progress_percent_clamp(percent.get());
27    let fill_style: String = format!("width: {clamped}%;");
28    let fill_style_ref: &str = fill_style.as_str();
29    let readout: String = format!("{clamped:.0}%");
30    html! {
31        div {
32            div {
33                class: c_progress_container()
34                div {
35                    class: c_progress_bar_fill()
36                    class: if { active } {
37                        c_progress_bar_running()
38                    } else {
39                        c_progress_bar_stopped()
40                    }
41                    style: fill_style_ref
42                }
43            }
44            div {
45                class: c_euv_slider_header()
46                span {
47                    class: c_form_label()
48                    label_text
49                }
50                span {
51                    class: c_binding_slider_value()
52                    readout
53                }
54            }
55        }
56    }
57}
58
59/// Clamps a raw percentage into the `0.0..=100.0` range a bar can render.
60///
61/// NaN collapses to `0.0` — a `Signal<f64>` carrying NaN (an
62/// unreported upload size, a `0.0 / 0.0` ratio) would otherwise emit a
63/// `width: NaN%` declaration the browser drops silently.
64///
65/// # Arguments
66///
67/// - `f64` - The raw percentage supplied by the caller.
68///
69/// # Returns
70///
71/// - `f64` - The percentage clamped into the `0.0..=100.0` range.
72pub fn progress_percent_clamp(percent: f64) -> f64 {
73    if percent.is_nan() {
74        return 0.0;
75    }
76    percent.clamp(0.0, PERCENT_MAX)
77}