@y14e/accordion 2.1.1 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,11 +13,11 @@ npm i @y14e/accordion
13
13
  import { Accordion } from '@y14e/accordion';
14
14
 
15
15
  // CDNs
16
- import { Accordion } from 'https://esm.sh/@y14e/accordion@2.1.1';
16
+ import { Accordion } from 'https://esm.sh/@y14e/accordion@2.1.3';
17
17
  // or
18
- import { Accordion } from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.1.1/+esm';
18
+ import { Accordion } from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.1.3/+esm';
19
19
  // or
20
- import { Accordion } from 'https://esm.unpkg.com/@y14e/accordion@2.1.1';
20
+ import { Accordion } from 'https://esm.unpkg.com/@y14e/accordion@2.1.3';
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -207,31 +207,25 @@ function normalizeRadioGroup(elements) {
207
207
  map = /* @__PURE__ */ new Map();
208
208
  }
209
209
  const root = element.getRootNode();
210
- let groups = map.get(root);
210
+ const groups = map.get(root) ?? map.set(root, /* @__PURE__ */ new Map()).get(root);
211
211
  if (!groups) {
212
- groups = /* @__PURE__ */ new Map();
213
- map.set(root, groups);
214
- }
215
- let group = groups.get(element.form);
216
- if (!group) {
217
- group = /* @__PURE__ */ new Map();
218
- groups.set(element.form, group);
212
+ continue;
219
213
  }
220
- let radios = group.get(element.name);
214
+ const { form, name } = element;
215
+ const radios = groups.get(form) ?? groups.set(form, /* @__PURE__ */ new Map()).get(form);
221
216
  if (!radios) {
222
- radios = [];
223
- group.set(element.name, radios);
217
+ continue;
224
218
  }
225
- radios.push(element);
219
+ (radios.get(name) ?? radios.set(name, []).get(name))?.push(element);
226
220
  }
227
221
  if (!map) {
228
222
  return elements;
229
223
  }
230
224
  const placeholder = /* @__PURE__ */ new Set();
