perspective_viewer/components/form/
select_field.rs1use std::fmt::{Debug, Display};
14use std::sync::Arc;
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 = 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: Arc<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 = props
83 .values
84 .iter()
85 .cloned()
86 .map(SelectItem::Option)
87 .collect_vec();
88
89 let selected = props
90 .current_value
91 .clone()
92 .unwrap_or_else(|| props.default_value.clone());
93
94 let checked = selected != props.default_value;
95 html! {
96 <div class="row">
97 <OptionalField
98 label={props.label.clone()}
99 on_check={props.on_change.reform(|_| None)}
100 {checked}
101 disabled={props.disabled}
102 >
103 <Select<T> {values} {selected} on_select={props.on_change.reform(Option::Some)} />
104 </OptionalField>
105 </div>
106 }
107}