1use super::{
2 add_event_listener, append_child, body, create_effect, create_element, create_text,
3 replace_child, set_attribute, Runtime,
4};
5use std::cell::RefCell;
6use std::ops::Deref;
7use std::rc::Rc;
8
9#[allow(non_snake_case)]
13#[derive(Debug, Clone)]
14pub struct DOM(web_sys::Element);
15
16impl DOM {
17 pub fn new(name: &str) -> Self {
21 let ele = create_element(name);
22 Self(ele)
23 }
24
25 pub fn attr(self, key: &str, value: &str) -> Self {
29 set_attribute(&self, key, value);
30 self
31 }
32
33 pub fn on<F>(self, name: &str, cb: F) -> Self
37 where
38 F: FnMut(web_sys::Event) + 'static,
39 {
40 add_event_listener(&self, name, cb);
41 self
42 }
43
44 pub fn child(self, child: &DOM) -> Self {
48 append_child(&self, child);
49 self
50 }
51
52 pub fn text(self, value: &str) -> Self {
56 let text = create_text(value);
57 append_child(&self, &text);
58
59 self
60 }
61
62 pub fn dyn_text<F>(self, ctx: &'static Runtime, cb: F) -> Self
66 where
67 F: 'static + Fn() -> String,
68 {
69 let text = create_text("not dyn.");
70 append_child(&self, &text);
71
72 create_effect(ctx, move || {
73 let output = cb();
74 text.set_data(&output);
75 });
76
77 self
78 }
79
80 pub fn dyn_child<F>(self, ctx: &'static Runtime, func: F) -> Self
84 where
85 F: 'static + Fn() -> DOM,
86 {
87 let child = DOM::new("span");
88 append_child(&self, &child);
89
90 let wrapper = Rc::new(RefCell::new(child));
91
92 create_effect(ctx, move || {
93 let output = func();
94
95 let mut child = wrapper.borrow_mut();
96 replace_child(&child, &output);
97 *child = output;
98 });
99
100 self
101 }
102
103 pub fn dyn_attr<F>(self, ctx: &'static Runtime, key: &str, func: F) -> Self
107 where
108 F: 'static + Fn() -> String,
109 {
110 let key = key.to_string();
111 let this_dom = self.clone();
112
113 create_effect(ctx, move || {
114 set_attribute(&this_dom, &key, &func());
115 });
116
117 self
118 }
119}
120
121impl Deref for DOM {
122 type Target = web_sys::Element;
123
124 fn deref(&self) -> &Self::Target {
125 &self.0
126 }
127}
128
129
130pub fn mount(cb: impl FnOnce(&'static Runtime) -> DOM) {
134 let ctx: &'static Runtime = Box::leak(Box::default());
135
136 let body = body();
137 let output = cb(ctx);
138 append_child(&body, &output);
139}