Focus Module
The pure focus model: derive tab `order`, `traverse` it, and `route` a delivered key against the focused control.
Functions and values
| Function or value |
Description
|
|
Feature 108 (US1, FR-001..005): stamp `VisualState.Focused` on the single focusable control whose identity (`Key ?? structural path`, the feature-098 unification minted root "0", child `path + "." + index`, the SAME id `collectBoundsWith`/dispatch use) equals `focused`. Every other control is untouched; a control already carrying a consumer-set non-`Normal` state (e.g. `Disabled`) keeps it — `Focused` never overrides it (spec edge case). `None` returns the tree byte-identical — no stamp, at-rest output unchanged (SC-012). Reaches keyed AND unkeyed focusable controls (path makes same-kind siblings distinct, FR-002); structural/non-focusable elements are never stamped (FR-004); at most one control carries the ring (FR-003). Consumers reflect their own focus model by calling `markFocused model.Focused (view …)` in `view` (FR-005). Pure, total; never throws.
|
|
Derive the deterministic tab order from a lowered Control tree (FR-001): a pre-order walk that keeps controls whose `Accessibility.Keyboard.Focusable = true`, ordered by (FocusOrder ascending with None last, then document/pre-order index). A focusable control is a SINGLE stop — its subtree is not descended for further stops (a composite is one tab stop, clarified). Non-focusable controls never appear. Pure, total; never throws.
|
Full Usage:
route role keyboard navRange key isTab shift
Parameters:
AccessibilityRole
keyboard : KeyboardOperation
navRange : NavRange option
key : string
isTab : bool
shift : bool
Returns: KeyRouting
|
Route a normalized key against the focused control's `role` + KeyboardOperation (FR-003/FR-007; FR-001/FR-006 for the navigation classification). `key` is the normalized key name matched against Activation/NavigationKeys; `isTab`/`shift` describe a traversal candidate. The control's own consumption wins: membership in ActivationKeys -> Activate; membership in NavigationKeys is classified by `role` (+ the declared `navRange` for a value role) into a closed `NavIntent` -> `Navigate intent`; both are tested BEFORE the Tab test, so a control that lists a traversal key consumes it. A navigation key whose role/range cannot form an intent (e.g. a value role with no `navRange`) -> Fallthrough (FR-008 no-op). Only an unconsumed Tab/Shift+Tab -> Traverse (Next/Previous by `shift`). Otherwise Fallthrough. `route` is the SINGLE role-specific branch (FR-006); pure, total; never throws.
|
|
Pure traversal reduction (FR-002): (order, current focus, move) -> next focus. None + Next -> first; None + Previous -> last; wraps cyclically at both ends; a current id absent from the order resolves to the first stop (Next) / last stop (Previous), or None if the order is empty (stale-target recovery — clarified). Total/deterministic: identical inputs -> identical output.
|