mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
feat: theme
This commit is contained in:
parent
c974f80ea5
commit
cf18b488db
20 changed files with 295 additions and 133 deletions
|
@ -5,7 +5,22 @@ use melt_ui::*;
|
|||
|
||||
#[component]
|
||||
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);
|
||||
view! {
|
||||
<Provider theme>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use leptos::*;
|
||||
use leptos_router::{use_navigate, use_query_map, Url};
|
||||
use leptos_router::{use_navigate, use_query_map};
|
||||
use melt_ui::*;
|
||||
|
||||
#[component]
|
||||
|
@ -8,19 +8,6 @@ pub fn Home() -> impl IntoView {
|
|||
// mobile page
|
||||
if let Some(path) = query_map.get("path") {
|
||||
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());
|
||||
}
|
||||
view! {
|
||||
|
|
|
@ -4,7 +4,7 @@ use melt_ui::{use_theme, Theme};
|
|||
#[component]
|
||||
pub fn MobilePage(path: &'static str) -> impl IntoView {
|
||||
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 |_| {
|
||||
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);");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
display: inline-block;
|
||||
max-height: 200px;
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
background-color: var(--melt-background-color);
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
|
@ -16,5 +16,5 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
.melt-auto-complete__menu-item:hover {
|
||||
background-color: #f6f6f7;
|
||||
background-color: var(--melt-background-color-hover);
|
||||
}
|
||||
|
|
|
@ -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::*;
|
||||
pub use theme::AutoCompleteTheme;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct AutoCompleteOption {
|
||||
|
@ -14,6 +19,22 @@ pub fn AutoComplete(
|
|||
#[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>,
|
||||
) -> impl IntoView {
|
||||
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 auto_complete_ref = create_node_ref::<html::Div>();
|
||||
let auto_complete_menu_ref = create_node_ref::<html::Div>();
|
||||
|
@ -58,7 +79,7 @@ pub fn AutoComplete(
|
|||
<div
|
||||
class="melt-auto-complete__menu"
|
||||
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
|
||||
|
|
23
src/auto_complete/theme.rs
Normal file
23
src/auto_complete/theme.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
right: 0;
|
||||
width: 240px;
|
||||
padding: 12px;
|
||||
background-color: #fff;
|
||||
background-color: var(--melt-background-color);
|
||||
border-radius: 3px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
|
@ -65,7 +65,7 @@
|
|||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
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 {
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
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::*;
|
||||
use leptos::leptos_dom::helpers::WindowListenerHandle;
|
||||
use leptos::*;
|
||||
pub use theme::ColorPickerTheme;
|
||||
use wasm_bindgen::__rt::IntoJsResult;
|
||||
|
||||
#[component]
|
||||
pub fn ColorPicker(#[prop(optional, into)] value: MaybeRwSignal<RGBA>) -> impl IntoView {
|
||||
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 sv = create_rw_signal((0.0, 0.0));
|
||||
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"
|
||||
ref=popover_ref
|
||||
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
20
src/color_picker/theme.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
mod theme;
|
||||
|
||||
use crate::{
|
||||
components::*,
|
||||
icon::*,
|
||||
use_theme,
|
||||
utils::{mount_style::mount_style, StoredMaybeSignal},
|
||||
Theme,
|
||||
};
|
||||
use leptos::*;
|
||||
pub use theme::NavBarTheme;
|
||||
|
||||
#[component]
|
||||
pub fn NavBar(
|
||||
|
@ -15,6 +20,15 @@ pub fn NavBar(
|
|||
#[prop(optional, into)] on_click_right: Option<Callback<ev::MouseEvent>>,
|
||||
) -> impl IntoView {
|
||||
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 left_text: StoredMaybeSignal<_> = left_text.into();
|
||||
let right_text: StoredMaybeSignal<_> = right_text.into();
|
||||
|
@ -32,7 +46,7 @@ pub fn NavBar(
|
|||
};
|
||||
|
||||
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())>
|
||||
<Then slot>
|
||||
<div class="melt-nav-bar__left" on:click=on_click_left>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
right: 0;
|
||||
height: 46px;
|
||||
line-height: 46px;
|
||||
background-color: #fff;
|
||||
background-color: var(--melt-background-color);
|
||||
}
|
||||
|
||||
.melt-nav-bar__center {
|
||||
|
|
20
src/mobile/nav_bar/theme.rs
Normal file
20
src/mobile/nav_bar/theme.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,14 @@
|
|||
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::*;
|
||||
|
||||
pub use tabbar_item::*;
|
||||
pub use theme::TabbarTheme;
|
||||
|
||||
#[component]
|
||||
pub fn Tabbar(
|
||||
|
@ -11,6 +16,15 @@ pub fn Tabbar(
|
|||
children: Children,
|
||||
) -> impl IntoView {
|
||||
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()));
|
||||
create_effect(move |_| {
|
||||
|
@ -29,7 +43,7 @@ pub fn Tabbar(
|
|||
}
|
||||
});
|
||||
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)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.melt-tabbar {
|
||||
background-color: #fff;
|
||||
background-color: var(--melt-background-color);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
@ -7,4 +7,4 @@
|
|||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
|
20
src/mobile/tabbar/theme.rs
Normal file
20
src/mobile/tabbar/theme.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,16 +47,16 @@ where
|
|||
css_vars
|
||||
});
|
||||
|
||||
let popover_css_vars = create_memo(move |_| {
|
||||
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.popover_background_color
|
||||
theme.select.menu_background_color
|
||||
));
|
||||
css_vars.push_str(&format!(
|
||||
"--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!(
|
||||
|
@ -67,14 +67,14 @@ where
|
|||
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 popover_ref = create_node_ref::<html::Div>();
|
||||
let show_popover = move |_| {
|
||||
let menu_ref = create_node_ref::<html::Div>();
|
||||
let show_menu = move |_| {
|
||||
let rect = trigger_ref.get().unwrap().get_bounding_client_rect();
|
||||
is_show_popover.set(true);
|
||||
if let Some(popover_ref) = popover_ref.get() {
|
||||
popover_ref
|
||||
is_show_menu.set(true);
|
||||
if let Some(menu_ref) = menu_ref.get() {
|
||||
menu_ref
|
||||
.style("width", format!("{}px", rect.width()))
|
||||
.style(
|
||||
"transform",
|
||||
|
@ -95,14 +95,14 @@ where
|
|||
if current_el == *body {
|
||||
break;
|
||||
};
|
||||
if current_el == ***popover_ref.get().unwrap()
|
||||
if current_el == ***menu_ref.get().unwrap()
|
||||
|| current_el == ***trigger_ref.get().unwrap()
|
||||
{
|
||||
return;
|
||||
}
|
||||
el = current_el.parent_element();
|
||||
}
|
||||
is_show_popover.set(false);
|
||||
is_show_menu.set(false);
|
||||
});
|
||||
on_cleanup(move || timer.remove());
|
||||
|
||||
|
@ -116,7 +116,7 @@ where
|
|||
None => String::new(),
|
||||
});
|
||||
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()}
|
||||
|
||||
|
@ -125,14 +125,14 @@ where
|
|||
<div
|
||||
class="melt-select-menu"
|
||||
style=move || {
|
||||
if is_show_popover.get() {
|
||||
popover_css_vars.get()
|
||||
if is_show_menu.get() {
|
||||
menu_css_vars.get()
|
||||
} else {
|
||||
"display: none;".into()
|
||||
}
|
||||
}
|
||||
|
||||
ref=popover_ref
|
||||
ref=menu_ref
|
||||
>
|
||||
<For
|
||||
each=move || options.get()
|
||||
|
@ -142,7 +142,7 @@ where
|
|||
let onclick = move |_| {
|
||||
let SelectOption { value: item_value, label: _ } = item.get_value();
|
||||
value.set(Some(item_value));
|
||||
is_show_popover.set(false);
|
||||
is_show_menu.set(false);
|
||||
};
|
||||
view! {
|
||||
<div
|
||||
|
|
|
@ -5,8 +5,8 @@ pub struct SelectTheme {
|
|||
pub font_color: String,
|
||||
pub border_color: String,
|
||||
pub background_color: String,
|
||||
pub popover_background_color: String,
|
||||
pub popover_background_color_hover: String,
|
||||
pub menu_background_color: String,
|
||||
pub menu_background_color_hover: String,
|
||||
}
|
||||
|
||||
impl ThemeMethod for SelectTheme {
|
||||
|
@ -15,8 +15,8 @@ impl ThemeMethod for SelectTheme {
|
|||
font_color: "#333639".into(),
|
||||
border_color: "#e0e0e6".into(),
|
||||
background_color: "#fff".into(),
|
||||
popover_background_color: "#fff".into(),
|
||||
popover_background_color_hover: "#f3f5f6".into(),
|
||||
menu_background_color: "#fff".into(),
|
||||
menu_background_color_hover: "#f3f5f6".into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,8 @@ impl ThemeMethod for SelectTheme {
|
|||
font_color: "#ffffffd1".into(),
|
||||
border_color: "#0000".into(),
|
||||
background_color: "#ffffff1a".into(),
|
||||
popover_background_color: "#48484e".into(),
|
||||
popover_background_color_hover: "#ffffff17".into(),
|
||||
menu_background_color: "#48484e".into(),
|
||||
menu_background_color_hover: "#ffffff17".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@ mod common;
|
|||
|
||||
use self::common::CommonTheme;
|
||||
use crate::{
|
||||
AlertTheme, AvatarTheme, ButtonTheme, InputTheme, MenuTheme, MessageTheme, SelectTheme,
|
||||
SkeletionTheme, SliderTheme, SwitchTheme, TableTheme, TagTheme, UploadTheme,
|
||||
mobile::{NavBarTheme, TabbarTheme},
|
||||
AlertTheme, AutoCompleteTheme, AvatarTheme, ButtonTheme, ColorPickerTheme, InputTheme,
|
||||
MenuTheme, MessageTheme, SelectTheme, SkeletionTheme, SliderTheme, SwitchTheme, TableTheme,
|
||||
TagTheme, UploadTheme,
|
||||
};
|
||||
use leptos::*;
|
||||
|
||||
|
@ -29,6 +31,10 @@ pub struct Theme {
|
|||
pub slider: SliderTheme,
|
||||
pub switch: SwitchTheme,
|
||||
pub upload: UploadTheme,
|
||||
pub nav_bar: NavBarTheme,
|
||||
pub tabbar: TabbarTheme,
|
||||
pub auto_complete: AutoCompleteTheme,
|
||||
pub color_picker: ColorPickerTheme,
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
|
@ -49,6 +55,10 @@ impl Theme {
|
|||
slider: SliderTheme::light(),
|
||||
switch: SwitchTheme::light(),
|
||||
upload: UploadTheme::light(),
|
||||
nav_bar: NavBarTheme::light(),
|
||||
tabbar: TabbarTheme::light(),
|
||||
auto_complete: AutoCompleteTheme::light(),
|
||||
color_picker: ColorPickerTheme::light(),
|
||||
}
|
||||
}
|
||||
pub fn dark() -> Self {
|
||||
|
@ -68,6 +78,10 @@ impl Theme {
|
|||
slider: SliderTheme::dark(),
|
||||
switch: SwitchTheme::dark(),
|
||||
upload: UploadTheme::dark(),
|
||||
nav_bar: NavBarTheme::dark(),
|
||||
tabbar: TabbarTheme::dark(),
|
||||
auto_complete: AutoCompleteTheme::dark(),
|
||||
color_picker: ColorPickerTheme::dark(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
use leptos::StoredValue;
|
||||
use std::{fmt, future::Future, pin::Pin, rc::Rc};
|
||||
// use leptos::StoredValue;
|
||||
// use std::{fmt, future::Future, pin::Pin, rc::Rc};
|
||||
|
||||
pub struct AsyncCallback<In: 'static, Out: 'static = ()>(
|
||||
#[allow(clippy::complexity)] StoredValue<Rc<dyn Fn(In) -> Pin<Box<dyn Future<Output = Out>>>>>,
|
||||
);
|
||||
// pub struct AsyncCallback<In: 'static, Out: 'static = ()>(
|
||||
// #[allow(clippy::complexity)] StoredValue<Rc<dyn Fn(In) -> Pin<Box<dyn Future<Output = Out>>>>>,
|
||||
// );
|
||||
|
||||
impl<In> fmt::Debug for AsyncCallback<In> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
fmt.write_str("AsyncCallback")
|
||||
}
|
||||
}
|
||||
// impl<In> fmt::Debug for AsyncCallback<In> {
|
||||
// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
// fmt.write_str("AsyncCallback")
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<In, Out> Clone for AsyncCallback<In, Out> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
// impl<In, Out> Clone for AsyncCallback<In, Out> {
|
||||
// fn clone(&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> {
|
||||
pub fn new<F, Fu>(f: F) -> Self
|
||||
where
|
||||
F: Fn(In) -> Fu + 'static,
|
||||
Fu: Future<Output = Out> + 'static,
|
||||
{
|
||||
let f = Rc::new(move |input: In| {
|
||||
let fut = f(input);
|
||||
Box::pin(fut) as Pin<Box<dyn Future<Output = Out>>>
|
||||
});
|
||||
Self(StoredValue::new(f))
|
||||
}
|
||||
// impl<In, Out> AsyncCallback<In, Out> {
|
||||
// pub fn new<F, Fu>(f: F) -> Self
|
||||
// where
|
||||
// F: Fn(In) -> Fu + 'static,
|
||||
// Fu: Future<Output = Out> + 'static,
|
||||
// {
|
||||
// let f = Rc::new(move |input: In| {
|
||||
// let fut = f(input);
|
||||
// Box::pin(fut) as Pin<Box<dyn Future<Output = Out>>>
|
||||
// });
|
||||
// Self(StoredValue::new(f))
|
||||
// }
|
||||
|
||||
pub async fn call(&self, input: In) -> Out {
|
||||
let f = self.0.get_value();
|
||||
f(input).await
|
||||
}
|
||||
}
|
||||
// pub async fn call(&self, input: In) -> Out {
|
||||
// let f = self.0.get_value();
|
||||
// f(input).await
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<F, In, Fu, Out> From<F> for AsyncCallback<In, Out>
|
||||
where
|
||||
F: Fn(In) -> Fu + 'static,
|
||||
Fu: Future<Output = Out> + 'static,
|
||||
{
|
||||
fn from(f: F) -> AsyncCallback<In, Out> {
|
||||
AsyncCallback::new(f)
|
||||
}
|
||||
}
|
||||
// impl<F, In, Fu, Out> From<F> for AsyncCallback<In, Out>
|
||||
// where
|
||||
// F: Fn(In) -> Fu + 'static,
|
||||
// Fu: Future<Output = Out> + 'static,
|
||||
// {
|
||||
// fn from(f: F) -> AsyncCallback<In, Out> {
|
||||
// AsyncCallback::new(f)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::AsyncCallback;
|
||||
use leptos::create_runtime;
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::utils::AsyncCallback;
|
||||
// use leptos::create_runtime;
|
||||
|
||||
struct NoClone {}
|
||||
// struct NoClone {}
|
||||
|
||||
#[test]
|
||||
fn clone_async_callback() {
|
||||
let rt = create_runtime();
|
||||
let callback = AsyncCallback::new(move |_no_clone: NoClone| async { NoClone {} });
|
||||
let _cloned = callback.clone();
|
||||
rt.dispose();
|
||||
}
|
||||
// #[test]
|
||||
// fn clone_async_callback() {
|
||||
// let rt = create_runtime();
|
||||
// let callback = AsyncCallback::new(move |_no_clone: NoClone| async { NoClone {} });
|
||||
// let _cloned = callback.clone();
|
||||
// rt.dispose();
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn async_callback_from() {
|
||||
let rt = create_runtime();
|
||||
let _callback: AsyncCallback<(), String> = (|()| async { "test".to_string() }).into();
|
||||
rt.dispose();
|
||||
}
|
||||
// #[test]
|
||||
// fn async_callback_from() {
|
||||
// let rt = create_runtime();
|
||||
// let _callback: AsyncCallback<(), String> = (|()| async { "test".to_string() }).into();
|
||||
// rt.dispose();
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn async_callback_from_html() {
|
||||
let rt = create_runtime();
|
||||
use leptos::{
|
||||
html::{HtmlElement, H1},
|
||||
*,
|
||||
};
|
||||
// #[test]
|
||||
// fn async_callback_from_html() {
|
||||
// let rt = create_runtime();
|
||||
// use leptos::{
|
||||
// html::{HtmlElement, H1},
|
||||
// *,
|
||||
// };
|
||||
|
||||
let _callback: AsyncCallback<String, HtmlElement<H1>> = (|x: String| async move {
|
||||
view! {
|
||||
<h1>{x}</h1>
|
||||
}
|
||||
})
|
||||
.into();
|
||||
rt.dispose();
|
||||
}
|
||||
}
|
||||
// let _callback: AsyncCallback<String, HtmlElement<H1>> = (|x: String| async move {
|
||||
// view! {
|
||||
// <h1>{x}</h1>
|
||||
// }
|
||||
// })
|
||||
// .into();
|
||||
// rt.dispose();
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
mod callback;
|
||||
// mod callback;
|
||||
pub mod maybe_rw_signal;
|
||||
mod maybe_signal_store;
|
||||
pub mod mount_style;
|
||||
pub mod signal;
|
||||
|
||||
pub use callback::AsyncCallback;
|
||||
// pub use callback::AsyncCallback;
|
||||
pub use maybe_signal_store::*;
|
||||
|
|
Loading…
Add table
Reference in a new issue