feat: Portals in 0.7
This commit is contained in:
parent
802fcc5c2a
commit
274e31018b
|
@ -8,6 +8,7 @@ leptos = { path = "../../leptos", features = ["csr"] }
|
|||
log = "0.4"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use leptos::*;
|
||||
use leptos::control_flow::Show;
|
||||
use leptos::portal::Portal;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn App() -> impl IntoView {
|
||||
let (show_overlay, set_show_overlay) = create_signal(false);
|
||||
let (show_inside_overlay, set_show_inside_overlay) = create_signal(false);
|
||||
let (show_overlay, set_show_overlay) = signal(false);
|
||||
let (show_inside_overlay, set_show_inside_overlay) = signal(false);
|
||||
|
||||
view! {
|
||||
<div>
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
use leptos::*;
|
||||
use leptos::prelude::*;
|
||||
use portal::App;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
console_error_panic_hook::set_once();
|
||||
mount_to(
|
||||
leptos::document()
|
||||
let handle = mount_to(
|
||||
helpers::document()
|
||||
.get_element_by_id("app")
|
||||
.unwrap()
|
||||
.unchecked_into(),
|
||||
|| view! { <App/> },
|
||||
)
|
||||
App,
|
||||
);
|
||||
handle.forget();
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ wasm-bindgen = "0.2"
|
|||
serde_qs = "0.12.0"
|
||||
slotmap = "1.0.7"
|
||||
futures = "0.3.30"
|
||||
send_wrapper = "0.6.0"
|
||||
|
||||
[features]
|
||||
default = ["serde"]
|
||||
|
|
|
@ -205,6 +205,9 @@ pub mod control_flow {
|
|||
mod for_loop;
|
||||
mod show;
|
||||
|
||||
/// A component that allows rendering a component somewhere else.
|
||||
pub mod portal;
|
||||
|
||||
/// Components to enable server-side rendering and client-side hydration.
|
||||
pub mod hydration;
|
||||
|
||||
|
@ -247,10 +250,10 @@ pub mod context {
|
|||
}
|
||||
|
||||
pub use leptos_server as server;
|
||||
/// HTML element types.
|
||||
pub use tachys::html::element as html;
|
||||
/// HTML attribute types.
|
||||
pub use tachys::html::attribute as attr;
|
||||
/// HTML element types.
|
||||
pub use tachys::html::element as html;
|
||||
/// HTML event types.
|
||||
#[doc(no_inline)]
|
||||
pub use tachys::html::event as ev;
|
||||
|
|
|
@ -130,12 +130,16 @@ where
|
|||
///
|
||||
/// If you are using it to create the root of an application, you should use
|
||||
/// [`UnmountHandle::forget`] to leak it.
|
||||
#[must_use]
|
||||
#[must_use = "Dropping an `UnmountHandle` will unmount the view and cancel the \
|
||||
reactive system. You should either call `.forget()` to keep the \
|
||||
view permanently mounted, or store the `UnmountHandle` somewhere \
|
||||
and drop it when you'd like to unmount the view."]
|
||||
pub struct UnmountHandle<M, R>
|
||||
where
|
||||
M: Mountable<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
owner: Owner,
|
||||
mountable: M,
|
||||
rndr: PhantomData<R>,
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
use crate::ChildrenFn;
|
||||
use crate::{
|
||||
children::{ChildrenFn, TypedChildrenFn},
|
||||
mount, IntoView,
|
||||
};
|
||||
use cfg_if::cfg_if;
|
||||
use leptos_dom::IntoView;
|
||||
use leptos_dom::helpers::document;
|
||||
use leptos_macro::component;
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
any(feature = "hydrate", feature = "csr")
|
||||
))]
|
||||
use leptos_reactive::untrack;
|
||||
use reactive_graph::untrack;
|
||||
use reactive_graph::{effect::Effect, owner::Owner};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Renders components somewhere else in the DOM.
|
||||
///
|
||||
|
@ -19,7 +24,7 @@ use leptos_reactive::untrack;
|
|||
tracing::instrument(level = "trace", skip_all)
|
||||
)]
|
||||
#[component]
|
||||
pub fn Portal(
|
||||
pub fn Portal<V>(
|
||||
/// Target element where the children will be appended
|
||||
#[prop(into, optional)]
|
||||
mount: Option<web_sys::Element>,
|
||||
|
@ -30,18 +35,25 @@ pub fn Portal(
|
|||
#[prop(optional)]
|
||||
is_svg: bool,
|
||||
/// The children to teleport into the `mount` element
|
||||
children: ChildrenFn,
|
||||
) -> impl IntoView {
|
||||
cfg_if! { if #[cfg(all(target_arch = "wasm32", any(feature = "hydrate", feature = "csr")))] {
|
||||
use leptos_dom::{document, Mountable};
|
||||
use leptos_reactive::{create_effect, on_cleanup};
|
||||
children: TypedChildrenFn<V>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
V: IntoView + 'static,
|
||||
{
|
||||
if cfg!(target_arch = "wasm32")
|
||||
&& Owner::current_shared_context()
|
||||
.map(|sc| sc.is_browser())
|
||||
.unwrap_or(true)
|
||||
{
|
||||
use send_wrapper::SendWrapper;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
let mount = mount
|
||||
.unwrap_or_else(|| document().body().expect("body to exist").unchecked_into());
|
||||
let mount = mount.unwrap_or_else(|| {
|
||||
document().body().expect("body to exist").unchecked_into()
|
||||
});
|
||||
let children = children.into_inner();
|
||||
|
||||
create_effect(move |_| {
|
||||
leptos::logging::log!("inside Portal effect");
|
||||
Effect::new(move |_| {
|
||||
let tag = if is_svg { "g" } else { "div" };
|
||||
|
||||
let container = document()
|
||||
|
@ -59,23 +71,23 @@ pub fn Portal(
|
|||
container.clone()
|
||||
};
|
||||
|
||||
let children = untrack(|| children().into_view().get_mountable_node());
|
||||
let _ = render_root.append_child(&children);
|
||||
|
||||
let _ = mount.append_child(&container);
|
||||
let handle = SendWrapper::new((
|
||||
mount::mount_to(render_root.unchecked_into(), {
|
||||
let children = Arc::clone(&children);
|
||||
move || untrack(children())
|
||||
}),
|
||||
mount.clone(),
|
||||
container,
|
||||
));
|
||||
|
||||
on_cleanup({
|
||||
let mount = mount.clone();
|
||||
|
||||
Owner::on_cleanup({
|
||||
move || {
|
||||
let (handle, mount, container) = handle.take();
|
||||
drop(handle);
|
||||
let _ = mount.remove_child(&container);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
let _ = mount;
|
||||
let _ = use_shadow;
|
||||
let _ = is_svg;
|
||||
let _ = children;
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue