use crate::{id::Id, prelude::*};
use derive_rich::Rich;
use savory::prelude::*;
use savory_style::{self as style, prelude::*};
use std::borrow::Cow;
pub enum Msg {
DesignSystem(DesignSystem),
Focus(bool),
MouseOver(bool),
Disable(bool),
Toggled(bool),
Toggle,
}
#[derive(Rich, Element)]
#[element(style_map(switch, check_sign, text))]
pub struct Switch {
#[rich(read)]
#[element(config)]
id: Option<Id>,
#[rich(read)]
#[element(config(default), data_lens)]
style: Style,
design_system: DesignSystem,
#[rich(read(copy, rename = is_toggled))]
#[element(config(default), data_lens(copy))]
toggled: bool,
#[rich(read)]
#[element(config)]
text: Option<Cow<'static, str>>,
#[rich(read(copy, rename = is_disabled))]
#[element(config(default), data_lens(copy))]
disabled: bool,
#[rich(read(copy, rename = is_focused))]
#[element(data_lens(copy))]
focused: bool,
#[rich(read(copy, rename = is_mouse_over))]
#[element(data_lens(copy))]
mouse_over: bool,
#[rich(read(copy))]
#[element(config, data_lens(copy))]
pub color: Option<style::Color>,
#[rich(write)]
#[element(config(default), data_lens(copy))]
pub checkbox_like: bool,
}
impl Element for Switch {
type Message = Msg;
type Config = Config;
fn init(config: Self::Config, orders: &mut impl Orders<Msg>) -> Self {
orders.subscribe(|ds: DesignSystemChanged| Msg::DesignSystem(ds.0));
Self {
id: config.id,
design_system: DesignSystem::default(),
text: config.text,
style: config.style,
toggled: config.toggled,
disabled: config.disabled,
focused: false,
mouse_over: false,
color: config.color,
checkbox_like: config.checkbox_like,
}
}
fn update(&mut self, msg: Msg, _orders: &mut impl Orders<Msg>) {
match msg {
Msg::DesignSystem(val) => self.design_system = val,
Msg::MouseOver(val) => self.mouse_over = val,
Msg::Focus(val) => self.focused = val,
Msg::Disable(val) => self.disabled = val,
Msg::Toggled(val) => self.toggled = val,
Msg::Toggle => self.toggled = !self.toggled,
}
}
}
impl View<Node<Msg>> for Switch {
fn view(&self) -> Node<Msg> {
let style_map = self.design_system.switch(self.data_lens());
let switch = html::button()
.class("switch")
.style(style_map.switch)
.disabled(self.disabled)
.on_focus(|_| Msg::Focus(true))
.on_blur(|_| Msg::Focus(false))
.on_mouse_enter(|_| Msg::MouseOver(true))
.on_mouse_leave(|_| Msg::MouseOver(false))
.on_click(|_| Msg::Toggle)
.set(html::div().class("check-sign").style(style_map.check_sign));
match self.text.as_ref() {
None => switch.try_id(self.id.clone()),
Some(lbl) => html::label()
.try_id(self.id.clone())
.class("text")
.style(style_map.text)
.push(switch)
.push(lbl.clone())
.on_mouse_enter(|_| Msg::MouseOver(true))
.on_mouse_leave(|_| Msg::MouseOver(false)),
}
}
}