Skip to main content

termwright_protocol/
roles.rs

1//! Closed vocabularies. Unknown members are rejected, never passed through.
2
3use serde::{Deserialize, Serialize};
4
5/// A v1 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 v1 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 v1 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 bounds for its nodes.
119    Bounds,
120    /// The published bounds are absolute viewport cells.
121    AbsoluteBounds,
122    /// Publishes state flags.
123    States,
124    /// Publishes action hints.
125    Actions,
126    /// Publishes offset-to-cell mappings.
127    TextRanges,
128    /// Emits a render-commit marker per revision.
129    RenderRevisions,
130    /// Can publish subtree diffs instead of full trees.
131    TreeDiffs,
132    /// Can forward application log records over the channel.
133    Logs,
134    /// Publishes protocol v2 evidence-qualified observations.
135    QualifiedObservations,
136    /// Publishes a complete exact fresh-pointer ownership grid.
137    PointerHitGrid,
138}
139
140/// Every v1 capability.
141pub const ADAPTER_CAPABILITIES: [&str; 11] = [
142    "tree",
143    "bounds",
144    "absolute-bounds",
145    "states",
146    "actions",
147    "text-ranges",
148    "render-revisions",
149    "tree-diffs",
150    "logs",
151    "qualified-observations",
152    "pointer-hit-grid",
153];
154
155/// Whether `role` is one of the v1 roles.
156pub fn valid_role(role: &str) -> bool {
157    SEMANTIC_ROLES.contains(&role)
158}
159
160/// Whether `action` is one of the v1 actions.
161pub fn valid_action(action: &str) -> bool {
162    SEMANTIC_ACTIONS.contains(&action)
163}
164
165/// Whether `capability` is one of the v1 capabilities.
166pub fn valid_capability(capability: &str) -> bool {
167    ADAPTER_CAPABILITIES.contains(&capability)
168}