@y14e/roving-tabindex 2.1.0 → 2.2.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 +14 -4
- package/dist/index.cjs +24 -7
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +24 -7
- 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@2.
|
|
13
|
+
import { createRovingTabIndex } from '@y14e/roving-tabindex@2.2.0';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@2.
|
|
16
|
+
import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@2.2.0';
|
|
17
17
|
// or
|
|
18
|
-
import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@2.
|
|
18
|
+
import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@2.2.0/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@2.
|
|
20
|
+
import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@2.2.0';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## 📦 APIs
|
|
@@ -41,6 +41,8 @@ interface RovingTabIndexOptions {
|
|
|
41
41
|
direction?: 'horizontal' | 'vertical'; // default: both (undefined)
|
|
42
42
|
navigationOnly?: boolean; // default: false
|
|
43
43
|
noMemory?: boolean; // default: false
|
|
44
|
+
noStart?: boolean; // default: false
|
|
45
|
+
noStopPropagation?: boolean; // default: false
|
|
44
46
|
selector?: string;
|
|
45
47
|
typeahead?: boolean; // default: false
|
|
46
48
|
wrap?: boolean; // default: false
|
|
@@ -55,6 +57,14 @@ If `true`, enables keyboard navigation without modifying `tabindex`. Useful for
|
|
|
55
57
|
|
|
56
58
|
If `true`, disables focus memory. Focus always starts from the first item.
|
|
57
59
|
|
|
60
|
+
### `noStart`
|
|
61
|
+
|
|
62
|
+
If `true`, does not assign `tabindex="0"` to the first item during initialization.
|
|
63
|
+
|
|
64
|
+
### `noStopPropagation`
|
|
65
|
+
|
|
66
|
+
If `true`, keyboard navigation will not call `stopPropagation()`.
|
|
67
|
+
|
|
58
68
|
### `typeahead`
|
|
59
69
|
|
|
60
70
|
If `true`, enables character-based focus navigation. Typing a character moves focus to the next matching element.
|
package/dist/index.cjs
CHANGED
|
@@ -300,6 +300,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
300
300
|
direction,
|
|
301
301
|
navigationOnly = false,
|
|
302
302
|
noMemory = false,
|
|
303
|
+
noStart = false,
|
|
304
|
+
noStopPropagation = false,
|
|
303
305
|
selector,
|
|
304
306
|
typeahead = false,
|
|
305
307
|
wrap = false
|
|
@@ -316,6 +318,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
316
318
|
console.warn("Invalid noMemory option. Fallback: false.");
|
|
317
319
|
noMemory = false;
|
|
318
320
|
}
|
|
321
|
+
if (typeof noStart !== "boolean") {
|
|
322
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
323
|
+
noStart = false;
|
|
324
|
+
}
|
|
325
|
+
if (typeof noStopPropagation !== "boolean") {
|
|
326
|
+
console.warn("Invalid noStopPropagation option. Fallback: false.");
|
|
327
|
+
noStopPropagation = false;
|
|
328
|
+
}
|
|
319
329
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
320
330
|
console.warn(
|
|
321
331
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -330,7 +340,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
330
340
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
331
341
|
wrap = false;
|
|
332
342
|
}
|
|
333
|
-
const settings = {
|
|
343
|
+
const settings = {
|
|
344
|
+
navigationOnly,
|
|
345
|
+
noMemory,
|
|
346
|
+
noStart,
|
|
347
|
+
noStopPropagation,
|
|
348
|
+
typeahead,
|
|
349
|
+
wrap
|
|
350
|
+
};
|
|
334
351
|
direction && Object.assign(settings, { direction });
|
|
335
352
|
selector && Object.assign(settings, { selector });
|
|
336
353
|
const roving = new RovingTabIndex(container, settings);
|
|
@@ -396,7 +413,7 @@ var RovingTabIndex = class {
|
|
|
396
413
|
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
397
414
|
return;
|
|
398
415
|
}
|
|
399
|
-
const { direction, typeahead, wrap } = this.#options;
|
|
416
|
+
const { direction, noStopPropagation, typeahead, wrap } = this.#options;
|
|
400
417
|
const isBoth = !direction;
|
|
401
418
|
const isHorizontal = direction === "horizontal";
|
|
402
419
|
if (![
|
|
@@ -418,7 +435,7 @@ var RovingTabIndex = class {
|
|
|
418
435
|
return;
|
|
419
436
|
}
|
|
420
437
|
event.preventDefault();
|
|
421
|
-
event.stopPropagation();
|
|
438
|
+
!noStopPropagation && event.stopPropagation();
|
|
422
439
|
const currentIndex = current.indexOf(active);
|
|
423
440
|
let rawIndex;
|
|
424
441
|
let newIndex = currentIndex;
|
|
@@ -464,7 +481,7 @@ var RovingTabIndex = class {
|
|
|
464
481
|
index >= 0 && focusables.splice(index, 1);
|
|
465
482
|
});
|
|
466
483
|
}
|
|
467
|
-
const { navigationOnly } = this.#options;
|
|
484
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
468
485
|
for (const focusable of current) {
|
|
469
486
|
if (this.#focusables.has(focusable)) {
|
|
470
487
|
continue;
|
|
@@ -474,7 +491,7 @@ var RovingTabIndex = class {
|
|
|
474
491
|
saveAttributes([focusable], ["tabindex"]);
|
|
475
492
|
focusable.setAttribute("tabindex", "-1");
|
|
476
493
|
}
|
|
477
|
-
if (!
|
|
494
|
+
if (!typeahead) {
|
|
478
495
|
continue;
|
|
479
496
|
}
|
|
480
497
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -505,7 +522,7 @@ var RovingTabIndex = class {
|
|
|
505
522
|
return;
|
|
506
523
|
}
|
|
507
524
|
[...this.#focusables].forEach((focusable, i) => {
|
|
508
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
525
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
509
526
|
});
|
|
510
527
|
}
|
|
511
528
|
#createSelectorFilter() {
|
|
@@ -536,7 +553,7 @@ function getActiveElement() {
|
|
|
536
553
|
* Lightweight roving tabindex utility with fully focus management.
|
|
537
554
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
538
555
|
*
|
|
539
|
-
* @version 2.1
|
|
556
|
+
* @version 2.2.1
|
|
540
557
|
* @author Yusuke Kamiyamane
|
|
541
558
|
* @license MIT
|
|
542
559
|
* @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 2.1
|
|
6
|
+
* @version 2.2.1
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -13,6 +13,8 @@ interface RovingTabIndexOptions {
|
|
|
13
13
|
readonly direction?: 'horizontal' | 'vertical';
|
|
14
14
|
readonly navigationOnly?: boolean;
|
|
15
15
|
readonly noMemory?: boolean;
|
|
16
|
+
readonly noStart?: boolean;
|
|
17
|
+
readonly noStopPropagation?: boolean;
|
|
16
18
|
readonly selector?: string;
|
|
17
19
|
readonly typeahead?: boolean;
|
|
18
20
|
readonly wrap?: boolean;
|
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 2.1
|
|
6
|
+
* @version 2.2.1
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -13,6 +13,8 @@ interface RovingTabIndexOptions {
|
|
|
13
13
|
readonly direction?: 'horizontal' | 'vertical';
|
|
14
14
|
readonly navigationOnly?: boolean;
|
|
15
15
|
readonly noMemory?: boolean;
|
|
16
|
+
readonly noStart?: boolean;
|
|
17
|
+
readonly noStopPropagation?: boolean;
|
|
16
18
|
readonly selector?: string;
|
|
17
19
|
readonly typeahead?: boolean;
|
|
18
20
|
readonly wrap?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -298,6 +298,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
298
298
|
direction,
|
|
299
299
|
navigationOnly = false,
|
|
300
300
|
noMemory = false,
|
|
301
|
+
noStart = false,
|
|
302
|
+
noStopPropagation = false,
|
|
301
303
|
selector,
|
|
302
304
|
typeahead = false,
|
|
303
305
|
wrap = false
|
|
@@ -314,6 +316,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
314
316
|
console.warn("Invalid noMemory option. Fallback: false.");
|
|
315
317
|
noMemory = false;
|
|
316
318
|
}
|
|
319
|
+
if (typeof noStart !== "boolean") {
|
|
320
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
321
|
+
noStart = false;
|
|
322
|
+
}
|
|
323
|
+
if (typeof noStopPropagation !== "boolean") {
|
|
324
|
+
console.warn("Invalid noStopPropagation option. Fallback: false.");
|
|
325
|
+
noStopPropagation = false;
|
|
326
|
+
}
|
|
317
327
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
318
328
|
console.warn(
|
|
319
329
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -328,7 +338,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
328
338
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
329
339
|
wrap = false;
|
|
330
340
|
}
|
|
331
|
-
const settings = {
|
|
341
|
+
const settings = {
|
|
342
|
+
navigationOnly,
|
|
343
|
+
noMemory,
|
|
344
|
+
noStart,
|
|
345
|
+
noStopPropagation,
|
|
346
|
+
typeahead,
|
|
347
|
+
wrap
|
|
348
|
+
};
|
|
332
349
|
direction && Object.assign(settings, { direction });
|
|
333
350
|
selector && Object.assign(settings, { selector });
|
|
334
351
|
const roving = new RovingTabIndex(container, settings);
|
|
@@ -394,7 +411,7 @@ var RovingTabIndex = class {
|
|
|
394
411
|
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
395
412
|
return;
|
|
396
413
|
}
|
|
397
|
-
const { direction, typeahead, wrap } = this.#options;
|
|
414
|
+
const { direction, noStopPropagation, typeahead, wrap } = this.#options;
|
|
398
415
|
const isBoth = !direction;
|
|
399
416
|
const isHorizontal = direction === "horizontal";
|
|
400
417
|
if (![
|
|
@@ -416,7 +433,7 @@ var RovingTabIndex = class {
|
|
|
416
433
|
return;
|
|
417
434
|
}
|
|
418
435
|
event.preventDefault();
|
|
419
|
-
event.stopPropagation();
|
|
436
|
+
!noStopPropagation && event.stopPropagation();
|
|
420
437
|
const currentIndex = current.indexOf(active);
|
|
421
438
|
let rawIndex;
|
|
422
439
|
let newIndex = currentIndex;
|
|
@@ -462,7 +479,7 @@ var RovingTabIndex = class {
|
|
|
462
479
|
index >= 0 && focusables.splice(index, 1);
|
|
463
480
|
});
|
|
464
481
|
}
|
|
465
|
-
const { navigationOnly } = this.#options;
|
|
482
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
466
483
|
for (const focusable of current) {
|
|
467
484
|
if (this.#focusables.has(focusable)) {
|
|
468
485
|
continue;
|
|
@@ -472,7 +489,7 @@ var RovingTabIndex = class {
|
|
|
472
489
|
saveAttributes([focusable], ["tabindex"]);
|
|
473
490
|
focusable.setAttribute("tabindex", "-1");
|
|
474
491
|
}
|
|
475
|
-
if (!
|
|
492
|
+
if (!typeahead) {
|
|
476
493
|
continue;
|
|
477
494
|
}
|
|
478
495
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -503,7 +520,7 @@ var RovingTabIndex = class {
|
|
|
503
520
|
return;
|
|
504
521
|
}
|
|
505
522
|
[...this.#focusables].forEach((focusable, i) => {
|
|
506
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
523
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
507
524
|
});
|
|
508
525
|
}
|
|
509
526
|
#createSelectorFilter() {
|
|
@@ -534,7 +551,7 @@ function getActiveElement() {
|
|
|
534
551
|
* Lightweight roving tabindex utility with fully focus management.
|
|
535
552
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
536
553
|
*
|
|
537
|
-
* @version 2.1
|
|
554
|
+
* @version 2.2.1
|
|
538
555
|
* @author Yusuke Kamiyamane
|
|
539
556
|
* @license MIT
|
|
540
557
|
* @copyright Copyright (c) Yusuke Kamiyamane
|