forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
106 lines (94 loc) · 2.91 KB
/
main.rs
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use wasm_bindgen::JsCast;
use web_sys::{Element, ShadowRootInit, ShadowRootMode};
use yew::{create_portal, html, Children, Component, Context, Html, NodeRef, Properties};
#[derive(Properties, PartialEq)]
pub struct ShadowDOMProps {
#[prop_or_default]
pub children: Children,
}
pub struct ShadowDOMHost {
host_ref: NodeRef,
inner_host: Option<Element>,
}
impl Component for ShadowDOMHost {
type Message = ();
type Properties = ShadowDOMProps;
fn create(_: &Context<Self>) -> Self {
Self {
host_ref: NodeRef::default(),
inner_host: None,
}
}
fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
if first_render {
let shadow_root = self
.host_ref
.get()
.expect("rendered host")
.unchecked_into::<Element>()
.attach_shadow(&ShadowRootInit::new(ShadowRootMode::Closed))
.expect("installing shadow root succeeds");
let inner_host = gloo_utils::document()
.create_element("div")
.expect("can create inner wrapper");
shadow_root
.append_child(&inner_host)
.expect("can attach inner host");
self.inner_host = Some(inner_host);
ctx.link().send_message(());
}
}
fn update(&mut self, _: &Context<Self>, _: Self::Message) -> bool {
true
}
fn view(&self, ctx: &Context<Self>) -> Html {
let contents = if let Some(ref inner_host) = self.inner_host {
create_portal(
html! {
{for ctx.props().children.iter()}
},
inner_host.clone(),
)
} else {
html! { <></> }
};
html! {
<div ref={self.host_ref.clone()}>
{contents}
</div>
}
}
}
pub struct App {
pub style_html: Html,
}
impl Component for App {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
let document_head = gloo_utils::document()
.head()
.expect("head element to be present");
let style_html = create_portal(
html! {
<style>{"p { color: red; }"}</style>
},
document_head.into(),
);
Self { style_html }
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<>
{self.style_html.clone()}
<p>{"This paragraph is colored red, and its style is mounted into "}<pre>{"document.head"}</pre>{" with a portal"}</p>
<ShadowDOMHost>
<p>{"This paragraph is rendered in a shadow dom and thus not affected by the surrounding styling context"}</p>
</ShadowDOMHost>
</>
}
}
}
fn main() {
yew::Renderer::<App>::new().render();
}