@y14e/roving-tabindex 3.0.18 → 3.1.0

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
@@ -10,14 +10,14 @@ npm i @y14e/roving-tabindex
10
10
 
11
11
  ```ts
12
12
  // npm
13
- import { createRovingTabIndex } from '@y14e/roving-tabindex@3.0.18';
13
+ import { createRovingTabIndex } from '@y14e/roving-tabindex@3.1.0';
14
14
 
15
15
  // CDNs
16
- import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.0.18';
16
+ import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@3.1.0';
17
17
  // or
18
- import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.0.18/+esm';
18
+ import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@3.1.0/+esm';
19
19
  // or
20
- import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.0.18';
20
+ import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@3.1.0';
21
21
  ```
22
22
 
23
23
  ## 📦 APIs
@@ -118,6 +118,12 @@ function getFocusables(container = document.body, options = {}) {
118
118
  const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
119
119
  return filter ? unfiltered.filter(filter) : unfiltered;
120
120
  }
121
+ function getNextFocusable(container = document.body, options = {}) {
122
+ return getRelativeFocusable(container, 1, options);
123
+ }
124
+ function getPreviousFocusable(container = document.body, options = {}) {
125
+ return getRelativeFocusable(container, -1, options);
126
+ }
121
127
  function isFocusable(element, options = {}) {
122
128
  if (!(element instanceof Element)) {
123
129
  console.warn("Invalid element");
@@ -155,6 +161,84 @@ function isFocusable(element, options = {}) {
155
161
  }
156
162
  return true;
157
163
  }
164
+ function getRelativeFocusable(container, offset, options) {
165
+ if (!(container instanceof Element)) {
166
+ console.warn("Invalid container element. Fallback: <body> element.");
167
+ container = document.body;
168
+ }
169
+ let {
170
+ anchor = getActiveElement(),
171
+ composed = false,
172
+ filter,
173
+ include,
174
+ skipNegativeTabIndexCheck = false,
175
+ skipVisibilityCheck = false,
176
+ wrap = false
177
+ } = options;
178
+ if (!(anchor instanceof Element)) {
179
+ const active = getActiveElement();
180
+ if (active instanceof Element) {
181
+ console.warn("Invalid anchor element. Fallback: active element.");
182
+ anchor = active;
183
+ } else {
184
+ console.warn("Invalid anchor element");
185
+ return null;
186
+ }
187
+ }
188
+ if (!containsComposed(container, anchor)) {
189
+ console.warn("Anchor (active) element not within container");
190
+ return null;
191
+ }
192
+ if (typeof composed !== "boolean") {
193
+ console.warn("Invalid composed option. Fallback: false.");
194
+ composed = false;
195
+ }
196
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
197
+ console.warn(
198
+ "Invalid filter function. Fallback: no filter function (undefined)."
199
+ );
200
+ filter = void 0;
201
+ }
202
+ if (typeof include !== "undefined" && typeof include !== "function") {
203
+ console.warn(
204
+ "Invalid include function. Fallback: no include function (undefined)."
205
+ );
206
+ include = void 0;
207
+ }
208
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
209
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
210
+ skipNegativeTabIndexCheck = false;
211
+ }
212
+ if (typeof skipVisibilityCheck !== "boolean") {
213
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
214
+ skipVisibilityCheck = false;
215
+ }
216
+ if (typeof wrap !== "boolean") {
217
+ console.warn("Invalid wrap option. Fallback: false.");
218
+ wrap = false;
219
+ }
220
+ const settings = { composed, skipNegativeTabIndexCheck, skipVisibilityCheck };
221
+ if (filter !== void 0) {
222
+ Object.assign(settings, { filter });
223
+ }
224
+ if (include !== void 0) {
225
+ Object.assign(settings, { include });
226
+ }
227
+ const focusables = getFocusables(container, settings);
228
+ const { length } = focusables;
229
+ if (!length) {
230
+ return null;
231
+ }
232
+ const currentIndex = focusables.indexOf(anchor);
233
+ if (currentIndex === -1) {
234
+ return null;
235
+ }
236
+ const offsetIndex = currentIndex + offset;
237
+ if ((offsetIndex < 0 || offsetIndex >= length) && !wrap) {
238
+ return null;
239
+ }
240
+ return focusables[(offsetIndex + length) % length] ?? null;
241
+ }
158
242
  function isDisabledDeep(element) {
159
243
  let current = element;
160
244
  while (current) {
@@ -235,6 +319,17 @@ function sortByTabIndex(elements) {
235
319
  }
236
320
  return sorted;
237
321
  }
322
+ function containsComposed(container, element) {
323
+ let current = element;
324
+ while (current) {
325
+ if (current === container) {
326
+ return true;
327
+ } else {
328
+ current = current instanceof ShadowRoot ? current.mode === "open" ? current.host : null : current.parentNode;
329
+ }
330
+ }
331
+ return false;
332
+ }
238
333
  function getComposedChildren(node) {
239
334
  if (node instanceof ShadowRoot) {
240
335
  return getChildren(node);
@@ -411,13 +506,14 @@ var RovingTabIndex = class _RovingTabIndex {
411
506
  };
412
507
  #onKeyDown = (event) => {
413
508
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
414
- if (altKey || ctrlKey || metaKey || shiftKey) {
509
+ if (shiftKey && key !== "Tab" || altKey || ctrlKey || metaKey) {
415
510
  return;
416
511
  }
417
512
  const { direction, typeahead, wrap } = this.#settings;
418
513
  const isBoth = !direction;
419
514
  const isHorizontal = direction === "horizontal";
420
515
  if (![
516
+ "Tab",
421
517
  "End",
422
518
  "Home",
423
519
  ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
@@ -435,11 +531,14 @@ var RovingTabIndex = class _RovingTabIndex {
435
531
  if (!current.includes(active)) {
436
532
  return;
437
533
  }
438
- event.preventDefault();
534
+ let shouldPrevent = true;
439
535
  const currentIndex = current.indexOf(active);
440
- let newIndex;
536
+ let newIndex = 0;
441
537
  let target = current;
442
538
  switch (key) {
539
+ case "Tab":
540
+ shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
541
+ break;
443
542
  case "End":
444
543
  newIndex = -1;
445
544
  break;
@@ -461,13 +560,16 @@ var RovingTabIndex = class _RovingTabIndex {
461
560
  default: {
462
561
  target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
463
562
  const foundIndex = target.findIndex(
464
- (focusable2) => current.indexOf(focusable2) > currentIndex
563
+ (focusable) => current.indexOf(focusable) > currentIndex
465
564
  );
466
565
  newIndex = foundIndex >= 0 ? foundIndex : 0;
467
566
  }
468
567
  }
469
- const focusable = target.at(newIndex);
470
- focusable && focusElement(focusable);
568
+ shouldPrevent && event.preventDefault();
569
+ if (key !== "Tab") {
570
+ const focusable = target.at(newIndex);
571
+ focusable && focusElement(focusable);
572
+ }
471
573
  };
472
574
  #update(active) {
473
575
  const current = new Set(this.#getFocusables());
@@ -540,13 +642,24 @@ var RovingTabIndex = class _RovingTabIndex {
540
642
  skipVisibilityCheck: true
541
643
  });
542
644
  }
645
+ #moveFocus(direction) {
646
+ const options = {
647
+ composed: true
648
+ };
649
+ const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
650
+ if (focusable) {
651
+ focusElement(focusable);
652
+ return true;
653
+ }
654
+ return false;
655
+ }
543
656
  };
544
657
  /**
545
658
  * Roving Tabindex
546
659
  * Lightweight roving tabindex utility with fully focus management.
547
660
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
548
661
  *
549
- * @version 3.0.18
662
+ * @version 3.1.0
550
663
  * @author Yusuke Kamiyamane
551
664
  * @license MIT
552
665
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -116,6 +116,12 @@ function getFocusables(container = document.body, options = {}) {
116
116
  const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
117
117
  return filter ? unfiltered.filter(filter) : unfiltered;
118
118
  }
119
+ function getNextFocusable(container = document.body, options = {}) {
120
+ return getRelativeFocusable(container, 1, options);
121
+ }
122
+ function getPreviousFocusable(container = document.body, options = {}) {
123
+ return getRelativeFocusable(container, -1, options);
124
+ }
119
125
  function isFocusable(element, options = {}) {
120
126
  if (!(element instanceof Element)) {
121
127
  console.warn("Invalid element");
@@ -153,6 +159,84 @@ function isFocusable(element, options = {}) {
153
159
  }
154
160
  return true;
155
161
  }
162
+ function getRelativeFocusable(container, offset, options) {
163
+ if (!(container instanceof Element)) {
164
+ console.warn("Invalid container element. Fallback: <body> element.");
165
+ container = document.body;
166
+ }
167
+ let {
168
+ anchor = getActiveElement(),
169
+ composed = false,
170
+ filter,
171
+ include,
172
+ skipNegativeTabIndexCheck = false,
173
+ skipVisibilityCheck = false,
174
+ wrap = false
175
+ } = options;
176
+ if (!(anchor instanceof Element)) {
177
+ const active = getActiveElement();
178
+ if (active instanceof Element) {
179
+ console.warn("Invalid anchor element. Fallback: active element.");
180
+ anchor = active;
181
+ } else {
182
+ console.warn("Invalid anchor element");
183
+ return null;
184
+ }
185
+ }
186
+ if (!containsComposed(container, anchor)) {
187
+ console.warn("Anchor (active) element not within container");
188
+ return null;
189
+ }
190
+ if (typeof composed !== "boolean") {
191
+ console.warn("Invalid composed option. Fallback: false.");
192
+ composed = false;
193
+ }
194
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
195
+ console.warn(
196
+ "Invalid filter function. Fallback: no filter function (undefined)."
197
+ );
198
+ filter = void 0;
199
+ }
200
+ if (typeof include !== "undefined" && typeof include !== "function") {
201
+ console.warn(
202
+ "Invalid include function. Fallback: no include function (undefined)."
203
+ );
204
+ include = void 0;
205
+ }
206
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
207
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
208
+ skipNegativeTabIndexCheck = false;
209
+ }
210
+ if (typeof skipVisibilityCheck !== "boolean") {
211
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
212
+ skipVisibilityCheck = false;
213
+ }
214
+ if (typeof wrap !== "boolean") {
215
+ console.warn("Invalid wrap option. Fallback: false.");
216
+ wrap = false;
217
+ }
218
+ const settings = { composed, skipNegativeTabIndexCheck, skipVisibilityCheck };
219
+ if (filter !== void 0) {
220
+ Object.assign(settings, { filter });
221
+ }
222
+ if (include !== void 0) {
223
+ Object.assign(settings, { include });
224
+ }
225
+ const focusables = getFocusables(container, settings);
226
+ const { length } = focusables;
227
+ if (!length) {
228
+ return null;
229
+ }
230
+ const currentIndex = focusables.indexOf(anchor);
231
+ if (currentIndex === -1) {
232
+ return null;
233
+ }
234
+ const offsetIndex = currentIndex + offset;
235
+ if ((offsetIndex < 0 || offsetIndex >= length) && !wrap) {
236
+ return null;
237
+ }
238
+ return focusables[(offsetIndex + length) % length] ?? null;
239
+ }
156
240
  function isDisabledDeep(element) {
157
241
  let current = element;
158
242
  while (current) {
@@ -233,6 +317,17 @@ function sortByTabIndex(elements) {
233
317
  }
234
318
  return sorted;
235
319
  }
320
+ function containsComposed(container, element) {
321
+ let current = element;
322
+ while (current) {
323
+ if (current === container) {
324
+ return true;
325
+ } else {
326
+ current = current instanceof ShadowRoot ? current.mode === "open" ? current.host : null : current.parentNode;
327
+ }
328
+ }
329
+ return false;
330
+ }
236
331
  function getComposedChildren(node) {
237
332
  if (node instanceof ShadowRoot) {
238
333
  return getChildren(node);
@@ -409,13 +504,14 @@ var RovingTabIndex = class _RovingTabIndex {
409
504
  };
410
505
  #onKeyDown = (event) => {
411
506
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
412
- if (altKey || ctrlKey || metaKey || shiftKey) {
507
+ if (shiftKey && key !== "Tab" || altKey || ctrlKey || metaKey) {
413
508
  return;
414
509
  }
415
510
  const { direction, typeahead, wrap } = this.#settings;
416
511
  const isBoth = !direction;
417
512
  const isHorizontal = direction === "horizontal";
418
513
  if (![
514
+ "Tab",
419
515
  "End",
420
516
  "Home",
421
517
  ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
@@ -433,11 +529,14 @@ var RovingTabIndex = class _RovingTabIndex {
433
529
  if (!current.includes(active)) {
434
530
  return;
435
531
  }
436
- event.preventDefault();
532
+ let shouldPrevent = true;
437
533
  const currentIndex = current.indexOf(active);
438
- let newIndex;
534
+ let newIndex = 0;
439
535
  let target = current;
440
536
  switch (key) {
537
+ case "Tab":
538
+ shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
539
+ break;
441
540
  case "End":
442
541
  newIndex = -1;
443
542
  break;
@@ -459,13 +558,16 @@ var RovingTabIndex = class _RovingTabIndex {
459
558
  default: {
460
559
  target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
461
560
  const foundIndex = target.findIndex(
462
- (focusable2) => current.indexOf(focusable2) > currentIndex
561
+ (focusable) => current.indexOf(focusable) > currentIndex
463
562
  );
464
563
  newIndex = foundIndex >= 0 ? foundIndex : 0;
465
564
  }
466
565
  }
467
- const focusable = target.at(newIndex);
468
- focusable && focusElement(focusable);
566
+ shouldPrevent && event.preventDefault();
567
+ if (key !== "Tab") {
568
+ const focusable = target.at(newIndex);
569
+ focusable && focusElement(focusable);
570
+ }
469
571
  };
470
572
  #update(active) {
471
573
  const current = new Set(this.#getFocusables());
@@ -538,13 +640,24 @@ var RovingTabIndex = class _RovingTabIndex {
538
640
  skipVisibilityCheck: true
539
641
  });
540
642
  }
643
+ #moveFocus(direction) {
644
+ const options = {
645
+ composed: true
646
+ };
647
+ const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
648
+ if (focusable) {
649
+ focusElement(focusable);
650
+ return true;
651
+ }
652
+ return false;
653
+ }
541
654
  };
542
655
  /**
543
656
  * Roving Tabindex
544
657
  * Lightweight roving tabindex utility with fully focus management.
545
658
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
546
659
  *
547
- * @version 3.0.18
660
+ * @version 3.1.0
548
661
  * @author Yusuke Kamiyamane
549
662
  * @license MIT
550
663
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -127,13 +127,14 @@ var RovingTabIndex = class _RovingTabIndex {
127
127
  };
128
128
  #onKeyDown = (event) => {
129
129
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
130
- if (altKey || ctrlKey || metaKey || shiftKey) {
130
+ if (shiftKey && key !== "Tab" || altKey || ctrlKey || metaKey) {
131
131
  return;
132
132
  }
133
133
  const { direction, typeahead, wrap } = this.#settings;
134
134
  const isBoth = !direction;
135
135
  const isHorizontal = direction === "horizontal";
136
136
  if (![
137
+ "Tab",
137
138
  "End",
138
139
  "Home",
139
140
  ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
@@ -151,11 +152,14 @@ var RovingTabIndex = class _RovingTabIndex {
151
152
  if (!current.includes(active)) {
152
153
  return;
153
154
  }
154
- event.preventDefault();
155
+ let shouldPrevent = true;
155
156
  const currentIndex = current.indexOf(active);
156
- let newIndex;
157
+ let newIndex = 0;
157
158
  let target = current;
158
159
  switch (key) {
160
+ case "Tab":
161
+ shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
162
+ break;
159
163
  case "End":
160
164
  newIndex = -1;
161
165
  break;
@@ -177,13 +181,16 @@ var RovingTabIndex = class _RovingTabIndex {
177
181
  default: {
178
182
  target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
179
183
  const foundIndex = target.findIndex(
180
- (focusable2) => current.indexOf(focusable2) > currentIndex
184
+ (focusable) => current.indexOf(focusable) > currentIndex
181
185
  );
182
186
  newIndex = foundIndex >= 0 ? foundIndex : 0;
183
187
  }
184
188
  }
185
- const focusable = target.at(newIndex);
186
- focusable && powerFocusable.focusElement(focusable);
189
+ shouldPrevent && event.preventDefault();
190
+ if (key !== "Tab") {
191
+ const focusable = target.at(newIndex);
192
+ focusable && powerFocusable.focusElement(focusable);
193
+ }
187
194
  };
188
195
  #update(active) {
189
196
  const current = new Set(this.#getFocusables());
@@ -256,13 +263,24 @@ var RovingTabIndex = class _RovingTabIndex {
256
263
  skipVisibilityCheck: true
257
264
  });
258
265
  }
266
+ #moveFocus(direction) {
267
+ const options = {
268
+ composed: true
269
+ };
270
+ const focusable = direction === "previous" ? powerFocusable.getPreviousFocusable(document.body, options) : powerFocusable.getNextFocusable(document.body, options);
271
+ if (focusable) {
272
+ powerFocusable.focusElement(focusable);
273
+ return true;
274
+ }
275
+ return false;
276
+ }
259
277
  };
260
278
  /**
261
279
  * Roving Tabindex
262
280
  * Lightweight roving tabindex utility with fully focus management.
263
281
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
264
282
  *
265
- * @version 3.0.18
283
+ * @version 3.1.0
266
284
  * @author Yusuke Kamiyamane
267
285
  * @license MIT
268
286
  * @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.0.18
6
+ * @version 3.1.0
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.0.18
6
+ * @version 3.1.0
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { restoreAttributes, saveAttributes, addTokenToAttribute } from '@y14e/attributes-utils';
2
- import { getActiveElement, focusElement, getFocusables } from 'power-focusable';
2
+ import { getActiveElement, focusElement, getFocusables, getPreviousFocusable, getNextFocusable } from 'power-focusable';
3
3
 
4
4
  // src/index.ts
5
5
  function createRovingTabIndex(container, options = {}) {
@@ -125,13 +125,14 @@ var RovingTabIndex = class _RovingTabIndex {
125
125
  };
126
126
  #onKeyDown = (event) => {
127
127
  const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
128
- if (altKey || ctrlKey || metaKey || shiftKey) {
128
+ if (shiftKey && key !== "Tab" || altKey || ctrlKey || metaKey) {
129
129
  return;
130
130
  }
131
131
  const { direction, typeahead, wrap } = this.#settings;
132
132
  const isBoth = !direction;
133
133
  const isHorizontal = direction === "horizontal";
134
134
  if (![
135
+ "Tab",
135
136
  "End",
136
137
  "Home",
137
138
  ...isBoth ? ["ArrowLeft", "ArrowUp"] : [`Arrow${isHorizontal ? "Left" : "Up"}`],
@@ -149,11 +150,14 @@ var RovingTabIndex = class _RovingTabIndex {
149
150
  if (!current.includes(active)) {
150
151
  return;
151
152
  }
152
- event.preventDefault();
153
+ let shouldPrevent = true;
153
154
  const currentIndex = current.indexOf(active);
154
- let newIndex;
155
+ let newIndex = 0;
155
156
  let target = current;
156
157
  switch (key) {
158
+ case "Tab":
159
+ shouldPrevent = this.#moveFocus(shiftKey ? "previous" : "next");
160
+ break;
157
161
  case "End":
158
162
  newIndex = -1;
159
163
  break;
@@ -175,13 +179,16 @@ var RovingTabIndex = class _RovingTabIndex {
175
179
  default: {
176
180
  target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
177
181
  const foundIndex = target.findIndex(
178
- (focusable2) => current.indexOf(focusable2) > currentIndex
182
+ (focusable) => current.indexOf(focusable) > currentIndex
179
183
  );
180
184
  newIndex = foundIndex >= 0 ? foundIndex : 0;
181
185
  }
182
186
  }
183
- const focusable = target.at(newIndex);
184
- focusable && focusElement(focusable);
187
+ shouldPrevent && event.preventDefault();
188
+ if (key !== "Tab") {
189
+ const focusable = target.at(newIndex);
190
+ focusable && focusElement(focusable);
191
+ }
185
192
  };
186
193
  #update(active) {
187
194
  const current = new Set(this.#getFocusables());
@@ -254,13 +261,24 @@ var RovingTabIndex = class _RovingTabIndex {
254
261
  skipVisibilityCheck: true
255
262
  });
256
263
  }
264
+ #moveFocus(direction) {
265
+ const options = {
266
+ composed: true
267
+ };
268
+ const focusable = direction === "previous" ? getPreviousFocusable(document.body, options) : getNextFocusable(document.body, options);
269
+ if (focusable) {
270
+ focusElement(focusable);
271
+ return true;
272
+ }
273
+ return false;
274
+ }
257
275
  };
258
276
  /**
259
277
  * Roving Tabindex
260
278
  * Lightweight roving tabindex utility with fully focus management.
261
279
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
262
280
  *
263
- * @version 3.0.18
281
+ * @version 3.1.0
264
282
  * @author Yusuke Kamiyamane
265
283
  * @license MIT
266
284
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/roving-tabindex",
3
- "version": "3.0.18",
3
+ "version": "3.1.0",
4
4
  "description": "Lightweight roving tabindex utility with fully focus management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",