231
- for (const groups of map.values()) {
232
- for (const group of groups.values()) {
233
- for (const radios of group.values()) {
234
- const radio = radios.find((r) => r.checked) ?? radios[0];
225
+ for (const v of map.values()) {
226
+ for (const w of v.values()) {
227
+ for (const x of w.values()) {
228
+ const radio = x.find((r) => r.checked) ?? x[0];
235
229
  radio && placeholder.add(radio);
236
230
  }
237
231
  }
@@ -407,8 +401,8 @@ function createRovingTabIndex(container, options = {}) {
407
401
  return () => {
408
402
  };
409
403
  }
410
- const roving = new RovingTabIndex(container, options);
411
- return () => roving.destroy();
404
+ const rovingTabIndex = new RovingTabIndex(container, options);
405
+ return () => rovingTabIndex.destroy();
412
406
  }
413
407
  var RovingTabIndex = class _RovingTabIndex {
414
408
  static #initialized = /* @__PURE__ */ new Set();
@@ -467,18 +461,19 @@ var RovingTabIndex = class _RovingTabIndex {
467
461
  if (!(event instanceof KeyboardEvent)) {
468
462
  return;
469
463
  }
464
+ const { direction, typeahead, wrap = false } = this.#settings;
465
+ const isGrid = direction === "grid";
470
466
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
471
- if (altKey || ctrlKey || metaKey || shiftKey) {
467
+ if (!(isGrid && ["End", "Home"].includes(key)) && ctrlKey || altKey || metaKey || shiftKey) {
472
468
  return;
473
469
  }
474
- const { direction, typeahead, wrap } = this.#settings;
475
470
  const isBoth = direction === "both";
476
471
  const isHorizontal = direction === "horizontal";
477
472
  if (![
478
473
  "End",
479
474
  "Home",
480
- ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
481
- ...isBoth ? ["ArrowRight", "ArrowDown"] : [`Arrow${isHorizontal ? "Right" : "Down"}`]
475
+ ...isGrid || isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
476
+ ...isGrid || isBoth ? ["ArrowRight", "ArrowDown"] : [`Arrow${isHorizontal ? "Right" : "Down"}`]
482
477
  ].includes(key)) {
483
478
  if (!typeahead || !/^\S$/i.test(key) || !this.#focusablesByFirstChar.has(key.toUpperCase())) {
484
479
  return;
@@ -497,39 +492,48 @@ var RovingTabIndex = class _RovingTabIndex {
497
492
  event.preventDefault();
498
493
  let newIndex;
499
494
  const activeIndex = candidates.indexOf(active);
500
- let focusables = candidates;
495
+ let target = candidates;
501
496
  switch (key) {
502
497
  case "End":
503
- newIndex = -1;
504
- break;
505
- case "Home":
506
- newIndex = 0;
507
- break;
508
- case "ArrowLeft":
509
- case "ArrowUp": {
510
- const rawIndex = activeIndex - 1;
511
- newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
498
+ case "Home": {
499
+ const rawIndex = key === "End" ? -1 : 0;
500
+ if (isGrid && !ctrlKey) {
501
+ const cell = this.#getCellsOfActiveRow().at(rawIndex);
502
+ newIndex = cell ? candidates.indexOf(cell) : activeIndex;
503
+ } else {
504
+ newIndex = rawIndex;
505
+ }
512
506
  break;
513
507
  }
508
+ case "ArrowLeft":
509
+ case "ArrowUp":
514
510
  case "ArrowRight":
515
511
  case "ArrowDown": {
516
- const rawIndex = activeIndex + 1;
517
- const length = focusables.length;
518
- newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
512
+ if (["ArrowUp", "ArrowDown"].includes(key) && isGrid) {
513
+ const cell = this.#getNextCell(key, wrap);
514
+ newIndex = cell ? candidates.indexOf(cell) : activeIndex;
515
+ } else {
516
+ if (isGrid) {
517
+ target = this.#getCellsOfActiveRow();
518
+ }
519
+ const isPrevious = ["ArrowLeft", "ArrowUp"].includes(key);
520
+ const rawIndex = (isGrid ? target.indexOf(active) : activeIndex) + (isPrevious ? -1 : 1);
521
+ newIndex = isPrevious ? wrap ? rawIndex : Math.max(rawIndex, 0) : wrap ? rawIndex % target.length : Math.min(rawIndex, target.length - 1);
522
+ }
519
523
  break;
520
524
  }
521
525
  default: {
522
526
  const focusablesByFirstChar = new Set(
523
527
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
524
528
  );
525
- focusables = candidates.filter((c) => focusablesByFirstChar.has(c));
526
- const afterIndex = focusables.findIndex(
529
+ target = candidates.filter((c) => focusablesByFirstChar.has(c));
530
+ const afterIndex = target.findIndex(
527
531
  (f) => candidates.indexOf(f) > activeIndex
528
532
  );
529
533
  newIndex = afterIndex >= 0 ? afterIndex : 0;
530
534
  }
531
535
  }
532
- const focusable = focusables.at(newIndex);
536
+ const focusable = target.at(newIndex);
533
537
  focusable && focusElement(focusable);
534
538
  };
535
539
  #update(active) {
@@ -599,6 +603,24 @@ var RovingTabIndex = class _RovingTabIndex {
599
603
  const { selector } = this.#settings;
600
604
  return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
601
605
  }
606
+ #getCellCoords(cell) {
607
+ const { height, left, top, width } = cell.getBoundingClientRect();
608
+ return {
609
+ x: left + width / 2,
610
+ y: top + height / 2
611
+ };
612
+ }
613
+ #getCellsOfActiveRow() {
614
+ const active = getActiveElement();
615
+ if (!(active instanceof Element)) {
616
+ return [];
617
+ }
618
+ const activeRect = active.getBoundingClientRect();
619
+ return this.#getFocusables().filter((cell) => {
620
+ const cellRect = cell.getBoundingClientRect();
621
+ return cellRect.top < activeRect.bottom && cellRect.bottom > activeRect.top;
622
+ });
623
+ }
602
624
  #getFocusables() {
603
625
  return getFocusables(this.#container, {
604
626
  composed: true,
@@ -607,6 +629,50 @@ var RovingTabIndex = class _RovingTabIndex {
607
629
  skipVisibilityCheck: true
608
630
  });
609
631
  }
632
+ #getNextCell(key, wrap) {
633
+ const cells = this.#getFocusables();
634
+ const active = getActiveElement();
635
+ if (!(active instanceof Element)) {
636
+ return null;
637
+ }
638
+ const activeCoords = this.#getCellCoords(active);
639
+ let min = Infinity;
640
+ let result = null;
641
+ for (const cell of cells) {
642
+ if (cell === active) {
643
+ continue;
644
+ }
645
+ const cellCoords = this.#getCellCoords(cell);
646
+ const distances = {
647
+ x: Math.abs(cellCoords.x - activeCoords.x),
648
+ y: Math.abs(cellCoords.y - activeCoords.y)
649
+ };
650
+ if (key === "ArrowUp" && cellCoords.y < activeCoords.y && distances.x < distances.y || key === "ArrowDown" && cellCoords.y > activeCoords.y && distances.x < distances.y) {
651
+ const distance = distances.x ** 2 + distances.y ** 2;
652
+ if (distance < min) {
653
+ min = distance;
654
+ result = cell;
655
+ }
656
+ }
657
+ }
658
+ if (!result && wrap) {
659
+ let max = -Infinity;
660
+ for (const cell of cells) {
661
+ if (cell === active) {
662
+ continue;
663
+ }
664
+ const cellCoords = this.#getCellCoords(cell);
665
+ if (Math.abs(cellCoords.x - activeCoords.x) < cell.getBoundingClientRect().width / 2) {
666
+ const distance = key === "ArrowUp" ? cellCoords.y - activeCoords.y : activeCoords.y - cellCoords.y;
667
+ if (distance > max) {
668
+ max = distance;
669
+ result = cell;
670
+ }
671
+ }
672
+ }
673
+ }
674
+ return result;
675
+ }
610
676
  #resolveOptions(options) {
611
677
  let {
612
678
  direction = "both",
@@ -618,7 +684,7 @@ var RovingTabIndex = class _RovingTabIndex {
618
684
  wrap = false
619
685
  } = options;
620
686
  direction = direction.toLowerCase();
621
- if (!["both", "horizontal", "vertical"].includes(direction)) {
687
+ if (!["both", "grid", "horizontal", "vertical"].includes(direction)) {
622
688
  console.warn("Invalid direction option. Fallback: 'both'.");
623
689
  direction = "both";
624
690
  }
@@ -943,21 +1009,24 @@ var Accordion = class _Accordion {
943
1009
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
944
1010
  merged.collapsible = collapsible;
945
1011
  }
946
- const mergedSelector = merged.selector;
947
- const defaultSelector = defaults.selector;
948
- try {
949
- document.querySelector(mergedSelector.content);
950
- } catch {
951
- const content = defaultSelector.content;
952
- console.warn(`Invalid content selector. Fallback: '${content}'.`);
953
- mergedSelector.content = content;
954
- }
955
- try {
956
- document.querySelector(mergedSelector.trigger);
957
- } catch {
958
- const trigger = defaultSelector.trigger;
959
- console.warn(`Invalid trigger selector. Fallback: '${trigger}'.`);
960
- mergedSelector.trigger = trigger;
1012
+ const selector = merged.selector;
1013
+ function resolveSelector(name, target2, source2) {
1014
+ try {
1015
+ document.querySelector(source2);
1016
+ return source2;
1017
+ } catch {
1018
+ console.warn(
1019
+ `Invalid ${name.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${target2}'.`
1020
+ );
1021
+ return target2;
1022
+ }
1023
+ }
1024
+ for (const name of ["content", "trigger"]) {
1025
+ selector[name] = resolveSelector(
1026
+ name,
1027
+ defaults.selector[name],
1028
+ selector[name]
1029
+ );
961
1030
  }
962
1031
  return merged;
963
1032
  }
@@ -979,7 +1048,7 @@ function waitAnimationFinish(animation) {
979
1048
  * Accordion
980
1049
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
981
1050
  *
982
- * @version 2.1.0
1051
+ * @version 2.1.3
983
1052
  * @author Yusuke Kamiyamane
984
1053
  * @license MIT
985
1054
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1004,7 +1073,7 @@ power-focusable/dist/index.js:
1004
1073
  * High-precision focus management utility with full composed tree support.
1005
1074
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1006
1075
  *
1007
- * @version 4.3.33
1076
+ * @version 4.4.2
1008
1077
  * @author Yusuke Kamiyamane
1009
1078
  * @license MIT
1010
1079
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1028,7 +1097,7 @@ power-focusable/dist/index.js:
1028
1097
  * Lightweight roving tabindex utility with fully focus management.
1029
1098
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1030
1099
  *
1031
- * @version 3.1.31
1100
+ * @version 3.3.1
1032
1101
  * @author Yusuke Kamiyamane
1033
1102
  * @license MIT
1034
1103
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -205,31 +205,25 @@ function normalizeRadioGroup(elements) {
205
205
  map = /* @__PURE__ */ new Map();
206
206
  }
207
207
  const root = element.getRootNode();
208
- let groups = map.get(root);
208
+ const groups = map.get(root) ?? map.set(root, /* @__PURE__ */ new Map()).get(root);
209
209
  if (!groups) {
210
- groups = /* @__PURE__ */ new Map();
211
- map.set(root, groups);
212
- }
213
- let group = groups.get(element.form);
214
- if (!group) {
215
- group = /* @__PURE__ */ new Map();
216
- groups.set(element.form, group);
210
+ continue;
217
211
  }
218
- let radios = group.get(element.name);
212
+ const { form, name } = element;
213
+ const radios = groups.get(form) ?? groups.set(form, /* @__PURE__ */ new Map()).get(form);
219
214
  if (!radios) {
220
- radios = [];
221
- group.set(element.name, radios);
215
+ continue;
222
216
  }
223
- radios.push(element);
217
+ (radios.get(name) ?? radios.set(name, []).get(name))?.push(element);
224
218
  }
225
219
  if (!map) {
226
220
  return elements;
227
221
  }
228
222
  const placeholder = /* @__PURE__ */ new Set();
229
- for (const groups of map.values()) {
230
- for (const group of groups.values()) {
231
- for (const radios of group.values()) {
232
- const radio = radios.find((r) => r.checked) ?? radios[0];
223
+ for (const v of map.values()) {
224
+ for (const w of v.values()) {
225
+ for (const x of w.values()) {
226
+ const radio = x.find((r) => r.checked) ?? x[0];
233
227
  radio && placeholder.add(radio);
234
228
  }
235
229
  }
@@ -405,8 +399,8 @@ function createRovingTabIndex(container, options = {}) {
405
399
  return () => {
406
400
  };
407
401
  }
408
- const roving = new RovingTabIndex(container, options);
409
- return () => roving.destroy();
402
+ const rovingTabIndex = new RovingTabIndex(container, options);
403
+ return () => rovingTabIndex.destroy();
410
404
  }
411
405
  var RovingTabIndex = class _RovingTabIndex {
412
406
  static #initialized = /* @__PURE__ */ new Set();
@@ -465,18 +459,19 @@ var RovingTabIndex = class _RovingTabIndex {
465
459
  if (!(event instanceof KeyboardEvent)) {
466
460
  return;
467
461
  }
462
+ const { direction, typeahead, wrap = false } = this.#settings;
463
+ const isGrid = direction === "grid";
468
464
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
469
- if (altKey || ctrlKey || metaKey || shiftKey) {
465
+ if (!(isGrid && ["End", "Home"].includes(key)) && ctrlKey || altKey || metaKey || shiftKey) {
470
466
  return;
471
467
  }
472
- const { direction, typeahead, wrap } = this.#settings;
473
468
  const isBoth = direction === "both";
474
469
  const isHorizontal = direction === "horizontal";
475
470
  if (![
476
471
  "End",
477
472
  "Home",
478
- ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
479
- ...isBoth ? ["ArrowRight", "ArrowDown"] : [`Arrow${isHorizontal ? "Right" : "Down"}`]
473
+ ...isGrid || isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
474
+ ...isGrid || isBoth ? ["ArrowRight", "ArrowDown"] : [`Arrow${isHorizontal ? "Right" : "Down"}`]
480
475
  ].includes(key)) {
481
476
  if (!typeahead || !/^\S$/i.test(key) || !this.#focusablesByFirstChar.has(key.toUpperCase())) {
482
477
  return;
@@ -495,39 +490,48 @@ var RovingTabIndex = class _RovingTabIndex {
495
490
  event.preventDefault();
496
491
  let newIndex;
497
492
  const activeIndex = candidates.indexOf(active);
498
- let focusables = candidates;
493
+ let target = candidates;
499
494
  switch (key) {
500
495
  case "End":
501
- newIndex = -1;
502
- break;
503
- case "Home":
504
- newIndex = 0;
505
- break;
506
- case "ArrowLeft":
507
- case "ArrowUp": {
508
- const rawIndex = activeIndex - 1;
509
- newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
496
+ case "Home": {
497
+ const rawIndex = key === "End" ? -1 : 0;
498
+ if (isGrid && !ctrlKey) {
499
+ const cell = this.#getCellsOfActiveRow().at(rawIndex);
500
+ newIndex = cell ? candidates.indexOf(cell) : activeIndex;
501
+ } else {
502
+ newIndex = rawIndex;
503
+ }
510
504
  break;
511
505
  }
506
+ case "ArrowLeft":
507
+ case "ArrowUp":
512
508
  case "ArrowRight":
513
509
  case "ArrowDown": {
514
- const rawIndex = activeIndex + 1;
515
- const length = focusables.length;
516
- newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
510
+ if (["ArrowUp", "ArrowDown"].includes(key) && isGrid) {
511
+ const cell = this.#getNextCell(key, wrap);
512
+ newIndex = cell ? candidates.indexOf(cell) : activeIndex;
513
+ } else {
514
+ if (isGrid) {
515
+ target = this.#getCellsOfActiveRow();
516
+ }
517
+ const isPrevious = ["ArrowLeft", "ArrowUp"].includes(key);
518
+ const rawIndex = (isGrid ? target.indexOf(active) : activeIndex) + (isPrevious ? -1 : 1);
519
+ newIndex = isPrevious ? wrap ? rawIndex : Math.max(rawIndex, 0) : wrap ? rawIndex % target.length : Math.min(rawIndex, target.length - 1);
520
+ }
517
521
  break;
518
522
  }
519
523
  default: {
520
524
  const focusablesByFirstChar = new Set(
521
525
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
522
526
  );
523
- focusables = candidates.filter((c) => focusablesByFirstChar.has(c));
524
- const afterIndex = focusables.findIndex(
527
+ target = candidates.filter((c) => focusablesByFirstChar.has(c));
528
+ const afterIndex = target.findIndex(
525
529
  (f) => candidates.indexOf(f) > activeIndex
526
530
  );
527
531
  newIndex = afterIndex >= 0 ? afterIndex : 0;
528
532
  }
529
533
  }
530
- const focusable = focusables.at(newIndex);
534
+ const focusable = target.at(newIndex);
531
535
  focusable && focusElement(focusable);
532
536
  };
533
537
  #update(active) {
@@ -597,6 +601,24 @@ var RovingTabIndex = class _RovingTabIndex {
597
601
  const { selector } = this.#settings;
598
602
  return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
599
603
  }
604
+ #getCellCoords(cell) {
605
+ const { height, left, top, width } = cell.getBoundingClientRect();
606
+ return {
607
+ x: left + width / 2,
608
+ y: top + height / 2
609
+ };
610
+ }
611
+ #getCellsOfActiveRow() {
612
+ const active = getActiveElement();
613
+ if (!(active instanceof Element)) {
614
+ return [];
615
+ }
616
+ const activeRect = active.getBoundingClientRect();
617
+ return this.#getFocusables().filter((cell) => {
618
+ const cellRect = cell.getBoundingClientRect();
619
+ return cellRect.top < activeRect.bottom && cellRect.bottom > activeRect.top;
620
+ });
621
+ }
600
622
  #getFocusables() {
601
623
  return getFocusables(this.#container, {
602
624
  composed: true,
@@ -605,6 +627,50 @@ var RovingTabIndex = class _RovingTabIndex {
605
627
  skipVisibilityCheck: true
606
628
  });
607
629
  }
630
+ #getNextCell(key, wrap) {
631
+ const cells = this.#getFocusables();
632
+ const active = getActiveElement();
633
+ if (!(active instanceof Element)) {
634
+ return null;
635
+ }
636
+ const activeCoords = this.#getCellCoords(active);
637
+ let min = Infinity;
638
+ let result = null;
639
+ for (const cell of cells) {
640
+ if (cell === active) {
641
+ continue;
642
+ }
643
+ const cellCoords = this.#getCellCoords(cell);
644
+ const distances = {
645
+ x: Math.abs(cellCoords.x - activeCoords.x),
646
+ y: Math.abs(cellCoords.y - activeCoords.y)
647
+ };
648
+ if (key === "ArrowUp" && cellCoords.y < activeCoords.y && distances.x < distances.y || key === "ArrowDown" && cellCoords.y > activeCoords.y && distances.x < distances.y) {
649
+ const distance = distances.x ** 2 + distances.y ** 2;
650
+ if (distance < min) {
651
+ min = distance;
652
+ result = cell;
653
+ }
654
+ }
655
+ }
656
+ if (!result && wrap) {
657
+ let max = -Infinity;
658
+ for (const cell of cells) {
659
+ if (cell === active) {
660
+ continue;
661
+ }
662
+ const cellCoords = this.#getCellCoords(cell);
663
+ if (Math.abs(cellCoords.x - activeCoords.x) < cell.getBoundingClientRect().width / 2) {
664
+ const distance = key === "ArrowUp" ? cellCoords.y - activeCoords.y : activeCoords.y - cellCoords.y;
665
+ if (distance > max) {
666
+ max = distance;
667
+ result = cell;
668
+ }
669
+ }
670
+ }
671
+ }
672
+ return result;
673
+ }
608
674
  #resolveOptions(options) {
609
675
  let {
610
676
  direction = "both",
@@ -616,7 +682,7 @@ var RovingTabIndex = class _RovingTabIndex {
616
682
  wrap = false
617
683
  } = options;
618
684
  direction = direction.toLowerCase();
619
- if (!["both", "horizontal", "vertical"].includes(direction)) {
685
+ if (!["both", "grid", "horizontal", "vertical"].includes(direction)) {
620
686
  console.warn("Invalid direction option. Fallback: 'both'.");
621
687
  direction = "both";
622
688
  }
@@ -941,21 +1007,24 @@ var Accordion = class _Accordion {
941
1007
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
942
1008
  merged.collapsible = collapsible;
943
1009
  }
944
- const mergedSelector = merged.selector;
945
- const defaultSelector = defaults.selector;
946
- try {
947
- document.querySelector(mergedSelector.content);
948
- } catch {
949
- const content = defaultSelector.content;
950
- console.warn(`Invalid content selector. Fallback: '${content}'.`);
951
- mergedSelector.content = content;
952
- }
953
- try {
954
- document.querySelector(mergedSelector.trigger);
955
- } catch {
956
- const trigger = defaultSelector.trigger;
957
- console.warn(`Invalid trigger selector. Fallback: '${trigger}'.`);
958
- mergedSelector.trigger = trigger;
1010
+ const selector = merged.selector;
1011
+ function resolveSelector(name, target2, source2) {
1012
+ try {
1013
+ document.querySelector(source2);
1014
+ return source2;
1015
+ } catch {
1016
+ console.warn(
1017
+ `Invalid ${name.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${target2}'.`
1018
+ );
1019
+ return target2;
1020
+ }
1021
+ }
1022
+ for (const name of ["content", "trigger"]) {
1023
+ selector[name] = resolveSelector(
1024
+ name,
1025
+ defaults.selector[name],
1026
+ selector[name]
1027
+ );
959
1028
  }
960
1029
  return merged;
961
1030
  }
@@ -977,7 +1046,7 @@ function waitAnimationFinish(animation) {
977
1046
  * Accordion
978
1047
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
979
1048
  *
980
- * @version 2.1.0
1049
+ * @version 2.1.3
981
1050
  * @author Yusuke Kamiyamane
982
1051
  * @license MIT
983
1052
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1002,7 +1071,7 @@ power-focusable/dist/index.js:
1002
1071
  * High-precision focus management utility with full composed tree support.
1003
1072
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1004
1073
  *
1005
- * @version 4.3.33
1074
+ * @version 4.4.2
1006
1075
  * @author Yusuke Kamiyamane
1007
1076
  * @license MIT
1008
1077
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1026,7 +1095,7 @@ power-focusable/dist/index.js:
1026
1095
  * Lightweight roving tabindex utility with fully focus management.
1027
1096
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1028
1097
  *
1029
- * @version 3.1.31
1098
+ * @version 3.3.1
1030
1099
  * @author Yusuke Kamiyamane
1031
1100
  * @license MIT
1032
1101
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -285,21 +285,24 @@ var Accordion = class _Accordion {
285
285
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
286
286
  merged.collapsible = collapsible;
287
287
  }
288
- const mergedSelector = merged.selector;
289
- const defaultSelector = defaults.selector;
290
- try {
291
- document.querySelector(mergedSelector.content);
292
- } catch {
293
- const content = defaultSelector.content;
294
- console.warn(`Invalid content selector. Fallback: '${content}'.`);
295
- mergedSelector.content = content;
288
+ const selector = merged.selector;
289
+ function resolveSelector(name, target2, source2) {
290
+ try {
291
+ document.querySelector(source2);
292
+ return source2;
293
+ } catch {
294
+ console.warn(
295
+ `Invalid ${name.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${target2}'.`
296
+ );
297
+ return target2;
298
+ }
296
299
  }
297
- try {
298
- document.querySelector(mergedSelector.trigger);
299
- } catch {
300
- const trigger = defaultSelector.trigger;
301
- console.warn(`Invalid trigger selector. Fallback: '${trigger}'.`);
302
- mergedSelector.trigger = trigger;
300
+ for (const name of ["content", "trigger"]) {
301
+ selector[name] = resolveSelector(
302
+ name,
303
+ defaults.selector[name],
304
+ selector[name]
305
+ );
303
306
  }
304
307
  return merged;
305
308
  }
@@ -321,7 +324,7 @@ function waitAnimationFinish(animation) {
321
324
  * Accordion
322
325
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
323
326
  *
324
- * @version 2.1.0
327
+ * @version 2.1.3
325
328
  * @author Yusuke Kamiyamane
326
329
  * @license MIT
327
330
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.1.0
5
+ * @version 2.1.3
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.1.0
5
+ * @version 2.1.3
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -283,21 +283,24 @@ var Accordion = class _Accordion {
283
283
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
284
284
  merged.collapsible = collapsible;
285
285
  }
286
- const mergedSelector = merged.selector;
287
- const defaultSelector = defaults.selector;
288
- try {
289
- document.querySelector(mergedSelector.content);
290
- } catch {
291
- const content = defaultSelector.content;
292
- console.warn(`Invalid content selector. Fallback: '${content}'.`);
293
- mergedSelector.content = content;
286
+ const selector = merged.selector;
287
+ function resolveSelector(name, target2, source2) {
288
+ try {
289
+ document.querySelector(source2);
290
+ return source2;
291
+ } catch {
292
+ console.warn(
293
+ `Invalid ${name.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${target2}'.`
294
+ );
295
+ return target2;
296
+ }
294
297
  }
295
- try {
296
- document.querySelector(mergedSelector.trigger);
297
- } catch {
298
- const trigger = defaultSelector.trigger;
299
- console.warn(`Invalid trigger selector. Fallback: '${trigger}'.`);
300
- mergedSelector.trigger = trigger;
298
+ for (const name of ["content", "trigger"]) {
299
+ selector[name] = resolveSelector(
300
+ name,
301
+ defaults.selector[name],
302
+ selector[name]
303
+ );
301
304
  }
302
305
  return merged;
303
306
  }
@@ -319,7 +322,7 @@ function waitAnimationFinish(animation) {
319
322
  * Accordion
320
323
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
321
324
  *
322
- * @version 2.1.0
325
+ * @version 2.1.3
323
326
  * @author Yusuke Kamiyamane
324
327
  * @license MIT
325
328
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/accordion",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "WAI-ARIA compliant accordion pattern implementation in TypeScript",
5
5
  "keywords": [
6
6
  "a11y",
@@ -56,6 +56,6 @@
56
56
  "dependencies": {
57
57
  "@y14e/attribute-utils": "^2.0.12",
58
58
  "@y14e/button": "^1.0.8",
59
- "@y14e/roving-tabindex": "^3.1.31"
59
+ "@y14e/roving-tabindex": "^3.3.1"
60
60
  }
61
61
  }