1use serde::Serialize;
25use serde_json::{Map, Value};
26
27use super::{
28 InputType, Node,
29 node::{
30 actions_methods, base_methods, children_methods, event_methods, kind_type, max_method, props,
31 title_method,
32 },
33};
34
35kind_type!(
36 El
39);
40
41impl<M> El<M> {
42 base_methods!();
43
44 title_method!();
45
46 max_method!();
47
48 actions_methods!();
49
50 event_methods!();
51
52 children_methods!();
53
54 props! {
55 tag(String) = "tag";
57 class(String) = "class";
59 text(String) = "text";
61 input_type(InputType) = "type";
63 name(String) = "name";
65 value(String) = "value";
67 checked(bool) = "checked";
69 disabled(bool) = "disabled";
71 }
72
73 pub fn attrs(mut self, attrs: Map<String, Value>) -> Self {
76 self.0.props.insert("attrs".into(), Value::Object(attrs));
77 self
78 }
79
80 pub fn attr(mut self, name: impl Into<String>, value: impl Serialize) -> Self {
82 let Ok(value) = serde_json::to_value(value) else {
83 return self;
84 };
85 if let Some(Value::Object(attrs)) = self.0.props.get_mut("attrs") {
86 attrs.insert(name.into(), value);
87 } else {
88 let mut attrs = Map::new();
89 attrs.insert(name.into(), value);
90 self.0.props.insert("attrs".into(), Value::Object(attrs));
91 }
92 self
93 }
94}
95
96pub fn el<M>(tag: impl Into<String>) -> El<M> {
98 El(Node::new("el")).tag(tag)
99}
100
101macro_rules! bare_tags {
103 ($($(#[$m:meta])* $f:ident = $tag:literal;)*) => {
104 $($(#[$m])* pub fn $f<M>() -> El<M> {
105 el($tag)
106 })*
107 };
108}
109
110macro_rules! text_tags {
112 ($($(#[$m:meta])* $f:ident = $tag:literal;)*) => {
113 $($(#[$m])* pub fn $f<M>(text: impl Into<String>) -> El<M> {
114 el($tag).text(text)
115 })*
116 };
117}
118
119bare_tags! {
120 div = "div";
122 section = "section";
124 header = "header";
126 footer = "footer";
128 nav = "nav";
130 aside = "aside";
132 main = "main";
134 article = "article";
136 figure = "figure";
138 blockquote = "blockquote";
140 ul = "ul";
142 ol = "ol";
144 dl = "dl";
146 hr = "hr";
148 table = "table";
150 thead = "thead";
152 tbody = "tbody";
154 tr = "tr";
156 label = "label";
158 form = "form";
160}
161
162text_tags! {
163 span = "span";
165 p = "p";
167 li = "li";
169 dt = "dt";
171 dd = "dd";
173 h1 = "h1";
175 h2 = "h2";
177 h3 = "h3";
179 h4 = "h4";
181 pre = "pre";
183 code = "code";
185 kbd = "kbd";
187 strong = "strong";
189 b = "b";
191 em = "em";
193 i = "i";
195 del = "del";
197 mark = "mark";
199 th = "th";
201 td = "td";
203 button = "button";
205}
206
207pub fn input<M>(kind: impl Into<InputType>) -> El<M> {
209 el("input").input_type(kind)
210}
211
212pub fn checkbox<M>(name: impl Into<String>, value: impl Into<String>) -> El<M> {
215 input(InputType::Checkbox).name(name).value(value)
216}
217
218pub fn radio<M>(name: impl Into<String>, value: impl Into<String>) -> El<M> {
220 input(InputType::Radio).name(name).value(value)
221}