Skip to main content

ferrox_front_ui/
lib.rs

1//! # Ferrox Front UI (`ferrox-front-ui`)
2//!
3//! `ferrox-front-ui` provides an enterprise-grade Glassmorphism Design System for WebAssembly:
4//! 12-column responsive layout grid (`Container`, `Row`, `Col`), Virtualized DataGrid (1,000,000+ rows),
5//! Design Tokens, and UI components (Buttons, Badges, Cards, Form Controls, Avatars, Progress Bars, Toasts, Spinners).
6
7pub mod layout;
8pub mod components;
9pub mod icons;
10pub mod tokens;
11pub mod ferrox_datagrid;
12pub mod ferrox_kanban;
13pub mod ferrox_theme;
14pub mod ferrox_admin;
15pub mod ferrox_security_dashboard;
16pub mod json_dashboard_builder;
17pub mod form_engine;
18pub mod overlays;
19pub mod doc_components;
20
21pub use components::*;
22pub use icons::*;
23pub use doc_components::*;
24pub use ferrox_datagrid::{
25    EnterpriseDataGrid, EnterpriseDataGridState, ColumnDef, SortDirection,
26    PinnedPosition, TextAlign, trigger_csv_download, generate_rfc4180_csv,
27    FerroxDataGridConfig, ferrox_datagrid,
28};
29pub use form_engine::{
30    FormField, RuleBuilder, ValidationRule, WizardStep, FormWizardState, form_wizard,
31};
32pub use overlays::{
33    CommandAction, CommandPaletteState, command_palette,
34    DatePickerSelection, DatePickerState, date_picker,
35    TreeNode, tree_view, modal_focus_trap,
36};
37
38use ferrox_front_core::dom::{div, span, DomBuilder};
39use ferrox_front_core::reactivity::Signal;
40
41pub struct DataGridState {
42    pub scroll_top: Signal<f64>,
43    pub row_height: f64,
44    pub visible_rows: usize,
45}
46
47impl DataGridState {
48    pub fn new(row_height: f64, visible_rows: usize) -> Self {
49        Self {
50            scroll_top: Signal::new(0.0),
51            row_height,
52            visible_rows,
53        }
54    }
55}
56
57pub fn virtual_data_grid(
58    columns: Vec<&str>,
59    rows: Vec<Vec<&str>>,
60    state: &DataGridState
61) -> DomBuilder {
62    let total_rows = rows.len();
63    let total_height = total_rows as f64 * state.row_height;
64
65    let start_idx = (state.scroll_top.get() / state.row_height).floor() as usize;
66    let end_idx = (start_idx + state.visible_rows).min(total_rows);
67
68    let mut container = div()
69        .attr("class", "ferrox-table-wrapper")
70        .attr("style", &format!("height: {}px; overflow-y: auto; position: relative;", state.row_height * state.visible_rows as f64));
71    
72    let ghost = div()
73        .attr("style", &format!("height: {}px; width: 1px;", total_height));
74    container = container.child(ghost);
75
76    let mut content = div()
77        .attr("style", &format!("position: absolute; top: {}px; left: 0; width: 100%;", start_idx as f64 * state.row_height));
78
79    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);");
80    for col in columns {
81        thead = thead.child(span().attr("style", "flex: 1; padding: 12px 16px;").text(col));
82    }
83    content = content.child(thead);
84
85    for i in start_idx..end_idx {
86        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));
87        for cell in &rows[i] {
88            tr = tr.child(span().attr("style", "flex: 1; padding: 0 16px; font-size: 0.95rem;").text(cell));
89        }
90        content = content.child(tr);
91    }
92
93    container.child(content)
94}