feat: ConfigProvider CSSVars

This commit is contained in:
luoxiao 2024-05-23 17:44:00 +08:00
parent 4aee77908f
commit 643a54185c
4 changed files with 60 additions and 15 deletions

View file

@ -1,6 +1,6 @@
use crate::Theme; use crate::Theme;
use leptos::*; use leptos::*;
use thaw_utils::mount_style; use thaw_utils::{mount_dynamic_style, mount_style};
#[component] #[component]
pub fn ConfigProvider( pub fn ConfigProvider(
@ -15,25 +15,26 @@ pub fn ConfigProvider(
mount_style("config-provider", include_str!("./config-provider.css")); mount_style("config-provider", include_str!("./config-provider.css"));
let theme = theme.unwrap_or_else(|| RwSignal::new(Theme::light())); let theme = theme.unwrap_or_else(|| RwSignal::new(Theme::light()));
let css_vars = Memo::new(move |_| { let id = StoredValue::new(uuid::Uuid::new_v4().to_string());
mount_dynamic_style(id.get_value(), move || {
let mut css_vars = String::new(); let mut css_vars = String::new();
theme.with(|theme| { theme.with(|theme| {
theme.common.write_css_vars(&mut css_vars); theme.common.write_css_vars(&mut css_vars);
theme.color.write_css_vars(&mut css_vars); theme.color.write_css_vars(&mut css_vars);
}); });
css_vars format!(
".thaw-config-provider[data-thaw-id=\"{}\"]{{{css_vars}}}",
id.get_value()
)
}); });
let config_injection = ConfigInjection { let config_injection = ConfigInjection { theme, dir };
theme,
dir: dir.clone(),
};
view! { view! {
<Provider value=config_injection> <Provider value=config_injection>
<div <div
class="thaw-config-provider" class="thaw-config-provider"
style=move || css_vars.get() data-thaw-id=id.get_value()
dir=move || dir.get().map(move |dir| dir.as_str()) dir=move || dir.get().map(move |dir| dir.as_str())
> >
{children()} {children()}
@ -44,8 +45,8 @@ pub fn ConfigProvider(
#[derive(Clone)] #[derive(Clone)]
pub struct ConfigInjection { pub struct ConfigInjection {
theme: RwSignal<Theme>, pub theme: RwSignal<Theme>,
dir: RwSignal<Option<ConfigDirection>>, pub dir: RwSignal<Option<ConfigDirection>>,
} }
#[derive(Clone)] #[derive(Clone)]

View file

@ -2,4 +2,4 @@ mod get_scroll_parent;
mod mount_style; mod mount_style;
pub use get_scroll_parent::get_scroll_parent; pub use get_scroll_parent::get_scroll_parent;
pub use mount_style::mount_style; pub use mount_style::{mount_dynamic_style, mount_style};

View file

@ -6,13 +6,13 @@ pub fn mount_style(id: &str, content: &'static str) {
use leptos::html::style; use leptos::html::style;
use leptos_meta::use_head; use leptos_meta::use_head;
let meta = use_head(); let meta = use_head();
let style_el = style().attr("csr-id", format!("thaw-{id}")).child(content); let style_el = style().attr("data-thaw-id", id).child(content);
meta.tags.register(format!("leptos-thaw-{id}").into(), style_el.into_any()); meta.tags.register(format!("leptos-thaw-{id}").into(), style_el.into_any());
} else { } else {
use leptos::document; use leptos::document;
let head = document().head().expect("head no exist"); let head = document().head().expect("head no exist");
let style = head let style = head
.query_selector(&format!("style[csr-id=\"thaw-{id}\"]")) .query_selector(&format!("style[data-thaw-id=\"{id}\"]"))
.expect("query style element error"); .expect("query style element error");
#[cfg(feature = "hydrate")] #[cfg(feature = "hydrate")]
@ -25,9 +25,53 @@ pub fn mount_style(id: &str, content: &'static str) {
let style = document() let style = document()
.create_element("style") .create_element("style")
.expect("create style element error"); .expect("create style element error");
_ = style.set_attribute("csr-id", &format!("thaw-{id}")); _ = style.set_attribute("data-thaw-id", id);
style.set_text_content(Some(content)); style.set_text_content(Some(content));
_ = head.prepend_with_node_1(&style); _ = head.prepend_with_node_1(&style);
} }
} }
} }
pub fn mount_dynamic_style<T: Fn() -> String + 'static>(id: String, f: T) {
cfg_if! {
if #[cfg(feature = "ssr")] {
use leptos::html::style;
use leptos_meta::use_head;
let meta = use_head();
let content = leptos::untrack(|| f());
let style_el = style().attr("data-thaw-id", id).child(content);
meta.tags.register(format!("leptos-thaw-{id}").into(), style_el.into_any());
} else {
use leptos::document;
let head = document().head().expect("head no exist");
let style = head
.query_selector(&format!("style[data-thaw-id=\"{id}\"]"))
.expect("query style element error");
#[cfg(feature = "hydrate")]
let _ = leptos::leptos_dom::HydrationCtx::id();
leptos::Effect::new_isomorphic(move |prev: Option<Option<web_sys::Element>>| {
let content = f();
if let Some(style) = style.as_ref() {
style.set_text_content(Some(&content));
None
} else if let Some(style) = prev.flatten() {
style.set_text_content(Some(&content));
Some(style)
} else {
let style = document()
.create_element("style")
.expect("create style element error");
_ = style.set_attribute("data-thaw-id", &id);
style.set_text_content(Some(&content));
_ = head.prepend_with_node_1(&style);
Some(style)
}
});
}
}
}

View file

@ -7,7 +7,7 @@ mod signals;
mod throttle; mod throttle;
mod time; mod time;
pub use dom::{get_scroll_parent, mount_style}; pub use dom::{get_scroll_parent, mount_dynamic_style, mount_style};
pub use event_listener::{ pub use event_listener::{
add_event_listener, add_event_listener_with_bool, EventListenerHandle, IntoEventTarget, add_event_listener, add_event_listener_with_bool, EventListenerHandle, IntoEventTarget,
}; };