textiler_core/context/
style_manager_context.rs1use std::ops::Deref;
2use std::rc::Rc;
3
4use cfg_if::cfg_if;
5use gloo::utils::document;
6use stylist::ast::ToStyleStr;
7use stylist::manager::StyleManager;
8use wasm_bindgen::JsCast;
9use web_sys::{HtmlStyleElement, Node};
10
11use crate::{Error, Sx};
12use crate::theme::Theme;
13use crate::theme::theme_mode::ThemeMode;
14
15#[derive(Default, Debug, Clone, PartialEq)]
16pub struct StyleManagerContext {
17 manager: Rc<StyleManager>,
18}
19
20impl StyleManagerContext {
21 pub fn new(manager: Rc<StyleManager>) -> Self {
22 Self { manager }
23 }
24
25 #[cfg(target_arch = "wasm32")]
26 pub(crate) fn mount_wasm(
27 &self,
28 theme: &Theme,
29 mode: &ThemeMode,
30 to_mount: Sx,
31 ) -> Result<(), Error> {
32 let document = document();
33 let container = self.container().ok_or(Error::Web(None))?;
34
35 (|| {
36 let css = to_mount.to_css(&mode, theme);
37 let style_element = document.create_element("style")?;
38 let theme_name = format!("theme-{}-main", theme.prefix);
39 style_element.set_attribute("data-style", &theme_name)?;
40 let base_css = css.to_style_str(None);
41
42 if option_env!("MINIFY_CSS").is_some() {
43 match minifier::css::minify(&base_css) {
44 Ok(minified) => {
45 style_element.set_text_content(Some(&minified.to_string()));
46 }
47 Err(non_minified) => {
48 style_element.set_text_content(Some(non_minified));
49 }
50 }
51 } else {
52 style_element.set_text_content(Some(&base_css));
53 }
54
55 let list = container.child_nodes();
56 let len = list.length();
57 let mut existing: Option<Node> = None;
58 for i in 0..len {
59 if let Some(child) = list.get(i) {
60 if let Some(style_element) = child.dyn_ref::<HtmlStyleElement>() {
61 if style_element.get_attribute("data-style").as_ref() == Some(&theme_name) {
62 existing = Some(child);
63 break;
64 }
65 }
66 }
67 }
68
69 if let Some(ref existing) = existing {
70 container.replace_child(&style_element, existing)?;
71 } else {
72 container.append_child(&style_element)?;
73 }
74
75 Ok(())
76 })()
77 .map_err(|e| Error::Web(Some(e)))
78 }
79 pub fn mount(&self, theme: &Theme, mode: &ThemeMode, to_mount: Sx) -> Result<(), crate::Error> {
80 cfg_if! {
81 if #[cfg(target_arch="wasm32")] {
82 self.mount_wasm(theme, mode, to_mount)
83 } else {
84 Err(Error::MountingUnsupported)
85 }
86 }
87 }
88}
89
90impl Deref for StyleManagerContext {
91 type Target = StyleManager;
92
93 fn deref(&self) -> &Self::Target {
94 &*self.manager
95 }
96}