tailwind_rs_core/utilities/
device_variants.rs1use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum PointerVariant {
13 Coarse,
15 Fine,
17 AnyCoarse,
19 AnyFine,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum MotionVariant {
26 Reduced,
28 NoPreference,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
34pub enum ColorSchemeVariant {
35 Light,
37 Dark,
39}
40
41impl PointerVariant {
42 pub fn to_class_name(&self) -> String {
43 match self {
44 PointerVariant::Coarse => "pointer-coarse".to_string(),
45 PointerVariant::Fine => "pointer-fine".to_string(),
46 PointerVariant::AnyCoarse => "any-pointer-coarse".to_string(),
47 PointerVariant::AnyFine => "any-pointer-fine".to_string(),
48 }
49 }
50
51 pub fn to_media_query(&self) -> String {
52 match self {
53 PointerVariant::Coarse => "@media (pointer: coarse)".to_string(),
54 PointerVariant::Fine => "@media (pointer: fine)".to_string(),
55 PointerVariant::AnyCoarse => "@media (any-pointer: coarse)".to_string(),
56 PointerVariant::AnyFine => "@media (any-pointer: fine)".to_string(),
57 }
58 }
59}
60
61impl MotionVariant {
62 pub fn to_class_name(&self) -> String {
63 match self {
64 MotionVariant::Reduced => "motion-reduce".to_string(),
65 MotionVariant::NoPreference => "motion-safe".to_string(),
66 }
67 }
68
69 pub fn to_media_query(&self) -> String {
70 match self {
71 MotionVariant::Reduced => "@media (prefers-reduced-motion: reduce)".to_string(),
72 MotionVariant::NoPreference => "@media (prefers-reduced-motion: no-preference)".to_string(),
73 }
74 }
75}
76
77impl ColorSchemeVariant {
78 pub fn to_class_name(&self) -> String {
79 match self {
80 ColorSchemeVariant::Light => "light".to_string(),
81 ColorSchemeVariant::Dark => "dark".to_string(),
82 }
83 }
84
85 pub fn to_media_query(&self) -> String {
86 match self {
87 ColorSchemeVariant::Light => "@media (prefers-color-scheme: light)".to_string(),
88 ColorSchemeVariant::Dark => "@media (prefers-color-scheme: dark)".to_string(),
89 }
90 }
91}
92
93impl fmt::Display for PointerVariant {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "{}", self.to_class_name())
96 }
97}
98
99impl fmt::Display for MotionVariant {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 write!(f, "{}", self.to_class_name())
102 }
103}
104
105impl fmt::Display for ColorSchemeVariant {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(f, "{}", self.to_class_name())
108 }
109}
110
111pub trait PointerVariantUtilities {
113 fn pointer_coarse(self) -> Self;
115 fn pointer_fine(self) -> Self;
117 fn any_pointer_coarse(self) -> Self;
119 fn any_pointer_fine(self) -> Self;
121}
122
123impl PointerVariantUtilities for ClassBuilder {
124 fn pointer_coarse(self) -> Self {
125 self.class("pointer-coarse")
126 }
127
128 fn pointer_fine(self) -> Self {
129 self.class("pointer-fine")
130 }
131
132 fn any_pointer_coarse(self) -> Self {
133 self.class("any-pointer-coarse")
134 }
135
136 fn any_pointer_fine(self) -> Self {
137 self.class("any-pointer-fine")
138 }
139}
140
141pub trait MotionVariantUtilities {
143 fn motion_reduce(self) -> Self;
145 fn motion_safe(self) -> Self;
147}
148
149impl MotionVariantUtilities for ClassBuilder {
150 fn motion_reduce(self) -> Self {
151 self.class("motion-reduce")
152 }
153
154 fn motion_safe(self) -> Self {
155 self.class("motion-safe")
156 }
157}
158
159pub trait ColorSchemeVariantUtilities {
161 fn light(self) -> Self;
163 fn dark(self) -> Self;
165}
166
167impl ColorSchemeVariantUtilities for ClassBuilder {
168 fn light(self) -> Self {
169 self.class("light")
170 }
171
172 fn dark(self) -> Self {
173 self.class("dark")
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_pointer_variant_class_names() {
183 assert_eq!(PointerVariant::Coarse.to_class_name(), "pointer-coarse");
184 assert_eq!(PointerVariant::Fine.to_class_name(), "pointer-fine");
185 assert_eq!(PointerVariant::AnyCoarse.to_class_name(), "any-pointer-coarse");
186 assert_eq!(PointerVariant::AnyFine.to_class_name(), "any-pointer-fine");
187 }
188
189 #[test]
190 fn test_pointer_variant_media_queries() {
191 assert_eq!(PointerVariant::Coarse.to_media_query(), "@media (pointer: coarse)");
192 assert_eq!(PointerVariant::Fine.to_media_query(), "@media (pointer: fine)");
193 assert_eq!(PointerVariant::AnyCoarse.to_media_query(), "@media (any-pointer: coarse)");
194 assert_eq!(PointerVariant::AnyFine.to_media_query(), "@media (any-pointer: fine)");
195 }
196
197 #[test]
198 fn test_motion_variant_class_names() {
199 assert_eq!(MotionVariant::Reduced.to_class_name(), "motion-reduce");
200 assert_eq!(MotionVariant::NoPreference.to_class_name(), "motion-safe");
201 }
202
203 #[test]
204 fn test_motion_variant_media_queries() {
205 assert_eq!(MotionVariant::Reduced.to_media_query(), "@media (prefers-reduced-motion: reduce)");
206 assert_eq!(MotionVariant::NoPreference.to_media_query(), "@media (prefers-reduced-motion: no-preference)");
207 }
208
209 #[test]
210 fn test_color_scheme_variant_class_names() {
211 assert_eq!(ColorSchemeVariant::Light.to_class_name(), "light");
212 assert_eq!(ColorSchemeVariant::Dark.to_class_name(), "dark");
213 }
214
215 #[test]
216 fn test_color_scheme_variant_media_queries() {
217 assert_eq!(ColorSchemeVariant::Light.to_media_query(), "@media (prefers-color-scheme: light)");
218 assert_eq!(ColorSchemeVariant::Dark.to_media_query(), "@media (prefers-color-scheme: dark)");
219 }
220
221 #[test]
222 fn test_pointer_variant_utilities() {
223 let classes = ClassBuilder::new()
224 .pointer_coarse()
225 .pointer_fine()
226 .any_pointer_coarse()
227 .any_pointer_fine()
228 .build();
229
230 assert!(classes.classes.contains("pointer-coarse"));
231 assert!(classes.classes.contains("pointer-fine"));
232 assert!(classes.classes.contains("any-pointer-coarse"));
233 assert!(classes.classes.contains("any-pointer-fine"));
234 }
235
236 #[test]
237 fn test_motion_variant_utilities() {
238 let classes = ClassBuilder::new()
239 .motion_reduce()
240 .motion_safe()
241 .build();
242
243 assert!(classes.classes.contains("motion-reduce"));
244 assert!(classes.classes.contains("motion-safe"));
245 }
246
247 #[test]
248 fn test_color_scheme_variant_utilities() {
249 let classes = ClassBuilder::new()
250 .light()
251 .dark()
252 .build();
253
254 assert!(classes.classes.contains("light"));
255 assert!(classes.classes.contains("dark"));
256 }
257
258 #[test]
259 fn test_device_variants_comprehensive() {
260 let classes = ClassBuilder::new()
261 .pointer_coarse()
262 .pointer_fine()
263 .motion_reduce()
264 .motion_safe()
265 .light()
266 .dark()
267 .build();
268
269 assert!(classes.classes.contains("pointer-coarse"));
270 assert!(classes.classes.contains("pointer-fine"));
271 assert!(classes.classes.contains("motion-reduce"));
272 assert!(classes.classes.contains("motion-safe"));
273 assert!(classes.classes.contains("light"));
274 assert!(classes.classes.contains("dark"));
275 }
276}