1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
6pub struct MotionDuration(u32);
7
8impl MotionDuration {
9 pub fn from_millis(value: u32) -> Self {
10 Self(value)
11 }
12
13 pub fn millis(self) -> u32 {
14 self.0
15 }
16
17 pub fn is_instant(self) -> bool {
18 self.0 == 0
19 }
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
24pub enum MotionCurve {
25 Linear,
26 Ease,
27 EaseIn,
28 EaseOut,
29 EaseInOut,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
34pub enum MotionPreference {
35 NoPreference,
36 Reduced,
37}
38
39impl MotionPreference {
40 pub fn allows_motion(self) -> bool {
41 matches!(self, Self::NoPreference)
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub struct Easing {
48 curve: MotionCurve,
49 duration: MotionDuration,
50}
51
52impl Easing {
53 pub fn new(curve: MotionCurve, duration: MotionDuration) -> Self {
54 Self { curve, duration }
55 }
56
57 pub fn curve(self) -> MotionCurve {
58 self.curve
59 }
60
61 pub fn duration(self) -> MotionDuration {
62 self.duration
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
68pub enum TransitionKind {
69 Enter,
70 Exit,
71 Move,
72 Resize,
73 Fade,
74 Scale,
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
79pub enum AnimationState {
80 Idle,
81 Pending,
82 Running,
83 Paused,
84 Finished,
85 Cancelled,
86}
87
88impl AnimationState {
89 pub fn is_terminal(self) -> bool {
90 matches!(self, Self::Finished | Self::Cancelled)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::{AnimationState, Easing, MotionCurve, MotionDuration, MotionPreference};
97
98 #[test]
99 fn checks_motion_helpers() {
100 let duration = MotionDuration::from_millis(150);
101 let easing = Easing::new(MotionCurve::EaseOut, duration);
102
103 assert_eq!(duration.millis(), 150);
104 assert!(!duration.is_instant());
105 assert!(MotionDuration::from_millis(0).is_instant());
106 assert_eq!(easing.curve(), MotionCurve::EaseOut);
107 assert_eq!(easing.duration(), duration);
108 }
109
110 #[test]
111 fn checks_motion_preference_and_state() {
112 assert!(MotionPreference::NoPreference.allows_motion());
113 assert!(!MotionPreference::Reduced.allows_motion());
114 assert!(AnimationState::Finished.is_terminal());
115 assert!(!AnimationState::Running.is_terminal());
116 }
117}