diff --git a/Cargo.lock b/Cargo.lock
index f3793382..7fda8c7b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3158,6 +3158,19 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "radix-leptos-portal"
+version = "0.0.2"
+dependencies = [
+ "cfg-if",
+ "leptos",
+ "leptos-node-ref",
+ "leptos_dom",
+ "radix-leptos-primitive",
+ "send_wrapper",
+ "web-sys",
+]
+
[[package]]
name = "radix-leptos-primitive"
version = "0.0.2"
@@ -3183,12 +3196,14 @@ dependencies = [
"console_error_panic_hook",
"console_log",
"leptos",
+ "leptos-node-ref",
"leptos_router",
"log",
"radix-leptos-accessible-icon",
"radix-leptos-arrow",
"radix-leptos-aspect-ratio",
"radix-leptos-label",
+ "radix-leptos-portal",
"radix-leptos-separator",
"radix-leptos-visually-hidden",
"tailwind_fuse",
diff --git a/Cargo.toml b/Cargo.toml
index eec5b2be..9bff9b3b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ members = [
"packages/primitives/leptos/focus-guards",
"packages/primitives/leptos/id",
"packages/primitives/leptos/label",
+ "packages/primitives/leptos/portal",
"packages/primitives/leptos/primitive",
"packages/primitives/leptos/separator",
"packages/primitives/leptos/use-controllable-state",
@@ -68,6 +69,7 @@ radix-leptos-icons = { path = "./packages/icons/leptos", version = "0.0.2" }
radix-leptos-id = { path = "./packages/primitives/leptos/id", version = "0.0.2" }
radix-leptos-label = { path = "./packages/primitives/leptos/label", version = "0.0.2" }
# radix-leptos-popper = { path = "./packages/primitives/leptos/popper", version = "0.0.2" }
+radix-leptos-portal = { path = "./packages/primitives/leptos/portal", version = "0.0.2" }
# radix-leptos-presence = { path = "./packages/primitives/leptos/presence", version = "0.0.2" }
radix-leptos-primitive = { path = "./packages/primitives/leptos/primitive", version = "0.0.2" }
# radix-leptos-roving-focus = { path = "./packages/primitives/leptos/roving-focus", version = "0.0.2" }
diff --git a/book/src/primitives/utilities/portal.md b/book/src/primitives/utilities/portal.md
index a704db70..08e74e2b 100644
--- a/book/src/primitives/utilities/portal.md
+++ b/book/src/primitives/utilities/portal.md
@@ -15,14 +15,7 @@ Install the component from your command line.
{{#tab name="Leptos" }}
```shell
-# CSR
-cargo add radix-leptos-portal --features csr
-
-# Hydrate
-cargo add radix-leptos-portal --features hydrate
-
-# SSR
-cargo add radix-leptos-portal --features ssr
+cargo add radix-leptos-portal
```
- [View on crates.io](https://crates.io/crates/radix-leptos-portal)
@@ -89,11 +82,11 @@ Anything you put inside this component will be rendered in a separate `
` el
{{#tabs global="framework" }}
{{#tab name="Leptos" }}
-| Prop | Type | Default |
-| --------------- | ----------------------------- | ------- |
-| `as_child` | `MaybeProp
` | `false` |
-| `container` | `MaybeProp` | - |
-| `container_ref` | `NodeRef` | - |
+| Prop | Type | Default |
+| --------------- | ------------------------------------------ | ------- |
+| `as_child` | `MaybeProp` | `false` |
+| `container` | `MaybeProp>` | - |
+| `container_ref` | `NodeRef` | - |
{{#endtab }}
{{#tab name="Yew" }}
diff --git a/packages/primitives/leptos/portal/Cargo.toml b/packages/primitives/leptos/portal/Cargo.toml
index 50274b38..53b43fef 100644
--- a/packages/primitives/leptos/portal/Cargo.toml
+++ b/packages/primitives/leptos/portal/Cargo.toml
@@ -13,13 +13,15 @@ version.workspace = true
cfg-if = "1.0.0"
leptos.workspace = true
leptos_dom.workspace = true
-tracing = "0.1"
+leptos-node-ref.workspace = true
+radix-leptos-primitive.workspace = true
+send_wrapper.workspace = true
web-sys.workspace = true
-[features]
-csr = ["leptos_dom/csr"]
-hydrate = ["leptos_dom/hydrate"]
-ssr = ["leptos_dom/ssr"]
+# [features]
+# csr = ["leptos_dom/csr"]
+# hydrate = ["leptos_dom/hydrate"]
+# ssr = ["leptos_dom/ssr"]
-[package.metadata.cargo-all-features]
-skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
+# [package.metadata.cargo-all-features]
+# skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
diff --git a/packages/primitives/leptos/portal/src/portal.rs b/packages/primitives/leptos/portal/src/portal.rs
index 05c1dc41..c15962ce 100644
--- a/packages/primitives/leptos/portal/src/portal.rs
+++ b/packages/primitives/leptos/portal/src/portal.rs
@@ -1,122 +1,109 @@
-use leptos::{html::AnyElement, *};
+use leptos::{html, prelude::*};
+use leptos_node_ref::AnyNodeRef;
use leptos_portal::LeptosPortal;
+use radix_leptos_primitive::Primitive;
+use send_wrapper::SendWrapper;
#[component]
pub fn Portal(
- #[prop(into, optional)] container: MaybeProp,
- #[prop(optional)] container_ref: NodeRef,
+ #[prop(into, optional)] container: MaybeProp>,
+ #[prop(optional)] container_ref: AnyNodeRef,
#[prop(into, optional)] as_child: MaybeProp,
- #[prop(optional)] node_ref: NodeRef,
- #[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
+ #[prop(optional)] node_ref: AnyNodeRef,
children: ChildrenFn,
) -> impl IntoView {
- let attrs = StoredValue::new(attrs);
let children = StoredValue::new(children);
+ // TODO: pass attrs to primitive
view! {
-
-
- {children.with_value(|children| children())}
-
-
+ //
+
+
+ {children.with_value(|children| children())}
+
+
+ //
}
}
/// Based on [`leptos::Portal`].
mod leptos_portal {
- use cfg_if::cfg_if;
- use leptos::{component, html::AnyElement, ChildrenFn, MaybeProp, NodeRef};
- use leptos_dom::IntoView;
+ use std::sync::Arc;
+
+ use leptos::prelude::{
+ Effect, Get, IntoView, MaybeProp, Owner, RwSignal, Set, Signal, TypedChildrenFn, component,
+ mount_to, untrack,
+ };
+ use leptos_dom::helpers::document;
+ use leptos_node_ref::AnyNodeRef;
+ use send_wrapper::SendWrapper;
/// Renders components somewhere else in the DOM.
///
/// Useful for inserting modals and tooltips outside of a cropping layout.
- /// If no mount point is given, the portal is inserted in `document.body`;
- #[cfg_attr(
- any(debug_assertions, feature = "ssr"),
- tracing::instrument(level = "trace", skip_all)
- )]
+ /// If no mount point is given, the portal is inserted in `document.body`.
#[component]
- pub fn LeptosPortal(
+ pub fn LeptosPortal(
/// Target element where the children will be appended
#[prop(into, optional)]
- mount: MaybeProp,
- #[prop(optional)] mount_ref: NodeRef,
+ mount: MaybeProp>,
+ #[prop(optional)] mount_ref: AnyNodeRef,
/// 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::{on_cleanup, Effect, RwSignal, Signal, SignalGet, SignalSet, StoredValue};
- use leptos_dom::{document, Mountable};
+ children: TypedChildrenFn,
+ ) -> impl IntoView
+ where
+ V: IntoView + 'static,
+ {
+ if cfg!(target_arch = "wasm32")
+ && Owner::current_shared_context()
+ .map(|sc| sc.is_browser())
+ .unwrap_or(true)
+ {
use web_sys::wasm_bindgen::JsCast;
- let children = StoredValue::new(children);
-
let mount = Signal::derive(move || {
mount_ref
.get()
- .map(|mount| {
- let element: &web_sys::HtmlElement = &mount;
- element.clone().unchecked_into::()
- })
+ .map(|mount| SendWrapper::new(mount.unchecked_into::()))
.or_else(|| mount.get())
- .unwrap_or_else(|| document().body().expect("body to exist").into())
+ .unwrap_or_else(|| {
+ SendWrapper::new(document().body().expect("body to exist").into())
+ })
});
+ let children = children.into_inner();
- let current_mount: RwSignal