@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-integration.d.ts","sourceRoot":"","sources":["../src/framework-integration.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,eAAe,CAAC;AAEjF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,0BAA0B,CAAC;IACnC,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;IACzC,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,kBAAkB,CAAC,EAAE,qBAAqB,CAAC;IAC3C,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,uBAAwB,SAAQ,UAAU;IACzD,qBAAqB,IAAI,eAAe,CAAC;IACzC,uBAAuB,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC9E,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAClD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IACtE,WAAW,IAAI,iBAAiB,EAAE,CAAC;IACnC,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,uBAAuB,IAAI;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,eAAe,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,0BAA0B,GACjC,uBAAuB,CAsHzB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 10: OBINexus Framework Integration
|
|
3
|
+
* Accessible navigation pathways, interaction modes, unified facade
|
|
4
|
+
*/
|
|
5
|
+
export function createFrameworkIntegration(config) {
|
|
6
|
+
const pathways = new Map();
|
|
7
|
+
const modeHandlers = new Set();
|
|
8
|
+
let currentMode = "pointer";
|
|
9
|
+
const listeners = [];
|
|
10
|
+
function setMode(mode) {
|
|
11
|
+
if (mode === currentMode)
|
|
12
|
+
return;
|
|
13
|
+
currentMode = mode;
|
|
14
|
+
for (const handler of modeHandlers) {
|
|
15
|
+
handler(mode);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function onKeyDown(e) {
|
|
19
|
+
const event = e;
|
|
20
|
+
if (event.key === "Tab" || event.key.startsWith("Arrow")) {
|
|
21
|
+
setMode("keyboard");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function onPointerDown() {
|
|
25
|
+
setMode("pointer");
|
|
26
|
+
}
|
|
27
|
+
function onTouchStart() {
|
|
28
|
+
setMode("touch");
|
|
29
|
+
}
|
|
30
|
+
function addListener(target, type, handler) {
|
|
31
|
+
target.addEventListener(type, handler);
|
|
32
|
+
listeners.push({ target, type, handler });
|
|
33
|
+
}
|
|
34
|
+
// Set up interaction mode detection
|
|
35
|
+
if (typeof config.rootElement.addEventListener === "function") {
|
|
36
|
+
addListener(config.rootElement, "keydown", onKeyDown);
|
|
37
|
+
addListener(config.rootElement, "pointerdown", onPointerDown);
|
|
38
|
+
addListener(config.rootElement, "touchstart", onTouchStart);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
detectInteractionMode() {
|
|
42
|
+
return currentMode;
|
|
43
|
+
},
|
|
44
|
+
onInteractionModeChange(handler) {
|
|
45
|
+
modeHandlers.add(handler);
|
|
46
|
+
return () => { modeHandlers.delete(handler); };
|
|
47
|
+
},
|
|
48
|
+
registerPathway(pathway) {
|
|
49
|
+
pathways.set(pathway.id, pathway);
|
|
50
|
+
},
|
|
51
|
+
removePathway(id) {
|
|
52
|
+
pathways.delete(id);
|
|
53
|
+
},
|
|
54
|
+
navigateToLandmark(pathwayId, landmarkLabel) {
|
|
55
|
+
const pathway = pathways.get(pathwayId);
|
|
56
|
+
if (!pathway)
|
|
57
|
+
return false;
|
|
58
|
+
const landmark = pathway.landmarks.find((l) => l.label === landmarkLabel);
|
|
59
|
+
if (!landmark)
|
|
60
|
+
return false;
|
|
61
|
+
// Use focus manager if available, otherwise direct focus
|
|
62
|
+
if (config.focusManager) {
|
|
63
|
+
config.focusManager.moveFocus(landmark.element);
|
|
64
|
+
}
|
|
65
|
+
else if (typeof landmark.element.focus === "function") {
|
|
66
|
+
landmark.element.focus();
|
|
67
|
+
}
|
|
68
|
+
// Announce navigation if screen reader bridge is available
|
|
69
|
+
if (config.screenReaderBridge) {
|
|
70
|
+
config.screenReaderBridge.announcePolite(`Navigated to ${landmarkLabel}`);
|
|
71
|
+
}
|
|
72
|
+
else if (config.liveRegionManager) {
|
|
73
|
+
config.liveRegionManager.announceGlobal(`Navigated to ${landmarkLabel}`);
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
},
|
|
77
|
+
getPathways() {
|
|
78
|
+
return Array.from(pathways.values());
|
|
79
|
+
},
|
|
80
|
+
announceNavigation(description) {
|
|
81
|
+
if (config.screenReaderBridge) {
|
|
82
|
+
config.screenReaderBridge.announcePolite(description);
|
|
83
|
+
}
|
|
84
|
+
else if (config.liveRegionManager) {
|
|
85
|
+
config.liveRegionManager.announceGlobal(description);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
getAccessibilitySummary() {
|
|
89
|
+
let landmarkCount = 0;
|
|
90
|
+
for (const pathway of pathways.values()) {
|
|
91
|
+
landmarkCount += pathway.landmarks.length;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
landmarks: landmarkCount,
|
|
95
|
+
liveRegions: config.liveRegionManager?.getActiveRegions().length ?? 0,
|
|
96
|
+
interactionMode: currentMode,
|
|
97
|
+
pathways: pathways.size,
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
destroy() {
|
|
101
|
+
for (const { target, type, handler } of listeners) {
|
|
102
|
+
target.removeEventListener(type, handler);
|
|
103
|
+
}
|
|
104
|
+
listeners.length = 0;
|
|
105
|
+
pathways.clear();
|
|
106
|
+
modeHandlers.clear();
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=framework-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework-integration.js","sourceRoot":"","sources":["../src/framework-integration.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,37 +2,17 @@
|
|
|
2
2
|
* Accessibility Tree Driver
|
|
3
3
|
* ARIA/live region management and screen reader bridge
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
liveRegionDefaults?: LiveRegionDefaults;
|
|
18
|
-
/** Screen reader hints and optimizations */
|
|
19
|
-
screenReaderHints?: boolean;
|
|
20
|
-
}
|
|
21
|
-
export interface AccessibilityNode {
|
|
22
|
-
role: AriaRole;
|
|
23
|
-
label?: string;
|
|
24
|
-
description?: string;
|
|
25
|
-
attributes?: Record<string, string>;
|
|
26
|
-
children?: AccessibilityNode[];
|
|
27
|
-
}
|
|
28
|
-
export interface AccessibilityTreeDriverAPI {
|
|
29
|
-
initialize(): Promise<void>;
|
|
30
|
-
registerLiveRegion(element: Element, config?: LiveRegionDefaults): Promise<void>;
|
|
31
|
-
announce(message: string, level?: AriaLiveRegion): void;
|
|
32
|
-
updateAccessibilityNode(element: Element, node: AccessibilityNode): void;
|
|
33
|
-
getAccessibilityTree(): AccessibilityNode;
|
|
34
|
-
setScreenReaderMode(enabled: boolean): void;
|
|
35
|
-
destroy(): Promise<void>;
|
|
36
|
-
}
|
|
5
|
+
export * from "./types.js";
|
|
6
|
+
export * from "./live-region-manager.js";
|
|
7
|
+
export * from "./state-properties-manager.js";
|
|
8
|
+
export * from "./focus-management.js";
|
|
9
|
+
export * from "./screen-reader-bridge.js";
|
|
10
|
+
export * from "./keyboard-navigation.js";
|
|
11
|
+
export * from "./accessibility-tree-mirror.js";
|
|
12
|
+
export * from "./semantic-html-enhancer.js";
|
|
13
|
+
export * from "./aria-widget-compliance.js";
|
|
14
|
+
export * from "./axe-core-integration.js";
|
|
15
|
+
export * from "./framework-integration.js";
|
|
16
|
+
import type { AccessibilityTreeDriverConfig, AccessibilityTreeDriverAPI } from "./types.js";
|
|
37
17
|
export declare function createAccessibilityTreeDriver(config: AccessibilityTreeDriverConfig): AccessibilityTreeDriverAPI;
|
|
38
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAG3C,OAAO,KAAK,EAIV,6BAA6B,EAC7B,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAYpB,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,0BAA0B,CA0L5B"}
|
package/dist/index.js
CHANGED
|
@@ -2,29 +2,133 @@
|
|
|
2
2
|
* Accessibility Tree Driver
|
|
3
3
|
* ARIA/live region management and screen reader bridge
|
|
4
4
|
*/
|
|
5
|
+
// Re-export all types
|
|
6
|
+
export * from "./types.js";
|
|
7
|
+
// Re-export all feature factories and their types
|
|
8
|
+
export * from "./live-region-manager.js";
|
|
9
|
+
export * from "./state-properties-manager.js";
|
|
10
|
+
export * from "./focus-management.js";
|
|
11
|
+
export * from "./screen-reader-bridge.js";
|
|
12
|
+
export * from "./keyboard-navigation.js";
|
|
13
|
+
export * from "./accessibility-tree-mirror.js";
|
|
14
|
+
export * from "./semantic-html-enhancer.js";
|
|
15
|
+
export * from "./aria-widget-compliance.js";
|
|
16
|
+
export * from "./axe-core-integration.js";
|
|
17
|
+
export * from "./framework-integration.js";
|
|
18
|
+
import { createLiveRegionManager } from "./live-region-manager.js";
|
|
19
|
+
import { createAriaStateManager } from "./state-properties-manager.js";
|
|
20
|
+
import { createFocusManager } from "./focus-management.js";
|
|
21
|
+
import { createScreenReaderBridge } from "./screen-reader-bridge.js";
|
|
22
|
+
import { createKeyboardNavigationController } from "./keyboard-navigation.js";
|
|
23
|
+
import { createAccessibilityTreeMirror } from "./accessibility-tree-mirror.js";
|
|
24
|
+
import { createSemanticEnhancer } from "./semantic-html-enhancer.js";
|
|
25
|
+
import { createWidgetComplianceEngine } from "./aria-widget-compliance.js";
|
|
26
|
+
import { createAxeIntegration } from "./axe-core-integration.js";
|
|
27
|
+
import { createFrameworkIntegration } from "./framework-integration.js";
|
|
5
28
|
export function createAccessibilityTreeDriver(config) {
|
|
6
29
|
let initialized = false;
|
|
7
|
-
|
|
30
|
+
// Sub-features (created lazily during initialize)
|
|
31
|
+
let liveRegions;
|
|
32
|
+
let stateManager;
|
|
33
|
+
let focusManager;
|
|
34
|
+
let screenReaderBridge;
|
|
35
|
+
let keyboardNav;
|
|
36
|
+
let treeMirror;
|
|
37
|
+
let semanticEnhancer;
|
|
38
|
+
let widgetCompliance;
|
|
39
|
+
let axeIntegration;
|
|
40
|
+
let framework;
|
|
41
|
+
// Legacy compatibility: node map for updateAccessibilityNode
|
|
8
42
|
const nodeMap = new Map();
|
|
9
|
-
const
|
|
10
|
-
let lastAnnouncement = "";
|
|
11
|
-
return {
|
|
43
|
+
const driver = {
|
|
12
44
|
async initialize() {
|
|
45
|
+
if (initialized)
|
|
46
|
+
return;
|
|
13
47
|
initialized = true;
|
|
48
|
+
// Create all sub-features
|
|
49
|
+
stateManager = createAriaStateManager();
|
|
50
|
+
focusManager = createFocusManager();
|
|
51
|
+
liveRegions = createLiveRegionManager({
|
|
52
|
+
container: config.rootElement,
|
|
53
|
+
defaultLevel: config.liveRegionDefaults?.level ?? "polite",
|
|
54
|
+
});
|
|
55
|
+
screenReaderBridge = createScreenReaderBridge({
|
|
56
|
+
liveRegionManager: liveRegions,
|
|
57
|
+
enableDetection: config.screenReaderHints,
|
|
58
|
+
});
|
|
59
|
+
keyboardNav = createKeyboardNavigationController();
|
|
60
|
+
treeMirror = createAccessibilityTreeMirror({
|
|
61
|
+
rootElement: config.rootElement,
|
|
62
|
+
observe: false,
|
|
63
|
+
});
|
|
64
|
+
semanticEnhancer = createSemanticEnhancer({
|
|
65
|
+
rootElement: config.rootElement,
|
|
66
|
+
stateManager,
|
|
67
|
+
});
|
|
68
|
+
widgetCompliance = createWidgetComplianceEngine({
|
|
69
|
+
stateManager,
|
|
70
|
+
focusManager,
|
|
71
|
+
keyboardNav,
|
|
72
|
+
});
|
|
73
|
+
axeIntegration = createAxeIntegration({
|
|
74
|
+
rootElement: config.rootElement,
|
|
75
|
+
});
|
|
76
|
+
framework = createFrameworkIntegration({
|
|
77
|
+
rootElement: config.rootElement,
|
|
78
|
+
driver,
|
|
79
|
+
liveRegionManager: liveRegions,
|
|
80
|
+
focusManager,
|
|
81
|
+
screenReaderBridge,
|
|
82
|
+
stateManager,
|
|
83
|
+
});
|
|
84
|
+
// Start tree observation
|
|
85
|
+
treeMirror.observe();
|
|
86
|
+
// Set screen reader mode if configured
|
|
87
|
+
if (config.screenReaderHints) {
|
|
88
|
+
screenReaderBridge.setOptimizationMode(true);
|
|
89
|
+
}
|
|
14
90
|
},
|
|
15
91
|
async registerLiveRegion(element, overrides) {
|
|
16
|
-
liveRegions
|
|
92
|
+
if (liveRegions) {
|
|
93
|
+
const id = element.id || `region-${Date.now()}`;
|
|
94
|
+
liveRegions.createRegion(id, { ...config.liveRegionDefaults, ...overrides });
|
|
95
|
+
}
|
|
17
96
|
},
|
|
18
97
|
announce(message, level = "polite") {
|
|
19
|
-
|
|
20
|
-
|
|
98
|
+
if (screenReaderBridge) {
|
|
99
|
+
if (level === "assertive") {
|
|
100
|
+
screenReaderBridge.announceAssertive(message);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
screenReaderBridge.announcePolite(message);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (liveRegions) {
|
|
107
|
+
liveRegions.announceGlobal(message, level);
|
|
108
|
+
}
|
|
109
|
+
else if (typeof config.rootElement.setAttribute === "function") {
|
|
110
|
+
// Fallback for uninitialized state
|
|
21
111
|
config.rootElement.setAttribute("aria-live", level);
|
|
22
112
|
config.rootElement.setAttribute("aria-label", message);
|
|
23
113
|
}
|
|
24
114
|
},
|
|
25
115
|
updateAccessibilityNode(element, node) {
|
|
26
116
|
nodeMap.set(element, node);
|
|
27
|
-
if (
|
|
117
|
+
if (stateManager) {
|
|
118
|
+
stateManager.setState(element, "role", node.role);
|
|
119
|
+
if (node.label) {
|
|
120
|
+
stateManager.setState(element, "aria-label", node.label);
|
|
121
|
+
}
|
|
122
|
+
if (node.description) {
|
|
123
|
+
stateManager.setState(element, "aria-describedby", node.description);
|
|
124
|
+
}
|
|
125
|
+
if (node.attributes) {
|
|
126
|
+
for (const [key, value] of Object.entries(node.attributes)) {
|
|
127
|
+
stateManager.setState(element, key, value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (typeof element.setAttribute === "function") {
|
|
28
132
|
element.setAttribute("role", node.role);
|
|
29
133
|
if (node.label) {
|
|
30
134
|
element.setAttribute("aria-label", node.label);
|
|
@@ -32,26 +136,61 @@ export function createAccessibilityTreeDriver(config) {
|
|
|
32
136
|
}
|
|
33
137
|
},
|
|
34
138
|
getAccessibilityTree() {
|
|
139
|
+
if (treeMirror) {
|
|
140
|
+
return treeMirror.snapshot();
|
|
141
|
+
}
|
|
142
|
+
// Fallback for uninitialized state
|
|
35
143
|
const children = Array.from(nodeMap.values());
|
|
36
144
|
return {
|
|
37
145
|
role: "root",
|
|
38
|
-
label:
|
|
146
|
+
label: "accessibility-tree",
|
|
39
147
|
children,
|
|
40
148
|
};
|
|
41
149
|
},
|
|
42
150
|
setScreenReaderMode(enabled) {
|
|
43
|
-
|
|
151
|
+
if (screenReaderBridge) {
|
|
152
|
+
screenReaderBridge.setOptimizationMode(enabled);
|
|
153
|
+
}
|
|
44
154
|
if (typeof config.rootElement.setAttribute === "function") {
|
|
45
|
-
config.rootElement.setAttribute("data-screen-reader-mode", String(
|
|
155
|
+
config.rootElement.setAttribute("data-screen-reader-mode", String(enabled));
|
|
46
156
|
}
|
|
47
157
|
},
|
|
48
158
|
async destroy() {
|
|
49
|
-
|
|
159
|
+
framework?.destroy();
|
|
160
|
+
axeIntegration?.destroy();
|
|
161
|
+
widgetCompliance?.destroy();
|
|
162
|
+
semanticEnhancer?.destroy();
|
|
163
|
+
treeMirror?.destroy();
|
|
164
|
+
keyboardNav?.destroy();
|
|
165
|
+
screenReaderBridge?.destroy();
|
|
166
|
+
focusManager?.destroy();
|
|
167
|
+
liveRegions?.destroy();
|
|
168
|
+
stateManager?.destroy();
|
|
169
|
+
framework = undefined;
|
|
170
|
+
axeIntegration = undefined;
|
|
171
|
+
widgetCompliance = undefined;
|
|
172
|
+
semanticEnhancer = undefined;
|
|
173
|
+
treeMirror = undefined;
|
|
174
|
+
keyboardNav = undefined;
|
|
175
|
+
screenReaderBridge = undefined;
|
|
176
|
+
focusManager = undefined;
|
|
177
|
+
liveRegions = undefined;
|
|
178
|
+
stateManager = undefined;
|
|
50
179
|
nodeMap.clear();
|
|
51
|
-
|
|
52
|
-
lastAnnouncement = "";
|
|
53
|
-
void initialized;
|
|
180
|
+
initialized = false;
|
|
54
181
|
},
|
|
182
|
+
// Sub-feature accessors
|
|
183
|
+
get liveRegions() { return liveRegions; },
|
|
184
|
+
get stateManager() { return stateManager; },
|
|
185
|
+
get focusManager() { return focusManager; },
|
|
186
|
+
get screenReaderBridge() { return screenReaderBridge; },
|
|
187
|
+
get keyboardNav() { return keyboardNav; },
|
|
188
|
+
get treeMirror() { return treeMirror; },
|
|
189
|
+
get semanticEnhancer() { return semanticEnhancer; },
|
|
190
|
+
get widgetCompliance() { return widgetCompliance; },
|
|
191
|
+
get axeIntegration() { return axeIntegration; },
|
|
192
|
+
get framework() { return framework; },
|
|
55
193
|
};
|
|
194
|
+
return driver;
|
|
56
195
|
}
|
|
57
196
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 7: Keyboard Navigation Controller
|
|
3
|
+
* ARIA widget keyboard patterns (roving tabindex, activedescendant, type-ahead)
|
|
4
|
+
*/
|
|
5
|
+
import type { Disposable } from "./types.js";
|
|
6
|
+
import type { FocusManagerAPI } from "./focus-management.js";
|
|
7
|
+
export type KeyboardPattern = "roving-tabindex" | "activedescendant" | "grid";
|
|
8
|
+
export interface KeyboardNavigationConfig {
|
|
9
|
+
container: Element;
|
|
10
|
+
pattern: KeyboardPattern;
|
|
11
|
+
orientation?: "horizontal" | "vertical" | "both";
|
|
12
|
+
wrap?: boolean;
|
|
13
|
+
typeAhead?: boolean;
|
|
14
|
+
focusManager: FocusManagerAPI;
|
|
15
|
+
}
|
|
16
|
+
export interface KeyboardNavigationHandle extends Disposable {
|
|
17
|
+
activate(): void;
|
|
18
|
+
deactivate(): void;
|
|
19
|
+
setItems(items: Element[]): void;
|
|
20
|
+
getCurrentItem(): Element | null;
|
|
21
|
+
moveTo(index: number): void;
|
|
22
|
+
}
|
|
23
|
+
export interface KeyboardNavigationAPI extends Disposable {
|
|
24
|
+
createNavigation(id: string, config: KeyboardNavigationConfig): KeyboardNavigationHandle;
|
|
25
|
+
getNavigation(id: string): KeyboardNavigationHandle | undefined;
|
|
26
|
+
destroyNavigation(id: string): void;
|
|
27
|
+
}
|
|
28
|
+
export declare function createKeyboardNavigationController(): KeyboardNavigationAPI;
|
|
29
|
+
//# sourceMappingURL=keyboard-navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard-navigation.d.ts","sourceRoot":"","sources":["../src/keyboard-navigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAE9E,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;IACjD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAyB,SAAQ,UAAU;IAC1D,QAAQ,IAAI,IAAI,CAAC;IACjB,UAAU,IAAI,IAAI,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjC,cAAc,IAAI,OAAO,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAsB,SAAQ,UAAU;IACvD,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,GAAG,wBAAwB,CAAC;IACzF,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAAC;IAChE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,kCAAkC,IAAI,qBAAqB,CA0L1E"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 7: Keyboard Navigation Controller
|
|
3
|
+
* ARIA widget keyboard patterns (roving tabindex, activedescendant, type-ahead)
|
|
4
|
+
*/
|
|
5
|
+
export function createKeyboardNavigationController() {
|
|
6
|
+
const navigations = new Map();
|
|
7
|
+
return {
|
|
8
|
+
createNavigation(id, config) {
|
|
9
|
+
if (navigations.has(id)) {
|
|
10
|
+
return navigations.get(id);
|
|
11
|
+
}
|
|
12
|
+
let items = [];
|
|
13
|
+
let currentIndex = -1;
|
|
14
|
+
let active = false;
|
|
15
|
+
let typeBuffer = "";
|
|
16
|
+
let typeTimer = null;
|
|
17
|
+
const orientation = config.orientation ?? "vertical";
|
|
18
|
+
const wrap = config.wrap ?? true;
|
|
19
|
+
function isForward(key) {
|
|
20
|
+
if (orientation === "horizontal" || orientation === "both") {
|
|
21
|
+
if (key === "ArrowRight")
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (orientation === "vertical" || orientation === "both") {
|
|
25
|
+
if (key === "ArrowDown")
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
function isBackward(key) {
|
|
31
|
+
if (orientation === "horizontal" || orientation === "both") {
|
|
32
|
+
if (key === "ArrowLeft")
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (orientation === "vertical" || orientation === "both") {
|
|
36
|
+
if (key === "ArrowUp")
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
function focusItem(index) {
|
|
42
|
+
if (index < 0 || index >= items.length)
|
|
43
|
+
return;
|
|
44
|
+
const prev = currentIndex;
|
|
45
|
+
currentIndex = index;
|
|
46
|
+
if (config.pattern === "roving-tabindex") {
|
|
47
|
+
if (prev >= 0 && prev < items.length) {
|
|
48
|
+
items[prev].setAttribute("tabindex", "-1");
|
|
49
|
+
}
|
|
50
|
+
items[currentIndex].setAttribute("tabindex", "0");
|
|
51
|
+
items[currentIndex].focus();
|
|
52
|
+
}
|
|
53
|
+
else if (config.pattern === "activedescendant") {
|
|
54
|
+
const itemId = items[currentIndex].id ||
|
|
55
|
+
`${config.container.id || "nav"}-item-${currentIndex}`;
|
|
56
|
+
if (!items[currentIndex].id) {
|
|
57
|
+
items[currentIndex].id = itemId;
|
|
58
|
+
}
|
|
59
|
+
config.container.setAttribute("aria-activedescendant", itemId);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function moveForward() {
|
|
63
|
+
if (items.length === 0)
|
|
64
|
+
return;
|
|
65
|
+
let next = currentIndex + 1;
|
|
66
|
+
if (next >= items.length) {
|
|
67
|
+
next = wrap ? 0 : items.length - 1;
|
|
68
|
+
}
|
|
69
|
+
focusItem(next);
|
|
70
|
+
}
|
|
71
|
+
function moveBackward() {
|
|
72
|
+
if (items.length === 0)
|
|
73
|
+
return;
|
|
74
|
+
let prev = currentIndex - 1;
|
|
75
|
+
if (prev < 0) {
|
|
76
|
+
prev = wrap ? items.length - 1 : 0;
|
|
77
|
+
}
|
|
78
|
+
focusItem(prev);
|
|
79
|
+
}
|
|
80
|
+
function handleTypeAhead(char) {
|
|
81
|
+
typeBuffer += char.toLowerCase();
|
|
82
|
+
if (typeTimer)
|
|
83
|
+
clearTimeout(typeTimer);
|
|
84
|
+
typeTimer = setTimeout(() => { typeBuffer = ""; }, 500);
|
|
85
|
+
const match = items.findIndex((item) => (item.textContent ?? "").toLowerCase().startsWith(typeBuffer));
|
|
86
|
+
if (match !== -1) {
|
|
87
|
+
focusItem(match);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function handleKeyDown(e) {
|
|
91
|
+
const event = e;
|
|
92
|
+
if (isForward(event.key)) {
|
|
93
|
+
event.preventDefault();
|
|
94
|
+
moveForward();
|
|
95
|
+
}
|
|
96
|
+
else if (isBackward(event.key)) {
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
moveBackward();
|
|
99
|
+
}
|
|
100
|
+
else if (event.key === "Home") {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
focusItem(0);
|
|
103
|
+
}
|
|
104
|
+
else if (event.key === "End") {
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
focusItem(items.length - 1);
|
|
107
|
+
}
|
|
108
|
+
else if (config.typeAhead && event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
|
|
109
|
+
handleTypeAhead(event.key);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const handle = {
|
|
113
|
+
activate() {
|
|
114
|
+
if (active)
|
|
115
|
+
return;
|
|
116
|
+
active = true;
|
|
117
|
+
config.container.addEventListener("keydown", handleKeyDown);
|
|
118
|
+
if (config.pattern === "roving-tabindex") {
|
|
119
|
+
for (const item of items) {
|
|
120
|
+
item.setAttribute("tabindex", "-1");
|
|
121
|
+
}
|
|
122
|
+
if (items.length > 0) {
|
|
123
|
+
focusItem(0);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (config.pattern === "activedescendant") {
|
|
127
|
+
config.container.setAttribute("tabindex", "0");
|
|
128
|
+
if (items.length > 0) {
|
|
129
|
+
focusItem(0);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
deactivate() {
|
|
134
|
+
if (!active)
|
|
135
|
+
return;
|
|
136
|
+
active = false;
|
|
137
|
+
config.container.removeEventListener("keydown", handleKeyDown);
|
|
138
|
+
if (typeTimer) {
|
|
139
|
+
clearTimeout(typeTimer);
|
|
140
|
+
typeTimer = null;
|
|
141
|
+
}
|
|
142
|
+
typeBuffer = "";
|
|
143
|
+
},
|
|
144
|
+
setItems(newItems) {
|
|
145
|
+
items = [...newItems];
|
|
146
|
+
currentIndex = items.length > 0 ? 0 : -1;
|
|
147
|
+
},
|
|
148
|
+
getCurrentItem() {
|
|
149
|
+
if (currentIndex >= 0 && currentIndex < items.length) {
|
|
150
|
+
return items[currentIndex];
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
},
|
|
154
|
+
moveTo(index) {
|
|
155
|
+
focusItem(index);
|
|
156
|
+
},
|
|
157
|
+
destroy() {
|
|
158
|
+
handle.deactivate();
|
|
159
|
+
navigations.delete(id);
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
navigations.set(id, handle);
|
|
163
|
+
return handle;
|
|
164
|
+
},
|
|
165
|
+
getNavigation(id) {
|
|
166
|
+
return navigations.get(id);
|
|
167
|
+
},
|
|
168
|
+
destroyNavigation(id) {
|
|
169
|
+
const handle = navigations.get(id);
|
|
170
|
+
if (handle) {
|
|
171
|
+
handle.destroy();
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
destroy() {
|
|
175
|
+
for (const handle of navigations.values()) {
|
|
176
|
+
handle.deactivate();
|
|
177
|
+
}
|
|
178
|
+
navigations.clear();
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=keyboard-navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard-navigation.js","sourceRoot":"","sources":["../src/keyboard-navigation.ts"],"names":[],"mappings":"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"}
|