@y14e/roving-tabindex 2.0.7 → 2.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@2.0.7';
13
+ import { createRovingTabIndex } from '@y14e/roving-tabindex@2.1.0';
14
14
 
15
15
  // CDNs
16
- import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@2.0.7';
16
+ import { createRovingTabIndex } from 'https://esm.sh/@y14e/roving-tabindex@2.1.0';
17
17
  // or
18
- import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@2.0.7/+esm';
18
+ import { createRovingTabIndex } from 'https://cdn.jsdelivr.net/npm/@y14e/roving-tabindex@2.1.0/+esm';
19
19
  // or
20
- import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@2.0.7';
20
+ import { createRovingTabIndex } from 'https://esm.unpkg.com/@y14e/roving-tabindex@2.1.0';
21
21
  ```
22
22
 
23
23
  ## 📦 APIs
@@ -40,6 +40,7 @@ const cleanup = createRovingTabIndex(container, options);
40
40
  interface RovingTabIndexOptions {
41
41
  direction?: 'horizontal' | 'vertical'; // default: both (undefined)
42
42
  navigationOnly?: boolean; // default: false
43
+ noMemory?: boolean; // default: false
43
44
  selector?: string;
44
45
  typeahead?: boolean; // default: false
45
46
  wrap?: boolean; // default: false
@@ -50,6 +51,10 @@ interface RovingTabIndexOptions {
50
51
 
51
52
  If `true`, enables keyboard navigation without modifying `tabindex`. Useful for widgets like accordions where all items should remain tabbable while still supporting arrow key navigation.
52
53
 
54
+ ### `noMemory`
55
+
56
+ If `true`, disables focus memory. Focus always starts from the first item.
57
+
53
58
  ### `typeahead`
54
59
 
55
60
  If `true`, enables character-based focus navigation. Typing a character moves focus to the next matching element.
package/dist/index.cjs CHANGED
@@ -13,11 +13,10 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
13
13
  const tokens = value ? parse(value).filter(Boolean) : [];
14
14
  if (caseInsensitive) {
15
15
  const lower = token.toLowerCase();
16
- if (tokens.some((token2) => token2.toLowerCase() === lower)) {
17
- return;
16
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
17
+ tokens.push(token);
18
+ element.setAttribute(attribute, serialize(tokens));
18
19
  }
19
- tokens.push(token);
20
- element.setAttribute(attribute, serialize(tokens));
21
20
  return;
22
21
  }
23
22
  const set = new Set(tokens);
@@ -300,6 +299,7 @@ function createRovingTabIndex(container, options = {}) {
300
299
  let {
301
300
  direction,
302
301
  navigationOnly = false,
302
+ noMemory = false,
303
303
  selector,
304
304
  typeahead = false,
305
305
  wrap = false
@@ -312,6 +312,10 @@ function createRovingTabIndex(container, options = {}) {
312
312
  console.warn("Invalid navigationOnly option. Fallback: false.");
313
313
  navigationOnly = false;
314
314
  }
315
+ if (typeof noMemory !== "boolean") {
316
+ console.warn("Invalid noMemory option. Fallback: false.");
317
+ noMemory = false;
318
+ }
315
319
  if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
316
320
  console.warn(
317
321
  "Invalid selector. Fallback: all focusable elements (undefined)."
@@ -326,7 +330,7 @@ function createRovingTabIndex(container, options = {}) {
326
330
  console.warn("Invalid wrap option. Fallback: false.");
327
331
  wrap = false;
328
332
  }
329
- const settings = { navigationOnly, typeahead, wrap };
333
+ const settings = { navigationOnly, noMemory, typeahead, wrap };
330
334
  direction && Object.assign(settings, { direction });
331
335
  selector && Object.assign(settings, { selector });
332
336
  const roving = new RovingTabIndex(container, settings);
@@ -374,10 +378,15 @@ var RovingTabIndex = class {
374
378
  }
375
379
  #onFocusIn = (event) => {
376
380
  const { target } = event;
377
- if (!(target instanceof Element) || !this.#focusables.has(target)) {
381
+ if (!(target instanceof Element)) {
382
+ return;
383
+ }
384
+ const isFocusable2 = this.#focusables.has(target);
385
+ if (this.#options.noMemory && !isFocusable2) {
386
+ this.#update(null);
378
387
  return;
379
388
  }
380
- this.#update(target);
389
+ isFocusable2 && this.#update(target);
381
390
  };
382
391
  #onKeyDown = (event) => {
383
392
  if (!event.composedPath().includes(this.#container)) {
@@ -527,7 +536,7 @@ function getActiveElement() {
527
536
  * Lightweight roving tabindex utility with fully focus management.
528
537
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
529
538
  *
530
- * @version 2.0.7
539
+ * @version 2.1.0
531
540
  * @author Yusuke Kamiyamane
532
541
  * @license MIT
533
542
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -539,7 +548,7 @@ function getActiveElement() {
539
548
  (**
540
549
  * Attributes Utils
541
550
  *
542
- * @version 1.1.0
551
+ * @version 1.1.1
543
552
  * @author Yusuke Kamiyamane
544
553
  * @license MIT
545
554
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -552,7 +561,7 @@ power-focusable/dist/index.js:
552
561
  * High-precision focus management utility with full composed tree support.
553
562
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
554
563
  *
555
- * @version 4.3.1
564
+ * @version 4.3.2
556
565
  * @author Yusuke Kamiyamane
557
566
  * @license MIT
558
567
  * @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 2.0.7
6
+ * @version 2.1.0
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -12,6 +12,7 @@
12
12
  interface RovingTabIndexOptions {
13
13
  readonly direction?: 'horizontal' | 'vertical';
14
14
  readonly navigationOnly?: boolean;
15
+ readonly noMemory?: boolean;
15
16
  readonly selector?: string;
16
17
  readonly typeahead?: boolean;
17
18
  readonly wrap?: boolean;
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 2.0.7
6
+ * @version 2.1.0
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -12,6 +12,7 @@
12
12
  interface RovingTabIndexOptions {
13
13
  readonly direction?: 'horizontal' | 'vertical';
14
14
  readonly navigationOnly?: boolean;
15
+ readonly noMemory?: boolean;
15
16
  readonly selector?: string;
16
17
  readonly typeahead?: boolean;
17
18
  readonly wrap?: boolean;
package/dist/index.js CHANGED
@@ -11,11 +11,10 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
11
11
  const tokens = value ? parse(value).filter(Boolean) : [];
12
12
  if (caseInsensitive) {
13
13
  const lower = token.toLowerCase();
14
- if (tokens.some((token2) => token2.toLowerCase() === lower)) {
15
- return;
14
+ if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
15
+ tokens.push(token);
16
+ element.setAttribute(attribute, serialize(tokens));
16
17
  }
17
- tokens.push(token);
18
- element.setAttribute(attribute, serialize(tokens));
19
18
  return;
20
19
  }
21
20
  const set = new Set(tokens);
@@ -298,6 +297,7 @@ function createRovingTabIndex(container, options = {}) {
298
297
  let {
299
298
  direction,
300
299
  navigationOnly = false,
300
+ noMemory = false,
301
301
  selector,
302
302
  typeahead = false,
303
303
  wrap = false
@@ -310,6 +310,10 @@ function createRovingTabIndex(container, options = {}) {
310
310
  console.warn("Invalid navigationOnly option. Fallback: false.");
311
311
  navigationOnly = false;
312
312
  }
313
+ if (typeof noMemory !== "boolean") {
314
+ console.warn("Invalid noMemory option. Fallback: false.");
315
+ noMemory = false;
316
+ }
313
317
  if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
314
318
  console.warn(
315
319
  "Invalid selector. Fallback: all focusable elements (undefined)."
@@ -324,7 +328,7 @@ function createRovingTabIndex(container, options = {}) {
324
328
  console.warn("Invalid wrap option. Fallback: false.");
325
329
  wrap = false;
326
330
  }
327
- const settings = { navigationOnly, typeahead, wrap };
331
+ const settings = { navigationOnly, noMemory, typeahead, wrap };
328
332
  direction && Object.assign(settings, { direction });
329
333
  selector && Object.assign(settings, { selector });
330
334
  const roving = new RovingTabIndex(container, settings);
@@ -372,10 +376,15 @@ var RovingTabIndex = class {
372
376
  }
373
377
  #onFocusIn = (event) => {
374
378
  const { target } = event;
375
- if (!(target instanceof Element) || !this.#focusables.has(target)) {
379
+ if (!(target instanceof Element)) {
380
+ return;
381
+ }
382
+ const isFocusable2 = this.#focusables.has(target);
383
+ if (this.#options.noMemory && !isFocusable2) {
384
+ this.#update(null);
376
385
  return;
377
386
  }
378
- this.#update(target);
387
+ isFocusable2 && this.#update(target);
379
388
  };
380
389
  #onKeyDown = (event) => {
381
390
  if (!event.composedPath().includes(this.#container)) {
@@ -525,7 +534,7 @@ function getActiveElement() {
525
534
  * Lightweight roving tabindex utility with fully focus management.
526
535
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
527
536
  *
528
- * @version 2.0.7
537
+ * @version 2.1.0
529
538
  * @author Yusuke Kamiyamane
530
539
  * @license MIT
531
540
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -537,7 +546,7 @@ function getActiveElement() {
537
546
  (**
538
547
  * Attributes Utils
539
548
  *
540
- * @version 1.1.0
549
+ * @version 1.1.1
541
550
  * @author Yusuke Kamiyamane
542
551
  * @license MIT
543
552
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -550,7 +559,7 @@ power-focusable/dist/index.js:
550
559
  * High-precision focus management utility with full composed tree support.
551
560
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
552
561
  *
553
- * @version 4.3.1
562
+ * @version 4.3.2
554
563
  * @author Yusuke Kamiyamane
555
564
  * @license MIT
556
565
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/roving-tabindex",
3
- "version": "2.0.7",
3
+ "version": "2.1.0",
4
4
  "description": "Lightweight roving tabindex utility with fully focus management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -48,9 +48,9 @@
48
48
  },
49
49
  "homepage": "https://github.com/y14e/roving-tabindex#readme",
50
50
  "devDependencies": {
51
- "@y14e/attributes-utils": "^1.1.0",
51
+ "@y14e/attributes-utils": "^1.1.1",
52
52
  "bun-types": "latest",
53
- "power-focusable": "^4.3.1",
53
+ "power-focusable": "^4.3.2",
54
54
  "tsup": "^8.0.0",
55
55
  "typescript": "^5.6.0"
56
56
  },