wal_core/virtual_dom/
vnode.rs1use web_sys::Node;
2
3use super::{VComponent, VElement, VList, VText};
4
5#[derive(PartialEq, Debug)]
8pub enum VNode {
9 Element(VElement),
11 Text(VText),
13 List(VList),
15 Component(VComponent),
17}
18
19impl VNode {
20 pub(crate) fn patch(&mut self, last: Option<VNode>, ancestor: &Node) {
21 match self {
22 VNode::Element(velement) => velement.patch(last, ancestor),
23 VNode::Text(vtext) => vtext.patch(last, ancestor),
24 VNode::Component(vcomp) => vcomp.patch(last, ancestor),
25 VNode::List(vlist) => vlist.patch(last, ancestor),
26 };
27 }
28
29 pub(crate) fn erase(&self) {
30 match self {
31 VNode::Element(v) => v.erase(),
32 VNode::Text(v) => v.erase(),
33 VNode::List(v) => v.erase(),
34 VNode::Component(v) => v.erase(),
35 }
36 }
37
38 pub(crate) fn set_depth(&mut self, depth: u32) {
39 match self {
40 VNode::Component(vcomp) => vcomp.set_depth(depth),
41 VNode::List(vlist) => vlist.set_depth(depth),
42 VNode::Element(velem) => velem.set_depth(depth),
43 VNode::Text(_) => {}
44 }
45 }
46}
47
48impl From<VElement> for VNode {
49 fn from(velement: VElement) -> Self {
50 Self::Element(velement)
51 }
52}
53
54impl From<VComponent> for VNode {
55 fn from(vcomp: VComponent) -> Self {
56 Self::Component(vcomp)
57 }
58}
59
60impl From<VText> for VNode {
61 fn from(vtext: VText) -> Self {
62 Self::Text(vtext)
63 }
64}
65
66impl From<VList> for VNode {
67 fn from(vlist: VList) -> Self {
68 Self::List(vlist)
69 }
70}
71
72impl<T: ToString> From<T> for VNode {
73 fn from(t: T) -> Self {
74 Self::Text(VText::new(t))
75 }
76}
77
78impl<T: Into<VNode>> FromIterator<T> for VNode {
79 fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
80 Self::List(VList::new(iter.into_iter().map(Into::into).collect(), None))
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use crate::{
87 component::{behavior::Behavior, Component},
88 virtual_dom::{VComponent, VElement, VList, VText},
89 };
90 use wasm_bindgen_test::wasm_bindgen_test;
91
92 use super::VNode;
93 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
94
95 #[wasm_bindgen_test]
96 fn from_to_string() {
97 let target = String::from("tmp");
98 assert_eq!(
99 VNode::Text(VText {
100 text: "tmp".to_string(),
101 dom: None
102 }),
103 target.into()
104 );
105 }
106
107 #[wasm_bindgen_test]
108 fn from_vec_string() {
109 let target = vec![String::from("tmp")];
110 assert_eq!(
111 VNode::List(VList::new(vec![VText::new("tmp").into()], None)),
112 VNode::from_iter(target)
113 );
114 }
115
116 #[wasm_bindgen_test]
117 fn from_vec_elements() {
118 let target = vec![VElement::new(
119 "div".to_string(),
120 [].into(),
121 [].into(),
122 None,
123 [].into(),
124 )];
125 assert_eq!(
126 VNode::List(VList::new(
127 vec![VNode::Element(VElement::new(
128 "div".to_string(),
129 [].into(),
130 [].into(),
131 None,
132 [].into()
133 ))],
134 None
135 )),
136 VNode::from_iter(target)
137 );
138 }
139
140 #[wasm_bindgen_test]
141 fn from_vec_lists() {
142 let target = vec![VList::new(vec![], None)];
143 assert_eq!(
144 VNode::List(VList::new(
145 vec![VNode::List(VList::new(vec![], None,))],
146 None
147 )),
148 VNode::from_iter(target)
149 );
150 }
151
152 struct Comp;
153 impl Component for Comp {
154 type Message = ();
155 type Properties = ();
156
157 fn new(_props: Self::Properties) -> Self {
158 Comp
159 }
160 fn view(&self, _behavior: &mut impl Behavior<Self>) -> VNode {
161 VText::new("Test").into()
162 }
163 fn update(&mut self, _message: Self::Message) -> bool {
164 false
165 }
166 }
167
168 #[wasm_bindgen_test]
169 fn from_vec_comp() {
170 let target = vec![VComponent::new::<Comp>((), None)];
171 assert_eq!(
172 VNode::List(VList::new(
173 vec![VNode::Component(VComponent::new::<Comp>((), None))],
174 None
175 )),
176 VNode::from_iter(target)
177 );
178 }
179}