canonrs-core 0.1.0

CanonRS core types, traits and primitives
#![allow(unused_variables)]
//! @canon-level: strict
//! @canon-owner: primitives-team
//! DataTable Primitive - HTML puro

use leptos::prelude::*;
use crate::primitives::table::SortDirection;
use crate::meta::SelectionState;

#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum DataTableDensity {
    Compact,
    #[default]
    Comfortable,
    Spacious,
}

impl DataTableDensity {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Compact     => "compact",
            Self::Comfortable => "comfortable",
            Self::Spacious    => "spacious",
        }
    }
}










#[component]
pub fn DataTablePrimitive(
    children: Children,
    #[prop(default = DataTableDensity::Comfortable)] density: DataTableDensity,
    #[prop(into, default = String::new())] class: String,
    #[prop(into, default = String::new())] name: String,
) -> impl IntoView {
    let uid_dt = crate::infra::uid::generate("dt");
    view! {
        <div
            data-rs-datatable=""
            data-rs-uid=uid_dt
            data-rs-interaction="data"
            data-rs-density=density.as_str()
            data-rs-name=name
            class=class
        >
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableBulkBarPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div data-rs-datatable-bulk-bar="" hidden class=class>
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableToolbarPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div data-rs-datatable-toolbar="" class=class>
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableScrollPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div data-rs-datatable-scroll="" class=class>
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableTablePrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
    #[prop(default = false)] resizable: bool,
) -> impl IntoView {
    view! {
        <table
            data-rs-datatable-table=""
            data-rs-resizable=if resizable { Some("true") } else { None }
            class=class
        >
            {children()}
        </table>
    }
}

#[component]
pub fn DataTableExpandHeadCellPrimitive(
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <th data-rs-datatable-head-cell="" data-rs-col-expand="" scope="col" class=class></th>
    }
}

#[component]
pub fn DataTableExpandCellPrimitive(
    children: Children,
    row_id: String,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <td data-rs-datatable-cell="" data-rs-col-expand="" class=class>
            {children()}
        </td>
    }
}

#[component]
pub fn DataTableExpandBtnPrimitive(
    row_id: String,
) -> impl IntoView {
    view! {
        <button
            type="button"
            data-rs-datatable-expand-btn=""
            data-rs-row-id=row_id
            aria-expanded="false"
        >
            "â–¶"
        </button>
    }
}

#[component]
pub fn DataTableExpandRowPrimitive(
    children: Children,
    row_id: String,
    colspan: String,
) -> impl IntoView {
    view! {
        <tr data-rs-datatable-expand-row="" data-rs-row-id=row_id hidden=true>
            <td data-rs-datatable-cell="" colspan=colspan>
                <div data-rs-datatable-expand-content="">
                    {children()}
                </div>
            </td>
        </tr>
    }
}

#[component]
pub fn DataTableColgroupPrimitive(
    children: Children,
) -> impl IntoView {
    view! {
        <colgroup data-rs-datatable-colgroup="">
            {children()}
        </colgroup>
    }
}

#[component]
pub fn DataTableColPrimitive(
    #[prop(into, default = String::new())] col_index: String,
    #[prop(into, default = String::new())] width: String,
) -> impl IntoView {
    view! {
        <col
            data-rs-datatable-col=""
            data-rs-col-index=col_index
            style=if width.is_empty() { String::new() } else { format!("width:{}", width) }
        />
    }
}

#[component]
pub fn DataTableHeadPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <thead data-rs-datatable-head="" data-rs-resize-container="" class=class>
            {children()}
        </thead>
    }
}

#[component]
pub fn DataTableHeadRowPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <tr data-rs-datatable-head-row="" class=class>
            {children()}
        </tr>
    }
}

#[component]
pub fn DataTableHeadCellPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
    #[prop(into, default = String::new())] sort_key: String,
    #[prop(default = SortDirection::None)] sort_direction: SortDirection,
    #[prop(into, default = String::new())] col_index: String,
    #[prop(into, default = String::new())] style: String,
    #[prop(default = false)] resizable: bool,
) -> impl IntoView {
    view! {
        <th
            data-rs-datatable-head-cell=""
            scope="col"
            role="columnheader"
            aria-sort=sort_direction.aria_sort()
            data-rs-sort=sort_direction.as_str()
            data-rs-sort-key=sort_key
            data-rs-col-index=col_index
            data-rs-resizable=if resizable { Some("true") } else { None }
            style=style
            class=class
        >
            {children()}
            {resizable.then(|| view! {
                <span data-rs-datatable-resize-handle="" aria-hidden="true"></span>
            })}
        </th>
    }
}

#[component]
pub fn DataTableBodyPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <tbody data-rs-datatable-body="" class=class>
            {children()}
        </tbody>
    }
}

#[component]
pub fn DataTableRowPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
    #[prop(into, default = String::new())] row_id: String,
    #[prop(into, default = String::new())] row_label: String,
    #[prop(default = SelectionState::Unselected)] selected: SelectionState,
    #[prop(optional)] row_index: Option<usize>,
) -> impl IntoView {
    let is_selected = selected == SelectionState::Selected;
    let aria_rowindex = row_index.map(|i| (i + 1).to_string()).unwrap_or_default();
    let row_index_str = row_index.map(|i| i.to_string()).unwrap_or_default();
    view! {
        <tr
            data-rs-datatable-row=""
            data-rs-selection=if is_selected { "selected" } else { "unselected" }
            data-rs-row-id=row_id
            data-rs-row-label=row_label
            aria-selected=if is_selected { "true" } else { "false" }
            aria-rowindex=aria_rowindex
            data-rs-row-index=row_index_str
            class=class
        >
            {children()}
        </tr>
    }
}

#[component]
pub fn DataTableCellPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
    #[prop(into, default = String::new())] col_index: String,
    #[prop(into, default = String::new())] style: String,
) -> impl IntoView {
    view! {
        <td
            data-rs-datatable-cell=""
            data-rs-col-index=col_index
            style=style
            class=class
        >
            {children()}
        </td>
    }
}

#[component]
pub fn DataTableFooterPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <tfoot data-rs-datatable-footer="" class=class>
            {children()}
        </tfoot>
    }
}

#[component]
pub fn DataTablePaginationPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div data-rs-datatable-pagination="" class=class>
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableEmptyPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div
            data-rs-datatable-empty=""
            data-rs-activity="empty"
            role="status"
            aria-live="polite"
            class=class
        >
            {children()}
        </div>
    }
}

#[component]
pub fn DataTableLoadingPrimitive(
    children: Children,
    #[prop(into, default = String::new())] class: String,
) -> impl IntoView {
    view! {
        <div
            data-rs-datatable-loading=""
            data-rs-loading="loading"
            role="status"
            aria-live="polite"
            class=class
        >
            {children()}
        </div>
    }
}