Skip to main content

max / quasi

0.9.0: the egui renderer draws the two nodes it had been panicking on Node::Image arrived in 0.4.0 and Node::Timeline in 0.6.0. quasi-immediate took neither, compiled clean through both, and panicked the frame on any screen carrying one. The guarantee that was meant to stop this is quoted verbatim in draw()'s own doc comment: Node has no #[non_exhaustive] so that a member added to the vocabulary stops every renderer compiling. The walk is split in two for the table's sake, and the split ended `other => container(..)` — a wildcard however it reads. Both new members fell through it to container's unreachable!. Fixed on both halves. draw() names its containers one by one, so neither arm ends in a wildcard and the next member stops the build. And the test that claimed to draw one of everything was nine members short; it now walks a list a second test counts, since Node cannot be iterated and nothing else stops the list going stale the way it did through two releases. The drawing. A picture is egui::Image at the source quasi holds and the description deliberately does not, with the alt text where the bytes do not arrive and the intrinsic dimensions sizing the box before they do, so nothing below it moves when the texture lands. Fit::Cover is the one member not honoured: cropping needs a box to crop to and a node in an egui vertical flow has a width and an unbounded height. Filed rather than faked. A track is a ruler and greedy first-fit lanes, the webview's packing against the same Placed::overlaps. A tick is one line of text tall, which is the least that lets the axis label itself, and every other measure falls out of it. Labels read layout::Unit, so a day strip counts days from one rather than printing 00:00 over a month. focus scrolls once per moment and not once per frame, or the track is one the user cannot scroll away from. Also: quasi_router re-exports Placed, which every sibling in Node's shape already had. quasi-immediate takes the publish = false guard the other nine carry, and drops a readme key naming a file that is not there.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-15 18:44 UTC
Signed with PGP, not checked
Commit: ceb451aeae68d9b016230016e2c75a2bf18deb9e
Parent: 45e114e
14 files changed, +473 insertions, -59 deletions
M Cargo.lock +18 -18
@@ -3092,11 +3092,11 @@
3092 3092
3093 3093 [[package]]
3094 3094 name = "quasi"
3095 - version = "0.8.0"
3095 + version = "0.9.0"
3096 3096
3097 3097 [[package]]
3098 3098 name = "quasi-axum"
3099 - version = "0.8.0"
3099 + version = "0.9.0"
3100 3100 dependencies = [
3101 3101 "axum",
3102 3102 "http",
@@ -3110,7 +3110,7 @@
3110 3110
3111 3111 [[package]]
3112 3112 name = "quasi-basics"
3113 - version = "0.8.0"
3113 + version = "0.9.0"
3114 3114 dependencies = [
3115 3115 "makeover-layout",
3116 3116 "quasi-http",
@@ -3120,7 +3120,7 @@
3120 3120
3121 3121 [[package]]
3122 3122 name = "quasi-bench"
3123 - version = "0.8.0"
3123 + version = "0.9.0"
3124 3124 dependencies = [
3125 3125 "dhat",
3126 3126 "makeover",
@@ -3135,7 +3135,7 @@
3135 3135
3136 3136 [[package]]
3137 3137 name = "quasi-http"
3138 - version = "0.8.0"
3138 + version = "0.9.0"
3139 3139 dependencies = [
3140 3140 "form_urlencoded",
3141 3141 "http",
@@ -3144,7 +3144,7 @@
3144 3144
3145 3145 [[package]]
3146 3146 name = "quasi-immediate"
3147 - version = "0.8.0"
3147 + version = "0.9.0"
3148 3148 dependencies = [
3149 3149 "docengine",
3150 3150 "egui",
@@ -3154,7 +3154,7 @@
3154 3154
3155 3155 [[package]]
3156 3156 name = "quasi-router"
3157 - version = "0.8.0"
3157 + version = "0.9.0"
3158 3158 dependencies = [
3159 3159 "makeover-layout",
3160 3160 ]
@@ -3171,7 +3171,7 @@
3171 3171
3172 3172 [[package]]
3173 3173 name = "quasi-tauri"
3174 - version = "0.8.0"
3174 + version = "0.9.0"
3175 3175 dependencies = [
3176 3176 "http",
3177 3177 "quasi-http",
@@ -3182,7 +3182,7 @@
3182 3182
3183 3183 [[package]]
3184 3184 name = "quasi-tui"
3185 - version = "0.8.0"
3185 + version = "0.9.0"
3186 3186 dependencies = [
3187 3187 "docengine",
3188 3188 "makeover",
@@ -3194,7 +3194,7 @@
3194 3194
3195 3195 [[package]]
3196 3196 name = "quasi-webview"
3197 - version = "0.8.0"
3197 + version = "0.9.0"
3198 3198 dependencies = [
3199 3199 "docengine",
3200 3200 "makeover-layout",
@@ -5624,14 +5624,6 @@
5624 5624 source = "registry+https://github.com/rust-lang/crates.io-index"
5625 5625 checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
5626 5626
5627 - [[patch.unused]]
5628 - name = "synckit-client"
5629 - version = "0.8.0"
5630 -
5631 - [[patch.unused]]
5632 - name = "synckit-config"
5633 - version = "0.2.0"
5634 -
5635 5627 [[patch.unused]]
5636 5628 name = "kberg"
5637 5629 version = "0.1.0"
@@ -5647,3 +5639,11 @@
5647 5639 [[patch.unused]]
5648 5640 name = "tagtree"
5649 5641 version = "0.4.0"
5642 +
5643 + [[patch.unused]]
5644 + name = "synckit-client"
5645 + version = "0.8.0"
5646 +
5647 + [[patch.unused]]
5648 + name = "synckit-config"
5649 + version = "0.2.0"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-axum"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 description = "The axum host adapter for quasi-router: an HTTP request in, a rendered description out"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,14 +13,14 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.8.0" }
17 - quasi-http = { path = "../quasi-http", version = "0.8.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.9.0" }
17 + quasi-http = { path = "../quasi-http", version = "0.9.0" }
18 18 axum = "0.8.8"
19 19 http = "1.3.1"
20 20 tokio = { version = "1.50.0", features = ["rt"] }
21 21
22 22 [dev-dependencies]
23 - quasi-webview = { path = "../quasi-webview", version = "0.8.0" }
23 + quasi-webview = { path = "../quasi-webview", version = "0.9.0" }
24 24 tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread"] }
25 25 tower = { version = "0.5.3", features = ["util"] }
26 26 http-body-util = "0.1.3"
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-basics"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 description = "The first-party widget set: named assemblies of primitives, shared across our apps"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,12 +13,12 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.8.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.9.0" }
17 17 makeover-layout = "0.26.1"
18 18
19 19 [dev-dependencies]
20 20 # A widget's guarantees are claims about what a renderer draws, so they are
21 21 # tested against a real one rather than by walking the tree the assembly just
22 22 # built. The webview is the renderer that recognises names today.
23 - quasi-webview = { path = "../quasi-webview", version = "0.8.0" }
24 - quasi-http = { path = "../quasi-http", version = "0.8.0" }
23 + quasi-webview = { path = "../quasi-webview", version = "0.9.0" }
24 + quasi-http = { path = "../quasi-http", version = "0.9.0" }
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-bench"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 description = "What a described screen costs to render, in time and in allocations"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -22,13 +22,13 @@
22 22 count = ["dep:dhat"]
23 23
24 24 [dependencies]
25 - quasi-router = { path = "../quasi-router", version = "0.8.0" }
26 - quasi-webview = { path = "../quasi-webview", version = "0.8.0" }
27 - quasi-tui = { path = "../quasi-tui", version = "0.8.0" }
25 + quasi-router = { path = "../quasi-router", version = "0.9.0" }
26 + quasi-webview = { path = "../quasi-webview", version = "0.9.0" }
27 + quasi-tui = { path = "../quasi-tui", version = "0.9.0" }
28 28 # `Serves` is the trait carrying `screen` and `fragment`, which is what the
29 29 # webview is measured through. Taken directly rather than through quasi-webview
30 30 # because a bench calling a trait method should name the trait it calls.
31 - quasi-http = { path = "../quasi-http", version = "0.8.0" }
31 + quasi-http = { path = "../quasi-http", version = "0.9.0" }
32 32 makeover-layout = "0.26.1"
33 33 makeover-tui = { version = "0.24.0", features = ["theme"] }
34 34 # Only to load a bundled theme file. `makeover_tui::Theme` is `#[non_exhaustive]`,
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-http"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 description = "The http-shaped seam quasi's webview host adapters share: decoding in, a rendered description out"
5 5 edition.workspace = true
6 6 rust-version.workspace = true
@@ -13,6 +13,6 @@
13 13 workspace = true
14 14
15 15 [dependencies]
16 - quasi-router = { path = "../quasi-router", version = "0.8.0" }
16 + quasi-router = { path = "../quasi-router", version = "0.9.0" }
17 17 http = "1.3.1"
18 18 form_urlencoded = "1.2.2"
@@ -1,16 +1,18 @@
1 1 [package]
2 2 name = "quasi-immediate"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 edition = "2024"
5 5 description = "The immediate-mode renderer for quasi-router: a described screen in, an egui frame out. Immediate mode is the constraint that matters, not the library."
6 6 license = "MIT"
7 + # Unpublished like every crate here: it takes `quasi-router`, which is
8 + # `publish = false` deliberately so the screen tree can churn.
9 + publish = false
7 10 repository = "https://makenot.work/git/max/quasi"
8 - readme = "README.md"
9 11 keywords = ["egui", "gui", "immediate-mode", "renderer"]
10 12 categories = ["gui"]
11 13
12 14 [dependencies]
13 - quasi-router = { path = "../quasi-router", version = "0.8.0" }
15 + quasi-router = { path = "../quasi-router", version = "0.9.0" }
14 16 # The node drawing, which is the makeover layer's and not this crate's. Every
15 17 # widget here that is not a container comes from it: a screen walk that painted
16 18 # its own meter would be the divergence the suite exists to end, one copy per
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "quasi-router"
3 - version = "0.8.0"
3 + version = "0.9.0"
4 4 description = "Host-agnostic router: a request in, a renderer-agnostic description out"
5 5 edition.workspace = true
6 6 rust-version.workspace = true