@y14e/roving-tabindex 3.1.13 → 3.1.14
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 +47 -47
- package/dist/index.bundle.js +47 -47
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +22 -22
- package/package.json +2 -2
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.14';
|
|
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.14/+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.14';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## 📦 APIs
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -51,7 +51,7 @@ function saveAttributes(elements, attributes) {
|
|
|
51
51
|
|
|
52
52
|
// node_modules/power-focusable/dist/index.js
|
|
53
53
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
54
|
-
var
|
|
54
|
+
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
55
55
|
/(,\s*)?\[tabindex="-1"\]/g,
|
|
56
56
|
""
|
|
57
57
|
);
|
|
@@ -113,7 +113,7 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
113
113
|
}
|
|
114
114
|
} else {
|
|
115
115
|
const candidates = container.querySelectorAll(
|
|
116
|
-
skipNegativeTabIndexCheck ?
|
|
116
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
117
117
|
);
|
|
118
118
|
for (let i = 0, l = candidates.length; i < l; i++) {
|
|
119
119
|
const candidate = candidates[i];
|
|
@@ -149,7 +149,7 @@ function isFocusable(element, options = {}) {
|
|
|
149
149
|
return false;
|
|
150
150
|
}
|
|
151
151
|
if (!element.matches(
|
|
152
|
-
skipNegativeTabIndexCheck ?
|
|
152
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
153
153
|
)) {
|
|
154
154
|
return false;
|
|
155
155
|
}
|
|
@@ -195,7 +195,7 @@ function isDisabledDeep(element) {
|
|
|
195
195
|
return false;
|
|
196
196
|
}
|
|
197
197
|
function normalizeRadioGroup(elements) {
|
|
198
|
-
let
|
|
198
|
+
let map = null;
|
|
199
199
|
for (let i = 0, l = elements.length; i < l; i++) {
|
|
200
200
|
const element = elements[i];
|
|
201
201
|
if (!(element instanceof HTMLInputElement)) {
|
|
@@ -204,35 +204,35 @@ function normalizeRadioGroup(elements) {
|
|
|
204
204
|
if (!isUngroupedRadio(element)) {
|
|
205
205
|
continue;
|
|
206
206
|
}
|
|
207
|
-
if (!
|
|
208
|
-
|
|
207
|
+
if (!map) {
|
|
208
|
+
map = /* @__PURE__ */ new Map();
|
|
209
209
|
}
|
|
210
210
|
const root = element.getRootNode();
|
|
211
|
-
let
|
|
212
|
-
if (!
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
let value = map.get(root);
|
|
212
|
+
if (!value) {
|
|
213
|
+
value = /* @__PURE__ */ new Map();
|
|
214
|
+
map.set(root, value);
|
|
215
215
|
}
|
|
216
|
-
let
|
|
217
|
-
if (!
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
let v = value.get(element.form);
|
|
217
|
+
if (!v) {
|
|
218
|
+
v = /* @__PURE__ */ new Map();
|
|
219
|
+
value.set(element.form, v);
|
|
220
220
|
}
|
|
221
|
-
let
|
|
222
|
-
if (!
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
let vv = v.get(element.name);
|
|
222
|
+
if (!vv) {
|
|
223
|
+
vv = [];
|
|
224
|
+
v.set(element.name, vv);
|
|
225
225
|
}
|
|
226
|
-
|
|
226
|
+
vv[vv.length] = element;
|
|
227
227
|
}
|
|
228
|
-
if (!
|
|
228
|
+
if (!map) {
|
|
229
229
|
return elements;
|
|
230
230
|
}
|
|
231
231
|
const placeholder = /* @__PURE__ */ new Set();
|
|
232
|
-
for (const
|
|
233
|
-
for (const
|
|
234
|
-
for (const
|
|
235
|
-
const radio =
|
|
232
|
+
for (const value of map.values()) {
|
|
233
|
+
for (const v of value.values()) {
|
|
234
|
+
for (const vv of v.values()) {
|
|
235
|
+
const radio = vv.find((element) => element.checked) ?? vv[0];
|
|
236
236
|
radio && placeholder.add(radio);
|
|
237
237
|
}
|
|
238
238
|
}
|
|
@@ -459,16 +459,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
459
459
|
if (!(active instanceof Element)) {
|
|
460
460
|
return;
|
|
461
461
|
}
|
|
462
|
-
const
|
|
462
|
+
const candidates = this.#getFocusables().filter(
|
|
463
463
|
(focusable2) => this.#focusables.has(focusable2)
|
|
464
464
|
);
|
|
465
|
-
if (!
|
|
465
|
+
if (!candidates.includes(active)) {
|
|
466
466
|
return;
|
|
467
467
|
}
|
|
468
468
|
event.preventDefault();
|
|
469
|
-
const
|
|
469
|
+
const activeIndex = candidates.indexOf(active);
|
|
470
470
|
let newIndex;
|
|
471
|
-
let target =
|
|
471
|
+
let target = candidates;
|
|
472
472
|
switch (key) {
|
|
473
473
|
case "End":
|
|
474
474
|
newIndex = -1;
|
|
@@ -478,48 +478,48 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
478
478
|
break;
|
|
479
479
|
case "ArrowLeft":
|
|
480
480
|
case "ArrowUp": {
|
|
481
|
-
const rawIndex =
|
|
481
|
+
const rawIndex = activeIndex - 1;
|
|
482
482
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
483
483
|
break;
|
|
484
484
|
}
|
|
485
485
|
case "ArrowRight":
|
|
486
486
|
case "ArrowDown": {
|
|
487
|
-
const rawIndex =
|
|
488
|
-
newIndex = wrap ? rawIndex %
|
|
487
|
+
const rawIndex = activeIndex + 1;
|
|
488
|
+
newIndex = wrap ? rawIndex % candidates.length : Math.min(rawIndex, candidates.length - 1);
|
|
489
489
|
break;
|
|
490
490
|
}
|
|
491
491
|
default: {
|
|
492
492
|
const focusables = new Set(
|
|
493
493
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
494
494
|
);
|
|
495
|
-
target =
|
|
496
|
-
const
|
|
497
|
-
(focusable2) =>
|
|
495
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
496
|
+
const afterIndex = target.findIndex(
|
|
497
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
498
498
|
);
|
|
499
|
-
newIndex =
|
|
499
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
500
500
|
}
|
|
501
501
|
}
|
|
502
502
|
const focusable = target.at(newIndex);
|
|
503
503
|
focusable && focusElement(focusable);
|
|
504
504
|
};
|
|
505
505
|
#update(active) {
|
|
506
|
-
const
|
|
506
|
+
const focusables = new Set(this.#getFocusables());
|
|
507
507
|
for (const focusable of this.#focusables) {
|
|
508
|
-
if (!
|
|
508
|
+
if (!focusables.has(focusable)) {
|
|
509
509
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
510
510
|
restoreAttributes([focusable]);
|
|
511
511
|
this.#focusables.delete(focusable);
|
|
512
|
-
for (const [key,
|
|
513
|
-
const index =
|
|
512
|
+
for (const [key, focusables2] of this.#focusablesByFirstChar) {
|
|
513
|
+
const index = focusables2.indexOf(focusable);
|
|
514
514
|
if (index >= 0) {
|
|
515
|
-
|
|
516
|
-
!
|
|
515
|
+
focusables2.splice(index, 1);
|
|
516
|
+
!focusables2.length && this.#focusablesByFirstChar.delete(key);
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
522
|
-
for (const focusable of
|
|
522
|
+
for (const focusable of focusables) {
|
|
523
523
|
if (this.#focusables.has(focusable)) {
|
|
524
524
|
continue;
|
|
525
525
|
}
|
|
@@ -548,9 +548,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
548
548
|
});
|
|
549
549
|
}
|
|
550
550
|
keys.forEach((key) => {
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
this.#focusablesByFirstChar.set(key,
|
|
551
|
+
const focusables2 = this.#focusablesByFirstChar.get(key) ?? [];
|
|
552
|
+
focusables2.push(focusable);
|
|
553
|
+
this.#focusablesByFirstChar.set(key, focusables2);
|
|
554
554
|
});
|
|
555
555
|
}
|
|
556
556
|
if (!navigationOnly) {
|
|
@@ -583,7 +583,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
583
583
|
* Lightweight roving tabindex utility with fully focus management.
|
|
584
584
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
585
585
|
*
|
|
586
|
-
* @version 3.1.
|
|
586
|
+
* @version 3.1.14
|
|
587
587
|
* @author Yusuke Kamiyamane
|
|
588
588
|
* @license MIT
|
|
589
589
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -608,7 +608,7 @@ power-focusable/dist/index.js:
|
|
|
608
608
|
* High-precision focus management utility with full composed tree support.
|
|
609
609
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
610
610
|
*
|
|
611
|
-
* @version 4.3.
|
|
611
|
+
* @version 4.3.18
|
|
612
612
|
* @author Yusuke Kamiyamane
|
|
613
613
|
* @license MIT
|
|
614
614
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -49,7 +49,7 @@ function saveAttributes(elements, attributes) {
|
|
|
49
49
|
|
|
50
50
|
// node_modules/power-focusable/dist/index.js
|
|
51
51
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
52
|
-
var
|
|
52
|
+
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
53
53
|
/(,\s*)?\[tabindex="-1"\]/g,
|
|
54
54
|
""
|
|
55
55
|
);
|
|
@@ -111,7 +111,7 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
111
111
|
}
|
|
112
112
|
} else {
|
|
113
113
|
const candidates = container.querySelectorAll(
|
|
114
|
-
skipNegativeTabIndexCheck ?
|
|
114
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
115
115
|
);
|
|
116
116
|
for (let i = 0, l = candidates.length; i < l; i++) {
|
|
117
117
|
const candidate = candidates[i];
|
|
@@ -147,7 +147,7 @@ function isFocusable(element, options = {}) {
|
|
|
147
147
|
return false;
|
|
148
148
|
}
|
|
149
149
|
if (!element.matches(
|
|
150
|
-
skipNegativeTabIndexCheck ?
|
|
150
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
151
151
|
)) {
|
|
152
152
|
return false;
|
|
153
153
|
}
|
|
@@ -193,7 +193,7 @@ function isDisabledDeep(element) {
|
|
|
193
193
|
return false;
|
|
194
194
|
}
|
|
195
195
|
function normalizeRadioGroup(elements) {
|
|
196
|
-
let
|
|
196
|
+
let map = null;
|
|
197
197
|
for (let i = 0, l = elements.length; i < l; i++) {
|
|
198
198
|
const element = elements[i];
|
|
199
199
|
if (!(element instanceof HTMLInputElement)) {
|
|
@@ -202,35 +202,35 @@ function normalizeRadioGroup(elements) {
|
|
|
202
202
|
if (!isUngroupedRadio(element)) {
|
|
203
203
|
continue;
|
|
204
204
|
}
|
|
205
|
-
if (!
|
|
206
|
-
|
|
205
|
+
if (!map) {
|
|
206
|
+
map = /* @__PURE__ */ new Map();
|
|
207
207
|
}
|
|
208
208
|
const root = element.getRootNode();
|
|
209
|
-
let
|
|
210
|
-
if (!
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
let value = map.get(root);
|
|
210
|
+
if (!value) {
|
|
211
|
+
value = /* @__PURE__ */ new Map();
|
|
212
|
+
map.set(root, value);
|
|
213
213
|
}
|
|
214
|
-
let
|
|
215
|
-
if (!
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
let v = value.get(element.form);
|
|
215
|
+
if (!v) {
|
|
216
|
+
v = /* @__PURE__ */ new Map();
|
|
217
|
+
value.set(element.form, v);
|
|
218
218
|
}
|
|
219
|
-
let
|
|
220
|
-
if (!
|
|
221
|
-
|
|
222
|
-
|
|
219
|
+
let vv = v.get(element.name);
|
|
220
|
+
if (!vv) {
|
|
221
|
+
vv = [];
|
|
222
|
+
v.set(element.name, vv);
|
|
223
223
|
}
|
|
224
|
-
|
|
224
|
+
vv[vv.length] = element;
|
|
225
225
|
}
|
|
226
|
-
if (!
|
|
226
|
+
if (!map) {
|
|
227
227
|
return elements;
|
|
228
228
|
}
|
|
229
229
|
const placeholder = /* @__PURE__ */ new Set();
|
|
230
|
-
for (const
|
|
231
|
-
for (const
|
|
232
|
-
for (const
|
|
233
|
-
const radio =
|
|
230
|
+
for (const value of map.values()) {
|
|
231
|
+
for (const v of value.values()) {
|
|
232
|
+
for (const vv of v.values()) {
|
|
233
|
+
const radio = vv.find((element) => element.checked) ?? vv[0];
|
|
234
234
|
radio && placeholder.add(radio);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
@@ -457,16 +457,16 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
457
457
|
if (!(active instanceof Element)) {
|
|
458
458
|
return;
|
|
459
459
|
}
|
|
460
|
-
const
|
|
460
|
+
const candidates = this.#getFocusables().filter(
|
|
461
461
|
(focusable2) => this.#focusables.has(focusable2)
|
|
462
462
|
);
|
|
463
|
-
if (!
|
|
463
|
+
if (!candidates.includes(active)) {
|
|
464
464
|
return;
|
|
465
465
|
}
|
|
466
466
|
event.preventDefault();
|
|
467
|
-
const
|
|
467
|
+
const activeIndex = candidates.indexOf(active);
|
|
468
468
|
let newIndex;
|
|
469
|
-
let target =
|
|
469
|
+
let target = candidates;
|
|
470
470
|
switch (key) {
|
|
471
471
|
case "End":
|
|
472
472
|
newIndex = -1;
|
|
@@ -476,48 +476,48 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
476
476
|
break;
|
|
477
477
|
case "ArrowLeft":
|
|
478
478
|
case "ArrowUp": {
|
|
479
|
-
const rawIndex =
|
|
479
|
+
const rawIndex = activeIndex - 1;
|
|
480
480
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
481
481
|
break;
|
|
482
482
|
}
|
|
483
483
|
case "ArrowRight":
|
|
484
484
|
case "ArrowDown": {
|
|
485
|
-
const rawIndex =
|
|
486
|
-
newIndex = wrap ? rawIndex %
|
|
485
|
+
const rawIndex = activeIndex + 1;
|
|
486
|
+
newIndex = wrap ? rawIndex % candidates.length : Math.min(rawIndex, candidates.length - 1);
|
|
487
487
|
break;
|
|
488
488
|
}
|
|
489
489
|
default: {
|
|
490
490
|
const focusables = new Set(
|
|
491
491
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
492
492
|
);
|
|
493
|
-
target =
|
|
494
|
-
const
|
|
495
|
-
(focusable2) =>
|
|
493
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
494
|
+
const afterIndex = target.findIndex(
|
|
495
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
496
496
|
);
|
|
497
|
-
newIndex =
|
|
497
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
498
498
|
}
|
|
499
499
|
}
|
|
500
500
|
const focusable = target.at(newIndex);
|
|
501
501
|
focusable && focusElement(focusable);
|
|
502
502
|
};
|
|
503
503
|
#update(active) {
|
|
504
|
-
const
|
|
504
|
+
const focusables = new Set(this.#getFocusables());
|
|
505
505
|
for (const focusable of this.#focusables) {
|
|
506
|
-
if (!
|
|
506
|
+
if (!focusables.has(focusable)) {
|
|
507
507
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
508
508
|
restoreAttributes([focusable]);
|
|
509
509
|
this.#focusables.delete(focusable);
|
|
510
|
-
for (const [key,
|
|
511
|
-
const index =
|
|
510
|
+
for (const [key, focusables2] of this.#focusablesByFirstChar) {
|
|
511
|
+
const index = focusables2.indexOf(focusable);
|
|
512
512
|
if (index >= 0) {
|
|
513
|
-
|
|
514
|
-
!
|
|
513
|
+
focusables2.splice(index, 1);
|
|
514
|
+
!focusables2.length && this.#focusablesByFirstChar.delete(key);
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
519
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
520
|
-
for (const focusable of
|
|
520
|
+
for (const focusable of focusables) {
|
|
521
521
|
if (this.#focusables.has(focusable)) {
|
|
522
522
|
continue;
|
|
523
523
|
}
|
|
@@ -546,9 +546,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
546
546
|
});
|
|
547
547
|
}
|
|
548
548
|
keys.forEach((key) => {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
this.#focusablesByFirstChar.set(key,
|
|
549
|
+
const focusables2 = this.#focusablesByFirstChar.get(key) ?? [];
|
|
550
|
+
focusables2.push(focusable);
|
|
551
|
+
this.#focusablesByFirstChar.set(key, focusables2);
|
|
552
552
|
});
|
|
553
553
|
}
|
|
554
554
|
if (!navigationOnly) {
|
|
@@ -581,7 +581,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
581
581
|
* Lightweight roving tabindex utility with fully focus management.
|
|
582
582
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
583
583
|
*
|
|
584
|
-
* @version 3.1.
|
|
584
|
+
* @version 3.1.14
|
|
585
585
|
* @author Yusuke Kamiyamane
|
|
586
586
|
* @license MIT
|
|
587
587
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -606,7 +606,7 @@ power-focusable/dist/index.js:
|
|
|
606
606
|
* High-precision focus management utility with full composed tree support.
|
|
607
607
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
608
608
|
*
|
|
609
|
-
* @version 4.3.
|
|
609
|
+
* @version 4.3.18
|
|
610
610
|
* @author Yusuke Kamiyamane
|
|
611
611
|
* @license MIT
|
|
612
612
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -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,48 +164,48 @@ 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
|
-
newIndex = wrap ? rawIndex %
|
|
173
|
+
const rawIndex = activeIndex + 1;
|
|
174
|
+
newIndex = wrap ? rawIndex % candidates.length : Math.min(rawIndex, candidates.length - 1);
|
|
175
175
|
break;
|
|
176
176
|
}
|
|
177
177
|
default: {
|
|
178
178
|
const focusables = new Set(
|
|
179
179
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
180
180
|
);
|
|
181
|
-
target =
|
|
182
|
-
const
|
|
183
|
-
(focusable2) =>
|
|
181
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
182
|
+
const afterIndex = target.findIndex(
|
|
183
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
184
184
|
);
|
|
185
|
-
newIndex =
|
|
185
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
const focusable = target.at(newIndex);
|
|
189
189
|
focusable && powerFocusable.focusElement(focusable);
|
|
190
190
|
};
|
|
191
191
|
#update(active) {
|
|
192
|
-
const
|
|
192
|
+
const focusables = new Set(this.#getFocusables());
|
|
193
193
|
for (const focusable of this.#focusables) {
|
|
194
|
-
if (!
|
|
194
|
+
if (!focusables.has(focusable)) {
|
|
195
195
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
196
196
|
attributesUtils.restoreAttributes([focusable]);
|
|
197
197
|
this.#focusables.delete(focusable);
|
|
198
|
-
for (const [key,
|
|
199
|
-
const index =
|
|
198
|
+
for (const [key, focusables2] of this.#focusablesByFirstChar) {
|
|
199
|
+
const index = focusables2.indexOf(focusable);
|
|
200
200
|
if (index >= 0) {
|
|
201
|
-
|
|
202
|
-
!
|
|
201
|
+
focusables2.splice(index, 1);
|
|
202
|
+
!focusables2.length && this.#focusablesByFirstChar.delete(key);
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
208
|
-
for (const focusable of
|
|
208
|
+
for (const focusable of focusables) {
|
|
209
209
|
if (this.#focusables.has(focusable)) {
|
|
210
210
|
continue;
|
|
211
211
|
}
|
|
@@ -234,9 +234,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
234
234
|
});
|
|
235
235
|
}
|
|
236
236
|
keys.forEach((key) => {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
this.#focusablesByFirstChar.set(key,
|
|
237
|
+
const focusables2 = this.#focusablesByFirstChar.get(key) ?? [];
|
|
238
|
+
focusables2.push(focusable);
|
|
239
|
+
this.#focusablesByFirstChar.set(key, focusables2);
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
242
|
if (!navigationOnly) {
|
|
@@ -269,7 +269,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
269
269
|
* Lightweight roving tabindex utility with fully focus management.
|
|
270
270
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
271
271
|
*
|
|
272
|
-
* @version 3.1.
|
|
272
|
+
* @version 3.1.14
|
|
273
273
|
* @author Yusuke Kamiyamane
|
|
274
274
|
* @license MIT
|
|
275
275
|
* @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.14
|
|
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.14
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -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,48 +162,48 @@ 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
|
-
newIndex = wrap ? rawIndex %
|
|
171
|
+
const rawIndex = activeIndex + 1;
|
|
172
|
+
newIndex = wrap ? rawIndex % candidates.length : Math.min(rawIndex, candidates.length - 1);
|
|
173
173
|
break;
|
|
174
174
|
}
|
|
175
175
|
default: {
|
|
176
176
|
const focusables = new Set(
|
|
177
177
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
178
178
|
);
|
|
179
|
-
target =
|
|
180
|
-
const
|
|
181
|
-
(focusable2) =>
|
|
179
|
+
target = candidates.filter((focusable2) => focusables.has(focusable2));
|
|
180
|
+
const afterIndex = target.findIndex(
|
|
181
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
182
182
|
);
|
|
183
|
-
newIndex =
|
|
183
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
const focusable = target.at(newIndex);
|
|
187
187
|
focusable && focusElement(focusable);
|
|
188
188
|
};
|
|
189
189
|
#update(active) {
|
|
190
|
-
const
|
|
190
|
+
const focusables = new Set(this.#getFocusables());
|
|
191
191
|
for (const focusable of this.#focusables) {
|
|
192
|
-
if (!
|
|
192
|
+
if (!focusables.has(focusable)) {
|
|
193
193
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
194
194
|
restoreAttributes([focusable]);
|
|
195
195
|
this.#focusables.delete(focusable);
|
|
196
|
-
for (const [key,
|
|
197
|
-
const index =
|
|
196
|
+
for (const [key, focusables2] of this.#focusablesByFirstChar) {
|
|
197
|
+
const index = focusables2.indexOf(focusable);
|
|
198
198
|
if (index >= 0) {
|
|
199
|
-
|
|
200
|
-
!
|
|
199
|
+
focusables2.splice(index, 1);
|
|
200
|
+
!focusables2.length && this.#focusablesByFirstChar.delete(key);
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
205
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
206
|
-
for (const focusable of
|
|
206
|
+
for (const focusable of focusables) {
|
|
207
207
|
if (this.#focusables.has(focusable)) {
|
|
208
208
|
continue;
|
|
209
209
|
}
|
|
@@ -232,9 +232,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
232
232
|
});
|
|
233
233
|
}
|
|
234
234
|
keys.forEach((key) => {
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
this.#focusablesByFirstChar.set(key,
|
|
235
|
+
const focusables2 = this.#focusablesByFirstChar.get(key) ?? [];
|
|
236
|
+
focusables2.push(focusable);
|
|
237
|
+
this.#focusablesByFirstChar.set(key, focusables2);
|
|
238
238
|
});
|
|
239
239
|
}
|
|
240
240
|
if (!navigationOnly) {
|
|
@@ -267,7 +267,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
267
267
|
* Lightweight roving tabindex utility with fully focus management.
|
|
268
268
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
269
269
|
*
|
|
270
|
-
* @version 3.1.
|
|
270
|
+
* @version 3.1.14
|
|
271
271
|
* @author Yusuke Kamiyamane
|
|
272
272
|
* @license MIT
|
|
273
273
|
* @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.14",
|
|
4
4
|
"description": "Lightweight roving tabindex utility with fully focus management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -57,6 +57,6 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@y14e/attributes-utils": "^1.1.3",
|
|
60
|
-
"power-focusable": "^4.3.
|
|
60
|
+
"power-focusable": "^4.3.18"
|
|
61
61
|
}
|
|
62
62
|
}
|