cabin/html/elements/
global.rs

1use std::borrow::Cow;
2use std::fmt;
3
4use cabin_macros::Attribute;
5
6use crate::html::attributes::WithAttribute;
7
8pub trait Global: WithAttribute {
9    /// Used by the user agent as a guide for creating a keyboard shortcut that activates or
10    /// focuses the element.
11    fn access_key(self, access_key: impl Into<Cow<'static, str>>) -> Self::Output<AccessKey> {
12        self.with_attribute(AccessKey(access_key.into()))
13    }
14
15    /// Hints the user-agent of how to automatically capitalize input (from non-physical
16    fn auto_capitalize(self, auto_capitalize: AutoCapitalize) -> Self::Output<AutoCapitalize> {
17        self.with_attribute(auto_capitalize)
18    }
19
20    /// Indicate that the element is to be focused as soon as the page is loaded.
21    fn auto_focus(self) -> Self::Output<AutoFocus> {
22        self.with_auto_focus(true)
23    }
24
25    /// Indicate that the element is to be focused as soon as the page is loaded.
26    fn with_auto_focus(self, auto_focus: bool) -> Self::Output<AutoFocus> {
27        self.with_attribute(AutoFocus(auto_focus))
28    }
29
30    /// Indicating whether the element should be editable by the user.
31    fn content_editable(self) -> Self::Output<ContentEditable> {
32        self.with_content_editable(true)
33    }
34
35    /// Indicating whether the element should be editable by the user.
36    fn with_content_editable(self, content_editable: bool) -> Self::Output<ContentEditable> {
37        self.with_attribute(ContentEditable(content_editable))
38    }
39
40    /// The element's text directionality.
41    fn dir(self, dir: Dir) -> Self::Output<Dir> {
42        self.with_attribute(dir)
43    }
44
45    /// Indicate whether the element can be dragged.
46    fn draggable(self) -> Self::Output<Draggable> {
47        self.with_draggable(true)
48    }
49
50    /// Indicate whether the element can be dragged.
51    fn with_draggable(self, draggable: bool) -> Self::Output<Draggable> {
52        self.with_attribute(Draggable(draggable))
53    }
54
55    /// Indicate the action label (or icon) to present for the enter key on virtual keyboards.
56    fn enter_key_hint(self, enter_key_hint: EnterKeyHint) -> Self::Output<EnterKeyHint> {
57        self.with_attribute(enter_key_hint)
58    }
59
60    /// Hide the element (visually and from screen-readers).
61    fn hidden(self, hidden: Hidden) -> Self::Output<Hidden> {
62        self.with_attribute(hidden)
63    }
64
65    /// Mark the element as not presently accessible (e.g. when overlayed by a loading state).
66    fn inert(self) -> Self::Output<Inert> {
67        self.with_inert(true)
68    }
69
70    /// Mark the element as not presently accessible (e.g. when overlayed by a loading state).
71    fn with_inert(self, inert: bool) -> Self::Output<Inert> {
72        self.with_attribute(Inert(inert))
73    }
74
75    /// Hint an input mechanism that would be most helpful for users entering content.
76    fn input_mode(self, input_mode: InputMode) -> Self::Output<InputMode> {
77        self.with_attribute(input_mode)
78    }
79
80    /// The element should behave like the defined custom element.
81    fn is(self, is: impl Into<Cow<'static, str>>) -> Self::Output<Is> {
82        self.with_attribute(Is(is.into()))
83    }
84
85    /// Unique, global identifier of the item (`item_scope` and `item_type` must also be defined).
86    fn item_id(self, item_id: impl Into<Cow<'static, str>>) -> Self::Output<ItemId> {
87        self.with_attribute(ItemId(item_id.into()))
88    }
89
90    /// A microdata name-value pair (this is the name – either a string or URL; the element's
91    /// content is the value).
92    fn item_prop(self, item_prop: impl Into<Cow<'static, str>>) -> Self::Output<ItemProp> {
93        self.with_attribute(ItemProp(item_prop.into()))
94    }
95
96    /// List of element IDs elsewehre in the document with additional properties.
97    fn item_ref(self, item_ref: impl Into<Cow<'static, str>>) -> Self::Output<ItemRef> {
98        self.with_attribute(ItemRef(item_ref.into()))
99    }
100
101    /// Create a new item by scoping the the descendent properties together (`item_type` must also
102    /// be defined).
103    fn item_scope(self) -> Self::Output<ItemScope> {
104        self.with_item_scope(true)
105    }
106
107    /// Create a new item by scoping the the descendent properties together (`item_type` must also
108    /// be defined).
109    fn with_item_scope(self, item_scope: bool) -> Self::Output<ItemScope> {
110        self.with_attribute(ItemScope(item_scope))
111    }
112
113    /// URL of the vocabulary that will be used to define item properties in the data structure.
114    fn item_type(self, item_type: impl Into<Cow<'static, str>>) -> Self::Output<ItemType> {
115        self.with_attribute(ItemType(item_type.into()))
116    }
117
118    /// Primary language of the element's contents.
119    fn lang(self, lang: impl Into<Cow<'static, str>>) -> Self::Output<Lang> {
120        self.with_attribute(Lang(lang.into()))
121    }
122
123    /// Cryptographic nonce ("number used once") which can be used by Content Security Policy to
124    /// determine whether or not a given fetch will be allowed to proceed.
125    fn nonce(self, nonce: impl Into<Cow<'static, str>>) -> Self::Output<Nonce> {
126        self.with_attribute(Nonce(nonce.into()))
127    }
128
129    /// Don't render the element until it becomes shown, at which point it will be rendered on top
130    /// of other page content.
131    fn popover(self) -> Self::Output<Popover> {
132        self.with_popover(true)
133    }
134
135    /// Don't render the element until it becomes shown, at which point it will be rendered on top
136    /// of other page content.
137    fn with_popover(self, popover: bool) -> Self::Output<Popover> {
138        self.with_attribute(Popover(popover))
139    }
140
141    /// The slot name this element is assigned to.
142    fn slot(self, slot: impl Into<Cow<'static, str>>) -> Self::Output<Slot> {
143        self.with_attribute(Slot(slot.into()))
144    }
145
146    /// Explicitly enable or disable spelling and grammar checking for the element's contents.
147    fn spellcheck(self, spellcheck: bool) -> Self::Output<Spellcheck> {
148        self.with_attribute(Spellcheck(spellcheck))
149    }
150
151    /// Inline CSS.
152    fn style(self, style: impl Into<Cow<'static, str>>) -> Self::Output<Style> {
153        self.with_attribute(Style(style.into()))
154    }
155
156    /// Specifify how and in which order the element can be focused.
157    fn tab_index(self, tab_index: TabIndex) -> Self::Output<TabIndex> {
158        self.with_attribute(tab_index)
159    }
160
161    /// Advisory information for the element, such as would be appropriate for a tooltip.
162    fn title(self, title: impl Into<Cow<'static, str>>) -> Self::Output<Title> {
163        self.with_attribute(Title(title.into()))
164    }
165
166    /// Indicate that the contents of this element should not be translated when the page is
167    /// localized.
168    fn translate(self, translate: bool) -> Self::Output<Translate> {
169        self.with_attribute(Translate(translate))
170    }
171}
172
173/// Used by the user agent as a guide for creating a keyboard shortcut that activates or
174/// focuses the element.
175#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
176pub struct AccessKey(pub Cow<'static, str>);
177
178/// Indicate that the element is to be focused as soon as the page is loaded.
179#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
180pub struct AutoFocus(pub bool);
181
182/// Indicating whether the element should be editable by the user.
183#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
184pub struct ContentEditable(pub bool);
185
186/// Indicate whether the element can be dragged.
187#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
188pub struct Draggable(pub bool);
189
190/// Mark the element as not presently accessible (e.g. when overlayed by a loading state).
191#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
192pub struct Inert(pub bool);
193
194/// The element should behave like the defined custom element.
195#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
196pub struct Is(pub Cow<'static, str>);
197
198/// Unique, global identifier of the item (`item_scope` and `item_type` must also be defined).
199#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
200pub struct ItemId(pub Cow<'static, str>);
201
202/// A microdata name-value pair (this is the name – either a string or URL; the element's
203/// content is the value).
204#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
205pub struct ItemProp(pub Cow<'static, str>);
206
207/// List of element IDs elsewehre in the document with additional properties.
208#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
209pub struct ItemRef(pub Cow<'static, str>);
210
211/// Create a new item by scoping the the descendent properties together (`item_type` must also
212/// be defined).
213#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
214pub struct ItemScope(pub bool);
215
216/// URL of the vocabulary that will be used to define item properties in the data structure.
217#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
218pub struct ItemType(pub Cow<'static, str>);
219
220/// Primary language of the element's contents.
221#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
222pub struct Lang(pub Cow<'static, str>);
223
224/// Cryptographic nonce ("number used once") which can be used by Content Security Policy to
225/// determine whether or not a given fetch will be allowed to proceed.
226#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
227pub struct Nonce(pub Cow<'static, str>);
228
229/// Don't render the element until it becomes shown, at which point it will be rendered on top
230/// of other page content.
231#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
232pub struct Popover(pub bool);
233
234/// The slot name this element is assigned to.
235#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
236pub struct Slot(pub Cow<'static, str>);
237
238/// Explicitly enable or disable spelling and grammar checking for the element's contents.
239#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
240pub struct Spellcheck(pub bool);
241
242/// Inline CSS.
243#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
244pub struct Style(pub Cow<'static, str>);
245
246/// Advisory information for the element, such as would be appropriate for a tooltip.
247#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
248pub struct Title(pub Cow<'static, str>);
249
250/// Hints the user-agent of how to automatically capitalize input (from non-physical
251#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
252pub enum AutoCapitalize {
253    /// No autocapitalization.
254    #[default]
255    None,
256
257    /// The first letter of each sentence defaults to a capital letter.
258    Sentences,
259
260    /// The first letter of each word defaults to a capital letter.
261    Words,
262
263    /// All letters should default to uppercase.
264    Characters,
265}
266
267impl fmt::Display for AutoCapitalize {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        match self {
270            Self::None => f.write_str("none"),
271            Self::Sentences => f.write_str("sentences"),
272            Self::Words => f.write_str("words"),
273            Self::Characters => f.write_str("characters"),
274        }
275    }
276}
277
278/// The element's text directionality.
279#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
280pub enum Dir {
281    /// Directionally isolated left-to-right text.
282    Ltr,
283
284    /// Directionally isolated right-to-left text.
285    Rtl,
286
287    /// Directionally isolated text, but direction is to be determined by user-agent.
288    Auto,
289}
290
291impl fmt::Display for Dir {
292    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293        match self {
294            Self::Ltr => f.write_str("ltr"),
295            Self::Rtl => f.write_str("rtl"),
296            Self::Auto => f.write_str("auto"),
297        }
298    }
299}
300
301/// Indicate the action label (or icon) to present for the enter key on virtual keyboards.
302#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
303pub enum EnterKeyHint {
304    /// Insert new line.
305    Enter,
306
307    /// Nothing more to input – close input method editor.
308    Done,
309
310    /// Take user to target of the typed text.
311    Go,
312
313    /// Take user to next field that will accept text.
314    Next,
315
316    /// Take user to previous field that will accept text.
317    Previous,
318
319    /// Take user to search result for typed text.
320    Search,
321
322    /// Deliver the text to its target.
323    Send,
324}
325
326impl fmt::Display for EnterKeyHint {
327    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328        match self {
329            Self::Enter => f.write_str("enter"),
330            Self::Done => f.write_str("done"),
331            Self::Go => f.write_str("go"),
332            Self::Next => f.write_str("next"),
333            Self::Previous => f.write_str("previous"),
334            Self::Search => f.write_str("search"),
335            Self::Send => f.write_str("send"),
336        }
337    }
338}
339
340/// Hide the element (visually and from screen-readers).
341#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
342pub enum Hidden {
343    /// Do not render element.
344    Hidden,
345
346    /// Do not render, unless found by searching the page or via fragment navigation.
347    UntilFound,
348}
349
350impl fmt::Display for Hidden {
351    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352        match self {
353            Self::Hidden => f.write_str("hidden"),
354            Self::UntilFound => f.write_str("until-found"),
355        }
356    }
357}
358
359/// Hint an input mechanism that would be most helpful for users entering content.
360#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
361pub enum InputMode {
362    /// Do not display a virtual keyboard (useful for when rendering your own keyboard).
363    None,
364
365    /// Text input in user's locale.
366    Text,
367
368    /// Telephone number input.
369    Tel,
370
371    /// Text input in user's locale, with keys for aiding in the input of URLs.
372    Url,
373
374    /// Text input in user's locale, with keys for aiding in the input of email addresses.
375    Email,
376
377    /// Numeric input.
378    Numeric,
379
380    /// Fractional numeric input.
381    Decimal,
382
383    /// Text input in user's locale, optimized for search.
384    Search,
385}
386
387impl fmt::Display for InputMode {
388    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389        match self {
390            Self::None => f.write_str("none"),
391            Self::Text => f.write_str("text"),
392            Self::Tel => f.write_str("tel"),
393            Self::Url => f.write_str("url"),
394            Self::Email => f.write_str("email"),
395            Self::Numeric => f.write_str("numeric"),
396            Self::Decimal => f.write_str("decimal"),
397            Self::Search => f.write_str("search"),
398        }
399    }
400}
401
402/// Specifify how and in which order the element can be focused.
403#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
404pub enum TabIndex {
405    /// Request that an element is to be click focusable but not sequentially focusable (-1).
406    Skip,
407
408    /// Request that an element is to be click and sequentially focusable. Focus-order should be
409    /// based on the given number from lowest to highest.
410    Order(u32),
411}
412
413impl fmt::Display for TabIndex {
414    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415        match self {
416            Self::Skip => f.write_str("-1"),
417            Self::Order(order) => order.fmt(f),
418        }
419    }
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
423#[attribute(outer)]
424pub struct Translate(bool);
425
426impl fmt::Display for Translate {
427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428        if !self.0 {
429            f.write_str("no")?;
430        }
431        Ok(())
432    }
433}