feat: add loading bar component

This commit is contained in:
luoxiao 2023-11-06 23:35:30 +08:00
parent 29068acd1a
commit a05cda35d7
5 changed files with 208 additions and 40 deletions

View file

@ -24,6 +24,14 @@ pub fn App() -> impl IntoView {
provide_context(theme); provide_context(theme);
view! { view! {
<Provider theme> <Provider theme>
<TheRouter />
</Provider>
}
}
#[component]
fn TheRouter() -> impl IntoView {
view! {
<Router base="/thaw"> <Router base="/thaw">
<Routes base="/thaw".to_string()> <Routes base="/thaw".to_string()>
<Route path="/" view=Home/> <Route path="/" view=Home/>
@ -64,7 +72,6 @@ pub fn App() -> impl IntoView {
<Route path="/mobile/toast" view=ToastDemoPage/> <Route path="/mobile/toast" view=ToastDemoPage/>
</Routes> </Routes>
</Router> </Router>
</Provider>
} }
} }

View file

@ -16,6 +16,7 @@ mod image;
mod input; mod input;
mod input_number; mod input_number;
mod layout; mod layout;
mod loading_bar;
mod menu; mod menu;
mod message; mod message;
pub mod mobile; pub mod mobile;
@ -53,6 +54,7 @@ pub use image::*;
pub use input::*; pub use input::*;
pub use input_number::*; pub use input_number::*;
pub use layout::*; pub use layout::*;
pub use loading_bar::*;
pub use menu::*; pub use menu::*;
pub use message::*; pub use message::*;
pub use modal::*; pub use modal::*;

View file

@ -0,0 +1,11 @@
.thaw-loading-bar-container {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}
.thaw-loading-bar {
height: 2px;
max-width: 0;
}

View file

@ -0,0 +1,46 @@
use super::{LoadingBar, LoadingBarRef};
use crate::{teleport::Teleport, utils::ComponentRef};
use leptos::*;
#[component]
pub fn LoadingBarProvider(children: Children) -> impl IntoView {
let loading_bar_ref = ComponentRef::<LoadingBarRef>::default();
provide_context(LoadingBarInjection { loading_bar_ref });
view! {
{children()}
<Teleport>
<LoadingBar comp_ref=loading_bar_ref/>
</Teleport>
}
}
#[derive(Clone)]
pub struct LoadingBarInjection {
loading_bar_ref: ComponentRef<LoadingBarRef>,
}
impl Copy for LoadingBarInjection {}
impl LoadingBarInjection {
pub fn start(&self) {
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
loading_bar_ref.start();
}
}
pub fn finish(&self) {
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
loading_bar_ref.finish();
}
}
pub fn error(&self) {
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
loading_bar_ref.error();
}
}
}
pub fn use_loading_bar() -> LoadingBarInjection {
expect_context::<LoadingBarInjection>()
}

102
src/loading_bar/mod.rs Normal file
View file

@ -0,0 +1,102 @@
mod loading_bar_provider;
use crate::{mount_style, use_theme, utils::ComponentRef, Theme};
use leptos::*;
pub use loading_bar_provider::{use_loading_bar, LoadingBarProvider};
#[derive(Clone)]
pub struct LoadingBarRef {
start: Callback<()>,
finish: Callback<()>,
error: Callback<()>,
}
impl LoadingBarRef {
pub fn start(&self) {
self.start.call(());
}
pub fn finish(&self) {
self.finish.call(());
}
pub fn error(&self) {
self.error.call(());
}
}
#[component]
pub fn LoadingBar(#[prop(optional)] comp_ref: ComponentRef<LoadingBarRef>) -> impl IntoView {
mount_style("loading-bar", include_str!("./loading-bar.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
let mut css_vars = String::new();
theme.with(|theme| {
css_vars.push_str(&format!(
"--thaw-background-color: {};",
theme.common.color_success
));
css_vars.push_str(&format!(
"--thaw-background-color-error: {};",
theme.common.color_error
));
});
css_vars
});
let loading_bar_ref = create_node_ref::<html::Div>();
let loading = create_rw_signal(false);
let start = Callback::new(move |_| {
loading.set(true);
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
let loading_bar_ref = loading_bar_ref
.style("background-color", "var(--thaw-background-color)")
.style("transition", "none")
.style("max-width", "0");
_ = loading_bar_ref.offset_width();
loading_bar_ref
.style("transition", "max-width 4s linear")
.style("max-width", "80%");
}
});
let finish = Callback::new(move |_| {
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
let loading_bar_ref = loading_bar_ref
.style("background-color", "var(--thaw-background-color)")
.style("transition", "max-width 0.5s linear")
.style("max-width", "1000%");
loading_bar_ref.on(ev::transitionend, move |_| {
loading.set(false);
});
}
});
let error = Callback::new(move |_| {
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
if !loading.get() {
loading.set(true);
let loading_bar_ref = loading_bar_ref.clone();
let loading_bar_ref = loading_bar_ref
.style("transition", "none")
.style("max-width", "0");
_ = loading_bar_ref.offset_width();
}
let loading_bar_ref = loading_bar_ref
.style("background-color", "var(--thaw-background-color-error)")
.style("transition", "max-width 0.5s linear")
.style("max-width", "100%");
loading_bar_ref.on(ev::transitionend, move |_| {
loading.set(false);
});
}
});
comp_ref.load(LoadingBarRef {
start,
finish,
error,
});
view! {
<div class="thaw-loading-bar-container">
<div class="thaw-loading-bar" ref=loading_bar_ref style=move || css_vars.get()>
</div>
</div>
}
}