use std::time::Duration;
use gpui::{Div, ElementId, Hsla, InteractiveElement, Pixels, Stateful, Styled};
pub trait AnimateExt {
fn animate_fade(
self,
id: impl Into<ElementId>,
duration: Duration,
progress: f32,
) -> Stateful<Self>
where
Self: Sized;
fn animate_slide(
self,
id: impl Into<ElementId>,
direction: SlideDirection,
distance: Pixels,
duration: Duration,
progress: f32,
) -> Stateful<Self>
where
Self: Sized;
fn animate_scale(
self,
id: impl Into<ElementId>,
duration: Duration,
progress: f32,
) -> Stateful<Self>
where
Self: Sized;
}
#[derive(Debug, Clone, Copy)]
pub enum SlideDirection {
Left,
Right,
Up,
Down,
}
impl AnimateExt for Div {
fn animate_fade(
self,
id: impl Into<ElementId>,
_duration: Duration,
progress: f32,
) -> Stateful<Self> {
self.id(id).opacity(progress)
}
fn animate_slide(
self,
id: impl Into<ElementId>,
direction: SlideDirection,
distance: Pixels,
_duration: Duration,
progress: f32,
) -> Stateful<Self> {
let distance_f: f32 = distance.into();
let (ml, mt) = match direction {
SlideDirection::Left => (gpui::px(distance_f * (progress - 1.0)), gpui::px(0.0)),
SlideDirection::Right => (gpui::px(distance_f * (1.0 - progress)), gpui::px(0.0)),
SlideDirection::Up => (gpui::px(0.0), gpui::px(distance_f * (progress - 1.0))),
SlideDirection::Down => (gpui::px(0.0), gpui::px(distance_f * (1.0 - progress))),
};
self.id(id).opacity(progress).ml(ml).mt(mt)
}
fn animate_scale(
self,
id: impl Into<ElementId>,
_duration: Duration,
progress: f32,
) -> Stateful<Self> {
self.id(id).opacity(progress)
}
}
pub fn lerp(start: f32, end: f32, t: f32) -> f32 {
start + (end - start) * t
}
pub fn lerp_color(start: Hsla, end: Hsla, t: f32) -> Hsla {
Hsla {
h: lerp(start.h, end.h, t),
s: lerp(start.s, end.s, t),
l: lerp(start.l, end.l, t),
a: lerp(start.a, end.a, t),
}
}
pub fn animation_id(prefix: &str, state: impl std::fmt::Debug) -> String {
format!("{}:{:?}", prefix, state)
}