aria-ease 2.2.3 → 2.4.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.
Files changed (101) hide show
  1. package/README.md +407 -27
  2. package/bin/cli.cjs +475 -0
  3. package/bin/cli.cjs.map +1 -0
  4. package/bin/cli.d.ts.map +1 -0
  5. package/bin/cli.js +452 -0
  6. package/bin/cli.js.map +1 -0
  7. package/bin/{audit-cli.ts → cli.ts} +25 -20
  8. package/bin/configLoader.d.ts +19 -0
  9. package/bin/configLoader.d.ts.map +1 -0
  10. package/bin/configLoader.js +155 -0
  11. package/bin/configLoader.ts +170 -0
  12. package/bin/contractTestRunnerPlaywright-2LQHVMXT.js +426 -0
  13. package/bin/contractTestRunnerPlaywright-2LQHVMXT.js.map +1 -0
  14. package/dist/chunk-4F6O5RKZ.js +207 -0
  15. package/dist/chunk-4F6O5RKZ.js.map +1 -0
  16. package/dist/contractTestRunnerPlaywright-FM6MK6DY.js +255 -0
  17. package/dist/contractTestRunnerPlaywright-FM6MK6DY.js.map +1 -0
  18. package/dist/index.cjs +13644 -233
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +102 -7
  21. package/dist/index.d.ts +102 -7
  22. package/dist/index.js +13191 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/{Types.d-p85gN5m_.d.cts → src/Types.d-BbztRe-S.d.cts} +0 -5
  25. package/dist/{Types.d-p85gN5m_.d.ts → src/Types.d-BbztRe-S.d.ts} +0 -5
  26. package/dist/src/accordion/index.cjs +25 -19
  27. package/dist/src/accordion/index.cjs.map +1 -1
  28. package/dist/src/accordion/index.d.cts +1 -1
  29. package/dist/src/accordion/index.d.ts +1 -1
  30. package/dist/src/accordion/index.js +28 -1
  31. package/dist/src/accordion/index.js.map +1 -1
  32. package/dist/src/block/index.cjs +99 -99
  33. package/dist/src/block/index.cjs.map +1 -1
  34. package/dist/src/block/index.d.cts +4 -2
  35. package/dist/src/block/index.d.ts +4 -2
  36. package/dist/src/block/index.js +42 -2
  37. package/dist/src/block/index.js.map +1 -1
  38. package/dist/src/checkbox/index.cjs +30 -13
  39. package/dist/src/checkbox/index.cjs.map +1 -1
  40. package/dist/src/checkbox/index.d.cts +1 -1
  41. package/dist/src/checkbox/index.d.ts +1 -1
  42. package/dist/src/checkbox/index.js +33 -1
  43. package/dist/src/checkbox/index.js.map +1 -1
  44. package/dist/src/chunk-MNMWQWXH.js +117 -0
  45. package/dist/src/chunk-MNMWQWXH.js.map +1 -0
  46. package/dist/src/menu/index.cjs +208 -130
  47. package/dist/src/menu/index.cjs.map +1 -1
  48. package/dist/src/menu/index.d.cts +9 -3
  49. package/dist/src/menu/index.d.ts +9 -3
  50. package/dist/src/menu/index.js +118 -2
  51. package/dist/src/menu/index.js.map +1 -1
  52. package/dist/src/radio/index.cjs +29 -16
  53. package/dist/src/radio/index.cjs.map +1 -1
  54. package/dist/src/radio/index.d.cts +1 -1
  55. package/dist/src/radio/index.d.ts +1 -1
  56. package/dist/src/radio/index.js +32 -1
  57. package/dist/src/radio/index.js.map +1 -1
  58. package/dist/src/toggle/index.cjs +26 -16
  59. package/dist/src/toggle/index.cjs.map +1 -1
  60. package/dist/src/toggle/index.d.cts +1 -1
  61. package/dist/src/toggle/index.d.ts +1 -1
  62. package/dist/src/toggle/index.js +29 -1
  63. package/dist/src/toggle/index.js.map +1 -1
  64. package/dist/src/utils/test/chunk-UAS6V5MH.js +203 -0
  65. package/dist/src/utils/test/chunk-UAS6V5MH.js.map +1 -0
  66. package/dist/src/utils/test/contractTestRunnerPlaywright-IBC4FHWK.js +251 -0
  67. package/dist/src/utils/test/contractTestRunnerPlaywright-IBC4FHWK.js.map +1 -0
  68. package/dist/src/utils/test/contracts/MenuContract.json +343 -0
  69. package/dist/src/utils/test/index.cjs +13092 -0
  70. package/dist/src/utils/test/index.cjs.map +1 -0
  71. package/dist/src/utils/test/index.d.cts +16 -0
  72. package/dist/src/utils/test/index.d.ts +16 -0
  73. package/dist/src/utils/test/index.js +12608 -0
  74. package/dist/src/utils/test/index.js.map +1 -0
  75. package/package.json +33 -12
  76. package/bin/audit-cli.cjs +0 -876
  77. package/bin/audit-cli.cjs.map +0 -1
  78. package/bin/audit-cli.js +0 -779
  79. package/bin/audit-cli.js.map +0 -1
  80. package/dist/chunk-4366LRNM.js +0 -38
  81. package/dist/chunk-4366LRNM.js.map +0 -1
  82. package/dist/chunk-5HQ6LLC5.js +0 -21
  83. package/dist/chunk-5HQ6LLC5.js.map +0 -1
  84. package/dist/chunk-FBQ5LF2T.js +0 -21
  85. package/dist/chunk-FBQ5LF2T.js.map +0 -1
  86. package/dist/chunk-KVTLMA4J.js +0 -58
  87. package/dist/chunk-KVTLMA4J.js.map +0 -1
  88. package/dist/chunk-MEA5U2G4.js +0 -24
  89. package/dist/chunk-MEA5U2G4.js.map +0 -1
  90. package/dist/chunk-RK3JUAFZ.js +0 -18
  91. package/dist/chunk-RK3JUAFZ.js.map +0 -1
  92. package/dist/chunk-RT5IROW4.js +0 -99
  93. package/dist/chunk-RT5IROW4.js.map +0 -1
  94. package/dist/src/utils/audit/audit.cjs +0 -239
  95. package/dist/src/utils/audit/audit.cjs.map +0 -1
  96. package/dist/src/utils/audit/audit.d.cts +0 -5
  97. package/dist/src/utils/audit/audit.d.ts +0 -5
  98. package/dist/src/utils/audit/audit.js +0 -232
  99. package/dist/src/utils/audit/audit.js.map +0 -1
  100. /package/bin/{audit-cli.d.cts → cli.d.cts} +0 -0
  101. /package/bin/{audit-cli.d.ts → cli.d.ts} +0 -0
