1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use rooting::{
    El,
};
pub use rooting_forms_proc_macros::Form;

pub struct FormElements {
    /// The error display element, with `CSS_CLASS_ERROR`. This may be placed before
    /// the label in a struct context.
    pub error: Option<El>,
    /// The input, and any additional controls.
    pub elements: Vec<El>,
}

/// An object representing a form (the state of the form).
pub trait FormState<T> {
    /// Get the elements for this form or subform.
    fn elements(&self) -> FormElements;

    /// Parse the elements into the resulting type.
    fn parse(&self) -> Result<T, ()>;
}

/// Provides methods for creating forms from a type. All types that can appear as
/// or within such forms must implement this. This is automatically implemented for
/// `FormWith<()>` so if implementing yourself, focus on that trait.
pub trait Form {
    /// Generates a form state manager to produce form elements and parse the entered
    /// values.
    ///
    /// * `field` - is the field name, for accessibility using `aria-label`. `<label>`
    ///   isn't used sometime due to anonymous fields in tuples.
    ///
    /// * `from` - data used to populate the initial form, for example if creating a form
    ///   to edit existing data.
    fn new_form(field: &str, from: Option<&Self>) -> Box<dyn FormState<Self>>;
}

/// Like `Form` but allows passing in additional context, for custom elements that
/// need it.  `FormWith<()>` is generated by the `Form` derive macro.
pub trait FormWith<C> {
    /// Generates a form state manager to produce form elements and parse the entered
    /// values.
    ///
    /// * `context` - any additional data to be used when generating form states and
    ///   elements. This is forwarded to all nested `new_form` calls.
    ///
    /// See `Form` for the other fields.
    fn new_form(context: &C, field: &str, from: Option<&Self>) -> Box<dyn FormState<Self>>;
}

impl<T: FormWith<()>> Form for T {
    fn new_form(field: &str, from: Option<&Self>) -> Box<dyn FormState<Self>> {
        return <T as FormWith<()>>::new_form(&(), field, from);
    }
}
pub mod css;

pub use css::*;

pub mod impl_str;

pub use impl_str::*;

pub mod impl_bool;
pub mod impl_option;
pub mod impl_unit_structs;
pub mod impl_vec;

/// Republished types for macro use.
pub mod republish {
    pub use web_sys::HtmlSelectElement;
}