@y14e/roving-tabindex 3.1.0 → 3.1.1
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 +4 -4
- package/dist/index.bundle.cjs +7 -120
- package/dist/index.bundle.js +7 -120
- package/dist/index.cjs +7 -25
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/roving-tabindex
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import { createRovingTabIndex } from '@y14e/roving-tabindex@3.1.
|
|
13
|
+
import { createRovingTabIndex } from '@y14e/roving-tabindex@3.1.1';
|
|
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.1';
|
|
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.1/+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.1';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## 📦 APIs
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -118,12 +118,6 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
118
118
|
const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
|
|
119
119
|
return filter ? unfiltered.filter(filter) : unfiltered;
|
|
120
120
|
}
|
|
121
|
-
function getNextFocusable(container = document.body, options = {}) {
|
|
122
|
-
return getRelativeFocusable(container, 1, options);
|
|
123
|
-
}
|
|
124
|
-
function getPreviousFocusable(container = document.body, options = {}) {
|
|
125
|
-
return getRelativeFocusable(container, -1, options);
|
|
126
|
-
}
|
|
127
121
|
function isFocusable(element, options = {}) {
|
|
128
122
|
if (!(element instanceof Element)) {
|
|
129
123
|
console.warn("Invalid element");
|
|
@@ -161,84 +155,6 @@ function isFocusable(element, options = {}) {
|
|
|
161
155
|
}
|
|
162
156
|
return true;
|
|
163
157
|
}
|
|
164
|
-
function getRelativeFocusable(container, offset, options) {
|
|
165
|
-
if (!(container instanceof Element)) {
|
|
166
|
-
console.warn("Invalid container element. Fallback: <body> element.");
|
|
167
|
-
container = document.body;
|
|
168
|
-
}
|
|
169
|
-
let {
|
|
170
|
-
anchor = getActiveElement(),
|
|
171
|
-
composed = false,
|
|
172
|
-
filter,
|
|
173
|
-
include,
|
|
174
|
-
skipNegativeTabIndexCheck = false,
|
|
175
|
-
skipVisibilityCheck = false,
|
|
176
|
-
wrap = false
|
|
177
|
-
} = options;
|
|
178
|
-
if (!(anchor instanceof Element)) {
|
|
179
|
-
const active = getActiveElement();
|
|
180
|
-
if (active instanceof Element) {
|
|
181
|
-
console.warn("Invalid anchor element. Fallback: active element.");
|
|
182
|
-
anchor = active;
|
|
183
|
-
} else {
|
|
184
|
-
console.warn("Invalid anchor element");
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
if (!containsComposed(container, anchor)) {
|
|
189
|
-
console.warn("Anchor (active) element not within container");
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
if (typeof composed !== "boolean") {
|
|
193
|
-
console.warn("Invalid composed option. Fallback: false.");
|
|
194
|
-
composed = false;
|
|
195
|
-
}
|
|
196
|
-
if (typeof filter !== "undefined" && typeof filter !== "function") {
|
|
197
|
-
console.warn(
|
|
198
|
-
"Invalid filter function. Fallback: no filter function (undefined)."
|
|
199
|
-
);
|
|
200
|
-
filter = void 0;
|
|
201
|
-
}
|
|
202
|
-
if (typeof include !== "undefined" && typeof include !== "function") {
|
|
203
|
-
console.warn(
|
|
204
|
-
"Invalid include function. Fallback: no include function (undefined)."
|
|
205
|
-
);
|
|
206
|
-
include = void 0;
|
|
207
|
-
}
|
|
208
|
-
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
209
|
-
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
210
|
-
skipNegativeTabIndexCheck = false;
|
|
211
|
-
}
|
|
212
|
-
if (typeof skipVisibilityCheck !== "boolean") {
|
|
213
|
-
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
214
|
-
skipVisibilityCheck = false;
|
|
215
|
-
}
|
|
216
|
-
if (typeof wrap !== "boolean") {
|
|
217
|
-
console.warn("Invalid wrap option. Fallback: false.");
|
|
218
|
-
wrap = false;
|
|
219
|
-
}
|
|
220
|
-
const settings = { composed, skipNegativeTabIndexCheck, skipVisibilityCheck };
|
|
221
|
-
if (filter !== void 0) {
|
|
222
|
-
Object.assign(settings, { filter });
|
|
223
|
-
}
|
|
224
|
-
if (include !== void 0) {
|
|
225
|
-
Object.assign(settings, { include });
|
|
226
|
-
}
|
|
227
|
-
const focusables = getFocusables(container, settings);
|
|
228
|
-
const { length } = focusables;
|
|
229
|
-
if (!length) {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
const currentIndex = focusables.indexOf(anchor);
|
|
233
|
-
if (currentIndex === -1) {
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
const offsetIndex = currentIndex + offset;
|
|
237
|
-
if ((offsetIndex < 0 || offsetIndex >= length) && !wrap) {
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
return focusables[(offsetIndex + length) % length] ?? null;
|
|
241
|
-
}
|
|
242
158
|
function isDisabledDeep(element) {
|
|
243
159
|
let current = element;
|
|
244
160
|
while (current) {
|
|
@@ -319,17 +235,6 @@ function sortByTabIndex(elements) {
|
|
|
319
235
|
}
|
|
320
236
|
return sorted;
|
|
321
237
|
}
|
|
322
|
-
function containsComposed(container, element) {
|
|
323
|
-
let current = element;
|
|
324
|
-
while (current) {
|
|
325
|
-
if (current === container) {
|
|
326
|
-
return true;
|
|
327
|
-
} else {
|
|
328
|
-
current = current instanceof ShadowRoot ? current.mode === "open" ? current.host : null : current.parentNode;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
238
|
function getComposedChildren(node) {
|
|
334
239
|
if (node instanceof ShadowRoot) {
|
|
335
240
|
return getChildren(node);
|
|
@@ -506,14 +411,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
506
411
|
};
|
|
507
412
|
#onKeyDown = (event) => {
|
|
508
413
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
509
|
-
if (
|
|
414
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
510
415
|
return;
|
|
511
416
|
}
|
|
512
417
|
const { direction, typeahead, wrap } = this.#settings;
|
|
513
418
|
const isBoth = !direction;
|
|
514
419
|
const isHorizontal = direction === "horizontal";
|
|
515
420
|
if (![
|
|
516
|
-
"Tab",
|
|
517
421
|
"End",
|
|
518
422
|
"Home",
|
|
519
423
|
...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
|
|
@@ -531,14 +435,11 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
531
435
|
if (!current.includes(active)) {
|
|
532
436
|
return;
|
|
533
437
|
}
|
|
534
|
-
|
|
438
|
+
event.preventDefault();
|
|
535
439
|
const currentIndex = current.indexOf(active);
|
|
536
|
-
let newIndex
|
|
440
|
+
let newIndex;
|
|
537
441
|
let target = current;
|
|
538
442
|
switch (key) {
|
|
539
|
-
case "Tab":
|
|
540
|
-
shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
|
|
541
|
-
break;
|
|
542
443
|
case "End":
|
|
543
444
|
newIndex = -1;
|
|
544
445
|
break;
|
|
@@ -560,16 +461,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
560
461
|
default: {
|
|
561
462
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
562
463
|
const foundIndex = target.findIndex(
|
|
563
|
-
(
|
|
464
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
564
465
|
);
|
|
565
466
|
newIndex = foundIndex >= 0 ? foundIndex : 0;
|
|
566
467
|
}
|
|
567
468
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
const focusable = target.at(newIndex);
|
|
571
|
-
focusable && focusElement(focusable);
|
|
572
|
-
}
|
|
469
|
+
const focusable = target.at(newIndex);
|
|
470
|
+
focusable && focusElement(focusable);
|
|
573
471
|
};
|
|
574
472
|
#update(active) {
|
|
575
473
|
const current = new Set(this.#getFocusables());
|
|
@@ -642,24 +540,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
642
540
|
skipVisibilityCheck: true
|
|
643
541
|
});
|
|
644
542
|
}
|
|
645
|
-
#moveFocus(direction) {
|
|
646
|
-
const options = {
|
|
647
|
-
composed: true
|
|
648
|
-
};
|
|
649
|
-
const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
|
|
650
|
-
if (focusable) {
|
|
651
|
-
focusElement(focusable);
|
|
652
|
-
return true;
|
|
653
|
-
}
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
543
|
};
|
|
657
544
|
/**
|
|
658
545
|
* Roving Tabindex
|
|
659
546
|
* Lightweight roving tabindex utility with fully focus management.
|
|
660
547
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
661
548
|
*
|
|
662
|
-
* @version 3.1.
|
|
549
|
+
* @version 3.1.1
|
|
663
550
|
* @author Yusuke Kamiyamane
|
|
664
551
|
* @license MIT
|
|
665
552
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -116,12 +116,6 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
116
116
|
const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
|
|
117
117
|
return filter ? unfiltered.filter(filter) : unfiltered;
|
|
118
118
|
}
|
|
119
|
-
function getNextFocusable(container = document.body, options = {}) {
|
|
120
|
-
return getRelativeFocusable(container, 1, options);
|
|
121
|
-
}
|
|
122
|
-
function getPreviousFocusable(container = document.body, options = {}) {
|
|
123
|
-
return getRelativeFocusable(container, -1, options);
|
|
124
|
-
}
|
|
125
119
|
function isFocusable(element, options = {}) {
|
|
126
120
|
if (!(element instanceof Element)) {
|
|
127
121
|
console.warn("Invalid element");
|
|
@@ -159,84 +153,6 @@ function isFocusable(element, options = {}) {
|
|
|
159
153
|
}
|
|
160
154
|
return true;
|
|
161
155
|
}
|
|
162
|
-
function getRelativeFocusable(container, offset, options) {
|
|
163
|
-
if (!(container instanceof Element)) {
|
|
164
|
-
console.warn("Invalid container element. Fallback: <body> element.");
|
|
165
|
-
container = document.body;
|
|
166
|
-
}
|
|
167
|
-
let {
|
|
168
|
-
anchor = getActiveElement(),
|
|
169
|
-
composed = false,
|
|
170
|
-
filter,
|
|
171
|
-
include,
|
|
172
|
-
skipNegativeTabIndexCheck = false,
|
|
173
|
-
skipVisibilityCheck = false,
|
|
174
|
-
wrap = false
|
|
175
|
-
} = options;
|
|
176
|
-
if (!(anchor instanceof Element)) {
|
|
177
|
-
const active = getActiveElement();
|
|
178
|
-
if (active instanceof Element) {
|
|
179
|
-
console.warn("Invalid anchor element. Fallback: active element.");
|
|
180
|
-
anchor = active;
|
|
181
|
-
} else {
|
|
182
|
-
console.warn("Invalid anchor element");
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (!containsComposed(container, anchor)) {
|
|
187
|
-
console.warn("Anchor (active) element not within container");
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
if (typeof composed !== "boolean") {
|
|
191
|
-
console.warn("Invalid composed option. Fallback: false.");
|
|
192
|
-
composed = false;
|
|
193
|
-
}
|
|
194
|
-
if (typeof filter !== "undefined" && typeof filter !== "function") {
|
|
195
|
-
console.warn(
|
|
196
|
-
"Invalid filter function. Fallback: no filter function (undefined)."
|
|
197
|
-
);
|
|
198
|
-
filter = void 0;
|
|
199
|
-
}
|
|
200
|
-
if (typeof include !== "undefined" && typeof include !== "function") {
|
|
201
|
-
console.warn(
|
|
202
|
-
"Invalid include function. Fallback: no include function (undefined)."
|
|
203
|
-
);
|
|
204
|
-
include = void 0;
|
|
205
|
-
}
|
|
206
|
-
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
207
|
-
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
208
|
-
skipNegativeTabIndexCheck = false;
|
|
209
|
-
}
|
|
210
|
-
if (typeof skipVisibilityCheck !== "boolean") {
|
|
211
|
-
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
212
|
-
skipVisibilityCheck = false;
|
|
213
|
-
}
|
|
214
|
-
if (typeof wrap !== "boolean") {
|
|
215
|
-
console.warn("Invalid wrap option. Fallback: false.");
|
|
216
|
-
wrap = false;
|
|
217
|
-
}
|
|
218
|
-
const settings = { composed, skipNegativeTabIndexCheck, skipVisibilityCheck };
|
|
219
|
-
if (filter !== void 0) {
|
|
220
|
-
Object.assign(settings, { filter });
|
|
221
|
-
}
|
|
222
|
-
if (include !== void 0) {
|
|
223
|
-
Object.assign(settings, { include });
|
|
224
|
-
}
|
|
225
|
-
const focusables = getFocusables(container, settings);
|
|
226
|
-
const { length } = focusables;
|
|
227
|
-
if (!length) {
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
const currentIndex = focusables.indexOf(anchor);
|
|
231
|
-
if (currentIndex === -1) {
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
const offsetIndex = currentIndex + offset;
|
|
235
|
-
if ((offsetIndex < 0 || offsetIndex >= length) && !wrap) {
|
|
236
|
-
return null;
|
|
237
|
-
}
|
|
238
|
-
return focusables[(offsetIndex + length) % length] ?? null;
|
|
239
|
-
}
|
|
240
156
|
function isDisabledDeep(element) {
|
|
241
157
|
let current = element;
|
|
242
158
|
while (current) {
|
|
@@ -317,17 +233,6 @@ function sortByTabIndex(elements) {
|
|
|
317
233
|
}
|
|
318
234
|
return sorted;
|
|
319
235
|
}
|
|
320
|
-
function containsComposed(container, element) {
|
|
321
|
-
let current = element;
|
|
322
|
-
while (current) {
|
|
323
|
-
if (current === container) {
|
|
324
|
-
return true;
|
|
325
|
-
} else {
|
|
326
|
-
current = current instanceof ShadowRoot ? current.mode === "open" ? current.host : null : current.parentNode;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
236
|
function getComposedChildren(node) {
|
|
332
237
|
if (node instanceof ShadowRoot) {
|
|
333
238
|
return getChildren(node);
|
|
@@ -504,14 +409,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
504
409
|
};
|
|
505
410
|
#onKeyDown = (event) => {
|
|
506
411
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
507
|
-
if (
|
|
412
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
508
413
|
return;
|
|
509
414
|
}
|
|
510
415
|
const { direction, typeahead, wrap } = this.#settings;
|
|
511
416
|
const isBoth = !direction;
|
|
512
417
|
const isHorizontal = direction === "horizontal";
|
|
513
418
|
if (![
|
|
514
|
-
"Tab",
|
|
515
419
|
"End",
|
|
516
420
|
"Home",
|
|
517
421
|
...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
|
|
@@ -529,14 +433,11 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
529
433
|
if (!current.includes(active)) {
|
|
530
434
|
return;
|
|
531
435
|
}
|
|
532
|
-
|
|
436
|
+
event.preventDefault();
|
|
533
437
|
const currentIndex = current.indexOf(active);
|
|
534
|
-
let newIndex
|
|
438
|
+
let newIndex;
|
|
535
439
|
let target = current;
|
|
536
440
|
switch (key) {
|
|
537
|
-
case "Tab":
|
|
538
|
-
shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
|
|
539
|
-
break;
|
|
540
441
|
case "End":
|
|
541
442
|
newIndex = -1;
|
|
542
443
|
break;
|
|
@@ -558,16 +459,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
558
459
|
default: {
|
|
559
460
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
560
461
|
const foundIndex = target.findIndex(
|
|
561
|
-
(
|
|
462
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
562
463
|
);
|
|
563
464
|
newIndex = foundIndex >= 0 ? foundIndex : 0;
|
|
564
465
|
}
|
|
565
466
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
const focusable = target.at(newIndex);
|
|
569
|
-
focusable && focusElement(focusable);
|
|
570
|
-
}
|
|
467
|
+
const focusable = target.at(newIndex);
|
|
468
|
+
focusable && focusElement(focusable);
|
|
571
469
|
};
|
|
572
470
|
#update(active) {
|
|
573
471
|
const current = new Set(this.#getFocusables());
|
|
@@ -640,24 +538,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
640
538
|
skipVisibilityCheck: true
|
|
641
539
|
});
|
|
642
540
|
}
|
|
643
|
-
#moveFocus(direction) {
|
|
644
|
-
const options = {
|
|
645
|
-
composed: true
|
|
646
|
-
};
|
|
647
|
-
const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
|
|
648
|
-
if (focusable) {
|
|
649
|
-
focusElement(focusable);
|
|
650
|
-
return true;
|
|
651
|
-
}
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
541
|
};
|
|
655
542
|
/**
|
|
656
543
|
* Roving Tabindex
|
|
657
544
|
* Lightweight roving tabindex utility with fully focus management.
|
|
658
545
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
659
546
|
*
|
|
660
|
-
* @version 3.1.
|
|
547
|
+
* @version 3.1.1
|
|
661
548
|
* @author Yusuke Kamiyamane
|
|
662
549
|
* @license MIT
|
|
663
550
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -127,14 +127,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
127
127
|
};
|
|
128
128
|
#onKeyDown = (event) => {
|
|
129
129
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
130
|
-
if (
|
|
130
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
const { direction, typeahead, wrap } = this.#settings;
|
|
134
134
|
const isBoth = !direction;
|
|
135
135
|
const isHorizontal = direction === "horizontal";
|
|
136
136
|
if (![
|
|
137
|
-
"Tab",
|
|
138
137
|
"End",
|
|
139
138
|
"Home",
|
|
140
139
|
...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
|
|
@@ -152,14 +151,11 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
152
151
|
if (!current.includes(active)) {
|
|
153
152
|
return;
|
|
154
153
|
}
|
|
155
|
-
|
|
154
|
+
event.preventDefault();
|
|
156
155
|
const currentIndex = current.indexOf(active);
|
|
157
|
-
let newIndex
|
|
156
|
+
let newIndex;
|
|
158
157
|
let target = current;
|
|
159
158
|
switch (key) {
|
|
160
|
-
case "Tab":
|
|
161
|
-
shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
|
|
162
|
-
break;
|
|
163
159
|
case "End":
|
|
164
160
|
newIndex = -1;
|
|
165
161
|
break;
|
|
@@ -181,16 +177,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
181
177
|
default: {
|
|
182
178
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
183
179
|
const foundIndex = target.findIndex(
|
|
184
|
-
(
|
|
180
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
185
181
|
);
|
|
186
182
|
newIndex = foundIndex >= 0 ? foundIndex : 0;
|
|
187
183
|
}
|
|
188
184
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const focusable = target.at(newIndex);
|
|
192
|
-
focusable && powerFocusable.focusElement(focusable);
|
|
193
|
-
}
|
|
185
|
+
const focusable = target.at(newIndex);
|
|
186
|
+
focusable && powerFocusable.focusElement(focusable);
|
|
194
187
|
};
|
|
195
188
|
#update(active) {
|
|
196
189
|
const current = new Set(this.#getFocusables());
|
|
@@ -263,24 +256,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
263
256
|
skipVisibilityCheck: true
|
|
264
257
|
});
|
|
265
258
|
}
|
|
266
|
-
#moveFocus(direction) {
|
|
267
|
-
const options = {
|
|
268
|
-
composed: true
|
|
269
|
-
};
|
|
270
|
-
const focusable = direction === "previous" ? powerFocusable.getPreviousFocusable(document.body, options) : powerFocusable.getNextFocusable(document.body, options);
|
|
271
|
-
if (focusable) {
|
|
272
|
-
powerFocusable.focusElement(focusable);
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
259
|
};
|
|
278
260
|
/**
|
|
279
261
|
* Roving Tabindex
|
|
280
262
|
* Lightweight roving tabindex utility with fully focus management.
|
|
281
263
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
282
264
|
*
|
|
283
|
-
* @version 3.1.
|
|
265
|
+
* @version 3.1.1
|
|
284
266
|
* @author Yusuke Kamiyamane
|
|
285
267
|
* @license MIT
|
|
286
268
|
* @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.1
|
|
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.1
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { restoreAttributes, saveAttributes, addTokenToAttribute } from '@y14e/attributes-utils';
|
|
2
|
-
import { getActiveElement, focusElement, getFocusables
|
|
2
|
+
import { getActiveElement, focusElement, getFocusables } from 'power-focusable';
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
5
|
function createRovingTabIndex(container, options = {}) {
|
|
@@ -125,14 +125,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
125
125
|
};
|
|
126
126
|
#onKeyDown = (event) => {
|
|
127
127
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
128
|
-
if (
|
|
128
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
131
|
const { direction, typeahead, wrap } = this.#settings;
|
|
132
132
|
const isBoth = !direction;
|
|
133
133
|
const isHorizontal = direction === "horizontal";
|
|
134
134
|
if (![
|
|
135
|
-
"Tab",
|
|
136
135
|
"End",
|
|
137
136
|
"Home",
|
|
138
137
|
...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
|
|
@@ -150,14 +149,11 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
150
149
|
if (!current.includes(active)) {
|
|
151
150
|
return;
|
|
152
151
|
}
|
|
153
|
-
|
|
152
|
+
event.preventDefault();
|
|
154
153
|
const currentIndex = current.indexOf(active);
|
|
155
|
-
let newIndex
|
|
154
|
+
let newIndex;
|
|
156
155
|
let target = current;
|
|
157
156
|
switch (key) {
|
|
158
|
-
case "Tab":
|
|
159
|
-
shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
|
|
160
|
-
break;
|
|
161
157
|
case "End":
|
|
162
158
|
newIndex = -1;
|
|
163
159
|
break;
|
|
@@ -179,16 +175,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
179
175
|
default: {
|
|
180
176
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
181
177
|
const foundIndex = target.findIndex(
|
|
182
|
-
(
|
|
178
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
183
179
|
);
|
|
184
180
|
newIndex = foundIndex >= 0 ? foundIndex : 0;
|
|
185
181
|
}
|
|
186
182
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const focusable = target.at(newIndex);
|
|
190
|
-
focusable && focusElement(focusable);
|
|
191
|
-
}
|
|
183
|
+
const focusable = target.at(newIndex);
|
|
184
|
+
focusable && focusElement(focusable);
|
|
192
185
|
};
|
|
193
186
|
#update(active) {
|
|
194
187
|
const current = new Set(this.#getFocusables());
|
|
@@ -261,24 +254,13 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
261
254
|
skipVisibilityCheck: true
|
|
262
255
|
});
|
|
263
256
|
}
|
|
264
|
-
#moveFocus(direction) {
|
|
265
|
-
const options = {
|
|
266
|
-
composed: true
|
|
267
|
-
};
|
|
268
|
-
const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
|
|
269
|
-
if (focusable) {
|
|
270
|
-
focusElement(focusable);
|
|
271
|
-
return true;
|
|
272
|
-
}
|
|
273
|
-
return false;
|
|
274
|
-
}
|
|
275
257
|
};
|
|
276
258
|
/**
|
|
277
259
|
* Roving Tabindex
|
|
278
260
|
* Lightweight roving tabindex utility with fully focus management.
|
|
279
261
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
280
262
|
*
|
|
281
|
-
* @version 3.1.
|
|
263
|
+
* @version 3.1.1
|
|
282
264
|
* @author Yusuke Kamiyamane
|
|
283
265
|
* @license MIT
|
|
284
266
|
* @copyright Copyright (c) Yusuke Kamiyamane
|