aria-ease 6.14.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +1 -1
  2. package/dist/AccordionComponentStrategy-2SWMNUR6.js +1 -0
  3. package/dist/ComboboxComponentStrategy-YSYLR2U5.js +5 -0
  4. package/dist/MenuComponentStrategy-C22BZEBH.js +5 -0
  5. package/dist/RelativeTargetResolver-T4P25J2M.js +1 -0
  6. package/dist/TabsComponentStrategy-ADEEFJXM.js +1 -0
  7. package/dist/audit-WBKVW7H6.js +9 -0
  8. package/dist/badgeHelper-IB5RTMAG.js +11 -0
  9. package/dist/badgeHelper-JSROP5ML.js +1 -0
  10. package/dist/buildContracts-T4XQZBDU.js +13 -0
  11. package/dist/chunk-52I3INNG.js +11 -0
  12. package/dist/chunk-APUMBDOT.js +1 -0
  13. package/dist/chunk-BHNO4ZI3.js +1 -0
  14. package/dist/chunk-CNU4N4AY.js +1 -0
  15. package/dist/chunk-SM6ZKEDR.js +1 -0
  16. package/dist/chunk-ZNQ5BXVJ.js +1 -0
  17. package/dist/cli.cjs +132 -3560
  18. package/dist/cli.js +19 -161
  19. package/dist/configLoader-ZEJVXLX7.js +1 -0
  20. package/dist/configLoader-ZXTSCIP6.js +1 -0
  21. package/dist/contractTestRunnerPlaywright-FOCQTM4L.js +46 -0
  22. package/dist/contractTestRunnerPlaywright-QPU6HZXG.js +46 -0
  23. package/dist/formatters-H3CPDLG5.js +87 -0
  24. package/dist/index.cjs +64 -5103
  25. package/dist/index.d.cts +4 -6
  26. package/dist/index.d.ts +4 -6
  27. package/dist/index.js +17 -2703
  28. package/dist/src/accordion/index.cjs +1 -183
  29. package/dist/src/accordion/index.js +1 -181
  30. package/dist/src/block/index.cjs +1 -124
  31. package/dist/src/block/index.js +1 -122
  32. package/dist/src/checkbox/index.cjs +1 -109
  33. package/dist/src/checkbox/index.js +1 -107
  34. package/dist/src/combobox/index.cjs +1 -265
  35. package/dist/src/combobox/index.js +1 -263
  36. package/dist/src/menu/index.cjs +1 -339
  37. package/dist/src/menu/index.js +1 -337
  38. package/dist/src/radio/index.cjs +1 -117
  39. package/dist/src/radio/index.js +1 -115
  40. package/dist/src/tabs/index.cjs +1 -265
  41. package/dist/src/tabs/index.js +1 -263
  42. package/dist/src/toggle/index.cjs +1 -119
  43. package/dist/src/toggle/index.js +1 -117
  44. package/dist/src/utils/test/AccordionComponentStrategy-X2GSQ5KT.js +1 -0
  45. package/dist/src/utils/test/ComboboxComponentStrategy-SICWLI27.js +5 -0
  46. package/dist/src/utils/test/MenuComponentStrategy-R4VPAHDE.js +5 -0
  47. package/dist/src/utils/test/RelativeTargetResolver-UQQMZHI6.js +1 -0
  48. package/dist/src/utils/test/TabsComponentStrategy-L2PYNEW6.js +1 -0
  49. package/dist/src/utils/test/badgeHelper-ER5ZOHWF.js +11 -0
  50. package/dist/src/utils/test/chunk-APUMBDOT.js +1 -0
  51. package/dist/src/utils/test/chunk-BHNO4ZI3.js +1 -0
  52. package/dist/src/utils/test/configLoader-NCYRL2O6.js +1 -0
  53. package/dist/src/utils/test/contractTestRunnerPlaywright-YZCMF64Q.js +46 -0
  54. package/dist/src/utils/test/dsl/index.cjs +1 -838
  55. package/dist/src/utils/test/dsl/index.d.cts +2 -4
  56. package/dist/src/utils/test/dsl/index.d.ts +2 -4
  57. package/dist/src/utils/test/dsl/index.js +1 -836
  58. package/dist/src/utils/test/index.cjs +64 -2672
  59. package/dist/src/utils/test/index.d.cts +2 -2
  60. package/dist/src/utils/test/index.d.ts +2 -2
  61. package/dist/src/utils/test/index.js +16 -340
  62. package/dist/test-VXSCSKV5.js +19 -0
  63. package/package.json +8 -10
  64. package/dist/AccordionComponentStrategy-4ZEIQ2V6.js +0 -42
  65. package/dist/ComboboxComponentStrategy-DU342VMB.js +0 -64
  66. package/dist/MenuComponentStrategy-VYCC2XOM.js +0 -81
  67. package/dist/RelativeTargetResolver-DJAITO6D.js +0 -7
  68. package/dist/TabsComponentStrategy-3SQURPMX.js +0 -29
  69. package/dist/audit-JYEPKLHR.js +0 -63
  70. package/dist/badgeHelper-JOWO6RQG.js +0 -15
  71. package/dist/badgeHelper-RDOMCC6E.js +0 -108
  72. package/dist/buildContracts-VIV6GM56.js +0 -437
  73. package/dist/chunk-4DU5Z5BR.js +0 -340
  74. package/dist/chunk-GJGUY643.js +0 -182
  75. package/dist/chunk-GLT43UVH.js +0 -43
  76. package/dist/chunk-I2KLQ2HA.js +0 -22
  77. package/dist/chunk-JJEPLK7L.js +0 -107
  78. package/dist/chunk-PK5L2SAF.js +0 -17
  79. package/dist/configLoader-Q7N5XV4P.js +0 -183
  80. package/dist/configLoader-REHK3S3Q.js +0 -7
  81. package/dist/contractTestRunnerPlaywright-B2HLZKKK.js +0 -1394
  82. package/dist/contractTestRunnerPlaywright-RWK52C7S.js +0 -1394
  83. package/dist/formatters-32KQIIYS.js +0 -183
  84. package/dist/src/utils/test/AccordionComponentStrategy-WRHZOEN6.js +0 -38
  85. package/dist/src/utils/test/ComboboxComponentStrategy-XKQ72RFD.js +0 -60
  86. package/dist/src/utils/test/MenuComponentStrategy-6XWU5KLW.js +0 -77
  87. package/dist/src/utils/test/RelativeTargetResolver-G2XDN2VV.js +0 -1
  88. package/dist/src/utils/test/TabsComponentStrategy-BKG53SEV.js +0 -26
  89. package/dist/src/utils/test/badgeHelper-HZKGOPB4.js +0 -102
  90. package/dist/src/utils/test/chunk-4DU5Z5BR.js +0 -332
  91. package/dist/src/utils/test/chunk-GLT43UVH.js +0 -41
  92. package/dist/src/utils/test/configLoader-NA7IBCS3.js +0 -181
  93. package/dist/src/utils/test/contractTestRunnerPlaywright-5FIGA5G4.js +0 -1372
  94. package/dist/test-WDBS5JWO.js +0 -358
