@y14e/roving-tabindex 3.1.13 → 3.1.15

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.13';
16
+ import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.1.15';
17
17
  // or
18
- import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.13/+esm';
18
+ import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.15/+esm';
19
19
  // or
20
- import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.13';
20
+ import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.15';
21
21
  ```
22
22
 
23
23
  ## 📦 APIs
@@ -51,7 +51,7 @@ function saveAttributes(elements, attributes) {
51
51
 
52
52
  // node_modules/power-focusable/dist/index.js
53
53
  var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
54
- var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX = FOCUSABLE_SELECTOR.replace(
54
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
55
55
  /(,\s*)?\[tabindex="-1"\]/g,
56
56
  ""
57
57
  );
@@ -91,14 +91,14 @@ function getFocusables(container = document.body, options = {}) {
91
91
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
92
92
  skipVisibilityCheck = false;
93
93
  }
94
- const elements = [];
94
+ const candidates = [];
95
95
  if (composed || include) {
96
96
  let traverse2 = function(node) {
97
97
  if (isFocusable(node, {
98
98
  skipNegativeTabIndexCheck,
99
99
  skipVisibilityCheck
100
100
  }) || include?.(node)) {
101
- elements[elements.length] = node;
101
+ candidates[candidates.length] = node;
102
102
  }
103
103
  const children2 = composed ? getComposedChildren(node) : getChildren(node);
104
104
  for (let i = 0, l = children2.length; i < l; i++) {
@@ -112,21 +112,22 @@ function getFocusables(container = document.body, options = {}) {
112
112
  child && traverse2(child);
113
113
  }
114
114
  } else {
115
- const candidates = container.querySelectorAll(
116
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX : FOCUSABLE_SELECTOR
115
+ const matches = container.querySelectorAll(
116
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
117
117
  );
118
- for (let i = 0, l = candidates.length; i < l; i++) {
119
- const candidate = candidates[i];
120
- if (candidate && isFocusable(candidate, {
118
+ for (let i = 0, l = matches.length; i < l; i++) {
119
+ const matched = matches[i];
120
+ if (matched && isFocusable(matched, {
121
121
  skipNegativeTabIndexCheck,
122
122
  skipVisibilityCheck
123
123
  })) {
124
- elements[elements.length] = candidate;
124
+ candidates[candidates.length] = matched;
125
125
  }
126
126
  }
127
127
  }
128
- const filtered = filter ? elements.filter(filter) : elements;
129
- return normalizeRadioGroup(sortByTabIndex(filtered));
128
+ return normalizeRadioGroup(
129
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
130
+ );
130
131
  }
131
132
  function isFocusable(element, options = {}) {
132
133
  if (!(element instanceof Element)) {
@@ -149,7 +150,7 @@ function isFocusable(element, options = {}) {
149
150
  return false;
150
151
  }
151
152
  if (!element.matches(
152
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX : FOCUSABLE_SELECTOR
153
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
153
154
  )) {
154
155
  return false;
155
156
  }
@@ -195,7 +196,7 @@ function isDisabledDeep(element) {
195
196
  return false;
196
197
  }
197
198
  function normalizeRadioGroup(elements) {
198
- let rootMap = null;
199
+ let map = null;
199
200
  for (let i = 0, l = elements.length; i < l; i++) {
200
201
  const element = elements[i];
201
202
  if (!(element instanceof HTMLInputElement)) {
@@ -204,35 +205,35 @@ function normalizeRadioGroup(elements) {
204
205
  if (!isUngroupedRadio(element)) {
205
206
  continue;
206
207
  }
207
- if (!rootMap) {
208
- rootMap = /* @__PURE__ */ new Map();
208
+ if (!map) {
209
+ map = /* @__PURE__ */ new Map();
209
210
  }
210
211
  const root = element.getRootNode();
211
- let formMap = rootMap.get(root);
212
- if (!formMap) {
213
- formMap = /* @__PURE__ */ new Map();
214
- rootMap.set(root, formMap);
212
+ let value = map.get(root);
213
+ if (!value) {
214
+ value = /* @__PURE__ */ new Map();
215
+ map.set(root, value);
215
216
  }
216
- let nameMap = formMap.get(element.form);
217
- if (!nameMap) {
218
- nameMap = /* @__PURE__ */ new Map();
219
- formMap.set(element.form, nameMap);
217
+ let v = value.get(element.form);
218
+ if (!v) {
219
+ v = /* @__PURE__ */ new Map();
220
+ value.set(element.form, v);
220
221
  }
221
- let group = nameMap.get(element.name);
222
- if (!group) {
223
- group = [];
224
- nameMap.set(element.name, group);
222
+ let vv = v.get(element.name);
223
+ if (!vv) {
224
+ vv = [];
225
+ v.set(element.name, vv);
225
226
  }
226
- group[group.length] = element;
227
+ vv[vv.length] = element;
227
228
  }
228
- if (!rootMap) {
229
+ if (!map) {
229
230
  return elements;
230
231
  }
231
232
  const placeholder = /* @__PURE__ */ new Set();
232
- for (const formMap of rootMap.values()) {
233
- for (const nameMap of formMap.values()) {
234
- for (const group of nameMap.values()) {
235
- const radio = group.find((element) => element.checked) ?? group[0];
233
+ for (const value of map.values()) {
234
+ for (const v of value.values()) {
235
+ for (const vv of v.values()) {
236
+ const radio = vv.find((element) => element.checked) ?? vv[0];
236
237
  radio && placeholder.add(radio);
237
238
  }
238
239
  }
@@ -459,16 +460,16 @@ var RovingTabIndex = class _RovingTabIndex {
459
460
  if (!(active instanceof Element)) {
460
461
  return;
461
462
  }
462
- const current = this.#getFocusables().filter(
463
+ const candidates = this.#getFocusables().filter(
463
464
  (focusable2) => this.#focusables.has(focusable2)
464
465
  );
465
- if (!current.includes(active)) {
466
+ if (!candidates.includes(active)) {
466
467
  return;
467
468
  }
468
469
  event.preventDefault();
469
- const currentIndex = current.indexOf(active);
470
+ const activeIndex = candidates.indexOf(active);
470
471
  let newIndex;
471
- let target = current;
472
+ let target = candidates;
472
473
  switch (key) {
473
474
  case "End":
474
475
  newIndex = -1;
@@ -478,25 +479,26 @@ var RovingTabIndex = class _RovingTabIndex {
478
479
  break;
479
480
  case "ArrowLeft":
480
481
  case "ArrowUp": {
481
- const rawIndex = currentIndex - 1;
482
+ const rawIndex = activeIndex - 1;
482
483
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
483
484
  break;
484
485
  }
485
486
  case "ArrowRight":
486
487
  case "ArrowDown": {
487
- const rawIndex = currentIndex + 1;
488
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
488
+ const rawIndex = activeIndex + 1;
489
+ const length = target.length;
490
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
489
491
  break;
490
492
  }
491
493
  default: {
492
494
  const focusables = new Set(
493
495
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
494
496
  );
495
- target = current.filter((focusable2) => focusables.has(focusable2));
496
- const foundIndex = target.findIndex(
497
- (focusable2) => current.indexOf(focusable2) > currentIndex
497
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
498
+ const afterIndex = target.findIndex(
499
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
498
500
  );
499
- newIndex = foundIndex >= 0 ? foundIndex : 0;
501
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
500
502
  }
501
503
  }
502
504
  const focusable = target.at(newIndex);
@@ -583,7 +585,7 @@ var RovingTabIndex = class _RovingTabIndex {
583
585
  * Lightweight roving tabindex utility with fully focus management.
584
586
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
585
587
  *
586
- * @version 3.1.13
588
+ * @version 3.1.15
587
589
  * @author Yusuke Kamiyamane
588
590
  * @license MIT
589
591
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -608,7 +610,7 @@ power-focusable/dist/index.js:
608
610
  * High-precision focus management utility with full composed tree support.
609
611
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
610
612
  *
611
- * @version 4.3.12
613
+ * @version 4.3.19
612
614
  * @author Yusuke Kamiyamane
613
615
  * @license MIT
614
616
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -49,7 +49,7 @@ function saveAttributes(elements, attributes) {
49
49
 
50
50
  // node_modules/power-focusable/dist/index.js
51
51
  var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
52
- var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX = FOCUSABLE_SELECTOR.replace(
52
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
53
53
  /(,\s*)?\[tabindex="-1"\]/g,
54
54
  ""
55
55
  );
@@ -89,14 +89,14 @@ function getFocusables(container = document.body, options = {}) {
89
89
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
90
90
  skipVisibilityCheck = false;
91
91
  }
92
- const elements = [];
92
+ const candidates = [];
93
93
  if (composed || include) {
94
94
  let traverse2 = function(node) {
95
95
  if (isFocusable(node, {
96
96
  skipNegativeTabIndexCheck,
97
97
  skipVisibilityCheck
98
98
  }) || include?.(node)) {
99
- elements[elements.length] = node;
99
+ candidates[candidates.length] = node;
100
100
  }
101
101
  const children2 = composed ? getComposedChildren(node) : getChildren(node);
102
102
  for (let i = 0, l = children2.length; i < l; i++) {
@@ -110,21 +110,22 @@ function getFocusables(container = document.body, options = {}) {
110
110
  child && traverse2(child);
111
111
  }
112
112
  } else {
113
- const candidates = container.querySelectorAll(
114
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX : FOCUSABLE_SELECTOR
113
+ const matches = container.querySelectorAll(
114
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
115
115
  );
116
- for (let i = 0, l = candidates.length; i < l; i++) {
117
- const candidate = candidates[i];
118
- if (candidate && isFocusable(candidate, {
116
+ for (let i = 0, l = matches.length; i < l; i++) {
117
+ const matched = matches[i];
118
+ if (matched && isFocusable(matched, {
119
119
  skipNegativeTabIndexCheck,
120
120
  skipVisibilityCheck
121
121
  })) {
122
- elements[elements.length] = candidate;
122
+ candidates[candidates.length] = matched;
123
123
  }
124
124
  }
125
125
  }
126
- const filtered = filter ? elements.filter(filter) : elements;
127
- return normalizeRadioGroup(sortByTabIndex(filtered));
126
+ return normalizeRadioGroup(
127
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
128
+ );
128
129
  }
129
130
  function isFocusable(element, options = {}) {
130
131
  if (!(element instanceof Element)) {
@@ -147,7 +148,7 @@ function isFocusable(element, options = {}) {
147
148
  return false;
148
149
  }
149
150
  if (!element.matches(
150
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TAB_INDEX : FOCUSABLE_SELECTOR
151
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
151
152
  )) {
152
153
  return false;
153
154
  }
@@ -193,7 +194,7 @@ function isDisabledDeep(element) {
193
194
  return false;
194
195
  }
195
196
  function normalizeRadioGroup(elements) {
196
- let rootMap = null;
197
+ let map = null;
197
198
  for (let i = 0, l = elements.length; i < l; i++) {
198
199
  const element = elements[i];
199
200
  if (!(element instanceof HTMLInputElement)) {
@@ -202,35 +203,35 @@ function normalizeRadioGroup(elements) {
202
203
  if (!isUngroupedRadio(element)) {
203
204
  continue;
204
205
  }
205
- if (!rootMap) {
206
- rootMap = /* @__PURE__ */ new Map();
206
+ if (!map) {
207
+ map = /* @__PURE__ */ new Map();
207
208
  }
208
209
  const root = element.getRootNode();
209
- let formMap = rootMap.get(root);
210
- if (!formMap) {
211
- formMap = /* @__PURE__ */ new Map();
212
- rootMap.set(root, formMap);
210
+ let value = map.get(root);
211
+ if (!value) {
212
+ value = /* @__PURE__ */ new Map();
213
+ map.set(root, value);
213
214
  }
214
- let nameMap = formMap.get(element.form);
215
- if (!nameMap) {
216
- nameMap = /* @__PURE__ */ new Map();
217
- formMap.set(element.form, nameMap);
215
+ let v = value.get(element.form);
216
+ if (!v) {
217
+ v = /* @__PURE__ */ new Map();
218
+ value.set(element.form, v);
218
219
  }
219
- let group = nameMap.get(element.name);
220
- if (!group) {
221
- group = [];
222
- nameMap.set(element.name, group);
220
+ let vv = v.get(element.name);
221
+ if (!vv) {
222
+ vv = [];
223
+ v.set(element.name, vv);
223
224
  }
224
- group[group.length] = element;
225
+ vv[vv.length] = element;
225
226
  }
226
- if (!rootMap) {
227
+ if (!map) {
227
228
  return elements;
228
229
  }
229
230
  const placeholder = /* @__PURE__ */ new Set();
230
- for (const formMap of rootMap.values()) {
231
- for (const nameMap of formMap.values()) {
232
- for (const group of nameMap.values()) {
233
- const radio = group.find((element) => element.checked) ?? group[0];
231
+ for (const value of map.values()) {
232
+ for (const v of value.values()) {
233
+ for (const vv of v.values()) {
234
+ const radio = vv.find((element) => element.checked) ?? vv[0];
234
235
  radio && placeholder.add(radio);
235
236
  }
236
237
  }
@@ -457,16 +458,16 @@ var RovingTabIndex = class _RovingTabIndex {
457
458
  if (!(active instanceof Element)) {
458
459
  return;
459
460
  }
460
- const current = this.#getFocusables().filter(
461
+ const candidates = this.#getFocusables().filter(
461
462
  (focusable2) => this.#focusables.has(focusable2)
462
463
  );
463
- if (!current.includes(active)) {
464
+ if (!candidates.includes(active)) {
464
465
  return;
465
466
  }
466
467
  event.preventDefault();
467
- const currentIndex = current.indexOf(active);
468
+ const activeIndex = candidates.indexOf(active);
468
469
  let newIndex;
469
- let target = current;
470
+ let target = candidates;
470
471
  switch (key) {
471
472
  case "End":
472
473
  newIndex = -1;
@@ -476,25 +477,26 @@ var RovingTabIndex = class _RovingTabIndex {
476
477
  break;
477
478
  case "ArrowLeft":
478
479
  case "ArrowUp": {
479
- const rawIndex = currentIndex - 1;
480
+ const rawIndex = activeIndex - 1;
480
481
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
481
482
  break;
482
483
  }
483
484
  case "ArrowRight":
484
485
  case "ArrowDown": {
485
- const rawIndex = currentIndex + 1;
486
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
486
+ const rawIndex = activeIndex + 1;
487
+ const length = target.length;
488
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
487
489
  break;
488
490
  }
489
491
  default: {
490
492
  const focusables = new Set(
491
493
  this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
492
494
  );
493
- target = current.filter((focusable2) => focusables.has(focusable2));
494
- const foundIndex = target.findIndex(
495
- (focusable2) => current.indexOf(focusable2) > currentIndex
495
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
496
+ const afterIndex = target.findIndex(
497
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
496
498
  );
497
- newIndex = foundIndex >= 0 ? foundIndex : 0;
499
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
498
500
  }
499
501
  }
500
502
  const focusable = target.at(newIndex);
@@ -581,7 +583,7 @@ var RovingTabIndex = class _RovingTabIndex {
581
583
  * Lightweight roving tabindex utility with fully focus management.
582
584
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
583
585
  *
584
- * @version 3.1.13
586
+ * @version 3.1.15
585
587
  * @author Yusuke Kamiyamane
586
588
  * @license MIT
587
589
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -606,7 +608,7 @@ power-focusable/dist/index.js:
606
608
  * High-precision focus management utility with full composed tree support.
607
609
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
608
610
  *
609
- * @version 4.3.12
611
+ * @version 4.3.19
610
612
  * @author Yusuke Kamiyamane
611
613
  * @license MIT
612
614
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -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);
@@ -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.13
273
+ * @version 3.1.15
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.13
6
+ * @version 3.1.15
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.13
6
+ * @version 3.1.15
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -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);
@@ -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.13
271
+ * @version 3.1.15
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.13",
3
+ "version": "3.1.15",
4
4
  "description": "Lightweight roving tabindex utility with fully focus management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -57,6 +57,6 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@y14e/attributes-utils": "^1.1.3",
60
- "power-focusable": "^4.3.12"
60
+ "power-focusable": "^4.3.19"
61
61
  }
62
62
  }