@y14e/roving-tabindex 3.1.16 → 3.1.18

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.16';
16
+ import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.1.18';
17
17
  // or
18
- import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.16/+esm';
18
+ import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.18/+esm';
19
19
  // or
20
- import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.16';
20
+ import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.18';
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();
@@ -459,16 +461,16 @@ var RovingTabIndex = class _RovingTabIndex {
459
461
  if (!(active instanceof Element)) {
460
462
  return;
461
463
  }
462
- const current = this.#getFocusables().filter(
464
+ const candidates = this.#getFocusables().filter(
463
465
  (focusable2) => this.#focusables.has(focusable2)
464
466
  );
465
- if (!current.includes(active)) {
467
+ if (!candidates.includes(active)) {
466
468
  return;
467
469
  }
468
470
  event.preventDefault();
469
- const currentIndex = current.indexOf(active);
471
+ const activeIndex = candidates.indexOf(active);
470
472
  let newIndex;
471
- let target = current;
473
+ let target = candidates;
472
474
  switch (key) {
473
475
  case "End":
474
476
  newIndex = -1;
@@ -478,25 +480,26 @@ var RovingTabIndex = class _RovingTabIndex {
478
480
  break;
479
481
  case "ArrowLeft":
480
482
  case "ArrowUp": {
481
- const rawIndex = currentIndex - 1;
483
+ const rawIndex = activeIndex - 1;
482
484
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
483
485
  break;
484
486
  }
485
487
  case "ArrowRight":
486
488
  case "ArrowDown": {
487
- const rawIndex = currentIndex + 1;
488
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
489
+ const rawIndex = activeIndex + 1;
490
+ const length = target.length;
491
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
489
492
  break;
490
493
  }
491
494
  default: {
492
495
  const focusables = new Set(
493
496
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
494
497
  );
495
- target = current.filter((focusable2) => focusables.has(focusable2));
496
- const foundIndex = target.findIndex(
497
- (focusable2) => current.indexOf(focusable2) > currentIndex
498
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
499
+ const afterIndex = target.findIndex(
500
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
498
501
  );
499
- newIndex = foundIndex >= 0 ? foundIndex : 0;
502
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
500
503
  }
501
504
  }
502
505
  const focusable = target.at(newIndex);
@@ -507,7 +510,7 @@ var RovingTabIndex = class _RovingTabIndex {
507
510
  for (const focusable of this.#focusables) {
508
511
  if (!current.has(focusable)) {
509
512
  _RovingTabIndex.#initialized.delete(focusable);
510
- restoreAttributes([focusable]);
513
+ restoreAttributes(focusable);
511
514
  this.#focusables.delete(focusable);
512
515
  for (const [key, focusables] of this.#focusablesByFirstChar) {
513
516
  const index = focusables.indexOf(focusable);
@@ -529,7 +532,7 @@ var RovingTabIndex = class _RovingTabIndex {
529
532
  this.#focusables.add(focusable);
530
533
  _RovingTabIndex.#initialized.add(focusable);
531
534
  if (!navigationOnly) {
532
- saveAttributes([focusable], ["tabindex"]);
535
+ saveAttributes(focusable, "tabindex");
533
536
  focusable.setAttribute("tabindex", "-1");
534
537
  }
535
538
  if (!typeahead) {
@@ -542,7 +545,7 @@ var RovingTabIndex = class _RovingTabIndex {
542
545
  );
543
546
  if (char) {
544
547
  keys.add(char);
545
- saveAttributes([focusable], ["aria-keyshortcuts"]);
548
+ saveAttributes(focusable, "aria-keyshortcuts");
546
549
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
547
550
  caseInsensitive: true
548
551
  });
@@ -567,7 +570,7 @@ var RovingTabIndex = class _RovingTabIndex {
567
570
  }
568
571
  #createSelectorFilter() {
569
572
  const { selector } = this.#settings;
570
- return (element) => !selector || element.matches(selector);
573
+ return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
571
574
  }
572
575
  #getFocusables() {
573
576
  return getFocusables(this.#container, {
@@ -583,7 +586,7 @@ var RovingTabIndex = class _RovingTabIndex {
583
586
  * Lightweight roving tabindex utility with fully focus management.
584
587
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
585
588
  *
586
- * @version 3.1.16
589
+ * @version 3.1.18
587
590
  * @author Yusuke Kamiyamane
588
591
  * @license MIT
589
592
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -595,7 +598,7 @@ var RovingTabIndex = class _RovingTabIndex {
595
598
  (**
596
599
  * Attributes Utils
597
600
  *
598
- * @version 1.1.3
601
+ * @version 1.1.4
599
602
  * @author Yusuke Kamiyamane
600
603
  * @license MIT
601
604
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -608,7 +611,7 @@ power-focusable/dist/index.js:
608
611
  * High-precision focus management utility with full composed tree support.
609
612
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
610
613
  *
611
- * @version 4.3.20
614
+ * @version 4.3.21
612
615
  * @author Yusuke Kamiyamane
613
616
  * @license MIT
614
617
  * @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();
@@ -457,16 +459,16 @@ var RovingTabIndex = class _RovingTabIndex {
457
459
  if (!(active instanceof Element)) {
458
460
  return;
459
461
  }
460
- const current = this.#getFocusables().filter(
462
+ const candidates = this.#getFocusables().filter(
461
463
  (focusable2) => this.#focusables.has(focusable2)
462
464
  );
463
- if (!current.includes(active)) {
465
+ if (!candidates.includes(active)) {
464
466
  return;
465
467
  }
466
468
  event.preventDefault();
467
- const currentIndex = current.indexOf(active);
469
+ const activeIndex = candidates.indexOf(active);
468
470
  let newIndex;
469
- let target = current;
471
+ let target = candidates;
470
472
  switch (key) {
471
473
  case "End":
472
474
  newIndex = -1;
@@ -476,25 +478,26 @@ var RovingTabIndex = class _RovingTabIndex {
476
478
  break;
477
479
  case "ArrowLeft":
478
480
  case "ArrowUp": {
479
- const rawIndex = currentIndex - 1;
481
+ const rawIndex = activeIndex - 1;
480
482
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
481
483
  break;
482
484
  }
483
485
  case "ArrowRight":
484
486
  case "ArrowDown": {
485
- const rawIndex = currentIndex + 1;
486
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
487
+ const rawIndex = activeIndex + 1;
488
+ const length = target.length;
489
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
487
490
  break;
488
491
  }
489
492
  default: {
490
493
  const focusables = new Set(
491
494
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
492
495
  );
493
- target = current.filter((focusable2) => focusables.has(focusable2));
494
- const foundIndex = target.findIndex(
495
- (focusable2) => current.indexOf(focusable2) > currentIndex
496
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
497
+ const afterIndex = target.findIndex(
498
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
496
499
  );
497
- newIndex = foundIndex >= 0 ? foundIndex : 0;
500
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
498
501
  }
499
502
  }
500
503
  const focusable = target.at(newIndex);
@@ -505,7 +508,7 @@ var RovingTabIndex = class _RovingTabIndex {
505
508
  for (const focusable of this.#focusables) {
506
509
  if (!current.has(focusable)) {
507
510
  _RovingTabIndex.#initialized.delete(focusable);
508
- restoreAttributes([focusable]);
511
+ restoreAttributes(focusable);
509
512
  this.#focusables.delete(focusable);
510
513
  for (const [key, focusables] of this.#focusablesByFirstChar) {
511
514
  const index = focusables.indexOf(focusable);
@@ -527,7 +530,7 @@ var RovingTabIndex = class _RovingTabIndex {
527
530
  this.#focusables.add(focusable);
528
531
  _RovingTabIndex.#initialized.add(focusable);
529
532
  if (!navigationOnly) {
530
- saveAttributes([focusable], ["tabindex"]);
533
+ saveAttributes(focusable, "tabindex");
531
534
  focusable.setAttribute("tabindex", "-1");
532
535
  }
533
536
  if (!typeahead) {
@@ -540,7 +543,7 @@ var RovingTabIndex = class _RovingTabIndex {
540
543
  );
541
544
  if (char) {
542
545
  keys.add(char);
543
- saveAttributes([focusable], ["aria-keyshortcuts"]);
546
+ saveAttributes(focusable, "aria-keyshortcuts");
544
547
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
545
548
  caseInsensitive: true
546
549
  });
@@ -565,7 +568,7 @@ var RovingTabIndex = class _RovingTabIndex {
565
568
  }
566
569
  #createSelectorFilter() {
567
570
  const { selector } = this.#settings;
568
- return (element) => !selector || element.matches(selector);
571
+ return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
569
572
  }
570
573
  #getFocusables() {
571
574
  return getFocusables(this.#container, {
@@ -581,7 +584,7 @@ var RovingTabIndex = class _RovingTabIndex {
581
584
  * Lightweight roving tabindex utility with fully focus management.
582
585
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
583
586
  *
584
- * @version 3.1.16
587
+ * @version 3.1.18
585
588
  * @author Yusuke Kamiyamane
586
589
  * @license MIT
587
590
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -593,7 +596,7 @@ var RovingTabIndex = class _RovingTabIndex {
593
596
  (**
594
597
  * Attributes Utils
595
598
  *
596
- * @version 1.1.3
599
+ * @version 1.1.4
597
600
  * @author Yusuke Kamiyamane
598
601
  * @license MIT
599
602
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -606,7 +609,7 @@ power-focusable/dist/index.js:
606
609
  * High-precision focus management utility with full composed tree support.
607
610
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
608
611
  *
609
- * @version 4.3.20
612
+ * @version 4.3.21
610
613
  * @author Yusuke Kamiyamane
611
614
  * @license MIT
612
615
  * @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();
@@ -145,16 +145,16 @@ var RovingTabIndex = class _RovingTabIndex {
145
145
  if (!(active instanceof Element)) {
146
146
  return;
147
147
  }
148
- const current = this.#getFocusables().filter(
148
+ const candidates = this.#getFocusables().filter(
149
149
  (focusable2) => this.#focusables.has(focusable2)
150
150
  );
151
- if (!current.includes(active)) {
151
+ if (!candidates.includes(active)) {
152
152
  return;
153
153
  }
154
154
  event.preventDefault();
155
- const currentIndex = current.indexOf(active);
155
+ const activeIndex = candidates.indexOf(active);
156
156
  let newIndex;
157
- let target = current;
157
+ let target = candidates;
158
158
  switch (key) {
159
159
  case "End":
160
160
  newIndex = -1;
@@ -164,25 +164,26 @@ var RovingTabIndex = class _RovingTabIndex {
164
164
  break;
165
165
  case "ArrowLeft":
166
166
  case "ArrowUp": {
167
- const rawIndex = currentIndex - 1;
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 = currentIndex + 1;
174
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
173
+ const rawIndex = activeIndex + 1;
174
+ const length = target.length;
175
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
175
176
  break;
176
177
  }
177
178
  default: {
178
179
  const focusables = new Set(
179
180
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
180
181
  );
181
- target = current.filter((focusable2) => focusables.has(focusable2));
182
- const foundIndex = target.findIndex(
183
- (focusable2) => current.indexOf(focusable2) > currentIndex
182
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
183
+ const afterIndex = target.findIndex(
184
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
184
185
  );
185
- newIndex = foundIndex >= 0 ? foundIndex : 0;
186
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
186
187
  }
187
188
  }
188
189
  const focusable = target.at(newIndex);
@@ -193,7 +194,7 @@ var RovingTabIndex = class _RovingTabIndex {
193
194
  for (const focusable of this.#focusables) {
194
195
  if (!current.has(focusable)) {
195
196
  _RovingTabIndex.#initialized.delete(focusable);
196
- attributesUtils.restoreAttributes([focusable]);
197
+ attributesUtils.restoreAttributes(focusable);
197
198
  this.#focusables.delete(focusable);
198
199
  for (const [key, focusables] of this.#focusablesByFirstChar) {
199
200
  const index = focusables.indexOf(focusable);
@@ -215,7 +216,7 @@ var RovingTabIndex = class _RovingTabIndex {
215
216
  this.#focusables.add(focusable);
216
217
  _RovingTabIndex.#initialized.add(focusable);
217
218
  if (!navigationOnly) {
218
- attributesUtils.saveAttributes([focusable], ["tabindex"]);
219
+ attributesUtils.saveAttributes(focusable, "tabindex");
219
220
  focusable.setAttribute("tabindex", "-1");
220
221
  }
221
222
  if (!typeahead) {
@@ -228,7 +229,7 @@ var RovingTabIndex = class _RovingTabIndex {
228
229
  );
229
230
  if (char) {
230
231
  keys.add(char);
231
- attributesUtils.saveAttributes([focusable], ["aria-keyshortcuts"]);
232
+ attributesUtils.saveAttributes(focusable, "aria-keyshortcuts");
232
233
  attributesUtils.addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
233
234
  caseInsensitive: true
234
235
  });
@@ -253,7 +254,7 @@ var RovingTabIndex = class _RovingTabIndex {
253
254
  }
254
255
  #createSelectorFilter() {
255
256
  const { selector } = this.#settings;
256
- return (element) => !selector || element.matches(selector);
257
+ return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
257
258
  }
258
259
  #getFocusables() {
259
260
  return powerFocusable.getFocusables(this.#container, {
@@ -269,7 +270,7 @@ var RovingTabIndex = class _RovingTabIndex {
269
270
  * Lightweight roving tabindex utility with fully focus management.
270
271
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
271
272
  *
272
- * @version 3.1.16
273
+ * @version 3.1.18
273
274
  * @author Yusuke Kamiyamane
274
275
  * @license MIT
275
276
  * @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.16
6
+ * @version 3.1.18
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.16
6
+ * @version 3.1.18
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();
@@ -143,16 +143,16 @@ var RovingTabIndex = class _RovingTabIndex {
143
143
  if (!(active instanceof Element)) {
144
144
  return;
145
145
  }
146
- const current = this.#getFocusables().filter(
146
+ const candidates = this.#getFocusables().filter(
147
147
  (focusable2) => this.#focusables.has(focusable2)
148
148
  );
149
- if (!current.includes(active)) {
149
+ if (!candidates.includes(active)) {
150
150
  return;
151
151
  }
152
152
  event.preventDefault();
153
- const currentIndex = current.indexOf(active);
153
+ const activeIndex = candidates.indexOf(active);
154
154
  let newIndex;
155
- let target = current;
155
+ let target = candidates;
156
156
  switch (key) {
157
157
  case "End":
158
158
  newIndex = -1;
@@ -162,25 +162,26 @@ var RovingTabIndex = class _RovingTabIndex {
162
162
  break;
163
163
  case "ArrowLeft":
164
164
  case "ArrowUp": {
165
- const rawIndex = currentIndex - 1;
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 = currentIndex + 1;
172
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
171
+ const rawIndex = activeIndex + 1;
172
+ const length = target.length;
173
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
173
174
  break;
174
175
  }
175
176
  default: {
176
177
  const focusables = new Set(
177
178
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
178
179
  );
179
- target = current.filter((focusable2) => focusables.has(focusable2));
180
- const foundIndex = target.findIndex(
181
- (focusable2) => current.indexOf(focusable2) > currentIndex
180
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
181
+ const afterIndex = target.findIndex(
182
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
182
183
  );
183
- newIndex = foundIndex >= 0 ? foundIndex : 0;
184
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
184
185
  }
185
186
  }
186
187
  const focusable = target.at(newIndex);
@@ -191,7 +192,7 @@ var RovingTabIndex = class _RovingTabIndex {
191
192
  for (const focusable of this.#focusables) {
192
193
  if (!current.has(focusable)) {
193
194
  _RovingTabIndex.#initialized.delete(focusable);
194
- restoreAttributes([focusable]);
195
+ restoreAttributes(focusable);
195
196
  this.#focusables.delete(focusable);
196
197
  for (const [key, focusables] of this.#focusablesByFirstChar) {
197
198
  const index = focusables.indexOf(focusable);
@@ -213,7 +214,7 @@ var RovingTabIndex = class _RovingTabIndex {
213
214
  this.#focusables.add(focusable);
214
215
  _RovingTabIndex.#initialized.add(focusable);
215
216
  if (!navigationOnly) {
216
- saveAttributes([focusable], ["tabindex"]);
217
+ saveAttributes(focusable, "tabindex");
217
218
  focusable.setAttribute("tabindex", "-1");
218
219
  }
219
220
  if (!typeahead) {
@@ -226,7 +227,7 @@ var RovingTabIndex = class _RovingTabIndex {
226
227
  );
227
228
  if (char) {
228
229
  keys.add(char);
229
- saveAttributes([focusable], ["aria-keyshortcuts"]);
230
+ saveAttributes(focusable, "aria-keyshortcuts");
230
231
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
231
232
  caseInsensitive: true
232
233
  });
@@ -251,7 +252,7 @@ var RovingTabIndex = class _RovingTabIndex {
251
252
  }
252
253
  #createSelectorFilter() {
253
254
  const { selector } = this.#settings;
254
- return (element) => !selector || element.matches(selector);
255
+ return (element) => !selector || [...this.#container.querySelectorAll(selector)].includes(element);
255
256
  }
256
257
  #getFocusables() {
257
258
  return getFocusables(this.#container, {
@@ -267,7 +268,7 @@ var RovingTabIndex = class _RovingTabIndex {
267
268
  * Lightweight roving tabindex utility with fully focus management.
268
269
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
269
270
  *
270
- * @version 3.1.16
271
+ * @version 3.1.18
271
272
  * @author Yusuke Kamiyamane
272
273
  * @license MIT
273
274
  * @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.16",
3
+ "version": "3.1.18",
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
  }