@@ -1,265 +1 @@
1
- 'use strict';
2
-
3
- // src/tabs/src/makeTabsAccessible/makeTabsAccessible.ts
4
- function makeTabsAccessible({ tabListId, tabsClass, tabPanelsClass, orientation = "horizontal", activateOnFocus = true, callback }) {
5
- const tabList = document.querySelector(`#${tabListId}`);
6
- if (!tabList) {
7
- console.error(`[aria-ease] Element with id="${tabListId}" not found. Make sure the tab list container exists before calling makeTabsAccessible.`);
8
- return { cleanup: () => {
9
- } };
10
- }
11
- const tabs = Array.from(tabList.querySelectorAll(`.${tabsClass}`));
12
- if (tabs.length === 0) {
13
- console.error(`[aria-ease] No elements with class="${tabsClass}" found. Make sure tab buttons exist before calling makeTabsAccessible.`);
14
- return { cleanup: () => {
15
- } };
16
- }
17
- const tabPanels = Array.from(document.querySelectorAll(`.${tabPanelsClass}`));
18
- if (tabPanels.length === 0) {
19
- console.error(`[aria-ease] No elements with class="${tabPanelsClass}" found. Make sure tab panels exist before calling makeTabsAccessible.`);
20
- return { cleanup: () => {
21
- } };
22
- }
23
- if (tabs.length !== tabPanels.length) {
24
- console.error(`[aria-ease] Tab/panel mismatch: found ${tabs.length} tabs but ${tabPanels.length} panels.`);
25
- return { cleanup: () => {
26
- } };
27
- }
28
- const handlerMap = /* @__PURE__ */ new WeakMap();
29
- const clickHandlerMap = /* @__PURE__ */ new WeakMap();
30
- const contextMenuHandlerMap = /* @__PURE__ */ new WeakMap();
31
- let activeTabIndex = 0;
32
- function initialize() {
33
- tabList.setAttribute("role", "tablist");
34
- tabList.setAttribute("aria-orientation", orientation);
35
- tabs.forEach((tab, index) => {
36
- const panel = tabPanels[index];
37
- if (!tab.id) {
38
- tab.id = `${tabListId}-tab-${index}`;
39
- }
40
- if (!panel.id) {
41
- panel.id = `${tabListId}-panel-${index}`;
42
- }
43
- tab.setAttribute("role", "tab");
44
- tab.setAttribute("aria-controls", panel.id);
45
- tab.setAttribute("aria-selected", "false");
46
- tab.setAttribute("tabindex", "-1");
47
- panel.setAttribute("role", "tabpanel");
48
- panel.setAttribute("aria-labelledby", tab.id);
49
- panel.hidden = true;
50
- const hasFocusableContent = panel.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
51
- if (!hasFocusableContent) {
52
- panel.setAttribute("tabindex", "0");
53
- }
54
- });
55
- activateTab(0, false);
56
- }
57
- function activateTab(index, shouldFocus = true) {
58
- if (index < 0 || index >= tabs.length) {
59
- console.error(`[aria-ease] Invalid tab index: ${index}`);
60
- return;
61
- }
62
- const previousIndex = activeTabIndex;
63
- tabs.forEach((tab, i) => {
64
- const panel = tabPanels[i];
65
- tab.setAttribute("aria-selected", "false");
66
- tab.setAttribute("tabindex", "-1");
67
- panel.hidden = true;
68
- });
69
- const activeTab = tabs[index];
70
- const activePanel = tabPanels[index];
71
- activeTab.setAttribute("aria-selected", "true");
72
- activeTab.setAttribute("tabindex", "0");
73
- activePanel.hidden = false;
74
- if (shouldFocus) {
75
- activeTab.focus();
76
- }
77
- activeTabIndex = index;
78
- if (callback?.onTabChange && previousIndex !== index) {
79
- try {
80
- callback.onTabChange(index, previousIndex);
81
- } catch (error) {
82
- console.error("[aria-ease] Error in tabs onTabChange callback:", error);
83
- }
84
- }
85
- }
86
- function moveFocus(direction) {
87
- const currentFocusedIndex = tabs.findIndex((tab) => tab === document.activeElement);
88
- const currentIndex = currentFocusedIndex !== -1 ? currentFocusedIndex : activeTabIndex;
89
- let newIndex = currentIndex;
90
- switch (direction) {
91
- case "first":
92
- newIndex = 0;
93
- break;
94
- case "last":
95
- newIndex = tabs.length - 1;
96
- break;
97
- case "next":
98
- newIndex = (currentIndex + 1) % tabs.length;
99
- break;
100
- case "prev":
101
- newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
102
- break;
103
- }
104
- tabs[newIndex].focus();
105
- tabs[newIndex].setAttribute("tabindex", "0");
106
- tabs[activeTabIndex].setAttribute("tabindex", "-1");
107
- if (activateOnFocus) {
108
- activateTab(newIndex, false);
109
- } else {
110
- const currentActive = activeTabIndex;
111
- tabs.forEach((tab, i) => {
112
- if (i === newIndex) {
113
- tab.setAttribute("tabindex", "0");
114
- } else if (i !== currentActive) {
115
- tab.setAttribute("tabindex", "-1");
116
- }
117
- });
118
- }
119
- }
120
- function handleTabClick(index) {
121
- return () => {
122
- activateTab(index);
123
- };
124
- }
125
- function handleTabKeydown(index) {
126
- return (event) => {
127
- const { key } = event;
128
- let handled = false;
129
- if (orientation === "horizontal") {
130
- switch (key) {
131
- case "ArrowLeft":
132
- event.preventDefault();
133
- moveFocus("prev");
134
- handled = true;
135
- break;
136
- case "ArrowRight":
137
- event.preventDefault();
138
- moveFocus("next");
139
- handled = true;
140
- break;
141
- }
142
- } else {
143
- switch (key) {
144
- case "ArrowUp":
145
- event.preventDefault();
146
- moveFocus("prev");
147
- handled = true;
148
- break;
149
- case "ArrowDown":
150
- event.preventDefault();
151
- moveFocus("next");
152
- handled = true;
153
- break;
154
- }
155
- }
156
- if (!handled) {
157
- switch (key) {
158
- case "Home":
159
- event.preventDefault();
160
- moveFocus("first");
161
- break;
162
- case "End":
163
- event.preventDefault();
164
- moveFocus("last");
165
- break;
166
- case " ":
167
- case "Enter":
168
- if (!activateOnFocus) {
169
- event.preventDefault();
170
- activateTab(index);
171
- }
172
- break;
173
- case "F10":
174
- if (event.shiftKey && callback?.onContextMenu) {
175
- event.preventDefault();
176
- try {
177
- callback.onContextMenu(index, tabs[index]);
178
- } catch (error) {
179
- console.error("[aria-ease] Error in tabs onContextMenu callback:", error);
180
- }
181
- }
182
- break;
183
- }
184
- }
185
- };
186
- }
187
- function handleTabContextMenu(index) {
188
- return (event) => {
189
- if (callback?.onContextMenu) {
190
- event.preventDefault();
191
- try {
192
- callback.onContextMenu(index, tabs[index]);
193
- } catch (error) {
194
- console.error("[aria-ease] Error in tabs onContextMenu callback:", error);
195
- }
196
- }
197
- };
198
- }
199
- function addListeners() {
200
- tabs.forEach((tab, index) => {
201
- const clickHandler = handleTabClick(index);
202
- const keydownHandler = handleTabKeydown(index);
203
- const contextMenuHandler = handleTabContextMenu(index);
204
- tab.addEventListener("click", clickHandler);
205
- tab.addEventListener("keydown", keydownHandler);
206
- if (callback?.onContextMenu) {
207
- tab.addEventListener("contextmenu", contextMenuHandler);
208
- contextMenuHandlerMap.set(tab, contextMenuHandler);
209
- }
210
- handlerMap.set(tab, keydownHandler);
211
- clickHandlerMap.set(tab, clickHandler);
212
- });
213
- }
214
- function removeListeners() {
215
- tabs.forEach((tab) => {
216
- const keydownHandler = handlerMap.get(tab);
217
- const clickHandler = clickHandlerMap.get(tab);
218
- const contextMenuHandler = contextMenuHandlerMap.get(tab);
219
- if (keydownHandler) {
220
- tab.removeEventListener("keydown", keydownHandler);
221
- handlerMap.delete(tab);
222
- }
223
- if (clickHandler) {
224
- tab.removeEventListener("click", clickHandler);
225
- clickHandlerMap.delete(tab);
226
- }
227
- if (contextMenuHandler) {
228
- tab.removeEventListener("contextmenu", contextMenuHandler);
229
- contextMenuHandlerMap.delete(tab);
230
- }
231
- });
232
- }
233
- function cleanup() {
234
- removeListeners();
235
- tabs.forEach((tab, index) => {
236
- const panel = tabPanels[index];
237
- tab.removeAttribute("role");
238
- tab.removeAttribute("aria-selected");
239
- tab.removeAttribute("aria-controls");
240
- tab.removeAttribute("tabindex");
241
- panel.removeAttribute("role");
242
- panel.removeAttribute("aria-labelledby");
243
- panel.removeAttribute("tabindex");
244
- panel.hidden = false;
245
- });
246
- tabList.removeAttribute("role");
247
- tabList.removeAttribute("aria-orientation");
248
- }
249
- function refresh() {
250
- removeListeners();
251
- const newTabs = Array.from(tabList.querySelectorAll(`.${tabsClass}`));
252
- const newPanels = Array.from(document.querySelectorAll(`.${tabPanelsClass}`));
253
- tabs.length = 0;
254
- tabs.push(...newTabs);
255
- tabPanels.length = 0;
256
- tabPanels.push(...newPanels);
257
- initialize();
258
- addListeners();
259
- }
260
- initialize();
261
- addListeners();
262
- return { activateTab, cleanup, refresh };
263
- }
264
-
265
- exports.makeTabsAccessible = makeTabsAccessible;
1
+ 'use strict';function D({tabListId:b,tabsClass:m,tabPanelsClass:h,orientation:E="horizontal",activateOnFocus:M=true,callback:i}){if(b==="")return console.error("[aria-ease] 'tabListId' should not be an empty string. Provide an id to the tab list container element that exists before calling makeTabsAccessible."),{cleanup:()=>{}};let l=document.querySelector(`#${b}`);if(!l)return console.error(`[aria-ease] Element with id="${b}" not found. Make sure the tab list container exists before calling makeTabsAccessible.`),{cleanup:()=>{}};if(m==="")return console.error("[aria-ease] 'tabsClass' should not be an empty string. Provide a class name that exists on the tab button elements before calling makeTabsAccessible."),{cleanup:()=>{}};let a=Array.from(l.querySelectorAll(`.${m}`));if(a.length===0)return console.error(`[aria-ease] No elements with class="${m}" found. Make sure tab buttons exist before calling makeTabsAccessible.`),{cleanup:()=>{}};if(h==="")return console.error("[aria-ease] 'tabPanelsClass' should not be an empty string. Provide a class name that exists on the tab panel elements before calling makeTabsAccessible."),{cleanup:()=>{}};let s=Array.from(document.querySelectorAll(`.${h}`));if(s.length===0)return console.error(`[aria-ease] No elements with class="${h}" found. Make sure tab panels exist before calling makeTabsAccessible.`),{cleanup:()=>{}};if(a.length!==s.length)return console.error(`[aria-ease] Tab/panel mismatch: found ${a.length} tabs but ${s.length} panels.`),{cleanup:()=>{}};let p=new WeakMap,v=new WeakMap,k=new WeakMap,f=0;function g(){l.setAttribute("role","tablist"),l.setAttribute("aria-orientation",E),a.forEach((e,t)=>{let n=s[t];e.id||(e.id=`${b}-tab-${t}`),n.id||(n.id=`${b}-panel-${t}`),e.setAttribute("role","tab"),e.setAttribute("aria-controls",n.id),e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),n.setAttribute("role","tabpanel"),n.setAttribute("aria-labelledby",e.id),n.hidden=true,n.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')||n.setAttribute("tabindex","0");}),d(0,false);}function d(e,t=true){if(e<0||e>=a.length){console.error(`[aria-ease] Invalid tab index: ${e}`);return}let n=f;a.forEach((c,A)=>{let C=s[A];c.setAttribute("aria-selected","false"),c.setAttribute("tabindex","-1"),C.hidden=true;});let r=a[e],o=s[e];if(r.setAttribute("aria-selected","true"),r.setAttribute("tabindex","0"),o.hidden=false,t&&r.focus(),f=e,i?.onTabChange&&n!==e)try{i.onTabChange(e,n);}catch(c){console.error("[aria-ease] Error in tabs onTabChange callback:",c);}}function u(e){let t=a.findIndex(o=>o===document.activeElement),n=t!==-1?t:f,r=n;switch(e){case "first":r=0;break;case "last":r=a.length-1;break;case "next":r=(n+1)%a.length;break;case "prev":r=(n-1+a.length)%a.length;break}if(a[r].focus(),a[r].setAttribute("tabindex","0"),a[f].setAttribute("tabindex","-1"),M)d(r,false);else {let o=f;a.forEach((c,A)=>{A===r?c.setAttribute("tabindex","0"):A!==o&&c.setAttribute("tabindex","-1");});}}function y(e){return ()=>{d(e);}}function w(e){return t=>{let{key:n}=t,r=false;if(E==="horizontal")switch(n){case "ArrowLeft":t.preventDefault(),u("prev"),r=true;break;case "ArrowRight":t.preventDefault(),u("next"),r=true;break}else switch(n){case "ArrowUp":t.preventDefault(),u("prev"),r=true;break;case "ArrowDown":t.preventDefault(),u("next"),r=true;break}if(!r)switch(n){case "Home":t.preventDefault(),u("first");break;case "End":t.preventDefault(),u("last");break;case " ":case "Enter":M||(t.preventDefault(),d(e));break;case "F10":if(t.shiftKey&&i?.onContextMenu){t.preventDefault();try{i.onContextMenu(e,a[e]);}catch(o){console.error("[aria-ease] Error in tabs onContextMenu callback:",o);}}break}}}function H(e){return t=>{if(i?.onContextMenu){t.preventDefault();try{i.onContextMenu(e,a[e]);}catch(n){console.error("[aria-ease] Error in tabs onContextMenu callback:",n);}}}}function x(){a.forEach((e,t)=>{let n=y(t),r=w(t),o=H(t);e.addEventListener("click",n),e.addEventListener("keydown",r),i?.onContextMenu&&(e.addEventListener("contextmenu",o),k.set(e,o)),p.set(e,r),v.set(e,n);});}function T(){a.forEach(e=>{let t=p.get(e),n=v.get(e),r=k.get(e);t&&(e.removeEventListener("keydown",t),p.delete(e)),n&&(e.removeEventListener("click",n),v.delete(e)),r&&(e.removeEventListener("contextmenu",r),k.delete(e));});}function L(){T(),a.forEach((e,t)=>{let n=s[t];e.removeAttribute("role"),e.removeAttribute("aria-selected"),e.removeAttribute("aria-controls"),e.removeAttribute("tabindex"),n.removeAttribute("role"),n.removeAttribute("aria-labelledby"),n.removeAttribute("tabindex"),n.hidden=false;}),l.removeAttribute("role"),l.removeAttribute("aria-orientation");}function $(){T();let e=Array.from(l.querySelectorAll(`.${m}`)),t=Array.from(document.querySelectorAll(`.${h}`));a.length=0,a.push(...e),s.length=0,s.push(...t),g(),x();}return g(),x(),{activateTab:d,cleanup:L,refresh:$}}exports.makeTabsAccessible=D;
@@ -1,263 +1 @@
1
- // src/tabs/src/makeTabsAccessible/makeTabsAccessible.ts
2
- function makeTabsAccessible({ tabListId, tabsClass, tabPanelsClass, orientation = "horizontal", activateOnFocus = true, callback }) {
3
- const tabList = document.querySelector(`#${tabListId}`);
4
- if (!tabList) {
5
- console.error(`[aria-ease] Element with id="${tabListId}" not found. Make sure the tab list container exists before calling makeTabsAccessible.`);
6
- return { cleanup: () => {
7
- } };
8
- }
9
- const tabs = Array.from(tabList.querySelectorAll(`.${tabsClass}`));
10
- if (tabs.length === 0) {
11
- console.error(`[aria-ease] No elements with class="${tabsClass}" found. Make sure tab buttons exist before calling makeTabsAccessible.`);
12
- return { cleanup: () => {
13
- } };
14
- }
15
- const tabPanels = Array.from(document.querySelectorAll(`.${tabPanelsClass}`));
16
- if (tabPanels.length === 0) {
17
- console.error(`[aria-ease] No elements with class="${tabPanelsClass}" found. Make sure tab panels exist before calling makeTabsAccessible.`);
18
- return { cleanup: () => {
19
- } };
20
- }
21
- if (tabs.length !== tabPanels.length) {
22
- console.error(`[aria-ease] Tab/panel mismatch: found ${tabs.length} tabs but ${tabPanels.length} panels.`);
23
- return { cleanup: () => {
24
- } };
25
- }
26
- const handlerMap = /* @__PURE__ */ new WeakMap();
27
- const clickHandlerMap = /* @__PURE__ */ new WeakMap();
28
- const contextMenuHandlerMap = /* @__PURE__ */ new WeakMap();
29
- let activeTabIndex = 0;
30
- function initialize() {
31
- tabList.setAttribute("role", "tablist");
32
- tabList.setAttribute("aria-orientation", orientation);
33
- tabs.forEach((tab, index) => {
34
- const panel = tabPanels[index];
35
- if (!tab.id) {
36
- tab.id = `${tabListId}-tab-${index}`;
37
- }
38
- if (!panel.id) {
39
- panel.id = `${tabListId}-panel-${index}`;
40
- }
41
- tab.setAttribute("role", "tab");
42
- tab.setAttribute("aria-controls", panel.id);
43
- tab.setAttribute("aria-selected", "false");
44
- tab.setAttribute("tabindex", "-1");
45
- panel.setAttribute("role", "tabpanel");
46
- panel.setAttribute("aria-labelledby", tab.id);
47
- panel.hidden = true;
48
- const hasFocusableContent = panel.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
49
- if (!hasFocusableContent) {
50
- panel.setAttribute("tabindex", "0");
51
- }
52
- });
53
- activateTab(0, false);
54
- }
55
- function activateTab(index, shouldFocus = true) {
56
- if (index < 0 || index >= tabs.length) {
57
- console.error(`[aria-ease] Invalid tab index: ${index}`);
58
- return;
59
- }
60
- const previousIndex = activeTabIndex;
61
- tabs.forEach((tab, i) => {
62
- const panel = tabPanels[i];
63
- tab.setAttribute("aria-selected", "false");
64
- tab.setAttribute("tabindex", "-1");
65
- panel.hidden = true;
66
- });
67
- const activeTab = tabs[index];
68
- const activePanel = tabPanels[index];
69
- activeTab.setAttribute("aria-selected", "true");
70
- activeTab.setAttribute("tabindex", "0");
71
- activePanel.hidden = false;
72
- if (shouldFocus) {
73
- activeTab.focus();
74
- }
75
- activeTabIndex = index;
76
- if (callback?.onTabChange && previousIndex !== index) {
77
- try {
78
- callback.onTabChange(index, previousIndex);
79
- } catch (error) {
80
- console.error("[aria-ease] Error in tabs onTabChange callback:", error);
81
- }
82
- }
83
- }
84
- function moveFocus(direction) {
85
- const currentFocusedIndex = tabs.findIndex((tab) => tab === document.activeElement);
86
- const currentIndex = currentFocusedIndex !== -1 ? currentFocusedIndex : activeTabIndex;
87
- let newIndex = currentIndex;
88
- switch (direction) {
89
- case "first":
90
- newIndex = 0;
91
- break;
92
- case "last":
93
- newIndex = tabs.length - 1;
94
- break;
95
- case "next":
96
- newIndex = (currentIndex + 1) % tabs.length;
97
- break;
98
- case "prev":
99
- newIndex = (currentIndex - 1 + tabs.length) % tabs.length;
100
- break;
101
- }
102
- tabs[newIndex].focus();
103
- tabs[newIndex].setAttribute("tabindex", "0");
104
- tabs[activeTabIndex].setAttribute("tabindex", "-1");
105
- if (activateOnFocus) {
106
- activateTab(newIndex, false);
107
- } else {
108
- const currentActive = activeTabIndex;
109
- tabs.forEach((tab, i) => {
110
- if (i === newIndex) {
111
- tab.setAttribute("tabindex", "0");
112
- } else if (i !== currentActive) {
113
- tab.setAttribute("tabindex", "-1");
114
- }
115
- });
116
- }
117
- }
118
- function handleTabClick(index) {
119
- return () => {
120
- activateTab(index);
121
- };
122
- }
123
- function handleTabKeydown(index) {
124
- return (event) => {
125
- const { key } = event;
126
- let handled = false;
127
- if (orientation === "horizontal") {
128
- switch (key) {
129
- case "ArrowLeft":
130
- event.preventDefault();
131
- moveFocus("prev");
132
- handled = true;
133
- break;
134
- case "ArrowRight":
135
- event.preventDefault();
136
- moveFocus("next");
137
- handled = true;
138
- break;
139
- }
140
- } else {
141
- switch (key) {
142
- case "ArrowUp":
143
- event.preventDefault();
144
- moveFocus("prev");
145
- handled = true;
146
- break;
147
- case "ArrowDown":
148
- event.preventDefault();
149
- moveFocus("next");
150
- handled = true;
151
- break;
152
- }
153
- }
154
- if (!handled) {
155
- switch (key) {
156
- case "Home":
157
- event.preventDefault();
158
- moveFocus("first");
159
- break;
160
- case "End":
161
- event.preventDefault();
162
- moveFocus("last");
163
- break;
164
- case " ":
165
- case "Enter":
166
- if (!activateOnFocus) {
167
- event.preventDefault();
168
- activateTab(index);
169
- }
170
- break;
171
- case "F10":
172
- if (event.shiftKey && callback?.onContextMenu) {
173
- event.preventDefault();
174
- try {
175
- callback.onContextMenu(index, tabs[index]);
176
- } catch (error) {
177
- console.error("[aria-ease] Error in tabs onContextMenu callback:", error);
178
- }
179
- }
180
- break;
181
- }
182
- }
183
- };
184
- }
185
- function handleTabContextMenu(index) {
186
- return (event) => {
187
- if (callback?.onContextMenu) {
188
- event.preventDefault();
189
- try {
190
- callback.onContextMenu(index, tabs[index]);
191
- } catch (error) {
192
- console.error("[aria-ease] Error in tabs onContextMenu callback:", error);
193
- }
194
- }
195
- };
196
- }
197
- function addListeners() {
198
- tabs.forEach((tab, index) => {
199
- const clickHandler = handleTabClick(index);
200
- const keydownHandler = handleTabKeydown(index);
201
- const contextMenuHandler = handleTabContextMenu(index);
202
- tab.addEventListener("click", clickHandler);
203
- tab.addEventListener("keydown", keydownHandler);
204
- if (callback?.onContextMenu) {
205
- tab.addEventListener("contextmenu", contextMenuHandler);
206
- contextMenuHandlerMap.set(tab, contextMenuHandler);
207
- }
208
- handlerMap.set(tab, keydownHandler);
209
- clickHandlerMap.set(tab, clickHandler);
210
- });
211
- }
212
- function removeListeners() {
213
- tabs.forEach((tab) => {
214
- const keydownHandler = handlerMap.get(tab);
215
- const clickHandler = clickHandlerMap.get(tab);
216
- const contextMenuHandler = contextMenuHandlerMap.get(tab);
217
- if (keydownHandler) {
218
- tab.removeEventListener("keydown", keydownHandler);
219
- handlerMap.delete(tab);
220
- }
221
- if (clickHandler) {
222
- tab.removeEventListener("click", clickHandler);
223
- clickHandlerMap.delete(tab);
224
- }
225
- if (contextMenuHandler) {
226
- tab.removeEventListener("contextmenu", contextMenuHandler);
227
- contextMenuHandlerMap.delete(tab);
228
- }
229
- });
230
- }
231
- function cleanup() {
232
- removeListeners();
233
- tabs.forEach((tab, index) => {
234
- const panel = tabPanels[index];
235
- tab.removeAttribute("role");
236
- tab.removeAttribute("aria-selected");
237
- tab.removeAttribute("aria-controls");
238
- tab.removeAttribute("tabindex");
239
- panel.removeAttribute("role");
240
- panel.removeAttribute("aria-labelledby");
241
- panel.removeAttribute("tabindex");
242
- panel.hidden = false;
243
- });
244
- tabList.removeAttribute("role");
245
- tabList.removeAttribute("aria-orientation");
246
- }
247
- function refresh() {
248
- removeListeners();
249
- const newTabs = Array.from(tabList.querySelectorAll(`.${tabsClass}`));
250
- const newPanels = Array.from(document.querySelectorAll(`.${tabPanelsClass}`));
251
- tabs.length = 0;
252
- tabs.push(...newTabs);
253
- tabPanels.length = 0;
254
- tabPanels.push(...newPanels);
255
- initialize();
256
- addListeners();
257
- }
258
- initialize();
259
- addListeners();
260
- return { activateTab, cleanup, refresh };
261
- }
262
-
263
- export { makeTabsAccessible };
1
+ function D({tabListId:b,tabsClass:m,tabPanelsClass:h,orientation:E="horizontal",activateOnFocus:M=true,callback:i}){if(b==="")return console.error("[aria-ease] 'tabListId' should not be an empty string. Provide an id to the tab list container element that exists before calling makeTabsAccessible."),{cleanup:()=>{}};let l=document.querySelector(`#${b}`);if(!l)return console.error(`[aria-ease] Element with id="${b}" not found. Make sure the tab list container exists before calling makeTabsAccessible.`),{cleanup:()=>{}};if(m==="")return console.error("[aria-ease] 'tabsClass' should not be an empty string. Provide a class name that exists on the tab button elements before calling makeTabsAccessible."),{cleanup:()=>{}};let a=Array.from(l.querySelectorAll(`.${m}`));if(a.length===0)return console.error(`[aria-ease] No elements with class="${m}" found. Make sure tab buttons exist before calling makeTabsAccessible.`),{cleanup:()=>{}};if(h==="")return console.error("[aria-ease] 'tabPanelsClass' should not be an empty string. Provide a class name that exists on the tab panel elements before calling makeTabsAccessible."),{cleanup:()=>{}};let s=Array.from(document.querySelectorAll(`.${h}`));if(s.length===0)return console.error(`[aria-ease] No elements with class="${h}" found. Make sure tab panels exist before calling makeTabsAccessible.`),{cleanup:()=>{}};if(a.length!==s.length)return console.error(`[aria-ease] Tab/panel mismatch: found ${a.length} tabs but ${s.length} panels.`),{cleanup:()=>{}};let p=new WeakMap,v=new WeakMap,k=new WeakMap,f=0;function g(){l.setAttribute("role","tablist"),l.setAttribute("aria-orientation",E),a.forEach((e,t)=>{let n=s[t];e.id||(e.id=`${b}-tab-${t}`),n.id||(n.id=`${b}-panel-${t}`),e.setAttribute("role","tab"),e.setAttribute("aria-controls",n.id),e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),n.setAttribute("role","tabpanel"),n.setAttribute("aria-labelledby",e.id),n.hidden=true,n.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')||n.setAttribute("tabindex","0");}),d(0,false);}function d(e,t=true){if(e<0||e>=a.length){console.error(`[aria-ease] Invalid tab index: ${e}`);return}let n=f;a.forEach((c,A)=>{let C=s[A];c.setAttribute("aria-selected","false"),c.setAttribute("tabindex","-1"),C.hidden=true;});let r=a[e],o=s[e];if(r.setAttribute("aria-selected","true"),r.setAttribute("tabindex","0"),o.hidden=false,t&&r.focus(),f=e,i?.onTabChange&&n!==e)try{i.onTabChange(e,n);}catch(c){console.error("[aria-ease] Error in tabs onTabChange callback:",c);}}function u(e){let t=a.findIndex(o=>o===document.activeElement),n=t!==-1?t:f,r=n;switch(e){case "first":r=0;break;case "last":r=a.length-1;break;case "next":r=(n+1)%a.length;break;case "prev":r=(n-1+a.length)%a.length;break}if(a[r].focus(),a[r].setAttribute("tabindex","0"),a[f].setAttribute("tabindex","-1"),M)d(r,false);else {let o=f;a.forEach((c,A)=>{A===r?c.setAttribute("tabindex","0"):A!==o&&c.setAttribute("tabindex","-1");});}}function y(e){return ()=>{d(e);}}function w(e){return t=>{let{key:n}=t,r=false;if(E==="horizontal")switch(n){case "ArrowLeft":t.preventDefault(),u("prev"),r=true;break;case "ArrowRight":t.preventDefault(),u("next"),r=true;break}else switch(n){case "ArrowUp":t.preventDefault(),u("prev"),r=true;break;case "ArrowDown":t.preventDefault(),u("next"),r=true;break}if(!r)switch(n){case "Home":t.preventDefault(),u("first");break;case "End":t.preventDefault(),u("last");break;case " ":case "Enter":M||(t.preventDefault(),d(e));break;case "F10":if(t.shiftKey&&i?.onContextMenu){t.preventDefault();try{i.onContextMenu(e,a[e]);}catch(o){console.error("[aria-ease] Error in tabs onContextMenu callback:",o);}}break}}}function H(e){return t=>{if(i?.onContextMenu){t.preventDefault();try{i.onContextMenu(e,a[e]);}catch(n){console.error("[aria-ease] Error in tabs onContextMenu callback:",n);}}}}function x(){a.forEach((e,t)=>{let n=y(t),r=w(t),o=H(t);e.addEventListener("click",n),e.addEventListener("keydown",r),i?.onContextMenu&&(e.addEventListener("contextmenu",o),k.set(e,o)),p.set(e,r),v.set(e,n);});}function T(){a.forEach(e=>{let t=p.get(e),n=v.get(e),r=k.get(e);t&&(e.removeEventListener("keydown",t),p.delete(e)),n&&(e.removeEventListener("click",n),v.delete(e)),r&&(e.removeEventListener("contextmenu",r),k.delete(e));});}function L(){T(),a.forEach((e,t)=>{let n=s[t];e.removeAttribute("role"),e.removeAttribute("aria-selected"),e.removeAttribute("aria-controls"),e.removeAttribute("tabindex"),n.removeAttribute("role"),n.removeAttribute("aria-labelledby"),n.removeAttribute("tabindex"),n.hidden=false;}),l.removeAttribute("role"),l.removeAttribute("aria-orientation");}function $(){T();let e=Array.from(l.querySelectorAll(`.${m}`)),t=Array.from(document.querySelectorAll(`.${h}`));a.length=0,a.push(...e),s.length=0,s.push(...t),g(),x();}return g(),x(),{activateTab:d,cleanup:L,refresh:$}}export{D as makeTabsAccessible};
@@ -1,119 +1 @@
1
- 'use strict';
2
-
3
- // src/toggle/src/makeTogggleAccessible/makeToggleAccessible.ts
4
- function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle = true }) {
5
- const toggleContainer = document.querySelector(`#${toggleId}`);
6
- if (!toggleContainer) {
7
- console.error(`[aria-ease] Element with id="${toggleId}" not found. Make sure the toggle element exists before calling makeToggleAccessible.`);
8
- return { cleanup: () => {
9
- } };
10
- }
11
- let toggles;
12
- if (isSingleToggle) {
13
- toggles = [toggleContainer];
14
- } else {
15
- if (!togglesClass) {
16
- console.error(`[aria-ease] togglesClass is required when isSingleToggle is false.`);
17
- return { cleanup: () => {
18
- } };
19
- }
20
- toggles = Array.from(toggleContainer.querySelectorAll(`.${togglesClass}`));
21
- if (toggles.length === 0) {
22
- console.error(`[aria-ease] No elements with class="${togglesClass}" found. Make sure toggle buttons exist before calling makeToggleAccessible.`);
23
- return { cleanup: () => {
24
- } };
25
- }
26
- }
27
- const handlerMap = /* @__PURE__ */ new WeakMap();
28
- const clickHandlerMap = /* @__PURE__ */ new WeakMap();
29
- function initialize() {
30
- toggles.forEach((toggle) => {
31
- if (toggle.tagName.toLowerCase() !== "button" && !toggle.getAttribute("role")) {
32
- toggle.setAttribute("role", "button");
33
- }
34
- if (!toggle.hasAttribute("aria-pressed")) {
35
- toggle.setAttribute("aria-pressed", "false");
36
- }
37
- if (!toggle.hasAttribute("tabindex")) {
38
- toggle.setAttribute("tabindex", "0");
39
- }
40
- });
41
- }
42
- function toggleButton(index) {
43
- if (index < 0 || index >= toggles.length) {
44
- console.error(`[aria-ease] Invalid toggle index: ${index}`);
45
- return;
46
- }
47
- const toggle = toggles[index];
48
- const isPressed = toggle.getAttribute("aria-pressed") === "true";
49
- toggle.setAttribute("aria-pressed", isPressed ? "false" : "true");
50
- }
51
- function setPressed(index, pressed) {
52
- if (index < 0 || index >= toggles.length) {
53
- console.error(`[aria-ease] Invalid toggle index: ${index}`);
54
- return;
55
- }
56
- toggles[index].setAttribute("aria-pressed", pressed ? "true" : "false");
57
- }
58
- function handleToggleClick(index) {
59
- return () => {
60
- toggleButton(index);
61
- };
62
- }
63
- function handleToggleKeydown(index) {
64
- return (event) => {
65
- const { key } = event;
66
- switch (key) {
67
- case "Enter":
68
- case " ":
69
- event.preventDefault();
70
- toggleButton(index);
71
- break;
72
- }
73
- };
74
- }
75
- function addListeners() {
76
- toggles.forEach((toggle, index) => {
77
- const clickHandler = handleToggleClick(index);
78
- const keydownHandler = handleToggleKeydown(index);
79
- toggle.addEventListener("click", clickHandler);
80
- toggle.addEventListener("keydown", keydownHandler);
81
- handlerMap.set(toggle, keydownHandler);
82
- clickHandlerMap.set(toggle, clickHandler);
83
- });
84
- }
85
- function removeListeners() {
86
- toggles.forEach((toggle) => {
87
- const keydownHandler = handlerMap.get(toggle);
88
- const clickHandler = clickHandlerMap.get(toggle);
89
- if (keydownHandler) {
90
- toggle.removeEventListener("keydown", keydownHandler);
91
- handlerMap.delete(toggle);
92
- }
93
- if (clickHandler) {
94
- toggle.removeEventListener("click", clickHandler);
95
- clickHandlerMap.delete(toggle);
96
- }
97
- });
98
- }
99
- function cleanup() {
100
- removeListeners();
101
- }
102
- function getPressedStates() {
103
- return toggles.map((toggle) => toggle.getAttribute("aria-pressed") === "true");
104
- }
105
- function getPressedIndices() {
106
- return toggles.map((toggle, index) => toggle.getAttribute("aria-pressed") === "true" ? index : -1).filter((index) => index !== -1);
107
- }
108
- initialize();
109
- addListeners();
110
- return {
111
- toggleButton,
112
- setPressed,
113
- getPressedStates,
114
- getPressedIndices,
115
- cleanup
116
- };
117
- }
118
-
119
- exports.makeToggleAccessible = makeToggleAccessible;
1
+ 'use strict';function T({toggleId:s,togglesClass:i,isSingleToggle:d=true}){if(s==="")return console.error("[aria-ease] 'toggleId' should not be an empty string. Provide an id to the toggle element or toggle container before calling makeToggleAccessible."),{cleanup:()=>{}};let a=document.querySelector(`#${s}`);if(!a)return console.error(`[aria-ease] Element with id="${s}" not found. Make sure the toggle element exists before calling makeToggleAccessible.`),{cleanup:()=>{}};let r;if(d)r=[a];else {if(!i)return console.error("[aria-ease] togglesClass is required when isSingleToggle is false."),{cleanup:()=>{}};if(r=Array.from(a.querySelectorAll(`.${i}`)),r.length===0)return console.error(`[aria-ease] No elements with class="${i}" found. Make sure toggle buttons exist before calling makeToggleAccessible.`),{cleanup:()=>{}}}let o=new WeakMap,l=new WeakMap;function f(){r.forEach(e=>{e.tagName.toLowerCase()!=="button"&&!e.getAttribute("role")&&e.setAttribute("role","button"),e.hasAttribute("aria-pressed")||e.setAttribute("aria-pressed","false"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0");});}function c(e){if(e<0||e>=r.length){console.error(`[aria-ease] Invalid toggle index: ${e}`);return}let t=r[e],n=t.getAttribute("aria-pressed")==="true";t.setAttribute("aria-pressed",n?"false":"true");}function b(e,t){if(e<0||e>=r.length){console.error(`[aria-ease] Invalid toggle index: ${e}`);return}r[e].setAttribute("aria-pressed",t?"true":"false");}function g(e){return ()=>{c(e);}}function m(e){return t=>{let{key:n}=t;switch(n){case "Enter":case " ":t.preventDefault(),c(e);break}}}function p(){r.forEach((e,t)=>{let n=g(t),u=m(t);e.addEventListener("click",n),e.addEventListener("keydown",u),o.set(e,u),l.set(e,n);});}function k(){r.forEach(e=>{let t=o.get(e),n=l.get(e);t&&(e.removeEventListener("keydown",t),o.delete(e)),n&&(e.removeEventListener("click",n),l.delete(e));});}function A(){k();}function h(){return r.map(e=>e.getAttribute("aria-pressed")==="true")}function E(){return r.map((e,t)=>e.getAttribute("aria-pressed")==="true"?t:-1).filter(e=>e!==-1)}return f(),p(),{toggleButton:c,setPressed:b,getPressedStates:h,getPressedIndices:E,cleanup:A}}exports.makeToggleAccessible=T;