@@ -1,2 +1,34 @@
1
- export { updateCheckboxAriaAttributes } from '../../chunk-RK3JUAFZ.js'; //# sourceMappingURL=index.js.map
1
+ // src/checkbox/src/updateCheckboxAriaAttributes/updateCheckboxAriaAttributes.ts
2
+ function updateCheckboxAriaAttributes(checkboxId, checkboxesClass, checkboxStates, currentPressedCheckboxIndex) {
3
+ const checkboxDiv = document.querySelector(`#${checkboxId}`);
4
+ if (!checkboxDiv) {
5
+ console.error(`[aria-ease] Invalid checkbox main div id provided. No checkbox div with id '${checkboxDiv} found.'`);
6
+ return;
7
+ }
8
+ const checkboxItems = Array.from(document.querySelectorAll(`.${checkboxesClass}`));
9
+ if (checkboxItems.length === 0) {
10
+ console.error(`[aria-ease] Element with class="${checkboxesClass}" not found. Make sure the checkbox items exist before calling updateCheckboxAriaAttributes.`);
11
+ return;
12
+ }
13
+ if (checkboxStates.length === 0) {
14
+ console.error(`[aria-ease] Checkbox states array is empty. Make sure the checkboxStates array is populated before calling updateCheckboxAriaAttributes.`);
15
+ return;
16
+ }
17
+ if (currentPressedCheckboxIndex < 0 || currentPressedCheckboxIndex >= checkboxStates.length) {
18
+ console.error(`[aria-ease] Checkbox index ${currentPressedCheckboxIndex} is out of bounds for states array of length ${checkboxStates.length}.`);
19
+ return;
20
+ }
21
+ checkboxItems.forEach((checkbox, index) => {
22
+ if (index === currentPressedCheckboxIndex) {
23
+ const checked = checkbox.getAttribute("aria-checked");
24
+ const shouldBeChecked = checkboxStates[index].checked ? "true" : "false";
25
+ if (checked && checked !== shouldBeChecked) {
26
+ checkbox.setAttribute("aria-checked", shouldBeChecked);
27
+ }
28
+ }
29
+ });
30
+ }
31
+
32
+ export { updateCheckboxAriaAttributes };
33
+ //# sourceMappingURL=index.js.map
2
34
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/macx/aria-ease/package/dist/src/checkbox/index.js"],"names":["updateCheckboxAriaAttributes"],"mappings":"AAAA,SAASA,4BAA4B,QAAQ,0BAA0B,CACvE,iCAAiC","sourcesContent":["export { updateCheckboxAriaAttributes } from '../../chunk-RK3JUAFZ.js';\n//# sourceMappingURL=index.js.map\n"]}
1
+ {"version":3,"sources":["../../../src/checkbox/src/updateCheckboxAriaAttributes/updateCheckboxAriaAttributes.ts"],"names":[],"mappings":";AAUO,SAAS,4BAAA,CAA6B,UAAA,EAAoB,eAAA,EAAyB,cAAA,EAAkC,2BAAA,EAA2C;AACrK,EAAA,MAAM,WAAA,GAAkC,QAAA,CAAS,aAAA,CAAc,CAAA,CAAA,EAAI,UAAU,CAAA,CAAE,CAAA;AAC/E,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,4EAAA,EAA+E,WAAW,CAAA,QAAA,CAAU,CAAA;AAClH,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,aAAA,GAA+B,MAAM,IAAA,CAAK,QAAA,CAAS,iBAAiB,CAAA,CAAA,EAAI,eAAe,EAAE,CAAC,CAAA;AAChG,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,gCAAA,EAAmC,eAAe,CAAA,4FAAA,CAA8F,CAAA;AAC9J,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAC/B,IAAA,OAAA,CAAQ,MAAM,CAAA,wIAAA,CAA0I,CAAA;AACxJ,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,2BAAA,GAA8B,CAAA,IAAK,2BAAA,IAA+B,cAAA,CAAe,MAAA,EAAQ;AAC3F,IAAA,OAAA,CAAQ,MAAM,CAAA,2BAAA,EAA8B,2BAA2B,CAAA,6CAAA,EAAgD,cAAA,CAAe,MAAM,CAAA,CAAA,CAAG,CAAA;AAC/I,IAAA;AAAA,EACF;AAEA,EAAA,aAAA,CAAc,OAAA,CAAQ,CAAC,QAAA,EAAuB,KAAA,KAAkB;AAC9D,IAAA,IAAI,UAAU,2BAAA,EAA6B;AACzC,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,YAAA,CAAa,cAAc,CAAA;AACpD,MAAA,MAAM,eAAA,GAAkB,cAAA,CAAe,KAAK,CAAA,CAAE,UAAU,MAAA,GAAS,OAAA;AACjE,MAAA,IAAI,OAAA,IAAW,YAAY,eAAA,EAAiB;AAC1C,QAAA,QAAA,CAAS,YAAA,CAAa,gBAAgB,eAAe,CAAA;AAAA,MACvD;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH","file":"index.js","sourcesContent":["/**\n * Adds screen reader accessibility to multiple checkboxes. Updates the aria attributes of the checkboxes. Checkbox elements must possess the following aria attributes; aria-checked and aria-label.\n * @param {string} checkboxId The id of the checkbox parent container.\n * @param {string} checkboxesClass The shared class of all the checkboxes.\n * @param {CheckboxStates[]} checkboxStates Array of objects containing checkboxes state information.\n * @param {number} currentPressedCheckboxIndex Index of the currently checked or unchecked checkbox.\n*/\n\nimport { CheckboxStates } from \"../../../../Types\";\n\nexport function updateCheckboxAriaAttributes(checkboxId: string, checkboxesClass: string, checkboxStates: CheckboxStates[], currentPressedCheckboxIndex: number): void {\n const checkboxDiv: HTMLElement | null = document.querySelector(`#${checkboxId}`);\n if (!checkboxDiv) {\n console.error(`[aria-ease] Invalid checkbox main div id provided. No checkbox div with id '${checkboxDiv} found.'`);\n return;\n }\n \n const checkboxItems: HTMLElement[] = Array.from(document.querySelectorAll(`.${checkboxesClass}`));\n if (checkboxItems.length === 0) {\n console.error(`[aria-ease] Element with class=\"${checkboxesClass}\" not found. Make sure the checkbox items exist before calling updateCheckboxAriaAttributes.`);\n return;\n };\n\n if (checkboxStates.length === 0) {\n console.error(`[aria-ease] Checkbox states array is empty. Make sure the checkboxStates array is populated before calling updateCheckboxAriaAttributes.`);\n return;\n }\n\n if (currentPressedCheckboxIndex < 0 || currentPressedCheckboxIndex >= checkboxStates.length) {\n console.error(`[aria-ease] Checkbox index ${currentPressedCheckboxIndex} is out of bounds for states array of length ${checkboxStates.length}.`);\n return;\n }\n\n checkboxItems.forEach((checkbox: HTMLElement, index: number) => {\n if (index === currentPressedCheckboxIndex) {\n const checked = checkbox.getAttribute(\"aria-checked\");\n const shouldBeChecked = checkboxStates[index].checked ? 'true' : 'false';\n if (checked && checked !== shouldBeChecked) {\n checkbox.setAttribute(\"aria-checked\", shouldBeChecked);\n }\n }\n });\n}"]}
@@ -0,0 +1,117 @@
1
+ // src/utils/handleKeyPress/handleKeyPress.ts
2
+ function isTextInput(el) {
3
+ if (el.tagName !== "INPUT") return false;
4
+ const type = el.type;
5
+ return ["text", "email", "password", "tel", "number"].includes(type);
6
+ }
7
+ function isTextArea(el) {
8
+ return el.tagName === "TEXTAREA";
9
+ }
10
+ function isNativeButton(el) {
11
+ return el.tagName === "BUTTON" || el.tagName === "INPUT" && ["button", "submit", "reset"].includes(el.type);
12
+ }
13
+ function isLink(el) {
14
+ return el.tagName === "A";
15
+ }
16
+ function moveFocus(elementItems, currentIndex, direction) {
17
+ const len = elementItems.length;
18
+ const nextIndex = (currentIndex + direction + len) % len;
19
+ elementItems.item(nextIndex).focus();
20
+ }
21
+ function isClickableButNotSemantic(el) {
22
+ return el.getAttribute("data-custom-click") !== null && el.getAttribute("data-custom-click") !== void 0;
23
+ }
24
+ function handleMenuEscapeKeyPress(menuElement, menuTriggerButton) {
25
+ menuElement.style.display = "none";
26
+ const menuTriggerButtonId = menuTriggerButton.getAttribute("id");
27
+ if (!menuTriggerButtonId) {
28
+ console.error("[aria-ease] Menu trigger button must have an id attribute to properly set aria attributes.");
29
+ return;
30
+ }
31
+ menuTriggerButton.setAttribute("aria-expanded", "false");
32
+ }
33
+ function hasSubmenu(menuItem) {
34
+ return menuItem.getAttribute("aria-haspopup") === "true" || menuItem.getAttribute("aria-haspopup") === "menu";
35
+ }
36
+ function getSubmenuId(menuItem) {
37
+ return menuItem.getAttribute("aria-controls");
38
+ }
39
+ function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, triggerButton, openSubmenu, closeSubmenu) {
40
+ const currentEl = elementItems.item(elementItemIndex);
41
+ switch (event.key) {
42
+ case "ArrowUp":
43
+ case "ArrowLeft": {
44
+ if (event.key === "ArrowLeft" && menuElementDiv && closeSubmenu) {
45
+ const labelledBy = menuElementDiv.getAttribute("aria-labelledby");
46
+ if (labelledBy) {
47
+ const parentTrigger = document.getElementById(labelledBy);
48
+ if (parentTrigger && parentTrigger.getAttribute("role") === "menuitem") {
49
+ event.preventDefault();
50
+ closeSubmenu();
51
+ parentTrigger.focus();
52
+ return;
53
+ }
54
+ }
55
+ }
56
+ if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
57
+ event.preventDefault();
58
+ moveFocus(elementItems, elementItemIndex, -1);
59
+ } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
60
+ const cursorStart = currentEl.selectionStart;
61
+ if (cursorStart === 0) {
62
+ event.preventDefault();
63
+ moveFocus(elementItems, elementItemIndex, -1);
64
+ }
65
+ }
66
+ break;
67
+ }
68
+ case "ArrowDown":
69
+ case "ArrowRight": {
70
+ if (event.key === "ArrowRight" && hasSubmenu(currentEl) && openSubmenu) {
71
+ event.preventDefault();
72
+ const submenuId = getSubmenuId(currentEl);
73
+ if (submenuId) {
74
+ openSubmenu(submenuId);
75
+ return;
76
+ }
77
+ }
78
+ if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
79
+ event.preventDefault();
80
+ moveFocus(elementItems, elementItemIndex, 1);
81
+ } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
82
+ const value = currentEl.value;
83
+ const cursorEnd = currentEl.selectionStart;
84
+ if (cursorEnd === value.length) {
85
+ event.preventDefault();
86
+ moveFocus(elementItems, elementItemIndex, 1);
87
+ }
88
+ }
89
+ break;
90
+ }
91
+ case "Escape": {
92
+ event.preventDefault();
93
+ if (menuElementDiv && triggerButton) {
94
+ if (getComputedStyle(menuElementDiv).display === "block") {
95
+ handleMenuEscapeKeyPress(menuElementDiv, triggerButton);
96
+ }
97
+ triggerButton.focus();
98
+ }
99
+ break;
100
+ }
101
+ case "Enter":
102
+ case " ": {
103
+ if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) {
104
+ event.preventDefault();
105
+ currentEl.click();
106
+ } else if (isNativeButton(currentEl)) {
107
+ event.preventDefault();
108
+ currentEl.click();
109
+ }
110
+ break;
111
+ }
112
+ }
113
+ }
114
+
115
+ export { handleKeyPress };
116
+ //# sourceMappingURL=chunk-MNMWQWXH.js.map
117
+ //# sourceMappingURL=chunk-MNMWQWXH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/handleKeyPress/handleKeyPress.ts"],"names":[],"mappings":"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","file":"chunk-MNMWQWXH.js","sourcesContent":["import { NodeListOfHTMLElement } from \"../../../Types\";\n\n\nfunction isTextInput(el: HTMLElement): boolean {\n if (el.tagName !== \"INPUT\") return false;\n const type = (el as HTMLInputElement).type;\n return [\"text\", \"email\", \"password\", \"tel\", \"number\"].includes(type);\n}\n\nfunction isTextArea(el: HTMLElement): boolean {\n return el.tagName === \"TEXTAREA\";\n}\n\nexport function isNativeButton(el: HTMLElement): boolean {\n return el.tagName === \"BUTTON\" || (el.tagName === \"INPUT\" && [\"button\", \"submit\", \"reset\"].includes((el as HTMLInputElement).type));\n}\n\nexport function isLink(el: HTMLElement): boolean {\n return el.tagName === \"A\";\n}\n\nfunction moveFocus(elementItems: NodeListOfHTMLElement, currentIndex: number, direction: -1 | 1) {\n const len = elementItems.length;\n const nextIndex = (currentIndex + direction + len) % len;\n elementItems.item(nextIndex).focus();\n}\n\nfunction isClickableButNotSemantic(el: HTMLElement): boolean {\n return el.getAttribute(\"data-custom-click\") !== null && el.getAttribute(\"data-custom-click\") !== undefined;\n}\n\nfunction handleMenuEscapeKeyPress(menuElement: HTMLElement, menuTriggerButton: HTMLElement) {\n menuElement.style.display = \"none\";\n const menuTriggerButtonId = menuTriggerButton.getAttribute(\"id\");\n if (!menuTriggerButtonId) {\n console.error(\"[aria-ease] Menu trigger button must have an id attribute to properly set aria attributes.\");\n return;\n }\n menuTriggerButton.setAttribute(\"aria-expanded\", \"false\");\n}\n\nfunction hasSubmenu(menuItem: HTMLElement): boolean {\n return menuItem.getAttribute(\"aria-haspopup\") === \"true\" || menuItem.getAttribute(\"aria-haspopup\") === \"menu\";\n}\n\nfunction getSubmenuId(menuItem: HTMLElement): string | null {\n return menuItem.getAttribute(\"aria-controls\");\n}\n\n\nexport function handleKeyPress(\n event: KeyboardEvent,\n elementItems: NodeListOfHTMLElement,\n elementItemIndex: number,\n menuElementDiv?: HTMLElement,\n triggerButton?: HTMLElement,\n openSubmenu?: (submenuId: string) => void,\n closeSubmenu?: () => void\n): void {\n const currentEl = elementItems.item(elementItemIndex);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowLeft\": {\n if(event.key === \"ArrowLeft\" && menuElementDiv && closeSubmenu) {\n const labelledBy = menuElementDiv.getAttribute(\"aria-labelledby\");\n if (labelledBy) {\n const parentTrigger = document.getElementById(labelledBy);\n if (parentTrigger && parentTrigger.getAttribute(\"role\") === \"menuitem\") {\n event.preventDefault();\n closeSubmenu();\n parentTrigger.focus();\n return;\n }\n }\n }\n\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const cursorStart = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorStart === 0) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n }\n }\n break;\n }\n case \"ArrowDown\":\n case \"ArrowRight\": {\n if(event.key === \"ArrowRight\" && hasSubmenu(currentEl) && openSubmenu) {\n event.preventDefault();\n const submenuId = getSubmenuId(currentEl);\n if (submenuId) {\n openSubmenu(submenuId);\n return;\n }\n }\n \n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const value = (currentEl as HTMLInputElement | HTMLTextAreaElement).value;\n const cursorEnd = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorEnd === value.length) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n }\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n if (menuElementDiv && triggerButton) {\n if (getComputedStyle(menuElementDiv).display === \"block\") {\n handleMenuEscapeKeyPress(menuElementDiv, triggerButton);\n }\n triggerButton.focus();\n }\n break;\n }\n case \"Enter\":\n case \" \": {\n if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) { \n event.preventDefault();\n currentEl.click();\n } else if (isNativeButton(currentEl)) {\n event.preventDefault();\n currentEl.click();\n }\n break;\n }\n default:\n break;\n }\n}"]}
@@ -1,155 +1,233 @@
1
1
  'use strict';
