1use std::{collections::HashMap, fmt::Debug, sync::Arc};
2
3use crate::{DomRef, EventHandler};
4
5pub struct HtmlElement {
7    pub(crate) tag_name: &'static str,
8    pub(crate) attributes: HashMap<String, String>,
9    pub(crate) callbacks: HashMap<String, EventHandler>,
10    pub(crate) dom_ref: Option<Arc<DomRef>>,
11}
12
13impl Debug for HtmlElement {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        f.debug_struct("HtmlElement")
16            .field("tag_name", &self.tag_name)
17            .field("attributes", &self.attributes)
18            .field("callbacks", &"Callbacks")
19            .field("dom_ref", &self.dom_ref)
20            .finish()
21    }
22}
23
24impl HtmlElement {
25    pub fn new() -> HtmlElementBuilder<()> {
30        HtmlElementBuilder {
31            tag_name: (),
32            attributes: HashMap::new(),
33            callbacks: HashMap::new(),
34            dom_ref: None,
35        }
36    }
37
38    pub fn tag_name(&self) -> &str {
39        &self.tag_name
40    }
41
42    pub fn attributes(&self) -> &HashMap<String, String> {
46        &self.attributes
47    }
48
49    pub fn callbacks(&self) -> &HashMap<String, EventHandler> {
53        &self.callbacks
54    }
55
56    pub fn dom_ref(&self) -> &Option<Arc<DomRef>> {
58        &self.dom_ref
59    }
60}
61
62pub struct HtmlElementBuilder<T> {
63    pub(crate) tag_name: T,
64    pub(crate) attributes: HashMap<String, String>,
65    pub(crate) callbacks: HashMap<String, EventHandler>,
66    pub(crate) dom_ref: Option<Arc<DomRef>>,
67}
68
69impl HtmlElementBuilder<()> {
70    pub fn tag_name(self, tag_name: &'static str) -> HtmlElementBuilder<&'static str> {
71        HtmlElementBuilder {
72            tag_name,
73            attributes: self.attributes,
74            callbacks: self.callbacks,
75            dom_ref: self.dom_ref,
76        }
77    }
78}
79
80impl<T> HtmlElementBuilder<T> {
81    pub fn attr<K, V>(mut self, key: K, value: V) -> Self
87    where
88        K: Into<String>,
89        V: Into<String>,
90        V: Into<String>,
91    {
92        self.attributes.insert(key.into(), value.into());
93        self
94    }
95
96    pub fn on<K, C>(mut self, key: K, handler: C) -> Self
102    where
103        K: Into<String>,
104        C: Fn(web_sys::Event) + Send + Sync + 'static,
105    {
106        self.callbacks.insert(key.into(), Box::new(handler));
107        self
108    }
109
110    pub fn dom_ref(mut self, dom_ref: Arc<DomRef>) -> Self {
113        self.dom_ref = Some(dom_ref);
114        self
115    }
116}
117
118impl HtmlElementBuilder<&'static str> {
119    pub fn build(self) -> HtmlElement {
120        HtmlElement {
121            tag_name: self.tag_name,
122            attributes: self.attributes,
123            callbacks: self.callbacks,
124            dom_ref: self.dom_ref,
125        }
126    }
127}
128
129impl PartialEq for HtmlElement {
130    fn eq(&self, other: &Self) -> bool {
131        self.tag_name == other.tag_name
132            && self.attributes == other.attributes
133            && self.callbacks.is_empty()
134            && other.callbacks.is_empty()
135            && self.dom_ref == other.dom_ref
136    }
137}