From 6b9b05b59ef6a952113bb951bf38fd5c6c7691ec Mon Sep 17 00:00:00 2001 From: luoxiao Date: Thu, 9 Nov 2023 16:46:14 +0800 Subject: [PATCH] feat: functional optimization --- Cargo.toml | 1 + src/button/mod.rs | 4 +- src/checkbox/checkbox_group.rs | 17 ++------ src/checkbox/checkbox_item.rs | 4 +- src/grid/mod.rs | 10 ++--- src/loading_bar/loading_bar_provider.rs | 1 + src/loading_bar/mod.rs | 2 +- src/menu/menu_item.rs | 9 ++-- src/menu/mod.rs | 32 ++------------ src/message/message.rs | 54 ------------------------ src/message/message_environment.rs | 2 +- src/message/message_provider.rs | 2 +- src/message/mod.rs | 56 ++++++++++++++++++++++++- src/mobile/tabbar/mod.rs | 33 ++------------- src/mobile/tabbar/tabbar_item.rs | 9 ++-- src/mobile/toast/mod.rs | 29 +++++-------- src/tabs/mod.rs | 10 ++--- src/teleport/mod.rs | 46 ++++++++++---------- 18 files changed, 129 insertions(+), 192 deletions(-) delete mode 100644 src/message/message.rs diff --git a/Cargo.toml b/Cargo.toml index d9c7909..d7b38d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ icondata = { version = "0.1.0", features = [ ] } icondata_core = "0.0.2" uuid = { version = "1.5.0", features = ["v4"] } +cfg-if = "1.0.0" [workspace] members = ["demo"] diff --git a/src/button/mod.rs b/src/button/mod.rs index 8b8a839..1d8eba7 100644 --- a/src/button/mod.rs +++ b/src/button/mod.rs @@ -95,12 +95,12 @@ pub fn Button( "--thaw-background-color-active: {};", theme.button.color_text_active )); - css_vars.push_str(&format!("--thaw-ripple-color: #0000;")); + css_vars.push_str("--thaw-ripple-color: #0000;"); } else { css_vars.push_str(&format!("--thaw-font-color-hover: {bg_color};")); css_vars.push_str("--thaw-border-color: #555a;"); css_vars.push_str("--thaw-border-color-hover: #555;"); - css_vars.push_str(&format!("--thaw-ripple-color: #0000;")); + css_vars.push_str("--thaw-ripple-color: #0000;"); } }); diff --git a/src/checkbox/checkbox_group.rs b/src/checkbox/checkbox_group.rs index 916809e..adefcb8 100644 --- a/src/checkbox/checkbox_group.rs +++ b/src/checkbox/checkbox_group.rs @@ -6,23 +6,14 @@ pub fn CheckboxGroup( #[prop(optional, into)] value: RwSignal>, children: Children, ) -> impl IntoView { - let injection_key = CheckboxGroupInjectionKey::new(value.into()); - provide_context(injection_key); + provide_context(CheckboxGroupInjection(value)); children() } #[derive(Clone)] -pub struct CheckboxGroupInjectionKey { - pub value: RwSignal>, -} +pub(crate) struct CheckboxGroupInjection(pub RwSignal>); -impl CheckboxGroupInjectionKey { - pub fn new(value: RwSignal>) -> Self { - Self { value } - } -} - -pub fn use_checkbox_group() -> CheckboxGroupInjectionKey { - expect_context::() +pub(crate) fn use_checkbox_group() -> CheckboxGroupInjection { + expect_context() } diff --git a/src/checkbox/checkbox_item.rs b/src/checkbox/checkbox_item.rs index aa6d827..a31e178 100644 --- a/src/checkbox/checkbox_item.rs +++ b/src/checkbox/checkbox_item.rs @@ -11,13 +11,13 @@ pub fn CheckboxItem( ) -> impl IntoView { let checkbox_group = use_checkbox_group(); let checked = checkbox_group - .value + .0 .with_untracked(|checkbox_group| checkbox_group.contains(&key)); let checked = create_rw_signal(checked); let item_key = store_value(key); _ = checked.watch(move |checked| { - checkbox_group.value.update(move |checkbox_group| { + checkbox_group.0.update(move |checkbox_group| { if *checked { checkbox_group.insert(item_key.get_value()); } else { diff --git a/src/grid/mod.rs b/src/grid/mod.rs index 6821b8f..16b5dfd 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -10,7 +10,7 @@ pub fn Grid( #[prop(optional, into)] y_gap: MaybeSignal, children: Children, ) -> impl IntoView { - let grid_injection_key = GridInjectionKey::new(x_gap); + let grid_injection_key = GridInjection::new(x_gap); provide_context(grid_injection_key); let style = create_memo(move |_| { @@ -31,16 +31,16 @@ pub fn Grid( } #[derive(Clone)] -pub struct GridInjectionKey { +pub(crate) struct GridInjection { x_gap: MaybeSignal, } -impl GridInjectionKey { +impl GridInjection { pub fn new(x_gap: MaybeSignal) -> Self { Self { x_gap } } } -pub fn use_grid() -> GridInjectionKey { - expect_context::() +pub(crate) fn use_grid() -> GridInjection { + expect_context() } diff --git a/src/loading_bar/loading_bar_provider.rs b/src/loading_bar/loading_bar_provider.rs index 7f085ef..e4640ec 100644 --- a/src/loading_bar/loading_bar_provider.rs +++ b/src/loading_bar/loading_bar_provider.rs @@ -19,6 +19,7 @@ pub fn LoadingBarProvider(children: Children) -> impl IntoView { pub struct LoadingBarInjection { loading_bar_ref: ComponentRef, } + impl Copy for LoadingBarInjection {} impl LoadingBarInjection { diff --git a/src/loading_bar/mod.rs b/src/loading_bar/mod.rs index d205a93..f18e704 100644 --- a/src/loading_bar/mod.rs +++ b/src/loading_bar/mod.rs @@ -99,7 +99,7 @@ pub(crate) fn LoadingBar(#[prop(optional)] comp_ref: ComponentRef view! {
diff --git a/src/menu/mod.rs b/src/menu/mod.rs index 7ffe8bb..8a9af71 100644 --- a/src/menu/mod.rs +++ b/src/menu/mod.rs @@ -9,37 +9,13 @@ pub use theme::MenuTheme; #[component] pub fn Menu(#[prop(optional, into)] value: RwSignal, children: Children) -> impl IntoView { - let menu_injection_key = create_rw_signal(MenuInjectionKey::new(value.get_untracked())); - create_effect(move |_| { - let selected_key = value.get(); - let key = menu_injection_key.get_untracked(); - if selected_key != key.value { - menu_injection_key.set(MenuInjectionKey::new(selected_key)); - } - }); - - create_effect(move |_| { - let selected_key = value.get_untracked(); - let key = menu_injection_key.get(); - if selected_key != key.value { - value.set(key.value); - } - }); - provide_context(menu_injection_key); + provide_context(MenuInjection(value)); view! {
{children()}
} } #[derive(Clone)] -pub struct MenuInjectionKey { - value: String, -} +pub(crate) struct MenuInjection(pub RwSignal); -impl MenuInjectionKey { - pub fn new(value: String) -> Self { - Self { value } - } -} - -pub fn use_menu() -> RwSignal { - expect_context::>() +pub(crate) fn use_menu() -> MenuInjection { + expect_context() } diff --git a/src/message/message.rs b/src/message/message.rs deleted file mode 100644 index 3f2fd50..0000000 --- a/src/message/message.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::{theme::use_theme, Icon, Theme}; -use icondata::*; -use leptos::*; - -#[derive(Default, Clone)] -pub enum MessageVariant { - #[default] - Success, - Warning, - Error, -} - -impl MessageVariant { - fn icon(&self) -> Icon { - match self { - MessageVariant::Success => icondata::Icon::Ai(AiCloseCircleFilled), - MessageVariant::Warning => icondata::Icon::Ai(AiExclamationCircleFilled), - MessageVariant::Error => icondata::Icon::Ai(AiCheckCircleFilled), - } - } - fn theme_color(&self, theme: &Theme) -> String { - match self { - MessageVariant::Success => theme.common.color_success.clone(), - MessageVariant::Warning => theme.common.color_warning.clone(), - MessageVariant::Error => theme.common.color_error.clone(), - } - } -} - -#[component] -pub(crate) fn Message(variant: MessageVariant, content: String) -> impl IntoView { - 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.message.background_color - )) - }); - css_vars - }); - let style = theme.with_untracked(|theme| format!("color: {};", variant.theme_color(theme))); - view! { -
-
-
- -
-
{content}
-
-
- } -} diff --git a/src/message/message_environment.rs b/src/message/message_environment.rs index 5533cdd..f015d94 100644 --- a/src/message/message_environment.rs +++ b/src/message/message_environment.rs @@ -1,4 +1,4 @@ -use super::{message::Message, message_provider::MessageType}; +use super::{message_provider::MessageType, Message}; use leptos::*; use uuid::Uuid; diff --git a/src/message/message_provider.rs b/src/message/message_provider.rs index 85fb156..f7268e3 100644 --- a/src/message/message_provider.rs +++ b/src/message/message_provider.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use super::{message::MessageVariant, message_environment::MessageEnvironment}; +use super::{message_environment::MessageEnvironment, MessageVariant}; use crate::{mount_style, teleport::Teleport}; use leptos::*; use uuid::Uuid; diff --git a/src/message/mod.rs b/src/message/mod.rs index 861e9c9..a4dd7b6 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -1,8 +1,60 @@ -mod message; mod message_environment; mod message_provider; mod theme; -pub use message::*; +use crate::{theme::use_theme, Icon, Theme}; +use icondata::*; +use leptos::*; pub use message_provider::*; pub use theme::MessageTheme; + +#[derive(Default, Clone)] +pub enum MessageVariant { + #[default] + Success, + Warning, + Error, +} + +impl MessageVariant { + fn icon(&self) -> Icon { + match self { + MessageVariant::Success => icondata::Icon::Ai(AiCloseCircleFilled), + MessageVariant::Warning => icondata::Icon::Ai(AiExclamationCircleFilled), + MessageVariant::Error => icondata::Icon::Ai(AiCheckCircleFilled), + } + } + fn theme_color(&self, theme: &Theme) -> String { + match self { + MessageVariant::Success => theme.common.color_success.clone(), + MessageVariant::Warning => theme.common.color_warning.clone(), + MessageVariant::Error => theme.common.color_error.clone(), + } + } +} + +#[component] +pub(crate) fn Message(variant: MessageVariant, content: String) -> impl IntoView { + 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.message.background_color + )) + }); + css_vars + }); + let style = theme.with_untracked(|theme| format!("color: {};", variant.theme_color(theme))); + view! { +
+
+
+ +
+
{content}
+
+
+ } +} diff --git a/src/mobile/tabbar/mod.rs b/src/mobile/tabbar/mod.rs index 1b60e05..84414f9 100644 --- a/src/mobile/tabbar/mod.rs +++ b/src/mobile/tabbar/mod.rs @@ -21,24 +21,7 @@ pub fn Tabbar( ) }) }); - - let tabbar_injection_key = create_rw_signal(TabbarInjectionKey::new(value.get())); - create_effect(move |_| { - let selected_key = value.get(); - let key = tabbar_injection_key.get_untracked(); - if selected_key != key.value { - tabbar_injection_key.set(TabbarInjectionKey::new(selected_key)); - } - }); - - create_effect(move |_| { - let selected_key = value.get_untracked(); - let key = tabbar_injection_key.get(); - if selected_key != key.value { - value.set(key.value); - } - }); - provide_context(tabbar_injection_key); + provide_context(TabbarInjection(value)); view! {
{children()} @@ -47,16 +30,8 @@ pub fn Tabbar( } #[derive(Clone)] -pub struct TabbarInjectionKey { - value: String, -} +pub(crate) struct TabbarInjection(pub RwSignal); -impl TabbarInjectionKey { - pub fn new(value: String) -> Self { - Self { value } - } -} - -pub fn use_tabbar() -> RwSignal { - use_context::>().expect("TabbarInjectionKey not exist") +pub(crate) fn use_tabbar() -> TabbarInjection { + expect_context() } diff --git a/src/mobile/tabbar/tabbar_item.rs b/src/mobile/tabbar/tabbar_item.rs index ff88678..b7c47a2 100644 --- a/src/mobile/tabbar/tabbar_item.rs +++ b/src/mobile/tabbar/tabbar_item.rs @@ -1,4 +1,4 @@ -use super::{use_tabbar, TabbarInjectionKey}; +use super::use_tabbar; use crate::components::*; use crate::utils::StoredMaybeSignal; use crate::{icon::*, theme::use_theme, utils::mount_style::mount_style, Theme}; @@ -15,7 +15,10 @@ pub fn TabbarItem( let tabbar = use_tabbar(); let key: StoredMaybeSignal<_> = key.into(); let on_click = move |_| { - tabbar.set(TabbarInjectionKey::new(key.get())); + let click_key = key.get(); + if tabbar.0.with(|key| key != &click_key) { + tabbar.0.set(click_key); + } }; let css_vars = create_memo(move |_| { @@ -30,7 +33,7 @@ pub fn TabbarItem( view! {
diff --git a/src/mobile/toast/mod.rs b/src/mobile/toast/mod.rs index e816e50..cb0aa61 100644 --- a/src/mobile/toast/mod.rs +++ b/src/mobile/toast/mod.rs @@ -1,7 +1,6 @@ use crate::utils::mount_style::mount_style; -use leptos::*; +use cfg_if::cfg_if; use std::time::Duration; -use web_sys::Element; pub struct ToastOptions { pub message: String, @@ -10,26 +9,20 @@ pub struct ToastOptions { pub fn show_toast(options: ToastOptions) { mount_style("toast", include_str!("./toast.css")); - - let parent = Element::from(document().body().expect("body element not to exist")); - let children = view! {
{options.message}
}; - let node = children.into_view(); - - #[cfg(target_arch = "wasm32")] - { - use leptos::leptos_dom::Mountable; + cfg_if! { if #[cfg(target_arch = "wasm32")] { + use leptos::{leptos_dom::Mountable, *}; + let mount = document().body().expect("body element not to exist"); + let children = view! {
{options.message}
}; + let node = children.into_view(); let node = node.get_mountable_node(); - parent.append_child(&node).unwrap(); + _ = mount.append_child(&node); set_timeout( move || { - _ = parent.remove_child(&node); + _ = mount.remove_child(&node); }, options.duration, ); - } - #[cfg(not(target_arch = "wasm32"))] - { - _ = parent; - _ = node; - } + } else { + _ = options; + }} } diff --git a/src/tabs/mod.rs b/src/tabs/mod.rs index 4ee18af..b6a7e3f 100644 --- a/src/tabs/mod.rs +++ b/src/tabs/mod.rs @@ -9,7 +9,7 @@ pub use tab::*; pub fn Tabs(#[prop(optional, into)] value: RwSignal, children: Children) -> impl IntoView { mount_style("tabs", include_str!("./tabs.css")); let tab_options_vec = create_rw_signal(vec![]); - provide_context(TabsInjectionKey { + provide_context(TabsInjection { active_key: value, tab_options_vec, }); @@ -106,12 +106,12 @@ pub(crate) struct TabsLabelLine { } #[derive(Clone)] -pub struct TabsInjectionKey { +pub(crate) struct TabsInjection { active_key: RwSignal, tab_options_vec: RwSignal>, } -impl TabsInjectionKey { +impl TabsInjection { pub fn get_key(&self) -> String { self.active_key.get() } @@ -123,6 +123,6 @@ impl TabsInjectionKey { } } -pub fn use_tabs() -> TabsInjectionKey { - use_context::().expect("TabsInjectionKey not exist") +pub(crate) fn use_tabs() -> TabsInjection { + expect_context() } diff --git a/src/teleport/mod.rs b/src/teleport/mod.rs index 8747075..777c49b 100644 --- a/src/teleport/mod.rs +++ b/src/teleport/mod.rs @@ -1,34 +1,30 @@ +use cfg_if::cfg_if; use leptos::*; -use web_sys::Element; - /// https://github.com/solidjs/solid/blob/main/packages/solid/web/src/index.ts#L56 #[component] -pub fn Teleport(#[prop(optional)] to: Option<&'static str>, children: Children) -> impl IntoView { - let parent = if let Some(to) = to { - document() - .query_selector(to) - .expect("element not to exist") - .expect("element not to exist") - } else { - Element::from(document().body().expect("body element not to exist")) - }; - - #[cfg(target_arch = "wasm32")] - { - use leptos::leptos_dom::Mountable; +pub fn Teleport( + #[prop(into, optional)] mount: Option, + children: Children, +) -> impl IntoView { + cfg_if! { if #[cfg(target_arch = "wasm32")] { + use leptos::{ + wasm_bindgen::JsCast, + leptos_dom::Mountable + }; + let mount = mount.unwrap_or_else(|| { + document() + .body() + .expect("body element not to exist") + .unchecked_into() + }); let node = children().into_view(); let node = node.get_mountable_node(); - parent.append_child(&node).unwrap(); + _ = mount.append_child(&node); on_cleanup(move || { - _ = parent.remove_child(&node); + _ = mount.remove_child(&node); }); - } - - #[cfg(not(target_arch = "wasm32"))] - { - _ = parent; + } else { + _ = mount; _ = children; - } - - view! { <> } + }} }