perspective_viewer/components/form/
select_field.rs1use std::fmt::{Debug, Display};
14use std::rc::Rc;
15
16use itertools::Itertools;
17use strum::IntoEnumIterator;
18use yew::{Callback, Properties, function_component, html};
19
20use crate::components::containers::select::{Select, SelectItem};
21use crate::components::form::optional_field::OptionalField;
22
23#[derive(Properties, Debug, PartialEq, Clone)]
24pub struct SelectEnumFieldProps<T>
25where
26 T: IntoEnumIterator + Display + Default + PartialEq + Clone + 'static,
27{
28 pub label: String,
29 pub current_value: Option<T>,
30 pub on_change: Callback<Option<T>>,
31
32 #[prop_or_default]
33 pub default_value: Option<T>,
34
35 #[prop_or_default]
36 pub disabled: bool,
37}
38
39#[function_component(SelectEnumField)]
40pub fn select_enum_field<T>(props: &SelectEnumFieldProps<T>) -> yew::Html
41where
42 T: IntoEnumIterator + Debug + Display + Default + PartialEq + Clone + 'static,
43{
44 let values = yew::use_memo((), |_| T::iter().map(SelectItem::Option).collect_vec());
45 let selected = props.current_value.clone().unwrap_or_default();
46 let checked = selected != props.default_value.clone().unwrap_or_default();
47 let reset_value = props.default_value.clone();
48 html! {
49 <div class="row">
50 <OptionalField
51 label={props.label.clone()}
52 on_check={props.on_change.reform(move |_| reset_value.clone())}
53 {checked}
54 disabled={props.disabled}
55 >
56 <Select<T> {values} {selected} on_select={props.on_change.reform(Option::Some)} />
57 </OptionalField>
58 </div>
59 }
60}
61
62#[derive(Properties, Debug, PartialEq, Clone)]
63pub struct SelectValueFieldProps<T>
64where
65 T: Display + PartialEq + Clone + 'static,
66{
67 pub label: String,
68 pub current_value: Option<T>,
69 pub default_value: T,
70 pub values: Rc<Vec<T>>,
71 pub on_change: Callback<Option<T>>,
72
73 #[prop_or_default]
74 pub disabled: bool,
75}
76
77#[function_component(SelectValueField)]
78pub fn select_value_field<T>(props: &SelectValueFieldProps<T>) -> yew::Html
79where
80 T: Display + PartialEq + Clone + 'static,
81{
82 let values = yew::use_memo(props.values.clone(), |values| {
83 values.iter().cloned().map(SelectItem::Option).collect_vec()
84 });
85
86 let selected = props
87 .current_value
88 .clone()
89 .unwrap_or_else(|| props.default_value.clone());
90
91 let checked = selected != props.default_value;
92 html! {
93 <div class="row">
94 <OptionalField
95 label={props.label.clone()}
96 on_check={props.on_change.reform(|_| None)}
97 {checked}
98 disabled={props.disabled}
99 >
100 <Select<T> {values} {selected} on_select={props.on_change.reform(Option::Some)} />
101 </OptionalField>
102 </div>
103 }
104}