2
+
2
3
  // src/utils/handleKeyPress/handleKeyPress.ts
3
4
  function isTextInput(el) {
4
- if (el.tagName !== "INPUT") return false;
5
- var type = el.type;
6
- return [
7
- "text",
8
- "email",
9
- "password",
10
- "tel",
11
- "number"
12
- ].includes(type);
5
+ if (el.tagName !== "INPUT") return false;
6
+ const type = el.type;
7
+ return ["text", "email", "password", "tel", "number"].includes(type);
13
8
  }
14
9
  function isTextArea(el) {
15
- return el.tagName === "TEXTAREA";
10
+ return el.tagName === "TEXTAREA";
16
11
  }
17
12
  function isNativeButton(el) {
18
- return el.tagName === "BUTTON" || el.tagName === "INPUT" && [
19
- "button",
20
- "submit",
21
- "reset"
22
- ].includes(el.type);
13
+ return el.tagName === "BUTTON" || el.tagName === "INPUT" && ["button", "submit", "reset"].includes(el.type);
23
14
  }
24
15
  function isLink(el) {
25
- return el.tagName === "A";
16
+ return el.tagName === "A";
26
17
  }
27
18
  function moveFocus(elementItems, currentIndex, direction) {
28
- var len = elementItems.length;
29
- var nextIndex = (currentIndex + direction + len) % len;
30
- elementItems.item(nextIndex).focus();
19
+ const len = elementItems.length;
20
+ const nextIndex = (currentIndex + direction + len) % len;
21
+ elementItems.item(nextIndex).focus();
31
22
  }
