mod edge;
mod size;
mod variant;
use web_sys::HtmlInputElement;
use yew::{
classes, function_component, html, use_state, AttrValue, Callback, Classes, Event, FocusEvent,
Html, Properties, TargetCast,
};
use zu_util::prop::ToAttr;
use crate::button_base::ButtonBase;
use crate::styles::edge::Edge;
use crate::styles::size::Size;
pub use variant::Variant;
#[derive(Debug, Clone, PartialEq, Properties)]
pub struct Props {
#[prop_or_default]
pub aria_label: AttrValue,
#[prop_or(false)]
pub auto_focus: bool,
#[prop_or(false)]
pub checked: bool,
#[prop_or_default]
pub checked_icon: Html,
#[prop_or_default]
pub classes: Classes,
#[prop_or(false)]
pub default_checked: bool,
#[prop_or(false)]
pub disabled: bool,
#[prop_or(true)]
pub disable_focus_ripple: bool,
#[prop_or_default]
pub edge: Option<Edge>,
pub icon: Html,
#[prop_or_default]
pub id: AttrValue,
#[prop_or_default]
pub input_classes: Classes,
#[prop_or_default]
pub name: AttrValue,
#[prop_or_default]
pub on_blur: Option<Callback<FocusEvent>>,
#[prop_or_default]
pub on_change: Option<Callback<bool>>,
#[prop_or_default]
pub on_focus: Option<Callback<FocusEvent>>,
#[prop_or(false)]
pub read_only: bool,
#[prop_or(false)]
pub required: bool,
#[prop_or_default]
pub size: Size,
#[prop_or_default]
pub style: AttrValue,
#[prop_or_default]
pub tab_index: Option<i32>,
pub variant: Variant,
#[prop_or_default]
pub value: AttrValue,
}
#[function_component(SwitchBase)]
pub fn switch_base(props: &Props) -> Html {
let checked_state = use_state(|| props.default_checked);
let on_input_change = {
let checked_state_clone = checked_state.clone();
let on_change_cb = props.on_change.clone();
Callback::from(move |event: Event| {
let input = event.target_unchecked_into::<HtmlInputElement>();
let is_checked: bool = input.checked();
checked_state_clone.set(is_checked);
if let Some(on_change) = &on_change_cb {
on_change.emit(is_checked);
}
})
};
let root_cls = classes!(
"ZuSwitchBase-root",
if *checked_state {
"ZuSwitchBase-checked"
} else {
""
},
if props.disabled {
"ZuSwitchBase-disabled"
} else {
""
},
edge::css_class(props.edge),
props.classes.clone(),
);
let has_label_for = match props.variant {
Variant::Checkbox | Variant::Radio => true,
Variant::Switch => false,
};
let input_id = if has_label_for {
Some(props.id.as_str().to_owned())
} else {
None
};
let value = if props.variant == Variant::Checkbox {
Some(props.value.as_str().to_owned())
} else {
None
};
let input_cls = classes!("ZuSwitchBase-input", props.input_classes.clone());
html! {
<ButtonBase
classes={root_cls}
component="span"
disabled={props.disabled}
focus_ripple={!props.disable_focus_ripple}
style={&props.style}
on_focus={&props.on_focus}
on_blur={&props.on_blur}
>
<input
class={input_cls}
aria_label={props.aria_label.to_attr()}
auto_focus={props.auto_focus.to_attr()}
checked={*checked_state}
default_checked={props.default_checked.to_attr()}
disabled={props.disabled}
id={input_id}
name={props.name.to_attr()}
onchange={on_input_change}
required={props.required}
tab_index={props.tab_index.to_attr()}
type={props.variant.name()}
value={value}
/>
if *checked_state {
{props.checked_icon.clone()}
} else {
{props.icon.clone()}
}
</ButtonBase>
}
}