cabin/html/elements/
td.rs

1use std::borrow::Cow;
2
3use cabin_macros::Attribute;
4
5use super::common::Common;
6use super::global::Global;
7use crate::html::attributes::{Attributes, WithAttribute};
8use crate::html::list::SpaceSeparated;
9use crate::html::{Aria, Html};
10use crate::View;
11
12/// The `td` element represents a data cell in a [super::table].
13pub fn td(content: impl View) -> Html<marker::Td, (), impl View> {
14    #[cfg(debug_assertions)]
15    let content = content.boxed();
16    Html::new("td", (), content)
17}
18
19pub mod marker {
20    pub struct Td;
21}
22
23impl<A: Attributes, V: 'static> Td for Html<marker::Td, A, V> {}
24impl<A: Attributes, V: 'static> Common for Html<marker::Td, A, V> {}
25impl<A: Attributes, V: 'static> Global for Html<marker::Td, A, V> {}
26impl<A: Attributes, V: 'static> Aria for Html<marker::Td, A, V> {}
27
28/// The `td` element represents a data cell in a [super::table].
29pub trait Td: WithAttribute {
30    /// Number of columns that the cell is to span.
31    fn col_span(self, col_span: u32) -> Self::Output<ColSpan> {
32        self.with_attribute(ColSpan(col_span))
33    }
34
35    /// Number of rows that the cell is to span.
36    fn row_span(self, row_span: u32) -> Self::Output<RowSpan> {
37        self.with_attribute(RowSpan(row_span))
38    }
39
40    /// The header cells for this cell.
41    fn headers(
42        self,
43        headers: impl Into<SpaceSeparated<Cow<'static, str>>>,
44    ) -> Self::Output<Headers> {
45        self.with_attribute(Headers(headers.into()))
46    }
47
48    /// Appends a header cell for this cell.
49    fn append_header(mut self, header: impl Into<Cow<'static, str>>) -> Self::Output<Headers> {
50        let headers = if let Some(list) = self.get_attribute_mut::<Headers>() {
51            Headers(
52                match std::mem::replace(&mut list.0, SpaceSeparated::Single(Cow::Borrowed(""))) {
53                    SpaceSeparated::Single(existing) => {
54                        SpaceSeparated::List([existing, header.into()].into())
55                    }
56                    SpaceSeparated::List(mut list) => {
57                        list.insert(header.into());
58                        SpaceSeparated::List(list)
59                    }
60                },
61            )
62        } else {
63            Headers(SpaceSeparated::Single(header.into()))
64        };
65        self.with_attribute(headers)
66    }
67}
68
69/// Number of columns that the cell is to span.
70#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
71pub struct ColSpan(pub u32);
72
73/// Number of rows that the cell is to span.
74#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Attribute)]
75pub struct RowSpan(pub u32);
76
77/// The header cells for a cell.
78#[derive(Debug, Clone, Hash, Attribute)]
79pub struct Headers(pub SpaceSeparated<Cow<'static, str>>);