tailwind_rs_core/utilities/
text_shadow.rs1use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum TextShadow {
13 None,
15 Sm,
17 Md,
19 Default,
21 Lg,
23 Xl,
25 Xl2,
27 Inner,
29}
30
31impl fmt::Display for TextShadow {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 TextShadow::None => write!(f, "none"),
35 TextShadow::Sm => write!(f, "0 1px 2px 0 rgb(0 0 0 / 0.05)"),
36 TextShadow::Md => write!(
37 f,
38 "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)"
39 ),
40 TextShadow::Default => write!(
41 f,
42 "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)"
43 ),
44 TextShadow::Lg => write!(
45 f,
46 "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)"
47 ),
48 TextShadow::Xl => write!(
49 f,
50 "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)"
51 ),
52 TextShadow::Xl2 => write!(f, "0 25px 50px -12px rgb(0 0 0 / 0.25)"),
53 TextShadow::Inner => write!(f, "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)"),
54 }
55 }
56}
57
58impl TextShadow {
59 pub fn to_class_name(&self) -> String {
61 match self {
62 TextShadow::None => "text-shadow-none".to_string(),
63 TextShadow::Sm => "text-shadow-sm".to_string(),
64 TextShadow::Md => "text-shadow-md".to_string(),
65 TextShadow::Default => "text-shadow".to_string(),
66 TextShadow::Lg => "text-shadow-lg".to_string(),
67 TextShadow::Xl => "text-shadow-xl".to_string(),
68 TextShadow::Xl2 => "text-shadow-2xl".to_string(),
69 TextShadow::Inner => "text-shadow-inner".to_string(),
70 }
71 }
72
73 pub fn to_css_value(&self) -> String {
75 self.to_string()
76 }
77}
78
79pub trait TextShadowUtilities {
81 fn text_shadow_none(self) -> Self;
83 fn text_shadow_sm(self) -> Self;
85 fn text_shadow_md(self) -> Self;
87 fn text_shadow(self) -> Self;
89 fn text_shadow_lg(self) -> Self;
91 fn text_shadow_xl(self) -> Self;
93 fn text_shadow_2xl(self) -> Self;
95 fn text_shadow_inner(self) -> Self;
97 fn text_shadow_custom(self, shadow: TextShadow) -> Self;
99}
100
101impl TextShadowUtilities for ClassBuilder {
102 fn text_shadow_none(self) -> Self {
103 self.class("text-shadow-none")
104 }
105
106 fn text_shadow_sm(self) -> Self {
107 self.class("text-shadow-sm")
108 }
109
110 fn text_shadow_md(self) -> Self {
111 self.class("text-shadow-md")
112 }
113
114 fn text_shadow(self) -> Self {
115 self.class("text-shadow")
116 }
117
118 fn text_shadow_lg(self) -> Self {
119 self.class("text-shadow-lg")
120 }
121
122 fn text_shadow_xl(self) -> Self {
123 self.class("text-shadow-xl")
124 }
125
126 fn text_shadow_2xl(self) -> Self {
127 self.class("text-shadow-2xl")
128 }
129
130 fn text_shadow_inner(self) -> Self {
131 self.class("text-shadow-inner")
132 }
133
134 fn text_shadow_custom(self, shadow: TextShadow) -> Self {
135 self.class(shadow.to_class_name())
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use crate::classes::ClassBuilder;
143
144 #[test]
145 fn test_text_shadow_enum_values() {
146 assert_eq!(TextShadow::None.to_string(), "none");
147 assert_eq!(TextShadow::Sm.to_string(), "0 1px 2px 0 rgb(0 0 0 / 0.05)");
148 assert_eq!(
149 TextShadow::Default.to_string(),
150 "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)"
151 );
152 assert_eq!(
153 TextShadow::Lg.to_string(),
154 "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)"
155 );
156 assert_eq!(
157 TextShadow::Xl.to_string(),
158 "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)"
159 );
160 assert_eq!(
161 TextShadow::Xl2.to_string(),
162 "0 25px 50px -12px rgb(0 0 0 / 0.25)"
163 );
164 assert_eq!(
165 TextShadow::Inner.to_string(),
166 "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)"
167 );
168 }
169
170 #[test]
171 fn test_text_shadow_class_names() {
172 assert_eq!(TextShadow::None.to_class_name(), "text-shadow-none");
173 assert_eq!(TextShadow::Sm.to_class_name(), "text-shadow-sm");
174 assert_eq!(TextShadow::Default.to_class_name(), "text-shadow");
175 assert_eq!(TextShadow::Lg.to_class_name(), "text-shadow-lg");
176 assert_eq!(TextShadow::Xl.to_class_name(), "text-shadow-xl");
177 assert_eq!(TextShadow::Xl2.to_class_name(), "text-shadow-2xl");
178 assert_eq!(TextShadow::Inner.to_class_name(), "text-shadow-inner");
179 }
180
181 #[test]
182 fn test_text_shadow_utilities() {
183 let classes = ClassBuilder::new()
184 .text_shadow_none()
185 .text_shadow_sm()
186 .text_shadow()
187 .text_shadow_lg()
188 .text_shadow_xl()
189 .text_shadow_2xl()
190 .text_shadow_inner();
191
192 let result = classes.build();
193 assert!(result.classes.contains("text-shadow-none"));
194 assert!(result.classes.contains("text-shadow-sm"));
195 assert!(result.classes.contains("text-shadow"));
196 assert!(result.classes.contains("text-shadow-lg"));
197 assert!(result.classes.contains("text-shadow-xl"));
198 assert!(result.classes.contains("text-shadow-2xl"));
199 assert!(result.classes.contains("text-shadow-inner"));
200 }
201
202 #[test]
203 fn test_text_shadow_css_values() {
204 assert_eq!(TextShadow::None.to_css_value(), "none");
205 assert_eq!(
206 TextShadow::Sm.to_css_value(),
207 "0 1px 2px 0 rgb(0 0 0 / 0.05)"
208 );
209 assert_eq!(
210 TextShadow::Default.to_css_value(),
211 "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)"
212 );
213 assert_eq!(
214 TextShadow::Lg.to_css_value(),
215 "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)"
216 );
217 assert_eq!(
218 TextShadow::Xl.to_css_value(),
219 "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)"
220 );
221 assert_eq!(
222 TextShadow::Xl2.to_css_value(),
223 "0 25px 50px -12px rgb(0 0 0 / 0.25)"
224 );
225 assert_eq!(
226 TextShadow::Inner.to_css_value(),
227 "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)"
228 );
229 }
230
231 #[test]
232 fn test_text_shadow_serialization() {
233 let shadow = TextShadow::Lg;
234 let serialized = serde_json::to_string(&shadow).unwrap();
235 let deserialized: TextShadow = serde_json::from_str(&serialized).unwrap();
236 assert_eq!(shadow, deserialized);
237 }
238
239 #[test]
240 fn test_text_shadow_comprehensive_usage() {
241 let classes = ClassBuilder::new().text_shadow_sm().text_shadow_lg();
242
243 let result = classes.build();
244 assert!(result.classes.contains("text-shadow-sm"));
245 assert!(result.classes.contains("text-shadow-lg"));
246 }
247
248 #[test]
249 fn test_text_shadow_custom_usage() {
250 let classes = ClassBuilder::new()
251 .text_shadow_custom(TextShadow::Xl)
252 .text_shadow_custom(TextShadow::Inner);
253
254 let result = classes.build();
255 assert!(result.classes.contains("text-shadow-xl"));
256 assert!(result.classes.contains("text-shadow-inner"));
257 }
258}