1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! `autofocus` global attribute — initial focus on app mount +
//! modal dialog open.
//!
//! ## Contract (from MDN)
//!
//! - `autofocus` is a global HTML attribute. When present on a
//! focusable element, the element receives focus:
//! - On page load (app mount, for us)
//! - When a `<dialog>` containing it is shown modally
//! - When an `<input>`-ish ancestor subtree is inserted
//! - Only the FIRST `[autofocus]` in document order wins per
//! activation — if multiple are set, later ones are ignored.
//! - `disabled` or otherwise non-focusable `[autofocus]` elements
//! are skipped.
//!
//! ## v1 scope
//!
//! - Mount: [`focus_first_autofocus`] walks the whole document
//! once and focuses the first eligible `[autofocus]` element.
//! Called from `App::build` after builtins install.
//! - Modal dialog: `runtime::builtins::dialog::show_modal` walks
//! the dialog subtree and focuses its first `[autofocus]`
//! descendant (see `dialog/mod.rs`).
//!
//! ## Not shipping in v1
//!
//! - Continuous mutation-observer-driven autofocus-on-subtree-
//! insert. Apps that add `[autofocus]` elements after mount
//! call [`focus_first_autofocus`] or [`focus_within`] manually.
//! - Any heuristic for "don't steal focus if user has already
//! interacted". Matches MDN's note that `autofocus` is
//! accessibility-risky — we honor the explicit opt-in without
//! second-guessing.
use NodeId;
use crateTuiDom;
use cratefocus;
use crateis_focusable;
/// Walk the whole document and focus the first focusable element
/// with an `autofocus` attribute. No-op when nothing matches or
/// when something else is already focused (to avoid clobbering
/// an earlier explicit `set_focused`).
/// Walk the subtree rooted at `root` and focus the first
/// focusable `[autofocus]` descendant. Used by
/// `dialog::show_modal` — modal dialogs should focus their
/// intended initial element without the app writing that boilerplate.
/// Depth-first, document-order walk starting at `id`. Returns the
/// first element with `[autofocus]` that's also focusable per the
/// C.1 rules.