32
23
  function isClickableButNotSemantic(el) {
33
- return el.getAttribute("data-custom-click") !== null || el.getAttribute("data-custom-click") !== void 0;
24
+ return el.getAttribute("data-custom-click") !== null && el.getAttribute("data-custom-click") !== void 0;
34
25
  }
35
26
  function handleMenuEscapeKeyPress(menuElement, menuTriggerButton) {
36
- menuElement.style.display = "none";
37
- var menuTriggerButtonId = menuTriggerButton.getAttribute("id");
38
- if (!menuTriggerButtonId) {
39
- throw new Error("Menu trigger button does not have id attribute");
40
- }
41
- menuTriggerButton.setAttribute("aria-expanded", "false");
27
+ menuElement.style.display = "none";
28
+ const menuTriggerButtonId = menuTriggerButton.getAttribute("id");
29
+ if (!menuTriggerButtonId) {
30
+ console.error("[aria-ease] Menu trigger button must have an id attribute to properly set aria attributes.");
31
+ return;
32
+ }
33
+ menuTriggerButton.setAttribute("aria-expanded", "false");
42
34
  }
43
- function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, triggerButton) {
44
- var currentEl = elementItems.item(elementItemIndex);
45
- switch(event.key){
46
- case "ArrowUp":
47
- case "ArrowLeft":
48
- {
49
- if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
50
- event.preventDefault();
51
- moveFocus(elementItems, elementItemIndex, -1);
52
- } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
53
- var cursorStart = currentEl.selectionStart;
54
- if (cursorStart === 0) {
55
- event.preventDefault();
56
- moveFocus(elementItems, elementItemIndex, -1);
57
- }
58
- }
59
- break;
60
- }
61
- case "ArrowDown":
62
- case "ArrowRight":
63
- {
64
- if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
65
- event.preventDefault();
66
- moveFocus(elementItems, elementItemIndex, 1);
67
- } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
68
- var value = currentEl.value;
69
- var cursorEnd = currentEl.selectionStart;
70
- if (cursorEnd === value.length) {
71
- event.preventDefault();
72
- moveFocus(elementItems, elementItemIndex, 1);
73
- }
74
- }
75
- break;
76
- }
77
- case "Escape":
78
- {
79
- event.preventDefault();
80
- if (menuElementDiv && triggerButton) {
81
- if (getComputedStyle(menuElementDiv).display === "block") {
82
- handleMenuEscapeKeyPress(menuElementDiv, triggerButton);
83
- }
84
- triggerButton.focus();
85
- }
86
- break;
87
- }
88
- case "Enter":
89
- case " ":
90
- {
91
- if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) {
92
- event.preventDefault();
93
- currentEl.click();
94
- }
95
- break;
96
- }
97
- }
35
+ function hasSubmenu(menuItem) {
36
+ return menuItem.getAttribute("aria-haspopup") === "true" || menuItem.getAttribute("aria-haspopup") === "menu";
98
37
  }
