aria-ease 6.0.0 → 6.1.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 (33) hide show
  1. package/bin/cli.cjs +21 -8
  2. package/bin/cli.js +1 -1
  3. package/bin/{contractTestRunnerPlaywright-PMSOP5FY.js → contractTestRunnerPlaywright-HL2VPEEV.js} +21 -8
  4. package/bin/{test-X6K2LCMO.js → test-HH2EW2NM.js} +1 -1
  5. package/dist/{contractTestRunnerPlaywright-ZO6GM4TU.js → contractTestRunnerPlaywright-EXEBWWPC.js} +21 -8
  6. package/dist/index.cjs +41 -20
  7. package/dist/index.d.cts +20 -12
  8. package/dist/index.d.ts +20 -12
  9. package/dist/index.js +21 -13
  10. package/dist/src/{Types.d-COr5IFp5.d.ts → Types.d-B-NDbH_q.d.cts} +17 -4
  11. package/dist/src/{Types.d-COr5IFp5.d.cts → Types.d-B-NDbH_q.d.ts} +17 -4
  12. package/dist/src/accordion/index.cjs +7 -1
  13. package/dist/src/accordion/index.d.cts +3 -8
  14. package/dist/src/accordion/index.d.ts +3 -8
  15. package/dist/src/accordion/index.js +7 -1
  16. package/dist/src/block/index.d.cts +1 -1
  17. package/dist/src/block/index.d.ts +1 -1
  18. package/dist/src/checkbox/index.d.cts +1 -1
  19. package/dist/src/checkbox/index.d.ts +1 -1
  20. package/dist/src/combobox/index.cjs +13 -11
  21. package/dist/src/combobox/index.d.cts +3 -3
  22. package/dist/src/combobox/index.d.ts +3 -3
  23. package/dist/src/combobox/index.js +13 -11
  24. package/dist/src/menu/index.d.cts +1 -1
  25. package/dist/src/menu/index.d.ts +1 -1
  26. package/dist/src/radio/index.d.cts +1 -1
  27. package/dist/src/radio/index.d.ts +1 -1
  28. package/dist/src/toggle/index.d.cts +1 -1
  29. package/dist/src/toggle/index.d.ts +1 -1
  30. package/dist/src/utils/test/{contractTestRunnerPlaywright-CREJNINL.js → contractTestRunnerPlaywright-LJHY3AB4.js} +21 -8
  31. package/dist/src/utils/test/index.cjs +21 -8
  32. package/dist/src/utils/test/index.js +1 -1
  33. package/package.json +1 -1
