1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//! Portal API.

use std::any::Any;

use wasm_bindgen::prelude::*;

use crate::prelude::*;

/// Props for [`Portal`].
pub struct PortalProps<G>
where
    G: GenericNode,
{
    pub children: View<G>,
    pub selector: &'static str,
}

/// A portal into another part of the DOM.
#[component(Portal<G>)]
pub fn portal(props: PortalProps<G>) -> View<G> {
    let PortalProps { children, selector } = props;

    if G::IS_BROWSER {
        let window = web_sys::window().unwrap_throw();
        let document = window.document().unwrap_throw();
        let container = document
            .query_selector(selector)
            .unwrap_throw()
            .expect_throw("could not find element matching selector");

        let children = children.flatten();

        for child in &children {
            container
                .append_child(
                    &<dyn Any>::downcast_ref::<DomNode>(child)
                        .unwrap_throw()
                        .inner_element(),
                )
                .unwrap_throw();
        }

        on_cleanup(move || {
            for child in &children {
                container
                    .remove_child(
                        &<dyn Any>::downcast_ref::<DomNode>(child)
                            .unwrap_throw()
                            .inner_element(),
                    )
                    .unwrap_throw();
            }
        });
    } else {
        // TODO: Support for other types of nodes.
    }

    view! {}
}