impulse_thaw/config_provider/
mod.rs

1use crate::Theme;
2use leptos::{context::Provider, prelude::*};
3use thaw_utils::{class_list, mount_dynamic_style, mount_style};
4
5#[component]
6pub fn ConfigProvider(
7    #[prop(optional, into)] class: MaybeProp<String>,
8    /// Sets the theme used in a scope.
9    #[prop(optional, into)]
10    theme: Option<RwSignal<Theme>>,
11    /// Theme id
12    #[prop(optional, into)]
13    theme_id: Option<String>,
14    /// Sets the direction of text & generated styles.
15    #[prop(optional, into)]
16    dir: Option<RwSignal<ConfigDirection>>,
17    children: Children,
18) -> impl IntoView {
19    mount_style("config-provider", include_str!("./config-provider.css"));
20
21    let theme = theme.unwrap_or_else(|| RwSignal::new(Theme::light()));
22    let theme_id = theme_id.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
23    let id = StoredValue::new(theme_id);
24
25    mount_dynamic_style(id.get_value(), move || {
26        let mut css_vars = String::new();
27        theme.with(|theme| {
28            theme.common.write_css_vars(&mut css_vars);
29            theme.color.write_css_vars(&mut css_vars);
30        });
31        format!(
32            ".thaw-config-provider[data-thaw-id=\"{}\"]{{{css_vars}}}",
33            id.get_value()
34        )
35    });
36
37    #[cfg(not(feature = "ssr"))]
38    Owner::on_cleanup(move || {
39        if let Ok(Some(style)) =
40            document().query_selector(&format!("head style[data-thaw-id=\"{}\"]", id.get_value()))
41        {
42            style.remove();
43        }
44    });
45
46    let config_injection = ConfigInjection { theme, dir, id };
47
48    view! {
49        <Provider value=config_injection>
50            <div
51                class=class_list!["thaw-config-provider", class]
52                data-thaw-id=id.get_value()
53                dir=move || dir.map(move |dir| dir.get().as_str())
54            >
55                {children()}
56            </div>
57        </Provider>
58    }
59}
60
61#[derive(Clone)]
62pub struct ConfigInjection {
63    pub theme: RwSignal<Theme>,
64    pub dir: Option<RwSignal<ConfigDirection>>,
65    id: StoredValue<String>,
66}
67
68impl ConfigInjection {
69    pub fn id(&self) -> String {
70        self.id.get_value()
71    }
72
73    pub fn expect_context() -> Self {
74        expect_context()
75    }
76}
77
78#[derive(Debug, Clone, Copy, Default)]
79pub enum ConfigDirection {
80    Ltr,
81    Rtl,
82    #[default]
83    Auto,
84}
85
86impl ConfigDirection {
87    pub fn as_str(&self) -> &'static str {
88        match self {
89            ConfigDirection::Ltr => "ltr",
90            ConfigDirection::Rtl => "rtl",
91            ConfigDirection::Auto => "auto",
92        }
93    }
94}