package/bin/cli.cjs CHANGED
@@ -676,7 +676,6 @@ async function runContractTestsPlaywright(componentName, url) {
676
676
  const passes = [];
677
677
  const skipped = [];
678
678
  let page = null;
679
- const useNavigation = !!url;
680
679
  try {
681
680
  page = await createTestPage();
682
681
  if (url) {
@@ -690,8 +689,7 @@ async function runContractTestsPlaywright(componentName, url) {
690
689
  if (!mainSelector) {
691
690
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
692
691
  }
693
- const elementTimeout = useNavigation ? 3e4 : 5e3;
694
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
692
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
695
693
  if (componentName === "menu" && componentContract.selectors.trigger) {
696
694
  await page.locator(componentContract.selectors.trigger).first().waitFor({
697
695
  state: "visible",
@@ -802,15 +800,13 @@ async function runContractTestsPlaywright(componentName, url) {
802
800
  menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
803
801
  }
804
802
  if (!menuClosed) {
805
- if (useNavigation) {
806
- throw new Error(
807
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
803
+ throw new Error(
804
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
808
805
  1. Escape key
809
806
  2. Clicking trigger
810
807
  3. Clicking outside
811
808
  This indicates a problem with the menu component's close functionality.`
812
- );
813
- }
809
+ );
814
810
  }
815
811
  if (componentContract.selectors.input) {
816
812
  await page.locator(componentContract.selectors.input).first().clear();
@@ -821,6 +817,23 @@ This indicates a problem with the menu component's close functionality.`
821
817
  }
822
818
  }
823
819
  }
820
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
821
+ const triggerSelector = componentContract.selectors.trigger;
822
+ const panelSelector = componentContract.selectors.panel;
823
+ if (triggerSelector && panelSelector) {
824
+ const allTriggers = await page.locator(triggerSelector).all();
825
+ for (const trigger of allTriggers) {
826
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
827
+ const triggerPanel = await trigger.getAttribute("aria-controls");
828
+ if (isExpanded && triggerPanel) {
829
+ await trigger.click();
830
+ const panel = page.locator(`#${triggerPanel}`);
831
+ await (0, test_exports.expect)(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
832
+ });
833
+ }
834
+ }
835
+ }
836
+ }
824
837
  let shouldSkipTest = false;
825
838
  for (const act of action) {
826
839
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
package/bin/cli.js CHANGED
@@ -204,7 +204,7 @@ program.command("audit").description("Run axe-core powered accessibility audit o
204
204
  console.log(chalk.green("\n\u{1F389} All audits completed."));
205
205
  });
206
206
  program.command("test").description("Run core a11y accessibility standard tests on UI components").action(async () => {
207
- const { runTest } = await import("./test-X6K2LCMO.js");
207
+ const { runTest } = await import("./test-HH2EW2NM.js");
208
208
  runTest();
209
209
  });
210
210
  program.command("help").description("Display help information").action(() => {
@@ -36,7 +36,6 @@ async function runContractTestsPlaywright(componentName, url) {
36
36
  const passes = [];
37
37
  const skipped = [];
38
38
  let page = null;
39
- const useNavigation = !!url;
40
39
  try {
41
40
  page = await createTestPage();
42
41
  if (url) {
@@ -50,8 +49,7 @@ async function runContractTestsPlaywright(componentName, url) {
50
49
  if (!mainSelector) {
51
50
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
52
51
  }
53
- const elementTimeout = useNavigation ? 3e4 : 5e3;
54
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
52
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
55
53
  if (componentName === "menu" && componentContract.selectors.trigger) {
56
54
  await page.locator(componentContract.selectors.trigger).first().waitFor({
57
55
  state: "visible",
@@ -162,15 +160,13 @@ async function runContractTestsPlaywright(componentName, url) {
162
160
  menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
163
161
  }
164
162
  if (!menuClosed) {
165
- if (useNavigation) {
166
- throw new Error(
167
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
163
+ throw new Error(
164
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
168
165
  1. Escape key
169
166
  2. Clicking trigger
170
167
  3. Clicking outside
171
168
  This indicates a problem with the menu component's close functionality.`
172
- );
173
- }
169
+ );
174
170
  }
175
171
  if (componentContract.selectors.input) {
176
172
  await page.locator(componentContract.selectors.input).first().clear();
@@ -181,6 +177,23 @@ This indicates a problem with the menu component's close functionality.`
181
177
  }
182
178
  }
183
179
  }
180
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
181
+ const triggerSelector = componentContract.selectors.trigger;
182
+ const panelSelector = componentContract.selectors.panel;
183
+ if (triggerSelector && panelSelector) {
184
+ const allTriggers = await page.locator(triggerSelector).all();
185
+ for (const trigger of allTriggers) {
186
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
187
+ const triggerPanel = await trigger.getAttribute("aria-controls");
188
+ if (isExpanded && triggerPanel) {
189
+ await trigger.click();
190
+ const panel = page.locator(`#${triggerPanel}`);
191
+ await (0, test_exports.expect)(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
192
+ });
193
+ }
194
+ }
195
+ }
196
+ }
184
197
  let shouldSkipTest = false;
185
198
  for (const act of action) {
186
199
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
@@ -114,7 +114,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
114
114
  const devServerUrl = await checkDevServer(url);
115
115
  if (devServerUrl) {
116
116
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
117
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-PMSOP5FY.js");
117
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-HL2VPEEV.js");
118
118
  contract = await runContractTestsPlaywright(componentName, devServerUrl);
119
119
  } else {
120
120
  throw new Error(
@@ -34,7 +34,6 @@ async function runContractTestsPlaywright(componentName, url) {
34
34
  const passes = [];
35
35
  const skipped = [];
36
36
  let page = null;
37
- const useNavigation = !!url;
38
37
  try {
39
38
  page = await createTestPage();
40
39
  if (url) {
@@ -48,8 +47,7 @@ async function runContractTestsPlaywright(componentName, url) {
48
47
  if (!mainSelector) {
49
48
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
50
49
  }
51
- const elementTimeout = useNavigation ? 3e4 : 5e3;
52
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
50
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
53
51
  if (componentName === "menu" && componentContract.selectors.trigger) {
54
52
  await page.locator(componentContract.selectors.trigger).first().waitFor({
55
53
  state: "visible",
@@ -160,15 +158,13 @@ async function runContractTestsPlaywright(componentName, url) {
160
158
  menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
161
159
  }
162
160
  if (!menuClosed) {
163
- if (useNavigation) {
164
- throw new Error(
165
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
161
+ throw new Error(
162
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
166
163
  1. Escape key
167
164
  2. Clicking trigger
168
165
  3. Clicking outside
169
166
  This indicates a problem with the menu component's close functionality.`
170
- );
171
- }
167
+ );
172
168
  }
173
169
  if (componentContract.selectors.input) {
174
170
  await page.locator(componentContract.selectors.input).first().clear();
@@ -179,6 +175,23 @@ This indicates a problem with the menu component's close functionality.`
179
175
  }
180
176
  }
181
177
  }
178
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
179
+ const triggerSelector = componentContract.selectors.trigger;
180
+ const panelSelector = componentContract.selectors.panel;
181
+ if (triggerSelector && panelSelector) {
182
+ const allTriggers = await page.locator(triggerSelector).all();
183
+ for (const trigger of allTriggers) {
184
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
185
+ const triggerPanel = await trigger.getAttribute("aria-controls");
186
+ if (isExpanded && triggerPanel) {
187
+ await trigger.click();
188
+ const panel = page.locator(`#${triggerPanel}`);
189
+ await (0, test_exports.expect)(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
190
+ });
191
+ }
192
+ }
193
+ }
194
+ }
182
195
  let shouldSkipTest = false;
183
196
  for (const act of action) {
184
197
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
package/dist/index.cjs CHANGED
@@ -365,7 +365,6 @@ async function runContractTestsPlaywright(componentName, url) {
365
365
  const passes = [];
366
366
  const skipped = [];
367
367
  let page = null;
368
- const useNavigation = !!url;
369
368
  try {
370
369
  page = await createTestPage();
371
370
  if (url) {
@@ -379,8 +378,7 @@ async function runContractTestsPlaywright(componentName, url) {
379
378
  if (!mainSelector) {
380
379
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
381
380
  }
382
- const elementTimeout = useNavigation ? 3e4 : 5e3;
383
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
381
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
384
382
  if (componentName === "menu" && componentContract.selectors.trigger) {
385
383
  await page.locator(componentContract.selectors.trigger).first().waitFor({
386
384
  state: "visible",
@@ -491,15 +489,13 @@ async function runContractTestsPlaywright(componentName, url) {
491
489
  menuClosed = await (0, test_exports.expect)(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
492
490
  }
493
491
  if (!menuClosed) {
494
- if (useNavigation) {
495
- throw new Error(
496
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
492
+ throw new Error(
493
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
497
494
  1. Escape key
498
495
  2. Clicking trigger
499
496
  3. Clicking outside
500
497
  This indicates a problem with the menu component's close functionality.`
501
- );
502
- }
498
+ );
503
499
  }
504
500
  if (componentContract.selectors.input) {
505
501
  await page.locator(componentContract.selectors.input).first().clear();
@@ -510,6 +506,23 @@ This indicates a problem with the menu component's close functionality.`
510
506
  }
511
507
  }
512
508
  }
509
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
510
+ const triggerSelector = componentContract.selectors.trigger;
511
+ const panelSelector = componentContract.selectors.panel;
512
+ if (triggerSelector && panelSelector) {
513
+ const allTriggers = await page.locator(triggerSelector).all();
514
+ for (const trigger of allTriggers) {
515
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
516
+ const triggerPanel = await trigger.getAttribute("aria-controls");
517
+ if (isExpanded && triggerPanel) {
518
+ await trigger.click();
519
+ const panel = page.locator(`#${triggerPanel}`);
520
+ await (0, test_exports.expect)(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
521
+ });
522
+ }
523
+ }
524
+ }
525
+ }
513
526
  let shouldSkipTest = false;
514
527
  for (const act of action) {
515
528
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
@@ -819,7 +832,7 @@ __export(index_exports, {
819
832
  module.exports = __toCommonJS(index_exports);
820
833
 
821
834
  // src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
822
- function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false }) {
835
+ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false, callback }) {
823
836
  const accordionContainer = document.querySelector(`#${accordionId}`);
824
837
  if (!accordionContainer) {
825
838
  console.error(`[aria-ease] Element with id="${accordionId}" not found. Make sure the accordion container exists before calling makeAccordionAccessible.`);
@@ -870,6 +883,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
870
883
  const panel = panels[index];
871
884
  trigger.setAttribute("aria-expanded", "true");
872
885
  panel.style.display = "block";
886
+ if (callback?.onExpand) {
887
+ callback.onExpand(index);
888
+ }
873
889
  }
874
890
  function collapseItem(index) {
875
891
  if (index < 0 || index >= triggers.length) {
@@ -880,6 +896,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
880
896
  const panel = panels[index];
881
897
  trigger.setAttribute("aria-expanded", "false");
882
898
  panel.style.display = "none";
899
+ if (callback?.onCollapse) {
900
+ callback.onCollapse(index);
901
+ }
883
902
  }
884
903
  function toggleItem(index) {
885
904
  const trigger = triggers[index];
@@ -1742,7 +1761,7 @@ function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle = true })
1742
1761
  }
1743
1762
 
1744
1763
  // src/combobox/src/makeComboBoxAccessible/makeComboBoxAccessible.ts
1745
- function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }) {
1764
+ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }) {
1746
1765
  const comboboxInput = document.getElementById(`${comboboxInputId}`);
1747
1766
  if (!comboboxInput) {
1748
1767
  console.error(`[aria-ease] Element with id="${comboboxInputId}" not found. Make sure the combobox input element exists before calling makeComboboxAccessible.`);
@@ -1789,9 +1808,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1789
1808
  if (typeof activeItem.scrollIntoView === "function") {
1790
1809
  activeItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
1791
1810
  }
1792
- if (config?.onActiveDescendantChange) {
1811
+ if (callback?.onActiveDescendantChange) {
1793
1812
  try {
1794
- config.onActiveDescendantChange(itemId, activeItem);
1813
+ callback.onActiveDescendantChange(itemId, activeItem);
1795
1814
  } catch (error) {
1796
1815
  console.error("[aria-ease] Error in onActiveDescendantChange callback:", error);
1797
1816
  }
@@ -1803,9 +1822,10 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1803
1822
  }
1804
1823
  function openListbox() {
1805
1824
  comboboxInput.setAttribute("aria-expanded", "true");
1806
- if (config?.onOpenChange) {
1825
+ listBox.style.display = "block";
1826
+ if (callback?.onOpenChange) {
1807
1827
  try {
1808
- config.onOpenChange(true);
1828
+ callback.onOpenChange(true);
1809
1829
  } catch (error) {
1810
1830
  console.error("[aria-ease] Error in onOpenChange callback:", error);
1811
1831
  }
@@ -1814,12 +1834,13 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1814
1834
  function closeListbox() {
1815
1835
  comboboxInput.setAttribute("aria-expanded", "false");
1816
1836
  comboboxInput.setAttribute("aria-activedescendant", "");
1837
+ listBox.style.display = "none";
1817
1838
  activeIndex = -1;
1818
1839
  const visibleItems = getVisibleItems();
1819
1840
  visibleItems.forEach((item) => item.setAttribute("aria-selected", "false"));
1820
- if (config?.onOpenChange) {
1841
+ if (callback?.onOpenChange) {
1821
1842
  try {
1822
- config.onOpenChange(false);
1843
+ callback.onOpenChange(false);
1823
1844
  } catch (error) {
1824
1845
  console.error("[aria-ease] Error in onOpenChange callback:", error);
1825
1846
  }
@@ -1829,9 +1850,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1829
1850
  const value = item.textContent?.trim() || "";
1830
1851
  comboboxInput.value = value;
1831
1852
  closeListbox();
1832
- if (config?.onSelect) {
1853
+ if (callback?.onSelect) {
1833
1854
  try {
1834
- config.onSelect(item, value);
1855
+ callback.onSelect(item);
1835
1856
  } catch (error) {
1836
1857
  console.error("[aria-ease] Error in onSelect callback:", error);
1837
1858
  }
@@ -1874,9 +1895,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1874
1895
  } else if (comboboxInput.value) {
1875
1896
  event.preventDefault();
1876
1897
  comboboxInput.value = "";
1877
- if (config?.onClear) {
1898
+ if (callback?.onClear) {
1878
1899
  try {
1879
- config.onClear();
1900
+ callback.onClear();
1880
1901
  } catch (error) {
1881
1902
  console.error("[aria-ease] Error in onClear callback:", error);
1882
1903
  }
package/dist/index.d.cts CHANGED
@@ -28,16 +28,29 @@ interface AccessibilityInstance {
28
28
  getPressedIndices?: () => number[];
29
29
  }
30
30
 
31
+ interface AccordionConfig {
32
+ accordionId: string;
33
+ triggersClass: string;
34
+ panelsClass: string;
35
+ allowMultipleOpen?: boolean;
36
+ callback?: AccordionCallback;
37
+ }
38
+
39
+ interface AccordionCallback {
40
+ onExpand?: (index: number) => void;
41
+ onCollapse?: (index: number) => void;
42
+ }
43
+
31
44
  interface ComboboxConfig {
32
45
  comboboxInputId: string;
33
46
  comboboxButtonId?: string;
34
47
  listBoxId: string;
35
48
  listBoxItemsClass: string;
36
- config?: config;
49
+ callback?: ComboboxCallback;
37
50
  }
38
51
 
39
- interface config {
40
- onSelect?: (item: HTMLElement, value: string) => void;
52
+ interface ComboboxCallback {
53
+ onSelect?: (item: HTMLElement) => void;
41
54
  onOpenChange?: (isOpen: boolean) => void;
42
55
  onActiveDescendantChange?: (optionId: string, item: HTMLElement) => void;
43
56
  onClear?: () => void;
@@ -50,15 +63,10 @@ interface config {
50
63
  * @param {string} triggersClass - The shared class of all accordion trigger buttons.
51
64
  * @param {string} panelsClass - The shared class of all accordion panels.
52
65
  * @param {boolean} allowMultipleOpen - Whether multiple panels can be open simultaneously (default: false).
66
+ * @param {AccordionCallback} callback - Configuration options for callbacks.
53
67
  */
54
68
 
55
- interface AccordionConfig {
56
- accordionId: string;
57
- triggersClass: string;
58
- panelsClass: string;
59
- allowMultipleOpen?: boolean;
60
- }
61
- declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen }: AccordionConfig): AccessibilityInstance;
69
+ declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen, callback }: AccordionConfig): AccessibilityInstance;
62
70
 
63
71
  /**
64
72
  * Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
@@ -134,10 +142,10 @@ declare function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle }
134
142
  * @param {string} comboboxButtonId - The id of the button that toggles the listbox (optional).
135
143
  * @param {string} listBoxId - The id of the listbox element.
136
144
  * @param {string} listBoxItemsClass - The class of the items within the listbox.
137
- * @param {ComboboxConfig} config - Configuration options for callbacks.
145
+ * @param {ComboboxCallback} callback - Configuration options for callbacks.
138
146
  */
139
147
 
140
- declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }: ComboboxConfig): AccessibilityInstance;
148
+ declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }: ComboboxConfig): AccessibilityInstance;
141
149
 
142
150
  /**
143
151
  * Runs static and interactions accessibility test on UI components.
package/dist/index.d.ts CHANGED
@@ -28,16 +28,29 @@ interface AccessibilityInstance {
28
28
  getPressedIndices?: () => number[];
29
29
  }
30
30
 
31
+ interface AccordionConfig {
32
+ accordionId: string;
33
+ triggersClass: string;
34
+ panelsClass: string;
35
+ allowMultipleOpen?: boolean;
36
+ callback?: AccordionCallback;
37
+ }
38
+
39
+ interface AccordionCallback {
40
+ onExpand?: (index: number) => void;
41
+ onCollapse?: (index: number) => void;
42
+ }
43
+
31
44
  interface ComboboxConfig {
32
45
  comboboxInputId: string;
33
46
  comboboxButtonId?: string;
34
47
  listBoxId: string;
35
48
  listBoxItemsClass: string;
36
- config?: config;
49
+ callback?: ComboboxCallback;
37
50
  }
38
51
 
39
- interface config {
40
- onSelect?: (item: HTMLElement, value: string) => void;
52
+ interface ComboboxCallback {
53
+ onSelect?: (item: HTMLElement) => void;
41
54
  onOpenChange?: (isOpen: boolean) => void;
42
55
  onActiveDescendantChange?: (optionId: string, item: HTMLElement) => void;
43
56
  onClear?: () => void;
@@ -50,15 +63,10 @@ interface config {
50
63
  * @param {string} triggersClass - The shared class of all accordion trigger buttons.
51
64
  * @param {string} panelsClass - The shared class of all accordion panels.
52
65
  * @param {boolean} allowMultipleOpen - Whether multiple panels can be open simultaneously (default: false).
66
+ * @param {AccordionCallback} callback - Configuration options for callbacks.
53
67
  */
54
68
 
55
- interface AccordionConfig {
56
- accordionId: string;
57
- triggersClass: string;
58
- panelsClass: string;
59
- allowMultipleOpen?: boolean;
60
- }
61
- declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen }: AccordionConfig): AccessibilityInstance;
69
+ declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen, callback }: AccordionConfig): AccessibilityInstance;
62
70
 
63
71
  /**
64
72
  * Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
@@ -134,10 +142,10 @@ declare function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle }
134
142
  * @param {string} comboboxButtonId - The id of the button that toggles the listbox (optional).
135
143
  * @param {string} listBoxId - The id of the listbox element.
136
144
  * @param {string} listBoxItemsClass - The class of the items within the listbox.
137
- * @param {ComboboxConfig} config - Configuration options for callbacks.
145
+ * @param {ComboboxCallback} callback - Configuration options for callbacks.
138
146
  */
139
147
 
140
- declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }: ComboboxConfig): AccessibilityInstance;
148
+ declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }: ComboboxConfig): AccessibilityInstance;
141
149
 
142
150
  /**
143
151
  * Runs static and interactions accessibility test on UI components.
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-PDZQOXUN.js";
6
6
 
7
7
  // src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
8
- function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false }) {
8
+ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false, callback }) {
9
9
  const accordionContainer = document.querySelector(`#${accordionId}`);
10
10
  if (!accordionContainer) {
11
11
  console.error(`[aria-ease] Element with id="${accordionId}" not found. Make sure the accordion container exists before calling makeAccordionAccessible.`);
@@ -56,6 +56,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
56
56
  const panel = panels[index];
57
57
  trigger.setAttribute("aria-expanded", "true");
58
58
  panel.style.display = "block";
59
+ if (callback?.onExpand) {
60
+ callback.onExpand(index);
61
+ }
59
62
  }
60
63
  function collapseItem(index) {
61
64
  if (index < 0 || index >= triggers.length) {
@@ -66,6 +69,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
66
69
  const panel = panels[index];
67
70
  trigger.setAttribute("aria-expanded", "false");
68
71
  panel.style.display = "none";
72
+ if (callback?.onCollapse) {
73
+ callback.onCollapse(index);
74
+ }
69
75
  }
70
76
  function toggleItem(index) {
71
77
  const trigger = triggers[index];
@@ -928,7 +934,7 @@ function makeToggleAccessible({ toggleId, togglesClass, isSingleToggle = true })
928
934
  }
929
935
 
930
936
  // src/combobox/src/makeComboBoxAccessible/makeComboBoxAccessible.ts
931
- function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }) {
937
+ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }) {
932
938
  const comboboxInput = document.getElementById(`${comboboxInputId}`);
933
939
  if (!comboboxInput) {
934
940
  console.error(`[aria-ease] Element with id="${comboboxInputId}" not found. Make sure the combobox input element exists before calling makeComboboxAccessible.`);
@@ -975,9 +981,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
975
981
  if (typeof activeItem.scrollIntoView === "function") {
976
982
  activeItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
977
983
  }
978
- if (config?.onActiveDescendantChange) {
984
+ if (callback?.onActiveDescendantChange) {
979
985
  try {
980
- config.onActiveDescendantChange(itemId, activeItem);
986
+ callback.onActiveDescendantChange(itemId, activeItem);
981
987
  } catch (error) {
982
988
  console.error("[aria-ease] Error in onActiveDescendantChange callback:", error);
983
989
  }
@@ -989,9 +995,10 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
989
995
  }
990
996
  function openListbox() {
991
997
  comboboxInput.setAttribute("aria-expanded", "true");
992
- if (config?.onOpenChange) {
998
+ listBox.style.display = "block";
999
+ if (callback?.onOpenChange) {
993
1000
  try {
994
- config.onOpenChange(true);
1001
+ callback.onOpenChange(true);
995
1002
  } catch (error) {
996
1003
  console.error("[aria-ease] Error in onOpenChange callback:", error);
997
1004
  }
@@ -1000,12 +1007,13 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1000
1007
  function closeListbox() {
1001
1008
  comboboxInput.setAttribute("aria-expanded", "false");
1002
1009
  comboboxInput.setAttribute("aria-activedescendant", "");
1010
+ listBox.style.display = "none";
1003
1011
  activeIndex = -1;
1004
1012
  const visibleItems = getVisibleItems();
1005
1013
  visibleItems.forEach((item) => item.setAttribute("aria-selected", "false"));
1006
- if (config?.onOpenChange) {
1014
+ if (callback?.onOpenChange) {
1007
1015
  try {
1008
- config.onOpenChange(false);
1016
+ callback.onOpenChange(false);
1009
1017
  } catch (error) {
1010
1018
  console.error("[aria-ease] Error in onOpenChange callback:", error);
1011
1019
  }
@@ -1015,9 +1023,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1015
1023
  const value = item.textContent?.trim() || "";
1016
1024
  comboboxInput.value = value;
1017
1025
  closeListbox();
1018
- if (config?.onSelect) {
1026
+ if (callback?.onSelect) {
1019
1027
  try {
1020
- config.onSelect(item, value);
1028
+ callback.onSelect(item);
1021
1029
  } catch (error) {
1022
1030
  console.error("[aria-ease] Error in onSelect callback:", error);
1023
1031
  }
@@ -1060,9 +1068,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
1060
1068
  } else if (comboboxInput.value) {
1061
1069
  event.preventDefault();
1062
1070
  comboboxInput.value = "";
1063
- if (config?.onClear) {
1071
+ if (callback?.onClear) {
1064
1072
  try {
1065
- config.onClear();
1073
+ callback.onClear();
1066
1074
  } catch (error) {
1067
1075
  console.error("[aria-ease] Error in onClear callback:", error);
1068
1076
  }
@@ -1278,7 +1286,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
1278
1286
  const devServerUrl = await checkDevServer(url);
1279
1287
  if (devServerUrl) {
1280
1288
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
1281
- const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-ZO6GM4TU.js");
1289
+ const { runContractTestsPlaywright } = await import("./contractTestRunnerPlaywright-EXEBWWPC.js");
1282
1290
  contract = await runContractTestsPlaywright(componentName, devServerUrl);
1283
1291
  } else {
1284
1292
  throw new Error(
@@ -22,19 +22,32 @@ interface AccessibilityInstance {
22
22
  getPressedIndices?: () => number[];
23
23
  }
24
24
 
25
+ interface AccordionConfig {
26
+ accordionId: string;
27
+ triggersClass: string;
28
+ panelsClass: string;
29
+ allowMultipleOpen?: boolean;
30
+ callback?: AccordionCallback;
31
+ }
32
+
33
+ interface AccordionCallback {
34
+ onExpand?: (index: number) => void;
35
+ onCollapse?: (index: number) => void;
36
+ }
37
+
25
38
  interface ComboboxConfig {
26
39
  comboboxInputId: string;
27
40
  comboboxButtonId?: string;
28
41
  listBoxId: string;
29
42
  listBoxItemsClass: string;
30
- config?: config;
43
+ callback?: ComboboxCallback;
31
44
  }
32
45
 
33
- interface config {
34
- onSelect?: (item: HTMLElement, value: string) => void;
46
+ interface ComboboxCallback {
47
+ onSelect?: (item: HTMLElement) => void;
35
48
  onOpenChange?: (isOpen: boolean) => void;
36
49
  onActiveDescendantChange?: (optionId: string, item: HTMLElement) => void;
37
50
  onClear?: () => void;
38
51
  }
39
52
 
40
- export type { AccessibilityInstance as A, ComboboxConfig as C };
53
+ export type { AccessibilityInstance as A, ComboboxConfig as C, AccordionConfig as a };
@@ -22,19 +22,32 @@ interface AccessibilityInstance {
22
22
  getPressedIndices?: () => number[];
23
23
  }
24
24
 
25
+ interface AccordionConfig {
26
+ accordionId: string;
27
+ triggersClass: string;
28
+ panelsClass: string;
29
+ allowMultipleOpen?: boolean;
30
+ callback?: AccordionCallback;
31
+ }
32
+
33
+ interface AccordionCallback {
34
+ onExpand?: (index: number) => void;
35
+ onCollapse?: (index: number) => void;
36
+ }
37
+
25
38
  interface ComboboxConfig {
26
39
  comboboxInputId: string;
27
40
  comboboxButtonId?: string;
28
41
  listBoxId: string;
29
42
  listBoxItemsClass: string;
30
- config?: config;
43
+ callback?: ComboboxCallback;
31
44
  }
32
45
 
33
- interface config {
34
- onSelect?: (item: HTMLElement, value: string) => void;
46
+ interface ComboboxCallback {
47
+ onSelect?: (item: HTMLElement) => void;
35
48
  onOpenChange?: (isOpen: boolean) => void;
36
49
  onActiveDescendantChange?: (optionId: string, item: HTMLElement) => void;
37
50
  onClear?: () => void;
38
51
  }
39
52
 
40
- export type { AccessibilityInstance as A, ComboboxConfig as C };
53
+ export type { AccessibilityInstance as A, ComboboxConfig as C, AccordionConfig as a };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
4
- function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false }) {
4
+ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false, callback }) {
5
5
  const accordionContainer = document.querySelector(`#${accordionId}`);
6
6
  if (!accordionContainer) {
7
7
  console.error(`[aria-ease] Element with id="${accordionId}" not found. Make sure the accordion container exists before calling makeAccordionAccessible.`);
@@ -52,6 +52,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
52
52
  const panel = panels[index];
53
53
  trigger.setAttribute("aria-expanded", "true");
54
54
  panel.style.display = "block";
55
+ if (callback?.onExpand) {
56
+ callback.onExpand(index);
57
+ }
55
58
  }
56
59
  function collapseItem(index) {
57
60
  if (index < 0 || index >= triggers.length) {
@@ -62,6 +65,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
62
65
  const panel = panels[index];
63
66
  trigger.setAttribute("aria-expanded", "false");
64
67
  panel.style.display = "none";
68
+ if (callback?.onCollapse) {
69
+ callback.onCollapse(index);
70
+ }
65
71
  }
66
72
  function toggleItem(index) {
67
73
  const trigger = triggers[index];
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { a as AccordionConfig, A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Makes an accordion accessible by managing ARIA attributes, keyboard navigation, and state.
@@ -7,14 +7,9 @@ import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
7
7
  * @param {string} triggersClass - The shared class of all accordion trigger buttons.
8
8
  * @param {string} panelsClass - The shared class of all accordion panels.
9
9
  * @param {boolean} allowMultipleOpen - Whether multiple panels can be open simultaneously (default: false).
10
+ * @param {AccordionCallback} callback - Configuration options for callbacks.
10
11
  */
11
12
 
12
- interface AccordionConfig {
13
- accordionId: string;
14
- triggersClass: string;
15
- panelsClass: string;
16
- allowMultipleOpen?: boolean;
17
- }
18
- declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen }: AccordionConfig): AccessibilityInstance;
13
+ declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen, callback }: AccordionConfig): AccessibilityInstance;
19
14
 
20
15
  export { makeAccordionAccessible };
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { a as AccordionConfig, A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Makes an accordion accessible by managing ARIA attributes, keyboard navigation, and state.
@@ -7,14 +7,9 @@ import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
7
7
  * @param {string} triggersClass - The shared class of all accordion trigger buttons.
8
8
  * @param {string} panelsClass - The shared class of all accordion panels.
9
9
  * @param {boolean} allowMultipleOpen - Whether multiple panels can be open simultaneously (default: false).
10
+ * @param {AccordionCallback} callback - Configuration options for callbacks.
10
11
  */
11
12
 
12
- interface AccordionConfig {
13
- accordionId: string;
14
- triggersClass: string;
15
- panelsClass: string;
16
- allowMultipleOpen?: boolean;
17
- }
18
- declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen }: AccordionConfig): AccessibilityInstance;
13
+ declare function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen, callback }: AccordionConfig): AccessibilityInstance;
19
14
 
20
15
  export { makeAccordionAccessible };
@@ -1,5 +1,5 @@
1
1
  // src/accordion/src/makeAccordionAccessible/makeAccordionAccessible.ts
2
- function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false }) {
2
+ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allowMultipleOpen = false, callback }) {
3
3
  const accordionContainer = document.querySelector(`#${accordionId}`);
4
4
  if (!accordionContainer) {
5
5
  console.error(`[aria-ease] Element with id="${accordionId}" not found. Make sure the accordion container exists before calling makeAccordionAccessible.`);
@@ -50,6 +50,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
50
50
  const panel = panels[index];
51
51
  trigger.setAttribute("aria-expanded", "true");
52
52
  panel.style.display = "block";
53
+ if (callback?.onExpand) {
54
+ callback.onExpand(index);
55
+ }
53
56
  }
54
57
  function collapseItem(index) {
55
58
  if (index < 0 || index >= triggers.length) {
@@ -60,6 +63,9 @@ function makeAccordionAccessible({ accordionId, triggersClass, panelsClass, allo
60
63
  const panel = panels[index];
61
64
  trigger.setAttribute("aria-expanded", "false");
62
65
  panel.style.display = "none";
66
+ if (callback?.onCollapse) {
67
+ callback.onCollapse(index);
68
+ }
63
69
  }
64
70
  function toggleItem(index) {
65
71
  const trigger = triggers[index];
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Adds keyboard interaction to block. The block traps focus and can be interacted with using the keyboard.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Makes a checkbox group accessible by managing ARIA attributes and keyboard navigation.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Makes a checkbox group accessible by managing ARIA attributes and keyboard navigation.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/combobox/src/makeComboBoxAccessible/makeComboBoxAccessible.ts
4
- function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }) {
4
+ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }) {
5
5
  const comboboxInput = document.getElementById(`${comboboxInputId}`);
6
6
  if (!comboboxInput) {
7
7
  console.error(`[aria-ease] Element with id="${comboboxInputId}" not found. Make sure the combobox input element exists before calling makeComboboxAccessible.`);
@@ -48,9 +48,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
48
48
  if (typeof activeItem.scrollIntoView === "function") {
49
49
  activeItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
50
50
  }
51
- if (config?.onActiveDescendantChange) {
51
+ if (callback?.onActiveDescendantChange) {
52
52
  try {
53
- config.onActiveDescendantChange(itemId, activeItem);
53
+ callback.onActiveDescendantChange(itemId, activeItem);
54
54
  } catch (error) {
55
55
  console.error("[aria-ease] Error in onActiveDescendantChange callback:", error);
56
56
  }
@@ -62,9 +62,10 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
62
62
  }
63
63
  function openListbox() {
64
64
  comboboxInput.setAttribute("aria-expanded", "true");
65
- if (config?.onOpenChange) {
65
+ listBox.style.display = "block";
66
+ if (callback?.onOpenChange) {
66
67
  try {
67
- config.onOpenChange(true);
68
+ callback.onOpenChange(true);
68
69
  } catch (error) {
69
70
  console.error("[aria-ease] Error in onOpenChange callback:", error);
70
71
  }
@@ -73,12 +74,13 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
73
74
  function closeListbox() {
74
75
  comboboxInput.setAttribute("aria-expanded", "false");
75
76
  comboboxInput.setAttribute("aria-activedescendant", "");
77
+ listBox.style.display = "none";
76
78
  activeIndex = -1;
77
79
  const visibleItems = getVisibleItems();
78
80
  visibleItems.forEach((item) => item.setAttribute("aria-selected", "false"));
79
- if (config?.onOpenChange) {
81
+ if (callback?.onOpenChange) {
80
82
  try {
81
- config.onOpenChange(false);
83
+ callback.onOpenChange(false);
82
84
  } catch (error) {
83
85
  console.error("[aria-ease] Error in onOpenChange callback:", error);
84
86
  }
@@ -88,9 +90,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
88
90
  const value = item.textContent?.trim() || "";
89
91
  comboboxInput.value = value;
90
92
  closeListbox();
91
- if (config?.onSelect) {
93
+ if (callback?.onSelect) {
92
94
  try {
93
- config.onSelect(item, value);
95
+ callback.onSelect(item);
94
96
  } catch (error) {
95
97
  console.error("[aria-ease] Error in onSelect callback:", error);
96
98
  }
@@ -133,9 +135,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
133
135
  } else if (comboboxInput.value) {
134
136
  event.preventDefault();
135
137
  comboboxInput.value = "";
136
- if (config?.onClear) {
138
+ if (callback?.onClear) {
137
139
  try {
138
- config.onClear();
140
+ callback.onClear();
139
141
  } catch (error) {
140
142
  console.error("[aria-ease] Error in onClear callback:", error);
141
143
  }
@@ -1,4 +1,4 @@
1
- import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
@@ -6,9 +6,9 @@ import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-COr5
6
6
  * @param {string} comboboxButtonId - The id of the button that toggles the listbox (optional).
7
7
  * @param {string} listBoxId - The id of the listbox element.
8
8
  * @param {string} listBoxItemsClass - The class of the items within the listbox.
9
- * @param {ComboboxConfig} config - Configuration options for callbacks.
9
+ * @param {ComboboxCallback} callback - Configuration options for callbacks.
10
10
  */
11
11
 
12
- declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }: ComboboxConfig): AccessibilityInstance;
12
+ declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }: ComboboxConfig): AccessibilityInstance;
13
13
 
14
14
  export { makeComboboxAccessible };
@@ -1,4 +1,4 @@
1
- import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Makes a Combobox accessible by adding appropriate ARIA attributes, keyboard interactions and focus management.
@@ -6,9 +6,9 @@ import { C as ComboboxConfig, A as AccessibilityInstance } from '../Types.d-COr5
6
6
  * @param {string} comboboxButtonId - The id of the button that toggles the listbox (optional).
7
7
  * @param {string} listBoxId - The id of the listbox element.
8
8
  * @param {string} listBoxItemsClass - The class of the items within the listbox.
9
- * @param {ComboboxConfig} config - Configuration options for callbacks.
9
+ * @param {ComboboxCallback} callback - Configuration options for callbacks.
10
10
  */
11
11
 
12
- declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }: ComboboxConfig): AccessibilityInstance;
12
+ declare function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }: ComboboxConfig): AccessibilityInstance;
13
13
 
14
14
  export { makeComboboxAccessible };
@@ -1,5 +1,5 @@
1
1
  // src/combobox/src/makeComboBoxAccessible/makeComboBoxAccessible.ts
2
- function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, config }) {
2
+ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId, listBoxItemsClass, callback }) {
3
3
  const comboboxInput = document.getElementById(`${comboboxInputId}`);
4
4
  if (!comboboxInput) {
5
5
  console.error(`[aria-ease] Element with id="${comboboxInputId}" not found. Make sure the combobox input element exists before calling makeComboboxAccessible.`);
@@ -46,9 +46,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
46
46
  if (typeof activeItem.scrollIntoView === "function") {
47
47
  activeItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
48
48
  }
49
- if (config?.onActiveDescendantChange) {
49
+ if (callback?.onActiveDescendantChange) {
50
50
  try {
51
- config.onActiveDescendantChange(itemId, activeItem);
51
+ callback.onActiveDescendantChange(itemId, activeItem);
52
52
  } catch (error) {
53
53
  console.error("[aria-ease] Error in onActiveDescendantChange callback:", error);
54
54
  }
@@ -60,9 +60,10 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
60
60
  }
61
61
  function openListbox() {
62
62
  comboboxInput.setAttribute("aria-expanded", "true");
63
- if (config?.onOpenChange) {
63
+ listBox.style.display = "block";
64
+ if (callback?.onOpenChange) {
64
65
  try {
65
- config.onOpenChange(true);
66
+ callback.onOpenChange(true);
66
67
  } catch (error) {
67
68
  console.error("[aria-ease] Error in onOpenChange callback:", error);
68
69
  }
@@ -71,12 +72,13 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
71
72
  function closeListbox() {
72
73
  comboboxInput.setAttribute("aria-expanded", "false");
73
74
  comboboxInput.setAttribute("aria-activedescendant", "");
75
+ listBox.style.display = "none";
74
76
  activeIndex = -1;
75
77
  const visibleItems = getVisibleItems();
76
78
  visibleItems.forEach((item) => item.setAttribute("aria-selected", "false"));
77
- if (config?.onOpenChange) {
79
+ if (callback?.onOpenChange) {
78
80
  try {
79
- config.onOpenChange(false);
81
+ callback.onOpenChange(false);
80
82
  } catch (error) {
81
83
  console.error("[aria-ease] Error in onOpenChange callback:", error);
82
84
  }
@@ -86,9 +88,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
86
88
  const value = item.textContent?.trim() || "";
87
89
  comboboxInput.value = value;
88
90
  closeListbox();
89
- if (config?.onSelect) {
91
+ if (callback?.onSelect) {
90
92
  try {
91
- config.onSelect(item, value);
93
+ callback.onSelect(item);
92
94
  } catch (error) {
93
95
  console.error("[aria-ease] Error in onSelect callback:", error);
94
96
  }
@@ -131,9 +133,9 @@ function makeComboboxAccessible({ comboboxInputId, comboboxButtonId, listBoxId,
131
133
  } else if (comboboxInput.value) {
132
134
  event.preventDefault();
133
135
  comboboxInput.value = "";
134
- if (config?.onClear) {
136
+ if (callback?.onClear) {
135
137
  try {
136
- config.onClear();
138
+ callback.onClear();
137
139
  } catch (error) {
138
140
  console.error("[aria-ease] Error in onClear callback:", error);
139
141
  }
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Adds keyboard interaction to toggle menu. The menu traps focus and can be interacted with using the keyboard. The first interactive item of the menu has focus when menu open.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Makes a radio group accessible by managing ARIA attributes, keyboard navigation, and state.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Makes a radio group accessible by managing ARIA attributes, keyboard navigation, and state.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.cjs';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.cjs';
2
2
 
3
3
  /**
4
4
  * Makes a toggle button accessible by managing ARIA attributes and keyboard interactions.
@@ -1,4 +1,4 @@
1
- import { A as AccessibilityInstance } from '../Types.d-COr5IFp5.js';
1
+ import { A as AccessibilityInstance } from '../Types.d-B-NDbH_q.js';
2
2
 
3
3
  /**
4
4
  * Makes a toggle button accessible by managing ARIA attributes and keyboard interactions.
@@ -19,7 +19,6 @@ async function runContractTestsPlaywright(componentName, url) {
19
19
  const passes = [];
20
20
  const skipped = [];
21
21
  let page = null;
22
- const useNavigation = !!url;
23
22
  try {
24
23
  page = await createTestPage();
25
24
  if (url) {
@@ -33,8 +32,7 @@ async function runContractTestsPlaywright(componentName, url) {
33
32
  if (!mainSelector) {
34
33
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
35
34
  }
36
- const elementTimeout = useNavigation ? 3e4 : 5e3;
37
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
35
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
38
36
  if (componentName === "menu" && componentContract.selectors.trigger) {
39
37
  await page.locator(componentContract.selectors.trigger).first().waitFor({
40
38
  state: "visible",
@@ -145,15 +143,13 @@ async function runContractTestsPlaywright(componentName, url) {
145
143
  menuClosed = await expect(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
146
144
  }
147
145
  if (!menuClosed) {
148
- if (useNavigation) {
149
- throw new Error(
150
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
146
+ throw new Error(
147
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
151
148
  1. Escape key
152
149
  2. Clicking trigger
153
150
  3. Clicking outside
154
151
  This indicates a problem with the menu component's close functionality.`
155
- );
156
- }
152
+ );
157
153
  }
158
154
  if (componentContract.selectors.input) {
159
155
  await page.locator(componentContract.selectors.input).first().clear();
@@ -164,6 +160,23 @@ This indicates a problem with the menu component's close functionality.`
164
160
  }
165
161
  }
166
162
  }
163
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
164
+ const triggerSelector = componentContract.selectors.trigger;
165
+ const panelSelector = componentContract.selectors.panel;
166
+ if (triggerSelector && panelSelector) {
167
+ const allTriggers = await page.locator(triggerSelector).all();
168
+ for (const trigger of allTriggers) {
169
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
170
+ const triggerPanel = await trigger.getAttribute("aria-controls");
171
+ if (isExpanded && triggerPanel) {
172
+ await trigger.click();
173
+ const panel = page.locator(`#${triggerPanel}`);
174
+ await expect(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
175
+ });
176
+ }
177
+ }
178
+ }
179
+ }
167
180
  let shouldSkipTest = false;
168
181
  for (const act of action) {
169
182
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
@@ -336,7 +336,6 @@ async function runContractTestsPlaywright(componentName, url) {
336
336
  const passes = [];
337
337
  const skipped = [];
338
338
  let page = null;
339
- const useNavigation = !!url;
340
339
  try {
341
340
  page = await createTestPage();
342
341
  if (url) {
@@ -350,8 +349,7 @@ async function runContractTestsPlaywright(componentName, url) {
350
349
  if (!mainSelector) {
351
350
  throw new Error(`No main selector (trigger, input, or container) found in contract for ${componentName}`);
352
351
  }
353
- const elementTimeout = useNavigation ? 3e4 : 5e3;
354
- await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: elementTimeout });
352
+ await page.locator(mainSelector).first().waitFor({ state: "attached", timeout: 3e4 });
355
353
  if (componentName === "menu" && componentContract.selectors.trigger) {
356
354
  await page.locator(componentContract.selectors.trigger).first().waitFor({
357
355
  state: "visible",
@@ -462,15 +460,13 @@ async function runContractTestsPlaywright(componentName, url) {
462
460
  menuClosed = await test.expect(popupElement).toBeHidden({ timeout: 2e3 }).then(() => true).catch(() => false);
463
461
  }
464
462
  if (!menuClosed) {
465
- if (useNavigation) {
466
- throw new Error(
467
- `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
463
+ throw new Error(
464
+ `\u274C FATAL: Cannot close menu between tests. Menu remains visible after trying:
468
465
  1. Escape key
469
466
  2. Clicking trigger
470
467
  3. Clicking outside
471
468
  This indicates a problem with the menu component's close functionality.`
472
- );
473
- }
469
+ );
474
470
  }
475
471
  if (componentContract.selectors.input) {
476
472
  await page.locator(componentContract.selectors.input).first().clear();
@@ -481,6 +477,23 @@ This indicates a problem with the menu component's close functionality.`
481
477
  }
482
478
  }
483
479
  }
480
+ if (componentContract.selectors.panel && componentContract.selectors.trigger && !componentContract.selectors.popup) {
481
+ const triggerSelector = componentContract.selectors.trigger;
482
+ const panelSelector = componentContract.selectors.panel;
483
+ if (triggerSelector && panelSelector) {
484
+ const allTriggers = await page.locator(triggerSelector).all();
485
+ for (const trigger of allTriggers) {
486
+ const isExpanded = await trigger.getAttribute("aria-expanded") === "true";
487
+ const triggerPanel = await trigger.getAttribute("aria-controls");
488
+ if (isExpanded && triggerPanel) {
489
+ await trigger.click();
490
+ const panel = page.locator(`#${triggerPanel}`);
491
+ await test.expect(panel).toBeHidden({ timeout: 1e3 }).catch(() => {
492
+ });
493
+ }
494
+ }
495
+ }
496
+ }
484
497
  let shouldSkipTest = false;
485
498
  for (const act of action) {
486
499
  if (act.type === "keypress" && (act.target === "submenuTrigger" || act.target === "submenu")) {
@@ -106,7 +106,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
106
106
  const devServerUrl = await checkDevServer(url);
107
107
  if (devServerUrl) {
108
108
  console.log(`\u{1F3AD} Running Playwright tests on ${devServerUrl}`);
109
- const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-CREJNINL.js');
109
+ const { runContractTestsPlaywright } = await import('./contractTestRunnerPlaywright-LJHY3AB4.js');
110
110
  contract = await runContractTestsPlaywright(componentName, devServerUrl);
111
111
  } else {
112
112
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aria-ease",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "Out-of-the-box accessibility utility package to develop production ready applications.",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "module",