#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports))]
use crate::{
IntoElementMaybeSignal, UseCssVarOptions, UseMutationObserverOptions, WatchOptions,
use_mutation_observer_with_options, watch_with_options,
};
use leptos::prelude::*;
use std::time::Duration;
use wasm_bindgen::JsCast;
pub fn use_css_var(prop: impl Into<Signal<String>>) -> (ReadSignal<String>, WriteSignal<String>) {
use_css_var_with_options(prop, UseCssVarOptions::default())
}
pub fn use_css_var_with_options<P, El, M>(
prop: P,
options: UseCssVarOptions<El, M>,
) -> (ReadSignal<String>, WriteSignal<String>)
where
P: Into<Signal<String>>,
El: Clone,
El: IntoElementMaybeSignal<web_sys::Element, M>,
{
let UseCssVarOptions {
target,
initial_value,
observe,
..
} = options;
let (variable, set_variable) = signal(initial_value.clone());
#[cfg(not(feature = "ssr"))]
{
let el_signal = target.into_element_maybe_signal();
let prop = prop.into();
let update_css_var = move || {
if let Some(el) = el_signal.get_untracked() {
if let Ok(Some(style)) = window().get_computed_style(&el)
&& let Ok(value) = style.get_property_value(&prop.read_untracked())
&& !value.trim().is_empty()
{
set_variable.update(|var| *var = value.trim().to_string());
return;
}
let initial_value = initial_value.clone();
set_variable.update(|var| *var = initial_value);
}
};
if observe {
let update_css_var = update_css_var.clone();
use_mutation_observer_with_options(
el_signal,
move |_, _| update_css_var(),
UseMutationObserverOptions::default().attribute_filter(vec!["style".to_string()]),
);
}
set_timeout(update_css_var.clone(), Duration::ZERO);
let _ = watch_with_options(
move || (el_signal.get(), prop.get()),
move |_, _, _| update_css_var(),
WatchOptions::default().immediate(true),
);
Effect::watch(
move || variable.get(),
move |val, _, _| {
if let Some(el) = el_signal.get() {
let el = el.unchecked_ref::<web_sys::HtmlElement>();
let style = el.style();
let _ = style.set_property(&prop.get_untracked(), val);
}
},
false,
);
}
(variable, set_variable)
}