1use std::ops::{Deref, DerefMut};
4use stylist::ast::ToStyleStr;
5use stylist::manager::StyleManager;
6use wasm_bindgen::JsCast;
7use yew::{function_component, html, use_effect_with, use_state_eq, Children, Html, Properties};
8
9use crate::theme::baseline::baseline;
10use crate::theme::theme_mode::ThemeMode;
11use crate::theme::{Theme};
12use crate::{Error, hooks, Sx};
13
14pub use self::{mode_context::ThemeModeContext, style_manager_context::StyleManagerContext, theme_context::ThemeContext};
15
16mod mode_context;
17mod style_manager_context;
18mod theme_context;
19
20#[derive(Debug, Clone, PartialEq, Properties)]
21pub struct ThemeProviderProps {
22 #[prop_or_default]
23 pub theme: Theme,
24 #[prop_or_default]
25 pub children: Children,
26}
27
28#[function_component]
29pub fn ThemeProvider(props: &ThemeProviderProps) -> Html {
30 let theme_state = ThemeContext::new(yew::use_state_eq(|| props.theme.clone()));
31 let manager = StyleManagerContext::new(yew::use_memo(theme_state.clone(), |_| {
32 StyleManager::builder()
33 .prefix(theme_state.prefix.clone().into())
34 .build()
35 .expect("could not create style manager")
36 }));
37 let mode = ThemeModeContext::new(use_state_eq(|| ThemeMode::System.detect()));
38
39 html! {
40 <yew::ContextProvider<ThemeContext> context={theme_state}>
41 <yew::ContextProvider<ThemeModeContext> context={mode}>
42 <yew::ContextProvider<StyleManagerContext> context={manager}>
43 {for props.children.iter()}
44 </yew::ContextProvider<StyleManagerContext>>
45 </yew::ContextProvider<ThemeModeContext>>
46 </yew::ContextProvider<ThemeContext>>
47 }
48}
49
50#[function_component]
51pub fn CssBaseline() -> Html {
52 let theme = hooks::use_theme();
53 let style_manager: StyleManagerContext = hooks::use_style_manager();
54 let (mode, ..) = hooks::use_mode();
55
56 use_effect_with((theme, mode), move |(theme, mode)| {
57 style_manager
58 .mount(theme, &mode, baseline(theme, &mode))
59 .expect("could not mount sx");
60 });
61
62 html! {}
63}