dioxus_tw_components/components/molecules/lightswitch/
props.rs1use crate::{atoms::icon::*, attributes::*};
2use dioxus::prelude::*;
3use dioxus_tw_components_macro::UiComp;
4use serde_json::Value;
5
6pub struct LightSwitchState {
7 active: bool,
8}
9
10impl LightSwitchState {
11 pub fn new(active: bool) -> Self {
12 Self { active }
13 }
14
15 fn toggle(&mut self) -> bool {
16 self.active = !self.active;
17 self.active
18 }
19
20 fn get_active(&self) -> bool {
21 self.active
22 }
23
24 fn set_active(&mut self, active: bool) {
25 self.active = active;
26 }
27}
28
29#[derive(Clone, PartialEq, Props, UiComp)]
30pub struct LightSwitchProps {
31 #[props(extends = GlobalAttributes)]
32 attributes: Vec<Attribute>,
33
34 #[props(optional)]
35 pub onclick: Option<EventHandler<MouseEvent>>,
36
37 children: Element,
38}
39
40impl std::default::Default for LightSwitchProps {
41 fn default() -> Self {
42 Self {
43 attributes: Vec::<Attribute>::default(),
44 onclick: None,
45 children: rsx! {},
46 }
47 }
48}
49
50#[component]
52pub fn LightSwitch(mut props: LightSwitchProps) -> Element {
53 props.update_class_attribute();
54
55 let storage_dark_theme = use_resource(move || async move {
56 let mut eval = document::eval(
58 r#"
59 var dark_theme = localStorage.getItem("dark_theme");
60 if (dark_theme == null) {
61 var dark_theme = false;
62 localStorage.setItem("dark_theme", dark_theme);
63 } else {
64 let main_div = document.getElementById("main");
65 if (main_div != null && dark_theme == "true") {
66 main_div.classList.add("dark");
67 }
68 }
69 dioxus.send(dark_theme);
70 "#,
71 );
72
73 eval.recv().await
74 });
75
76 let mut state = use_signal(|| LightSwitchState::new(false));
77
78 use_effect(move || {
79 if let Some(Ok(Value::String(str))) = &*storage_dark_theme.read_unchecked() {
80 let parsed_str = str.parse::<bool>();
81 if let Ok(bool_value) = parsed_str {
82 state.write().set_active(bool_value);
83 }
84 };
85 });
86
87 let mut onclick = move |_| {
88 let dark_theme = state.write().toggle();
89 spawn(async move {
90 let eval = document::eval(
92 r#"
93 const dark_theme = await dioxus.recv();
94 localStorage.setItem("dark_theme", dark_theme);
95 let main_div = document.getElementById("main");
96 if (main != null) {
97 if (dark_theme) {
98 main_div.classList.add("dark");
99 } else {
100 main_div.classList.remove("dark");
101 }
102 }
103 "#,
104 );
105 let _ = eval.send(dark_theme);
106 });
107 };
108
109 let icon = if state.read().get_active() {
110 rsx! {
111 Icon { icon: Icons::DarkMode }
112 }
113 } else {
114 rsx! {
115 Icon { icon: Icons::LightMode }
116 }
117 };
118
119 rsx! {
120 button {
121 r#type: "button",
122 onclick: move |e| {
123 match props.onclick {
124 Some(p) => {
125 state.write().toggle();
126 p.call(e);
127 }
128 None => onclick(e),
129 }
130 },
131 ..props.attributes,
132 {icon}
133 }
134 }
135}