use std::cell::RefCell;
use std::collections::BTreeMap;
use std::ops::Deref;
use std::rc::Rc;
use wasm_bindgen::JsCast;
use web_sys::HtmlStyleElement;
use crate::*;
type CSSResource = (&'static str, &'static str);
static DOM_STYLES: &[CSSResource] = &[css!("dom/checkbox"), css!("dom/select")];
#[derive(Clone, Default)]
pub struct StyleCache(Rc<StyleCacheData>);
impl Deref for StyleCache {
type Target = StyleCacheData;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl PartialEq for StyleCache {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl StyleCache {
pub fn add_style(&self, name: &'static str, css: &'static str) {
let mut map = self.0.styles.borrow_mut();
if !map.contains_key(name) {
let style = Self::into_style(name, css);
let first = map.values().next().cloned();
map.insert(name, style.clone());
if let Some(x) = first {
x.parent_node()
.unwrap_or_else(|| x.get_root_node())
.insert_before(&style, Some(&x))
.unwrap();
}
}
}
fn into_style(name: &str, css: &str) -> web_sys::HtmlStyleElement {
let elem = web_sys::window()
.unwrap()
.document()
.unwrap()
.create_element("style")
.unwrap();
elem.set_text_content(Some(css));
elem.set_attribute("name", name).unwrap();
elem.unchecked_into()
}
pub fn iter_styles(&self) -> impl Iterator<Item = (&'static str, HtmlStyleElement)> {
self.styles.borrow().clone().into_iter()
}
}
pub struct StyleCacheData {
styles: RefCell<BTreeMap<&'static str, web_sys::HtmlStyleElement>>,
}
impl Default for StyleCacheData {
fn default() -> Self {
let styles = DOM_STYLES
.iter()
.map(|x| (x.0, StyleCache::into_style(x.0, x.1)));
Self {
styles: RefCell::new(styles.collect()),
}
}
}