feat: theme

This commit is contained in:
luoxiao 2023-11-01 14:04:12 +08:00
parent c974f80ea5
commit cf18b488db
20 changed files with 295 additions and 133 deletions

View file

@ -5,7 +5,22 @@ use melt_ui::*;
#[component] #[component]
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
let theme = create_rw_signal(Theme::light()); fn use_query_value(key: &str) -> Option<String> {
let href = window().location().href().ok()?;
let url = Url::try_from(href.as_str()).ok()?;
url.search_params.get(key).cloned()
}
let theme = use_query_value("theme").map_or_else(Theme::light, |name| {
if name == "light" {
Theme::light()
} else if name == "dark" {
Theme::dark()
} else {
Theme::light()
}
});
let theme = create_rw_signal(theme);
provide_context(theme); provide_context(theme);
view! { view! {
<Provider theme> <Provider theme>

View file

@ -1,5 +1,5 @@
use leptos::*; use leptos::*;
use leptos_router::{use_navigate, use_query_map, Url}; use leptos_router::{use_navigate, use_query_map};
use melt_ui::*; use melt_ui::*;
#[component] #[component]
@ -8,19 +8,6 @@ pub fn Home() -> impl IntoView {
// mobile page // mobile page
if let Some(path) = query_map.get("path") { if let Some(path) = query_map.get("path") {
let navigate = use_navigate(); let navigate = use_navigate();
if let Some((_, search)) = path.split_once("?") {
if let Some((key, value)) = search.split_once("=") {
if key == "theme" {
let theme = use_rw_theme();
let theme_name = theme.with_untracked(|theme| theme.name.clone());
if value == "light" && theme_name != "light" {
theme.set(Theme::light())
} else if value == "dark" && theme_name != "dark" {
theme.set(Theme::dark())
}
}
}
}
navigate(path, Default::default()); navigate(path, Default::default());
} }
view! { view! {

View file

@ -4,7 +4,7 @@ use melt_ui::{use_theme, Theme};
#[component] #[component]
pub fn MobilePage(path: &'static str) -> impl IntoView { pub fn MobilePage(path: &'static str) -> impl IntoView {
let theme = use_theme(Theme::light); let theme = use_theme(Theme::light);
let src = create_memo(move |_| theme.with(|theme| format!("{path}?theme={}", theme.name))); let src = create_memo(move |_| theme.with(|theme| format!("{path}&theme={}", theme.name)));
let style = create_memo(move |_| { let style = create_memo(move |_| {
theme.with(|theme| { theme.with(|theme| {
let mut style = String::from("margin-top: 5vh; width: 350px; height: 680px; border-radius: 16px; box-shadow: 0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03);"); let mut style = String::from("margin-top: 5vh; width: 350px; height: 680px; border-radius: 16px; box-shadow: 0 6px 16px -9px rgba(0, 0, 0, .08), 0 9px 28px 0 rgba(0, 0, 0, .05), 0 12px 48px 16px rgba(0, 0, 0, .03);");

View file

@ -3,7 +3,7 @@
display: inline-block; display: inline-block;
max-height: 200px; max-height: 200px;
padding: 5px; padding: 5px;
background-color: #fff; background-color: var(--melt-background-color);
border-radius: 3px; border-radius: 3px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12),
@ -16,5 +16,5 @@
cursor: pointer; cursor: pointer;
} }
.melt-auto-complete__menu-item:hover { .melt-auto-complete__menu-item:hover {
background-color: #f6f6f7; background-color: var(--melt-background-color-hover);
} }

View file

@ -1,5 +1,10 @@
use crate::{mount_style, teleport::Teleport, utils::maybe_rw_signal::MaybeRwSignal, Input}; mod theme;
use crate::{
mount_style, teleport::Teleport, use_theme, utils::maybe_rw_signal::MaybeRwSignal, Input, Theme,
};
use leptos::*; use leptos::*;
pub use theme::AutoCompleteTheme;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct AutoCompleteOption { pub struct AutoCompleteOption {
@ -14,6 +19,22 @@ pub fn AutoComplete(
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>, #[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
) -> impl IntoView { ) -> impl IntoView {
mount_style("auto-complete", include_str!("./auto-complete.css")); mount_style("auto-complete", include_str!("./auto-complete.css"));
let theme = use_theme(Theme::light);
let menu_css_vars = create_memo(move |_| {
let mut css_vars = String::new();
theme.with(|theme| {
css_vars.push_str(&format!(
"--melt-background-color: {};",
theme.select.menu_background_color
));
css_vars.push_str(&format!(
"--melt-background-color-hover: {};",
theme.select.menu_background_color_hover
));
});
css_vars
});
let is_show_menu = create_rw_signal(false); let is_show_menu = create_rw_signal(false);
let auto_complete_ref = create_node_ref::<html::Div>(); let auto_complete_ref = create_node_ref::<html::Div>();
let auto_complete_menu_ref = create_node_ref::<html::Div>(); let auto_complete_menu_ref = create_node_ref::<html::Div>();
@ -58,7 +79,7 @@ pub fn AutoComplete(
<div <div
class="melt-auto-complete__menu" class="melt-auto-complete__menu"
style=move || { style=move || {
if is_show_menu.get() { None } else { Some("display: none;") } if is_show_menu.get() { menu_css_vars.get() } else { "display: none;".to_string() }
} }
ref=auto_complete_menu_ref ref=auto_complete_menu_ref

View file

@ -0,0 +1,23 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct AutoCompleteTheme {
pub menu_background_color: String,
pub menu_background_color_hover: String,
}
impl ThemeMethod for AutoCompleteTheme {
fn light() -> Self {
Self {
menu_background_color: "#fff".into(),
menu_background_color_hover: "#f3f5f6".into(),
}
}
fn dark() -> Self {
Self {
menu_background_color: "#48484e".into(),
menu_background_color_hover: "#ffffff17".into(),
}
}
}

View file

@ -24,7 +24,7 @@
right: 0; right: 0;
width: 240px; width: 240px;
padding: 12px; padding: 12px;
background-color: #fff; background-color: var(--melt-background-color);
border-radius: 3px; border-radius: 3px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12),
@ -65,7 +65,7 @@
border-radius: 6px; border-radius: 6px;
box-sizing: border-box; box-sizing: border-box;
border: 2px solid white; border: 2px solid white;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, .45); box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.45);
} }
.melt-color-picker-slider { .melt-color-picker-slider {

View file

@ -1,14 +1,28 @@
mod color; mod color;
mod theme;
use crate::{mount_style, teleport::Teleport, utils::maybe_rw_signal::MaybeRwSignal}; use crate::{
mount_style, teleport::Teleport, use_theme, utils::maybe_rw_signal::MaybeRwSignal, Theme,
};
pub use color::*; pub use color::*;
use leptos::leptos_dom::helpers::WindowListenerHandle; use leptos::leptos_dom::helpers::WindowListenerHandle;
use leptos::*; use leptos::*;
pub use theme::ColorPickerTheme;
use wasm_bindgen::__rt::IntoJsResult; use wasm_bindgen::__rt::IntoJsResult;
#[component] #[component]
pub fn ColorPicker(#[prop(optional, into)] value: MaybeRwSignal<RGBA>) -> impl IntoView { pub fn ColorPicker(#[prop(optional, into)] value: MaybeRwSignal<RGBA>) -> impl IntoView {
mount_style("color-picker", include_str!("./color-picker.css")); mount_style("color-picker", include_str!("./color-picker.css"));
let theme = use_theme(Theme::light);
let popover_css_vars = create_memo(move |_| {
theme.with(|theme| {
format!(
"--melt-background-color: {};",
theme.color_picker.popover_background_color
)
})
});
let hue = create_rw_signal(0); let hue = create_rw_signal(0);
let sv = create_rw_signal((0.0, 0.0)); let sv = create_rw_signal((0.0, 0.0));
let label = create_rw_signal(String::new()); let label = create_rw_signal(String::new());
@ -95,7 +109,7 @@ pub fn ColorPicker(#[prop(optional, into)] value: MaybeRwSignal<RGBA>) -> impl I
class="melt-color-picker-popover" class="melt-color-picker-popover"
ref=popover_ref ref=popover_ref
style=move || { style=move || {
if !is_show_popover.get() { Some("display: none") } else { None } if is_show_popover.get() { popover_css_vars.get() } else { "display: none".to_string() }
} }
> >

20
src/color_picker/theme.rs Normal file
View file

@ -0,0 +1,20 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct ColorPickerTheme {
pub popover_background_color: String,
}
impl ThemeMethod for ColorPickerTheme {
fn light() -> Self {
Self {
popover_background_color: "#fff".into(),
}
}
fn dark() -> Self {
Self {
popover_background_color: "#48484e".into(),
}
}
}

View file

@ -1,9 +1,14 @@
mod theme;
use crate::{ use crate::{
components::*, components::*,
icon::*, icon::*,
use_theme,
utils::{mount_style::mount_style, StoredMaybeSignal}, utils::{mount_style::mount_style, StoredMaybeSignal},
Theme,
}; };
use leptos::*; use leptos::*;
pub use theme::NavBarTheme;
#[component] #[component]
pub fn NavBar( pub fn NavBar(
@ -15,6 +20,15 @@ pub fn NavBar(
#[prop(optional, into)] on_click_right: Option<Callback<ev::MouseEvent>>, #[prop(optional, into)] on_click_right: Option<Callback<ev::MouseEvent>>,
) -> impl IntoView { ) -> impl IntoView {
mount_style("nav-bar", include_str!("./nav-bar.css")); mount_style("nav-bar", include_str!("./nav-bar.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
theme.with(|theme| {
format!(
"--melt-background-color: {};",
theme.nav_bar.background_color
)
})
});
let title: StoredMaybeSignal<_> = title.into(); let title: StoredMaybeSignal<_> = title.into();
let left_text: StoredMaybeSignal<_> = left_text.into(); let left_text: StoredMaybeSignal<_> = left_text.into();
let right_text: StoredMaybeSignal<_> = right_text.into(); let right_text: StoredMaybeSignal<_> = right_text.into();
@ -32,7 +46,7 @@ pub fn NavBar(
}; };
view! { view! {
<div class="melt-nav-bar"> <div class="melt-nav-bar" style=move || css_vars.get()>
<If cond=MaybeSignal::derive(move || left_arrow.get() || !left_text.get().is_empty())> <If cond=MaybeSignal::derive(move || left_arrow.get() || !left_text.get().is_empty())>
<Then slot> <Then slot>
<div class="melt-nav-bar__left" on:click=on_click_left> <div class="melt-nav-bar__left" on:click=on_click_left>

View file

@ -5,7 +5,7 @@
right: 0; right: 0;
height: 46px; height: 46px;
line-height: 46px; line-height: 46px;
background-color: #fff; background-color: var(--melt-background-color);
} }
.melt-nav-bar__center { .melt-nav-bar__center {

View file

@ -0,0 +1,20 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct NavBarTheme {
pub background_color: String,
}
impl ThemeMethod for NavBarTheme {
fn light() -> Self {
Self {
background_color: "#fff".into(),
}
}
fn dark() -> Self {
Self {
background_color: "#323233".into(),
}
}
}

View file

@ -1,9 +1,14 @@
mod tabbar_item; mod tabbar_item;
mod theme;
use crate::utils::{maybe_rw_signal::MaybeRwSignal, mount_style::mount_style}; use crate::{
use_theme,
utils::{maybe_rw_signal::MaybeRwSignal, mount_style::mount_style},
Theme,
};
use leptos::*; use leptos::*;
pub use tabbar_item::*; pub use tabbar_item::*;
pub use theme::TabbarTheme;
#[component] #[component]
pub fn Tabbar( pub fn Tabbar(
@ -11,6 +16,15 @@ pub fn Tabbar(
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
mount_style("tabbar", include_str!("./tabbar.css")); mount_style("tabbar", include_str!("./tabbar.css"));
let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| {
theme.with(|theme| {
format!(
"--melt-background-color: {};",
theme.tabbar.background_color
)
})
});
let tabbar_injection_key = create_rw_signal(TabbarInjectionKey::new(value.get())); let tabbar_injection_key = create_rw_signal(TabbarInjectionKey::new(value.get()));
create_effect(move |_| { create_effect(move |_| {
@ -29,7 +43,7 @@ pub fn Tabbar(
} }
}); });
provide_context(tabbar_injection_key); provide_context(tabbar_injection_key);
view! { <div class="melt-tabbar">{children()}</div> } view! { <div class="melt-tabbar" style=move || css_vars.get()>{children()}</div> }
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -1,5 +1,5 @@
.melt-tabbar { .melt-tabbar {
background-color: #fff; background-color: var(--melt-background-color);
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;

View file

@ -0,0 +1,20 @@
use crate::theme::ThemeMethod;
#[derive(Clone)]
pub struct TabbarTheme {
pub background_color: String,
}
impl ThemeMethod for TabbarTheme {
fn light() -> Self {
Self {
background_color: "#fff".into(),
}
}
fn dark() -> Self {
Self {
background_color: "#323233".into(),
}
}
}

View file

@ -47,16 +47,16 @@ where
css_vars css_vars
}); });
let popover_css_vars = create_memo(move |_| { let menu_css_vars = create_memo(move |_| {
let mut css_vars = String::new(); let mut css_vars = String::new();
theme.with(|theme| { theme.with(|theme| {
css_vars.push_str(&format!( css_vars.push_str(&format!(
"--melt-background-color: {};", "--melt-background-color: {};",
theme.select.popover_background_color theme.select.menu_background_color
)); ));
css_vars.push_str(&format!( css_vars.push_str(&format!(
"--melt-background-color-hover: {};", "--melt-background-color-hover: {};",
theme.select.popover_background_color_hover theme.select.menu_background_color_hover
)); ));
css_vars.push_str(&format!("--melt-font-color: {};", theme.select.font_color)); css_vars.push_str(&format!("--melt-font-color: {};", theme.select.font_color));
css_vars.push_str(&format!( css_vars.push_str(&format!(
@ -67,14 +67,14 @@ where
css_vars css_vars
}); });
let is_show_popover = create_rw_signal(false); let is_show_menu = create_rw_signal(false);
let trigger_ref = create_node_ref::<html::Div>(); let trigger_ref = create_node_ref::<html::Div>();
let popover_ref = create_node_ref::<html::Div>(); let menu_ref = create_node_ref::<html::Div>();
let show_popover = move |_| { let show_menu = move |_| {
let rect = trigger_ref.get().unwrap().get_bounding_client_rect(); let rect = trigger_ref.get().unwrap().get_bounding_client_rect();
is_show_popover.set(true); is_show_menu.set(true);
if let Some(popover_ref) = popover_ref.get() { if let Some(menu_ref) = menu_ref.get() {
popover_ref menu_ref
.style("width", format!("{}px", rect.width())) .style("width", format!("{}px", rect.width()))
.style( .style(
"transform", "transform",
@ -95,14 +95,14 @@ where
if current_el == *body { if current_el == *body {
break; break;
}; };
if current_el == ***popover_ref.get().unwrap() if current_el == ***menu_ref.get().unwrap()
|| current_el == ***trigger_ref.get().unwrap() || current_el == ***trigger_ref.get().unwrap()
{ {
return; return;
} }
el = current_el.parent_element(); el = current_el.parent_element();
} }
is_show_popover.set(false); is_show_menu.set(false);
}); });
on_cleanup(move || timer.remove()); on_cleanup(move || timer.remove());
@ -116,7 +116,7 @@ where
None => String::new(), None => String::new(),
}); });
view! { view! {
<div class="melt-select" ref=trigger_ref on:click=show_popover style=move || css_vars.get()> <div class="melt-select" ref=trigger_ref on:click=show_menu style=move || css_vars.get()>
{move || select_option_label.get()} {move || select_option_label.get()}
@ -125,14 +125,14 @@ where
<div <div
class="melt-select-menu" class="melt-select-menu"
style=move || { style=move || {
if is_show_popover.get() { if is_show_menu.get() {
popover_css_vars.get() menu_css_vars.get()
} else { } else {
"display: none;".into() "display: none;".into()
} }
} }
ref=popover_ref ref=menu_ref
> >
<For <For
each=move || options.get() each=move || options.get()
@ -142,7 +142,7 @@ where
let onclick = move |_| { let onclick = move |_| {
let SelectOption { value: item_value, label: _ } = item.get_value(); let SelectOption { value: item_value, label: _ } = item.get_value();
value.set(Some(item_value)); value.set(Some(item_value));
is_show_popover.set(false); is_show_menu.set(false);
}; };
view! { view! {
<div <div

View file

@ -5,8 +5,8 @@ pub struct SelectTheme {
pub font_color: String, pub font_color: String,
pub border_color: String, pub border_color: String,
pub background_color: String, pub background_color: String,
pub popover_background_color: String, pub menu_background_color: String,
pub popover_background_color_hover: String, pub menu_background_color_hover: String,
} }
impl ThemeMethod for SelectTheme { impl ThemeMethod for SelectTheme {
@ -15,8 +15,8 @@ impl ThemeMethod for SelectTheme {
font_color: "#333639".into(), font_color: "#333639".into(),
border_color: "#e0e0e6".into(), border_color: "#e0e0e6".into(),
background_color: "#fff".into(), background_color: "#fff".into(),
popover_background_color: "#fff".into(), menu_background_color: "#fff".into(),
popover_background_color_hover: "#f3f5f6".into(), menu_background_color_hover: "#f3f5f6".into(),
} }
} }
@ -25,8 +25,8 @@ impl ThemeMethod for SelectTheme {
font_color: "#ffffffd1".into(), font_color: "#ffffffd1".into(),
border_color: "#0000".into(), border_color: "#0000".into(),
background_color: "#ffffff1a".into(), background_color: "#ffffff1a".into(),
popover_background_color: "#48484e".into(), menu_background_color: "#48484e".into(),
popover_background_color_hover: "#ffffff17".into(), menu_background_color_hover: "#ffffff17".into(),
} }
} }
} }

View file

@ -2,8 +2,10 @@ mod common;
use self::common::CommonTheme; use self::common::CommonTheme;
use crate::{ use crate::{
AlertTheme, AvatarTheme, ButtonTheme, InputTheme, MenuTheme, MessageTheme, SelectTheme, mobile::{NavBarTheme, TabbarTheme},
SkeletionTheme, SliderTheme, SwitchTheme, TableTheme, TagTheme, UploadTheme, AlertTheme, AutoCompleteTheme, AvatarTheme, ButtonTheme, ColorPickerTheme, InputTheme,
MenuTheme, MessageTheme, SelectTheme, SkeletionTheme, SliderTheme, SwitchTheme, TableTheme,
TagTheme, UploadTheme,
}; };
use leptos::*; use leptos::*;
@ -29,6 +31,10 @@ pub struct Theme {
pub slider: SliderTheme, pub slider: SliderTheme,
pub switch: SwitchTheme, pub switch: SwitchTheme,
pub upload: UploadTheme, pub upload: UploadTheme,
pub nav_bar: NavBarTheme,
pub tabbar: TabbarTheme,
pub auto_complete: AutoCompleteTheme,
pub color_picker: ColorPickerTheme,
} }
impl Theme { impl Theme {
@ -49,6 +55,10 @@ impl Theme {
slider: SliderTheme::light(), slider: SliderTheme::light(),
switch: SwitchTheme::light(), switch: SwitchTheme::light(),
upload: UploadTheme::light(), upload: UploadTheme::light(),
nav_bar: NavBarTheme::light(),
tabbar: TabbarTheme::light(),
auto_complete: AutoCompleteTheme::light(),
color_picker: ColorPickerTheme::light(),
} }
} }
pub fn dark() -> Self { pub fn dark() -> Self {
@ -68,6 +78,10 @@ impl Theme {
slider: SliderTheme::dark(), slider: SliderTheme::dark(),
switch: SwitchTheme::dark(), switch: SwitchTheme::dark(),
upload: UploadTheme::dark(), upload: UploadTheme::dark(),
nav_bar: NavBarTheme::dark(),
tabbar: TabbarTheme::dark(),
auto_complete: AutoCompleteTheme::dark(),
color_picker: ColorPickerTheme::dark(),
} }
} }
} }

View file

@ -1,89 +1,89 @@
use leptos::StoredValue; // use leptos::StoredValue;
use std::{fmt, future::Future, pin::Pin, rc::Rc}; // use std::{fmt, future::Future, pin::Pin, rc::Rc};
pub struct AsyncCallback<In: 'static, Out: 'static = ()>( // pub struct AsyncCallback<In: 'static, Out: 'static = ()>(
#[allow(clippy::complexity)] StoredValue<Rc<dyn Fn(In) -> Pin<Box<dyn Future<Output = Out>>>>>, // #[allow(clippy::complexity)] StoredValue<Rc<dyn Fn(In) -> Pin<Box<dyn Future<Output = Out>>>>>,
); // );
impl<In> fmt::Debug for AsyncCallback<In> { // impl<In> fmt::Debug for AsyncCallback<In> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { // fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
fmt.write_str("AsyncCallback") // fmt.write_str("AsyncCallback")
} // }
} // }
impl<In, Out> Clone for AsyncCallback<In, Out> { // impl<In, Out> Clone for AsyncCallback<In, Out> {
fn clone(&self) -> Self { // fn clone(&self) -> Self {
*self // *self
} // }
} // }
impl<In, Out> Copy for AsyncCallback<In, Out> {} // impl<In, Out> Copy for AsyncCallback<In, Out> {}
impl<In, Out> AsyncCallback<In, Out> { // impl<In, Out> AsyncCallback<In, Out> {
pub fn new<F, Fu>(f: F) -> Self // pub fn new<F, Fu>(f: F) -> Self
where // where
F: Fn(In) -> Fu + 'static, // F: Fn(In) -> Fu + 'static,
Fu: Future<Output = Out> + 'static, // Fu: Future<Output = Out> + 'static,
{ // {
let f = Rc::new(move |input: In| { // let f = Rc::new(move |input: In| {
let fut = f(input); // let fut = f(input);
Box::pin(fut) as Pin<Box<dyn Future<Output = Out>>> // Box::pin(fut) as Pin<Box<dyn Future<Output = Out>>>
}); // });
Self(StoredValue::new(f)) // Self(StoredValue::new(f))
} // }
pub async fn call(&self, input: In) -> Out { // pub async fn call(&self, input: In) -> Out {
let f = self.0.get_value(); // let f = self.0.get_value();
f(input).await // f(input).await
} // }
} // }
impl<F, In, Fu, Out> From<F> for AsyncCallback<In, Out> // impl<F, In, Fu, Out> From<F> for AsyncCallback<In, Out>
where // where
F: Fn(In) -> Fu + 'static, // F: Fn(In) -> Fu + 'static,
Fu: Future<Output = Out> + 'static, // Fu: Future<Output = Out> + 'static,
{ // {
fn from(f: F) -> AsyncCallback<In, Out> { // fn from(f: F) -> AsyncCallback<In, Out> {
AsyncCallback::new(f) // AsyncCallback::new(f)
} // }
} // }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use crate::utils::AsyncCallback; // use crate::utils::AsyncCallback;
use leptos::create_runtime; // use leptos::create_runtime;
struct NoClone {} // struct NoClone {}
#[test] // #[test]
fn clone_async_callback() { // fn clone_async_callback() {
let rt = create_runtime(); // let rt = create_runtime();
let callback = AsyncCallback::new(move |_no_clone: NoClone| async { NoClone {} }); // let callback = AsyncCallback::new(move |_no_clone: NoClone| async { NoClone {} });
let _cloned = callback.clone(); // let _cloned = callback.clone();
rt.dispose(); // rt.dispose();
} // }
#[test] // #[test]
fn async_callback_from() { // fn async_callback_from() {
let rt = create_runtime(); // let rt = create_runtime();
let _callback: AsyncCallback<(), String> = (|()| async { "test".to_string() }).into(); // let _callback: AsyncCallback<(), String> = (|()| async { "test".to_string() }).into();
rt.dispose(); // rt.dispose();
} // }
#[test] // #[test]
fn async_callback_from_html() { // fn async_callback_from_html() {
let rt = create_runtime(); // let rt = create_runtime();
use leptos::{ // use leptos::{
html::{HtmlElement, H1}, // html::{HtmlElement, H1},
*, // *,
}; // };
let _callback: AsyncCallback<String, HtmlElement<H1>> = (|x: String| async move { // let _callback: AsyncCallback<String, HtmlElement<H1>> = (|x: String| async move {
view! { // view! {
<h1>{x}</h1> // <h1>{x}</h1>
} // }
}) // })
.into(); // .into();
rt.dispose(); // rt.dispose();
} // }
} // }

View file

@ -1,8 +1,8 @@
mod callback; // mod callback;
pub mod maybe_rw_signal; pub mod maybe_rw_signal;
mod maybe_signal_store; mod maybe_signal_store;
pub mod mount_style; pub mod mount_style;
pub mod signal; pub mod signal;
pub use callback::AsyncCallback; // pub use callback::AsyncCallback;
pub use maybe_signal_store::*; pub use maybe_signal_store::*;