1mod auto_complete;
2
3use std::borrow::Cow;
4use std::fmt;
5
6pub use auto_complete::AutoComplete;
7use cabin_macros::Attribute;
8
9use super::button::{
10 Disabled, Form, FormAction, FormEnctype, FormMethod, FormNoValidate, FormTarget, Name,
11 PopoverTarget, PopoverTargetAction,
12};
13use super::common::Common;
14use super::global::Global;
15use super::img::Alt;
16use super::script::Src;
17use super::SerializeEventFn;
18use crate::error::InternalError;
19use crate::html::attributes::{Attributes, WithAttribute};
20use crate::html::events::InputEvent;
21use crate::html::{Aria, Html};
22
23pub fn input() -> Html<marker::Input, (), ()> {
24 Html::new("input", (), ())
25}
26
27pub mod marker {
28 pub struct Input;
29}
30
31impl<A: Attributes, V: 'static> Input for Html<marker::Input, A, V> {}
32impl<A: Attributes, V: 'static> Common for Html<marker::Input, A, V> {}
33impl<A: Attributes, V: 'static> Global for Html<marker::Input, A, V> {}
34impl<A: Attributes, V: 'static> Aria for Html<marker::Input, A, V> {}
35
36pub trait Input: WithAttribute {
39 fn accept(self, accept: impl Into<Cow<'static, str>>) -> Self::Output<Accept> {
41 self.with_attribute(Accept(accept.into()))
42 }
43
44 fn alt(self, alt: impl Into<Cow<'static, str>>) -> Self::Output<Alt> {
46 self.with_attribute(Alt(alt.into()))
47 }
48
49 fn autocomplete(self, autocomplete: AutoComplete) -> Self::Output<AutoComplete> {
51 self.with_attribute(autocomplete)
52 }
53
54 fn checked(self) -> Self::Output<Checked> {
56 self.with_checked(true)
57 }
58
59 fn with_checked(self, checked: bool) -> Self::Output<Checked> {
61 self.with_attribute(Checked(checked))
62 }
63
64 fn dirname(self, dirname: impl Into<Cow<'static, str>>) -> Self::Output<Dirname> {
66 self.with_attribute(Dirname(dirname.into()))
67 }
68
69 fn disabled(self) -> Self::Output<Disabled> {
71 self.with_disabled(true)
72 }
73
74 fn with_disabled(self, disabled: bool) -> Self::Output<Disabled> {
76 self.with_attribute(Disabled(disabled))
77 }
78
79 fn form(self, form: impl Into<Cow<'static, str>>) -> Self::Output<Form> {
81 self.with_attribute(Form(form.into()))
82 }
83
84 fn form_action(self, form_action: impl Into<Cow<'static, str>>) -> Self::Output<FormAction> {
86 self.with_attribute(FormAction(form_action.into()))
87 }
88
89 fn form_enctype(self, form_enctype: impl Into<Cow<'static, str>>) -> Self::Output<FormEnctype> {
91 self.with_attribute(FormEnctype(form_enctype.into()))
92 }
93
94 fn form_method(self, form_method: FormMethod) -> Self::Output<FormMethod> {
96 self.with_attribute(form_method)
97 }
98
99 fn form_novalidate(self) -> Self::Output<FormNoValidate> {
101 self.with_form_novalidate(true)
102 }
103
104 fn with_form_novalidate(self, form_novalidate: bool) -> Self::Output<FormNoValidate> {
106 self.with_attribute(FormNoValidate(form_novalidate))
107 }
108
109 fn form_target(self, form_target: impl Into<Cow<'static, str>>) -> Self::Output<FormTarget> {
111 self.with_attribute(FormTarget(form_target.into()))
112 }
113
114 fn height(self, height: u32) -> Self::Output<Height> {
116 self.with_attribute(Height(height))
117 }
118
119 fn list(self, list: impl Into<Cow<'static, str>>) -> Self::Output<List> {
121 self.with_attribute(List(list.into()))
122 }
123
124 fn max(self, max: impl Into<Cow<'static, str>>) -> Self::Output<Max> {
126 self.with_attribute(Max(max.into()))
127 }
128
129 fn max_length(self, max_length: i32) -> Self::Output<MaxLength> {
131 self.with_attribute(MaxLength(max_length))
132 }
133
134 fn min(self, min: impl Into<Cow<'static, str>>) -> Self::Output<Min> {
136 self.with_attribute(Min(min.into()))
137 }
138
139 fn min_length(self, min_length: i32) -> Self::Output<MinLength> {
141 self.with_attribute(MinLength(min_length))
142 }
143
144 fn multiple(self) -> Self::Output<Multiple> {
146 self.with_multiple(true)
147 }
148
149 fn with_multiple(self, multiple: bool) -> Self::Output<Multiple> {
151 self.with_attribute(Multiple(multiple))
152 }
153
154 fn name(self, name: impl Into<Cow<'static, str>>) -> Self::Output<Name> {
156 self.with_attribute(Name(name.into()))
157 }
158
159 fn pattern(self, pattern: impl Into<Cow<'static, str>>) -> Self::Output<Pattern> {
161 self.with_attribute(Pattern(pattern.into()))
162 }
163
164 fn placeholder(self, placeholder: impl Into<Cow<'static, str>>) -> Self::Output<Placeholder> {
166 self.with_attribute(Placeholder(placeholder.into()))
167 }
168
169 fn popover_target(
171 self,
172 popover_target: impl Into<Cow<'static, str>>,
173 ) -> Self::Output<PopoverTarget> {
174 self.with_attribute(PopoverTarget(popover_target.into()))
175 }
176
177 fn popover_target_action(
179 self,
180 popover_target_action: PopoverTargetAction,
181 ) -> Self::Output<PopoverTargetAction> {
182 self.with_attribute(popover_target_action)
183 }
184
185 fn read_only(self) -> Self::Output<ReadOnly> {
187 self.with_read_only(true)
188 }
189
190 fn with_read_only(self, read_only: bool) -> Self::Output<ReadOnly> {
192 self.with_attribute(ReadOnly(read_only))
193 }
194
195 fn required(self) -> Self::Output<Required> {
197 self.with_required(true)
198 }
199
200 fn with_required(self, required: bool) -> Self::Output<Required> {
202 self.with_attribute(Required(required))
203 }
204
205 fn size(self, size: u32) -> Self::Output<Size> {
207 self.with_attribute(Size(size))
208 }
209
210 fn src(self, src: impl Into<Cow<'static, str>>) -> Self::Output<Src> {
212 self.with_attribute(Src(src.into()))
213 }
214
215 fn step(self, step: impl Into<Cow<'static, str>>) -> Self::Output<Step> {
217 self.with_attribute(Step(step.into()))
218 }
219
220 fn r#type(self, r#type: Type) -> Self::Output<Type> {
222 self.with_attribute(r#type)
223 }
224
225 fn type_hidden(self) -> Self::Output<Type> {
226 self.r#type(Type::Hidden)
227 }
228
229 fn type_text(self) -> Self::Output<Type> {
230 self.r#type(Type::Text)
231 }
232
233 fn type_search(self) -> Self::Output<Type> {
234 self.r#type(Type::Search)
235 }
236
237 fn type_tel(self) -> Self::Output<Type> {
238 self.r#type(Type::Tel)
239 }
240
241 fn type_url(self) -> Self::Output<Type> {
242 self.r#type(Type::Url)
243 }
244
245 fn type_email(self) -> Self::Output<Type> {
246 self.r#type(Type::Email)
247 }
248
249 fn type_password(self) -> Self::Output<Type> {
250 self.r#type(Type::Password)
251 }
252
253 fn type_date(self) -> Self::Output<Type> {
254 self.r#type(Type::Date)
255 }
256
257 fn type_month(self) -> Self::Output<Type> {
258 self.r#type(Type::Month)
259 }
260
261 fn type_week(self) -> Self::Output<Type> {
262 self.r#type(Type::Week)
263 }
264
265 fn type_time(self) -> Self::Output<Type> {
266 self.r#type(Type::Time)
267 }
268
269 fn type_date_time_local(self) -> Self::Output<Type> {
270 self.r#type(Type::DateTimeLocal)
271 }
272
273 fn type_number(self) -> Self::Output<Type> {
274 self.r#type(Type::Number)
275 }
276
277 fn type_range(self) -> Self::Output<Type> {
278 self.r#type(Type::Range)
279 }
280
281 fn type_color(self) -> Self::Output<Type> {
282 self.r#type(Type::Color)
283 }
284
285 fn type_checkbox(self) -> Self::Output<Type> {
286 self.r#type(Type::Checkbox)
287 }
288
289 fn type_radio(self) -> Self::Output<Type> {
290 self.r#type(Type::Radio)
291 }
292
293 fn type_file(self) -> Self::Output<Type> {
294 self.r#type(Type::File)
295 }
296
297 fn type_submit(self) -> Self::Output<Type> {
298 self.r#type(Type::Submit)
299 }
300
301 fn type_image(self) -> Self::Output<Type> {
302 self.r#type(Type::Image)
303 }
304
305 fn type_reset(self) -> Self::Output<Type> {
306 self.r#type(Type::Reset)
307 }
308
309 fn type_button(self) -> Self::Output<Type> {
310 self.r#type(Type::Button)
311 }
312
313 fn value(self, value: impl Into<Cow<'static, str>>) -> Self::Output<Value> {
315 self.with_attribute(Value(value.into()))
316 }
317
318 fn width(self, width: u32) -> Self::Output<Width> {
320 self.with_attribute(Width(width))
321 }
322
323 fn on_input<E>(self, event: impl FnOnce(InputEvent) -> E) -> Self::Output<OnInput>
324 where
325 E: ::serde::Serialize + 'static,
326 {
327 let event = event(InputEvent::default());
328 self.with_attribute(OnInput(Box::new(move || {
329 use std::hash::{Hash, Hasher};
330
331 let mut hasher = twox_hash::XxHash32::default();
332 std::any::TypeId::of::<E>().hash(&mut hasher);
333 let hash = hasher.finish() as u32;
334 serde_json::to_string(&event)
335 .map_err(|err| InternalError::Serialize {
336 what: "on_input event",
337 err,
338 })
339 .map(|json| (hash, json))
340 })))
341 }
342
343 fn on_change<E>(self, event: impl FnOnce(InputEvent) -> E) -> Self::Output<OnChange>
344 where
345 E: ::serde::Serialize + 'static,
346 {
347 let event = event(InputEvent::default());
348 self.with_attribute(OnChange(Box::new(move || {
349 use std::hash::{Hash, Hasher};
350
351 let mut hasher = twox_hash::XxHash32::default();
352 std::any::TypeId::of::<E>().hash(&mut hasher);
353 let hash = hasher.finish() as u32;
354 serde_json::to_string(&event)
355 .map_err(|err| InternalError::Serialize {
356 what: "on_change event",
357 err,
358 })
359 .map(|json| (hash, json))
360 })))
361 }
362}
363
364#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
366pub struct Accept(pub Cow<'static, str>);
367
368#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
370pub struct Checked(pub bool);
371
372#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
374pub struct Dirname(pub Cow<'static, str>);
375
376#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
378pub struct Height(pub u32);
379
380#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
382pub struct List(pub Cow<'static, str>);
383
384#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
386pub struct Max(pub Cow<'static, str>);
387
388#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
390pub struct MaxLength(pub i32);
391
392#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
394pub struct Min(pub Cow<'static, str>);
395
396#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
398pub struct MinLength(pub i32);
399
400#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
402pub struct Multiple(pub bool);
403
404#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
406pub struct Pattern(pub Cow<'static, str>);
407
408#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
410pub struct Placeholder(pub Cow<'static, str>);
411
412#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
414pub struct ReadOnly(pub bool);
415
416#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
418pub struct Required(pub bool);
419
420#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
422pub struct Size(pub u32);
423
424#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
426pub struct Step(pub Cow<'static, str>);
427
428#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
430pub struct Value(pub Cow<'static, str>);
431
432#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
434pub struct Width(pub u32);
435
436#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
438pub enum Type {
439 Hidden,
440 Text,
441 Search,
442 Tel,
443 Url,
444 Email,
445 Password,
446 Date,
447 Month,
448 Week,
449 Time,
450 DateTimeLocal,
451 Number,
452 Range,
453 Color,
454 Checkbox,
455 Radio,
456 File,
457 Submit,
458 Image,
459 Reset,
460 Button,
461}
462
463impl fmt::Display for Type {
464 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
465 f.write_str(match self {
466 Self::Hidden => "hidden",
467 Self::Text => "text",
468 Self::Search => "search",
469 Self::Tel => "tel",
470 Self::Url => "url",
471 Self::Email => "email",
472 Self::Password => "password",
473 Self::Date => "date",
474 Self::Month => "month",
475 Self::Week => "week",
476 Self::Time => "time",
477 Self::DateTimeLocal => "datetime-local",
478 Self::Number => "number",
479 Self::Range => "range",
480 Self::Color => "color",
481 Self::Checkbox => "checkbox",
482 Self::Radio => "radio",
483 Self::File => "file",
484 Self::Submit => "submit",
485 Self::Image => "image",
486 Self::Reset => "reset",
487 Self::Button => "button",
488 })
489 }
490}
491
492pub struct OnInput(pub Box<SerializeEventFn>);
493
494impl Attributes for OnInput {
495 fn render(self, r: &mut crate::render::ElementRenderer) -> Result<(), crate::Error> {
496 let (id, payload) = &(self.0)()?;
498 r.attribute("cabin-input", id)
499 .map_err(crate::error::InternalError::from)?;
500 r.attribute("cabin-input-payload", payload)
501 .map_err(crate::error::InternalError::from)?;
502
503 Ok(())
504 }
505}
506
507pub struct OnChange(pub Box<SerializeEventFn>);
508
509impl Attributes for OnChange {
510 fn render(self, r: &mut crate::render::ElementRenderer) -> Result<(), crate::Error> {
511 let (id, payload) = &(self.0)()?;
513 r.attribute("cabin-change", id)
514 .map_err(crate::error::InternalError::from)?;
515 r.attribute("cabin-change-payload", payload)
516 .map_err(crate::error::InternalError::from)?;
517
518 Ok(())
519 }
520}