1pub mod layout;
8pub mod components;
9pub mod tokens;
10
11use ferrox_front_core::dom::{div, span, DomBuilder};
12use ferrox_front_core::reactivity::Signal;
13
14pub struct DataGridState {
15 pub scroll_top: Signal<f64>,
16 pub row_height: f64,
17 pub visible_rows: usize,
18}
19
20impl DataGridState {
21 pub fn new(row_height: f64, visible_rows: usize) -> Self {
22 Self {
23 scroll_top: Signal::new(0.0),
24 row_height,
25 visible_rows,
26 }
27 }
28}
29
30pub fn virtual_data_grid(
31 columns: Vec<&str>,
32 rows: Vec<Vec<&str>>,
33 state: &DataGridState
34) -> DomBuilder {
35 let total_rows = rows.len();
36 let total_height = total_rows as f64 * state.row_height;
37
38 let start_idx = (state.scroll_top.get() / state.row_height).floor() as usize;
39 let end_idx = (start_idx + state.visible_rows).min(total_rows);
40
41 let mut container = div()
42 .attr("class", "ferrox-table-wrapper")
43 .attr("style", &format!("height: {}px; overflow-y: auto; position: relative;", state.row_height * state.visible_rows as f64));
44
45 let ghost = div()
46 .attr("style", &format!("height: {}px; width: 1px;", total_height));
47 container = container.child(ghost);
48
49 let mut content = div()
50 .attr("style", &format!("position: absolute; top: {}px; left: 0; width: 100%;", start_idx as f64 * state.row_height));
51
52 let mut thead = div().attr("class", "ferrox-thead").attr("style", "display: flex; background: rgba(0,0,0,0.4); font-weight: 700; border-bottom: var(--border-glass);");
53 for col in columns {
54 thead = thead.child(span().attr("style", "flex: 1; padding: 12px 16px;").text(col));
55 }
56 content = content.child(thead);
57
58 for i in start_idx..end_idx {
59 let mut tr = div().attr("class", "ferrox-tr").attr("style", &format!("display: flex; height: {}px; align-items: center; border-bottom: 1px solid rgba(255,255,255,0.05);", state.row_height));
60 for cell in &rows[i] {
61 tr = tr.child(span().attr("style", "flex: 1; padding: 0 16px; font-size: 0.95rem;").text(cell));
62 }
63 content = content.child(tr);
64 }
65
66 container.child(content)
67}