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 leptos::*;
use thaw_utils::mount_style;
use thaw_utils::{mount_dynamic_style, mount_style};
#[component]
pub fn ConfigProvider(
@ -15,25 +15,26 @@ pub fn ConfigProvider(
mount_style("config-provider", include_str!("./config-provider.css"));
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();
theme.with(|theme| {
theme.common.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 {
theme,
dir: dir.clone(),
};
let config_injection = ConfigInjection { theme, dir };
view! {
<Provider value=config_injection>
<div
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())
>
{children()}
@ -44,8 +45,8 @@ pub fn ConfigProvider(
#[derive(Clone)]
pub struct ConfigInjection {
theme: RwSignal<Theme>,
dir: RwSignal<Option<ConfigDirection>>,
pub theme: RwSignal<Theme>,
pub dir: RwSignal<Option<ConfigDirection>>,
}
#[derive(Clone)]

View file

@ -2,4 +2,4 @@ mod get_scroll_parent;
mod mount_style;
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_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());
} else {
use leptos::document;
let head = document().head().expect("head no exist");
let style = head
.query_selector(&format!("style[csr-id=\"thaw-{id}\"]"))
.query_selector(&format!("style[data-thaw-id=\"{id}\"]"))
.expect("query style element error");
#[cfg(feature = "hydrate")]
@ -25,9 +25,53 @@ pub fn mount_style(id: &str, content: &'static str) {
let style = document()
.create_element("style")
.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));
_ = 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 time;
pub use dom::{get_scroll_parent, mount_style};
pub use dom::{get_scroll_parent, mount_dynamic_style, mount_style};
pub use event_listener::{
add_event_listener, add_event_listener_with_bool, EventListenerHandle, IntoEventTarget,
};