use super::*;
#[component]
pub fn euv_segmented(node: VirtualNode<EuvSegmentedProps>) -> VirtualNode {
let EuvSegmentedProps {
options,
value,
on_change,
}: EuvSegmentedProps = node.try_get_props().unwrap_or_default();
let selected: String = value.get();
let items: Vec<VirtualNode> = options
.into_iter()
.map(|option: EuvSegmentedOption| {
let is_active: bool = selected == option.value;
segmented_item(option, is_active, value, on_change.clone())
})
.collect();
html! {
div {
class: c_euv_segmented()
items
}
}
}
fn segmented_item(
option: EuvSegmentedOption,
is_active: bool,
value: Signal<String>,
on_change: Option<Rc<dyn Fn(&'static str)>>,
) -> VirtualNode {
let disabled: bool = option.disabled;
let handler: Option<Rc<dyn Fn(Event)>> = if disabled {
None
} else {
segmented_pick(value, on_change, option.value)
};
html! {
button {
type: "button"
class: segmented_item_class(is_active)
disabled: boolean_attr(disabled)
onclick: handler
option.label
}
}
}
fn segmented_item_class(is_active: bool) -> String {
let base: &str = c_euv_segmented_item().get_name();
if !is_active {
return String::from(base);
}
let active: &str = c_euv_segmented_item_active().get_name();
let mut class_name: String = String::with_capacity(base.len() + 1 + active.len());
class_name.push_str(base);
class_name.push(' ');
class_name.push_str(active);
class_name
}
fn segmented_pick(
value: Signal<String>,
on_change: Option<Rc<dyn Fn(&'static str)>>,
option_value: &'static str,
) -> Option<Rc<dyn Fn(Event)>> {
Some(Rc::new(move |_: Event| {
value.set(String::from(option_value));
if let Some(callback) = &on_change {
callback(option_value);
}
}))
}
fn boolean_attr(flag: bool) -> &'static str {
if flag { "true" } else { "" }
}