@obinexusltd/obix-driver-accessibility-tree 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +380 -0
- package/dist/accessibility-tree-mirror.d.ts +26 -0
- package/dist/accessibility-tree-mirror.d.ts.map +1 -0
- package/dist/accessibility-tree-mirror.js +173 -0
- package/dist/accessibility-tree-mirror.js.map +1 -0
- package/dist/aria-widget-compliance.d.ts +42 -0
- package/dist/aria-widget-compliance.d.ts.map +1 -0
- package/dist/aria-widget-compliance.js +291 -0
- package/dist/aria-widget-compliance.js.map +1 -0
- package/dist/axe-core-integration.d.ts +30 -0
- package/dist/axe-core-integration.d.ts.map +1 -0
- package/dist/axe-core-integration.js +85 -0
- package/dist/axe-core-integration.js.map +1 -0
- package/dist/focus-management.d.ts +26 -0
- package/dist/focus-management.d.ts.map +1 -0
- package/dist/focus-management.js +138 -0
- package/dist/focus-management.js.map +1 -0
- package/dist/framework-integration.d.ts +45 -0
- package/dist/framework-integration.d.ts.map +1 -0
- package/dist/framework-integration.js +110 -0
- package/dist/framework-integration.js.map +1 -0
- package/dist/index.d.ts +12 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +154 -15
- package/dist/index.js.map +1 -1
- package/dist/keyboard-navigation.d.ts +29 -0
- package/dist/keyboard-navigation.d.ts.map +1 -0
- package/dist/keyboard-navigation.js +182 -0
- package/dist/keyboard-navigation.js.map +1 -0
- package/dist/live-region-manager.d.ts +25 -0
- package/dist/live-region-manager.d.ts.map +1 -0
- package/dist/live-region-manager.js +123 -0
- package/dist/live-region-manager.js.map +1 -0
- package/dist/screen-reader-bridge.d.ts +25 -0
- package/dist/screen-reader-bridge.d.ts.map +1 -0
- package/dist/screen-reader-bridge.js +71 -0
- package/dist/screen-reader-bridge.js.map +1 -0
- package/dist/semantic-html-enhancer.d.ts +36 -0
- package/dist/semantic-html-enhancer.d.ts.map +1 -0
- package/dist/semantic-html-enhancer.js +140 -0
- package/dist/semantic-html-enhancer.js.map +1 -0
- package/dist/state-properties-manager.d.ts +19 -0
- package/dist/state-properties-manager.d.ts.map +1 -0
- package/dist/state-properties-manager.js +94 -0
- package/dist/state-properties-manager.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +9 -1
package/README.md
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# @obinexusltd/obix-driver-accessibility-tree
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@obinexusltd/obix-driver-accessibility-tree)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
A full-featured accessibility driver for the [OBIX SDK](https://github.com/OBINexusComputing/obix-sdk). Solves 10 core browser accessibility problems: live region management, screen reader detection, accessibility tree mirroring, ARIA widget compliance, semantic HTML enhancement, keyboard navigation, ARIA state management, focus trapping, axe-core validation, and framework-level interaction mode detection.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @obinexusltd/obix-driver-accessibility-tree
|
|
12
|
+
|
|
13
|
+
# Optional: enable axe-core validation
|
|
14
|
+
npm install axe-core
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createAccessibilityTreeDriver } from '@obinexusltd/obix-driver-accessibility-tree';
|
|
21
|
+
|
|
22
|
+
const driver = createAccessibilityTreeDriver({
|
|
23
|
+
rootElement: document.getElementById('app')!,
|
|
24
|
+
liveRegionDefaults: { level: 'polite', atomic: true },
|
|
25
|
+
screenReaderHints: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await driver.initialize();
|
|
29
|
+
|
|
30
|
+
// Announce a message to screen readers
|
|
31
|
+
driver.announce('Your changes have been saved.', 'polite');
|
|
32
|
+
|
|
33
|
+
// Trap focus inside a dialog
|
|
34
|
+
const trap = driver.focusManager.createFocusTrap(dialogElement);
|
|
35
|
+
trap.activate();
|
|
36
|
+
|
|
37
|
+
// Clean up
|
|
38
|
+
await driver.destroy();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API Reference
|
|
42
|
+
|
|
43
|
+
### Driver Lifecycle
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const driver = createAccessibilityTreeDriver(config?: AccessibilityTreeDriverConfig);
|
|
47
|
+
|
|
48
|
+
await driver.initialize(); // Lazy-initialize all sub-features
|
|
49
|
+
await driver.destroy(); // Tear down all features and release resources
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Config options:**
|
|
53
|
+
|
|
54
|
+
| Field | Type | Default | Description |
|
|
55
|
+
|-------|------|---------|-------------|
|
|
56
|
+
| `rootElement` | `HTMLElement` | `document.body` | Root element to observe |
|
|
57
|
+
| `liveRegionDefaults.level` | `'off' \| 'polite' \| 'assertive'` | `'polite'` | Default aria-live level |
|
|
58
|
+
| `liveRegionDefaults.atomic` | `boolean` | `false` | Default aria-atomic value |
|
|
59
|
+
| `liveRegionDefaults.relevant` | `string` | `'additions text'` | Default aria-relevant value |
|
|
60
|
+
| `liveRegionDefaults.label` | `string` | `undefined` | Default aria-label for regions |
|
|
61
|
+
| `screenReaderHints` | `boolean` | `false` | Enable screen reader detection heuristics |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### Live Region Manager
|
|
66
|
+
|
|
67
|
+
Manages `aria-live` regions for dynamic content announcements. Creates visually hidden elements that are accessible to screen readers.
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Access after initialize()
|
|
71
|
+
const { liveRegions } = driver;
|
|
72
|
+
|
|
73
|
+
// Create a named live region
|
|
74
|
+
const region = liveRegions.createRegion('status', { level: 'polite', atomic: true });
|
|
75
|
+
|
|
76
|
+
// Announce via a specific region
|
|
77
|
+
region.announce('Item deleted.');
|
|
78
|
+
|
|
79
|
+
// Announce globally (uses the default region)
|
|
80
|
+
liveRegions.announceGlobal('Page loaded.', 'assertive');
|
|
81
|
+
|
|
82
|
+
// Inspect active regions
|
|
83
|
+
const active = liveRegions.getActiveRegions();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### Screen Reader Bridge
|
|
89
|
+
|
|
90
|
+
Browser-safe screen reader detection using media queries (no intrusive heuristics). Creates dedicated regions for polite, assertive, and route-change announcements.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const { screenReaderBridge } = driver;
|
|
94
|
+
|
|
95
|
+
// Detect screen reader signals
|
|
96
|
+
const result = screenReaderBridge.detect();
|
|
97
|
+
result.likely; // boolean — screen reader probably active
|
|
98
|
+
result.signals; // string[] — detected signals (forced-colors, prefers-contrast, etc.)
|
|
99
|
+
|
|
100
|
+
// Make announcements
|
|
101
|
+
screenReaderBridge.announcePolite('Form submitted successfully.');
|
|
102
|
+
screenReaderBridge.announceAssertive('Error: required field missing.');
|
|
103
|
+
screenReaderBridge.announceRouteChange('/dashboard');
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### Accessibility Tree Mirror
|
|
109
|
+
|
|
110
|
+
Real-time DOM-to-accessibility-tree synchronization via `MutationObserver`. Maps HTML semantics to ARIA roles and diffs the tree on every mutation.
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const { treeMirror } = driver;
|
|
114
|
+
|
|
115
|
+
// Start observing
|
|
116
|
+
treeMirror.observe(document.getElementById('app')!);
|
|
117
|
+
|
|
118
|
+
// Snapshot the current tree
|
|
119
|
+
const tree = treeMirror.snapshot();
|
|
120
|
+
|
|
121
|
+
// Diff since last snapshot
|
|
122
|
+
const changes = treeMirror.diff();
|
|
123
|
+
|
|
124
|
+
// Serialize to JSON
|
|
125
|
+
const json = treeMirror.serialize();
|
|
126
|
+
|
|
127
|
+
// React to tree changes
|
|
128
|
+
treeMirror.onTreeChange((changes) => {
|
|
129
|
+
console.log('tree updated', changes);
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### ARIA Widget Compliance
|
|
136
|
+
|
|
137
|
+
W3C ARIA Authoring Practices pattern validation and auto-configuration. Applies correct ARIA attributes for common widget patterns.
|
|
138
|
+
|
|
139
|
+
**Supported patterns:**
|
|
140
|
+
|
|
141
|
+
| Pattern | Widget Type |
|
|
142
|
+
|---------|-------------|
|
|
143
|
+
| `accordion` | Expandable sections |
|
|
144
|
+
| `menu-bar` | Horizontal menu |
|
|
145
|
+
| `slider` | Range input |
|
|
146
|
+
| `tabs` | Tab panel group |
|
|
147
|
+
| `dialog` | Modal dialog |
|
|
148
|
+
| `listbox` | Selection list |
|
|
149
|
+
| `tree` | Hierarchical list |
|
|
150
|
+
| `combobox` | Autocomplete input |
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const { widgetCompliance } = driver;
|
|
154
|
+
|
|
155
|
+
// Apply a pattern to an element
|
|
156
|
+
widgetCompliance.applyPattern(element, 'tabs');
|
|
157
|
+
|
|
158
|
+
// Validate an element against its declared pattern
|
|
159
|
+
const result = widgetCompliance.validate(element);
|
|
160
|
+
result.valid; // boolean
|
|
161
|
+
result.errors; // string[]
|
|
162
|
+
result.warnings; // string[]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
### Semantic HTML Enhancer
|
|
168
|
+
|
|
169
|
+
Auto-injects missing ARIA attributes based on built-in rules. Detects and fixes common accessibility issues such as clickable `div` elements without a role, missing `alt` text, and unlabeled inputs.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
const { semanticEnhancer } = driver;
|
|
173
|
+
|
|
174
|
+
// One-shot scan of the root element
|
|
175
|
+
const report = semanticEnhancer.scan();
|
|
176
|
+
report.fixed; // number — attributes auto-applied
|
|
177
|
+
report.skipped; // number — elements that needed manual review
|
|
178
|
+
|
|
179
|
+
// Continuously observe and fix new content
|
|
180
|
+
semanticEnhancer.observe(document.body);
|
|
181
|
+
|
|
182
|
+
// Add a custom rule
|
|
183
|
+
semanticEnhancer.addRule({
|
|
184
|
+
selector: '[data-tooltip]',
|
|
185
|
+
apply: (el) => { el.setAttribute('aria-describedby', el.dataset.tooltip!); },
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Inspect the built-in rule set
|
|
189
|
+
const rules = semanticEnhancer.getBuiltinRules();
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Keyboard Navigation Controller
|
|
195
|
+
|
|
196
|
+
Implements ARIA keyboard navigation patterns with arrow-key movement, Home/End support, and optional type-ahead.
|
|
197
|
+
|
|
198
|
+
**Supported patterns:** `roving-tabindex`, `activedescendant`, `grid`
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const { keyboardNav } = driver;
|
|
202
|
+
|
|
203
|
+
// Create a named navigation context
|
|
204
|
+
const nav = keyboardNav.createNavigation('my-listbox', {
|
|
205
|
+
pattern: 'roving-tabindex',
|
|
206
|
+
orientation: 'vertical',
|
|
207
|
+
wrap: true,
|
|
208
|
+
typeAhead: true,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
nav.mount(containerElement);
|
|
212
|
+
|
|
213
|
+
// Programmatic movement
|
|
214
|
+
nav.moveTo(itemElement);
|
|
215
|
+
nav.moveNext();
|
|
216
|
+
nav.movePrev();
|
|
217
|
+
nav.moveFirst();
|
|
218
|
+
nav.moveLast();
|
|
219
|
+
|
|
220
|
+
const current = nav.getCurrentItem();
|
|
221
|
+
|
|
222
|
+
nav.unmount();
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### ARIA State Manager
|
|
228
|
+
|
|
229
|
+
Reactive ARIA state management with batch update support. Tracks element-to-state mappings and emits change events.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const { stateManager } = driver;
|
|
233
|
+
|
|
234
|
+
// Set ARIA state on an element
|
|
235
|
+
stateManager.setState(buttonEl, { expanded: true, disabled: false });
|
|
236
|
+
|
|
237
|
+
// Read current state
|
|
238
|
+
const state = stateManager.getState(buttonEl);
|
|
239
|
+
|
|
240
|
+
// Read all tracked states
|
|
241
|
+
const all = stateManager.getAllStates();
|
|
242
|
+
|
|
243
|
+
// Subscribe to changes
|
|
244
|
+
const unsubscribe = stateManager.onStateChange((element, newState) => {
|
|
245
|
+
console.log('state changed', element, newState);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
unsubscribe(); // remove listener
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### Focus Management
|
|
254
|
+
|
|
255
|
+
Programmatic focus control with a save/restore stack and focus trap support. Escape key automatically deactivates traps.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
const { focusManager } = driver;
|
|
259
|
+
|
|
260
|
+
// Move focus to an element
|
|
261
|
+
focusManager.moveFocus(targetElement);
|
|
262
|
+
|
|
263
|
+
// Save the current focus position
|
|
264
|
+
focusManager.saveFocus();
|
|
265
|
+
|
|
266
|
+
// Restore last saved focus
|
|
267
|
+
focusManager.restoreFocus();
|
|
268
|
+
|
|
269
|
+
// Create and activate a focus trap (e.g. inside a modal)
|
|
270
|
+
const trap = focusManager.createFocusTrap(dialogElement);
|
|
271
|
+
trap.activate(); // Tab/Shift+Tab cycle inside dialogElement, Escape deactivates
|
|
272
|
+
trap.deactivate(); // Release trap and return focus to trigger
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
### axe-core Integration
|
|
278
|
+
|
|
279
|
+
Optional runtime ARIA validation using axe-core (peer dependency). Lazy-loads axe-core on first use; runs 18 default ARIA-specific rules.
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// Requires: npm install axe-core
|
|
283
|
+
const { axeIntegration } = driver;
|
|
284
|
+
|
|
285
|
+
// Check if axe-core is available
|
|
286
|
+
const available = await axeIntegration.isAvailable();
|
|
287
|
+
|
|
288
|
+
// Run on the whole document
|
|
289
|
+
const results = await axeIntegration.run();
|
|
290
|
+
results.violations; // AxeViolation[]
|
|
291
|
+
results.passes; // AxePass[]
|
|
292
|
+
results.incomplete; // AxeIncomplete[]
|
|
293
|
+
|
|
294
|
+
// Run on a specific element
|
|
295
|
+
const nodeResults = await axeIntegration.runOnNode(formElement);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### Framework Integration
|
|
301
|
+
|
|
302
|
+
Unified facade for framework-level accessibility. Detects interaction mode, manages navigation landmarks, and provides an accessibility summary.
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const { framework } = driver;
|
|
306
|
+
|
|
307
|
+
// Detect how the user is currently interacting
|
|
308
|
+
const mode = framework.detectInteractionMode();
|
|
309
|
+
// 'keyboard' | 'pointer' | 'touch' | 'screen-reader'
|
|
310
|
+
|
|
311
|
+
// Register a navigation pathway
|
|
312
|
+
framework.registerPathway('main-nav', {
|
|
313
|
+
landmark: 'navigation',
|
|
314
|
+
element: navElement,
|
|
315
|
+
label: 'Main Navigation',
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Jump to a landmark
|
|
319
|
+
framework.navigateToLandmark('main');
|
|
320
|
+
|
|
321
|
+
// Get an accessibility health summary
|
|
322
|
+
const summary = framework.getAccessibilitySummary();
|
|
323
|
+
summary.interactionMode; // current mode
|
|
324
|
+
summary.landmarks; // registered landmark count
|
|
325
|
+
summary.liveRegions; // active region count
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### Sub-Module Accessors
|
|
331
|
+
|
|
332
|
+
Direct access to underlying sub-modules after `initialize()`:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
driver.liveRegions // LiveRegionManagerAPI
|
|
336
|
+
driver.screenReaderBridge // ScreenReaderBridgeAPI
|
|
337
|
+
driver.treeMirror // TreeMirrorAPI
|
|
338
|
+
driver.widgetCompliance // WidgetComplianceAPI
|
|
339
|
+
driver.semanticEnhancer // SemanticEnhancerAPI
|
|
340
|
+
driver.keyboardNav // KeyboardNavigationAPI
|
|
341
|
+
driver.stateManager // AriaStateManagerAPI
|
|
342
|
+
driver.focusManager // FocusManagerAPI
|
|
343
|
+
driver.axeIntegration // AxeIntegrationAPI
|
|
344
|
+
driver.framework // FrameworkIntegrationAPI
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Architecture
|
|
350
|
+
|
|
351
|
+
| Module | Responsibility |
|
|
352
|
+
|--------|---------------|
|
|
353
|
+
| `live-region-manager` | aria-live region creation and announcements |
|
|
354
|
+
| `screen-reader-bridge` | Screen reader detection via media queries |
|
|
355
|
+
| `accessibility-tree-mirror` | MutationObserver-based DOM-to-ARIA tree sync |
|
|
356
|
+
| `aria-widget-compliance` | W3C ARIA pattern validation and auto-config |
|
|
357
|
+
| `semantic-html-enhancer` | Auto-inject missing ARIA from built-in rules |
|
|
358
|
+
| `keyboard-navigation` | Roving tabindex / activedescendant / grid patterns |
|
|
359
|
+
| `state-properties-manager` | Reactive ARIA state with change events |
|
|
360
|
+
| `focus-management` | Focus trap, save/restore, programmatic movement |
|
|
361
|
+
| `axe-core-integration` | Optional runtime validation via axe-core |
|
|
362
|
+
| `framework-integration` | Interaction mode, landmarks, accessibility summary |
|
|
363
|
+
| `types` | All shared TypeScript interfaces |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Environment Support
|
|
368
|
+
|
|
369
|
+
| Environment | Support |
|
|
370
|
+
|-------------|---------|
|
|
371
|
+
| Browser | Full — MutationObserver, media queries, focus APIs |
|
|
372
|
+
| Node.js / SSR | Safe import — no `window`/`document` access at load time |
|
|
373
|
+
| Deno | Graceful no-op — `isBrowser: false` |
|
|
374
|
+
| jsdom (test) | Full — all features work in JSDOM (Vitest) |
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## License
|
|
379
|
+
|
|
380
|
+
MIT — OBINexus <okpalan@protonmail.com>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 4: Accessibility Tree Mirror
|
|
3
|
+
* Real-time DOM-to-Accessibility Tree synchronization with MutationObserver
|
|
4
|
+
*/
|
|
5
|
+
import type { AccessibilityNode, Disposable } from "./types.js";
|
|
6
|
+
export interface TreeMirrorConfig {
|
|
7
|
+
rootElement: Element;
|
|
8
|
+
observe?: boolean;
|
|
9
|
+
subtreeFilter?: (element: Element) => boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface TreeDiff {
|
|
12
|
+
type: "added" | "removed" | "changed";
|
|
13
|
+
path: string;
|
|
14
|
+
oldNode?: AccessibilityNode;
|
|
15
|
+
newNode?: AccessibilityNode;
|
|
16
|
+
}
|
|
17
|
+
export interface TreeMirrorAPI extends Disposable {
|
|
18
|
+
observe(): void;
|
|
19
|
+
disconnect(): void;
|
|
20
|
+
snapshot(): AccessibilityNode;
|
|
21
|
+
diff(previous: AccessibilityNode, current: AccessibilityNode): TreeDiff[];
|
|
22
|
+
serialize(): string;
|
|
23
|
+
onTreeChange(handler: (diffs: TreeDiff[]) => void): () => void;
|
|
24
|
+
}
|
|
25
|
+
export declare function createAccessibilityTreeMirror(config: TreeMirrorConfig): TreeMirrorAPI;
|
|
26
|
+
//# sourceMappingURL=accessibility-tree-mirror.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-tree-mirror.d.ts","sourceRoot":"","sources":["../src/accessibility-tree-mirror.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA2ChE,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,OAAO,IAAI,IAAI,CAAC;IAChB,UAAU,IAAI,IAAI,CAAC;IACnB,QAAQ,IAAI,iBAAiB,CAAC;IAC9B,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE,iBAAiB,GAAG,QAAQ,EAAE,CAAC;IAC1E,SAAS,IAAI,MAAM,CAAC;IACpB,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChE;AA6ED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,gBAAgB,GACvB,aAAa,CA4Ef"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 4: Accessibility Tree Mirror
|
|
3
|
+
* Real-time DOM-to-Accessibility Tree synchronization with MutationObserver
|
|
4
|
+
*/
|
|
5
|
+
/** Implied ARIA role mapping from HTML tag names */
|
|
6
|
+
const IMPLIED_ROLES = {
|
|
7
|
+
a: "link",
|
|
8
|
+
article: "article",
|
|
9
|
+
aside: "complementary",
|
|
10
|
+
button: "button",
|
|
11
|
+
details: "group",
|
|
12
|
+
dialog: "dialog",
|
|
13
|
+
footer: "contentinfo",
|
|
14
|
+
form: "form",
|
|
15
|
+
h1: "heading",
|
|
16
|
+
h2: "heading",
|
|
17
|
+
h3: "heading",
|
|
18
|
+
h4: "heading",
|
|
19
|
+
h5: "heading",
|
|
20
|
+
h6: "heading",
|
|
21
|
+
header: "banner",
|
|
22
|
+
hr: "separator",
|
|
23
|
+
img: "img",
|
|
24
|
+
input: "textbox",
|
|
25
|
+
li: "listitem",
|
|
26
|
+
main: "main",
|
|
27
|
+
menu: "menu",
|
|
28
|
+
nav: "navigation",
|
|
29
|
+
ol: "list",
|
|
30
|
+
option: "option",
|
|
31
|
+
progress: "progressbar",
|
|
32
|
+
section: "region",
|
|
33
|
+
select: "combobox",
|
|
34
|
+
summary: "button",
|
|
35
|
+
table: "table",
|
|
36
|
+
tbody: "rowgroup",
|
|
37
|
+
td: "cell",
|
|
38
|
+
textarea: "textbox",
|
|
39
|
+
tfoot: "rowgroup",
|
|
40
|
+
th: "columnheader",
|
|
41
|
+
thead: "rowgroup",
|
|
42
|
+
tr: "row",
|
|
43
|
+
ul: "list",
|
|
44
|
+
};
|
|
45
|
+
function buildNode(element, filter) {
|
|
46
|
+
const tag = element.tagName?.toLowerCase() ?? "";
|
|
47
|
+
const explicitRole = element.getAttribute("role");
|
|
48
|
+
const role = explicitRole || IMPLIED_ROLES[tag] || "generic";
|
|
49
|
+
const label = element.getAttribute("aria-label") ||
|
|
50
|
+
element.getAttribute("aria-labelledby") ||
|
|
51
|
+
element.title ||
|
|
52
|
+
undefined;
|
|
53
|
+
const description = element.getAttribute("aria-describedby") || undefined;
|
|
54
|
+
// Collect aria-* attributes
|
|
55
|
+
const attributes = {};
|
|
56
|
+
if (element.attributes) {
|
|
57
|
+
for (let i = 0; i < element.attributes.length; i++) {
|
|
58
|
+
const attr = element.attributes[i];
|
|
59
|
+
if (attr.name.startsWith("aria-") || attr.name === "role" || attr.name === "tabindex") {
|
|
60
|
+
attributes[attr.name] = attr.value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const children = [];
|
|
65
|
+
for (let i = 0; i < element.children.length; i++) {
|
|
66
|
+
const child = element.children[i];
|
|
67
|
+
if (filter && !filter(child))
|
|
68
|
+
continue;
|
|
69
|
+
children.push(buildNode(child, filter));
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
role,
|
|
73
|
+
label,
|
|
74
|
+
description,
|
|
75
|
+
attributes: Object.keys(attributes).length > 0 ? attributes : undefined,
|
|
76
|
+
children: children.length > 0 ? children : undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function diffNodes(prev, curr, path, result) {
|
|
80
|
+
if (!prev && curr) {
|
|
81
|
+
result.push({ type: "added", path, newNode: curr });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (prev && !curr) {
|
|
85
|
+
result.push({ type: "removed", path, oldNode: prev });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!prev || !curr)
|
|
89
|
+
return;
|
|
90
|
+
// Check if node itself changed
|
|
91
|
+
if (prev.role !== curr.role ||
|
|
92
|
+
prev.label !== curr.label ||
|
|
93
|
+
prev.description !== curr.description ||
|
|
94
|
+
JSON.stringify(prev.attributes) !== JSON.stringify(curr.attributes)) {
|
|
95
|
+
result.push({ type: "changed", path, oldNode: prev, newNode: curr });
|
|
96
|
+
}
|
|
97
|
+
// Diff children
|
|
98
|
+
const prevChildren = prev.children ?? [];
|
|
99
|
+
const currChildren = curr.children ?? [];
|
|
100
|
+
const maxLen = Math.max(prevChildren.length, currChildren.length);
|
|
101
|
+
for (let i = 0; i < maxLen; i++) {
|
|
102
|
+
diffNodes(prevChildren[i], currChildren[i], `${path}/${i}`, result);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function createAccessibilityTreeMirror(config) {
|
|
106
|
+
let observer = null;
|
|
107
|
+
let cachedSnapshot = null;
|
|
108
|
+
const changeHandlers = new Set();
|
|
109
|
+
function takeSnapshot() {
|
|
110
|
+
return buildNode(config.rootElement, config.subtreeFilter);
|
|
111
|
+
}
|
|
112
|
+
function handleMutations() {
|
|
113
|
+
const prev = cachedSnapshot;
|
|
114
|
+
cachedSnapshot = takeSnapshot();
|
|
115
|
+
if (prev && changeHandlers.size > 0) {
|
|
116
|
+
const diffs = diffNodes_wrapper(prev, cachedSnapshot);
|
|
117
|
+
if (diffs.length > 0) {
|
|
118
|
+
for (const handler of changeHandlers) {
|
|
119
|
+
handler(diffs);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function diffNodes_wrapper(prev, curr) {
|
|
125
|
+
const result = [];
|
|
126
|
+
diffNodes(prev, curr, "", result);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
observe() {
|
|
131
|
+
if (observer)
|
|
132
|
+
return;
|
|
133
|
+
cachedSnapshot = takeSnapshot();
|
|
134
|
+
observer = new MutationObserver(handleMutations);
|
|
135
|
+
observer.observe(config.rootElement, {
|
|
136
|
+
attributes: true,
|
|
137
|
+
attributeFilter: ["role", "tabindex", "aria-label", "aria-labelledby",
|
|
138
|
+
"aria-describedby", "aria-expanded", "aria-selected", "aria-hidden",
|
|
139
|
+
"aria-controls", "aria-live", "aria-atomic", "aria-relevant",
|
|
140
|
+
"aria-activedescendant", "aria-checked", "aria-disabled",
|
|
141
|
+
"aria-pressed", "aria-valuenow", "aria-valuemin", "aria-valuemax"],
|
|
142
|
+
childList: true,
|
|
143
|
+
subtree: true,
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
disconnect() {
|
|
147
|
+
if (observer) {
|
|
148
|
+
observer.disconnect();
|
|
149
|
+
observer = null;
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
snapshot() {
|
|
153
|
+
cachedSnapshot = takeSnapshot();
|
|
154
|
+
return cachedSnapshot;
|
|
155
|
+
},
|
|
156
|
+
diff(previous, current) {
|
|
157
|
+
return diffNodes_wrapper(previous, current);
|
|
158
|
+
},
|
|
159
|
+
serialize() {
|
|
160
|
+
return JSON.stringify(this.snapshot(), null, 2);
|
|
161
|
+
},
|
|
162
|
+
onTreeChange(handler) {
|
|
163
|
+
changeHandlers.add(handler);
|
|
164
|
+
return () => { changeHandlers.delete(handler); };
|
|
165
|
+
},
|
|
166
|
+
destroy() {
|
|
167
|
+
this.disconnect();
|
|
168
|
+
cachedSnapshot = null;
|
|
169
|
+
changeHandlers.clear();
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=accessibility-tree-mirror.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-tree-mirror.js","sourceRoot":"","sources":["../src/accessibility-tree-mirror.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 2: ARIA Widget Compliance Engine
|
|
3
|
+
* W3C ARIA Authoring Practices design patterns with validation
|
|
4
|
+
*/
|
|
5
|
+
import type { Disposable } from "./types.js";
|
|
6
|
+
import type { AriaStateManagerAPI } from "./state-properties-manager.js";
|
|
7
|
+
import type { FocusManagerAPI } from "./focus-management.js";
|
|
8
|
+
import type { KeyboardNavigationAPI } from "./keyboard-navigation.js";
|
|
9
|
+
export type WidgetPattern = "accordion" | "menu-bar" | "slider" | "tabs" | "dialog" | "listbox" | "tree" | "combobox";
|
|
10
|
+
export interface WidgetConfig {
|
|
11
|
+
container: Element;
|
|
12
|
+
pattern: WidgetPattern;
|
|
13
|
+
options?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface WidgetHandle extends Disposable {
|
|
16
|
+
activate(): void;
|
|
17
|
+
deactivate(): void;
|
|
18
|
+
getPattern(): WidgetPattern;
|
|
19
|
+
validate(): WidgetValidationResult;
|
|
20
|
+
}
|
|
21
|
+
export interface WidgetValidationResult {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
errors: Array<{
|
|
24
|
+
element: Element;
|
|
25
|
+
message: string;
|
|
26
|
+
severity: "error" | "warning";
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export interface WidgetComplianceDeps {
|
|
30
|
+
stateManager: AriaStateManagerAPI;
|
|
31
|
+
focusManager: FocusManagerAPI;
|
|
32
|
+
keyboardNav: KeyboardNavigationAPI;
|
|
33
|
+
}
|
|
34
|
+
export interface WidgetComplianceAPI extends Disposable {
|
|
35
|
+
createWidget(id: string, config: WidgetConfig): WidgetHandle;
|
|
36
|
+
getWidget(id: string): WidgetHandle | undefined;
|
|
37
|
+
destroyWidget(id: string): void;
|
|
38
|
+
validateAll(): Map<string, WidgetValidationResult>;
|
|
39
|
+
getSupportedPatterns(): WidgetPattern[];
|
|
40
|
+
}
|
|
41
|
+
export declare function createWidgetComplianceEngine(deps: WidgetComplianceDeps): WidgetComplianceAPI;
|
|
42
|
+
//# sourceMappingURL=aria-widget-compliance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aria-widget-compliance.d.ts","sourceRoot":"","sources":["../src/aria-widget-compliance.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,UAAU,GACV,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,UAAU,CAAC;AAEf,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,QAAQ,IAAI,IAAI,CAAC;IACjB,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,aAAa,CAAC;IAC5B,QAAQ,IAAI,sBAAsB,CAAC;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;KAC/B,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,mBAAmB,CAAC;IAClC,YAAY,EAAE,eAAe,CAAC;IAC9B,WAAW,EAAE,qBAAqB,CAAC;CACpC;AAED,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY,CAAC;IAC7D,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAChD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACnD,oBAAoB,IAAI,aAAa,EAAE,CAAC;CACzC;AAmQD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,oBAAoB,GACzB,mBAAmB,CAiErB"}
|