@y14e/roving-tabindex 1.2.3 → 1.2.5
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/dist/index.cjs +30 -29
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +30 -29
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// node_modules/@y14e/attributes-utils/dist/index.js
|
|
4
|
+
var defaultParser = (value) => value.split(/\s+/);
|
|
5
|
+
var defaultSerializer = (tokens) => tokens.join(" ");
|
|
4
6
|
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
5
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
caseInsensitive = false,
|
|
9
|
+
parse = defaultParser,
|
|
10
|
+
serialize = defaultSerializer
|
|
11
|
+
} = options;
|
|
6
12
|
const value = element.getAttribute(attribute)?.trim();
|
|
7
|
-
const tokens = value ? value.
|
|
13
|
+
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
8
14
|
if (caseInsensitive) {
|
|
9
15
|
const lower = token.toLowerCase();
|
|
10
16
|
if (tokens.some((token2) => token2.toLowerCase() === lower)) {
|
|
11
17
|
return;
|
|
12
18
|
}
|
|
13
19
|
tokens.push(token);
|
|
14
|
-
element.setAttribute(attribute, tokens
|
|
20
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
15
21
|
return;
|
|
16
22
|
}
|
|
17
23
|
const set = new Set(tokens);
|
|
18
24
|
set.add(token);
|
|
19
|
-
element.setAttribute(attribute, [...set]
|
|
20
|
-
return;
|
|
25
|
+
element.setAttribute(attribute, serialize([...set]));
|
|
21
26
|
}
|
|
22
27
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
23
28
|
function restoreAttributes(elements) {
|
|
@@ -27,11 +32,7 @@ function restoreAttributes(elements) {
|
|
|
27
32
|
continue;
|
|
28
33
|
}
|
|
29
34
|
for (const [attribute, value] of snapshot.entries()) {
|
|
30
|
-
|
|
31
|
-
element.removeAttribute(attribute);
|
|
32
|
-
} else {
|
|
33
|
-
element.setAttribute(attribute, value);
|
|
34
|
-
}
|
|
35
|
+
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
35
36
|
}
|
|
36
37
|
snapshots.delete(element);
|
|
37
38
|
}
|
|
@@ -344,16 +345,16 @@ var RovingTabIndex = class {
|
|
|
344
345
|
if (!(active instanceof HTMLElement)) {
|
|
345
346
|
return;
|
|
346
347
|
}
|
|
347
|
-
const
|
|
348
|
-
if (!
|
|
348
|
+
const current = this.#getFocusables();
|
|
349
|
+
if (!current.includes(active)) {
|
|
349
350
|
return;
|
|
350
351
|
}
|
|
351
352
|
event.preventDefault();
|
|
352
353
|
event.stopPropagation();
|
|
353
|
-
const currentIndex =
|
|
354
|
+
const currentIndex = current.indexOf(active);
|
|
354
355
|
let rawIndex;
|
|
355
356
|
let newIndex = currentIndex;
|
|
356
|
-
let target =
|
|
357
|
+
let target = current;
|
|
357
358
|
switch (key) {
|
|
358
359
|
case "End":
|
|
359
360
|
newIndex = -1;
|
|
@@ -369,7 +370,7 @@ var RovingTabIndex = class {
|
|
|
369
370
|
case "ArrowRight":
|
|
370
371
|
case "ArrowDown":
|
|
371
372
|
rawIndex = currentIndex + 1;
|
|
372
|
-
newIndex = wrap ? rawIndex %
|
|
373
|
+
newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
|
|
373
374
|
break;
|
|
374
375
|
default: {
|
|
375
376
|
if (!typeahead) {
|
|
@@ -377,7 +378,7 @@ var RovingTabIndex = class {
|
|
|
377
378
|
}
|
|
378
379
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
379
380
|
const foundIndex = target.findIndex(
|
|
380
|
-
(focusable2) =>
|
|
381
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
381
382
|
);
|
|
382
383
|
newIndex = foundIndex !== -1 ? foundIndex : 0;
|
|
383
384
|
}
|
|
@@ -407,36 +408,36 @@ var RovingTabIndex = class {
|
|
|
407
408
|
this.#focusables.delete(focusable);
|
|
408
409
|
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
409
410
|
const index = focusables.indexOf(focusable);
|
|
410
|
-
if (index
|
|
411
|
+
if (index >= 0) {
|
|
411
412
|
focusables.splice(index, 1);
|
|
412
413
|
}
|
|
413
414
|
});
|
|
414
415
|
}
|
|
415
|
-
for (const
|
|
416
|
-
if (this.#focusables.has(
|
|
416
|
+
for (const focusable of current) {
|
|
417
|
+
if (this.#focusables.has(focusable)) {
|
|
417
418
|
continue;
|
|
418
419
|
}
|
|
419
|
-
this.#focusables.add(
|
|
420
|
-
saveAttributes([
|
|
421
|
-
|
|
420
|
+
this.#focusables.add(focusable);
|
|
421
|
+
saveAttributes([focusable], ["tabindex"]);
|
|
422
|
+
focusable.setAttribute("tabindex", "-1");
|
|
422
423
|
if (!this.#options.typeahead) {
|
|
423
424
|
continue;
|
|
424
425
|
}
|
|
425
|
-
const value =
|
|
426
|
+
const value = focusable.ariaKeyShortcuts?.trim();
|
|
426
427
|
const keys = new Set(
|
|
427
428
|
value ? value.split(/\s+/).filter((key) => /^\S$/i.test(key)).map((key) => key.toUpperCase()) : []
|
|
428
429
|
);
|
|
429
|
-
const char =
|
|
430
|
+
const char = focusable.textContent?.trim()?.at(0)?.toUpperCase();
|
|
430
431
|
if (char) {
|
|
431
432
|
keys.add(char);
|
|
432
|
-
saveAttributes([
|
|
433
|
-
addTokenToAttribute(
|
|
433
|
+
saveAttributes([focusable], ["aria-keyshortcuts"]);
|
|
434
|
+
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
434
435
|
caseInsensitive: true
|
|
435
436
|
});
|
|
436
437
|
}
|
|
437
438
|
keys.forEach((key) => {
|
|
438
439
|
const focusables = this.#focusablesByFirstChar.get(key) ?? [];
|
|
439
|
-
focusables.push(
|
|
440
|
+
focusables.push(focusable);
|
|
440
441
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
441
442
|
});
|
|
442
443
|
}
|
|
@@ -477,7 +478,7 @@ function getActiveElement() {
|
|
|
477
478
|
* Lightweight roving tabindex utility with fully focus management.
|
|
478
479
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
479
480
|
*
|
|
480
|
-
* @version 1.2.
|
|
481
|
+
* @version 1.2.5
|
|
481
482
|
* @author Yusuke Kamiyamane
|
|
482
483
|
* @license MIT
|
|
483
484
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -489,7 +490,7 @@ function getActiveElement() {
|
|
|
489
490
|
(**
|
|
490
491
|
* Attributes Utils
|
|
491
492
|
*
|
|
492
|
-
* @version 1.0.
|
|
493
|
+
* @version 1.0.5
|
|
493
494
|
* @author Yusuke Kamiyamane
|
|
494
495
|
* @license MIT
|
|
495
496
|
* @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 1.2.
|
|
6
|
+
* @version 1.2.5
|
|
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 1.2.
|
|
6
|
+
* @version 1.2.5
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
// node_modules/@y14e/attributes-utils/dist/index.js
|
|
2
|
+
var defaultParser = (value) => value.split(/\s+/);
|
|
3
|
+
var defaultSerializer = (tokens) => tokens.join(" ");
|
|
2
4
|
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
3
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
caseInsensitive = false,
|
|
7
|
+
parse = defaultParser,
|
|
8
|
+
serialize = defaultSerializer
|
|
9
|
+
} = options;
|
|
4
10
|
const value = element.getAttribute(attribute)?.trim();
|
|
5
|
-
const tokens = value ? value.
|
|
11
|
+
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
6
12
|
if (caseInsensitive) {
|
|
7
13
|
const lower = token.toLowerCase();
|
|
8
14
|
if (tokens.some((token2) => token2.toLowerCase() === lower)) {
|
|
9
15
|
return;
|
|
10
16
|
}
|
|
11
17
|
tokens.push(token);
|
|
12
|
-
element.setAttribute(attribute, tokens
|
|
18
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
13
19
|
return;
|
|
14
20
|
}
|
|
15
21
|
const set = new Set(tokens);
|
|
16
22
|
set.add(token);
|
|
17
|
-
element.setAttribute(attribute, [...set]
|
|
18
|
-
return;
|
|
23
|
+
element.setAttribute(attribute, serialize([...set]));
|
|
19
24
|
}
|
|
20
25
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
21
26
|
function restoreAttributes(elements) {
|
|
@@ -25,11 +30,7 @@ function restoreAttributes(elements) {
|
|
|
25
30
|
continue;
|
|
26
31
|
}
|
|
27
32
|
for (const [attribute, value] of snapshot.entries()) {
|
|
28
|
-
|
|
29
|
-
element.removeAttribute(attribute);
|
|
30
|
-
} else {
|
|
31
|
-
element.setAttribute(attribute, value);
|
|
32
|
-
}
|
|
33
|
+
value === null ? element.removeAttribute(attribute) : element.setAttribute(attribute, value);
|
|
33
34
|
}
|
|
34
35
|
snapshots.delete(element);
|
|
35
36
|
}
|
|
@@ -342,16 +343,16 @@ var RovingTabIndex = class {
|
|
|
342
343
|
if (!(active instanceof HTMLElement)) {
|
|
343
344
|
return;
|
|
344
345
|
}
|
|
345
|
-
const
|
|
346
|
-
if (!
|
|
346
|
+
const current = this.#getFocusables();
|
|
347
|
+
if (!current.includes(active)) {
|
|
347
348
|
return;
|
|
348
349
|
}
|
|
349
350
|
event.preventDefault();
|
|
350
351
|
event.stopPropagation();
|
|
351
|
-
const currentIndex =
|
|
352
|
+
const currentIndex = current.indexOf(active);
|
|
352
353
|
let rawIndex;
|
|
353
354
|
let newIndex = currentIndex;
|
|
354
|
-
let target =
|
|
355
|
+
let target = current;
|
|
355
356
|
switch (key) {
|
|
356
357
|
case "End":
|
|
357
358
|
newIndex = -1;
|
|
@@ -367,7 +368,7 @@ var RovingTabIndex = class {
|
|
|
367
368
|
case "ArrowRight":
|
|
368
369
|
case "ArrowDown":
|
|
369
370
|
rawIndex = currentIndex + 1;
|
|
370
|
-
newIndex = wrap ? rawIndex %
|
|
371
|
+
newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
|
|
371
372
|
break;
|
|
372
373
|
default: {
|
|
373
374
|
if (!typeahead) {
|
|
@@ -375,7 +376,7 @@ var RovingTabIndex = class {
|
|
|
375
376
|
}
|
|
376
377
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
377
378
|
const foundIndex = target.findIndex(
|
|
378
|
-
(focusable2) =>
|
|
379
|
+
(focusable2) => current.indexOf(focusable2) > currentIndex
|
|
379
380
|
);
|
|
380
381
|
newIndex = foundIndex !== -1 ? foundIndex : 0;
|
|
381
382
|
}
|
|
@@ -405,36 +406,36 @@ var RovingTabIndex = class {
|
|
|
405
406
|
this.#focusables.delete(focusable);
|
|
406
407
|
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
407
408
|
const index = focusables.indexOf(focusable);
|
|
408
|
-
if (index
|
|
409
|
+
if (index >= 0) {
|
|
409
410
|
focusables.splice(index, 1);
|
|
410
411
|
}
|
|
411
412
|
});
|
|
412
413
|
}
|
|
413
|
-
for (const
|
|
414
|
-
if (this.#focusables.has(
|
|
414
|
+
for (const focusable of current) {
|
|
415
|
+
if (this.#focusables.has(focusable)) {
|
|
415
416
|
continue;
|
|
416
417
|
}
|
|
417
|
-
this.#focusables.add(
|
|
418
|
-
saveAttributes([
|
|
419
|
-
|
|
418
|
+
this.#focusables.add(focusable);
|
|
419
|
+
saveAttributes([focusable], ["tabindex"]);
|
|
420
|
+
focusable.setAttribute("tabindex", "-1");
|
|
420
421
|
if (!this.#options.typeahead) {
|
|
421
422
|
continue;
|
|
422
423
|
}
|
|
423
|
-
const value =
|
|
424
|
+
const value = focusable.ariaKeyShortcuts?.trim();
|
|
424
425
|
const keys = new Set(
|
|
425
426
|
value ? value.split(/\s+/).filter((key) => /^\S$/i.test(key)).map((key) => key.toUpperCase()) : []
|
|
426
427
|
);
|
|
427
|
-
const char =
|
|
428
|
+
const char = focusable.textContent?.trim()?.at(0)?.toUpperCase();
|
|
428
429
|
if (char) {
|
|
429
430
|
keys.add(char);
|
|
430
|
-
saveAttributes([
|
|
431
|
-
addTokenToAttribute(
|
|
431
|
+
saveAttributes([focusable], ["aria-keyshortcuts"]);
|
|
432
|
+
addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
|
|
432
433
|
caseInsensitive: true
|
|
433
434
|
});
|
|
434
435
|
}
|
|
435
436
|
keys.forEach((key) => {
|
|
436
437
|
const focusables = this.#focusablesByFirstChar.get(key) ?? [];
|
|
437
|
-
focusables.push(
|
|
438
|
+
focusables.push(focusable);
|
|
438
439
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
439
440
|
});
|
|
440
441
|
}
|
|
@@ -475,7 +476,7 @@ function getActiveElement() {
|
|
|
475
476
|
* Lightweight roving tabindex utility with fully focus management.
|
|
476
477
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
477
478
|
*
|
|
478
|
-
* @version 1.2.
|
|
479
|
+
* @version 1.2.5
|
|
479
480
|
* @author Yusuke Kamiyamane
|
|
480
481
|
* @license MIT
|
|
481
482
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -487,7 +488,7 @@ function getActiveElement() {
|
|
|
487
488
|
(**
|
|
488
489
|
* Attributes Utils
|
|
489
490
|
*
|
|
490
|
-
* @version 1.0.
|
|
491
|
+
* @version 1.0.5
|
|
491
492
|
* @author Yusuke Kamiyamane
|
|
492
493
|
* @license MIT
|
|
493
494
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/roving-tabindex",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Lightweight roving tabindex utility with fully focus management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"homepage": "https://github.com/y14e/roving-tabindex#readme",
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@y14e/attributes-utils": "^1.0.
|
|
51
|
+
"@y14e/attributes-utils": "^1.0.5",
|
|
52
52
|
"bun-types": "latest",
|
|
53
53
|
"power-focusable": "^4.1.7",
|
|
54
54
|
"tsup": "^8.0.0",
|