- {move || select_name.get()}
{
gen_menu_data().into_iter().map(|data| {
diff --git a/thaw/src/accordion/accordion_item.rs b/thaw/src/accordion/accordion_item.rs
index 1a74f83..b7d02c8 100644
--- a/thaw/src/accordion/accordion_item.rs
+++ b/thaw/src/accordion/accordion_item.rs
@@ -59,7 +59,7 @@ pub fn AccordionItem(
{children()}
diff --git a/thaw/src/table/mod.rs b/thaw/src/table/mod.rs
index 3afeaa2..8779f78 100644
--- a/thaw/src/table/mod.rs
+++ b/thaw/src/table/mod.rs
@@ -1,10 +1,8 @@
-use leptos::prelude::*;
-use thaw_components::OptionComp;
+use leptos::{either::Either, prelude::*};
use thaw_utils::{class_list, mount_style};
#[component]
pub fn Table(
- #[prop(optional, into)] style: MaybeProp,
#[prop(optional, into)] class: MaybeProp,
children: Children,
) -> impl IntoView {
@@ -31,9 +29,13 @@ pub fn TableHeaderCell(#[prop(optional)] children: Option) -> impl Int
view! {
}
@@ -61,9 +63,13 @@ pub fn TableRow(children: Children) -> impl IntoView {
pub fn TableCell(#[prop(optional)] children: Option) -> impl IntoView {
view! {
-
- {children()}
-
+ {
+ if let Some(children) = children {
+ Either::Left(children())
+ } else {
+ Either::Right(())
+ }
+ }
|
}
}
diff --git a/thaw_components/src/css_transition/mod.rs b/thaw_components/src/css_transition/mod.rs
index 3834386..b58e9d9 100644
--- a/thaw_components/src/css_transition/mod.rs
+++ b/thaw_components/src/css_transition/mod.rs
@@ -27,6 +27,10 @@ where
IV: IntoView + 'static,
{
let display = RwSignal::new((!show.get_untracked()).then_some("display: none;"));
+ let next_frame = NextFrame::new();
+ let end_handle = StoredValue::new(None::);
+ let end_count = StoredValue::new(None::);
+ let finish = StoredValue::new(None::>);
Effect::new(move |_| {
let target_ref = node_ref.get();
@@ -35,27 +39,23 @@ where
};
let class_list = el.class_list();
- let next_frame = NextFrame::use_();
- let end_handle = StoredValue::new(None::);
- let end_count = StoredValue::new(None::);
- let finish = StoredValue::new(None::>);
- let on_end = Callback::new({
+ let on_end = {
let el = send_wrapper::SendWrapper::new(el.clone());
- move |remove: Callback<()>| {
+ move |remove: Box| {
let Some(CSSTransitionInfo {
types,
prop_count,
timeout,
}) = get_transition_info(&el)
else {
- remove.call(());
+ remove();
return;
};
- finish.set_value(Some(Callback::new(move |_| {
+ finish.set_value(Some(Box::new(move || {
end_count.set_value(None);
- remove.call(());
+ remove();
end_handle.update_value(|h| {
h.take().map(|h| {
h.remove();
@@ -65,9 +65,9 @@ where
set_timeout(
move || {
- finish.try_update_value(|v| {
- v.take().map(|f| f.call(()));
- });
+ if let Some(Some(f)) = finish.try_update_value(|f| f.take()) {
+ f();
+ }
},
Duration::from_millis(timeout + 1),
);
@@ -86,9 +86,9 @@ where
};
*v >= prop_count
}) {
- finish.update_value(|v| {
- v.take().map(|f| f.call(()));
- });
+ if let Some(Some(f)) = finish.try_update_value(|f| f.take()) {
+ f();
+ }
}
};
let handle = match types {
@@ -105,97 +105,16 @@ where
};
end_handle.set_value(Some(handle));
}
- });
+ };
let on_finish = move || {
- finish.update_value(|v| {
- v.take().map(|f| f.call(()));
- });
- };
-
- let on_enter_fn = {
- let class_list = class_list.clone();
- let class_list = send_wrapper::SendWrapper::new(class_list);
- let on_before_enter = on_before_enter.clone();
- let on_after_enter = on_after_enter.clone();
- let on_enter = on_enter.clone();
- let on_end = on_end.clone();
- Callback::new(move |name: String| {
- if let Some(on_before_enter) = on_before_enter.as_ref() {
- on_before_enter.call(());
- }
- let enter_from = format!("{name}-enter-from");
- let enter_active = format!("{name}-enter-active");
- let enter_to = format!("{name}-enter-to");
-
- let _ = class_list.add_2(&enter_from, &enter_active);
- display.set(None);
-
- let class_list = class_list.clone();
- let on_after_enter = on_after_enter.clone();
- let on_end = on_end.clone();
- let on_enter = on_enter.clone();
- next_frame.run(move || {
- let _ = class_list.remove_1(&enter_from);
- let _ = class_list.add_1(&enter_to);
-
- let remove = Callback::new(move |_| {
- let _ = class_list.remove_2(&enter_active, &enter_to);
- if let Some(on_after_enter) = on_after_enter.as_ref() {
- on_after_enter.call(());
- }
- });
- on_end.call(remove);
-
- if let Some(on_enter) = on_enter {
- on_enter.call(());
- }
- });
- })
- };
-
- let on_leave_fn = {
- let class_list = class_list.clone();
- let class_list = send_wrapper::SendWrapper::new(class_list);
- let on_before_leave = on_before_leave.clone();
- let on_after_leave = on_after_leave.clone();
- let on_leave = on_leave.clone();
- let on_end = on_end.clone();
- Callback::new(move |name: String| {
- if let Some(on_before_leave) = on_before_leave.as_ref() {
- on_before_leave.call(());
- }
- let leave_from = format!("{name}-leave-from");
- let leave_active = format!("{name}-leave-active");
- let leave_to = format!("{name}-leave-to");
-
- let _ = class_list.add_2(&leave_from, &leave_active);
-
- let class_list = class_list.clone();
- let on_after_leave = on_after_leave.clone();
- let on_end = on_end.clone();
- let on_leave = on_leave.clone();
- next_frame.run(move || {
- let _ = class_list.remove_1(&leave_from);
- let _ = class_list.add_1(&leave_to);
-
- let remove = Callback::new(move |_| {
- let _ = class_list.remove_2(&leave_active, &leave_to);
- display.set(Some("display: none;"));
- if let Some(on_after_leave) = on_after_leave.as_ref() {
- on_after_leave.call(());
- }
- });
- on_end.call(remove);
- if let Some(on_leave) = on_leave {
- on_leave.call(());
- }
- });
- })
+ if let Some(Some(f)) = finish.try_update_value(|f| f.take()) {
+ f();
+ }
};
let name = name.clone();
- let _ = RenderEffect::new(move |prev: Option| {
+ let effect = RenderEffect::new(move |prev: Option| {
let show = show.get();
let prev = if let Some(prev) = prev {
prev
@@ -209,16 +128,80 @@ where
if show && !prev {
on_finish();
- on_enter_fn.call(name);
+ {
+ // on_enter
+ if let Some(on_before_enter) = on_before_enter.as_ref() {
+ on_before_enter.call(());
+ }
+ let enter_from = format!("{name}-enter-from");
+ let enter_active = format!("{name}-enter-active");
+ let enter_to = format!("{name}-enter-to");
+
+ let _ = class_list.add_2(&enter_from, &enter_active);
+ display.set(None);
+
+ let class_list = class_list.clone();
+ let on_end = on_end.clone();
+ next_frame.run(move || {
+ let _ = class_list.remove_1(&enter_from);
+ let _ = class_list.add_1(&enter_to);
+
+ let class_list = send_wrapper::SendWrapper::new(class_list);
+ let remove = Box::new(move || {
+ let _ = class_list.remove_2(&enter_active, &enter_to);
+ if let Some(on_after_enter) = on_after_enter.as_ref() {
+ on_after_enter.call(());
+ }
+ });
+ on_end(remove);
+
+ if let Some(on_enter) = on_enter.as_ref() {
+ on_enter.call(());
+ }
+ });
+ }
} else if !show && prev {
on_finish();
- on_leave_fn.call(name);
+ {
+ // on_leave
+ if let Some(on_before_leave) = on_before_leave.as_ref() {
+ on_before_leave.call(());
+ }
+ let leave_from = format!("{name}-leave-from");
+ let leave_active = format!("{name}-leave-active");
+ let leave_to = format!("{name}-leave-to");
+
+ let _ = class_list.add_2(&leave_from, &leave_active);
+
+ let class_list = class_list.clone();
+ let on_after_leave = on_after_leave.clone();
+ let on_end = on_end.clone();
+ let on_leave = on_leave.clone();
+ next_frame.run(move || {
+ let _ = class_list.remove_1(&leave_from);
+ let _ = class_list.add_1(&leave_to);
+
+ let class_list = send_wrapper::SendWrapper::new(class_list);
+ let remove = Box::new(move || {
+ let _ = class_list.remove_2(&leave_active, &leave_to);
+ display.set(Some("display: none;"));
+ if let Some(on_after_leave) = on_after_leave.as_ref() {
+ on_after_leave.call(());
+ }
+ });
+ on_end(remove);
+ if let Some(on_leave) = on_leave {
+ on_leave.call(());
+ }
+ });
+ }
}
show
});
on_cleanup(move || {
+ drop(effect);
end_handle.update_value(|handle| {
if let Some(handle) = handle.take() {
handle.remove();
diff --git a/thaw_utils/src/class_list.rs b/thaw_utils/src/class_list.rs
index b118654..8175e06 100644
--- a/thaw_utils/src/class_list.rs
+++ b/thaw_utils/src/class_list.rs
@@ -1,12 +1,8 @@
#[cfg(not(feature = "ssr"))]
use leptos::prelude::RenderEffect;
use leptos::{
- logging::log,
prelude::{MaybeProp, Memo, Oco, RwSignal},
- reactive_graph::{
- graph::{AnySubscriber, ToAnySubscriber},
- traits::{Get, Update, With, WithUntracked},
- },
+ reactive_graph::traits::{Get, Update, With, WithUntracked},
tachys::renderer::DomRenderer,
};
use std::{collections::HashSet, sync::Arc};
@@ -14,7 +10,8 @@ use std::{collections::HashSet, sync::Arc};
#[derive(Clone, Default)]
pub struct ClassList {
value: RwSignal>>,
- effects: Vec,
+ effects_oco: Vec>>>,
+ effects_option_oco: Vec>>>>,
effects_bool: Vec>>,
}
@@ -58,7 +55,7 @@ impl ClassList {
}
name
});
- self.effects.push(effect.to_any_subscriber());
+ self.effects_oco.push(effect.into());
}
}
Class::FnOptionString(f) => {
@@ -99,7 +96,7 @@ impl ClassList {
}
name
});
- self.effects.push(effect.to_any_subscriber());
+ self.effects_option_oco.push(effect.into());
}
}
Class::Fn(name, f) => {
@@ -117,7 +114,6 @@ impl ClassList {
let effect = RenderEffect::new(move |old| {
let name = name.clone();
let new = f();
- log!("ClassList: {name} {new} {old:#?}");
if old.is_none() {
if new {
self.value.update(|set| {
@@ -209,11 +205,17 @@ where
fn build(self, el: &R::Element) -> Self::State {
let el = el.to_owned();
RenderEffect::new(move |prev| {
- if let Some(_) = prev {
- unreachable!()
+ let mut class = String::new();
+ self.write_class_string(&mut class);
+ if let Some(state) = prev {
+ let (el, prev_class) = state;
+ if class != prev_class {
+ R::set_attribute(&el, "class", &class);
+ (el, class)
+ } else {
+ (el, prev_class)
+ }
} else {
- let mut class = String::new();
- self.write_class_string(&mut class);
if !class.is_empty() {
R::set_attribute(&el, "class", &class);
}
diff --git a/thaw_utils/src/hooks/use_next_frame.rs b/thaw_utils/src/hooks/use_next_frame.rs
index c2af79d..1e13781 100644
--- a/thaw_utils/src/hooks/use_next_frame.rs
+++ b/thaw_utils/src/hooks/use_next_frame.rs
@@ -20,7 +20,7 @@ impl Default for NextFrame {
impl Copy for NextFrame {}
impl NextFrame {
- pub fn use_() -> Self {
+ pub fn new() -> Self {
let next_frame = NextFrame::default();
on_cleanup(move || {