use std::ops::{Deref, DerefMut};
use blinc_layout::div::{Div, ElementBuilder, ElementTypeId};
use blinc_layout::prelude::*;
use blinc_layout::widgets::table as layout_table;
use blinc_theme::{SpacingToken, ThemeState};
pub fn table() -> Div {
layout_table::table().class("cn-table")
}
pub fn table_header() -> Div {
layout_table::thead().class("cn-table-header")
}
pub fn table_body() -> Div {
layout_table::tbody().class("cn-table-body")
}
pub fn table_footer() -> Div {
layout_table::tfoot().class("cn-table-footer")
}
pub struct TableRow {
inner: Div,
}
impl TableRow {
fn new() -> Self {
Self {
inner: layout_table::tr().class("cn-table-row"),
}
}
pub fn selected(mut self, selected: impl blinc_layout::binding::IntoReactive<bool>) -> Self {
self.inner = self.inner.attr_when("data-state", "selected", selected);
self
}
pub fn child(mut self, child: impl ElementBuilder + 'static) -> Self {
self.inner = self.inner.child(child);
self
}
pub fn child_box(mut self, child: Box<dyn ElementBuilder>) -> Self {
self.inner = self.inner.child_box(child);
self
}
pub fn into_div(self) -> Div {
self.inner
}
}
impl Default for TableRow {
fn default() -> Self {
Self::new()
}
}
impl Deref for TableRow {
type Target = Div;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for TableRow {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl ElementBuilder for TableRow {
fn build(&self, tree: &mut blinc_layout::tree::LayoutTree) -> blinc_layout::tree::LayoutNodeId {
self.inner.build(tree)
}
fn render_props(&self) -> blinc_layout::element::RenderProps {
self.inner.render_props()
}
fn children_builders(&self) -> &[Box<dyn ElementBuilder>] {
self.inner.children_builders()
}
fn event_handlers(&self) -> Option<&blinc_layout::event_handler::EventHandlers> {
ElementBuilder::event_handlers(&self.inner)
}
fn layout_style(&self) -> Option<&taffy::Style> {
ElementBuilder::layout_style(&self.inner)
}
fn element_type_id(&self) -> ElementTypeId {
ElementBuilder::element_type_id(&self.inner)
}
fn element_classes(&self) -> &[std::sync::Arc<str>] {
self.inner.element_classes()
}
fn element_id(&self) -> Option<&str> {
self.inner.element_id()
}
}
pub fn table_row() -> TableRow {
TableRow::new()
}
pub fn table_head(content: impl Into<String>) -> layout_table::TableCell {
let theme = ThemeState::get();
layout_table::cell()
.class("cn-table-head")
.child(text(content).size(theme.typography().text_sm).medium())
}
pub fn table_cell() -> layout_table::TableCell {
layout_table::cell().class("cn-table-cell")
}
pub fn table_caption(content: impl Into<String>) -> Div {
let theme = ThemeState::get();
let pad = theme.spacing_value(SpacingToken::Space3);
div()
.class("cn-table-caption")
.flex_row()
.w_full()
.justify_center()
.padding_y_px(pad)
.child(text(content).size(theme.typography().text_sm))
}
#[cfg(test)]
mod tests {
use super::*;
fn init_theme() {
let _ = ThemeState::try_get().unwrap_or_else(|| {
ThemeState::init_default();
ThemeState::get()
});
}
#[test]
fn build_simple_table() {
init_theme();
let _ = table()
.child(table_header().child(table_row().child(table_head("Name"))))
.child(table_body().child(table_row().child(table_cell().child(text("Alice")))));
}
#[test]
fn caption_builds() {
init_theme();
let _ = table_caption("Caption text");
}
}