use super::types::{StackDirection, ToastAnimation, ToastDirection};
use crate::animation::{Easing, Spring};
pub fn material_snackbar() -> ToastAnimation {
ToastAnimation::SlideFade {
enter_duration_ms: 250,
exit_duration_ms: 75,
hold_duration_ms: 2000,
enter_easing: Easing::CubicBezier(0.4, 0.0, 0.2, 1.0), exit_easing: Easing::CubicBezier(0.4, 0.0, 1.0, 1.0), direction: ToastDirection::Bottom,
offset: 100.0,
}
}
pub fn material_snackbar_long() -> ToastAnimation {
ToastAnimation::SlideFade {
enter_duration_ms: 250,
exit_duration_ms: 75,
hold_duration_ms: 3500,
enter_easing: Easing::CubicBezier(0.4, 0.0, 0.2, 1.0),
exit_easing: Easing::CubicBezier(0.4, 0.0, 1.0, 1.0),
direction: ToastDirection::Bottom,
offset: 100.0,
}
}
pub fn sonner_spring() -> ToastAnimation {
ToastAnimation::StackPush {
push_duration_ms: 400,
push_easing: Easing::EASE, gap: 14.0,
scale_factor: 0.05, direction: StackDirection::Up,
}
}
pub fn ios_banner() -> ToastAnimation {
ToastAnimation::SpringBounce {
enter_spring: Spring::new().stiffness(350.0).damping(28.0),
exit_duration_ms: 200,
exit_easing: Easing::EASE_IN,
hold_duration_ms: 5000,
direction: ToastDirection::Top,
}
}
pub fn slide_fade_bottom() -> ToastAnimation {
ToastAnimation::SlideFade {
enter_duration_ms: 300,
exit_duration_ms: 300,
hold_duration_ms: 3000,
enter_easing: Easing::EASE,
exit_easing: Easing::EASE,
direction: ToastDirection::Bottom,
offset: 50.0, }
}
pub fn slide_fade_top() -> ToastAnimation {
ToastAnimation::SlideFade {
enter_duration_ms: 300,
exit_duration_ms: 200,
hold_duration_ms: 3000,
enter_easing: Easing::EASE_OUT,
exit_easing: Easing::EASE_IN,
direction: ToastDirection::Top,
offset: 50.0,
}
}
pub fn bounce_drop() -> ToastAnimation {
ToastAnimation::DropIn {
spring: Spring::new().stiffness(300.0).damping(15.0),
exit_duration_ms: 150,
exit_easing: Easing::CubicBezier(0.5, 0.0, 1.0, 1.0),
hold_duration_ms: 3000,
drop_height: 120.0,
}
}
pub fn scale_fade() -> ToastAnimation {
ToastAnimation::ScaleFade {
enter_duration_ms: 150,
exit_duration_ms: 75,
hold_duration_ms: 2000,
enter_easing: Easing::CubicBezier(0.0, 0.0, 0.2, 1.0), exit_easing: Easing::CubicBezier(0.4, 0.0, 1.0, 1.0), scale_from: 0.8,
scale_to: 1.0,
}
}
pub fn zoom_toast() -> ToastAnimation {
ToastAnimation::ScaleFade {
enter_duration_ms: 500,
exit_duration_ms: 600,
hold_duration_ms: 3000,
enter_easing: Easing::EASE_OUT,
exit_easing: Easing::EASE_IN,
scale_from: 0.3,
scale_to: 1.0,
}
}
pub fn framer_spring_toast() -> ToastAnimation {
ToastAnimation::SpringBounce {
enter_spring: Spring::new().stiffness(260.0).damping(20.0),
exit_duration_ms: 300,
exit_easing: Easing::EASE_OUT,
hold_duration_ms: 3000,
direction: ToastDirection::Bottom,
}
}
pub fn framer_spring_gentle() -> ToastAnimation {
ToastAnimation::SpringBounce {
enter_spring: Spring::new().stiffness(100.0).damping(10.0),
exit_duration_ms: 300,
exit_easing: Easing::EASE_OUT,
hold_duration_ms: 3000,
direction: ToastDirection::Bottom,
}
}
pub fn framer_spring_bouncy() -> ToastAnimation {
ToastAnimation::SpringBounce {
enter_spring: Spring::new().stiffness(300.0).damping(15.0),
exit_duration_ms: 300,
exit_easing: Easing::EASE_OUT,
hold_duration_ms: 3000,
direction: ToastDirection::Bottom,
}
}
pub fn swipe_dismiss() -> ToastAnimation {
ToastAnimation::SwipeDismiss {
velocity_threshold: 0.11,
distance_threshold: 100.0,
friction: 0.998, spring_back_spring: Spring::new().stiffness(400.0).damping(25.0),
}
}
pub fn progress_countdown() -> ToastAnimation {
ToastAnimation::ProgressBar {
enter_duration_ms: 300,
enter_easing: Easing::CubicBezier(0.68, -0.55, 0.265, 1.35), exit_duration_ms: 300,
exit_easing: Easing::EASE_OUT,
hold_duration_ms: 5000,
progress_easing: Easing::Linear,
direction: ToastDirection::Right,
}
}
pub fn progress_countdown_short() -> ToastAnimation {
ToastAnimation::ProgressBar {
enter_duration_ms: 300,
enter_easing: Easing::CubicBezier(0.68, -0.55, 0.265, 1.35),
exit_duration_ms: 300,
exit_easing: Easing::EASE_OUT,
hold_duration_ms: 3000,
progress_easing: Easing::Linear,
direction: ToastDirection::Right,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_material_snackbar() {
let anim = material_snackbar();
assert_eq!(anim.total_duration_ms(), 250 + 2000 + 75);
}
#[test]
fn test_sonner_spring() {
let anim = sonner_spring();
assert_eq!(anim.total_duration_ms(), 400);
}
#[test]
fn test_ios_banner() {
let anim = ios_banner();
let duration = anim.total_duration_ms();
assert!(duration > 5000);
assert!(duration < 10000);
}
#[test]
fn test_slide_fade_bottom() {
let anim = slide_fade_bottom();
assert_eq!(anim.total_duration_ms(), 300 + 3000 + 300);
}
#[test]
fn test_scale_fade() {
let anim = scale_fade();
assert_eq!(anim.total_duration_ms(), 150 + 2000 + 75);
}
#[test]
fn test_framer_spring_variants() {
let snappy = framer_spring_toast();
let gentle = framer_spring_gentle();
let bouncy = framer_spring_bouncy();
assert!(snappy.total_duration_ms() > 3000);
assert!(gentle.total_duration_ms() > 3000);
assert!(bouncy.total_duration_ms() > 3000);
}
#[test]
fn test_progress_countdown() {
let anim = progress_countdown();
assert_eq!(anim.total_duration_ms(), 300 + 5000 + 300);
let short = progress_countdown_short();
assert_eq!(short.total_duration_ms(), 300 + 3000 + 300);
}
#[test]
fn test_swipe_dismiss() {
let anim = swipe_dismiss();
assert_eq!(anim.total_duration_ms(), 0);
}
}