oriel-iced 0.1.0

iced integrator for the oriel headless data grid: satisfies the data and render seams for iced 0.14.
Documentation

oriel

CI crates.io docs.rs

A virtualized, batteries-included data grid for iced — sort, filter, live ingest, themes, and smooth scrolling over hundreds of thousands of rows.

The oriel showcase: live ingest with tail-follow, sorting, filtering, theme switching, row animations

Recorded deterministically, headless — the demo renders itself: cargo run -p oriel-iced --example record_showcase --release

cargo run -p oriel-iced --example showcase --release

The showcase is the full tour in one window: a live job pipeline streaming over ~25 000 rows of history, with every feature reachable from the toolbar and keyboard.

Features

  • Virtualization — materialized widgets are a function of the viewport, never the row count; sub-pixel-exact to ~670 000 default-height rows.
  • Transactional ingest — append/update/remove imperatively at 60 Hz; the viewport re-anchors by row identity, so mutations above the view never make visible content jump.
  • Tail-follow with intent-aware auto-freeze (scrolling up frees you; content growth never does).
  • Sort & filter as plain, persistable specs, executed by your store — in memory, or pushed down to a real query engine through the async seam.
  • Selection & keyboard navigation, identity-keyed — survives re-sorting and churn by construction.
  • Columns: resizable with policy bounds, grip double-click auto-size (headers, cells, footers, and the sort arrow all measured), pluggable cell renderers via an opaque-element trait.
  • Footers with live aggregates that dock to short content.
  • Row animations — ag-grid-style flights and enter-fades, screen-space, shared deadline, suppressed while tail-following.
  • Themes — CSS-verified ports of ag-grid Quartz/Alpine/Balham, Material, Spreadsheet, and Bootstrap (provenance), plus fully palette-derived defaults; every color and length is a public knob with a public default.
  • Own scrollbar with a real minimum thumb (iced's is 2 px at grid scale).

Quickstart

[dependencies]
iced = "0.14"
oriel-core = "0.1"
oriel-iced = "0.1"
use iced::{Element, Task};
use oriel_core::columns::ColumnId;
use oriel_core::data::VecStore;
use oriel_iced::column::TextColumn;
use oriel_iced::grid::{self, BoxedColumn, VirtualGrid};

#[derive(Clone, Debug)]
struct Person { id: u64, name: String }

type Store = VecStore<Person, u64, fn(&Person) -> u64>;

struct App { grid: VirtualGrid<Store> }

#[derive(Debug, Clone)]
enum Msg { Grid(grid::Message<Person>) }

fn boot() -> (App, Task<Msg>) {
    fn key(p: &Person) -> u64 { p.id }
    let rows = (0..100_000u64).map(|id| Person { id, name: format!("Person {id}") }).collect();
    let store = VecStore::new(rows, key as fn(&Person) -> u64);
    let columns: Vec<BoxedColumn<Person>> = vec![
        Box::new(TextColumn::new(ColumnId(1), "#", 70.0, |p: &Person| p.id.to_string()).numeric()),
        Box::new(TextColumn::new(ColumnId(2), "Name", 260.0, |p: &Person| p.name.clone())),
    ];
    let (grid, init) = VirtualGrid::new(store, columns);
    (App { grid }, init.map(Msg::Grid))
}

fn update(app: &mut App, msg: Msg) -> Task<Msg> {
    match msg { Msg::Grid(m) => app.grid.update(m).map(Msg::Grid) }
}

fn view(app: &App) -> Element<'_, Msg> {
    app.grid.view().map(Msg::Grid)
}

fn main() -> iced::Result {
    iced::application(boot, update, view).run()
}

The crate-level rustdoc is the real manual: the wiring contract, a "where do I…?" map, keyboard/persistence/testing recipes, and compiled doc examples on every high-traffic API.

Architecture

Two crates, one-way dependency:

  • oriel-core — headless, zero dependencies: virtualization math, view/interaction state, and the two seams an integrator satisfies (an async DataSource, an opaque-element Column model). Unit-testable with no GUI in the loop.
  • oriel-iced — the iced integrator: the VirtualGrid widget, provided column renderers, themes, and the grid's hand-rolled widgets (resize grips, auto-size measurer, scrollbar, row animations).

The rules this project is built under — and held to by tests and lints — live in DESIGN-PHILOSOPHY.md. AI agents working on the codebase are bound to them via AGENTS.md.

Examples

Example What it shows
showcase The flagship tour — every feature, one grid
record_showcase Deterministic headless demo recording (renders the showcase into a video, no window)

Status

Early 0.x. Built and verified against iced 0.14 (iced is pre-1.0 and its widget API moves between minor versions — development is lockfile-pinned, and the upstream behaviors this crate depends on are pinned by canary tests). Interaction behavior is regression-tested headlessly against the real iced runtime with the tiny-skia renderer — no window or GPU needed; cargo test --workspace runs everything.

License

MIT