termwright_protocol/roles.rs
1//! Closed vocabularies. Unknown members are rejected, never passed through.
2
3use serde::{Deserialize, Serialize};
4
5/// A semantic role. ARIA-aligned and closed: unknown roles fail validation.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Role {
9 /// The application as a whole.
10 Application,
11 /// A grouping container with no stronger meaning.
12 Region,
13 /// A dialog, modal or not.
14 Dialog,
15 /// An urgent message.
16 Alert,
17 /// A non-urgent status message.
18 Status,
19 /// A collection of items.
20 List,
21 /// One entry in a list.
22 #[serde(rename = "listitem")]
23 ListItem,
24 /// A menu of commands.
25 Menu,
26 /// One command in a menu.
27 #[serde(rename = "menuitem")]
28 MenuItem,
29 /// An activatable control.
30 Button,
31 /// A two- or three-state toggle.
32 Checkbox,
33 /// One option in a mutually exclusive set.
34 Radio,
35 /// One tab in a tab strip.
36 Tab,
37 /// An editable text field.
38 Textbox,
39 /// A section heading.
40 Heading,
41 /// Static text.
42 Text,
43 /// Progress towards completion.
44 #[serde(rename = "progressbar")]
45 ProgressBar,
46 /// A visual divider.
47 Separator,
48 /// A scroll position indicator.
49 Scrollbar,
50 /// A grid of rows and cells.
51 Table,
52 /// One row of a table.
53 Row,
54 /// One cell of a table row.
55 Cell,
56 /// No more specific role applies.
57 Generic,
58}
59
60/// Every role, in the order the reference implementation declares them.
61pub const SEMANTIC_ROLES: [&str; 23] = [
62 "application",
63 "region",
64 "dialog",
65 "alert",
66 "status",
67 "list",
68 "listitem",
69 "menu",
70 "menuitem",
71 "button",
72 "checkbox",
73 "radio",
74 "tab",
75 "textbox",
76 "heading",
77 "text",
78 "progressbar",
79 "separator",
80 "scrollbar",
81 "table",
82 "row",
83 "cell",
84 "generic",
85];
86
87/// A descriptive capability hint: a diagnostic, never a callback endpoint.
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
89#[serde(rename_all = "camelCase")]
90pub enum Action {
91 /// The node can take focus.
92 Focus,
93 /// The node can be activated (pressed, chosen).
94 Activate,
95 /// The node's checked state can be flipped.
96 Toggle,
97 /// The node's value can be replaced.
98 SetValue,
99 /// The node's viewport can be scrolled.
100 Scroll,
101 /// The node can be selected within its set.
102 Select,
103 /// The node can be expanded or collapsed.
104 Expand,
105}
106
107/// Every action.
108pub const SEMANTIC_ACTIONS: [&str; 7] = [
109 "focus", "activate", "toggle", "setValue", "scroll", "select", "expand",
110];
111
112/// Something the adapter tells the driver it can provide.
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
114#[serde(rename_all = "kebab-case")]
115pub enum Capability {
116 /// Publishes a node tree.
117 Tree,
118 /// Publishes authoritative intended layout geometry for every applicable node.
119 IntendedGeometry,
120 /// Publishes authoritative clipped geometry for every applicable node.
121 ClippedGeometry,
122 /// Publishes state flags.
123 States,
124 /// Publishes authoritative focus state.
125 FocusState,
126 /// Publishes action hints.
127 Actions,
128 /// Publishes physical input recipes.
129 ActionRecipes,
130 /// Publishes offset-to-cell mappings.
131 TextRanges,
132 /// Emits a render-commit marker per revision.
133 RenderRevisions,
134 /// Can forward application log records over the channel.
135 Logs,
136 /// Publishes a complete exact fresh-pointer ownership grid.
137 PointerHitGrid,
138 /// Publishes revision-based semantic deltas after an initial full tree.
139 IncrementalTree,
140}
141
142/// Every adapter capability.
143pub const ADAPTER_CAPABILITIES: [&str; 12] = [
144 "tree",
145 "intended-geometry",
146 "clipped-geometry",
147 "states",
148 "focus-state",
149 "actions",
150 "action-recipes",
151 "text-ranges",
152 "render-revisions",
153 "logs",
154 "pointer-hit-grid",
155 "incremental-tree",
156];
157
158/// Whether `role` is one of the roles.
159pub fn valid_role(role: &str) -> bool {
160 SEMANTIC_ROLES.contains(&role)
161}
162
163/// Whether `action` is one of the actions.
164pub fn valid_action(action: &str) -> bool {
165 SEMANTIC_ACTIONS.contains(&action)
166}
167
168/// Whether `capability` is one of the capabilities.
169pub fn valid_capability(capability: &str) -> bool {
170 ADAPTER_CAPABILITIES.contains(&capability)
171}