Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facet-wrapped/src/lib.rs

//! **facet-wrapped** — the REAL facett components, wrapped for wasm.
//!
//! This is a **wrapper**, not a library. It owns no rendering, no data model and no
//! port of a pane: every pixel is drawn by the existing facett `*-view` crates. If
//! anything in here grows logic of its own, it is wrong.
//!
//! Two halves ship together:
//!
//! 1. a **[`registry`]** of wrapped components — plain host Rust, fully unit-tested
//!    without a browser or a wasm toolchain;
//! 2. a thin **wasm-bindgen boundary** ([`wasm`], `cfg(target_arch = "wasm32")`) that
//!    mounts a chosen component onto a canvas and exposes read-back hooks.
//!
//! The crate is **host-agnostic**: it compiles to a `.wasm` and knows nothing about
//! whatever page eventually loads it.
//!
//! # The data seam
//!
//! Each [`Entry`] pairs a **fixture** builder with an optional [`DataFactory`]. The
//! fixture is a zero-config showcase; the data factory is the point:
//!
//! ```ignore
//! let r = facet_wrapped::builtins();
//! // Live — the caller's rows, rendered by the real component:
//! let view = r.build_with("table", &payload)?;
//! // Showcase — explicitly asked for:
//! let demo = r.build("table").unwrap();
//! ```
//!
//! [`Registry::build_with`] **refuses loudly** ([`EmbedError`]) rather than falling
//! back to a fixture. A registry that can only build fixtures cannot show a caller's
//! data, so the caller renders it itself — and that second renderer drifts from the
//! component immediately and invisibly. Canned data displayed as though it were live
//! is worse than an error, because it looks correct.
//!
//! # Payload contracts
//!
//! Three, one per family, each documented on its module:
//!
//! * [`map`] — points + ways carrying **raw OSM tags**, so the component classifies
//!   and styles them. The payload has no colour field, deliberately.
//! * [`graph`] — **one** `{nodes, edges}` document that all five facett graph crates
//!   accept. Semantics (`label`, `group`, `rel`) in; styling out.
//! * [`tabular`] — tables, the Iceberg browser, KPI grids, charts, matrices.
//!
//! The rule they share: **a caller supplies values; the component decides pixels.**

// The bundle-group features are declared by `facet-wrapped-group` (which shares this crate
// root), not here — see `groups`. Two warnings would otherwise be noise in both builds.
#![allow(unexpected_cfgs)]
#![cfg_attr(feature = "group-only", allow(dead_code))]

/// Moved to `facett-core` (2026-10-01) so facett-demo's pages bundle shares the policy
/// and the wording; re-exported so every `crate::adapter_retry` path still holds.
pub use facett_core::adapter_retry;
pub mod charts;
pub mod chrome;
pub mod forge;
pub mod devmode;
pub mod gpu;
pub mod graph;
pub mod map;
pub mod ops;
/// Browser bench harness (native only): a large graph in a real WebGPU browser.
#[cfg(not(target_arch = "wasm32"))]
pub mod browser_bench;
pub mod registry;
pub mod tabular;

pub use registry::{DataFactory, EmbedError, Entry, Registry};

/// The wasm-bindgen boundary (only compiled for the `wasm32` target).
#[cfg(target_arch = "wasm32")]
pub mod wasm;

/// The built-in [`Registry`] of every wrapped facett component — the one-call front
/// door for a host.
#[must_use]
pub fn builtins() -> Registry {
    Registry::with_builtins()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[allow(unexpected_cfgs)]
    #[cfg(not(feature = "group-only"))]
    fn the_front_door_matches_the_registry() {
        assert_eq!(builtins().len(), Registry::with_builtins().len());
        assert!(builtins().get("table").is_some());
        assert!(builtins().get("osm2d").is_some());
        assert!(builtins().get("graphnav").is_some());
    }
}

// ── BUNDLE GROUPS (2026-09-29): the entries outside the `core` group. ──
// This source is ALSO the crate root of `facet-wrapped-group` (its `[lib] path` points
// here), which declares the group features; `facet-wrapped` declares NONE, so the core
// bundle it builds stays byte-identical to main's — MEASURED: even an empty `[features]`
// table on facet-wrapped changes the release wasm (14 517 bytes, same size). Declared at
// the END of the file, and gated on the SAME lines in `registry.rs`, so no existing line
// moves (every panic `Location` the release wasm embeds stays put).
/// docview + manual (resvg/usvg): the `docs` group.
#[allow(unexpected_cfgs)]
#[cfg(feature = "docs")]
pub mod docs;
/// model3d (gltf; the mesh as base64 in the JSON payload): the `model3d` group.
#[allow(unexpected_cfgs)]
#[cfg(feature = "model3d")]
pub mod model;
/// The bundle groups: which group each entry belongs to, and this bundle's own group.
/// Not compiled into the core wasm (host builds, tests and group bundles only), so the
/// core bundle carries none of it.
#[allow(unexpected_cfgs)]
#[cfg(any(not(target_arch = "wasm32"), feature = "group-only"))]
pub mod groups;
/// simview (the population Simulate viewer over /power + /sim/api): the `sim` group.
#[allow(unexpected_cfgs)]
#[cfg(feature = "sim")]
pub mod sim;
/// The generator seam (`{"generate": …}`) and the two generator-first entries
/// (`universe`, `decograph`) — facett-demo's size + generator, in the wasm (lane F).
pub mod generated;