add animation

This commit is contained in:
JMARyA 2025-01-16 20:24:01 +01:00
parent 86f61ff3f6
commit bcb69805ef
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
4 changed files with 215 additions and 4 deletions

View file

@ -19,14 +19,15 @@ pub mod prelude {
pub use super::primitives::Nothing;
pub use super::primitives::Side;
pub use super::primitives::Size;
pub use super::primitives::animation::{Animated, Animation, Delay, Duration, Scope, Timing};
pub use super::primitives::aspect::Aspect;
pub use super::primitives::background::Background;
pub use super::primitives::container::Container;
pub use super::primitives::cursor::Cursor;
pub use super::primitives::div::Div;
pub use super::primitives::flex::{Flex, Justify};
pub use super::primitives::flex::{Flex, FlexBasis, FlexGrow, Justify};
pub use super::primitives::header::Header;
pub use super::primitives::height::HeightWidget;
pub use super::primitives::height::{Height, MaxHeight, MinHeight};
pub use super::primitives::image::Image;
pub use super::primitives::link::Link;
pub use super::primitives::margin::Margin;
@ -38,7 +39,7 @@ pub mod prelude {
pub use super::primitives::space::{ScreenValue, SpaceBetween};
pub use super::primitives::text::{Paragraph, Span, Text};
pub use super::primitives::visibility::Visibility;
pub use super::primitives::width::Width;
pub use super::primitives::width::{MaxWidth, MinWidth, Width};
pub use super::primitives::zindex::ZIndex;
pub use super::wrapper::Hover;
}

View file

@ -0,0 +1,204 @@
use maud::{Markup, Render, html};
use crate::ui::UIWidget;
#[allow(non_snake_case)]
pub fn Animated<T: UIWidget + 'static>(inner: T) -> AnimatedWidget {
AnimatedWidget {
inner: Box::new(inner),
scope: Scope::Normal,
timing: None,
delay: None,
duration: None,
animation: None,
}
}
pub struct AnimatedWidget {
inner: Box<dyn UIWidget>,
scope: Scope,
timing: Option<Timing>,
delay: Option<Delay>,
duration: Option<Duration>,
animation: Option<Animation>,
}
impl AnimatedWidget {
pub fn scope(mut self, scope: Scope) -> Self {
self.scope = scope;
self
}
pub fn timing(mut self, timing: Timing) -> Self {
self.timing = Some(timing);
self
}
pub fn delay(mut self, delay: Delay) -> Self {
self.delay = Some(delay);
self
}
pub fn duration(mut self, duration: Duration) -> Self {
self.duration = Some(duration);
self
}
pub fn animate(mut self, animation: Animation) -> Self {
self.animation = Some(animation);
self
}
}
impl Render for AnimatedWidget {
fn render(&self) -> Markup {
self.render_with_class("")
}
}
impl UIWidget for AnimatedWidget {
fn can_inherit(&self) -> bool {
true
}
fn base_class(&self) -> Vec<String> {
let mut ret = vec![self.scope.to_value().to_string()];
if let Some(timing) = &self.timing {
ret.push(timing.to_value().to_owned());
}
if let Some(delay) = &self.delay {
ret.push(delay.to_value());
}
if let Some(duration) = &self.duration {
ret.push(duration.to_value());
}
if let Some(anim) = &self.animation {
ret.push(anim.to_value().to_owned());
}
ret
}
fn extended_class(&self) -> Vec<String> {
let mut c = self.base_class();
c.extend_from_slice(&self.inner.extended_class());
c
}
fn render_with_class(&self, class: &str) -> Markup {
if self.inner.as_ref().can_inherit() {
self.inner
.as_ref()
.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
} else {
html! {
div class=(format!("{} {class}", self.base_class().join(" "))) {
(self.inner.as_ref())
}
}
}
}
}
pub enum Scope {
None,
All,
Normal,
Colors,
Opacity,
Shadow,
Transform,
}
impl Scope {
pub fn to_value(&self) -> &str {
match self {
Scope::None => "transition-none",
Scope::All => "transition-all",
Scope::Normal => "transition",
Scope::Colors => "transition-colors",
Scope::Opacity => "transition-opacity",
Scope::Shadow => "transition-shadow",
Scope::Transform => "transition-transform",
}
}
}
macro_rules! num_opt {
($name:ident, $id:literal) => {
pub enum $name {
Custom(String),
_0,
_75,
_100,
_150,
_200,
_300,
_500,
_700,
_1000,
}
impl $name {
pub fn to_value(&self) -> String {
match self {
Self::Custom(s) => format!("{}-[{s}]", $id),
Self::_0 => concat!($id, "-0").to_string(),
Self::_75 => concat!($id, "-75").to_string(),
Self::_100 => concat!($id, "-100").to_string(),
Self::_150 => concat!($id, "-150").to_string(),
Self::_200 => concat!($id, "-200").to_string(),
Self::_300 => concat!($id, "-300").to_string(),
Self::_500 => concat!($id, "-500").to_string(),
Self::_700 => concat!($id, "-700").to_string(),
Self::_1000 => concat!($id, "-1000").to_string(),
}
}
}
};
}
num_opt!(Duration, "duration");
num_opt!(Delay, "delay");
pub enum Timing {
EaseLinear,
EaseIn,
EaseOut,
EaseInOut,
}
impl Timing {
pub const fn to_value(&self) -> &str {
match self {
Timing::EaseLinear => "ease-linear",
Timing::EaseIn => "ease-in",
Timing::EaseOut => "ease-out",
Timing::EaseInOut => "ease-in-out",
}
}
}
pub enum Animation {
None,
Spin,
Ping,
Pulse,
Bounce,
}
impl Animation {
pub fn to_value(&self) -> &str {
match self {
Animation::None => "animate-none",
Animation::Spin => "animate-spin",
Animation::Ping => "animate-ping",
Animation::Pulse => "animate-pulse",
Animation::Bounce => "animate-bounce",
}
}
}

View file

@ -2,6 +2,7 @@ use maud::{PreEscaped, html};
use super::UIWidget;
pub mod animation;
pub mod aspect;
pub mod background;
pub mod container;

View file

@ -41,7 +41,12 @@ impl UIWidget for HoverWrapper {
}
fn extended_class(&self) -> Vec<String> {
self.base_class()
let mut ret = self.base_class();
if let Some(inner) = &self.0 {
ret.extend_from_slice(&inner.extended_class());
}
ret
}
fn render_with_class(&self, class: &str) -> Markup {