1use sycamore_macro::component;
2
3use crate::*;
4
5#[component(inline_props)]
8pub fn Portal<'a, T: Into<View> + Default>(selector: &'a str, children: T) -> View {
9 if is_not_ssr!() {
10 let Some(parent) = document().query_selector(selector).unwrap() else {
11 panic!("element matching selector `{selector}` not found");
12 };
13
14 let start = HtmlNode::create_marker_node();
15 let start_node = start.as_web_sys().clone();
16 let end = HtmlNode::create_marker_node();
17 let end_node = end.as_web_sys().clone();
18 let children: View = (start, children.into(), end).into();
19
20 let nodes = children.as_web_sys();
21 for node in &nodes {
22 parent.append_child(node).unwrap();
23 }
24
25 on_cleanup(move || {
26 let nodes = utils::get_nodes_between(&start_node, &end_node);
27 for node in nodes {
28 parent.remove_child(&node).unwrap();
29 }
30 parent.remove_child(&start_node).unwrap();
31 parent.remove_child(&end_node).unwrap();
32 });
33 }
34 View::default()
35}