perspective_viewer/components/form/
number_range_field.rs1use web_sys::HtmlInputElement;
14use yew::{Callback, Properties, function_component, html, use_callback, use_node_ref};
15
16use crate::components::form::optional_field::OptionalField;
17
18#[derive(Properties, Debug, PartialEq, Clone)]
19pub struct NumberRangeFieldProps {
20 pub label: String,
21 pub current_value: Option<(f64, f64)>,
22 pub default: (f64, f64),
23 pub on_change: Callback<Option<(f64, f64)>>,
24
25 #[prop_or_default]
26 pub min: Option<f64>,
27
28 #[prop_or_default]
29 pub max: Option<f64>,
30
31 #[prop_or_default]
32 pub step: Option<f64>,
33}
34
35#[function_component(NumberRangeField)]
36pub fn number_range_field(props: &NumberRangeFieldProps) -> yew::Html {
37 let ref1 = use_node_ref();
38 let ref2 = use_node_ref();
39 let parse_number_input = use_callback(
40 (ref1.clone(), ref2.clone(), props.on_change.clone()),
41 |_, deps| {
42 deps.2.emit(Some((
43 deps.0.cast::<HtmlInputElement>().unwrap().value_as_number(),
44 deps.1.cast::<HtmlInputElement>().unwrap().value_as_number(),
45 )));
46 },
47 );
48
49 html! {
50 <OptionalField
51 label={props.label.clone()}
52 on_check={props.on_change.reform(|_| None)}
53 checked={props.current_value.map(|val| val != props.default).unwrap_or_default()}
54 >
55 <input
56 type="number"
57 class="parameter parameter-min"
58 ref={ref1}
59 min={props.min.map(|val| val.to_string())}
60 max={props.max.map(|val| val.to_string())}
61 step={props.step.map(|val| val.to_string())}
62 value={props.current_value.unwrap_or(props.default).0.to_string()}
63 oninput={parse_number_input.clone()}
64 />
65 <input
66 type="number"
67 class="parameter parameter-max"
68 ref={ref2}
69 min={props.min.map(|val| val.to_string())}
70 max={props.max.map(|val| val.to_string())}
71 step={props.step.map(|val| val.to_string())}
72 value={props.current_value.unwrap_or(props.default).1.to_string()}
73 oninput={parse_number_input}
74 />
75 </OptionalField>
76 }
77}