feat(leptos-v0.7): error

This commit is contained in:
luoxiao 2024-07-10 11:29:22 +08:00 committed by luoxiaozero
parent 4262493f61
commit 58b7eb35aa
8 changed files with 60 additions and 108 deletions

View file

@ -4,9 +4,7 @@ pub use auto_complete_option::AutoCompleteOption;
use crate::{ComponentRef, ConfigInjection, Input, InputPrefix, InputRef, InputSuffix}; use crate::{ComponentRef, ConfigInjection, Input, InputPrefix, InputRef, InputSuffix};
use leptos::{context::Provider, either::Either, html, prelude::*}; use leptos::{context::Provider, either::Either, html, prelude::*};
use thaw_components::{ use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement, FollowerWidth};
Binder, CSSTransition, Follower, FollowerPlacement, FollowerWidth, OptionComp,
};
use thaw_utils::{class_list, mount_style, Model, OptionalProp}; use thaw_utils::{class_list, mount_style, Model, OptionalProp};
#[slot] #[slot]

View file

@ -1,6 +1,6 @@
use crate::{ConfigInjection, Icon}; use crate::{ConfigInjection, Icon};
use leptos::{ev, html, prelude::*}; use leptos::{either::Either, ev, html, prelude::*};
use thaw_components::{CSSTransition, Fallback, OptionComp, Teleport}; use thaw_components::{CSSTransition, Teleport};
use thaw_utils::{ use thaw_utils::{
add_event_listener, class_list, get_scroll_parent, mount_style, EventListenerHandle, add_event_listener, class_list, get_scroll_parent, mount_style, EventListenerHandle,
OptionalProp, OptionalProp,
@ -93,12 +93,13 @@ pub fn BackTop(
} }
on:click=on_click on:click=on_click
> >
<OptionComp value=children let:children> {
<Fallback slot> if let Some(children) = children {
<Icon icon=icondata_ai::AiVerticalAlignTopOutlined/> Either::Left(children())
</Fallback> } else {
{children()} Either::Right(view!{<Icon icon=icondata_ai::AiVerticalAlignTopOutlined/>})
</OptionComp> }
}
</div> </div>
</CSSTransition> </CSSTransition>
</Teleport> </Teleport>

View file

@ -5,7 +5,6 @@ pub use button_group::ButtonGroup;
use crate::icon::Icon; use crate::icon::Icon;
use leptos::{either::Either, ev, prelude::*}; use leptos::{either::Either, ev, prelude::*};
use send_wrapper::SendWrapper; use send_wrapper::SendWrapper;
use thaw_components::OptionComp;
use thaw_utils::{class_list, mount_style, OptionalMaybeSignal, OptionalProp}; use thaw_utils::{class_list, mount_style, OptionalMaybeSignal, OptionalProp};
#[derive(Default, PartialEq, Clone, Copy)] #[derive(Default, PartialEq, Clone, Copy)]
@ -115,10 +114,10 @@ pub fn Button(
move || { move || {
let icon = icon.get(); let icon = icon.get();
view! { if let Some(icon) = icon {
<OptionComp value=icon let:icon> Either::Left(view!{<Icon icon=icon class="thaw-button__icon"/>})
<Icon icon=icon class="thaw-button__icon"/> } else {
</OptionComp> Either::Right(())
} }
} }
} }

View file

