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
package/dist/index.js
CHANGED
|
@@ -9208,6 +9208,164 @@ function updateAccordionTriggerAriaAttributes(accordionId, accordionTriggersClas
|
|
|
9208
9208
|
});
|
|
9209
9209
|
}
|
|
9210
9210
|
|
|
9211
|
+
// src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
|
|
9212
|
+
function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultiple = false }) {
|
|
9213
|
+
const accordionContainer = document.querySelector(`#${accordionId}`);
|
|
9214
|
+
if (!accordionContainer) {
|
|
9215
|
+
console.error(`[aria-ease] Element with id="${accordionId}" not found. Make sure the accordion container exists before calling makeAccordionAccessible.`);
|
|
9216
|
+
return { cleanup: () => {
|
|
9217
|
+
} };
|
|
9218
|
+
}
|
|
9219
|
+
const triggers = Array.from(accordionContainer.querySelectorAll(`.${triggersClass}`));
|
|
9220
|
+
if (triggers.length === 0) {
|
|
9221
|
+
console.error(`[aria-ease] No elements with class="${triggersClass}" found. Make sure accordion triggers exist before calling makeAccordionAccessible.`);
|
|
9222
|
+
return { cleanup: () => {
|
|
9223
|
+
} };
|
|
9224
|
+
}
|
|
9225
|
+
const panels = Array.from(accordionContainer.querySelectorAll(`.${panelsClass}`));
|
|
9226
|
+
if (panels.length === 0) {
|
|
9227
|
+
console.error(`[aria-ease] No elements with class="${panelsClass}" found. Make sure accordion panels exist before calling makeAccordionAccessible.`);
|
|
9228
|
+
return { cleanup: () => {
|
|
9229
|
+
} };
|
|
9230
|
+
}
|
|
9231
|
+
if (triggers.length !== panels.length) {
|
|
9232
|
+
console.error(`[aria-ease] Accordion trigger/panel mismatch: found ${triggers.length} triggers but ${panels.length} panels.`);
|
|
9233
|
+
return { cleanup: () => {
|
|
9234
|
+
} };
|
|
9235
|
+
}
|
|
9236
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
9237
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
9238
|
+
function initialize() {
|
|
9239
|
+
triggers.forEach((trigger, index) => {
|
|
9240
|
+
const panel = panels[index];
|
|
9241
|
+
if (!trigger.id) {
|
|
9242
|
+
trigger.id = `${accordionId}-trigger-${index}`;
|
|
9243
|
+
}
|
|
9244
|
+
if (!panel.id) {
|
|
9245
|
+
panel.id = `${accordionId}-panel-${index}`;
|
|
9246
|
+
}
|
|
9247
|
+
trigger.setAttribute("aria-controls", panel.id);
|
|
9248
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
9249
|
+
panel.setAttribute("role", "region");
|
|
9250
|
+
panel.setAttribute("aria-labelledby", trigger.id);
|
|
9251
|
+
panel.style.display = "none";
|
|
9252
|
+
});
|
|
9253
|
+
}
|
|
9254
|
+
function expandItem(index) {
|
|
9255
|
+
if (index < 0 || index >= triggers.length) {
|
|
9256
|
+
console.error(`[aria-ease] Invalid accordion index: ${index}`);
|
|
9257
|
+
return;
|
|
9258
|
+
}
|
|
9259
|
+
const trigger = triggers[index];
|
|
9260
|
+
const panel = panels[index];
|
|
9261
|
+
trigger.setAttribute("aria-expanded", "true");
|
|
9262
|
+
panel.style.display = "block";
|
|
9263
|
+
}
|
|
9264
|
+
function collapseItem(index) {
|
|
9265
|
+
if (index < 0 || index >= triggers.length) {
|
|
9266
|
+
console.error(`[aria-ease] Invalid accordion index: ${index}`);
|
|
9267
|
+
return;
|
|
9268
|
+
}
|
|
9269
|
+
const trigger = triggers[index];
|
|
9270
|
+
const panel = panels[index];
|
|
9271
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
9272
|
+
panel.style.display = "none";
|
|
9273
|
+
}
|
|
9274
|
+
function toggleItem(index) {
|
|
9275
|
+
const trigger = triggers[index];
|
|
9276
|
+
const isExpanded = trigger.getAttribute("aria-expanded") === "true";
|
|
9277
|
+
if (isExpanded) {
|
|
9278
|
+
collapseItem(index);
|
|
9279
|
+
} else {
|
|
9280
|
+
if (!allowMultiple) {
|
|
9281
|
+
triggers.forEach((_, i) => {
|
|
9282
|
+
if (i !== index) {
|
|
9283
|
+
collapseItem(i);
|
|
9284
|
+
}
|
|
9285
|
+
});
|
|
9286
|
+
}
|
|
9287
|
+
expandItem(index);
|
|
9288
|
+
}
|
|
9289
|
+
}
|
|
9290
|
+
function handleTriggerClick(index) {
|
|
9291
|
+
return () => {
|
|
9292
|
+
toggleItem(index);
|
|
9293
|
+
};
|
|
9294
|
+
}
|
|
9295
|
+
function handleTriggerKeydown(index) {
|
|
9296
|
+
return (event) => {
|
|
9297
|
+
const { key } = event;
|
|
9298
|
+
switch (key) {
|
|
9299
|
+
case "Enter":
|
|
9300
|
+
case " ":
|
|
9301
|
+
event.preventDefault();
|
|
9302
|
+
toggleItem(index);
|
|
9303
|
+
break;
|
|
9304
|
+
case "ArrowDown":
|
|
9305
|
+
event.preventDefault();
|
|
9306
|
+
{
|
|
9307
|
+
const nextIndex = (index + 1) % triggers.length;
|
|
9308
|
+
triggers[nextIndex].focus();
|
|
9309
|
+
}
|
|
9310
|
+
break;
|
|
9311
|
+
case "ArrowUp":
|
|
9312
|
+
event.preventDefault();
|
|
9313
|
+
{
|
|
9314
|
+
const prevIndex = (index - 1 + triggers.length) % triggers.length;
|
|
9315
|
+
triggers[prevIndex].focus();
|
|
9316
|
+
}
|
|
9317
|
+
break;
|
|
9318
|
+
case "Home":
|
|
9319
|
+
event.preventDefault();
|
|
9320
|
+
triggers[0].focus();
|
|
9321
|
+
break;
|
|
9322
|
+
case "End":
|
|
9323
|
+
event.preventDefault();
|
|
9324
|
+
triggers[triggers.length - 1].focus();
|
|
9325
|
+
break;
|
|
9326
|
+
}
|
|
9327
|
+
};
|
|
9328
|
+
}
|
|
9329
|
+
function addListeners() {
|
|
9330
|
+
triggers.forEach((trigger, index) => {
|
|
9331
|
+
const clickHandler = handleTriggerClick(index);
|
|
9332
|
+
const keydownHandler = handleTriggerKeydown(index);
|
|
9333
|
+
trigger.addEventListener("click", clickHandler);
|
|
9334
|
+
trigger.addEventListener("keydown", keydownHandler);
|
|
9335
|
+
handlerMap.set(trigger, keydownHandler);
|
|
9336
|
+
clickHandlerMap.set(trigger, clickHandler);
|
|
9337
|
+
});
|
|
9338
|
+
}
|
|
9339
|
+
function removeListeners() {
|
|
9340
|
+
triggers.forEach((trigger) => {
|
|
9341
|
+
const keydownHandler = handlerMap.get(trigger);
|
|
9342
|
+
const clickHandler = clickHandlerMap.get(trigger);
|
|
9343
|
+
if (keydownHandler) {
|
|
9344
|
+
trigger.removeEventListener("keydown", keydownHandler);
|
|
9345
|
+
handlerMap.delete(trigger);
|
|
9346
|
+
}
|
|
9347
|
+
if (clickHandler) {
|
|
9348
|
+
trigger.removeEventListener("click", clickHandler);
|
|
9349
|
+
clickHandlerMap.delete(trigger);
|
|
9350
|
+
}
|
|
9351
|
+
});
|
|
9352
|
+
}
|
|
9353
|
+
function cleanup() {
|
|
9354
|
+
removeListeners();
|
|
9355
|
+
triggers.forEach((_, index) => {
|
|
9356
|
+
collapseItem(index);
|
|
9357
|
+
});
|
|
9358
|
+
}
|
|
9359
|
+
initialize();
|
|
9360
|
+
addListeners();
|
|
9361
|
+
return {
|
|
9362
|
+
expandItem,
|
|
9363
|
+
collapseItem,
|
|
9364
|
+
toggleItem,
|
|
9365
|
+
cleanup
|
|
9366
|
+
};
|
|
9367
|
+
}
|
|
9368
|
+
|
|
9211
9369
|
// src/utils/handleKeyPress/handleKeyPress.ts
|
|
9212
9370
|
function isTextInput(el) {
|
|
9213
9371
|
if (el.tagName !== "INPUT") return false;
|
|
@@ -9331,7 +9489,7 @@ function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, t
|
|
|
9331
9489
|
}
|
|
9332
9490
|
|
|
9333
9491
|
// src/block/src/makeBlockAccessible/makeBlockAccessible.ts
|
|
9334
|
-
function makeBlockAccessible(blockId, blockItemsClass) {
|
|
9492
|
+
function makeBlockAccessible({ blockId, blockItemsClass }) {
|
|
9335
9493
|
const blockDiv = document.querySelector(`#${blockId}`);
|
|
9336
9494
|
if (!blockDiv) {
|
|
9337
9495
|
console.error(`[aria-ease] Element with id="${blockId}" not found. Make sure the block element exists before calling makeBlockAccessible.`);
|
|
@@ -9410,6 +9568,134 @@ function updateCheckboxAriaAttributes(checkboxId, checkboxesClass, checkboxState
|
|
|
9410
9568
|
});
|
|
9411
9569
|
}
|
|
9412
9570
|
|
|
9571
|
+
// src/checkbox/src/makeCheckboxAccessible/makeCheckboxAccessible.ts
|
|
9572
|
+
function makeCheckboxAccessible({ checkboxGroupId, checkboxesClass }) {
|
|
9573
|
+
const checkboxGroup = document.querySelector(`#${checkboxGroupId}`);
|
|
9574
|
+
if (!checkboxGroup) {
|
|
9575
|
+
console.error(`[aria-ease] Element with id="${checkboxGroupId}" not found. Make sure the checkbox group container exists before calling makeCheckboxAccessible.`);
|
|
9576
|
+
return { cleanup: () => {
|
|
9577
|
+
} };
|
|
9578
|
+
}
|
|
9579
|
+
const checkboxes = Array.from(checkboxGroup.querySelectorAll(`.${checkboxesClass}`));
|
|
9580
|
+
if (checkboxes.length === 0) {
|
|
9581
|
+
console.error(`[aria-ease] No elements with class="${checkboxesClass}" found. Make sure checkboxes exist before calling makeCheckboxAccessible.`);
|
|
9582
|
+
return { cleanup: () => {
|
|
9583
|
+
} };
|
|
9584
|
+
}
|
|
9585
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
9586
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
9587
|
+
function initialize() {
|
|
9588
|
+
if (!checkboxGroup.getAttribute("role")) {
|
|
9589
|
+
checkboxGroup.setAttribute("role", "group");
|
|
9590
|
+
}
|
|
9591
|
+
checkboxes.forEach((checkbox) => {
|
|
9592
|
+
checkbox.setAttribute("role", "checkbox");
|
|
9593
|
+
if (!checkbox.hasAttribute("aria-checked")) {
|
|
9594
|
+
checkbox.setAttribute("aria-checked", "false");
|
|
9595
|
+
}
|
|
9596
|
+
if (!checkbox.hasAttribute("tabindex")) {
|
|
9597
|
+
checkbox.setAttribute("tabindex", "0");
|
|
9598
|
+
}
|
|
9599
|
+
});
|
|
9600
|
+
}
|
|
9601
|
+
function toggleCheckbox(index) {
|
|
9602
|
+
if (index < 0 || index >= checkboxes.length) {
|
|
9603
|
+
console.error(`[aria-ease] Invalid checkbox index: ${index}`);
|
|
9604
|
+
return;
|
|
9605
|
+
}
|
|
9606
|
+
const checkbox = checkboxes[index];
|
|
9607
|
+
const isChecked = checkbox.getAttribute("aria-checked") === "true";
|
|
9608
|
+
checkbox.setAttribute("aria-checked", isChecked ? "false" : "true");
|
|
9609
|
+
}
|
|
9610
|
+
function setCheckboxState(index, checked) {
|
|
9611
|
+
if (index < 0 || index >= checkboxes.length) {
|
|
9612
|
+
console.error(`[aria-ease] Invalid checkbox index: ${index}`);
|
|
9613
|
+
return;
|
|
9614
|
+
}
|
|
9615
|
+
checkboxes[index].setAttribute("aria-checked", checked ? "true" : "false");
|
|
9616
|
+
}
|
|
9617
|
+
function handleCheckboxClick(index) {
|
|
9618
|
+
return () => {
|
|
9619
|
+
toggleCheckbox(index);
|
|
9620
|
+
};
|
|
9621
|
+
}
|
|
9622
|
+
function handleCheckboxKeydown(index) {
|
|
9623
|
+
return (event) => {
|
|
9624
|
+
const { key } = event;
|
|
9625
|
+
switch (key) {
|
|
9626
|
+
case " ":
|
|
9627
|
+
event.preventDefault();
|
|
9628
|
+
toggleCheckbox(index);
|
|
9629
|
+
break;
|
|
9630
|
+
case "ArrowDown":
|
|
9631
|
+
event.preventDefault();
|
|
9632
|
+
{
|
|
9633
|
+
const nextIndex = (index + 1) % checkboxes.length;
|
|
9634
|
+
checkboxes[nextIndex].focus();
|
|
9635
|
+
}
|
|
9636
|
+
break;
|
|
9637
|
+
case "ArrowUp":
|
|
9638
|
+
event.preventDefault();
|
|
9639
|
+
{
|
|
9640
|
+
const prevIndex = (index - 1 + checkboxes.length) % checkboxes.length;
|
|
9641
|
+
checkboxes[prevIndex].focus();
|
|
9642
|
+
}
|
|
9643
|
+
break;
|
|
9644
|
+
case "Home":
|
|
9645
|
+
event.preventDefault();
|
|
9646
|
+
checkboxes[0].focus();
|
|
9647
|
+
break;
|
|
9648
|
+
case "End":
|
|
9649
|
+
event.preventDefault();
|
|
9650
|
+
checkboxes[checkboxes.length - 1].focus();
|
|
9651
|
+
break;
|
|
9652
|
+
}
|
|
9653
|
+
};
|
|
9654
|
+
}
|
|
9655
|
+
function addListeners() {
|
|
9656
|
+
checkboxes.forEach((checkbox, index) => {
|
|
9657
|
+
const clickHandler = handleCheckboxClick(index);
|
|
9658
|
+
const keydownHandler = handleCheckboxKeydown(index);
|
|
9659
|
+
checkbox.addEventListener("click", clickHandler);
|
|
9660
|
+
checkbox.addEventListener("keydown", keydownHandler);
|
|
9661
|
+
handlerMap.set(checkbox, keydownHandler);
|
|
9662
|
+
clickHandlerMap.set(checkbox, clickHandler);
|
|
9663
|
+
});
|
|
9664
|
+
}
|
|
9665
|
+
function removeListeners() {
|
|
9666
|
+
checkboxes.forEach((checkbox) => {
|
|
9667
|
+
const keydownHandler = handlerMap.get(checkbox);
|
|
9668
|
+
const clickHandler = clickHandlerMap.get(checkbox);
|
|
9669
|
+
if (keydownHandler) {
|
|
9670
|
+
checkbox.removeEventListener("keydown", keydownHandler);
|
|
9671
|
+
handlerMap.delete(checkbox);
|
|
9672
|
+
}
|
|
9673
|
+
if (clickHandler) {
|
|
9674
|
+
checkbox.removeEventListener("click", clickHandler);
|
|
9675
|
+
clickHandlerMap.delete(checkbox);
|
|
9676
|
+
}
|
|
9677
|
+
});
|
|
9678
|
+
}
|
|
9679
|
+
function cleanup() {
|
|
9680
|
+
removeListeners();
|
|
9681
|
+
}
|
|
9682
|
+
function getCheckedStates() {
|
|
9683
|
+
return checkboxes.map((checkbox) => checkbox.getAttribute("aria-checked") === "true");
|
|
9684
|
+
}
|
|
9685
|
+
function getCheckedIndices() {
|
|
9686
|
+
return checkboxes.map((checkbox, index) => checkbox.getAttribute("aria-checked") === "true" ? index : -1).filter((index) => index !== -1);
|
|
9687
|
+
}
|
|
9688
|
+
initialize();
|
|
9689
|
+
addListeners();
|
|
9690
|
+
return {
|
|
9691
|
+
toggleCheckbox,
|
|
9692
|
+
setCheckboxState,
|
|
9693
|
+
getCheckedStates,
|
|
9694
|
+
getCheckedIndices,
|
|
9695
|
+
cleanup
|
|
9696
|
+
};
|
|
9697
|
+
}
|
|
9698
|
+
|
|
9413
9699
|
// src/menu/src/makeMenuAccessible/makeMenuAccessible.ts
|
|
9414
9700
|
function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
9415
9701
|
const menuDiv = document.querySelector(`#${menuId}`);
|
|
@@ -9439,6 +9725,7 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9439
9725
|
triggerButton.setAttribute("aria-controls", menuId);
|
|
9440
9726
|
triggerButton.setAttribute("aria-expanded", "false");
|
|
9441
9727
|
menuDiv.setAttribute("role", "menu");
|
|
9728
|
+
menuDiv.setAttribute("aria-labelledby", triggerId);
|
|
9442
9729
|
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
9443
9730
|
const submenuInstances = /* @__PURE__ */ new Map();
|
|
9444
9731
|
let cachedItems = null;
|
|
@@ -9575,8 +9862,39 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9575
9862
|
});
|
|
9576
9863
|
}
|
|
9577
9864
|
intializeMenuItems();
|
|
9865
|
+
function handleTriggerKeydown(event) {
|
|
9866
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
9867
|
+
event.preventDefault();
|
|
9868
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
9869
|
+
if (isOpen) {
|
|
9870
|
+
closeMenu();
|
|
9871
|
+
} else {
|
|
9872
|
+
openMenu();
|
|
9873
|
+
}
|
|
9874
|
+
}
|
|
9875
|
+
}
|
|
9876
|
+
function handleTriggerClick() {
|
|
9877
|
+
const isOpen = menuDiv.style.display !== "none";
|
|
9878
|
+
if (isOpen) {
|
|
9879
|
+
closeMenu();
|
|
9880
|
+
} else {
|
|
9881
|
+
openMenu();
|
|
9882
|
+
}
|
|
9883
|
+
}
|
|
9884
|
+
function handleClickOutside(event) {
|
|
9885
|
+
if (menuDiv && triggerButton && !menuDiv.contains(event.target) && !triggerButton.contains(event.target) && getComputedStyle(menuDiv).display !== "none" && triggerButton.getAttribute("aria-expanded") === "true") {
|
|
9886
|
+
closeMenu();
|
|
9887
|
+
}
|
|
9888
|
+
}
|
|
9889
|
+
triggerButton.addEventListener("keydown", handleTriggerKeydown);
|
|
9890
|
+
triggerButton.addEventListener("click", handleTriggerClick);
|
|
9891
|
+
document.addEventListener("click", handleClickOutside);
|
|
9892
|
+
triggerButton.setAttribute("data-menu-initialized", "true");
|
|
9578
9893
|
function cleanup() {
|
|
9579
9894
|
removeListeners();
|
|
9895
|
+
triggerButton.removeEventListener("keydown", handleTriggerKeydown);
|
|
9896
|
+
triggerButton.removeEventListener("click", handleTriggerClick);
|
|
9897
|
+
document.removeEventListener("click", handleClickOutside);
|
|
9580
9898
|
menuDiv.style.display = "none";
|
|
9581
9899
|
setAria(false);
|
|
9582
9900
|
submenuInstances.forEach((instance) => instance.cleanup());
|
|
@@ -9619,6 +9937,127 @@ function updateRadioAriaAttributes(radioId, radiosClass, radioStates, currentPre
|
|
|
9619
9937
|
});
|
|
9620
9938
|
}
|
|
9621
9939
|
|
|
9940
|
+
// src/radio/src/makeRadioAccessible/makeRadioAccessible.ts
|
|
9941
|
+
function makeRadioAccessible({ radioGroupId, radiosClass, defaultSelectedIndex = 0 }) {
|
|
9942
|
+
const radioGroup = document.querySelector(`#${radioGroupId}`);
|
|
9943
|
+
if (!radioGroup) {
|
|
9944
|
+
console.error(`[aria-ease] Element with id="${radioGroupId}" not found. Make sure the radio group container exists before calling makeRadioAccessible.`);
|
|
9945
|
+
return { cleanup: () => {
|
|
9946
|
+
} };
|
|
9947
|
+
}
|
|
9948
|
+
const radios = Array.from(radioGroup.querySelectorAll(`.${radiosClass}`));
|
|
9949
|
+
if (radios.length === 0) {
|
|
9950
|
+
console.error(`[aria-ease] No elements with class="${radiosClass}" found. Make sure radio buttons exist before calling makeRadioAccessible.`);
|
|
9951
|
+
return { cleanup: () => {
|
|
9952
|
+
} };
|
|
9953
|
+
}
|
|
9954
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
9955
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
9956
|
+
let currentSelectedIndex = defaultSelectedIndex;
|
|
9957
|
+
function initialize() {
|
|
9958
|
+
if (!radioGroup.getAttribute("role")) {
|
|
9959
|
+
radioGroup.setAttribute("role", "radiogroup");
|
|
9960
|
+
}
|
|
9961
|
+
radios.forEach((radio, index) => {
|
|
9962
|
+
radio.setAttribute("role", "radio");
|
|
9963
|
+
radio.setAttribute("tabindex", index === currentSelectedIndex ? "0" : "-1");
|
|
9964
|
+
if (index === currentSelectedIndex) {
|
|
9965
|
+
radio.setAttribute("aria-checked", "true");
|
|
9966
|
+
} else {
|
|
9967
|
+
radio.setAttribute("aria-checked", "false");
|
|
9968
|
+
}
|
|
9969
|
+
});
|
|
9970
|
+
}
|
|
9971
|
+
function selectRadio(index) {
|
|
9972
|
+
if (index < 0 || index >= radios.length) {
|
|
9973
|
+
console.error(`[aria-ease] Invalid radio index: ${index}`);
|
|
9974
|
+
return;
|
|
9975
|
+
}
|
|
9976
|
+
if (currentSelectedIndex >= 0 && currentSelectedIndex < radios.length) {
|
|
9977
|
+
radios[currentSelectedIndex].setAttribute("aria-checked", "false");
|
|
9978
|
+
radios[currentSelectedIndex].setAttribute("tabindex", "-1");
|
|
9979
|
+
}
|
|
9980
|
+
radios[index].setAttribute("aria-checked", "true");
|
|
9981
|
+
radios[index].setAttribute("tabindex", "0");
|
|
9982
|
+
radios[index].focus();
|
|
9983
|
+
currentSelectedIndex = index;
|
|
9984
|
+
}
|
|
9985
|
+
function handleRadioClick(index) {
|
|
9986
|
+
return () => {
|
|
9987
|
+
selectRadio(index);
|
|
9988
|
+
};
|
|
9989
|
+
}
|
|
9990
|
+
function handleRadioKeydown(index) {
|
|
9991
|
+
return (event) => {
|
|
9992
|
+
const { key } = event;
|
|
9993
|
+
let nextIndex = index;
|
|
9994
|
+
switch (key) {
|
|
9995
|
+
case "ArrowDown":
|
|
9996
|
+
case "ArrowRight":
|
|
9997
|
+
event.preventDefault();
|
|
9998
|
+
nextIndex = (index + 1) % radios.length;
|
|
9999
|
+
selectRadio(nextIndex);
|
|
10000
|
+
break;
|
|
10001
|
+
case "ArrowUp":
|
|
10002
|
+
case "ArrowLeft":
|
|
10003
|
+
event.preventDefault();
|
|
10004
|
+
nextIndex = (index - 1 + radios.length) % radios.length;
|
|
10005
|
+
selectRadio(nextIndex);
|
|
10006
|
+
break;
|
|
10007
|
+
case " ":
|
|
10008
|
+
event.preventDefault();
|
|
10009
|
+
selectRadio(index);
|
|
10010
|
+
break;
|
|
10011
|
+
case "Home":
|
|
10012
|
+
event.preventDefault();
|
|
10013
|
+
selectRadio(0);
|
|
10014
|
+
break;
|
|
10015
|
+
case "End":
|
|
10016
|
+
event.preventDefault();
|
|
10017
|
+
selectRadio(radios.length - 1);
|
|
10018
|
+
break;
|
|
10019
|
+
}
|
|
10020
|
+
};
|
|
10021
|
+
}
|
|
10022
|
+
function addListeners() {
|
|
10023
|
+
radios.forEach((radio, index) => {
|
|
10024
|
+
const clickHandler = handleRadioClick(index);
|
|
10025
|
+
const keydownHandler = handleRadioKeydown(index);
|
|
10026
|
+
radio.addEventListener("click", clickHandler);
|
|
10027
|
+
radio.addEventListener("keydown", keydownHandler);
|
|
10028
|
+
handlerMap.set(radio, keydownHandler);
|
|
10029
|
+
clickHandlerMap.set(radio, clickHandler);
|
|
10030
|
+
});
|
|
10031
|
+
}
|
|
10032
|
+
function removeListeners() {
|
|
10033
|
+
radios.forEach((radio) => {
|
|
10034
|
+
const keydownHandler = handlerMap.get(radio);
|
|
10035
|
+
const clickHandler = clickHandlerMap.get(radio);
|
|
10036
|
+
if (keydownHandler) {
|
|
10037
|
+
radio.removeEventListener("keydown", keydownHandler);
|
|
10038
|
+
handlerMap.delete(radio);
|
|
10039
|
+
}
|
|
10040
|
+
if (clickHandler) {
|
|
10041
|
+
radio.removeEventListener("click", clickHandler);
|
|
10042
|
+
clickHandlerMap.delete(radio);
|
|
10043
|
+
}
|
|
10044
|
+
});
|
|
10045
|
+
}
|
|
10046
|
+
function cleanup() {
|
|
10047
|
+
removeListeners();
|
|
10048
|
+
}
|
|
10049
|
+
function getSelectedIndex() {
|
|
10050
|
+
return currentSelectedIndex;
|
|
10051
|
+
}
|
|
10052
|
+
initialize();
|
|
10053
|
+
addListeners();
|
|
10054
|
+
return {
|
|
10055
|
+
selectRadio,
|
|
10056
|
+
getSelectedIndex,
|
|
10057
|
+
cleanup
|
|
10058
|
+
};
|
|
10059
|
+
}
|
|
10060
|
+
|
|
9622
10061
|
// src/toggle/src/updateToggleAriaAttribute/updateToggleAriaAttribute.ts
|
|
9623
10062
|
function updateToggleAriaAttribute(toggleId, togglesClass, toggleStates, currentPressedToggleIndex) {
|
|
9624
10063
|
const toggleDiv = document.querySelector(`#${toggleId}`);
|
|
@@ -9646,6 +10085,150 @@ function updateToggleAriaAttribute(toggleId, togglesClass, toggleStates, current
|
|
|
9646
10085
|
});
|
|
9647
10086
|
}
|
|
9648
10087
|
|
|
10088
|
+
// src/toggle/src/makeTogggleAccessible/makeToggleAccessible.ts
|
|
10089
|
+
function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle = true }) {
|
|
10090
|
+
const toggleContainer = document.querySelector(`#${toggleId}`);
|
|
10091
|
+
if (!toggleContainer) {
|
|
10092
|
+
console.error(`[aria-ease] Element with id="${toggleId}" not found. Make sure the toggle element exists before calling makeToggleAccessible.`);
|
|
10093
|
+
return { cleanup: () => {
|
|
10094
|
+
} };
|
|
10095
|
+
}
|
|
10096
|
+
let toggles;
|
|
10097
|
+
if (isSingleToggle) {
|
|
10098
|
+
toggles = [toggleContainer];
|
|
10099
|
+
} else {
|
|
10100
|
+
if (!togglesClass) {
|
|
10101
|
+
console.error(`[aria-ease] togglesClass is required when isSingleToggle is false.`);
|
|
10102
|
+
return { cleanup: () => {
|
|
10103
|
+
} };
|
|
10104
|
+
}
|
|
10105
|
+
toggles = Array.from(toggleContainer.querySelectorAll(`.${togglesClass}`));
|
|
10106
|
+
if (toggles.length === 0) {
|
|
10107
|
+
console.error(`[aria-ease] No elements with class="${togglesClass}" found. Make sure toggle buttons exist before calling makeToggleAccessible.`);
|
|
10108
|
+
return { cleanup: () => {
|
|
10109
|
+
} };
|
|
10110
|
+
}
|
|
10111
|
+
}
|
|
10112
|
+
const handlerMap = /* @__PURE__ */ new WeakMap();
|
|
10113
|
+
const clickHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
10114
|
+
function initialize() {
|
|
10115
|
+
toggles.forEach((toggle) => {
|
|
10116
|
+
if (toggle.tagName.toLowerCase() !== "button" && !toggle.getAttribute("role")) {
|
|
10117
|
+
toggle.setAttribute("role", "button");
|
|
10118
|
+
}
|
|
10119
|
+
if (!toggle.hasAttribute("aria-pressed")) {
|
|
10120
|
+
toggle.setAttribute("aria-pressed", "false");
|
|
10121
|
+
}
|
|
10122
|
+
if (!toggle.hasAttribute("tabindex")) {
|
|
10123
|
+
toggle.setAttribute("tabindex", "0");
|
|
10124
|
+
}
|
|
10125
|
+
});
|
|
10126
|
+
}
|
|
10127
|
+
function toggleButton(index) {
|
|
10128
|
+
if (index < 0 || index >= toggles.length) {
|
|
10129
|
+
console.error(`[aria-ease] Invalid toggle index: ${index}`);
|
|
10130
|
+
return;
|
|
10131
|
+
}
|
|
10132
|
+
const toggle = toggles[index];
|
|
10133
|
+
const isPressed = toggle.getAttribute("aria-pressed") === "true";
|
|
10134
|
+
toggle.setAttribute("aria-pressed", isPressed ? "false" : "true");
|
|
10135
|
+
}
|
|
10136
|
+
function setPressed(index, pressed) {
|
|
10137
|
+
if (index < 0 || index >= toggles.length) {
|
|
10138
|
+
console.error(`[aria-ease] Invalid toggle index: ${index}`);
|
|
10139
|
+
return;
|
|
10140
|
+
}
|
|
10141
|
+
toggles[index].setAttribute("aria-pressed", pressed ? "true" : "false");
|
|
10142
|
+
}
|
|
10143
|
+
function handleToggleClick(index) {
|
|
10144
|
+
return () => {
|
|
10145
|
+
toggleButton(index);
|
|
10146
|
+
};
|
|
10147
|
+
}
|
|
10148
|
+
function handleToggleKeydown(index) {
|
|
10149
|
+
return (event) => {
|
|
10150
|
+
const { key } = event;
|
|
10151
|
+
switch (key) {
|
|
10152
|
+
case "Enter":
|
|
10153
|
+
case " ":
|
|
10154
|
+
event.preventDefault();
|
|
10155
|
+
toggleButton(index);
|
|
10156
|
+
break;
|
|
10157
|
+
case "ArrowDown":
|
|
10158
|
+
case "ArrowRight":
|
|
10159
|
+
if (!isSingleToggle && toggles.length > 1) {
|
|
10160
|
+
event.preventDefault();
|
|
10161
|
+
const nextIndex = (index + 1) % toggles.length;
|
|
10162
|
+
toggles[nextIndex].focus();
|
|
10163
|
+
}
|
|
10164
|
+
break;
|
|
10165
|
+
case "ArrowUp":
|
|
10166
|
+
case "ArrowLeft":
|
|
10167
|
+
if (!isSingleToggle && toggles.length > 1) {
|
|
10168
|
+
event.preventDefault();
|
|
10169
|
+
const prevIndex = (index - 1 + toggles.length) % toggles.length;
|
|
10170
|
+
toggles[prevIndex].focus();
|
|
10171
|
+
}
|
|
10172
|
+
break;
|
|
10173
|
+
case "Home":
|
|
10174
|
+
if (!isSingleToggle && toggles.length > 1) {
|
|
10175
|
+
event.preventDefault();
|
|
10176
|
+
toggles[0].focus();
|
|
10177
|
+
}
|
|
10178
|
+
break;
|
|
10179
|
+
case "End":
|
|
10180
|
+
if (!isSingleToggle && toggles.length > 1) {
|
|
10181
|
+
event.preventDefault();
|
|
10182
|
+
toggles[toggles.length - 1].focus();
|
|
10183
|
+
}
|
|
10184
|
+
break;
|
|
10185
|
+
}
|
|
10186
|
+
};
|
|
10187
|
+
}
|
|
10188
|
+
function addListeners() {
|
|
10189
|
+
toggles.forEach((toggle, index) => {
|
|
10190
|
+
const clickHandler = handleToggleClick(index);
|
|
10191
|
+
const keydownHandler = handleToggleKeydown(index);
|
|
10192
|
+
toggle.addEventListener("click", clickHandler);
|
|
10193
|
+
toggle.addEventListener("keydown", keydownHandler);
|
|
10194
|
+
handlerMap.set(toggle, keydownHandler);
|
|
10195
|
+
clickHandlerMap.set(toggle, clickHandler);
|
|
10196
|
+
});
|
|
10197
|
+
}
|
|
10198
|
+
function removeListeners() {
|
|
10199
|
+
toggles.forEach((toggle) => {
|
|
10200
|
+
const keydownHandler = handlerMap.get(toggle);
|
|
10201
|
+
const clickHandler = clickHandlerMap.get(toggle);
|
|
10202
|
+
if (keydownHandler) {
|
|
10203
|
+
toggle.removeEventListener("keydown", keydownHandler);
|
|
10204
|
+
handlerMap.delete(toggle);
|
|
10205
|
+
}
|
|
10206
|
+
if (clickHandler) {
|
|
10207
|
+
toggle.removeEventListener("click", clickHandler);
|
|
10208
|
+
clickHandlerMap.delete(toggle);
|
|
10209
|
+
}
|
|
10210
|
+
});
|
|
10211
|
+
}
|
|
10212
|
+
function cleanup() {
|
|
10213
|
+
removeListeners();
|
|
10214
|
+
}
|
|
10215
|
+
function getPressedStates() {
|
|
10216
|
+
return toggles.map((toggle) => toggle.getAttribute("aria-pressed") === "true");
|
|
10217
|
+
}
|
|
10218
|
+
function getPressedIndices() {
|
|
10219
|
+
return toggles.map((toggle, index) => toggle.getAttribute("aria-pressed") === "true" ? index : -1).filter((index) => index !== -1);
|
|
10220
|
+
}
|
|
10221
|
+
initialize();
|
|
10222
|
+
addListeners();
|
|
10223
|
+
return {
|
|
10224
|
+
toggleButton,
|
|
10225
|
+
setPressed,
|
|
10226
|
+
getPressedStates,
|
|
10227
|
+
getPressedIndices,
|
|
10228
|
+
cleanup
|
|
10229
|
+
};
|
|
10230
|
+
}
|
|
10231
|
+
|
|
9649
10232
|
// src/combobox/src/makeComboBoxAccessible.ts
|
|
9650
10233
|
function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config: config2 }) {
|
|
9651
10234
|
const comboboxInput = document.getElementById(`${comboboxInputId}`);
|
|
@@ -13480,7 +14063,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
13480
14063
|
URL must include protocol (e.g., "http://localhost:5173/test")`
|
|
13481
14064
|
);
|
|
13482
14065
|
}
|
|
13483
|
-
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-
|
|
14066
|
+
const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-UQQI5MYS.js");
|
|
13484
14067
|
contract = await runContractTestsPlaywright(componentName, url);
|
|
13485
14068
|
} else {
|
|
13486
14069
|
console.log(`\u{1F9EA} Running jsdom tests (limited event handling)`);
|
|
@@ -13554,9 +14137,13 @@ if (typeof window === "undefined") {
|
|
|
13554
14137
|
};
|
|
13555
14138
|
}
|
|
13556
14139
|
export {
|
|
14140
|
+
makeAccordionAccessible,
|
|
13557
14141
|
makeBlockAccessible,
|
|
14142
|
+
makeCheckboxAccessible,
|
|
13558
14143
|
makeComboboxAccessible,
|
|
13559
14144
|
makeMenuAccessible,
|
|
14145
|
+
makeRadioAccessible,
|
|
14146
|
+
makeToggleAccessible,
|
|
13560
14147
|
testUiComponent,
|
|
13561
14148
|
updateAccordionTriggerAriaAttributes,
|
|
13562
14149
|
updateCheckboxAriaAttributes,
|
|
@@ -19,6 +19,23 @@ interface AccessibilityInstance {
|
|
|
19
19
|
refresh?: () => void;
|
|
20
20
|
openMenu?: () => void;
|
|
21
21
|
closeMenu?: () => void;
|
|
22
|
+
// Accordion methods
|
|
23
|
+
expandItem?: (index: number) => void;
|
|
24
|
+
collapseItem?: (index: number) => void;
|
|
25
|
+
toggleItem?: (index: number) => void;
|
|
26
|
+
// Radio methods
|
|
27
|
+
selectRadio?: (index: number) => void;
|
|
28
|
+
getSelectedIndex?: () => number;
|
|
29
|
+
// Checkbox methods
|
|
30
|
+
toggleCheckbox?: (index: number) => void;
|
|
31
|
+
setCheckboxState?: (index: number, checked: boolean) => void;
|
|
32
|
+
getCheckedStates?: () => boolean[];
|
|
33
|
+
getCheckedIndices?: () => number[];
|
|
34
|
+
// Toggle methods
|
|
35
|
+
toggleButton?: (index: number) => void;
|
|
36
|
+
setPressed?: (index: number, pressed: boolean) => void;
|
|
37
|
+
getPressedStates?: () => boolean[];
|
|
38
|
+
getPressedIndices?: () => number[];
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
interface ComboboxConfig {
|
|
@@ -19,6 +19,23 @@ interface AccessibilityInstance {
|
|
|
19
19
|
refresh?: () => void;
|
|
20
20
|
openMenu?: () => void;
|
|
21
21
|
closeMenu?: () => void;
|
|
22
|
+
// Accordion methods
|
|
23
|
+
expandItem?: (index: number) => void;
|
|
24
|
+
collapseItem?: (index: number) => void;
|
|
25
|
+
toggleItem?: (index: number) => void;
|
|
26
|
+
// Radio methods
|
|
27
|
+
selectRadio?: (index: number) => void;
|
|
28
|
+
getSelectedIndex?: () => number;
|
|
29
|
+
// Checkbox methods
|
|
30
|
+
toggleCheckbox?: (index: number) => void;
|
|
31
|
+
setCheckboxState?: (index: number, checked: boolean) => void;
|
|
32
|
+
getCheckedStates?: () => boolean[];
|
|
33
|
+
getCheckedIndices?: () => number[];
|
|
34
|
+
// Toggle methods
|
|
35
|
+
toggleButton?: (index: number) => void;
|
|
36
|
+
setPressed?: (index: number, pressed: boolean) => void;
|
|
37
|
+
getPressedStates?: () => boolean[];
|
|
38
|
+
getPressedIndices?: () => number[];
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
interface ComboboxConfig {
|