@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 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.17';
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.17/+esm';
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.17';
20
+ import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.19';
21
21
  ```
22
22
 
23
23
  ## 📦 APIs
@@ -24,8 +24,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
24
24
  }
25
25
  }
26
26
  var snapshots = /* @__PURE__ */ new WeakMap();
27
- function restoreAttributes(elements) {
28
- for (const element of elements) {
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(elements, attributes) {
40
- elements.forEach((element) => {
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 elements = [];
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
- elements[elements.length] = node;
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 candidates = container.querySelectorAll(
116
+ const matches = container.querySelectorAll(
116
117
  skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
117
118
  );
118
- for (let i = 0, l = candidates.length; i < l; i++) {
119
- const candidate = candidates[i];
120
- if (candidate && isFocusable(candidate, {
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
- elements[elements.length] = candidate;
125
+ candidates[candidates.length] = matched;
125
126
  }
126
127
  }
127
128
  }
128
- const filtered = filter ? elements.filter(filter) : elements;
129
- return normalizeRadioGroup(sortByTabIndex(filtered));
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([focusable]);
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
- let target = candidates;
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 = target.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 focusables = new Set(
495
+ const focusablesByFirstChar = new Set(
494
496
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
495
497
  );
496
- target = candidates.filter((focusable2) => focusables.has(focusable2));
497
- const afterIndex = target.findIndex(
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 = target.at(newIndex);
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([focusable]);
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([focusable], ["tabindex"]);
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([focusable], ["aria-keyshortcuts"]);
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.17
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.3
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.20
616
+ * @version 4.3.21
613
617
  * @author Yusuke Kamiyamane
614
618
  * @license MIT
615
619
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -22,8 +22,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
22
22
  }
23
23
  }
24
24
  var snapshots = /* @__PURE__ */ new WeakMap();
25
- function restoreAttributes(elements) {
26
- for (const element of elements) {
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(elements, attributes) {
38
- elements.forEach((element) => {
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 elements = [];
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
- elements[elements.length] = node;
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 candidates = container.querySelectorAll(
114
+ const matches = container.querySelectorAll(
114
115
  skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
115
116
  );
116
- for (let i = 0, l = candidates.length; i < l; i++) {
117
- const candidate = candidates[i];
118
- if (candidate && isFocusable(candidate, {
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
- elements[elements.length] = candidate;
123
+ candidates[candidates.length] = matched;
123
124
  }
124
125
  }
125
126
  }
126
- const filtered = filter ? elements.filter(filter) : elements;
127
- return normalizeRadioGroup(sortByTabIndex(filtered));
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([focusable]);
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
- let target = candidates;
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 = target.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 focusables = new Set(
493
+ const focusablesByFirstChar = new Set(
492
494
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
493
495
  );
494
- target = candidates.filter((focusable2) => focusables.has(focusable2));
495
- const afterIndex = target.findIndex(
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 = target.at(newIndex);
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([focusable]);
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([focusable], ["tabindex"]);
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([focusable], ["aria-keyshortcuts"]);
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.17
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.3
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.20
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([focusable]);
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
- let target = candidates;
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 = target.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 focusables = new Set(
179
+ const focusablesByFirstChar = new Set(
180
180
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
181
181
  );
182
- target = candidates.filter((focusable2) => focusables.has(focusable2));
183
- const afterIndex = target.findIndex(
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 = target.at(newIndex);
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([focusable]);
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([focusable], ["tabindex"]);
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([focusable], ["aria-keyshortcuts"]);
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.17
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.17
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.17
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([focusable]);
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
- let target = candidates;
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 = target.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 focusables = new Set(
177
+ const focusablesByFirstChar = new Set(
178
178
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
179
179
  );
180
- target = candidates.filter((focusable2) => focusables.has(focusable2));
181
- const afterIndex = target.findIndex(
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 = target.at(newIndex);
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([focusable]);
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([focusable], ["tabindex"]);
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([focusable], ["aria-keyshortcuts"]);
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.17
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.17",
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.3",
60
- "power-focusable": "^4.3.20"
59
+ "@y14e/attributes-utils": "^1.1.4",
60
+ "power-focusable": "^4.3.21"
61
61
  }
62
62
  }