99
- // src/menu/src/makeMenuAccessible/makeMenuAccessible.ts
100
- function makeMenuAccessible(param) {
101
- var menuId = param.menuId, menuElementsClass = param.menuElementsClass, triggerId = param.triggerId;
102
- var menuDiv = document.querySelector("#".concat(menuId));
103
- if (!menuDiv) throw new Error("Invalid menu div id provided");
104
- var triggerButton = document.querySelector("#".concat(triggerId));
105
- if (!triggerButton) throw new Error("Invalid trigger button id provided");
106
- var handlerMap = /* @__PURE__ */ new Map();
107
- function setAria(isOpen) {
108
- triggerButton.setAttribute("aria-expanded", isOpen ? "true" : "false");
38
+ function getSubmenuId(menuItem) {
39
+ return menuItem.getAttribute("aria-controls");
40
+ }
41
+ function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, triggerButton, openSubmenu, closeSubmenu) {
42
+ const currentEl = elementItems.item(elementItemIndex);
43
+ switch (event.key) {
44
+ case "ArrowUp":
45
+ case "ArrowLeft": {
46
+ if (event.key === "ArrowLeft" && menuElementDiv && closeSubmenu) {
47
+ const labelledBy = menuElementDiv.getAttribute("aria-labelledby");
48
+ if (labelledBy) {
49
+ const parentTrigger = document.getElementById(labelledBy);
50
+ if (parentTrigger && parentTrigger.getAttribute("role") === "menuitem") {
51
+ event.preventDefault();
52
+ closeSubmenu();
53
+ parentTrigger.focus();
54
+ return;
55
+ }
56
+ }
57
+ }
58
+ if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
59
+ event.preventDefault();
60
+ moveFocus(elementItems, elementItemIndex, -1);
61
+ } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
62
+ const cursorStart = currentEl.selectionStart;
63
+ if (cursorStart === 0) {
64
+ event.preventDefault();
65
+ moveFocus(elementItems, elementItemIndex, -1);
66
+ }
67
+ }
68
+ break;
109
69
  }
110
- function addListeners() {
111
- var menuItems = menuDiv.querySelectorAll(".".concat(menuElementsClass));
112
- menuItems.forEach(function(menuItem, index) {
113
- if (!handlerMap.has(menuItem)) {
114
- var handler = function(event) {
115
- return handleKeyPress(event, menuItems, index, menuDiv, triggerButton);
116
- };
117
- menuItem.addEventListener("keydown", handler);
118
- handlerMap.set(menuItem, handler);
119
- }
120
- });
70
+ case "ArrowDown":
71
+ case "ArrowRight": {
72
+ if (event.key === "ArrowRight" && hasSubmenu(currentEl) && openSubmenu) {
73
+ event.preventDefault();
74
+ const submenuId = getSubmenuId(currentEl);
75
+ if (submenuId) {
76
+ openSubmenu(submenuId);
77
+ return;
78
+ }
79
+ }
80
+ if (!isTextInput(currentEl) && !isTextArea(currentEl)) {
81
+ event.preventDefault();
82
+ moveFocus(elementItems, elementItemIndex, 1);
83
+ } else if (isTextInput(currentEl) || isTextArea(currentEl)) {
84
+ const value = currentEl.value;
85
+ const cursorEnd = currentEl.selectionStart;
86
+ if (cursorEnd === value.length) {
87
+ event.preventDefault();
88
+ moveFocus(elementItems, elementItemIndex, 1);
89
+ }
90
+ }
91
+ break;
121
92
  }
122
- function removeListeners() {
123
- var menuItems = menuDiv.querySelectorAll(".".concat(menuElementsClass));
124
- menuItems.forEach(function(menuItem) {
125
- var handler = handlerMap.get(menuItem);
126
- if (handler) {
127
- menuItem.removeEventListener("keydown", handler);
128
- handlerMap.delete(menuItem);
129
- }
130
- });
93
+ case "Escape": {
94
+ event.preventDefault();
95
+ if (menuElementDiv && triggerButton) {
96
+ if (getComputedStyle(menuElementDiv).display === "block") {
97
+ handleMenuEscapeKeyPress(menuElementDiv, triggerButton);
98
+ }
99
+ triggerButton.focus();
100
+ }
101
+ break;
131
102
  }
132
- function openMenu() {
133
- menuDiv.style.display = "block";
134
- setAria(true);
135
- addListeners();
136
- var menuItems = menuDiv.querySelectorAll(".".concat(menuElementsClass));
137
- if (menuItems.length > 0) menuItems[0].focus();
103
+ case "Enter":
104
+ case " ": {
105
+ if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) {
106
+ event.preventDefault();
107
+ currentEl.click();
108
+ } else if (isNativeButton(currentEl)) {
109
+ event.preventDefault();
110
+ currentEl.click();
111
+ }
112
+ break;
138
113
  }
139
- function closeMenu() {
140
- removeListeners();
141
- menuDiv.style.display = "none";
142
- setAria(false);
143
- triggerButton.focus();
114
+ }
115
+ }
116
+
117
+ // src/menu/src/makeMenuAccessible/makeMenuAccessible.ts
118
+ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
119
+ const menuDiv = document.querySelector(`#${menuId}`);
120
+ if (!menuDiv) {
121
+ console.error(`[aria-ease] Element with id="${menuId}" not found. Make sure the menu element exists before calling makeMenuAccessible.`);
122
+ return { openMenu: () => {
123
+ }, closeMenu: () => {
124
+ }, cleanup: () => {
125
+ } };
126
+ }
127
+ const triggerButton = document.querySelector(`#${triggerId}`);
128
+ if (!triggerButton) {
129
+ console.error(`[aria-ease] Element with id="${triggerId}" not found. Make sure the trigger button element exists before calling makeMenuAccessible.`);
130
+ return { openMenu: () => {
131
+ }, closeMenu: () => {
132
+ }, cleanup: () => {
133
+ } };
134
+ }
135
+ const handlerMap = /* @__PURE__ */ new Map();
136
+ const submenuInstances = /* @__PURE__ */ new Map();
137
+ let cachedItems = null;
138
+ function getItems() {
139
+ if (!cachedItems) {
140
+ cachedItems = menuDiv.querySelectorAll(`:scope > .${menuItemsClass}`);
144
141
  }
145
- function cleanup() {
146
- removeListeners();
142
+ return cachedItems;
143
+ }
144
+ function setAria(isOpen) {
145
+ triggerButton.setAttribute("aria-expanded", isOpen ? "true" : "false");
146
+ }
147
+ function openSubmenu(submenuId) {
148
+ let submenuInstance = submenuInstances.get(submenuId);
149
+ if (!submenuInstance) {
150
+ const submenuTrigger = menuDiv.querySelector(`[aria-controls="${submenuId}"]`);
151
+ if (!submenuTrigger) {
152
+ console.error(`[aria-ease] Submenu trigger with aria-controls="${submenuId}" not found in menu "${menuId}".`);
153
+ return;
154
+ }
155
+ if (!submenuTrigger.id) {
156
+ const generatedId = `trigger-${submenuId}`;
157
+ submenuTrigger.id = generatedId;
158
+ console.warn(`[aria-ease] Submenu trigger for "${submenuId}" had no ID. Auto-generated ID: "${generatedId}".`);
159
+ }
160
+ const submenuElement = document.querySelector(`#${submenuId}`);
161
+ if (!submenuElement) {
162
+ console.error(`[aria-ease] Submenu element with id="${submenuId}" not found. Cannot create submenu instance.`);
163
+ return;
164
+ }
165
+ submenuInstance = makeMenuAccessible({
166
+ menuId: submenuId,
167
+ menuItemsClass,
168
+ triggerId: submenuTrigger.id
169
+ });
170
+ submenuInstances.set(submenuId, submenuInstance);
147
171
  }
148
- return {
149
- openMenu: openMenu,
150
- closeMenu: closeMenu,
151
- cleanup: cleanup
152
- };
172
+ submenuInstance.openMenu();
173
+ }
174
+ function closeSubmenu() {
175
+ closeMenu();
176
+ }
177
+ function addListeners() {
178
+ const menuItems = getItems();
179
+ menuItems.forEach((menuItem, index) => {
180
+ if (!handlerMap.has(menuItem)) {
181
+ const handler = (event) => handleKeyPress(
182
+ event,
183
+ menuItems,
184
+ index,
185
+ menuDiv,
186
+ triggerButton,
187
+ openSubmenu,
188
+ closeSubmenu
189
+ );
190
+ menuItem.addEventListener("keydown", handler);
191
+ handlerMap.set(menuItem, handler);
192
+ }
193
+ });
194
+ }
195
+ function removeListeners() {
196
+ const menuItems = getItems();
197
+ menuItems.forEach((menuItem) => {
198
+ const handler = handlerMap.get(menuItem);
199
+ if (handler) {
200
+ menuItem.removeEventListener("keydown", handler);
201
+ handlerMap.delete(menuItem);
202
+ }
203
+ });
204
+ }
205
+ function openMenu() {
206
+ menuDiv.style.display = "block";
207
+ setAria(true);
208
+ addListeners();
209
+ const menuItems = getItems();
210
+ if (menuItems.length > 0) menuItems[0].focus();
211
+ }
212
+ function closeMenu() {
213
+ removeListeners();
214
+ menuDiv.style.display = "none";
215
+ setAria(false);
216
+ triggerButton.focus();
217
+ }
218
+ function cleanup() {
219
+ removeListeners();
220
+ menuDiv.style.display = "none";
221
+ setAria(false);
222
+ submenuInstances.forEach((instance) => instance.cleanup());
223
+ submenuInstances.clear();
224
+ }
225
+ function refresh() {
226
+ cachedItems = null;
227
+ }
228
+ return { openMenu, closeMenu, cleanup, refresh };
153
229
  }
154
- exports.makeMenuAccessible = makeMenuAccessible; //# sourceMappingURL=index.cjs.map
230
+
231
+ exports.makeMenuAccessible = makeMenuAccessible;
232
+ //# sourceMappingURL=index.cjs.map
155
233
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/macx/aria-ease/package/dist/src/menu/index.cjs","../../../src/utils/handleKeyPress/handleKeyPress.ts"],"names":[],"mappings":"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","sourcesContent":["'use strict';\n\n// src/utils/handleKeyPress/handleKeyPress.ts\nfunction isTextInput(el) {\n if (el.tagName !== \"INPUT\") return false;\n const type = el.type;\n return [\"text\", \"email\", \"password\", \"tel\", \"number\"].includes(type);\n}\nfunction isTextArea(el) {\n return el.tagName === \"TEXTAREA\";\n}\nfunction isNativeButton(el) {\n return el.tagName === \"BUTTON\" || el.tagName === \"INPUT\" && [\"button\", \"submit\", \"reset\"].includes(el.type);\n}\nfunction isLink(el) {\n return el.tagName === \"A\";\n}\nfunction moveFocus(elementItems, currentIndex, direction) {\n const len = elementItems.length;\n const nextIndex = (currentIndex + direction + len) % len;\n elementItems.item(nextIndex).focus();\n}\nfunction isClickableButNotSemantic(el) {\n return el.getAttribute(\"data-custom-click\") !== null || el.getAttribute(\"data-custom-click\") !== void 0;\n}\nfunction handleMenuEscapeKeyPress(menuElement, menuTriggerButton) {\n menuElement.style.display = \"none\";\n const menuTriggerButtonId = menuTriggerButton.getAttribute(\"id\");\n if (!menuTriggerButtonId) {\n throw new Error(\"Menu trigger button does not have id attribute\");\n }\n menuTriggerButton.setAttribute(\"aria-expanded\", \"false\");\n}\nfunction handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, triggerButton) {\n const currentEl = elementItems.item(elementItemIndex);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowLeft\": {\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const cursorStart = currentEl.selectionStart;\n if (cursorStart === 0) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n }\n }\n break;\n }\n case \"ArrowDown\":\n case \"ArrowRight\": {\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const value = currentEl.value;\n const cursorEnd = currentEl.selectionStart;\n if (cursorEnd === value.length) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n }\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n if (menuElementDiv && triggerButton) {\n if (getComputedStyle(menuElementDiv).display === \"block\") {\n handleMenuEscapeKeyPress(menuElementDiv, triggerButton);\n }\n triggerButton.focus();\n }\n break;\n }\n case \"Enter\":\n case \" \": {\n if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) {\n event.preventDefault();\n currentEl.click();\n }\n break;\n }\n }\n}\n\n// src/menu/src/makeMenuAccessible/makeMenuAccessible.ts\nfunction makeMenuAccessible({ menuId, menuElementsClass, triggerId }) {\n const menuDiv = document.querySelector(`#${menuId}`);\n if (!menuDiv) throw new Error(\"Invalid menu div id provided\");\n const triggerButton = document.querySelector(`#${triggerId}`);\n if (!triggerButton) throw new Error(\"Invalid trigger button id provided\");\n const handlerMap = /* @__PURE__ */ new Map();\n function setAria(isOpen) {\n triggerButton.setAttribute(\"aria-expanded\", isOpen ? \"true\" : \"false\");\n }\n function addListeners() {\n const menuItems = menuDiv.querySelectorAll(`.${menuElementsClass}`);\n menuItems.forEach((menuItem, index) => {\n if (!handlerMap.has(menuItem)) {\n const handler = (event) => handleKeyPress(event, menuItems, index, menuDiv, triggerButton);\n menuItem.addEventListener(\"keydown\", handler);\n handlerMap.set(menuItem, handler);\n }\n });\n }\n function removeListeners() {\n const menuItems = menuDiv.querySelectorAll(`.${menuElementsClass}`);\n menuItems.forEach((menuItem) => {\n const handler = handlerMap.get(menuItem);\n if (handler) {\n menuItem.removeEventListener(\"keydown\", handler);\n handlerMap.delete(menuItem);\n }\n });\n }\n function openMenu() {\n menuDiv.style.display = \"block\";\n setAria(true);\n addListeners();\n const menuItems = menuDiv.querySelectorAll(`.${menuElementsClass}`);\n if (menuItems.length > 0) menuItems[0].focus();\n }\n function closeMenu() {\n removeListeners();\n menuDiv.style.display = \"none\";\n setAria(false);\n triggerButton.focus();\n }\n function cleanup() {\n removeListeners();\n }\n return { openMenu, closeMenu, cleanup };\n}\n\nexports.makeMenuAccessible = makeMenuAccessible;\n//# sourceMappingURL=index.cjs.map\n","import { NodeListOfHTMLElement, HTMLElement } from \"../../../Types\";\n\n\nfunction isTextInput(el: HTMLElement): boolean {\n if (el.tagName !== 'INPUT') return false;\n const type = (el as HTMLInputElement).type;\n return ['text', 'email', 'password', 'tel', 'number'].includes(type);\n}\n\nfunction isTextArea(el: HTMLElement): boolean {\n return el.tagName === 'TEXTAREA';\n}\n\nexport function isNativeButton(el: HTMLElement): boolean {\n return el.tagName === 'BUTTON' || (el.tagName === 'INPUT' && ['button', 'submit', 'reset'].includes((el as HTMLInputElement).type));\n}\n\nexport function isLink(el: HTMLElement): boolean {\n return el.tagName === 'A';\n}\n\nfunction moveFocus(elementItems: NodeListOfHTMLElement, currentIndex: number, direction: -1 | 1) {\n const len = elementItems.length;\n const nextIndex = (currentIndex + direction + len) % len;\n elementItems.item(nextIndex).focus();\n}\n\nfunction isClickableButNotSemantic(el: HTMLElement): boolean {\n return el.getAttribute(\"data-custom-click\") !== null || el.getAttribute(\"data-custom-click\") !== undefined;\n}\n\nfunction handleMenuEscapeKeyPress(menuElement: HTMLElement, menuTriggerButton: HTMLElement) {\n menuElement.style.display = 'none';\n const menuTriggerButtonId = menuTriggerButton.getAttribute('id');\n if (!menuTriggerButtonId) {\n throw new Error(\"Menu trigger button does not have id attribute\");\n }\n menuTriggerButton.setAttribute(\"aria-expanded\", \"false\");\n}\n\nexport function handleKeyPress(\n event: KeyboardEvent,\n elementItems: NodeListOfHTMLElement,\n elementItemIndex: number,\n menuElementDiv?: HTMLElement,\n triggerButton?: HTMLElement\n): void {\n const currentEl = elementItems.item(elementItemIndex);\n switch (event.key) {\n case 'ArrowUp':\n case 'ArrowLeft': {\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const cursorStart = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorStart === 0) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n }\n }\n break;\n }\n case 'ArrowDown':\n case 'ArrowRight': {\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const value = (currentEl as HTMLInputElement | HTMLTextAreaElement).value;\n const cursorEnd = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorEnd === value.length) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n }\n }\n break;\n }\n case 'Escape': {\n event.preventDefault();\n if (menuElementDiv && triggerButton) {\n if (getComputedStyle(menuElementDiv).display === 'block') {\n handleMenuEscapeKeyPress(menuElementDiv, triggerButton);\n }\n triggerButton.focus();\n }\n break;\n }\n case 'Enter':\n case ' ': {\n if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) {\n event.preventDefault();\n currentEl.click();\n }\n break;\n }\n default:\n break;\n }\n}"]}
1
+ {"version":3,"sources":["../../../src/utils/handleKeyPress/handleKeyPress.ts","../../../src/menu/src/makeMenuAccessible/makeMenuAccessible.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import { NodeListOfHTMLElement } from \"../../../Types\";\n\n\nfunction isTextInput(el: HTMLElement): boolean {\n if (el.tagName !== \"INPUT\") return false;\n const type = (el as HTMLInputElement).type;\n return [\"text\", \"email\", \"password\", \"tel\", \"number\"].includes(type);\n}\n\nfunction isTextArea(el: HTMLElement): boolean {\n return el.tagName === \"TEXTAREA\";\n}\n\nexport function isNativeButton(el: HTMLElement): boolean {\n return el.tagName === \"BUTTON\" || (el.tagName === \"INPUT\" && [\"button\", \"submit\", \"reset\"].includes((el as HTMLInputElement).type));\n}\n\nexport function isLink(el: HTMLElement): boolean {\n return el.tagName === \"A\";\n}\n\nfunction moveFocus(elementItems: NodeListOfHTMLElement, currentIndex: number, direction: -1 | 1) {\n const len = elementItems.length;\n const nextIndex = (currentIndex + direction + len) % len;\n elementItems.item(nextIndex).focus();\n}\n\nfunction isClickableButNotSemantic(el: HTMLElement): boolean {\n return el.getAttribute(\"data-custom-click\") !== null && el.getAttribute(\"data-custom-click\") !== undefined;\n}\n\nfunction handleMenuEscapeKeyPress(menuElement: HTMLElement, menuTriggerButton: HTMLElement) {\n menuElement.style.display = \"none\";\n const menuTriggerButtonId = menuTriggerButton.getAttribute(\"id\");\n if (!menuTriggerButtonId) {\n console.error(\"[aria-ease] Menu trigger button must have an id attribute to properly set aria attributes.\");\n return;\n }\n menuTriggerButton.setAttribute(\"aria-expanded\", \"false\");\n}\n\nfunction hasSubmenu(menuItem: HTMLElement): boolean {\n return menuItem.getAttribute(\"aria-haspopup\") === \"true\" || menuItem.getAttribute(\"aria-haspopup\") === \"menu\";\n}\n\nfunction getSubmenuId(menuItem: HTMLElement): string | null {\n return menuItem.getAttribute(\"aria-controls\");\n}\n\n\nexport function handleKeyPress(\n event: KeyboardEvent,\n elementItems: NodeListOfHTMLElement,\n elementItemIndex: number,\n menuElementDiv?: HTMLElement,\n triggerButton?: HTMLElement,\n openSubmenu?: (submenuId: string) => void,\n closeSubmenu?: () => void\n): void {\n const currentEl = elementItems.item(elementItemIndex);\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowLeft\": {\n if(event.key === \"ArrowLeft\" && menuElementDiv && closeSubmenu) {\n const labelledBy = menuElementDiv.getAttribute(\"aria-labelledby\");\n if (labelledBy) {\n const parentTrigger = document.getElementById(labelledBy);\n if (parentTrigger && parentTrigger.getAttribute(\"role\") === \"menuitem\") {\n event.preventDefault();\n closeSubmenu();\n parentTrigger.focus();\n return;\n }\n }\n }\n\n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const cursorStart = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorStart === 0) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, -1);\n }\n }\n break;\n }\n case \"ArrowDown\":\n case \"ArrowRight\": {\n if(event.key === \"ArrowRight\" && hasSubmenu(currentEl) && openSubmenu) {\n event.preventDefault();\n const submenuId = getSubmenuId(currentEl);\n if (submenuId) {\n openSubmenu(submenuId);\n return;\n }\n }\n \n if (!isTextInput(currentEl) && !isTextArea(currentEl)) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n } else if (isTextInput(currentEl) || isTextArea(currentEl)) {\n const value = (currentEl as HTMLInputElement | HTMLTextAreaElement).value;\n const cursorEnd = (currentEl as HTMLInputElement | HTMLTextAreaElement).selectionStart;\n if (cursorEnd === value.length) {\n event.preventDefault();\n moveFocus(elementItems, elementItemIndex, 1);\n }\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n if (menuElementDiv && triggerButton) {\n if (getComputedStyle(menuElementDiv).display === \"block\") {\n handleMenuEscapeKeyPress(menuElementDiv, triggerButton);\n }\n triggerButton.focus();\n }\n break;\n }\n case \"Enter\":\n case \" \": {\n if (!isNativeButton(currentEl) && !isLink(currentEl) && isClickableButNotSemantic(currentEl)) { \n event.preventDefault();\n currentEl.click();\n } else if (isNativeButton(currentEl)) {\n event.preventDefault();\n currentEl.click();\n }\n break;\n }\n default:\n break;\n }\n}","/**\n * 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.\n * @param {string} menuId - The id of the menu.\n * @param {string} menuItemsClass - The class of the items that are children of the menu.\n * @param {string} triggerId - The id of the button that triggers the menu.\n*/\n\nimport { handleKeyPress } from \"../../../utils/handleKeyPress/handleKeyPress\";\nimport { NodeListOfHTMLElement } from \"Types\";\n\n\nexport function makeMenuAccessible({ menuId, menuItemsClass, triggerId }: {menuId: string; menuItemsClass: string; triggerId: string;}) {\n const menuDiv = document.querySelector(`#${menuId}`) as HTMLElement;\n if (!menuDiv) {\n console.error(`[aria-ease] Element with id=\"${menuId}\" not found. Make sure the menu element exists before calling makeMenuAccessible.`);\n return { openMenu: () => {}, closeMenu: () => {}, cleanup: () => {} };\n }\n\n const triggerButton = document.querySelector(`#${triggerId}`) as HTMLElement;\n if (!triggerButton) {\n console.error(`[aria-ease] Element with id=\"${triggerId}\" not found. Make sure the trigger button element exists before calling makeMenuAccessible.`);\n return { openMenu: () => {}, closeMenu: () => {}, cleanup: () => {} };\n }\n\n\n const handlerMap = new Map<HTMLElement, (event: KeyboardEvent) => void>();\n const submenuInstances = new Map<string, ReturnType<typeof makeMenuAccessible>>();\n\n let cachedItems: NodeListOfHTMLElement | null = null;\n function getItems() {\n if (!cachedItems) {\n cachedItems = menuDiv.querySelectorAll(`:scope > .${menuItemsClass}`) as NodeListOfHTMLElement;\n }\n return cachedItems;\n }\n\n function setAria(isOpen: boolean) {\n triggerButton.setAttribute(\"aria-expanded\", isOpen ? \"true\" : \"false\");\n }\n\n function openSubmenu(submenuId: string) {\n let submenuInstance = submenuInstances.get(submenuId);\n if (!submenuInstance) {\n const submenuTrigger = menuDiv.querySelector(`[aria-controls=\"${submenuId}\"]`) as HTMLElement;\n if (!submenuTrigger) {\n console.error(`[aria-ease] Submenu trigger with aria-controls=\"${submenuId}\" not found in menu \"${menuId}\".`);\n return;\n }\n\n // Ensure the trigger has an ID for proper ARIA references\n if (!submenuTrigger.id) {\n const generatedId = `trigger-${submenuId}`;\n submenuTrigger.id = generatedId;\n console.warn(`[aria-ease] Submenu trigger for \"${submenuId}\" had no ID. Auto-generated ID: \"${generatedId}\".`);\n }\n\n // Verify the submenu element exists before creating instance\n const submenuElement = document.querySelector(`#${submenuId}`);\n if (!submenuElement) {\n console.error(`[aria-ease] Submenu element with id=\"${submenuId}\" not found. Cannot create submenu instance.`);\n return;\n }\n\n submenuInstance = makeMenuAccessible({\n menuId: submenuId,\n menuItemsClass: menuItemsClass,\n triggerId: submenuTrigger.id\n });\n submenuInstances.set(submenuId, submenuInstance);\n }\n \n submenuInstance.openMenu();\n }\n\n function closeSubmenu() {\n closeMenu();\n }\n\n function addListeners() {\n const menuItems = getItems();\n menuItems.forEach((menuItem: HTMLElement, index: number) => {\n if (!handlerMap.has(menuItem)) {\n const handler = (event: KeyboardEvent) => handleKeyPress(\n event, \n menuItems, \n index, \n menuDiv, \n triggerButton,\n openSubmenu,\n closeSubmenu\n );\n menuItem.addEventListener(\"keydown\", handler);\n handlerMap.set(menuItem, handler);\n } \n });\n }\n\n function removeListeners() {\n const menuItems = getItems();\n menuItems.forEach((menuItem: HTMLElement) => {\n const handler = handlerMap.get(menuItem);\n if (handler) {\n menuItem.removeEventListener(\"keydown\", handler);\n handlerMap.delete(menuItem);\n }\n });\n }\n\n function openMenu() {\n menuDiv.style.display = \"block\";\n setAria(true);\n addListeners();\n \n const menuItems = getItems();\n if (menuItems.length > 0) menuItems[0].focus();\n }\n\n function closeMenu() {\n removeListeners();\n menuDiv.style.display = \"none\";\n setAria(false);\n triggerButton.focus();\n }\n\n function cleanup() {\n removeListeners();\n \n // Close menu and reset ARIA attributes\n menuDiv.style.display = \"none\";\n setAria(false);\n \n submenuInstances.forEach(instance => instance.cleanup());\n submenuInstances.clear();\n }\n\n function refresh() {\n cachedItems = null;\n }\n\n return { openMenu, closeMenu, cleanup, refresh };\n}"]}