205 lines
5 KiB
Rust
205 lines
5 KiB
Rust
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>,
|
|
}
|
|
|
|
macro_rules! setter {
|
|
($fnname:ident, $varname:ident, $vartype:ident, $internal_var:ident) => {
|
|
#[must_use]
|
|
pub fn $fnname(mut self, $varname: $vartype) -> Self {
|
|
self.$internal_var = $varname;
|
|
self
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! setter_opt {
|
|
($fnname:ident, $varname:ident, $vartype:ident, $internal_var:ident) => {
|
|
#[must_use]
|
|
pub fn $fnname(mut self, $varname: $vartype) -> Self {
|
|
self.$internal_var = Some($varname);
|
|
self
|
|
}
|
|
};
|
|
}
|
|
|
|
impl AnimatedWidget {
|
|
setter!(scope, scope, Scope, scope);
|
|
setter_opt!(timing, timing, Timing, timing);
|
|
setter_opt!(delay, delay, Delay, delay);
|
|
setter_opt!(duration, duration, Duration, duration);
|
|
setter_opt!(animate, animation, Animation, animation);
|
|
}
|
|
|
|
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",
|
|
}
|
|
}
|
|
}
|