kael_ui 0.2.0

Professional shadcn-inspired UI component library for Kael. 100+ accessible components for building beautiful, performant desktop applications.
use kael::*;
use std::time::Duration;

use crate::animations::easings;

#[derive(IntoElement)]
pub struct ContentTransition {
    id: ElementId,
    old_content: Option<AnyElement>,
    new_content: AnyElement,
    duration: Duration,
    transitioning: bool,
}

impl ContentTransition {
    pub fn new(id: impl Into<ElementId>, content: impl IntoElement) -> Self {
        Self {
            id: id.into(),
            old_content: None,
            new_content: content.into_any_element(),
            duration: Duration::from_millis(200),
            transitioning: false,
        }
    }

    pub fn duration(mut self, duration: Duration) -> Self {
        self.duration = duration;
        self
    }

    pub fn crossfade_from(mut self, old: impl IntoElement) -> Self {
        self.old_content = Some(old.into_any_element());
        self.transitioning = true;
        self
    }
}

impl RenderOnce for ContentTransition {
    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
        let duration = self.duration;

        if self.transitioning {
            let mut container = div().relative().size_full();

            if let Some(old) = self.old_content {
                container = container.child(div().absolute().inset_0().child(old).with_animation(
                    ElementId::Name(format!("{}-old", self.id).into()),
                    Animation::new(duration).with_easing(easings::ease_in_cubic),
                    |el, delta| el.opacity(1.0 - delta),
                ));
            }

            container = container.child(div().size_full().child(self.new_content).with_animation(
                ElementId::Name(format!("{}-new", self.id).into()),
                Animation::new(duration).with_easing(easings::ease_out_cubic),
                |el, delta| el.opacity(delta),
            ));

            container
        } else {
            div().size_full().child(self.new_content)
        }
    }
}

pub struct ContentTransitionState {
    current_key: u64,
}

impl ContentTransitionState {
    pub fn new() -> Self {
        Self { current_key: 0 }
    }

    pub fn set_key(&mut self, key: u64) -> bool {
        if self.current_key != key {
            self.current_key = key;
            true
        } else {
            false
        }
    }

    pub fn key(&self) -> u64 {
        self.current_key
    }
}

impl Default for ContentTransitionState {
    fn default() -> Self {
        Self::new()
    }
}