thaw 0.4.8

An easy to use leptos component library
Documentation
mod loading_bar_provider;

pub use loading_bar_provider::*;

use crate::ConfigInjection;
use leptos::{html, prelude::*};
use std::sync::Arc;
use thaw_utils::{mount_style, ComponentRef};

#[derive(Clone)]
pub(crate) struct LoadingBarRef {
    start: Arc<dyn Fn() + Send + Sync + 'static>,
    finish: Arc<dyn Fn() + Send + Sync + 'static>,
    error: Arc<dyn Fn() + Send + Sync + 'static>,
}

impl LoadingBarRef {
    #[inline]
    pub fn start(&self) {
        (self.start)();
    }
    #[inline]
    pub fn finish(&self) {
        (self.finish)();
    }
    #[inline]
    pub fn error(&self) {
        (self.error)();
    }
}

#[component]
fn LoadingBar(#[prop(optional)] comp_ref: ComponentRef<LoadingBarRef>) -> impl IntoView {
    mount_style("loading-bar", include_str!("./loading-bar.css"));
    let config_provider = ConfigInjection::expect_context();
    let container_ref = NodeRef::<html::Div>::new();
    let loading_bar_ref = NodeRef::<html::Div>::new();

    let start = Arc::new(move || {
        let Some(container_el) = container_ref.get_untracked() else {
            return;
        };
        let Some(loading_bar_el) = loading_bar_ref.get_untracked() else {
            return;
        };
        let _ = container_el.set_attribute("style", "");
        loading_bar_el.style(("background-color", "var(--colorStatusSuccessForeground1)"));
        loading_bar_el.style(("transition", "none"));
        loading_bar_el.style(("max-width", "0"));
        let _ = loading_bar_el.offset_width();
        loading_bar_el.style(("transition", "max-width 4s linear"));
        loading_bar_el.style(("max-width", "80%"));
    });
    let on_transitionend = move |_| {
        let Some(container_el) = container_ref.get_untracked() else {
            return;
        };
        let Some(loading_bar_el) = loading_bar_ref.get_untracked() else {
            return;
        };
        if let Ok(max_width) = Dom::style(&loading_bar_el).get_property_value("max-width") {
            if max_width == "100%" {
                let _ = container_el.set_attribute("style", "display: none");
            }
        }
    };
    let finish = Arc::new(move || {
        let Some(loading_bar_el) = loading_bar_ref.get_untracked() else {
            return;
        };
        loading_bar_el.style(("background-color", "var(--colorStatusSuccessForeground1)"));
        loading_bar_el.style(("transition", "max-width 0.5s linear"));
        loading_bar_el.style(("max-width", "100%"));
    });
    let error = Arc::new(move || {
        let Some(container_el) = container_ref.get_untracked() else {
            return;
        };
        let Some(loading_bar_el) = loading_bar_ref.get_untracked() else {
            return;
        };
        if container_el.get_attribute("style") != Some(String::new()) {
            let _ = container_el.set_attribute("style", "");
            loading_bar_el.style(("transition", "none"));
            loading_bar_el.style(("max-width", "0"));
            let _ = loading_bar_el.offset_width();
        }
        loading_bar_el.style(("background-color", "var(--colorStatusDangerForeground1)"));
        loading_bar_el.style(("transition", "max-width 0.5s linear"));
        loading_bar_el.style(("max-width", "100%"));
    });

    comp_ref.load(LoadingBarRef {
        start,
        finish,
        error,
    });
    view! {
        <div
            class="thaw-config-provider thaw-loading-bar-container"
            data-thaw-id=config_provider.id()
            style="display: none"
            node_ref=container_ref
        >
            <div
                class="thaw-loading-bar"
                node_ref=loading_bar_ref
                on:transitionend=on_transitionend
            ></div>
        </div>
    }
}