use wasm_bindgen::prelude::*; #[derive(Default)] struct Router { url: Option, route: Option, subscription: Option, } enum Message { Subscribe, Navigate(draco::router::Url), NoOp, } impl Default for Message { fn default() -> Self { Message::NoOp } } #[derive(Debug)] enum Route { Index, PostIndex { sort: Option }, PostShow { id: i32, hash: Option }, } impl Route { fn new(url: &draco::router::Url) -> Option { use draco::router::*; parse(url) // / .alt((), |()| Route::Index) // /posts // /posts?sort=some-string .alt(("posts", query("sort").optional()), |((), sort)| { Route::PostIndex { sort } }) // /posts/123 // /posts/123#some-string .alt(("posts", param()), |((), id)| Route::PostShow { id, hash: url.hash.clone(), }) .value() } } impl draco::App for Router { type Message = Message; fn update(&mut self, mailbox: &draco::Mailbox, message: Self::Message) { match message { Message::Subscribe => { self.subscription = Some(mailbox.subscribe( draco::router::Router::new(draco::router::Mode::Hash), Message::Navigate, )); } Message::Navigate(url) => { self.route = Route::new(&url); self.url = Some(url); } Message::NoOp => {} } } fn render(&self) -> draco::Node { use draco::html as h; use draco::router::Mode::Hash; let links = [ "/", "/posts", "/posts?sort=id", "/posts?sort=title", "/posts/1", "/posts/1#section-1", "/posts/2", "/posts/2#section-1", ]; h::div() .push(h::div().push(format!("Url: {:?}", &self.url))) .push(h::div().push(format!("Route: {:?}", &self.route))) .append(links.iter().map(|link| { h::h2() .push( h::span().push( draco::router::link(Hash, link) .push(link.to_string()) .attr("style", "margin-right: .5rem;"), ), ) .push(h::button().push("Push").on("click", { let link = link.clone(); move |_| { draco::router::push(Hash, link); Message::NoOp } })) .push(h::button().push("Replace").on("click", { let link = link.clone(); move |_| { draco::router::replace(Hash, link); Message::NoOp } })) })) .into() } } #[wasm_bindgen] pub fn start() { let mailbox = draco::start( Router::default(), draco::select("main").expect("main").into(), ); mailbox.send(Message::Subscribe); } pub fn main() {}