@y14e/accordion 2.1.2 → 2.1.4
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 +3 -3
- package/dist/index.bundle.cjs +120 -55
- package/dist/index.bundle.js +120 -55
- package/dist/index.cjs +13 -14
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -14
- package/package.json +2 -2
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.
|
|
16
|
+
import { Accordion } from 'https://esm.sh/@y14e/accordion@2.1.4';
|
|
17
17
|
// or
|
|
18
|
-
import { Accordion } from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.1.
|
|
18
|
+
import { Accordion } from 'https://cdn.jsdelivr.net/npm/@y14e/accordion@2.1.4/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import { Accordion } from 'https://esm.unpkg.com/@y14e/accordion@2.1.
|
|
20
|
+
import { Accordion } from 'https://esm.unpkg.com/@y14e/accordion@2.1.4';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -207,31 +207,25 @@ function normalizeRadioGroup(elements) {
|
|
|
207
207
|
map = /* @__PURE__ */ new Map();
|
|
208
208
|
}
|
|
209
209
|
const root = element.getRootNode();
|
|
210
|
-
|
|
210
|
+
const groups = map.get(root) ?? map.set(root, /* @__PURE__ */ new Map()).get(root);
|
|
211
211
|
if (!groups) {
|
|
212
|
-
|
|
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
|
-
|
|
214
|
+
const { form, name } = element;
|
|
215
|
+
const radios = groups.get(form) ?? groups.set(form, /* @__PURE__ */ new Map()).get(form);
|
|
221
216
|
if (!radios) {
|
|
222
|
-
|
|
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
|
|
232
|
-
for (const
|
|
233
|
-
for (const
|
|
234
|
-
const radio =
|
|
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
|
|
411
|
-
return () =>
|
|
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 (
|
|
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
|
|
495
|
+
let target = candidates;
|
|
501
496
|
switch (key) {
|
|
502
497
|
case "End":
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
526
|
-
const afterIndex =
|
|
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 =
|
|
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
|
}
|
|
@@ -945,19 +1011,18 @@ var Accordion = class _Accordion {
|
|
|
945
1011
|
}
|
|
946
1012
|
const mergedSelector = merged.selector;
|
|
947
1013
|
const defaultSelector = defaults.selector;
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
mergedSelector.trigger = trigger;
|
|
1014
|
+
for (const key of Object.keys(
|
|
1015
|
+
defaultSelector
|
|
1016
|
+
)) {
|
|
1017
|
+
try {
|
|
1018
|
+
document.querySelector(mergedSelector[key]);
|
|
1019
|
+
} catch {
|
|
1020
|
+
const selector = defaultSelector[key];
|
|
1021
|
+
console.warn(
|
|
1022
|
+
`Invalid ${key.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${selector}'.`
|
|
1023
|
+
);
|
|
1024
|
+
mergedSelector[key] = selector;
|
|
1025
|
+
}
|
|
961
1026
|
}
|
|
962
1027
|
return merged;
|
|
963
1028
|
}
|
|
@@ -979,7 +1044,7 @@ function waitAnimationFinish(animation) {
|
|
|
979
1044
|
* Accordion
|
|
980
1045
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
981
1046
|
*
|
|
982
|
-
* @version 2.1.
|
|
1047
|
+
* @version 2.1.3
|
|
983
1048
|
* @author Yusuke Kamiyamane
|
|
984
1049
|
* @license MIT
|
|
985
1050
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1004,7 +1069,7 @@ power-focusable/dist/index.js:
|
|
|
1004
1069
|
* High-precision focus management utility with full composed tree support.
|
|
1005
1070
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1006
1071
|
*
|
|
1007
|
-
* @version 4.
|
|
1072
|
+
* @version 4.4.2
|
|
1008
1073
|
* @author Yusuke Kamiyamane
|
|
1009
1074
|
* @license MIT
|
|
1010
1075
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1028,7 +1093,7 @@ power-focusable/dist/index.js:
|
|
|
1028
1093
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1029
1094
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1030
1095
|
*
|
|
1031
|
-
* @version 3.1
|
|
1096
|
+
* @version 3.3.1
|
|
1032
1097
|
* @author Yusuke Kamiyamane
|
|
1033
1098
|
* @license MIT
|
|
1034
1099
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -205,31 +205,25 @@ function normalizeRadioGroup(elements) {
|
|
|
205
205
|
map = /* @__PURE__ */ new Map();
|
|
206
206
|
}
|
|
207
207
|
const root = element.getRootNode();
|
|
208
|
-
|
|
208
|
+
const groups = map.get(root) ?? map.set(root, /* @__PURE__ */ new Map()).get(root);
|
|
209
209
|
if (!groups) {
|
|
210
|
-
|
|
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
|
-
|
|
212
|
+
const { form, name } = element;
|
|
213
|
+
const radios = groups.get(form) ?? groups.set(form, /* @__PURE__ */ new Map()).get(form);
|
|
219
214
|
if (!radios) {
|
|
220
|
-
|
|
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
|
|
230
|
-
for (const
|
|
231
|
-
for (const
|
|
232
|
-
const radio =
|
|
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
|
|
409
|
-
return () =>
|
|
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 (
|
|
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
|
|
493
|
+
let target = candidates;
|
|
499
494
|
switch (key) {
|
|
500
495
|
case "End":
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|
-
|
|
524
|
-
const afterIndex =
|
|
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 =
|
|
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
|
}
|
|
@@ -943,19 +1009,18 @@ var Accordion = class _Accordion {
|
|
|
943
1009
|
}
|
|
944
1010
|
const mergedSelector = merged.selector;
|
|
945
1011
|
const defaultSelector = defaults.selector;
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
mergedSelector.trigger = trigger;
|
|
1012
|
+
for (const key of Object.keys(
|
|
1013
|
+
defaultSelector
|
|
1014
|
+
)) {
|
|
1015
|
+
try {
|
|
1016
|
+
document.querySelector(mergedSelector[key]);
|
|
1017
|
+
} catch {
|
|
1018
|
+
const selector = defaultSelector[key];
|
|
1019
|
+
console.warn(
|
|
1020
|
+
`Invalid ${key.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${selector}'.`
|
|
1021
|
+
);
|
|
1022
|
+
mergedSelector[key] = selector;
|
|
1023
|
+
}
|
|
959
1024
|
}
|
|
960
1025
|
return merged;
|
|
961
1026
|
}
|
|
@@ -977,7 +1042,7 @@ function waitAnimationFinish(animation) {
|
|
|
977
1042
|
* Accordion
|
|
978
1043
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
979
1044
|
*
|
|
980
|
-
* @version 2.1.
|
|
1045
|
+
* @version 2.1.3
|
|
981
1046
|
* @author Yusuke Kamiyamane
|
|
982
1047
|
* @license MIT
|
|
983
1048
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1002,7 +1067,7 @@ power-focusable/dist/index.js:
|
|
|
1002
1067
|
* High-precision focus management utility with full composed tree support.
|
|
1003
1068
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1004
1069
|
*
|
|
1005
|
-
* @version 4.
|
|
1070
|
+
* @version 4.4.2
|
|
1006
1071
|
* @author Yusuke Kamiyamane
|
|
1007
1072
|
* @license MIT
|
|
1008
1073
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1026,7 +1091,7 @@ power-focusable/dist/index.js:
|
|
|
1026
1091
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1027
1092
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1028
1093
|
*
|
|
1029
|
-
* @version 3.1
|
|
1094
|
+
* @version 3.3.1
|
|
1030
1095
|
* @author Yusuke Kamiyamane
|
|
1031
1096
|
* @license MIT
|
|
1032
1097
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -287,19 +287,18 @@ var Accordion = class _Accordion {
|
|
|
287
287
|
}
|
|
288
288
|
const mergedSelector = merged.selector;
|
|
289
289
|
const defaultSelector = defaults.selector;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
mergedSelector.trigger = trigger;
|
|
290
|
+
for (const key of Object.keys(
|
|
291
|
+
defaultSelector
|
|
292
|
+
)) {
|
|
293
|
+
try {
|
|
294
|
+
document.querySelector(mergedSelector[key]);
|
|
295
|
+
} catch {
|
|
296
|
+
const selector = defaultSelector[key];
|
|
297
|
+
console.warn(
|
|
298
|
+
`Invalid ${key.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${selector}'.`
|
|
299
|
+
);
|
|
300
|
+
mergedSelector[key] = selector;
|
|
301
|
+
}
|
|
303
302
|
}
|
|
304
303
|
return merged;
|
|
305
304
|
}
|
|
@@ -321,7 +320,7 @@ function waitAnimationFinish(animation) {
|
|
|
321
320
|
* Accordion
|
|
322
321
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
323
322
|
*
|
|
324
|
-
* @version 2.1.
|
|
323
|
+
* @version 2.1.3
|
|
325
324
|
* @author Yusuke Kamiyamane
|
|
326
325
|
* @license MIT
|
|
327
326
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -285,19 +285,18 @@ var Accordion = class _Accordion {
|
|
|
285
285
|
}
|
|
286
286
|
const mergedSelector = merged.selector;
|
|
287
287
|
const defaultSelector = defaults.selector;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
mergedSelector.trigger = trigger;
|
|
288
|
+
for (const key of Object.keys(
|
|
289
|
+
defaultSelector
|
|
290
|
+
)) {
|
|
291
|
+
try {
|
|
292
|
+
document.querySelector(mergedSelector[key]);
|
|
293
|
+
} catch {
|
|
294
|
+
const selector = defaultSelector[key];
|
|
295
|
+
console.warn(
|
|
296
|
+
`Invalid ${key.replace(/[A-Z]/g, (c) => ` ${c.toLowerCase()}`)} selector. Fallback: '${selector}'.`
|
|
297
|
+
);
|
|
298
|
+
mergedSelector[key] = selector;
|
|
299
|
+
}
|
|
301
300
|
}
|
|
302
301
|
return merged;
|
|
303
302
|
}
|
|
@@ -319,7 +318,7 @@ function waitAnimationFinish(animation) {
|
|
|
319
318
|
* Accordion
|
|
320
319
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
321
320
|
*
|
|
322
|
-
* @version 2.1.
|
|
321
|
+
* @version 2.1.3
|
|
323
322
|
* @author Yusuke Kamiyamane
|
|
324
323
|
* @license MIT
|
|
325
324
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/accordion",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
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
|
|
59
|
+
"@y14e/roving-tabindex": "^3.3.1"
|
|
60
60
|
}
|
|
61
61
|
}
|