yew_hooks/hooks/
use_toggle.rs1use std::fmt;
2use std::ops::Deref;
3use std::rc::Rc;
4
5use yew::prelude::*;
6
7enum ToggleAction<T> {
8 Toggle,
9 Reset,
10 Set(T),
11 SetLeft,
12 SetRight,
13}
14
15struct UseToggleReducer<T>
16where
17 T: PartialEq,
18{
19 value: Rc<T>,
20 left: Rc<T>,
21 right: Rc<T>,
22}
23
24impl<T> Reducible for UseToggleReducer<T>
25where
26 T: PartialEq,
27{
28 type Action = ToggleAction<T>;
29
30 fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
31 let next_value = match action {
32 ToggleAction::Toggle => {
33 if self.value == self.left {
34 self.right.clone()
35 } else {
36 self.left.clone()
37 }
38 }
39 ToggleAction::Set(value) => Rc::new(value),
40 ToggleAction::Reset | ToggleAction::SetLeft => self.left.clone(),
41 ToggleAction::SetRight => self.right.clone(),
42 };
43
44 Self {
45 value: next_value,
46 left: self.left.clone(),
47 right: self.right.clone(),
48 }
49 .into()
50 }
51}
52
53impl<T> PartialEq for UseToggleReducer<T>
54where
55 T: PartialEq,
56{
57 fn eq(&self, other: &Self) -> bool {
58 self.value == other.value
59 }
60}
61
62pub struct UseToggleHandle<T>
64where
65 T: PartialEq,
66{
67 inner: UseReducerHandle<UseToggleReducer<T>>,
68}
69
70impl<T> UseToggleHandle<T>
71where
72 T: PartialEq,
73{
74 pub fn toggle(&self) {
76 self.inner.dispatch(ToggleAction::Toggle);
77 }
78
79 pub fn set(&self, value: T) {
81 self.inner.dispatch(ToggleAction::Set(value));
82 }
83
84 pub fn set_left(&self) {
86 self.inner.dispatch(ToggleAction::SetLeft);
87 }
88
89 pub fn set_right(&self) {
91 self.inner.dispatch(ToggleAction::SetRight);
92 }
93
94 pub fn reset(&self) {
96 self.inner.dispatch(ToggleAction::Reset);
97 }
98}
99
100impl<T> Deref for UseToggleHandle<T>
101where
102 T: PartialEq,
103{
104 type Target = T;
105
106 fn deref(&self) -> &Self::Target {
107 &(*self.inner).value
108 }
109}
110
111impl<T> Clone for UseToggleHandle<T>
112where
113 T: PartialEq,
114{
115 fn clone(&self) -> Self {
116 Self {
117 inner: self.inner.clone(),
118 }
119 }
120}
121
122impl<T> PartialEq for UseToggleHandle<T>
123where
124 T: PartialEq,
125{
126 fn eq(&self, other: &Self) -> bool {
127 *self.inner == *other.inner
128 }
129}
130
131impl<T: fmt::Debug + PartialEq> fmt::Debug for UseToggleHandle<T> {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("UseToggleHandle")
134 .field("value", &format!("{:?}", self.inner.value))
135 .field("left", &format!("{:?}", self.inner.left))
136 .field("right", &format!("{:?}", self.inner.right))
137 .finish()
138 }
139}
140
141#[hook]
171pub fn use_bool_toggle(default: bool) -> UseToggleHandle<bool> {
172 use_toggle(default, !default)
173}
174
175#[hook]
205pub fn use_toggle<T>(default: T, other: T) -> UseToggleHandle<T>
206where
207 T: 'static + PartialEq,
208{
209 let value = Rc::new(default);
210 let left = value.clone();
211 let right = Rc::new(other);
212
213 let inner = use_reducer(move || UseToggleReducer { value, left, right });
214
215 UseToggleHandle { inner }
216}