Skip to main content

autumn_plugin_vanilla/behaviors/
mod.rs

1//! Typed builders. Each builder writes the attributes of one behavior.
2//!
3//! All builders have `attributes()`, for any template engine, and `attr()`,
4//! for extra attributes. Most builders also have `wrap()`, which puts
5//! content in a `<div>` with those attributes. A behavior acts on events from
6//! its element and from the descendants of that element.
7
8mod autosubmit;
9mod confirm;
10mod copy;
11mod count;
12mod dismiss;
13mod local_time;
14mod toggle;
15
16use std::fmt;
17
18use autumn_web::Markup;
19
20pub use autosubmit::AutoSubmit;
21pub use confirm::Confirm;
22pub use copy::CopyText;
23pub use count::{Count, CountMode, OutputSlot};
24pub use dismiss::Dismiss;
25pub use local_time::{LocalTime, TimeFormat};
26pub use toggle::Toggle;
27
28/// A built-in behavior. Use it as the value of `data-vanilla` in raw markup.
29///
30/// ```rust
31/// use autumn_plugin_vanilla::Behavior;
32/// use autumn_web::html;
33///
34/// let html = html! { button data-vanilla=(Behavior::Copy) {} };
35/// assert_eq!(html.into_string(), r#"<button data-vanilla="copy"></button>"#);
36/// ```
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38#[non_exhaustive]
39pub enum Behavior {
40    /// Submits the form when a field changes.
41    AutoSubmit,
42    /// Asks the user before a form submits or a link opens.
43    Confirm,
44    /// Copies text to the clipboard on click.
45    Copy,
46    /// Shows the character count of a field.
47    Count,
48    /// Removes the element when the user clicks a close control, or after a time.
49    Dismiss,
50    /// Shows a `<time>` in the browser locale and time zone.
51    LocalTime,
52    /// Shows or hides target elements on click.
53    Toggle,
54}
55
56impl Behavior {
57    /// All built-in behaviors, in name order.
58    pub const ALL: &'static [Self] = &[
59        Self::AutoSubmit,
60        Self::Confirm,
61        Self::Copy,
62        Self::Count,
63        Self::Dismiss,
64        Self::LocalTime,
65        Self::Toggle,
66    ];
67
68    /// The name that `vanilla.js` registers.
69    #[must_use]
70    pub const fn name(self) -> &'static str {
71        match self {
72            Self::AutoSubmit => "autosubmit",
73            Self::Confirm => "confirm",
74            Self::Copy => "copy",
75            Self::Count => "count",
76            Self::Dismiss => "dismiss",
77            Self::LocalTime => "local-time",
78            Self::Toggle => "toggle",
79        }
80    }
81}
82
83impl fmt::Display for Behavior {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        f.write_str(self.name())
86    }
87}
88
89impl maud::Render for Behavior {
90    fn render_to(&self, buffer: &mut String) {
91        // Names are lowercase ASCII and `-`. They need no escaping.
92        buffer.push_str(self.name());
93    }
94}
95
96/// The `data-vanilla` pair for `behavior`.
97fn marker(behavior: Behavior) -> (&'static str, String) {
98    ("data-vanilla", behavior.name().to_owned())
99}
100
101/// A `<button type="button">` with `attributes` and `content`.
102fn button(attributes: Vec<(&'static str, String)>, content: Markup) -> Markup {
103    let mut all = Vec::with_capacity(attributes.len() + 1);
104    all.push(("type", "button".to_owned()));
105    all.extend(attributes);
106    crate::markup::element("button", &all, content)
107}