Skip to main content

dioxus_element_plug/components/
input_number.rs

1use dioxus::prelude::*;
2
3/// InputNumber props
4#[derive(Props, Clone, PartialEq)]
5pub struct InputNumberProps {
6    #[props(default = 0.0)]
7    pub model_value: f64,
8
9    #[props(default = f64::MIN)]
10    pub min: f64,
11
12    #[props(default = f64::MAX)]
13    pub max: f64,
14
15    #[props(default = 1.0)]
16    pub step: f64,
17
18    #[props(default = false)]
19    pub step_strictly: bool,
20
21    #[props(default = false)]
22    pub disabled: bool,
23
24    #[props(default = false)]
25    pub controls: bool,
26
27    #[props(default = "default".to_string())]
28    pub size: String,
29
30    #[props(default)]
31    pub precision: Option<u32>,
32
33    #[props(default = "large".to_string())]
34    pub controls_position: String,
35
36    #[props(default)]
37    pub on_change: Option<EventHandler<f64>>,
38
39    #[props(default)]
40    pub class: Option<String>,
41
42    #[props(default)]
43    pub style: Option<String>,
44}
45
46/// InputNumber component for numeric input with controls
47#[component]
48pub fn InputNumber(props: InputNumberProps) -> Element {
49    let mut class_names = vec!["el-input-number".to_string()];
50    if props.disabled { class_names.push("is-disabled".to_string()); }
51    class_names.push(format!("el-input-number--{}", props.size));
52    if let Some(ref c) = props.class { class_names.push(c.clone()); }
53
54    rsx! {
55        div {
56            class: "{class_names.join(\" \")}",
57            style: props.style.clone().unwrap_or_default(),
58            if props.controls {
59                span {
60                    class: "el-input-number__decrease",
61                    role: "button",
62                    onclick: move |_| {
63                        if !props.disabled {
64                            let new_val = (props.model_value - props.step).max(props.min);
65                            if let Some(handler) = props.on_change {
66                                handler.call(new_val);
67                            }
68                        }
69                    },
70                    i { class: "el-icon-minus" }
71                }
72            }
73            div {
74                class: "el-input",
75                input {
76                    class: "el-input__inner",
77                    r#type: "number",
78                    value: "{props.model_value}",
79                    min: "{props.min}",
80                    max: "{props.max}",
81                    step: "{props.step}",
82                    disabled: props.disabled,
83                    onchange: move |e| {
84                        if let Ok(val) = e.value().parse::<f64>() {
85                            if let Some(handler) = props.on_change {
86                                handler.call(val);
87                            }
88                        }
89                    },
90                }
91            }
92            if props.controls {
93                span {
94                    class: "el-input-number__increase",
95                    role: "button",
96                    onclick: move |_| {
97                        if !props.disabled {
98                            let new_val = (props.model_value + props.step).min(props.max);
99                            if let Some(handler) = props.on_change {
100                                handler.call(new_val);
101                            }
102                        }
103                    },
104                    i { class: "el-icon-plus" }
105                }
106            }
107        }
108    }
109}