@y14e/roving-tabindex 3.1.16 → 3.1.18
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 +35 -32
- package/dist/index.bundle.js +35 -32
- package/dist/index.cjs +18 -17
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -17
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,11 +13,11 @@ npm i @y14e/roving-tabindex
|
|
|
13
13
|
import { createRovingTabIndex } from '@y14e/roving-tabindex';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.1.
|
|
16
|
+
import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.1.18';
|
|
17
17
|
// or
|
|
18
|
-
import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.
|
|
18
|
+
import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.18/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.
|
|
20
|
+
import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.18';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## 📦 APIs
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -24,8 +24,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
27
|
-
function restoreAttributes(
|
|
28
|
-
for (const element of
|
|
27
|
+
function restoreAttributes(element_or_elements) {
|
|
28
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
29
29
|
const snapshot = snapshots.get(element);
|
|
30
30
|
if (!snapshot) {
|
|
31
31
|
continue;
|
|
@@ -36,8 +36,9 @@ function restoreAttributes(elements) {
|
|
|
36
36
|
snapshots.delete(element);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
function saveAttributes(
|
|
40
|
-
|
|
39
|
+
function saveAttributes(element_or_elements, attribute_or_attributes) {
|
|
40
|
+
const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
|
|
41
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
41
42
|
let snapshot = snapshots.get(element);
|
|
42
43
|
if (!snapshot) {
|
|
43
44
|
snapshot = /* @__PURE__ */ new Map();
|
|
@@ -91,14 +92,14 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
91
92
|
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
92
93
|
skipVisibilityCheck = false;
|
|
93
94
|
}
|
|
94
|
-
const
|
|
95
|
+
const candidates = [];
|
|
95
96
|
if (composed || include) {
|
|
96
97
|
let traverse2 = function(node) {
|
|
97
98
|
if (isFocusable(node, {
|
|
98
99
|
skipNegativeTabIndexCheck,
|
|
99
100
|
skipVisibilityCheck
|
|
100
101
|
}) || include?.(node)) {
|
|
101
|
-
|
|
102
|
+
candidates[candidates.length] = node;
|
|
102
103
|
}
|
|
103
104
|
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
104
105
|
for (let i = 0, l = children2.length; i < l; i++) {
|
|
@@ -112,21 +113,22 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
112
113
|
child && traverse2(child);
|
|
113
114
|
}
|
|
114
115
|
} else {
|
|
115
|
-
const
|
|
116
|
+
const matches = container.querySelectorAll(
|
|
116
117
|
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
117
118
|
);
|
|
118
|
-
for (let i = 0, l =
|
|
119
|
-
const
|
|
120
|
-
if (
|
|
119
|
+
for (let i = 0, l = matches.length; i < l; i++) {
|
|
120
|
+
const matched = matches[i];
|
|
121
|
+
if (matched && isFocusable(matched, {
|
|
121
122
|
skipNegativeTabIndexCheck,
|
|
122
123
|
skipVisibilityCheck
|
|
123
124
|
})) {
|
|
124
|
-
|
|
125
|
+
candidates[candidates.length] = matched;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
return normalizeRadioGroup(
|
|
130
|
+
sortByTabIndex(filter ? candidates.filter(filter) : candidates)
|
|
131
|
+
);
|
|
130
132
|
}
|
|
131
133
|
function isFocusable(element, options = {}) {
|
|
132
134
|
if (!(element instanceof Element)) {
|
|
@@ -405,7 +407,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
405
407
|
this.#controller = null;
|
|
406
408
|
this.#focusables.forEach((focusable) => {
|
|
407
409
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
408
|
-
restoreAttributes(
|
|
410
|
+
restoreAttributes(focusable);
|
|
409
411
|
});
|
|
410
412
|
this.#focusables.clear();
|
|
411
413
|
this.#focusablesByFirstChar.clear();
|
|
@@ -459,16 +461,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
459
461
|
if (!(active instanceof Element)) {
|
|
460
462
|
return;
|
|
461
463
|
}
|
|
462
|
-
const
|
|
464
|
+
const candidates = this.#getFocusables().filter(
|
|
463
465
|
(focusable2) => this.#focusables.has(focusable2)
|
|
464
466
|
);
|
|
465
|
-
if (!
|
|
467
|
+
if (!candidates.includes(active)) {
|
|
466
468
|
return;
|
|
467
469
|
}
|
|
468
470
|
event.preventDefault();
|
|
469
|
-
const
|
|
471
|
+
const activeIndex = candidates.indexOf(active);
|
|
470
472
|
let newIndex;
|
|
471
|
-
let target =
|
|
473
|
+
let target = candidates;
|
|
472
474
|
switch (key) {
|
|
473
475
|
case "End":
|
|
474
476
|
newIndex = -1;
|
|
@@ -478,25 +480,26 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
478
480
|
break;
|
|
479
481
|
case "ArrowLeft":
|
|
480
482
|
case "ArrowUp": {
|
|
481
|
-
const rawIndex =
|
|
483
|
+
const rawIndex = activeIndex - 1;
|
|
482
484
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
483
485
|
break;
|
|
484
486
|
}
|
|
485
487
|
case "ArrowRight":
|
|
486
488
|
case "ArrowDown": {
|
|
487
|
-
const rawIndex =
|
|
488
|
-
|
|
489
|
+
const rawIndex = activeIndex + 1;
|
|
490
|
+
const length = target.length;
|
|
491
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
489
492
|
break;
|
|
490
493
|
}
|
|
491
494
|
default: {
|
|
492
495
|
const focusables = new Set(
|
|
493
496
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
494
497
|
);
|
|
495
|
-
target =
|
|
496
|
-
const
|
|
497
|
-
(focusable2) =>
|
|
498
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
499
|
+
const afterIndex = target.findIndex(
|
|
500
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
498
501
|
);
|
|
499
|
-
newIndex =
|
|
502
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
500
503
|
}
|
|
501
504
|
}
|
|
502
505
|
const focusable = target.at(newIndex);
|
|
@@ -507,7 +510,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
507
510
|
for (const focusable of this.#focusables) {
|
|
508
511
|
if (!current.has(focusable)) {
|
|
509
512
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
510
|
-
restoreAttributes(
|
|
513
|
+
restoreAttributes(focusable);
|
|
511
514
|
this.#focusables.delete(focusable);
|
|
512
515
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
513
516
|
const index = focusables.indexOf(focusable);
|
|
@@ -529,7 +532,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
529
532
|
this.#focusables.add(focusable);
|
|
530
533
|
_RovingTabIndex.#initialized.add(focusable);
|
|
531
534
|
if (!navigationOnly) {
|
|
532
|
-
saveAttributes(
|
|
535
|
+
saveAttributes(focusable, "tabindex");
|
|
533
536
|
focusable.setAttribute("tabindex", "-1");
|
|
534
537
|
}
|
|
535
538
|
if (!typeahead) {
|
|
@@ -542,7 +545,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
542
545
|
);
|
|
543
546
|
if (char) {
|
|
544
547
|
keys.add(char);
|
|
545
|
-
saveAttributes(
|
|
548
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
546
549
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
547
550
|
caseInsensitive: true
|
|
548
551
|
});
|
|
@@ -567,7 +570,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
567
570
|
}
|
|
568
571
|
#createSelectorFilter() {
|
|
569
572
|
const { selector } = this.#settings;
|
|
570
|
-
return (element) => !selector ||
|
|
573
|
+
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
571
574
|
}
|
|
572
575
|
#getFocusables() {
|
|
573
576
|
return getFocusables(this.#container, {
|
|
@@ -583,7 +586,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
583
586
|
* Lightweight roving tabindex utility with fully focus management.
|
|
584
587
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
585
588
|
*
|
|
586
|
-
* @version 3.1.
|
|
589
|
+
* @version 3.1.18
|
|
587
590
|
* @author Yusuke Kamiyamane
|
|
588
591
|
* @license MIT
|
|
589
592
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -595,7 +598,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
595
598
|
(**
|
|
596
599
|
* Attributes Utils
|
|
597
600
|
*
|
|
598
|
-
* @version 1.1.
|
|
601
|
+
* @version 1.1.4
|
|
599
602
|
* @author Yusuke Kamiyamane
|
|
600
603
|
* @license MIT
|
|
601
604
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -608,7 +611,7 @@ power-focusable/dist/index.js:
|
|
|
608
611
|
* High-precision focus management utility with full composed tree support.
|
|
609
612
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
610
613
|
*
|
|
611
|
-
* @version 4.3.
|
|
614
|
+
* @version 4.3.21
|
|
612
615
|
* @author Yusuke Kamiyamane
|
|
613
616
|
* @license MIT
|
|
614
617
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -22,8 +22,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
25
|
-
function restoreAttributes(
|
|
26
|
-
for (const element of
|
|
25
|
+
function restoreAttributes(element_or_elements) {
|
|
26
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
27
27
|
const snapshot = snapshots.get(element);
|
|
28
28
|
if (!snapshot) {
|
|
29
29
|
continue;
|
|
@@ -34,8 +34,9 @@ function restoreAttributes(elements) {
|
|
|
34
34
|
snapshots.delete(element);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
function saveAttributes(
|
|
38
|
-
|
|
37
|
+
function saveAttributes(element_or_elements, attribute_or_attributes) {
|
|
38
|
+
const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
|
|
39
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
39
40
|
let snapshot = snapshots.get(element);
|
|
40
41
|
if (!snapshot) {
|
|
41
42
|
snapshot = /* @__PURE__ */ new Map();
|
|
@@ -89,14 +90,14 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
89
90
|
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
90
91
|
skipVisibilityCheck = false;
|
|
91
92
|
}
|
|
92
|
-
const
|
|
93
|
+
const candidates = [];
|
|
93
94
|
if (composed || include) {
|
|
94
95
|
let traverse2 = function(node) {
|
|
95
96
|
if (isFocusable(node, {
|
|
96
97
|
skipNegativeTabIndexCheck,
|
|
97
98
|
skipVisibilityCheck
|
|
98
99
|
}) || include?.(node)) {
|
|
99
|
-
|
|
100
|
+
candidates[candidates.length] = node;
|
|
100
101
|
}
|
|
101
102
|
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
102
103
|
for (let i = 0, l = children2.length; i < l; i++) {
|
|
@@ -110,21 +111,22 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
110
111
|
child && traverse2(child);
|
|
111
112
|
}
|
|
112
113
|
} else {
|
|
113
|
-
const
|
|
114
|
+
const matches = container.querySelectorAll(
|
|
114
115
|
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
115
116
|
);
|
|
116
|
-
for (let i = 0, l =
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
117
|
+
for (let i = 0, l = matches.length; i < l; i++) {
|
|
118
|
+
const matched = matches[i];
|
|
119
|
+
if (matched && isFocusable(matched, {
|
|
119
120
|
skipNegativeTabIndexCheck,
|
|
120
121
|
skipVisibilityCheck
|
|
121
122
|
})) {
|
|
122
|
-
|
|
123
|
+
candidates[candidates.length] = matched;
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
return normalizeRadioGroup(
|
|
128
|
+
sortByTabIndex(filter ? candidates.filter(filter) : candidates)
|
|
129
|
+
);
|
|
128
130
|
}
|
|
129
131
|
function isFocusable(element, options = {}) {
|
|
130
132
|
if (!(element instanceof Element)) {
|
|
@@ -403,7 +405,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
403
405
|
this.#controller = null;
|
|
404
406
|
this.#focusables.forEach((focusable) => {
|
|
405
407
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
406
|
-
restoreAttributes(
|
|
408
|
+
restoreAttributes(focusable);
|
|
407
409
|
});
|
|
408
410
|
this.#focusables.clear();
|
|
409
411
|
this.#focusablesByFirstChar.clear();
|
|
@@ -457,16 +459,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
457
459
|
if (!(active instanceof Element)) {
|
|
458
460
|
return;
|
|
459
461
|
}
|
|
460
|
-
const
|
|
462
|
+
const candidates = this.#getFocusables().filter(
|
|
461
463
|
(focusable2) => this.#focusables.has(focusable2)
|
|
462
464
|
);
|
|
463
|
-
if (!
|
|
465
|
+
if (!candidates.includes(active)) {
|
|
464
466
|
return;
|
|
465
467
|
}
|
|
466
468
|
event.preventDefault();
|
|
467
|
-
const
|
|
469
|
+
const activeIndex = candidates.indexOf(active);
|
|
468
470
|
let newIndex;
|
|
469
|
-
let target =
|
|
471
|
+
let target = candidates;
|
|
470
472
|
switch (key) {
|
|
471
473
|
case "End":
|
|
472
474
|
newIndex = -1;
|
|
@@ -476,25 +478,26 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
476
478
|
break;
|
|
477
479
|
case "ArrowLeft":
|
|
478
480
|
case "ArrowUp": {
|
|
479
|
-
const rawIndex =
|
|
481
|
+
const rawIndex = activeIndex - 1;
|
|
480
482
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
481
483
|
break;
|
|
482
484
|
}
|
|
483
485
|
case "ArrowRight":
|
|
484
486
|
case "ArrowDown": {
|
|
485
|
-
const rawIndex =
|
|
486
|
-
|
|
487
|
+
const rawIndex = activeIndex + 1;
|
|
488
|
+
const length = target.length;
|
|
489
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
487
490
|
break;
|
|
488
491
|
}
|
|
489
492
|
default: {
|
|
490
493
|
const focusables = new Set(
|
|
491
494
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
492
495
|
);
|
|
493
|
-
target =
|
|
494
|
-
const
|
|
495
|
-
(focusable2) =>
|
|
496
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
497
|
+
const afterIndex = target.findIndex(
|
|
498
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
496
499
|
);
|
|
497
|
-
newIndex =
|
|
500
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
503
|
const focusable = target.at(newIndex);
|
|
@@ -505,7 +508,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
505
508
|
for (const focusable of this.#focusables) {
|
|
506
509
|
if (!current.has(focusable)) {
|
|
507
510
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
508
|
-
restoreAttributes(
|
|
511
|
+
restoreAttributes(focusable);
|
|
509
512
|
this.#focusables.delete(focusable);
|
|
510
513
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
511
514
|
const index = focusables.indexOf(focusable);
|
|
@@ -527,7 +530,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
527
530
|
this.#focusables.add(focusable);
|
|
528
531
|
_RovingTabIndex.#initialized.add(focusable);
|
|
529
532
|
if (!navigationOnly) {
|
|
530
|
-
saveAttributes(
|
|
533
|
+
saveAttributes(focusable, "tabindex");
|
|
531
534
|
focusable.setAttribute("tabindex", "-1");
|
|
532
535
|
}
|
|
533
536
|
if (!typeahead) {
|
|
@@ -540,7 +543,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
540
543
|
);
|
|
541
544
|
if (char) {
|
|
542
545
|
keys.add(char);
|
|
543
|
-
saveAttributes(
|
|
546
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
544
547
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
545
548
|
caseInsensitive: true
|
|
546
549
|
});
|
|
@@ -565,7 +568,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
565
568
|
}
|
|
566
569
|
#createSelectorFilter() {
|
|
567
570
|
const { selector } = this.#settings;
|
|
568
|
-
return (element) => !selector ||
|
|
571
|
+
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
569
572
|
}
|
|
570
573
|
#getFocusables() {
|
|
571
574
|
return getFocusables(this.#container, {
|
|
@@ -581,7 +584,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
581
584
|
* Lightweight roving tabindex utility with fully focus management.
|
|
582
585
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
583
586
|
*
|
|
584
|
-
* @version 3.1.
|
|
587
|
+
* @version 3.1.18
|
|
585
588
|
* @author Yusuke Kamiyamane
|
|
586
589
|
* @license MIT
|
|
587
590
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -593,7 +596,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
593
596
|
(**
|
|
594
597
|
* Attributes Utils
|
|
595
598
|
*
|
|
596
|
-
* @version 1.1.
|
|
599
|
+
* @version 1.1.4
|
|
597
600
|
* @author Yusuke Kamiyamane
|
|
598
601
|
* @license MIT
|
|
599
602
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -606,7 +609,7 @@ power-focusable/dist/index.js:
|
|
|
606
609
|
* High-precision focus management utility with full composed tree support.
|
|
607
610
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
608
611
|
*
|
|
609
|
-
* @version 4.3.
|
|
612
|
+
* @version 4.3.21
|
|
610
613
|
* @author Yusuke Kamiyamane
|
|
611
614
|
* @license MIT
|
|
612
615
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -91,7 +91,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
91
91
|
this.#controller = null;
|
|
92
92
|
this.#focusables.forEach((focusable) => {
|
|
93
93
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
94
|
-
attributesUtils.restoreAttributes(
|
|
94
|
+
attributesUtils.restoreAttributes(focusable);
|
|
95
95
|
});
|
|
96
96
|
this.#focusables.clear();
|
|
97
97
|
this.#focusablesByFirstChar.clear();
|
|
@@ -145,16 +145,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
145
145
|
if (!(active instanceof Element)) {
|
|
146
146
|
return;
|
|
147
147
|
}
|
|
148
|
-
const
|
|
148
|
+
const candidates = this.#getFocusables().filter(
|
|
149
149
|
(focusable2) => this.#focusables.has(focusable2)
|
|
150
150
|
);
|
|
151
|
-
if (!
|
|
151
|
+
if (!candidates.includes(active)) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
event.preventDefault();
|
|
155
|
-
const
|
|
155
|
+
const activeIndex = candidates.indexOf(active);
|
|
156
156
|
let newIndex;
|
|
157
|
-
let target =
|
|
157
|
+
let target = candidates;
|
|
158
158
|
switch (key) {
|
|
159
159
|
case "End":
|
|
160
160
|
newIndex = -1;
|
|
@@ -164,25 +164,26 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
164
164
|
break;
|
|
165
165
|
case "ArrowLeft":
|
|
166
166
|
case "ArrowUp": {
|
|
167
|
-
const rawIndex =
|
|
167
|
+
const rawIndex = activeIndex - 1;
|
|
168
168
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
169
169
|
break;
|
|
170
170
|
}
|
|
171
171
|
case "ArrowRight":
|
|
172
172
|
case "ArrowDown": {
|
|
173
|
-
const rawIndex =
|
|
174
|
-
|
|
173
|
+
const rawIndex = activeIndex + 1;
|
|
174
|
+
const length = target.length;
|
|
175
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
175
176
|
break;
|
|
176
177
|
}
|
|
177
178
|
default: {
|
|
178
179
|
const focusables = new Set(
|
|
179
180
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
180
181
|
);
|
|
181
|
-
target =
|
|
182
|
-
const
|
|
183
|
-
(focusable2) =>
|
|
182
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
183
|
+
const afterIndex = target.findIndex(
|
|
184
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
184
185
|
);
|
|
185
|
-
newIndex =
|
|
186
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
const focusable = target.at(newIndex);
|
|
@@ -193,7 +194,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
193
194
|
for (const focusable of this.#focusables) {
|
|
194
195
|
if (!current.has(focusable)) {
|
|
195
196
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
196
|
-
attributesUtils.restoreAttributes(
|
|
197
|
+
attributesUtils.restoreAttributes(focusable);
|
|
197
198
|
this.#focusables.delete(focusable);
|
|
198
199
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
199
200
|
const index = focusables.indexOf(focusable);
|
|
@@ -215,7 +216,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
215
216
|
this.#focusables.add(focusable);
|
|
216
217
|
_RovingTabIndex.#initialized.add(focusable);
|
|
217
218
|
if (!navigationOnly) {
|
|
218
|
-
attributesUtils.saveAttributes(
|
|
219
|
+
attributesUtils.saveAttributes(focusable, "tabindex");
|
|
219
220
|
focusable.setAttribute("tabindex", "-1");
|
|
220
221
|
}
|
|
221
222
|
if (!typeahead) {
|
|
@@ -228,7 +229,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
228
229
|
);
|
|
229
230
|
if (char) {
|
|
230
231
|
keys.add(char);
|
|
231
|
-
attributesUtils.saveAttributes(
|
|
232
|
+
attributesUtils.saveAttributes(focusable, "aria-keyshortcuts");
|
|
232
233
|
attributesUtils.addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
233
234
|
caseInsensitive: true
|
|
234
235
|
});
|
|
@@ -253,7 +254,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
253
254
|
}
|
|
254
255
|
#createSelectorFilter() {
|
|
255
256
|
const { selector } = this.#settings;
|
|
256
|
-
return (element) => !selector ||
|
|
257
|
+
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
257
258
|
}
|
|
258
259
|
#getFocusables() {
|
|
259
260
|
return powerFocusable.getFocusables(this.#container, {
|
|
@@ -269,7 +270,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
269
270
|
* Lightweight roving tabindex utility with fully focus management.
|
|
270
271
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
271
272
|
*
|
|
272
|
-
* @version 3.1.
|
|
273
|
+
* @version 3.1.18
|
|
273
274
|
* @author Yusuke Kamiyamane
|
|
274
275
|
* @license MIT
|
|
275
276
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Lightweight roving tabindex utility with fully focus management.
|
|
4
4
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
5
5
|
*
|
|
6
|
-
* @version 3.1.
|
|
6
|
+
* @version 3.1.18
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Lightweight roving tabindex utility with fully focus management.
|
|
4
4
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
5
5
|
*
|
|
6
|
-
* @version 3.1.
|
|
6
|
+
* @version 3.1.18
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -89,7 +89,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
89
89
|
this.#controller = null;
|
|
90
90
|
this.#focusables.forEach((focusable) => {
|
|
91
91
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
92
|
-
restoreAttributes(
|
|
92
|
+
restoreAttributes(focusable);
|
|
93
93
|
});
|
|
94
94
|
this.#focusables.clear();
|
|
95
95
|
this.#focusablesByFirstChar.clear();
|
|
@@ -143,16 +143,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
143
143
|
if (!(active instanceof Element)) {
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
|
-
const
|
|
146
|
+
const candidates = this.#getFocusables().filter(
|
|
147
147
|
(focusable2) => this.#focusables.has(focusable2)
|
|
148
148
|
);
|
|
149
|
-
if (!
|
|
149
|
+
if (!candidates.includes(active)) {
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
event.preventDefault();
|
|
153
|
-
const
|
|
153
|
+
const activeIndex = candidates.indexOf(active);
|
|
154
154
|
let newIndex;
|
|
155
|
-
let target =
|
|
155
|
+
let target = candidates;
|
|
156
156
|
switch (key) {
|
|
157
157
|
case "End":
|
|
158
158
|
newIndex = -1;
|
|
@@ -162,25 +162,26 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
162
162
|
break;
|
|
163
163
|
case "ArrowLeft":
|
|
164
164
|
case "ArrowUp": {
|
|
165
|
-
const rawIndex =
|
|
165
|
+
const rawIndex = activeIndex - 1;
|
|
166
166
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
167
167
|
break;
|
|
168
168
|
}
|
|
169
169
|
case "ArrowRight":
|
|
170
170
|
case "ArrowDown": {
|
|
171
|
-
const rawIndex =
|
|
172
|
-
|
|
171
|
+
const rawIndex = activeIndex + 1;
|
|
172
|
+
const length = target.length;
|
|
173
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
173
174
|
break;
|
|
174
175
|
}
|
|
175
176
|
default: {
|
|
176
177
|
const focusables = new Set(
|
|
177
178
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
178
179
|
);
|
|
179
|
-
target =
|
|
180
|
-
const
|
|
181
|
-
(focusable2) =>
|
|
180
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
181
|
+
const afterIndex = target.findIndex(
|
|
182
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
182
183
|
);
|
|
183
|
-
newIndex =
|
|
184
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
const focusable = target.at(newIndex);
|
|
@@ -191,7 +192,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
191
192
|
for (const focusable of this.#focusables) {
|
|
192
193
|
if (!current.has(focusable)) {
|
|
193
194
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
194
|
-
restoreAttributes(
|
|
195
|
+
restoreAttributes(focusable);
|
|
195
196
|
this.#focusables.delete(focusable);
|
|
196
197
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
197
198
|
const index = focusables.indexOf(focusable);
|
|
@@ -213,7 +214,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
213
214
|
this.#focusables.add(focusable);
|
|
214
215
|
_RovingTabIndex.#initialized.add(focusable);
|
|
215
216
|
if (!navigationOnly) {
|
|
216
|
-
saveAttributes(
|
|
217
|
+
saveAttributes(focusable, "tabindex");
|
|
217
218
|
focusable.setAttribute("tabindex", "-1");
|
|
218
219
|
}
|
|
219
220
|
if (!typeahead) {
|
|
@@ -226,7 +227,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
226
227
|
);
|
|
227
228
|
if (char) {
|
|
228
229
|
keys.add(char);
|
|
229
|
-
saveAttributes(
|
|
230
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
230
231
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
231
232
|
caseInsensitive: true
|
|
232
233
|
});
|
|
@@ -251,7 +252,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
251
252
|
}
|
|
252
253
|
#createSelectorFilter() {
|
|
253
254
|
const { selector } = this.#settings;
|
|
254
|
-
return (element) => !selector ||
|
|
255
|
+
return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
|
|
255
256
|
}
|
|
256
257
|
#getFocusables() {
|
|
257
258
|
return getFocusables(this.#container, {
|
|
@@ -267,7 +268,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
267
268
|
* Lightweight roving tabindex utility with fully focus management.
|
|
268
269
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
269
270
|
*
|
|
270
|
-
* @version 3.1.
|
|
271
|
+
* @version 3.1.18
|
|
271
272
|
* @author Yusuke Kamiyamane
|
|
272
273
|
* @license MIT
|
|
273
274
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/roving-tabindex",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.18",
|
|
4
4
|
"description": "Lightweight roving tabindex utility with fully focus management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"node": ">=18"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@y14e/attributes-utils": "^1.1.
|
|
60
|
-
"power-focusable": "^4.3.
|
|
59
|
+
"@y14e/attributes-utils": "^1.1.4",
|
|
60
|
+
"power-focusable": "^4.3.21"
|
|
61
61
|
}
|
|
62
62
|
}
|