tailwind_rs_core/utilities/
animations.rs

1//! Animation utilities for tailwind-rs
2//!
3//! This module provides utilities for CSS animations including animate-none,
4//! animate-spin, animate-ping, animate-pulse, and animate-bounce.
5
6use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10/// Animation values
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum Animation {
13    /// No animation
14    None,
15    /// Spin animation
16    Spin,
17    /// Ping animation
18    Ping,
19    /// Pulse animation
20    Pulse,
21    /// Bounce animation
22    Bounce,
23}
24
25impl Animation {
26    pub fn to_class_name(&self) -> String {
27        match self {
28            Animation::None => "none".to_string(),
29            Animation::Spin => "spin".to_string(),
30            Animation::Ping => "ping".to_string(),
31            Animation::Pulse => "pulse".to_string(),
32            Animation::Bounce => "bounce".to_string(),
33        }
34    }
35    
36    pub fn to_css_value(&self) -> String {
37        match self {
38            Animation::None => "none".to_string(),
39            Animation::Spin => "spin 1s linear infinite".to_string(),
40            Animation::Ping => "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite".to_string(),
41            Animation::Pulse => "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite".to_string(),
42            Animation::Bounce => "bounce 1s infinite".to_string(),
43        }
44    }
45}
46
47impl fmt::Display for Animation {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(f, "{}", self.to_class_name())
50    }
51}
52
53/// Trait for adding animation utilities to a class builder
54pub trait AnimationUtilities {
55    fn animation(self, animation: Animation) -> Self;
56}
57
58impl AnimationUtilities for ClassBuilder {
59    fn animation(self, animation: Animation) -> Self {
60        self.class(format!("animate-{}", animation.to_class_name()))
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    
68    #[test]
69    fn test_animation_utilities() {
70        let classes = ClassBuilder::new()
71            .animation(Animation::None)
72            .animation(Animation::Spin)
73            .animation(Animation::Ping)
74            .animation(Animation::Pulse)
75            .animation(Animation::Bounce)
76            .build();
77        
78        let css_classes = classes.to_css_classes();
79        assert!(css_classes.contains("animate-none"));
80        assert!(css_classes.contains("animate-spin"));
81        assert!(css_classes.contains("animate-ping"));
82        assert!(css_classes.contains("animate-pulse"));
83        assert!(css_classes.contains("animate-bounce"));
84    }
85    
86    /// Test that all Week 12 animation utilities are implemented
87    #[test]
88    fn test_week12_animation_utilities() {
89        // Test all Week 12 animation utilities
90        let classes = ClassBuilder::new()
91            .animation(Animation::None)
92            .animation(Animation::Spin)
93            .animation(Animation::Ping)
94            .animation(Animation::Pulse)
95            .animation(Animation::Bounce)
96            .build();
97        
98        let css_classes = classes.to_css_classes();
99        
100        // Animations
101        assert!(css_classes.contains("animate-none"));
102        assert!(css_classes.contains("animate-spin"));
103        assert!(css_classes.contains("animate-ping"));
104        assert!(css_classes.contains("animate-pulse"));
105        assert!(css_classes.contains("animate-bounce"));
106    }
107}