dioxus_tw_components/attributes/
mod.rs1use dioxus::dioxus_core::{Attribute, AttributeValue, Element};
2use std::str::FromStr;
3use tailwind_fuse::tw_merge;
4
5pub trait UiComp: HasChildren + BuildClass + std::fmt::Display {}
6
7pub trait HasChildren {
9 fn has_children(&self) -> bool {
10 false
11 }
12
13 fn set_children(&mut self, _children: Element) {}
14}
15
16pub trait Class {
17 fn base(&self) -> &'static str {
18 ""
19 }
20
21 fn color(&self) -> Option<&'static str> {
22 None
23 }
24
25 fn size(&self) -> Option<&'static str> {
26 None
27 }
28
29 fn variant(&self) -> Option<&'static str> {
30 None
31 }
32
33 fn animation(&self) -> Option<&'static str> {
34 None
35 }
36
37 fn orientation(&self) -> Option<&'static str> {
38 None
39 }
40
41 fn side(&self) -> Option<&'static str> {
42 None
43 }
44}
45
46pub trait BuildClass: Class {
47 fn build_class(&self) -> String {
48 let mut class = String::from(self.base());
49
50 if let Some(color) = self.color() {
51 class.push(' ');
52 class.push_str(color);
53 }
54
55 if let Some(size) = self.size() {
56 class.push(' ');
57 class.push_str(size);
58 }
59
60 if let Some(variant) = self.variant() {
61 class.push(' ');
62 class.push_str(variant);
63 }
64
65 if let Some(animation) = self.animation() {
66 class.push(' ');
67 class.push_str(animation);
68 }
69
70 if let Some(orientation) = self.orientation() {
71 class.push(' ');
72 class.push_str(orientation);
73 }
74
75 if let Some(side) = self.side() {
76 class.push(' ');
77 class.push_str(side);
78 }
79
80 tw_merge!(class)
81 }
82
83 fn update_class_attribute(&mut self) {
84 let class = self.build_class();
85
86 if let Some(vec_attributes) = self.get_attributes() {
88 if let Some(class_attribute) =
90 vec_attributes.iter_mut().find(|attr| attr.name == "class")
91 {
92 if let AttributeValue::Text(ref mut value) = class_attribute.value {
93 *value = tw_merge!(class, value.clone());
94 }
95 } else {
96 vec_attributes.push(Attribute::new("class", class, None, true));
98 }
99 }
100 }
101
102 fn get_attributes(&mut self) -> Option<&mut Vec<Attribute>> {
103 None
104 }
105
106 fn has_color(&self) -> bool {
108 self.color().is_some()
109 }
110
111 fn set_color(&mut self, _color: Color) {}
112
113 fn has_size(&self) -> bool {
114 self.size().is_some()
115 }
116
117 fn set_size(&mut self, _size: Size) {}
118
119 fn has_animation(&self) -> bool {
120 self.animation().is_some()
121 }
122
123 fn set_animation(&mut self, _animation: Animation) {}
124
125 fn has_orientation(&self) -> bool {
126 self.orientation().is_some()
127 }
128
129 fn set_orientation(&mut self, _orientation: Orientation) {}
130
131 fn has_side(&self) -> bool {
132 self.side().is_some()
133 }
134
135 fn set_side(&mut self, _side: Side) {}
136}
137
138#[derive(Default, Debug, Clone, Copy, PartialEq)]
139pub enum Color {
140 #[default]
141 Default,
142 Primary,
143 Secondary,
144 Destructive,
145 Success,
146 Accent,
147 Muted,
148}
149
150impl FromStr for Color {
151 type Err = &'static str;
152
153 fn from_str(s: &str) -> Result<Self, Self::Err> {
154 match s.to_lowercase().as_str() {
155 "primary" => Ok(Color::Primary),
156 "secondary" => Ok(Color::Secondary),
157 "destructive" => Ok(Color::Destructive),
158 "success" => Ok(Color::Success),
159 "accent" => Ok(Color::Accent),
160 "muted" => Ok(Color::Muted),
161 _ => Ok(Color::default()),
162 }
163 }
164}
165
166impl std::fmt::Display for Color {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 let s = match self {
169 Color::Default => "Default",
170 Color::Primary => "Primary",
171 Color::Secondary => "Secondary",
172 Color::Destructive => "Destructive",
173 Color::Success => "Success",
174 Color::Accent => "Accent",
175 Color::Muted => "Muted",
176 };
177 f.write_str(s)
178 }
179}
180
181#[derive(Default, Clone, Copy, PartialEq)]
182pub enum Size {
183 Xs,
184 Sm,
185 #[default]
186 Md,
187 Lg,
188 Xl,
189}
190
191impl FromStr for Size {
192 type Err = &'static str;
193
194 fn from_str(s: &str) -> Result<Self, Self::Err> {
195 match s.to_lowercase().as_str() {
196 "xs" => Ok(Size::Xs),
197 "sm" => Ok(Size::Sm),
198 "md" => Ok(Size::Md),
199 "lg" => Ok(Size::Lg),
200 "xl" => Ok(Size::Xl),
201 _ => Ok(Size::default()),
202 }
203 }
204}
205
206impl std::fmt::Display for Size {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 let s = match self {
209 Size::Xs => "Xs",
210 Size::Sm => "Sm",
211 Size::Md => "Md",
212 Size::Lg => "Lg",
213 Size::Xl => "Xl",
214 };
215 f.write_str(s)
216 }
217}
218
219#[derive(Default, Clone, Copy, PartialEq)]
220pub enum Orientation {
221 #[default]
222 Horizontal,
223 Vertical,
224}
225
226impl FromStr for Orientation {
227 type Err = &'static str;
228
229 fn from_str(s: &str) -> Result<Self, Self::Err> {
230 match s.to_lowercase().as_str() {
231 "horizontal" => Ok(Orientation::Horizontal),
232 _ => Ok(Orientation::Vertical),
233 }
234 }
235}
236
237impl std::fmt::Display for Orientation {
238 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239 let s = match self {
240 Orientation::Vertical => "vertical",
241 Orientation::Horizontal => "horizontal",
242 };
243 f.write_str(s)
244 }
245}
246
247#[derive(Default, Debug, Clone, Copy, PartialEq)]
248pub enum Animation {
249 None,
250 Light,
251 #[default]
252 Full,
253}
254
255impl FromStr for Animation {
256 type Err = &'static str;
257
258 fn from_str(s: &str) -> Result<Self, Self::Err> {
259 match s.to_lowercase().as_str() {
260 "none" => Ok(Animation::None),
261 "light" => Ok(Animation::Light),
262 _ => Ok(Animation::Full),
263 }
264 }
265}
266
267impl std::fmt::Display for Animation {
268 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 let s = match self {
270 Animation::None => "None",
271 Animation::Light => "Light",
272 Animation::Full => "Full",
273 };
274 f.write_str(s)
275 }
276}
277
278#[derive(Default, Clone, Copy, PartialEq)]
279pub enum Side {
280 Top,
281 Bottom,
282 Left,
283 #[default]
284 Right,
285}
286
287impl FromStr for Side {
288 type Err = &'static str;
289
290 fn from_str(s: &str) -> Result<Self, Self::Err> {
291 match s.to_lowercase().as_str() {
292 "top" => Ok(Side::Top),
293 "bottom" => Ok(Side::Bottom),
294 "left" => Ok(Side::Left),
295 _ => Ok(Side::Right),
296 }
297 }
298}
299
300impl std::fmt::Display for Side {
301 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
302 let s = match self {
303 Side::Top => "Top",
304 Side::Bottom => "Bottom",
305 Side::Left => "Left",
306 Side::Right => "Right",
307 };
308 f.write_str(s)
309 }
310}