Skip to main content

orbital_motion/
atom.rs

1//! Motion atoms: one enter or exit leg of a presence transition.
2//!
3//! Each [`MotionAtom`] maps to a CSS keyframe family (`orbital-motion-fade`, `orbital-motion-scale`,
4//! `orbital-motion-slide-*`, etc.). Pair atoms with [`crate::PresenceMotion`] for enter+exit presets,
5//! or compose manually via [`PresenceMotion::new`](crate::PresenceMotion::new).
6
7use crate::tokens::{MotionCurve, MotionDuration};
8
9/// Slide direction for [`MotionAtom::slide`] and [`crate::PresenceMotion::slide`].
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
11pub enum SlideFrom {
12    #[default]
13    Bottom,
14    Top,
15    Left,
16    Right,
17}
18
19impl SlideFrom {
20    pub const fn keyframes_suffix(self) -> &'static str {
21        match self {
22            Self::Bottom => "bottom",
23            Self::Top => "top",
24            Self::Left => "left",
25            Self::Right => "right",
26        }
27    }
28}
29
30/// One-shot motion descriptor (enter or exit leg of a presence transition).
31#[derive(Clone, Copy, Debug, PartialEq, Eq)]
32pub struct MotionAtom {
33    pub keyframes: &'static str,
34    pub duration: MotionDuration,
35    pub curve: MotionCurve,
36    pub delay: Option<MotionDuration>,
37}
38
39impl MotionAtom {
40    pub const fn new(
41        keyframes: &'static str,
42        duration: MotionDuration,
43        curve: MotionCurve,
44    ) -> Self {
45        Self {
46            keyframes,
47            duration,
48            curve,
49            delay: None,
50        }
51    }
52
53    pub const fn with_delay(mut self, delay: MotionDuration) -> Self {
54        self.delay = Some(delay);
55        self
56    }
57
58    pub const fn fade() -> Self {
59        Self::new(
60            "orbital-motion-fade",
61            MotionDuration::Normal,
62            MotionCurve::EasyEase,
63        )
64    }
65
66    pub const fn scale() -> Self {
67        Self::new(
68            "orbital-motion-scale",
69            MotionDuration::Normal,
70            MotionCurve::EasyEase,
71        )
72    }
73
74    pub const fn slide(from: SlideFrom) -> Self {
75        Self::new(
76            match from {
77                SlideFrom::Bottom => "orbital-motion-slide-bottom",
78                SlideFrom::Top => "orbital-motion-slide-top",
79                SlideFrom::Left => "orbital-motion-slide-left",
80                SlideFrom::Right => "orbital-motion-slide-right",
81            },
82            MotionDuration::Normal,
83            MotionCurve::DecelerateMid,
84        )
85    }
86
87    pub const fn collapse() -> Self {
88        Self::new(
89            "orbital-motion-collapse",
90            MotionDuration::Normal,
91            MotionCurve::EasyEaseMax,
92        )
93    }
94
95    pub const fn blur() -> Self {
96        Self::new(
97            "orbital-motion-blur",
98            MotionDuration::Normal,
99            MotionCurve::EasyEase,
100        )
101    }
102
103    pub const fn rotate() -> Self {
104        Self::new(
105            "orbital-motion-rotate",
106            MotionDuration::Normal,
107            MotionCurve::EasyEase,
108        )
109    }
110
111    pub const fn with_duration(mut self, duration: MotionDuration) -> Self {
112        self.duration = duration;
113        self
114    }
115
116    pub const fn with_curve(mut self, curve: MotionCurve) -> Self {
117        self.curve = curve;
118        self
119    }
120}