Skip to main content

cotis_web/
custom_data.rs

1//! Custom HTML host data for render commands.
2//!
3//! Attach [`ExtraHTMLData`] as the `extra_data` type parameter on
4//! [`ElementConfig`](cotis_defaults::element_configs::ElementConfig) and render commands
5//! ([`Rectangle`](cotis_defaults::render_commands::Rectangle),
6//! [`Text`](cotis_defaults::render_commands::Text), etc.). During drawing,
7//! [`OptionalExtraHTMLData::extra_html_data`] is read and passed to
8//! [`HTMLCanvas::ensure_command_element`](crate::rendering::HTMLCanvas::ensure_command_element),
9//! which sets the DOM tag name and optional inline style on the `cotis-{id}` host element.
10//!
11//! For arbitrary HTML fragments inside a host, use [`HTMLElement`] with custom draw logic
12//! or [`HTMLRenderer::get_custom_element_html`](crate::renderer::HTMLRenderer::get_custom_element_html).
13
14#[allow(dead_code)]
15pub(crate) trait IntoHTMLElement {
16    fn html_element(&self) -> Option<HTMLElement>;
17}
18
19impl IntoHTMLElement for () {
20    fn html_element(&self) -> Option<HTMLElement> {
21        None
22    }
23}
24
25impl IntoHTMLElement for HTMLElement {
26    fn html_element(&self) -> Option<HTMLElement> {
27        Some(self.clone())
28    }
29}
30
31/// Raw HTML content for a custom host element's `innerHTML`.
32#[derive(Debug, Clone)]
33pub struct HTMLElement {
34    html: String,
35}
36
37impl HTMLElement {
38    /// Creates a wrapper around an HTML fragment string.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use cotis_web::custom_data::HTMLElement;
44    ///
45    /// let el = HTMLElement::new("<span>Hello</span>");
46    /// assert_eq!(el.html(), "<span>Hello</span>");
47    /// ```
48    pub fn new(html: &str) -> HTMLElement {
49        Self {
50            html: html.to_string(),
51        }
52    }
53
54    /// Returns the stored HTML fragment.
55    pub fn html(&self) -> &str {
56        &self.html
57    }
58}
59
60/// Types that may carry [`ExtraHTMLData`] on a render command's `extra_data` field.
61pub trait OptionalExtraHTMLData {
62    /// Returns host tag/style overrides, or `None` for default `div` styling.
63    fn extra_html_data(&self) -> Option<ExtraHTMLData>;
64}
65
66impl OptionalExtraHTMLData for () {
67    fn extra_html_data(&self) -> Option<ExtraHTMLData> {
68        None
69    }
70}
71
72impl OptionalExtraHTMLData for ExtraHTMLData {
73    fn extra_html_data(&self) -> Option<ExtraHTMLData> {
74        Some(self.clone())
75    }
76}
77
78/// HTML tag name for a render command's DOM host element (`cotis-{id}`).
79///
80/// Used via [`ExtraHTMLData::tag`] on render command
81/// [`RenderCommandInfo::extra_data`](cotis_defaults::render_commands::RenderCommandInfo::extra_data).
82#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
83pub enum CustomHtmlElementTag {
84    /// Standard block container (`<div>`).
85    #[default]
86    Div,
87    /// Clickable button host (`<button>`).
88    Button,
89}
90
91impl CustomHtmlElementTag {
92    /// Returns the lowercase HTML tag name for this variant.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use cotis_web::custom_data::CustomHtmlElementTag;
98    ///
99    /// assert_eq!(CustomHtmlElementTag::Div.as_json_str(), "div");
100    /// assert_eq!(CustomHtmlElementTag::Button.as_json_str(), "button");
101    /// ```
102    pub const fn as_json_str(self) -> &'static str {
103        match self {
104            Self::Div => "div",
105            Self::Button => "button",
106        }
107    }
108}
109
110/// Per-command overrides for the DOM host element tag and inline CSS.
111#[derive(Clone, Debug, Default)]
112pub struct ExtraHTMLData {
113    /// HTML tag for the host element (default [`CustomHtmlElementTag::Div`]).
114    pub tag: CustomHtmlElementTag,
115    /// Optional inline `style` attribute value applied before drawable CSS pushes.
116    pub extra_style: Option<String>,
117}