@y14e/roving-tabindex 3.1.17 → 3.1.19
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 +34 -30
- package/dist/index.bundle.js +34 -30
- package/dist/index.cjs +17 -15
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -15
- 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.19';
|
|
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.19/+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.19';
|
|
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();
|
|
@@ -455,20 +457,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
455
457
|
return;
|
|
456
458
|
}
|
|
457
459
|
}
|
|
460
|
+
const candidates = this.#getFocusables().filter(
|
|
461
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
462
|
+
);
|
|
458
463
|
const active = getActiveElement();
|
|
459
464
|
if (!(active instanceof Element)) {
|
|
460
465
|
return;
|
|
461
466
|
}
|
|
462
|
-
const candidates = this.#getFocusables().filter(
|
|
463
|
-
(focusable2) => this.#focusables.has(focusable2)
|
|
464
|
-
);
|
|
465
467
|
if (!candidates.includes(active)) {
|
|
466
468
|
return;
|
|
467
469
|
}
|
|
468
470
|
event.preventDefault();
|
|
469
|
-
const activeIndex = candidates.indexOf(active);
|
|
470
471
|
let newIndex;
|
|
471
|
-
|
|
472
|
+
const activeIndex = candidates.indexOf(active);
|
|
473
|
+
let focusables = candidates;
|
|
472
474
|
switch (key) {
|
|
473
475
|
case "End":
|
|
474
476
|
newIndex = -1;
|
|
@@ -485,22 +487,24 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
485
487
|
case "ArrowRight":
|
|
486
488
|
case "ArrowDown": {
|
|
487
489
|
const rawIndex = activeIndex + 1;
|
|
488
|
-
const length =
|
|
490
|
+
const length = focusables.length;
|
|
489
491
|
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
490
492
|
break;
|
|
491
493
|
}
|
|
492
494
|
default: {
|
|
493
|
-
const
|
|
495
|
+
const focusablesByFirstChar = new Set(
|
|
494
496
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
495
497
|
);
|
|
496
|
-
|
|
497
|
-
|
|
498
|
+
focusables = candidates.filter(
|
|
499
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
500
|
+
);
|
|
501
|
+
const afterIndex = focusables.findIndex(
|
|
498
502
|
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
499
503
|
);
|
|
500
504
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
501
505
|
}
|
|
502
506
|
}
|
|
503
|
-
const focusable =
|
|
507
|
+
const focusable = focusables.at(newIndex);
|
|
504
508
|
focusable && focusElement(focusable);
|
|
505
509
|
};
|
|
506
510
|
#update(active) {
|
|
@@ -508,7 +512,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
508
512
|
for (const focusable of this.#focusables) {
|
|
509
513
|
if (!current.has(focusable)) {
|
|
510
514
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
511
|
-
restoreAttributes(
|
|
515
|
+
restoreAttributes(focusable);
|
|
512
516
|
this.#focusables.delete(focusable);
|
|
513
517
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
514
518
|
const index = focusables.indexOf(focusable);
|
|
@@ -530,7 +534,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
530
534
|
this.#focusables.add(focusable);
|
|
531
535
|
_RovingTabIndex.#initialized.add(focusable);
|
|
532
536
|
if (!navigationOnly) {
|
|
533
|
-
saveAttributes(
|
|
537
|
+
saveAttributes(focusable, "tabindex");
|
|
534
538
|
focusable.setAttribute("tabindex", "-1");
|
|
535
539
|
}
|
|
536
540
|
if (!typeahead) {
|
|
@@ -543,7 +547,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
543
547
|
);
|
|
544
548
|
if (char) {
|
|
545
549
|
keys.add(char);
|
|
546
|
-
saveAttributes(
|
|
550
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
547
551
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
548
552
|
caseInsensitive: true
|
|
549
553
|
});
|
|
@@ -584,7 +588,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
584
588
|
* Lightweight roving tabindex utility with fully focus management.
|
|
585
589
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
586
590
|
*
|
|
587
|
-
* @version 3.1.
|
|
591
|
+
* @version 3.1.19
|
|
588
592
|
* @author Yusuke Kamiyamane
|
|
589
593
|
* @license MIT
|
|
590
594
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -596,7 +600,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
596
600
|
(**
|
|
597
601
|
* Attributes Utils
|
|
598
602
|
*
|
|
599
|
-
* @version 1.1.
|
|
603
|
+
* @version 1.1.4
|
|
600
604
|
* @author Yusuke Kamiyamane
|
|
601
605
|
* @license MIT
|
|
602
606
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -609,7 +613,7 @@ power-focusable/dist/index.js:
|
|
|
609
613
|
* High-precision focus management utility with full composed tree support.
|
|
610
614
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
611
615
|
*
|
|
612
|
-
* @version 4.3.
|
|
616
|
+
* @version 4.3.21
|
|
613
617
|
* @author Yusuke Kamiyamane
|
|
614
618
|
* @license MIT
|
|
615
619
|
* @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();
|
|
@@ -453,20 +455,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
453
455
|
return;
|
|
454
456
|
}
|
|
455
457
|
}
|
|
458
|
+
const candidates = this.#getFocusables().filter(
|
|
459
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
460
|
+
);
|
|
456
461
|
const active = getActiveElement();
|
|
457
462
|
if (!(active instanceof Element)) {
|
|
458
463
|
return;
|
|
459
464
|
}
|
|
460
|
-
const candidates = this.#getFocusables().filter(
|
|
461
|
-
(focusable2) => this.#focusables.has(focusable2)
|
|
462
|
-
);
|
|
463
465
|
if (!candidates.includes(active)) {
|
|
464
466
|
return;
|
|
465
467
|
}
|
|
466
468
|
event.preventDefault();
|
|
467
|
-
const activeIndex = candidates.indexOf(active);
|
|
468
469
|
let newIndex;
|
|
469
|
-
|
|
470
|
+
const activeIndex = candidates.indexOf(active);
|
|
471
|
+
let focusables = candidates;
|
|
470
472
|
switch (key) {
|
|
471
473
|
case "End":
|
|
472
474
|
newIndex = -1;
|
|
@@ -483,22 +485,24 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
483
485
|
case "ArrowRight":
|
|
484
486
|
case "ArrowDown": {
|
|
485
487
|
const rawIndex = activeIndex + 1;
|
|
486
|
-
const length =
|
|
488
|
+
const length = focusables.length;
|
|
487
489
|
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
488
490
|
break;
|
|
489
491
|
}
|
|
490
492
|
default: {
|
|
491
|
-
const
|
|
493
|
+
const focusablesByFirstChar = new Set(
|
|
492
494
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
493
495
|
);
|
|
494
|
-
|
|
495
|
-
|
|
496
|
+
focusables = candidates.filter(
|
|
497
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
498
|
+
);
|
|
499
|
+
const afterIndex = focusables.findIndex(
|
|
496
500
|
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
497
501
|
);
|
|
498
502
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
499
503
|
}
|
|
500
504
|
}
|
|
501
|
-
const focusable =
|
|
505
|
+
const focusable = focusables.at(newIndex);
|
|
502
506
|
focusable && focusElement(focusable);
|
|
503
507
|
};
|
|
504
508
|
#update(active) {
|
|
@@ -506,7 +510,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
506
510
|
for (const focusable of this.#focusables) {
|
|
507
511
|
if (!current.has(focusable)) {
|
|
508
512
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
509
|
-
restoreAttributes(
|
|
513
|
+
restoreAttributes(focusable);
|
|
510
514
|
this.#focusables.delete(focusable);
|
|
511
515
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
512
516
|
const index = focusables.indexOf(focusable);
|
|
@@ -528,7 +532,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
528
532
|
this.#focusables.add(focusable);
|
|
529
533
|
_RovingTabIndex.#initialized.add(focusable);
|
|
530
534
|
if (!navigationOnly) {
|
|
531
|
-
saveAttributes(
|
|
535
|
+
saveAttributes(focusable, "tabindex");
|
|
532
536
|
focusable.setAttribute("tabindex", "-1");
|
|
533
537
|
}
|
|
534
538
|
if (!typeahead) {
|
|
@@ -541,7 +545,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
541
545
|
);
|
|
542
546
|
if (char) {
|
|
543
547
|
keys.add(char);
|
|
544
|
-
saveAttributes(
|
|
548
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
545
549
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
546
550
|
caseInsensitive: true
|
|
547
551
|
});
|
|
@@ -582,7 +586,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
582
586
|
* Lightweight roving tabindex utility with fully focus management.
|
|
583
587
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
584
588
|
*
|
|
585
|
-
* @version 3.1.
|
|
589
|
+
* @version 3.1.19
|
|
586
590
|
* @author Yusuke Kamiyamane
|
|
587
591
|
* @license MIT
|
|
588
592
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -594,7 +598,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
594
598
|
(**
|
|
595
599
|
* Attributes Utils
|
|
596
600
|
*
|
|
597
|
-
* @version 1.1.
|
|
601
|
+
* @version 1.1.4
|
|
598
602
|
* @author Yusuke Kamiyamane
|
|
599
603
|
* @license MIT
|
|
600
604
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -607,7 +611,7 @@ power-focusable/dist/index.js:
|
|
|
607
611
|
* High-precision focus management utility with full composed tree support.
|
|
608
612
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
609
613
|
*
|
|
610
|
-
* @version 4.3.
|
|
614
|
+
* @version 4.3.21
|
|
611
615
|
* @author Yusuke Kamiyamane
|
|
612
616
|
* @license MIT
|
|
613
617
|
* @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();
|
|
@@ -141,20 +141,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
const candidates = this.#getFocusables().filter(
|
|
145
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
146
|
+
);
|
|
144
147
|
const active = powerFocusable.getActiveElement();
|
|
145
148
|
if (!(active instanceof Element)) {
|
|
146
149
|
return;
|
|
147
150
|
}
|
|
148
|
-
const candidates = this.#getFocusables().filter(
|
|
149
|
-
(focusable2) => this.#focusables.has(focusable2)
|
|
150
|
-
);
|
|
151
151
|
if (!candidates.includes(active)) {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
154
154
|
event.preventDefault();
|
|
155
|
-
const activeIndex = candidates.indexOf(active);
|
|
156
155
|
let newIndex;
|
|
157
|
-
|
|
156
|
+
const activeIndex = candidates.indexOf(active);
|
|
157
|
+
let focusables = candidates;
|
|
158
158
|
switch (key) {
|
|
159
159
|
case "End":
|
|
160
160
|
newIndex = -1;
|
|
@@ -171,22 +171,24 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
171
171
|
case "ArrowRight":
|
|
172
172
|
case "ArrowDown": {
|
|
173
173
|
const rawIndex = activeIndex + 1;
|
|
174
|
-
const length =
|
|
174
|
+
const length = focusables.length;
|
|
175
175
|
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
176
176
|
break;
|
|
177
177
|
}
|
|
178
178
|
default: {
|
|
179
|
-
const
|
|
179
|
+
const focusablesByFirstChar = new Set(
|
|
180
180
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
181
181
|
);
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
focusables = candidates.filter(
|
|
183
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
184
|
+
);
|
|
185
|
+
const afterIndex = focusables.findIndex(
|
|
184
186
|
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
185
187
|
);
|
|
186
188
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
|
-
const focusable =
|
|
191
|
+
const focusable = focusables.at(newIndex);
|
|
190
192
|
focusable && powerFocusable.focusElement(focusable);
|
|
191
193
|
};
|
|
192
194
|
#update(active) {
|
|
@@ -194,7 +196,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
194
196
|
for (const focusable of this.#focusables) {
|
|
195
197
|
if (!current.has(focusable)) {
|
|
196
198
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
197
|
-
attributesUtils.restoreAttributes(
|
|
199
|
+
attributesUtils.restoreAttributes(focusable);
|
|
198
200
|
this.#focusables.delete(focusable);
|
|
199
201
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
200
202
|
const index = focusables.indexOf(focusable);
|
|
@@ -216,7 +218,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
216
218
|
this.#focusables.add(focusable);
|
|
217
219
|
_RovingTabIndex.#initialized.add(focusable);
|
|
218
220
|
if (!navigationOnly) {
|
|
219
|
-
attributesUtils.saveAttributes(
|
|
221
|
+
attributesUtils.saveAttributes(focusable, "tabindex");
|
|
220
222
|
focusable.setAttribute("tabindex", "-1");
|
|
221
223
|
}
|
|
222
224
|
if (!typeahead) {
|
|
@@ -229,7 +231,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
229
231
|
);
|
|
230
232
|
if (char) {
|
|
231
233
|
keys.add(char);
|
|
232
|
-
attributesUtils.saveAttributes(
|
|
234
|
+
attributesUtils.saveAttributes(focusable, "aria-keyshortcuts");
|
|
233
235
|
attributesUtils.addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
234
236
|
caseInsensitive: true
|
|
235
237
|
});
|
|
@@ -270,7 +272,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
270
272
|
* Lightweight roving tabindex utility with fully focus management.
|
|
271
273
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
272
274
|
*
|
|
273
|
-
* @version 3.1.
|
|
275
|
+
* @version 3.1.19
|
|
274
276
|
* @author Yusuke Kamiyamane
|
|
275
277
|
* @license MIT
|
|
276
278
|
* @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.19
|
|
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.19
|
|
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();
|
|
@@ -139,20 +139,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
139
139
|
return;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
const candidates = this.#getFocusables().filter(
|
|
143
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
144
|
+
);
|
|
142
145
|
const active = getActiveElement();
|
|
143
146
|
if (!(active instanceof Element)) {
|
|
144
147
|
return;
|
|
145
148
|
}
|
|
146
|
-
const candidates = this.#getFocusables().filter(
|
|
147
|
-
(focusable2) => this.#focusables.has(focusable2)
|
|
148
|
-
);
|
|
149
149
|
if (!candidates.includes(active)) {
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
event.preventDefault();
|
|
153
|
-
const activeIndex = candidates.indexOf(active);
|
|
154
153
|
let newIndex;
|
|
155
|
-
|
|
154
|
+
const activeIndex = candidates.indexOf(active);
|
|
155
|
+
let focusables = candidates;
|
|
156
156
|
switch (key) {
|
|
157
157
|
case "End":
|
|
158
158
|
newIndex = -1;
|
|
@@ -169,22 +169,24 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
169
169
|
case "ArrowRight":
|
|
170
170
|
case "ArrowDown": {
|
|
171
171
|
const rawIndex = activeIndex + 1;
|
|
172
|
-
const length =
|
|
172
|
+
const length = focusables.length;
|
|
173
173
|
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
174
174
|
break;
|
|
175
175
|
}
|
|
176
176
|
default: {
|
|
177
|
-
const
|
|
177
|
+
const focusablesByFirstChar = new Set(
|
|
178
178
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
179
179
|
);
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
focusables = candidates.filter(
|
|
181
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
182
|
+
);
|
|
183
|
+
const afterIndex = focusables.findIndex(
|
|
182
184
|
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
183
185
|
);
|
|
184
186
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
|
-
const focusable =
|
|
189
|
+
const focusable = focusables.at(newIndex);
|
|
188
190
|
focusable && focusElement(focusable);
|
|
189
191
|
};
|
|
190
192
|
#update(active) {
|
|
@@ -192,7 +194,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
192
194
|
for (const focusable of this.#focusables) {
|
|
193
195
|
if (!current.has(focusable)) {
|
|
194
196
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
195
|
-
restoreAttributes(
|
|
197
|
+
restoreAttributes(focusable);
|
|
196
198
|
this.#focusables.delete(focusable);
|
|
197
199
|
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
198
200
|
const index = focusables.indexOf(focusable);
|
|
@@ -214,7 +216,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
214
216
|
this.#focusables.add(focusable);
|
|
215
217
|
_RovingTabIndex.#initialized.add(focusable);
|
|
216
218
|
if (!navigationOnly) {
|
|
217
|
-
saveAttributes(
|
|
219
|
+
saveAttributes(focusable, "tabindex");
|
|
218
220
|
focusable.setAttribute("tabindex", "-1");
|
|
219
221
|
}
|
|
220
222
|
if (!typeahead) {
|
|
@@ -227,7 +229,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
227
229
|
);
|
|
228
230
|
if (char) {
|
|
229
231
|
keys.add(char);
|
|
230
|
-
saveAttributes(
|
|
232
|
+
saveAttributes(focusable, "aria-keyshortcuts");
|
|
231
233
|
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
232
234
|
caseInsensitive: true
|
|
233
235
|
});
|
|
@@ -268,7 +270,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
268
270
|
* Lightweight roving tabindex utility with fully focus management.
|
|
269
271
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
270
272
|
*
|
|
271
|
-
* @version 3.1.
|
|
273
|
+
* @version 3.1.19
|
|
272
274
|
* @author Yusuke Kamiyamane
|
|
273
275
|
* @license MIT
|
|
274
276
|
* @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.19",
|
|
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
|
}
|