Merge pull request #23 from thaw-ui/docs/theme

fix: provide context
This commit is contained in:
luoxiaozero 2023-11-19 14:11:47 +08:00 committed by GitHub
commit 787e25cc71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 311 additions and 243 deletions

View file

@ -6,6 +6,85 @@ use thaw::*;
#[component] #[component]
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
let is_routing = create_rw_signal(false);
let set_is_routing = SignalSetter::map(move |is_routing_data| {
is_routing.set(is_routing_data);
});
provide_meta_context();
view! {
<Router base="/thaw" set_is_routing>
<TheProvider>
<TheRouter is_routing/>
</TheProvider>
</Router>
}
}
#[component]
fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
let loading_bar = use_loading_bar();
_ = is_routing.watch(move |is_routing| {
if *is_routing {
loading_bar.start();
} else {
loading_bar.finish();
}
});
view! {
<Routes base="/thaw".to_string()>
<Route path="/" view=Home/>
<Route path="/guide" view=GuidePage>
<Route path="/installation" view=InstallationPage/>
<Route path="/usage" view=UsagePage/>
</Route>
<Route path="/components" view=ComponentsPage>
<Route path="/menu" view=MenuPage/>
<Route path="/slider" view=SliderPage/>
<Route path="/tabbar" view=TabbarPage/>
<Route path="/nav-bar" view=NavBarPage/>
<Route path="/input" view=InputPage/>
<Route path="/image" view=ImagePage/>
<Route path="/modal" view=ModalPage/>
<Route path="/button" view=ButtonPage/>
<Route path="/checkbox" view=CheckboxPage/>
<Route path="/toast" view=ToastPage/>
<Route path="/tabs" view=TabsPage/>
<Route path="/select" view=SelectPage/>
<Route path="/space" view=SpacePage/>
<Route path="/table" view=TablePage/>
<Route path="/color-picker" view=ColorPickerPage/>
<Route path="/alert" view=AlertPage/>
<Route path="/grid" view=GridPage/>
<Route path="/auto-complete" view=AutoCompletePage/>
<Route path="/avatar" view=AvatarPage/>
<Route path="/badge" view=BadgePage/>
<Route path="/card" view=CardPage/>
<Route path="/divider" view=DividerPage/>
<Route path="/input-number" view=InputNumberPage/>
<Route path="/icon" view=IconPage/>
<Route path="/message" view=MessagePage/>
<Route path="/radio" view=RadioPage/>
<Route path="/skeleton" view=SkeletonPage/>
<Route path="/switch" view=SwitchPage/>
<Route path="/tag" view=TagPage/>
<Route path="/upload" view=UploadPage/>
<Route path="/loading-bar" view=LoadingBarPage/>
<Route path="/breadcrumb" view=BreadcrumbPage/>
<Route path="/layout" view=LayoutPage/>
<Route path="/progress" view=ProgressPage/>
<Route path="/theme" view=ThemePage/>
</Route>
<Route path="/mobile/tabbar" view=TabbarDemoPage/>
<Route path="/mobile/nav-bar" view=NavBarDemoPage/>
<Route path="/mobile/toast" view=ToastDemoPage/>
</Routes>
}
}
#[component]
fn TheProvider(children: Children) -> impl IntoView {
fn use_query_value(key: &str) -> Option<String> { fn use_query_value(key: &str) -> Option<String> {
let href = window().location().href().ok()?; let href = window().location().href().ok()?;
let url = Url::try_from(href.as_str()).ok()?; let url = Url::try_from(href.as_str()).ok()?;
@ -22,86 +101,11 @@ pub fn App() -> impl IntoView {
}); });
let theme = create_rw_signal(theme); let theme = create_rw_signal(theme);
provide_meta_context();
view! {
<Provider theme>
<TheRouter />
</Provider>
}
}
#[component]
fn TheRouter() -> impl IntoView {
let loading_bar = use_loading_bar();
let set_is_routing = SignalSetter::map(move |is_routing| {
if is_routing {
loading_bar.start();
} else {
loading_bar.finish();
}
});
view! {
<Router base="/thaw" set_is_routing>
<Routes base="/thaw".to_string()>
<Route path="/" view=Home/>
<Route path="/guide" view=GuidePage>
<Route path="/installation" view=InstallationPage/>
<Route path="/usage" view=UsagePage/>
</Route>
<Route path="/components" view=ComponentsPage>
<Route path="/menu" view=MenuPage/>
<Route path="/slider" view=SliderPage/>
<Route path="/tabbar" view=TabbarPage/>
<Route path="/nav-bar" view=NavBarPage/>
<Route path="/input" view=InputPage/>
<Route path="/image" view=ImagePage/>
<Route path="/modal" view=ModalPage/>
<Route path="/button" view=ButtonPage/>
<Route path="/checkbox" view=CheckboxPage/>
<Route path="/toast" view=ToastPage/>
<Route path="/tabs" view=TabsPage/>
<Route path="/select" view=SelectPage/>
<Route path="/space" view=SpacePage/>
<Route path="/table" view=TablePage/>
<Route path="/color-picker" view=ColorPickerPage/>
<Route path="/alert" view=AlertPage/>
<Route path="/grid" view=GridPage/>
<Route path="/auto-complete" view=AutoCompletePage/>
<Route path="/avatar" view=AvatarPage/>
<Route path="/badge" view=BadgePage/>
<Route path="/card" view=CardPage/>
<Route path="/divider" view=DividerPage/>
<Route path="/input-number" view=InputNumberPage/>
<Route path="/icon" view=IconPage/>
<Route path="/message" view=MessagePage/>
<Route path="/radio" view=RadioPage/>
<Route path="/skeleton" view=SkeletonPage/>
<Route path="/switch" view=SwitchPage/>
<Route path="/tag" view=TagPage/>
<Route path="/upload" view=UploadPage/>
<Route path="/loading-bar" view=LoadingBarPage/>
<Route path="/breadcrumb" view=BreadcrumbPage/>
<Route path="/layout" view=LayoutPage/>
<Route path="/progress" view=ProgressPage/>
<Route path="/theme" view=ThemePage/>
</Route>
<Route path="/mobile/tabbar" view=TabbarDemoPage/>
<Route path="/mobile/nav-bar" view=NavBarDemoPage/>
<Route path="/mobile/toast" view=ToastDemoPage/>
</Routes>
</Router>
}
}
#[component]
fn Provider(theme: RwSignal<Theme>, children: Children) -> impl IntoView {
view! { view! {
<ThemeProvider theme> <ThemeProvider theme>
<GlobalStyle /> <GlobalStyle/>
<MessageProvider> <MessageProvider>
<LoadingBarProvider> <LoadingBarProvider>{children()}</LoadingBarProvider>
{children()}
</LoadingBarProvider>
</MessageProvider> </MessageProvider>
</ThemeProvider> </ThemeProvider>
} }

View file

@ -5,6 +5,7 @@ use thaw::*;
#[component] #[component]
pub fn ThemePage() -> impl IntoView { pub fn ThemePage() -> impl IntoView {
let theme = create_rw_signal(Theme::light());
let customize_theme = create_rw_signal(Theme::light()); let customize_theme = create_rw_signal(Theme::light());
let on_customize_theme = move |_| { let on_customize_theme = move |_| {
customize_theme.update(|theme| { customize_theme.update(|theme| {
@ -16,7 +17,40 @@ pub fn ThemePage() -> impl IntoView {
view! { view! {
<div style="width: 896px; margin: 0 auto;"> <div style="width: 896px; margin: 0 auto;">
<h1>"Theme"</h1> <h1>"Theme"</h1>
<ThemeProviderPage/> <h3>"ThemeProvider"</h3>
<Demo>
<ThemeProvider theme>
<Card>
<Space>
<Button on_click=move |_| theme.set(Theme::light())>"Light"</Button>
<Button on_click=move |_| theme.set(Theme::dark())>"Dark"</Button>
</Space>
</Card>
</ThemeProvider>
<DemoCode
slot
html=highlight_str!(
r#"
let theme = create_rw_signal(Theme::light());
view! {
<ThemeProvider theme>
<Card>
<Space>
<Button on_click=move |_| theme.set(Theme::light())>"Light"</Button>
<Button on_click=move |_| theme.set(Theme::dark())>"Dark"</Button>
</Space>
</Card>
</ThemeProvider>
}
"#,
"rust"
)
>
""
</DemoCode>
</Demo>
<h3>"GlobalStyle"</h3> <h3>"GlobalStyle"</h3>
<p>"You can use GlobalStyle to sync common global style to the body element."</p> <p>"You can use GlobalStyle to sync common global style to the body element."</p>
<Demo> <Demo>
@ -106,36 +140,3 @@ pub fn ThemePage() -> impl IntoView {
</div> </div>
} }
} }
#[component]
fn ThemeProviderPage() -> impl IntoView {
view! {
<h3>"ThemeProvider"</h3>
<Demo>
""
<DemoCode
slot
html=highlight_str!(
r#"
let theme = create_rw_signal(Theme::light());
view! {
<ThemeProvider theme>
<Card>
<Space>
<Button on_click=move |_| theme.set(Theme::light())>"Light"</Button>
<Button on_click=move |_| theme.set(Theme::dark())>"Dark"</Button>
</Space>
</Card>
</ThemeProvider>
}
"#,
"rust"
)
>
""
</DemoCode>
</Demo>
}
}

View file

@ -61,11 +61,13 @@ pub fn AutoComplete(
allow_value allow_value
/> />
</div> </div>
<Follower slot show=is_show_menu placement=FollowerPlacement::BottomStart width=FollowerWidth::Target> <Follower
<div slot
class="thaw-auto-complete__menu" show=is_show_menu
style=move || menu_css_vars.get() placement=FollowerPlacement::BottomStart
> width=FollowerWidth::Target
>
<div class="thaw-auto-complete__menu" style=move || menu_css_vars.get()>
{move || { {move || {
options options

View file

@ -1,7 +1,11 @@
mod breadcrumb_item; mod breadcrumb_item;
mod theme; mod theme;
use crate::{use_theme, utils::mount_style, Theme}; use crate::{
use_theme,
utils::{mount_style, Provider},
Theme,
};
pub use breadcrumb_item::BreadcrumbItem; pub use breadcrumb_item::BreadcrumbItem;
use leptos::*; use leptos::*;
pub use theme::BreadcrumbTheme; pub use theme::BreadcrumbTheme;
@ -31,11 +35,12 @@ pub fn Breadcrumb(
}); });
css_vars css_vars
}); });
provide_context(BreadcrumbSeparatorInjection(separator));
view! { view! {
<nav class="thaw-breadcrumb" style=move || css_vars.get()> <Provider value=BreadcrumbSeparatorInjection(separator)>
<ul>{children()}</ul> <nav class="thaw-breadcrumb" style=move || css_vars.get()>
</nav> <ul>{children()}</ul>
</nav>
</Provider>
} }
} }

View file

@ -1,3 +1,4 @@
use crate::utils::Provider;
use leptos::*; use leptos::*;
use std::collections::HashSet; use std::collections::HashSet;
@ -6,9 +7,7 @@ pub fn CheckboxGroup(
#[prop(optional, into)] value: RwSignal<HashSet<String>>, #[prop(optional, into)] value: RwSignal<HashSet<String>>,
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
provide_context(CheckboxGroupInjection(value)); view! { <Provider value=CheckboxGroupInjection(value) children/> }
children()
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -204,9 +204,7 @@ fn FollowerContainer<El: ElementDescriptor + Clone + 'static>(
.attr("style", move || content_style.get()) .attr("style", move || content_style.get())
.child(children()), .child(children()),
); );
view! { view! { <Teleport element=children/> }
<Teleport element=children />
}
} }
fn get_scroll_parent(element: Option<HtmlElement<AnyElement>>) -> Option<HtmlElement<AnyElement>> { fn get_scroll_parent(element: Option<HtmlElement<AnyElement>>) -> Option<HtmlElement<AnyElement>> {

View file

@ -50,6 +50,7 @@ pub fn Wave(#[prop(optional)] comp_ref: ComponentRef<WaveRef>) -> impl IntoView
"thaw-wave--active", "thaw-wave--active",
move || animation_timeout_handle.with(|handle| handle.is_some()), move || animation_timeout_handle.with(|handle| handle.is_some()),
) )
ref=wave_ref ref=wave_ref
></div> ></div>
} }

View file

@ -1,5 +1,6 @@
mod grid_item; mod grid_item;
use crate::utils::Provider;
pub use grid_item::*; pub use grid_item::*;
use leptos::*; use leptos::*;
@ -10,9 +11,6 @@ pub fn Grid(
#[prop(optional, into)] y_gap: MaybeSignal<u16>, #[prop(optional, into)] y_gap: MaybeSignal<u16>,
children: Children, children: Children,
) -> impl IntoView { ) -> impl IntoView {
let grid_injection_key = GridInjection::new(x_gap);
provide_context(grid_injection_key);
let style = create_memo(move |_| { let style = create_memo(move |_| {
let mut style = String::from("display: grid;"); let mut style = String::from("display: grid;");
style.push_str(&format!( style.push_str(&format!(
@ -24,9 +22,11 @@ pub fn Grid(
}); });
view! { view! {
<div class="thaw-grid" style=move || style.get()> <Provider value=GridInjection::new(x_gap)>
{children()} <div class="thaw-grid" style=move || style.get()>
</div> {children()}
</div>
</Provider>
} }
} }

View file

@ -97,12 +97,17 @@ pub fn Input(
css_vars css_vars
}); });
view! { view! {
<div class="thaw-input" class=("thaw-input--focus", move || is_focus.get()) style=move || css_vars.get()> <div
class="thaw-input"
class=("thaw-input--focus", move || is_focus.get())
style=move || css_vars.get()
>
{if let Some(prefix) = input_prefix { {if let Some(prefix) = input_prefix {
view! { <div class="thaw-input__prefix">{(prefix.children)()}</div> }.into() view! { <div class="thaw-input__prefix">{(prefix.children)()}</div> }.into()
} else { } else {
None None
}} }}
<input <input
type=move || variant.get().as_str() type=move || variant.get().as_str()
prop:value=move || { prop:value=move || {

View file

@ -1,17 +1,22 @@
use super::{LoadingBar, LoadingBarRef}; use super::{LoadingBar, LoadingBarRef};
use crate::{components::Teleport, utils::ComponentRef}; use crate::{
components::Teleport,
utils::{ComponentRef, Provider},
};
use leptos::*; use leptos::*;
#[component] #[component]
pub fn LoadingBarProvider(children: Children) -> impl IntoView { pub fn LoadingBarProvider(children: Children) -> impl IntoView {
let loading_bar_ref = ComponentRef::<LoadingBarRef>::default(); let loading_bar_ref = ComponentRef::<LoadingBarRef>::default();
provide_context(LoadingBarInjection { loading_bar_ref });
view! { view! {
{children()} <Provider value=LoadingBarInjection {
<Teleport> loading_bar_ref,
<LoadingBar comp_ref=loading_bar_ref/> }>
</Teleport> {children()} <Teleport>
<LoadingBar comp_ref=loading_bar_ref/>
</Teleport>
</Provider>
} }
} }

View file

@ -2,6 +2,7 @@ mod menu_group;
mod menu_item; mod menu_item;
mod theme; mod theme;
use crate::utils::Provider;
use leptos::*; use leptos::*;
pub use menu_group::MenuGroup; pub use menu_group::MenuGroup;
pub use menu_item::*; pub use menu_item::*;
@ -9,8 +10,11 @@ pub use theme::MenuTheme;
#[component] #[component]
pub fn Menu(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView { pub fn Menu(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView {
provide_context(MenuInjection(value)); view! {
view! { <div class="thaw-menu">{children()}</div> } <Provider value=MenuInjection(value)>
<div class="thaw-menu">{children()}</div>
</Provider>
}
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -1,7 +1,10 @@
use std::time::Duration; use std::time::Duration;
use super::{message_environment::MessageEnvironment, MessageVariant}; use super::{message_environment::MessageEnvironment, MessageVariant};
use crate::{components::Teleport, utils::mount_style}; use crate::{
components::Teleport,
utils::{mount_style, Provider},
};
use leptos::*; use leptos::*;
use uuid::Uuid; use uuid::Uuid;
@ -10,7 +13,6 @@ pub fn MessageProvider(children: Children) -> impl IntoView {
mount_style("message", include_str!("./message.css")); mount_style("message", include_str!("./message.css"));
let message_list = create_rw_signal::<Vec<MessageType>>(vec![]); let message_list = create_rw_signal::<Vec<MessageType>>(vec![]);
provide_context(MessageInjection::new(message_list));
let handle_after_leave = move |id| { let handle_after_leave = move |id| {
message_list.update(move |message_list| { message_list.update(move |message_list| {
@ -22,21 +24,28 @@ pub fn MessageProvider(children: Children) -> impl IntoView {
}; };
view! { view! {
{children()} <Provider value=MessageInjection::new(
<Teleport> message_list,
<div class="thaw-message-container"> )>
<For {children()}
each=move || message_list.get() <Teleport>
key=|message| message.0 <div class="thaw-message-container">
children=move |message| { <For
view! { each=move || message_list.get()
<MessageEnvironment message on_internal_after_leave=handle_after_leave/> key=|message| message.0
children=move |message| {
view! {
<MessageEnvironment
message
on_internal_after_leave=handle_after_leave
/>
}
} }
} />
/>
</div> </div>
</Teleport> </Teleport>
</Provider>
} }
} }

View file

@ -1,7 +1,11 @@
mod tabbar_item; mod tabbar_item;
mod theme; mod theme;
use crate::{use_theme, utils::mount_style, Theme}; use crate::{
use_theme,
utils::{mount_style, Provider},
Theme,
};
use leptos::*; use leptos::*;
pub use tabbar_item::*; pub use tabbar_item::*;
pub use theme::TabbarTheme; pub use theme::TabbarTheme;
@ -21,11 +25,13 @@ pub fn Tabbar(
) )
}) })
}); });
provide_context(TabbarInjection(value));
view! { view! {
<div class="thaw-tabbar" style=move || css_vars.get()> <Provider value=TabbarInjection(value)>
{children()} <div class="thaw-tabbar" style=move || css_vars.get()>
</div> {children()}
</div>
</Provider>
} }
} }

View file

@ -89,27 +89,29 @@ pub fn Progress(
}; };
view! { view! {
<div class="thaw-progress" style=move || css_vars.get() > <div class="thaw-progress" style=move || css_vars.get()>
<div class=class> <div class=class>
<div class="thaw-progress__progress-inner" style=style> <div class="thaw-progress__progress-inner" style=style>
<Show when=move || show_indicator.get() && indicator_placement.get() == ProgressIndicatorPlacement::Inside> <Show when=move || {
show_indicator.get()
&& indicator_placement.get() == ProgressIndicatorPlacement::Inside
}>
<div class="thaw-progress__indicator--inside"> <div class="thaw-progress__indicator--inside">
{
move || { {move || { format!("{}%", percentage.get()) }}
format!("{}%", percentage.get())
}
}
</div> </div>
</Show> </Show>
</div> </div>
</div> </div>
<Show when=move || show_indicator.get() && indicator_placement.get() == ProgressIndicatorPlacement::Outside> <Show when=move || {
show_indicator.get()
&& indicator_placement.get() == ProgressIndicatorPlacement::Outside
}>
<div class="thaw-progress__indicator--outside"> <div class="thaw-progress__indicator--outside">
{
move || { {move || { format!("{}%", percentage.get()) }}
format!("{}%", percentage.get())
}
}
</div> </div>
</Show> </Show>
</div> </div>

View file

@ -104,17 +104,23 @@ where
}); });
view! { view! {
<Binder target_ref=trigger_ref> <Binder target_ref=trigger_ref>
<div class="thaw-select" ref=trigger_ref on:click=show_menu style=move || css_vars.get()> <div
class="thaw-select"
ref=trigger_ref
on:click=show_menu
style=move || css_vars.get()
>
{move || select_option_label.get()} {move || select_option_label.get()}
</div> </div>
<Follower slot show=is_show_menu placement=FollowerPlacement::BottomStart width=FollowerWidth::Target> <Follower
<div slot
class="thaw-select-menu" show=is_show_menu
style=move || menu_css_vars.get() placement=FollowerPlacement::BottomStart
ref=menu_ref width=FollowerWidth::Target
> >
<div class="thaw-select-menu" style=move || menu_css_vars.get() ref=menu_ref>
<For <For
each=move || options.get() each=move || options.get()
key=move |item| item.value.clone() key=move |item| item.value.clone()

View file

@ -1,6 +1,10 @@
mod tab; mod tab;
use crate::{theme::use_theme, utils::mount_style, Theme}; use crate::{
theme::use_theme,
utils::{mount_style, Provider},
Theme,
};
use leptos::*; use leptos::*;
pub use tab::*; pub use tab::*;
@ -9,10 +13,6 @@ pub use tab::*;
pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView { pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children) -> impl IntoView {
mount_style("tabs", include_str!("./tabs.css")); mount_style("tabs", include_str!("./tabs.css"));
let tab_options_vec = create_rw_signal(vec![]); let tab_options_vec = create_rw_signal(vec![]);
provide_context(TabsInjection {
active_key: value,
tab_options_vec,
});
let theme = use_theme(Theme::light); let theme = use_theme(Theme::light);
let css_vars = create_memo(move |_| { let css_vars = create_memo(move |_| {
let mut css_vars = String::new(); let mut css_vars = String::new();
@ -36,66 +36,71 @@ pub fn Tabs(#[prop(optional, into)] value: RwSignal<String>, children: Children)
let label_list_ref = create_node_ref::<html::Div>(); let label_list_ref = create_node_ref::<html::Div>();
view! { view! {
<div class="thaw-tabs" style=move || css_vars.get()> <Provider value=TabsInjection {
<div class="thaw-tabs__label-list" ref=label_list_ref> active_key: value,
<For tab_options_vec,
each=move || tab_options_vec.get() }>
key=move |v| v.key.clone() <div class="thaw-tabs" style=move || css_vars.get()>
children=move |option| { <div class="thaw-tabs__label-list" ref=label_list_ref>
let label_ref = create_node_ref::<html::Span>(); <For
let TabOption { key, label } = option; each=move || tab_options_vec.get()
create_effect({ key=move |v| v.key.clone()
let key = key.clone(); children=move |option| {
move |_| { let label_ref = create_node_ref::<html::Span>();
let Some(label) = label_ref.get() else { let TabOption { key, label } = option;
return; create_effect({
}; let key = key.clone();
let Some(label_list) = label_list_ref.get() else { move |_| {
return; let Some(label) = label_ref.get() else {
}; return;
if key.clone() == value.get() { };
request_animation_frame(move || { let Some(label_list) = label_list_ref.get() else {
let list_rect = label_list.get_bounding_client_rect(); return;
let rect = label.get_bounding_client_rect(); };
label_line if key.clone() == value.get() {
.set( request_animation_frame(move || {
Some(TabsLabelLine { let list_rect = label_list.get_bounding_client_rect();
width: rect.width(), let rect = label.get_bounding_client_rect();
left: rect.left() - list_rect.left(), label_line
}), .set(
); Some(TabsLabelLine {
}); width: rect.width(),
left: rect.left() - list_rect.left(),
}),
);
});
}
} }
} });
}); view! {
view! { <span
<span class="thaw-tabs__label"
class="thaw-tabs__label" class=(
class=( "thaw-tabs__label--active",
"thaw-tabs__label--active", {
{ let key = key.clone();
move || key == value.get()
},
)
on:click={
let key = key.clone(); let key = key.clone();
move || key == value.get() move |_| value.set(key.clone())
}, }
)
on:click={ ref=label_ref
let key = key.clone(); >
move |_| value.set(key.clone()) {label}
} </span>
}
ref=label_ref
>
{label}
</span>
} }
} />
/>
<span class="thaw-tabs-label__line" style=move || label_line_style.get()></span> <span class="thaw-tabs-label__line" style=move || label_line_style.get()></span>
</div>
<div>{children()}</div>
</div> </div>
<div>{children()}</div> </Provider>
</div>
} }
} }

View file

@ -3,6 +3,7 @@ mod common;
use self::common::CommonTheme; use self::common::CommonTheme;
use crate::{ use crate::{
mobile::{NavBarTheme, TabbarTheme}, mobile::{NavBarTheme, TabbarTheme},
utils::Provider,
AlertTheme, AutoCompleteTheme, AvatarTheme, BreadcrumbTheme, ButtonTheme, ColorPickerTheme, AlertTheme, AutoCompleteTheme, AvatarTheme, BreadcrumbTheme, ButtonTheme, ColorPickerTheme,
InputTheme, MenuTheme, MessageTheme, ProgressTheme, SelectTheme, SkeletionTheme, SliderTheme, InputTheme, MenuTheme, MessageTheme, ProgressTheme, SelectTheme, SkeletionTheme, SliderTheme,
SwitchTheme, TableTheme, TagTheme, UploadTheme, SwitchTheme, TableTheme, TagTheme, UploadTheme,
@ -111,8 +112,8 @@ pub fn ThemeProvider(
} else { } else {
create_rw_signal(Theme::light()) create_rw_signal(Theme::light())
}; };
provide_context(theme);
children() view! { <Provider value=theme children/> }
} }
pub fn use_theme(default: impl Fn() -> Theme) -> ReadSignal<Theme> { pub fn use_theme(default: impl Fn() -> Theme) -> ReadSignal<Theme> {

View file

@ -2,6 +2,7 @@
mod component_ref; mod component_ref;
mod event_listener; mod event_listener;
mod mount_style; mod mount_style;
mod provider;
mod signal; mod signal;
mod stored_maybe_signal; mod stored_maybe_signal;
@ -9,5 +10,6 @@ mod stored_maybe_signal;
pub(crate) use component_ref::ComponentRef; pub(crate) use component_ref::ComponentRef;
pub(crate) use event_listener::*; pub(crate) use event_listener::*;
pub(crate) use mount_style::mount_style; pub(crate) use mount_style::mount_style;
pub(crate) use provider::Provider;
pub use signal::SignalWatch; pub use signal::SignalWatch;
pub(crate) use stored_maybe_signal::*; pub(crate) use stored_maybe_signal::*;

13
src/utils/provider.rs Normal file
View file

@ -0,0 +1,13 @@
/// https://github.com/leptos-rs/leptos/issues/2038
use leptos::*;
#[component]
pub fn Provider<T>(value: T, children: Children) -> impl IntoView
where
T: Clone + 'static,
{
run_as_child(move || {
provide_context(value);
children()
})
}