facett-wasm-demo/examples/panel.rs
//! The **template** a `<repo>-demo` copies: one [`facett_core::Facet`] panel mounted as
//! a native window *and* a wasm/WebGL canvas by [`facett_wasm_demo`], with the state
//! hook exported for a headless drive. Swap `HelloPanel` for your panel (built from
//! your fixture) and you have a demo.
//!
//! - native: `cargo run -p facett-wasm-demo --example panel`
//! - wasm: `cargo build -p facett-wasm-demo --example panel --target wasm32-unknown-unknown`
//! then `wasm-bindgen … --target web` the artifact and serve it with the
//! `index.html` [`facett_wasm_demo::IndexHtml`] writes.
use facett_wasm_demo::FacetApp;
/// A trivial panel. Real panels come from the consumer's crate, built from a fixture;
/// the harness only needs a `Box<dyn Facet>`.
struct HelloPanel {
clicks: u32,
}
impl facett_core::Facet for HelloPanel {
fn title(&self) -> &str {
"hello"
}
fn ui(&mut self, ui: &mut egui::Ui) {
ui.heading("facett-wasm-demo");
ui.label("one panel, mounted on a canvas — native + web from the same code.");
if ui.button(format!("clicks: {}", self.clicks)).clicked() {
self.clicks += 1;
}
}
fn state_json(&self) -> serde_json::Value {
serde_json::json!({ "clicks": self.clicks })
}
}
fn panel() -> HelloPanel {
HelloPanel { clicks: 0 }
}
// ── native host ──────────────────────────────────────────────────────────────
#[cfg(not(target_arch = "wasm32"))]
fn main() -> eframe::Result<()> {
facett_wasm_demo::NativeDemo::new("facett-wasm-demo — panel template")
.run(move |_cc| FacetApp::boxed(Box::new(panel())))
}
// On wasm the entry point is `start` (below); `main` still has to exist to link.
#[cfg(target_arch = "wasm32")]
fn main() {}
// ── web host ─────────────────────────────────────────────────────────────────
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn start() {
facett_wasm_demo::WebDemo::new("demo_canvas")
.mount(move |_cc, _hash| FacetApp::boxed(Box::new(panel())));
}
/// The browser-readable state hook: `window.__demo_state()` returns the panel's live
/// `state_json`, so a headless Chromium drive verifies the shipped bundle without a human.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen(js_name = __demo_state)]
pub fn demo_state() -> String {
facett_wasm_demo::latest_state()
}