kozan_core/html/
html_input_element.rs1use super::form_control::{FormControlElement, TextControlElement};
25use crate::Handle;
26use kozan_macros::{Element, Props};
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
33pub enum InputType {
34 #[default]
36 Text,
37 Password,
39 Number,
41 Email,
43 Url,
45 Tel,
47 Search,
49 Range,
51 Color,
53 Date,
55 Time,
57 DatetimeLocal,
59 Checkbox,
61 Radio,
63 File,
65 Submit,
67 Reset,
69 Button,
71 Hidden,
73 Image,
75}
76
77impl InputType {
78 #[must_use]
82 pub fn parse(s: &str) -> Self {
83 match s.to_ascii_lowercase().as_str() {
84 "text" => Self::Text,
85 "password" => Self::Password,
86 "number" => Self::Number,
87 "email" => Self::Email,
88 "url" => Self::Url,
89 "tel" => Self::Tel,
90 "search" => Self::Search,
91 "range" => Self::Range,
92 "color" => Self::Color,
93 "date" => Self::Date,
94 "time" => Self::Time,
95 "datetime-local" => Self::DatetimeLocal,
96 "checkbox" => Self::Checkbox,
97 "radio" => Self::Radio,
98 "file" => Self::File,
99 "submit" => Self::Submit,
100 "reset" => Self::Reset,
101 "button" => Self::Button,
102 "hidden" => Self::Hidden,
103 "image" => Self::Image,
104 _ => Self::Text, }
106 }
107
108 #[must_use]
110 pub fn is_text_type(&self) -> bool {
111 matches!(
112 self,
113 Self::Text
114 | Self::Password
115 | Self::Number
116 | Self::Email
117 | Self::Url
118 | Self::Tel
119 | Self::Search
120 )
121 }
122
123 #[must_use]
125 pub fn is_checkable(&self) -> bool {
126 matches!(self, Self::Checkbox | Self::Radio)
127 }
128
129 #[must_use]
131 pub fn is_button_type(&self) -> bool {
132 matches!(
133 self,
134 Self::Submit | Self::Reset | Self::Button | Self::Image
135 )
136 }
137
138 #[must_use]
140 pub fn is_focusable(&self) -> bool {
141 !matches!(self, Self::Hidden)
142 }
143}
144
145#[derive(Copy, Clone, Element)]
150#[element(tag = "input", focusable, data = InputData)]
151pub struct HtmlInputElement(Handle);
152
153#[derive(Default, Clone, Props)]
155#[props(element = HtmlInputElement)]
156pub struct InputData {
157 #[prop]
159 pub input_type: InputType,
160 #[prop]
162 pub checked: bool,
163}
164
165impl FormControlElement for HtmlInputElement {}
166impl TextControlElement for HtmlInputElement {}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn input_type_parse() {
174 assert_eq!(InputType::parse("text"), InputType::Text);
175 assert_eq!(InputType::parse("PASSWORD"), InputType::Password);
176 assert_eq!(InputType::parse("number"), InputType::Number);
177 assert_eq!(InputType::parse("checkbox"), InputType::Checkbox);
178 assert_eq!(InputType::parse("unknown"), InputType::Text); }
180
181 #[test]
182 fn text_type_classification() {
183 assert!(InputType::Text.is_text_type());
184 assert!(InputType::Password.is_text_type());
185 assert!(!InputType::Checkbox.is_text_type());
186 assert!(!InputType::File.is_text_type());
187 }
188
189 #[test]
190 fn checkable_classification() {
191 assert!(InputType::Checkbox.is_checkable());
192 assert!(InputType::Radio.is_checkable());
193 assert!(!InputType::Text.is_checkable());
194 }
195
196 #[test]
197 fn button_type_classification() {
198 assert!(InputType::Submit.is_button_type());
199 assert!(InputType::Reset.is_button_type());
200 assert!(InputType::Button.is_button_type());
201 assert!(InputType::Image.is_button_type());
202 assert!(!InputType::Text.is_button_type());
203 assert!(!InputType::Checkbox.is_button_type());
204 }
205
206 #[test]
207 fn focusable_classification() {
208 assert!(InputType::Text.is_focusable());
210 assert!(InputType::Password.is_focusable());
211 assert!(InputType::Checkbox.is_focusable());
212 assert!(InputType::Submit.is_focusable());
213 assert!(!InputType::Hidden.is_focusable());
214 }
215
216 #[test]
217 fn input_type_default() {
218 assert_eq!(InputType::default(), InputType::Text);
219 }
220
221 #[test]
222 fn input_data_props() {
223 use crate::dom::document::Document;
224
225 let doc = Document::new();
226 let input = doc.create::<HtmlInputElement>();
227
228 assert_eq!(input.input_type(), InputType::Text);
230 assert!(!input.checked());
231
232 input.set_input_type(InputType::Checkbox);
234 assert_eq!(input.input_type(), InputType::Checkbox);
235
236 input.set_checked(true);
238 assert!(input.checked());
239 }
240
241 #[test]
242 fn input_text_control() {
243 use crate::dom::document::Document;
244
245 let doc = Document::new();
246 let input = doc.create::<HtmlInputElement>();
247
248 input.set_value("hello");
250 assert_eq!(input.value(), "hello");
251
252 input.set_placeholder("Enter text...");
253 assert_eq!(input.placeholder(), "Enter text...");
254 }
255
256 #[test]
257 fn input_form_control() {
258 use crate::dom::document::Document;
259
260 let doc = Document::new();
261 let input = doc.create::<HtmlInputElement>();
262
263 assert!(!input.disabled());
265 input.set_disabled(true);
266 assert!(input.disabled());
267
268 input.set_name("username");
269 assert_eq!(input.name(), "username");
270 }
271}