0.41.0: a control in a table cell is reached by stepping into the row
`27f2331e`. Thirty table rows across the MNW templates carry a control in a cell, in 25
files, and a terminal could draw every one of them and reach none. The reason is layout:
`makeover_tui::table` decides column widths, drops the columns a narrow window has no room
for and answers no coordinates back, so nothing in quasi-tui knows where in a row a button
ended up, and a focus order is a list of places the caret can stand.
Max ruled it on 2026-08-18: **the row is one focus stop, and a key enters it and cycles the
controls inside**. No coordinates, and no new public surface on a published makeover-tui.
Per-cell rects stay available underneath this later without changing what a user does.
The open half of the ruling was which key, and it is Right and Left. Enter is taken --
`Cells::activate` already means "this row opens", and every measured table with a control in
a cell also opens its rows -- and Right and Left are the keys a grid is walked with
everywhere else. They mean this before they mean the region they move: the caret standing on
a row with controls in it beats the screen-wide search that arm falls back to, so a table
inside a carousel steps between frames from any stop but that one. The smaller cost of the
two, because the frames are reachable from everywhere else and the row's controls are
reachable from nowhere else. Escape steps out before it dismisses or goes back, and the
short circuit is what keeps one press from doing two of the three.
`Spot::Row` gains `inside`, populated only for a table row: a list row's run is walked
straight after the row, so its controls are stops of their own and there is nothing to step
into. `View` gains the eighth thing a browser was quietly providing, `inside: Option<usize>`,
held beside `focus` rather than folded into it so that nothing counting reachable things has
to know a table is different. A control the caret has stepped onto draws with the focus
style inside the row's own highlight, which is what the two-step has instead of a ring
around a rect.
`focus.rs` and `draw_table` now decide a row's reachability with one function
(`row_reachable`) and pick the lit part from one list (`inside`), because that pair has
drifted before: the walk and the count disagreeing shifts every stop below the table by one.
A row that neither opens nor ticks is a stop now when its cells carry a control, which is the
third case and the one this task was filed for.
Not reachable inside a cell: a disabled control, as everywhere else, and an `Act::asks` that
wants boxes a cell has no room to draw -- a stop on that would fire it with nothing gathered.
quasi-webview and quasi-immediate need nothing. The browser builds the tab order from the
document, and egui's cell controls are real widgets it focuses itself.
18 files changed,
+618 insertions,
-93 deletions
| 3404 |
3404 |
|
|
| 3405 |
3405 |
|
[[package]]
|
| 3406 |
3406 |
|
name = "quasi"
|
| 3407 |
|
- |
version = "0.40.0"
|
|
3407 |
+ |
version = "0.41.0"
|
| 3408 |
3408 |
|
|
| 3409 |
3409 |
|
[[package]]
|
| 3410 |
3410 |
|
name = "quasi-axum"
|
| 3411 |
|
- |
version = "0.40.0"
|
|
3411 |
+ |
version = "0.41.0"
|
| 3412 |
3412 |
|
dependencies = [
|
| 3413 |
3413 |
|
"axum",
|
| 3414 |
3414 |
|
"http",
|
| 3422 |
3422 |
|
|
| 3423 |
3423 |
|
[[package]]
|
| 3424 |
3424 |
|
name = "quasi-basics"
|
| 3425 |
|
- |
version = "0.40.0"
|
|
3425 |
+ |
version = "0.41.0"
|
| 3426 |
3426 |
|
dependencies = [
|
| 3427 |
3427 |
|
"makeover-layout",
|
| 3428 |
3428 |
|
"quasi-http",
|
| 3432 |
3432 |
|
|
| 3433 |
3433 |
|
[[package]]
|
| 3434 |
3434 |
|
name = "quasi-bench"
|
| 3435 |
|
- |
version = "0.40.0"
|
|
3435 |
+ |
version = "0.41.0"
|
| 3436 |
3436 |
|
dependencies = [
|
| 3437 |
3437 |
|
"dhat",
|
| 3438 |
3438 |
|
"makeover",
|
| 3447 |
3447 |
|
|
| 3448 |
3448 |
|
[[package]]
|
| 3449 |
3449 |
|
name = "quasi-http"
|
| 3450 |
|
- |
version = "0.40.0"
|
|
3450 |
+ |
version = "0.41.0"
|
| 3451 |
3451 |
|
dependencies = [
|
| 3452 |
3452 |
|
"form_urlencoded",
|
| 3453 |
3453 |
|
"http",
|
| 3456 |
3456 |
|
|
| 3457 |
3457 |
|
[[package]]
|
| 3458 |
3458 |
|
name = "quasi-immediate"
|
| 3459 |
|
- |
version = "0.40.0"
|
|
3459 |
+ |
version = "0.41.0"
|
| 3460 |
3460 |
|
dependencies = [
|
| 3461 |
3461 |
|
"docengine",
|
| 3462 |
3462 |
|
"egui",
|
| 3466 |
3466 |
|
|
| 3467 |
3467 |
|
[[package]]
|
| 3468 |
3468 |
|
name = "quasi-notifs"
|
| 3469 |
|
- |
version = "0.40.0"
|
|
3469 |
+ |
version = "0.41.0"
|
| 3470 |
3470 |
|
dependencies = [
|
| 3471 |
3471 |
|
"quasi-router",
|
| 3472 |
3472 |
|
"synckit-config",
|
| 3474 |
3474 |
|
|
| 3475 |
3475 |
|
[[package]]
|
| 3476 |
3476 |
|
name = "quasi-router"
|
| 3477 |
|
- |
version = "0.40.0"
|
|
3477 |
+ |
version = "0.41.0"
|
| 3478 |
3478 |
|
dependencies = [
|
| 3479 |
3479 |
|
"makeover-layout",
|
| 3480 |
3480 |
|
]
|
| 3491 |
3491 |
|
|
| 3492 |
3492 |
|
[[package]]
|
| 3493 |
3493 |
|
name = "quasi-tauri"
|
| 3494 |
|
- |
version = "0.40.0"
|
|
3494 |
+ |
version = "0.41.0"
|
| 3495 |
3495 |
|
dependencies = [
|
| 3496 |
3496 |
|
"http",
|
| 3497 |
3497 |
|
"quasi-http",
|
| 3504 |
3504 |
|
|
| 3505 |
3505 |
|
[[package]]
|
| 3506 |
3506 |
|
name = "quasi-tui"
|
| 3507 |
|
- |
version = "0.40.0"
|
|
3507 |
+ |
version = "0.41.0"
|
| 3508 |
3508 |
|
dependencies = [
|
| 3509 |
3509 |
|
"docengine",
|
| 3510 |
3510 |
|
"makeover",
|
| 3516 |
3516 |
|
|
| 3517 |
3517 |
|
[[package]]
|
| 3518 |
3518 |
|
name = "quasi-webview"
|
| 3519 |
|
- |
version = "0.40.0"
|
|
3519 |
+ |
version = "0.41.0"
|
| 3520 |
3520 |
|
dependencies = [
|
| 3521 |
3521 |
|
"docengine",
|
| 3522 |
3522 |
|
"makeover-layout",
|
| 6187 |
6187 |
|
"winnow 1.0.4",
|
| 6188 |
6188 |
|
]
|
| 6189 |
6189 |
|
|
| 6190 |
|
- |
[[patch.unused]]
|
| 6191 |
|
- |
name = "makeover-build"
|
| 6192 |
|
- |
version = "0.47.0"
|
| 6193 |
|
- |
|
| 6194 |
|
- |
[[patch.unused]]
|
| 6195 |
|
- |
name = "quasi-type"
|
| 6196 |
|
- |
version = "0.1.0"
|
| 6197 |
|
- |
|
| 6198 |
|
- |
[[patch.unused]]
|
| 6199 |
|
- |
name = "synckit-client"
|
| 6200 |
|
- |
version = "0.8.0"
|
| 6201 |
|
- |
|
| 6202 |
6190 |
|
[[patch.unused]]
|
| 6203 |
6191 |
|
name = "kberg"
|
| 6204 |
6192 |
|
version = "0.1.0"
|
| 6214 |
6202 |
|
[[patch.unused]]
|
| 6215 |
6203 |
|
name = "tagtree"
|
| 6216 |
6204 |
|
version = "0.4.0"
|
|
6205 |
+ |
|
|
6206 |
+ |
[[patch.unused]]
|
|
6207 |
+ |
name = "quasi-type"
|
|
6208 |
+ |
version = "0.1.0"
|
|
6209 |
+ |
|
|
6210 |
+ |
[[patch.unused]]
|
|
6211 |
+ |
name = "synckit-client"
|
|
6212 |
+ |
version = "0.8.0"
|
|
6213 |
+ |
|
|
6214 |
+ |
[[patch.unused]]
|
|
6215 |
+ |
name = "makeover-build"
|
|
6216 |
+ |
version = "0.47.0"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-axum"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0" }
|
| 17 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.40.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0" }
|
|
17 |
+ |
quasi-http = { path = "../quasi-http", version = "0.41.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.40.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.41.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 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-basics"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0" }
|
| 17 |
17 |
|
makeover-layout = "0.31.0"
|
| 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.40.0" }
|
| 24 |
|
- |
quasi-http = { path = "../quasi-http", version = "0.40.0" }
|
|
23 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.41.0" }
|
|
24 |
+ |
quasi-http = { path = "../quasi-http", version = "0.41.0" }
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-bench"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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 |
22 |
|
count = ["dep:dhat"]
|
| 23 |
23 |
|
|
| 24 |
24 |
|
[dependencies]
|
| 25 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0" }
|
| 26 |
|
- |
quasi-webview = { path = "../quasi-webview", version = "0.40.0" }
|
| 27 |
|
- |
quasi-tui = { path = "../quasi-tui", version = "0.40.0" }
|
|
25 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0" }
|
|
26 |
+ |
quasi-webview = { path = "../quasi-webview", version = "0.41.0" }
|
|
27 |
+ |
quasi-tui = { path = "../quasi-tui", version = "0.41.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.40.0" }
|
|
31 |
+ |
quasi-http = { path = "../quasi-http", version = "0.41.0" }
|
| 32 |
32 |
|
makeover-layout = "0.31.0"
|
| 33 |
33 |
|
makeover-tui = { version = "0.30.0", features = ["theme"] }
|
| 34 |
34 |
|
# Only to load a bundled theme file. `makeover_tui::Theme` is `#[non_exhaustive]`,
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-http"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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 |
13 |
|
workspace = true
|
| 14 |
14 |
|
|
| 15 |
15 |
|
[dependencies]
|
| 16 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0" }
|
|
16 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0" }
|
| 17 |
17 |
|
http = "1.3.1"
|
| 18 |
18 |
|
form_urlencoded = "1.2.2"
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-immediate"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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"
|
| 12 |
12 |
|
categories = ["gui"]
|
| 13 |
13 |
|
|
| 14 |
14 |
|
[dependencies]
|
| 15 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0" }
|
|
15 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0" }
|
| 16 |
16 |
|
# The node drawing, which is the makeover layer's and not this crate's. Every
|
| 17 |
17 |
|
# widget here that is not a container comes from it: a screen walk that painted
|
| 18 |
18 |
|
# its own meter would be the divergence the suite exists to end, one copy per
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-notifs"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.0"
|
| 4 |
4 |
|
description = "Declared notification kinds and the registry that holds them: what a notification says and what it is for, apart from how it reaches a person"
|
| 5 |
5 |
|
edition.workspace = true
|
| 6 |
6 |
|
rust-version.workspace = true
|
| 24 |
24 |
|
describe = ["dep:quasi-router"]
|
| 25 |
25 |
|
|
| 26 |
26 |
|
[dependencies]
|
| 27 |
|
- |
quasi-router = { path = "../quasi-router", version = "0.40.0", optional = true }
|
|
27 |
+ |
quasi-router = { path = "../quasi-router", version = "0.41.0", optional = true }
|
| 28 |
28 |
|
synckit-config = { git = "https://makenot.work/git/max/synckit.git", version = "0.2", optional = true }
|
| 1 |
1 |
|
[package]
|
| 2 |
2 |
|
name = "quasi-router"
|
| 3 |
|
- |
version = "0.40.0"
|
|
3 |
+ |
version = "0.41.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
|