@ -7,12 +7,12 @@ use leptos::leptos_dom::helpers::WindowListenerHandle;
use leptos::{ev, html, prelude::*}; use leptos::{ev, html, prelude::*};
use palette::{Hsv, IntoColor, Srgb}; use palette::{Hsv, IntoColor, Srgb};
use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement}; use thaw_components::{Binder, CSSTransition, Follower, FollowerPlacement};
use thaw_utils::{class_list, mount_style, Model, OptionalProp}; use thaw_utils::{class_list, mount_style, Model};
#[component] #[component]
pub fn ColorPicker( pub fn ColorPicker(
#[prop(optional, into)] value: Model<Color>, #[prop(optional, into)] value: Model<Color>,
#[prop(optional, into)] class: OptionalProp<MaybeSignal<String>>, #[prop(optional, into)] class: MaybeProp<String>,
) -> impl IntoView { ) -> impl IntoView {
mount_style("color-picker", include_str!("./color-picker.css")); mount_style("color-picker", include_str!("./color-picker.css"));
let config_provider = ConfigInjection::use_(); let config_provider = ConfigInjection::use_();
@ -106,6 +106,12 @@ pub fn ColorPicker(
{ {
use leptos::wasm_bindgen::__rt::IntoJsResult; use leptos::wasm_bindgen::__rt::IntoJsResult;
let timer = window_event_listener(ev::click, move |ev| { let timer = window_event_listener(ev::click, move |ev| {
let Some(popovel_el) = popover_ref.get_untracked() else {
return;
};
let Some(trigger_el) = trigger_ref.get_untracked() else {
return;
};
let el = ev.target(); let el = ev.target();
let mut el: Option<web_sys::Element> = let mut el: Option<web_sys::Element> =
el.into_js_result().map_or(None, |el| Some(el.into())); el.into_js_result().map_or(None, |el| Some(el.into()));
@ -114,9 +120,7 @@ pub fn ColorPicker(
if current_el == *body { if current_el == *body {
break; break;
}; };
if current_el == **popover_ref.get().unwrap() if current_el == **popovel_el || current_el == **trigger_el {
|| current_el == **trigger_ref.get().unwrap()
{
return; return;
} }
el = current_el.parent_element(); el = current_el.parent_element();
@ -129,7 +133,7 @@ pub fn ColorPicker(
view! { view! {
<Binder target_ref=trigger_ref> <Binder target_ref=trigger_ref>
<div <div
class=class_list!["thaw-color-picker-trigger", class.map(| c | move || c.get())] class=class_list!["thaw-color-picker-trigger", class]
on:click=show_popover on:click=show_popover
node_ref=trigger_ref node_ref=trigger_ref
> >

View file

@ -19,35 +19,16 @@ pub fn OverlayDrawer(
let config_provider = ConfigInjection::use_(); let config_provider = ConfigInjection::use_();
let drawer_ref = NodeRef::<html::Div>::new(); let drawer_ref = NodeRef::<html::Div>::new();
let is_css_transition = RwSignal::new(false);
let on_after_enter = move |_| {
is_css_transition.set(false);
};
let lazy_position = Memo::new(move |prev| {
let position = position.get().as_str();
let Some(prev) = prev else {
return position;
};
if is_css_transition.get() {
prev
} else {
position
}
});
let is_lock = RwSignal::new(open.get_untracked()); let is_lock = RwSignal::new(open.get_untracked());
Effect::new(move |_| { Effect::new(move |_| {
let is_open = open.get(); let is_open = open.get();
if is_open { if is_open {
is_lock.set(true); is_lock.set(true);
is_css_transition.set(true);
} }
}); });
use_lock_html_scroll(is_lock.into()); use_lock_html_scroll(is_lock.into());
let on_after_leave = move |_| { let on_after_leave = move |_| {
is_lock.set(false); is_lock.set(false);
is_css_transition.set(false);
}; };
let mask_ref = NodeRef::<html::Div>::new(); let mask_ref = NodeRef::<html::Div>::new();
@ -83,17 +64,16 @@ pub fn OverlayDrawer(
appear=open.get_untracked() appear=open.get_untracked()
show=open.signal() show=open.signal()
name=Memo::new(move |_| { name=Memo::new(move |_| {
format!("slide-in-from-{}-transition", lazy_position.get()) format!("slide-in-from-{}-transition", position.get().as_str())
}) })
on_after_enter
on_after_leave on_after_leave
let:display let:display
> >
<div <div
class=class_list![ class=class_list![
"thaw-overlay-drawer", "thaw-overlay-drawer",
move || format!("thaw-overlay-drawer--position-{}", lazy_position.get()) move || format!("thaw-overlay-drawer--position-{}", position.get().as_str())
] ]
style=move || { style=move || {

View file

@ -13,9 +13,7 @@ use leptos::{
leptos_dom::helpers::WindowListenerHandle, leptos_dom::helpers::WindowListenerHandle,
prelude::*, prelude::*,
}; };
use thaw_utils::{ use thaw_utils::{add_event_listener, get_scroll_parent, mount_style, EventListenerHandle};
add_event_listener, get_scroll_parent, mount_style, with_hydration_off, EventListenerHandle,
};
#[slot] #[slot]
pub struct Follower { pub struct Follower {
@ -193,19 +191,19 @@ where
remove_listener(); remove_listener();
}); });
let teleport_children = with_hydration_off(|| {
html::div().class("thaw-binder-follower-container").child(
html::div()
.class("thaw-binder-follower-content")
.attr("data-thaw-placement", move || placement_str.get())
.node_ref(content_ref)
.attr("style", move || content_style.get())
.child(follower_children()),
)
});
view! { view! {
{children()} {children()}
<Teleport element=teleport_children.into_any() immediate=follower_show/> <Teleport immediate=follower_show>
<div class="thaw-binder-follower-container">
<div
class="thaw-binder-follower-content"
data-thaw-placement=move || placement_str.get()
node_ref=content_ref
style=move || content_style.get()
>
{follower_children()}
</div>
</div>
</Teleport>
} }
} }

View file

@ -17,5 +17,5 @@ where
(fallback.children)().into_any() (fallback.children)().into_any()
} else { } else {
().into_any() ().into_any()
}; }
} }

View file

@ -1,74 +1,46 @@
use std::cell::Cell;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use leptos::{children, prelude::*}; use leptos::prelude::*;
use tachys::view::any_view::AnyView;
/// https://github.com/solidjs/solid/blob/main/packages/solid/web/src/index.ts#L56 /// https://github.com/solidjs/solid/blob/main/packages/solid/web/src/index.ts#L56
#[component] #[component]
pub fn Teleport( pub fn Teleport(
#[prop(default = true.into(), into)] immediate: MaybeSignal<bool>, #[prop(default = true.into(), into)] immediate: MaybeSignal<bool>,
#[prop(into, optional)] mount: Option<web_sys::Element>, #[prop(into, optional)] mount: Option<web_sys::Element>,
#[prop(optional, into)] element: Option<AnyView<Dom>>, children: Children,
#[prop(optional)] children: Option<Children>,
) -> impl IntoView { ) -> impl IntoView {
// cfg_if! { if #[cfg(all(target_arch = "wasm32", any(feature = "csr", feature = "hydrate")))] { // cfg_if! { if #[cfg(all(target_arch = "wasm32", any(feature = "csr", feature = "hydrate")))] {
let mount_fn = StoredValue::new(None::<Box<dyn FnOnce() + Send + Sync>>); let mount_fn: Cell<Option<Box<dyn FnOnce() -> ()>>> = Cell::new(Some(Box::new(move || {
let mount = send_wrapper::SendWrapper::new(mount); let mount = if let Some(el) = mount.as_ref() {
let element = send_wrapper::SendWrapper::new(element);
let children = send_wrapper::SendWrapper::new(children);
mount_fn.set_value(Some(Box::new(move || {
let mount = if let Some(el) = mount.take() {
el el
} else { } else {
use leptos::wasm_bindgen::JsCast; use leptos::wasm_bindgen::JsCast;
document() &document()
.body() .body()
.expect("body element to exist") .expect("body element to exist")
.unchecked_into() .unchecked_into()
}; };
if let Some(element) = element.take() { let mountable = {
let render_root = element; let view = children().into_view();
let mut mountable = render_root.build(); let mut mountable = view.build();
mountable.mount(&mount, None); mountable.mount(mount, None);
on_cleanup({ mountable
let mut mountable = send_wrapper::SendWrapper::new(mountable); };
move || {
mountable.unmount();
}
});
} else if let Some(children) = children.take() {
let container = document()
.create_element("div")
.expect("element creation to work");
let mountable = thaw_utils::with_hydration_off(|| { on_cleanup({
let view = children().into_view(); let mut mountable = send_wrapper::SendWrapper::new(mountable);
let mut mountable = view.build(); move || {
mountable.mount(&container, None); mountable.unmount();
mountable }
}); });
let render_root = container;
let _ = mount.append_child(&render_root);
on_cleanup({
let mount = send_wrapper::SendWrapper::new(mount);
let render_root = send_wrapper::SendWrapper::new(render_root);
let mut mountable = send_wrapper::SendWrapper::new(mountable);
move || {
mountable.unmount();
let _ = mount.remove_child(&render_root);
}
});
}
}))); })));
let owner = Owner::current().unwrap(); let owner = Owner::current().unwrap();
Effect::new(move |_| { Effect::new(move |_| {
if immediate.get() { if immediate.get() {
let Some(f) = mount_fn let Some(f) = mount_fn.take() else {
.try_update_value(|mount_fn| mount_fn.take())
.flatten()
else {
return; return;
}; };