mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: add is_mounted
and dyn_classes
(#714)
This commit is contained in:
parent
89ca047f2f
commit
5329561687
1 changed files with 119 additions and 0 deletions
|
@ -573,6 +573,23 @@ impl<El: ElementDescriptor + 'static> HtmlElement<El> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Checks to see if this element is mounted to the DOM as a child
|
||||
/// of `body`.
|
||||
///
|
||||
/// This method will always return [`None`] on non-wasm CSR targets.
|
||||
pub fn is_mounted(&self) -> bool {
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
{
|
||||
crate::document()
|
||||
.body()
|
||||
.unwrap()
|
||||
.contains(Some(self.element.as_ref()))
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
false
|
||||
}
|
||||
|
||||
/// Adds an attribute to this element.
|
||||
#[track_caller]
|
||||
pub fn attr(
|
||||
|
@ -679,6 +696,108 @@ impl<El: ElementDescriptor + 'static> HtmlElement<El> {
|
|||
this
|
||||
}
|
||||
|
||||
/// Sets the class on the element as the class signal changes.
|
||||
#[track_caller]
|
||||
pub fn dyn_classes<I, C>(
|
||||
self,
|
||||
classes_signal: impl Fn() -> I + 'static,
|
||||
) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = C>,
|
||||
C: Into<Cow<'static, str>>,
|
||||
{
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
{
|
||||
use smallvec::SmallVec;
|
||||
|
||||
let class_list = self.element.as_ref().class_list();
|
||||
|
||||
leptos_reactive::create_effect(
|
||||
self.cx,
|
||||
move |prev_classes: Option<
|
||||
SmallVec<[Cow<'static, str>; 4]>,
|
||||
>| {
|
||||
let classes = classes_signal()
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect::<SmallVec<[Cow<'static, str>; 4]>>(
|
||||
);
|
||||
|
||||
let mut new_classes = classes
|
||||
.iter()
|
||||
.flat_map(|classes| classes.split_whitespace());
|
||||
|
||||
if let Some(prev_classes) = prev_classes {
|
||||
let mut old_classes = prev_classes
|
||||
.iter()
|
||||
.flat_map(|classes| classes.split_whitespace());
|
||||
|
||||
// Remove old classes
|
||||
for prev_class in old_classes.clone() {
|
||||
if !new_classes.any(|c| c == prev_class) {
|
||||
class_list.remove_1(prev_class).unwrap_or_else(
|
||||
|err| {
|
||||
panic!(
|
||||
"failed to add class \
|
||||
`{prev_class}`, error: {err:#?}"
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new classes
|
||||
for class in new_classes {
|
||||
if !old_classes.any(|c| c == class) {
|
||||
class_list.add_1(class).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"failed to remove class `{class}`, \
|
||||
error: {err:#?}"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let new_classes = new_classes
|
||||
.map(ToOwned::to_owned)
|
||||
.collect::<SmallVec<[_; 4]>>();
|
||||
|
||||
for class in &new_classes {
|
||||
class_list.add_1(class).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"failed to add class `{class}`, error: \
|
||||
{err:#?}"
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
classes
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
|
||||
{
|
||||
let mut this = self;
|
||||
|
||||
let this = classes_signal()
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.flat_map(|classes| {
|
||||
classes
|
||||
.split_whitespace()
|
||||
.map(ToString::to_string)
|
||||
.collect::<SmallVec<[_; 4]>>()
|
||||
})
|
||||
.fold(this, |this, class| this.class(class, true));
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets a property on an element.
|
||||
#[track_caller]
|
||||
pub fn prop(
|
||||
|
|
Loading…
Reference in a new issue