dioxus_tabular/
lib.rs

1//! Type-safe and composable table framework for Dioxus.
2//!
3//! `dioxus-tabular` provides a declarative, type-safe way to build reactive tables in Dioxus.
4//! Instead of configuring tables with dynamic descriptors, you define columns as typed components
5//! that own their rendering, filtering, and sorting logic.
6//!
7//! # Core Concepts
8//!
9//! - **[`Row`]**: Trait defining the unique key and identity of each row
10//! - **[`GetRowData<T>`]**: Trait providing typed access to row data
11//! - **[`TableColumn`]**: Trait describing how a column renders, filters, and sorts
12//! - **[`Columns`]**: Automatically implemented for tuples of `TableColumn`s
13//! - **[`use_tabular`]**: Hook to create a reactive table
14//! - **[`TableHeaders`]** / **[`TableCells`]**: Components for rendering headers and cells
15//!
16//! # Quick Start
17//!
18//! ```rust
19//! use dioxus::prelude::*;
20//! use dioxus_tabular::*;
21//!
22//! // 1. Define your row type
23//! #[derive(Clone, PartialEq)]
24//! struct User {
25//!     id: u32,
26//!     name: String,
27//! }
28//!
29//! // 2. Implement Row trait
30//! impl Row for User {
31//!     fn key(&self) -> impl Into<String> {
32//!         self.id.to_string()
33//!     }
34//! }
35//!
36//! // 3. Define data accessor types
37//! #[derive(Clone, PartialEq)]
38//! struct UserName(String);
39//!
40//! impl GetRowData<UserName> for User {
41//!     fn get(&self) -> UserName {
42//!         UserName(self.name.clone())
43//!     }
44//! }
45//!
46//! // 4. Define a column
47//! #[derive(Clone, PartialEq)]
48//! struct NameColumn;
49//!
50//! impl<R: Row + GetRowData<UserName>> TableColumn<R> for NameColumn {
51//!     fn column_name(&self) -> String {
52//!         "name".into()
53//!     }
54//!
55//!     fn render_header(&self, _context: ColumnContext, attributes: Vec<Attribute>) -> Element {
56//!         rsx! { th { ..attributes, "Name" } }
57//!     }
58//!
59//!     fn render_cell(&self, _context: ColumnContext, row: &R, attributes: Vec<Attribute>) -> Element {
60//!         rsx! { td { ..attributes, "{row.get().0}" } }
61//!     }
62//! }
63//!
64//! // 5. Use in your component
65//! fn app() -> Element {
66//!     let users = use_signal(|| vec![
67//!         User { id: 1, name: "Alice".to_string() },
68//!         User { id: 2, name: "Bob".to_string() },
69//!     ]);
70//!
71//!     let data = use_tabular((NameColumn,), users.into());
72//!
73//!     rsx! {
74//!         table {
75//!             thead { tr { TableHeaders { data } } }
76//!             tbody {
77//!                 for row in data.rows() {
78//!                     tr { key: "{row.key()}", TableCells { row } }
79//!                 }
80//!             }
81//!         }
82//!     }
83//! }
84//! ```
85//!
86//! # Features
87//!
88//! ## Multi-Column Sorting
89//!
90//! Columns can implement custom comparison logic via [`TableColumn::compare`].
91//! Users can sort by multiple columns with priority control using [`ColumnContext::request_sort`].
92//!
93//! ## Row Filtering
94//!
95//! Columns can implement filtering logic via [`TableColumn::filter`].
96//! Filters are automatically applied when rendering rows.
97//!
98//! ## Column Ordering and Visibility
99//!
100//! Control which columns are displayed and in what order using methods on [`ColumnContext`]:
101//! - `hide()` / `show()` - Toggle column visibility
102//! - `move_to()`, `move_forward()`, `move_backward()` - Reorder columns
103//! - `reset_order()` - Restore default state
104//!
105//! ## Export (optional feature)
106//!
107//! Enable the `export` feature to serialize table data:
108//!
109//! ```toml
110//! dioxus-tabular = { version = "0.1", features = ["export"] }
111//! ```
112//!
113//! Implement [`SerializableColumn`] and use the [`Exporter`] trait to export to various formats.
114
115mod column;
116mod columns;
117mod components;
118mod context;
119#[cfg(feature = "export")]
120mod export;
121mod row;
122
123#[cfg(test)]
124pub mod test_suite;
125
126pub use column::*;
127pub use columns::*;
128pub use components::*;
129pub use context::*;
130#[cfg(feature = "export")]
131pub use export::*;
132pub use row::*;