aria-ease 3.0.3 → 4.0.0
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/bin/cli.cjs +32 -0
- package/bin/cli.js +1 -1
- package/bin/{contractTestRunnerPlaywright-3VJUZSYK.js → contractTestRunnerPlaywright-EZLNNJV5.js} +32 -0
- package/bin/{test-D374H2ZS.js → test-45KMD4F4.js} +1 -1
- package/dist/{contractTestRunnerPlaywright-4UOHWGWD.js → contractTestRunnerPlaywright-UQQI5MYS.js} +32 -0
- package/dist/index.cjs +624 -1
- package/dist/index.d.cts +83 -2
- package/dist/index.d.ts +83 -2
- package/dist/index.js +589 -2
- package/dist/src/{Types.d-uG0Hm1yK.d.ts → Types.d-BrHSyS03.d.cts} +17 -0
- package/dist/src/{Types.d-uG0Hm1yK.d.cts → Types.d-BrHSyS03.d.ts} +17 -0
- package/dist/src/accordion/index.cjs +159 -0
- package/dist/src/accordion/index.d.cts +19 -2
- package/dist/src/accordion/index.d.ts +19 -2
- package/dist/src/accordion/index.js +159 -1
- package/dist/src/block/index.cjs +1 -1
- package/dist/src/block/index.d.cts +6 -2
- package/dist/src/block/index.d.ts +6 -2
- package/dist/src/block/index.js +1 -1
- package/dist/src/checkbox/index.cjs +129 -0
- package/dist/src/checkbox/index.d.cts +15 -2
- package/dist/src/checkbox/index.d.ts +15 -2
- package/dist/src/checkbox/index.js +129 -1
- package/dist/src/combobox/index.d.cts +1 -1
- package/dist/src/combobox/index.d.ts +1 -1
- package/dist/src/menu/index.cjs +32 -0
- package/dist/src/menu/index.d.cts +1 -1
- package/dist/src/menu/index.d.ts +1 -1
- package/dist/src/menu/index.js +32 -0
- package/dist/src/radio/index.cjs +122 -0
- package/dist/src/radio/index.d.cts +17 -2
- package/dist/src/radio/index.d.ts +17 -2
- package/dist/src/radio/index.js +122 -1
- package/dist/src/toggle/index.cjs +145 -0
- package/dist/src/toggle/index.d.cts +17 -2
- package/dist/src/toggle/index.d.ts +17 -2
- package/dist/src/toggle/index.js +145 -1
- package/dist/src/utils/test/{contractTestRunnerPlaywright-4UOHWGWD.js → contractTestRunnerPlaywright-UQQI5MYS.js} +32 -0
- package/dist/src/utils/test/contracts/MenuContract.json +0 -1
- package/dist/src/utils/test/index.cjs +32 -0
- package/dist/src/utils/test/index.js +1 -1
- package/package.json +1 -1
|
@@ -29,4 +29,132 @@ function updateCheckboxAriaAttributes(checkboxId, checkboxesClass, checkboxState
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
// src/checkbox/src/makeCheckboxAccessible/makeCheckboxAccessible.ts
|
|
33
|
+
function makeCheckboxAccessible({ checkboxGroupId, checkboxesClass }) {
|
|
34
|
+
const checkboxGroup = document.querySelector(`#${checkboxGroupId}`);
|
|
35
|
+
if (!checkboxGroup) {
|
|
36
|
+
console.error(`[aria-ease] Element with id="${checkboxGroupId}" not found. Make sure the checkbox group container exists before calling makeCheckboxAccessible.`);
|
|
37
|
+
return { cleanup: () => {
|
|
38
|
+
} };
|
|
39
|
+
}
|
|
40
|
+
const checkboxes = Array.from(checkboxGroup.querySelectorAll(`.${checkboxesClass}`));
|
|
41
|
+
if (checkboxes.length === 0) {
|
|
42
|
+
console.error(`[aria-ease] No elements with class="${checkboxesClass}" found. Make sure checkboxes exist before calling makeCheckboxAccessible.`);
|
|
43
|
+
return { cleanup: () => {
|
|
44
|
+
} };
|
|
45
|
+
}
|
|
46
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
48
|
+
function initialize() {
|
|
49
|
+
if (!checkboxGroup.getAttribute("role")) {
|
|
50
|
+
checkboxGroup.setAttribute("role", "group");
|
|
51
|
+
}
|
|
52
|
+
checkboxes.forEach((checkbox) => {
|
|
53
|
+
checkbox.setAttribute("role", "checkbox");
|
|
54
|
+
if (!checkbox.hasAttribute("aria-checked")) {
|
|
55
|
+
checkbox.setAttribute("aria-checked", "false");
|
|
56
|
+
}
|
|
57
|
+
if (!checkbox.hasAttribute("tabindex")) {
|
|
58
|
+
checkbox.setAttribute("tabindex", "0");
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function toggleCheckbox(index) {
|
|
63
|
+
if (index < 0 || index >= checkboxes.length) {
|
|
64
|
+
console.error(`[aria-ease] Invalid checkbox index: ${index}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const checkbox = checkboxes[index];
|
|
68
|
+
const isChecked = checkbox.getAttribute("aria-checked") === "true";
|
|
69
|
+
checkbox.setAttribute("aria-checked", isChecked ? "false" : "true");
|
|
70
|
+
}
|
|
71
|
+
function setCheckboxState(index, checked) {
|
|
72
|
+
if (index < 0 || index >= checkboxes.length) {
|
|
73
|
+
console.error(`[aria-ease] Invalid checkbox index: ${index}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
checkboxes[index].setAttribute("aria-checked", checked ? "true" : "false");
|
|
77
|
+
}
|
|
78
|
+
function handleCheckboxClick(index) {
|
|
79
|
+
return () => {
|
|
80
|
+
toggleCheckbox(index);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function handleCheckboxKeydown(index) {
|
|
84
|
+
return (event) => {
|
|
85
|
+
const { key } = event;
|
|
86
|
+
switch (key) {
|
|
87
|
+
case " ":
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
toggleCheckbox(index);
|
|
90
|
+
break;
|
|
91
|
+
case "ArrowDown":
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
{
|
|
94
|
+
const nextIndex = (index + 1) % checkboxes.length;
|
|
95
|
+
checkboxes[nextIndex].focus();
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case "ArrowUp":
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
{
|
|
101
|
+
const prevIndex = (index - 1 + checkboxes.length) % checkboxes.length;
|
|
102
|
+
checkboxes[prevIndex].focus();
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
case "Home":
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
checkboxes[0].focus();
|
|
108
|
+
break;
|
|
109
|
+
case "End":
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
checkboxes[checkboxes.length - 1].focus();
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function addListeners() {
|
|
117
|
+
checkboxes.forEach((checkbox, index) => {
|
|
118
|
+
const clickHandler = handleCheckboxClick(index);
|
|
119
|
+
const keydownHandler = handleCheckboxKeydown(index);
|
|
120
|
+
checkbox.addEventListener("click", clickHandler);
|
|
121
|
+
checkbox.addEventListener("keydown", keydownHandler);
|
|
122
|
+
handlerMap.set(checkbox, keydownHandler);
|
|
123
|
+
clickHandlerMap.set(checkbox, clickHandler);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function removeListeners() {
|
|
127
|
+
checkboxes.forEach((checkbox) => {
|
|
128
|
+
const keydownHandler = handlerMap.get(checkbox);
|
|
129
|
+
const clickHandler = clickHandlerMap.get(checkbox);
|
|
130
|
+
if (keydownHandler) {
|
|
131
|
+
checkbox.removeEventListener("keydown", keydownHandler);
|
|
132
|
+
handlerMap.delete(checkbox);
|
|
133
|
+
}
|
|
134
|
+
if (clickHandler) {
|
|
135
|
+
checkbox.removeEventListener("click", clickHandler);
|
|
136
|
+
clickHandlerMap.delete(checkbox);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function cleanup() {
|
|
141
|
+
removeListeners();
|
|
142
|
+
}
|
|
143
|
+
function getCheckedStates() {
|
|
144
|
+
return checkboxes.map((checkbox) => checkbox.getAttribute("aria-checked") === "true");
|
|
145
|
+
}
|
|
146
|
+
function getCheckedIndices() {
|
|
147
|
+
return checkboxes.map((checkbox, index) => checkbox.getAttribute("aria-checked") === "true" ? index : -1).filter((index) => index !== -1);
|
|
148
|
+
}
|
|
149
|
+
initialize();
|
|
150
|
+
addListeners();
|
|
151
|
+
return {
|
|
152
|
+
toggleCheckbox,
|
|
153
|
+
setCheckboxState,
|
|
154
|
+
getCheckedStates,
|
|
155
|
+
getCheckedIndices,
|
|
156
|
+
cleanup
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { makeCheckboxAccessible, updateCheckboxAriaAttributes };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as ComboboxConfig, a as AccessibilityInstance } from '../Types.d-
|
|
1
|
+
import { b as ComboboxConfig, a as AccessibilityInstance } from '../Types.d-BrHSyS03.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as ComboboxConfig, a as AccessibilityInstance } from '../Types.d-
|
|
1
|
+
import { b as ComboboxConfig, a as AccessibilityInstance } from '../Types.d-BrHSyS03.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
|
package/dist/src/menu/index.cjs
CHANGED
|
@@ -149,6 +149,7 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
149
149
|
triggerButton.setAttribute("aria-controls", menuId);
|
|
150
150
|
triggerButton.setAttribute("aria-expanded", "false");
|
|
151
151
|
menuDiv.setAttribute("role", "menu");
|
|
152
|
+
menuDiv.setAttribute("aria-labelledby", triggerId);
|
|
152
153
|
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
153
154
|
const submenuInstances = /* @__PURE__ */ new Map();
|
|
154
155
|
let cachedItems = null;
|
|
@@ -285,8 +286,39 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
285
286
|
});
|
|
286
287
|
}
|
|
287
288
|
intializeMenuItems();
|
|
289
|
+
function handleTriggerKeydown(event) {
|
|
290
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
291
|
+
event.preventDefault();
|
|
292
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
293
|
+
if (isOpen) {
|
|
294
|
+
closeMenu();
|
|
295
|
+
} else {
|
|
296
|
+
openMenu();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function handleTriggerClick() {
|
|
301
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
302
|
+
if (isOpen) {
|
|
303
|
+
closeMenu();
|
|
304
|
+
} else {
|
|
305
|
+
openMenu();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function handleClickOutside(event) {
|
|
309
|
+
if (menuDiv && triggerButton && !menuDiv.contains(event.target) && !triggerButton.contains(event.target) && getComputedStyle(menuDiv).display !== "none" && triggerButton.getAttribute("aria-expanded") === "true") {
|
|
310
|
+
closeMenu();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
triggerButton.addEventListener("keydown", handleTriggerKeydown);
|
|
314
|
+
triggerButton.addEventListener("click", handleTriggerClick);
|
|
315
|
+
document.addEventListener("click", handleClickOutside);
|
|
316
|
+
triggerButton.setAttribute("data-menu-initialized", "true");
|
|
288
317
|
function cleanup() {
|
|
289
318
|
removeListeners();
|
|
319
|
+
triggerButton.removeEventListener("keydown", handleTriggerKeydown);
|
|
320
|
+
triggerButton.removeEventListener("click", handleTriggerClick);
|
|
321
|
+
document.removeEventListener("click", handleClickOutside);
|
|
290
322
|
menuDiv.style.display = "none";
|
|
291
323
|
setAria(false);
|
|
292
324
|
submenuInstances.forEach((instance) => instance.cleanup());
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AccessibilityInstance } from '../Types.d-
|
|
1
|
+
import { a as AccessibilityInstance } from '../Types.d-BrHSyS03.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
|
package/dist/src/menu/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AccessibilityInstance } from '../Types.d-
|
|
1
|
+
import { a as AccessibilityInstance } from '../Types.d-BrHSyS03.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
|
package/dist/src/menu/index.js
CHANGED
|
@@ -29,6 +29,7 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
29
29
|
triggerButton.setAttribute("aria-controls", menuId);
|
|
30
30
|
triggerButton.setAttribute("aria-expanded", "false");
|
|
31
31
|
menuDiv.setAttribute("role", "menu");
|
|
32
|
+
menuDiv.setAttribute("aria-labelledby", triggerId);
|
|
32
33
|
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
33
34
|
const submenuInstances = /* @__PURE__ */ new Map();
|
|
34
35
|
let cachedItems = null;
|
|
@@ -165,8 +166,39 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
165
166
|
});
|
|
166
167
|
}
|
|
167
168
|
intializeMenuItems();
|
|
169
|
+
function handleTriggerKeydown(event) {
|
|
170
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
173
|
+
if (isOpen) {
|
|
174
|
+
closeMenu();
|
|
175
|
+
} else {
|
|
176
|
+
openMenu();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function handleTriggerClick() {
|
|
181
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
182
|
+
if (isOpen) {
|
|
183
|
+
closeMenu();
|
|
184
|
+
} else {
|
|
185
|
+
openMenu();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function handleClickOutside(event) {
|
|
189
|
+
if (menuDiv && triggerButton && !menuDiv.contains(event.target) && !triggerButton.contains(event.target) && getComputedStyle(menuDiv).display !== "none" && triggerButton.getAttribute("aria-expanded") === "true") {
|
|
190
|
+
closeMenu();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
triggerButton.addEventListener("keydown", handleTriggerKeydown);
|
|
194
|
+
triggerButton.addEventListener("click", handleTriggerClick);
|
|
195
|
+
document.addEventListener("click", handleClickOutside);
|
|
196
|
+
triggerButton.setAttribute("data-menu-initialized", "true");
|
|
168
197
|
function cleanup() {
|
|
169
198
|
removeListeners();
|
|
199
|
+
triggerButton.removeEventListener("keydown", handleTriggerKeydown);
|
|
200
|
+
triggerButton.removeEventListener("click", handleTriggerClick);
|
|
201
|
+
document.removeEventListener("click", handleClickOutside);
|
|
170
202
|
menuDiv.style.display = "none";
|
|
171
203
|
setAria(false);
|
|
172
204
|
submenuInstances.forEach((instance) => instance.cleanup());
|
package/dist/src/radio/index.cjs
CHANGED
|
@@ -30,4 +30,126 @@ function updateRadioAriaAttributes(radioId, radiosClass, radioStates, currentPre
|
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
// src/radio/src/makeRadioAccessible/makeRadioAccessible.ts
|
|
34
|
+
function makeRadioAccessible({ radioGroupId, radiosClass, defaultSelectedIndex = 0 }) {
|
|
35
|
+
const radioGroup = document.querySelector(`#${radioGroupId}`);
|
|
36
|
+
if (!radioGroup) {
|
|
37
|
+
console.error(`[aria-ease] Element with id="${radioGroupId}" not found. Make sure the radio group container exists before calling makeRadioAccessible.`);
|
|
38
|
+
return { cleanup: () => {
|
|
39
|
+
} };
|
|
40
|
+
}
|
|
41
|
+
const radios = Array.from(radioGroup.querySelectorAll(`.${radiosClass}`));
|
|
42
|
+
if (radios.length === 0) {
|
|
43
|
+
console.error(`[aria-ease] No elements with class="${radiosClass}" found. Make sure radio buttons exist before calling makeRadioAccessible.`);
|
|
44
|
+
return { cleanup: () => {
|
|
45
|
+
} };
|
|
46
|
+
}
|
|
47
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
48
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
49
|
+
let currentSelectedIndex = defaultSelectedIndex;
|
|
50
|
+
function initialize() {
|
|
51
|
+
if (!radioGroup.getAttribute("role")) {
|
|
52
|
+
radioGroup.setAttribute("role", "radiogroup");
|
|
53
|
+
}
|
|
54
|
+
radios.forEach((radio, index) => {
|
|
55
|
+
radio.setAttribute("role", "radio");
|
|
56
|
+
radio.setAttribute("tabindex", index === currentSelectedIndex ? "0" : "-1");
|
|
57
|
+
if (index === currentSelectedIndex) {
|
|
58
|
+
radio.setAttribute("aria-checked", "true");
|
|
59
|
+
} else {
|
|
60
|
+
radio.setAttribute("aria-checked", "false");
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function selectRadio(index) {
|
|
65
|
+
if (index < 0 || index >= radios.length) {
|
|
66
|
+
console.error(`[aria-ease] Invalid radio index: ${index}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (currentSelectedIndex >= 0 && currentSelectedIndex < radios.length) {
|
|
70
|
+
radios[currentSelectedIndex].setAttribute("aria-checked", "false");
|
|
71
|
+
radios[currentSelectedIndex].setAttribute("tabindex", "-1");
|
|
72
|
+
}
|
|
73
|
+
radios[index].setAttribute("aria-checked", "true");
|
|
74
|
+
radios[index].setAttribute("tabindex", "0");
|
|
75
|
+
radios[index].focus();
|
|
76
|
+
currentSelectedIndex = index;
|
|
77
|
+
}
|
|
78
|
+
function handleRadioClick(index) {
|
|
79
|
+
return () => {
|
|
80
|
+
selectRadio(index);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function handleRadioKeydown(index) {
|
|
84
|
+
return (event) => {
|
|
85
|
+
const { key } = event;
|
|
86
|
+
let nextIndex = index;
|
|
87
|
+
switch (key) {
|
|
88
|
+
case "ArrowDown":
|
|
89
|
+
case "ArrowRight":
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
nextIndex = (index + 1) % radios.length;
|
|
92
|
+
selectRadio(nextIndex);
|
|
93
|
+
break;
|
|
94
|
+
case "ArrowUp":
|
|
95
|
+
case "ArrowLeft":
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
nextIndex = (index - 1 + radios.length) % radios.length;
|
|
98
|
+
selectRadio(nextIndex);
|
|
99
|
+
break;
|
|
100
|
+
case " ":
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
selectRadio(index);
|
|
103
|
+
break;
|
|
104
|
+
case "Home":
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
selectRadio(0);
|
|
107
|
+
break;
|
|
108
|
+
case "End":
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
selectRadio(radios.length - 1);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function addListeners() {
|
|
116
|
+
radios.forEach((radio, index) => {
|
|
117
|
+
const clickHandler = handleRadioClick(index);
|
|
118
|
+
const keydownHandler = handleRadioKeydown(index);
|
|
119
|
+
radio.addEventListener("click", clickHandler);
|
|
120
|
+
radio.addEventListener("keydown", keydownHandler);
|
|
121
|
+
handlerMap.set(radio, keydownHandler);
|
|
122
|
+
clickHandlerMap.set(radio, clickHandler);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function removeListeners() {
|
|
126
|
+
radios.forEach((radio) => {
|
|
127
|
+
const keydownHandler = handlerMap.get(radio);
|
|
128
|
+
const clickHandler = clickHandlerMap.get(radio);
|
|
129
|
+
if (keydownHandler) {
|
|
130
|
+
radio.removeEventListener("keydown", keydownHandler);
|
|
131
|
+
handlerMap.delete(radio);
|
|
132
|
+
}
|
|
133
|
+
if (clickHandler) {
|
|
134
|
+
radio.removeEventListener("click", clickHandler);
|
|
135
|
+
clickHandlerMap.delete(radio);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function cleanup() {
|
|
140
|
+
removeListeners();
|
|
141
|
+
}
|
|
142
|
+
function getSelectedIndex() {
|
|
143
|
+
return currentSelectedIndex;
|
|
144
|
+
}
|
|
145
|
+
initialize();
|
|
146
|
+
addListeners();
|
|
147
|
+
return {
|
|
148
|
+
selectRadio,
|
|
149
|
+
getSelectedIndex,
|
|
150
|
+
cleanup
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
exports.makeRadioAccessible = makeRadioAccessible;
|
|
33
155
|
exports.updateRadioAriaAttributes = updateRadioAriaAttributes;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RadioStates } from '../Types.d-
|
|
1
|
+
import { R as RadioStates, a as AccessibilityInstance } from '../Types.d-BrHSyS03.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds screen reader accessibility to multiple radio buttons. Updates the aria attributes of the radio buttons. Radio elements must possess the following aria attributes; aria-checked and aria-label.
|
|
@@ -10,4 +10,19 @@ import { R as RadioStates } from '../Types.d-uG0Hm1yK.cjs';
|
|
|
10
10
|
|
|
11
11
|
declare function updateRadioAriaAttributes(radioId: string, radiosClass: string, radioStates: RadioStates[], currentPressedRadioIndex: number): void;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Makes a radio group accessible by managing ARIA attributes, keyboard navigation, and state.
|
|
15
|
+
* Handles radio button selection with proper focus management and keyboard interactions.
|
|
16
|
+
* @param {string} radioGroupId - The id of the radio group container.
|
|
17
|
+
* @param {string} radiosClass - The shared class of all radio buttons.
|
|
18
|
+
* @param {number} defaultSelectedIndex - The index of the initially selected radio (default: 0).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface RadioConfig {
|
|
22
|
+
radioGroupId: string;
|
|
23
|
+
radiosClass: string;
|
|
24
|
+
defaultSelectedIndex?: number;
|
|
25
|
+
}
|
|
26
|
+
declare function makeRadioAccessible({ radioGroupId, radiosClass, defaultSelectedIndex }: RadioConfig): AccessibilityInstance;
|
|
27
|
+
|
|
28
|
+
export { makeRadioAccessible, updateRadioAriaAttributes };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as RadioStates } from '../Types.d-
|
|
1
|
+
import { R as RadioStates, a as AccessibilityInstance } from '../Types.d-BrHSyS03.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Adds screen reader accessibility to multiple radio buttons. Updates the aria attributes of the radio buttons. Radio elements must possess the following aria attributes; aria-checked and aria-label.
|
|
@@ -10,4 +10,19 @@ import { R as RadioStates } from '../Types.d-uG0Hm1yK.js';
|
|
|
10
10
|
|
|
11
11
|
declare function updateRadioAriaAttributes(radioId: string, radiosClass: string, radioStates: RadioStates[], currentPressedRadioIndex: number): void;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Makes a radio group accessible by managing ARIA attributes, keyboard navigation, and state.
|
|
15
|
+
* Handles radio button selection with proper focus management and keyboard interactions.
|
|
16
|
+
* @param {string} radioGroupId - The id of the radio group container.
|
|
17
|
+
* @param {string} radiosClass - The shared class of all radio buttons.
|
|
18
|
+
* @param {number} defaultSelectedIndex - The index of the initially selected radio (default: 0).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface RadioConfig {
|
|
22
|
+
radioGroupId: string;
|
|
23
|
+
radiosClass: string;
|
|
24
|
+
defaultSelectedIndex?: number;
|
|
25
|
+
}
|
|
26
|
+
declare function makeRadioAccessible({ radioGroupId, radiosClass, defaultSelectedIndex }: RadioConfig): AccessibilityInstance;
|
|
27
|
+
|
|
28
|
+
export { makeRadioAccessible, updateRadioAriaAttributes };
|
package/dist/src/radio/index.js
CHANGED
|
@@ -28,4 +28,125 @@ function updateRadioAriaAttributes(radioId, radiosClass, radioStates, currentPre
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// src/radio/src/makeRadioAccessible/makeRadioAccessible.ts
|
|
32
|
+
function makeRadioAccessible({ radioGroupId, radiosClass, defaultSelectedIndex = 0 }) {
|
|
33
|
+
const radioGroup = document.querySelector(`#${radioGroupId}`);
|
|
34
|
+
if (!radioGroup) {
|
|
35
|
+
console.error(`[aria-ease] Element with id="${radioGroupId}" not found. Make sure the radio group container exists before calling makeRadioAccessible.`);
|
|
36
|
+
return { cleanup: () => {
|
|
37
|
+
} };
|
|
38
|
+
}
|
|
39
|
+
const radios = Array.from(radioGroup.querySelectorAll(`.${radiosClass}`));
|
|
40
|
+
if (radios.length === 0) {
|
|
41
|
+
console.error(`[aria-ease] No elements with class="${radiosClass}" found. Make sure radio buttons exist before calling makeRadioAccessible.`);
|
|
42
|
+
return { cleanup: () => {
|
|
43
|
+
} };
|
|
44
|
+
}
|
|
45
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
46
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
let currentSelectedIndex = defaultSelectedIndex;
|
|
48
|
+
function initialize() {
|
|
49
|
+
if (!radioGroup.getAttribute("role")) {
|
|
50
|
+
radioGroup.setAttribute("role", "radiogroup");
|
|
51
|
+
}
|
|
52
|
+
radios.forEach((radio, index) => {
|
|
53
|
+
radio.setAttribute("role", "radio");
|
|
54
|
+
radio.setAttribute("tabindex", index === currentSelectedIndex ? "0" : "-1");
|
|
55
|
+
if (index === currentSelectedIndex) {
|
|
56
|
+
radio.setAttribute("aria-checked", "true");
|
|
57
|
+
} else {
|
|
58
|
+
radio.setAttribute("aria-checked", "false");
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function selectRadio(index) {
|
|
63
|
+
if (index < 0 || index >= radios.length) {
|
|
64
|
+
console.error(`[aria-ease] Invalid radio index: ${index}`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (currentSelectedIndex >= 0 && currentSelectedIndex < radios.length) {
|
|
68
|
+
radios[currentSelectedIndex].setAttribute("aria-checked", "false");
|
|
69
|
+
radios[currentSelectedIndex].setAttribute("tabindex", "-1");
|
|
70
|
+
}
|
|
71
|
+
radios[index].setAttribute("aria-checked", "true");
|
|
72
|
+
radios[index].setAttribute("tabindex", "0");
|
|
73
|
+
radios[index].focus();
|
|
74
|
+
currentSelectedIndex = index;
|
|
75
|
+
}
|
|
76
|
+
function handleRadioClick(index) {
|
|
77
|
+
return () => {
|
|
78
|
+
selectRadio(index);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function handleRadioKeydown(index) {
|
|
82
|
+
return (event) => {
|
|
83
|
+
const { key } = event;
|
|
84
|
+
let nextIndex = index;
|
|
85
|
+
switch (key) {
|
|
86
|
+
case "ArrowDown":
|
|
87
|
+
case "ArrowRight":
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
nextIndex = (index + 1) % radios.length;
|
|
90
|
+
selectRadio(nextIndex);
|
|
91
|
+
break;
|
|
92
|
+
case "ArrowUp":
|
|
93
|
+
case "ArrowLeft":
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
nextIndex = (index - 1 + radios.length) % radios.length;
|
|
96
|
+
selectRadio(nextIndex);
|
|
97
|
+
break;
|
|
98
|
+
case " ":
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
selectRadio(index);
|
|
101
|
+
break;
|
|
102
|
+
case "Home":
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
selectRadio(0);
|
|
105
|
+
break;
|
|
106
|
+
case "End":
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
selectRadio(radios.length - 1);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function addListeners() {
|
|
114
|
+
radios.forEach((radio, index) => {
|
|
115
|
+
const clickHandler = handleRadioClick(index);
|
|
116
|
+
const keydownHandler = handleRadioKeydown(index);
|
|
117
|
+
radio.addEventListener("click", clickHandler);
|
|
118
|
+
radio.addEventListener("keydown", keydownHandler);
|
|
119
|
+
handlerMap.set(radio, keydownHandler);
|
|
120
|
+
clickHandlerMap.set(radio, clickHandler);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function removeListeners() {
|
|
124
|
+
radios.forEach((radio) => {
|
|
125
|
+
const keydownHandler = handlerMap.get(radio);
|
|
126
|
+
const clickHandler = clickHandlerMap.get(radio);
|
|
127
|
+
if (keydownHandler) {
|
|
128
|
+
radio.removeEventListener("keydown", keydownHandler);
|
|
129
|
+
handlerMap.delete(radio);
|
|
130
|
+
}
|
|
131
|
+
if (clickHandler) {
|
|
132
|
+
radio.removeEventListener("click", clickHandler);
|
|
133
|
+
clickHandlerMap.delete(radio);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function cleanup() {
|
|
138
|
+
removeListeners();
|
|
139
|
+
}
|
|
140
|
+
function getSelectedIndex() {
|
|
141
|
+
return currentSelectedIndex;
|
|
142
|
+
}
|
|
143
|
+
initialize();
|
|
144
|
+
addListeners();
|
|
145
|
+
return {
|
|
146
|
+
selectRadio,
|
|
147
|
+
getSelectedIndex,
|
|
148
|
+
cleanup
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export { makeRadioAccessible, updateRadioAriaAttributes };
|