@y14e/roving-tabindex 1.3.1 → 2.0.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/dist/index.cjs CHANGED
@@ -61,6 +61,7 @@ function getFocusables(container = document.body, options = {}) {
61
61
  composed = false,
62
62
  filter,
63
63
  include,
64
+ skipNegativeTabIndexCheck = false,
64
65
  skipVisibilityCheck = false
65
66
  } = options;
66
67
  if (typeof composed !== "boolean") {
@@ -79,11 +80,22 @@ function getFocusables(container = document.body, options = {}) {
79
80
  );
80
81
  include = void 0;
81
82
  }
83
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
84
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
85
+ skipNegativeTabIndexCheck = false;
86
+ }
87
+ if (typeof skipVisibilityCheck !== "boolean") {
88
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
89
+ skipVisibilityCheck = false;
90
+ }
82
91
  const elements = [];
83
92
  if (composed || include) {
84
93
  let traverse2 = function(node) {
85
94
  if (node instanceof Element) {
86
- if (isFocusable(node, { skipVisibilityCheck }) || include?.(node)) {
95
+ if (isFocusable(node, {
96
+ skipNegativeTabIndexCheck,
97
+ skipVisibilityCheck
98
+ }) || include?.(node)) {
87
99
  elements[elements.length] = node;
88
100
  }
89
101
  }
@@ -104,7 +116,10 @@ function getFocusables(container = document.body, options = {}) {
104
116
  if (!(candidate instanceof Element)) {
105
117
  continue;
106
118
  }
107
- if (isFocusable(candidate, { skipVisibilityCheck })) {
119
+ if (isFocusable(candidate, {
120
+ skipNegativeTabIndexCheck,
121
+ skipVisibilityCheck
122
+ })) {
108
123
  elements[elements.length] = candidate;
109
124
  }
110
125
  }
@@ -117,7 +132,11 @@ function isFocusable(element, options = {}) {
117
132
  console.warn("Invalid element");
118
133
  return false;
119
134
  }
120
- let { skipVisibilityCheck = false } = options;
135
+ let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
136
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
137
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
138
+ skipNegativeTabIndexCheck = false;
139
+ }
121
140
  if (typeof skipVisibilityCheck !== "boolean") {
122
141
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
123
142
  skipVisibilityCheck = false;
@@ -125,10 +144,12 @@ function isFocusable(element, options = {}) {
125
144
  if (element.hasAttribute("hidden") || isInert(element)) {
126
145
  return false;
127
146
  }
128
- if (getTabIndex(element) < 0) {
147
+ if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
129
148
  return false;
130
149
  }
131
- if (!element.matches(FOCUSABLE_SELECTOR)) {
150
+ if (!element.matches(
151
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
152
+ )) {
132
153
  return false;
133
154
  }
134
155
  if (isDisabledDeep(element)) {
@@ -422,7 +443,7 @@ var RovingTabIndex = class {
422
443
  ...getFocusables(this.#container, {
423
444
  composed: true,
424
445
  filter: this.#selectorFilter,
425
- skipVisibilityCheck: true
446
+ skipNegativeTabIndexCheck: !this.#options.navigationOnly
426
447
  })
427
448
  ]);
428
449
  for (const focusable of this.#focusables) {
@@ -488,8 +509,7 @@ var RovingTabIndex = class {
488
509
  return getFocusables(this.#container, {
489
510
  composed: true,
490
511
  filter: this.#selectorFilter,
491
- include: (element) => this.#focusables.has(element),
492
- skipVisibilityCheck: true
512
+ skipNegativeTabIndexCheck: !this.#options.navigationOnly
493
513
  });
494
514
  }
495
515
  };
@@ -508,7 +528,7 @@ function getActiveElement() {
508
528
  * Lightweight roving tabindex utility with fully focus management.
509
529
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
510
530
  *
511
- * @version 1.3.1
531
+ * @version 2.0.0
512
532
  * @author Yusuke Kamiyamane
513
533
  * @license MIT
514
534
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -533,7 +553,7 @@ power-focusable/dist/index.js:
533
553
  * High-precision focus management utility with full composed tree support.
534
554
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
535
555
  *
536
- * @version 4.2.0
556
+ * @version 4.3.0
537
557
  * @author Yusuke Kamiyamane
538
558
  * @license MIT
539
559
  * @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 1.3.1
6
+ * @version 2.0.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 1.3.1
6
+ * @version 2.0.0
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ function getFocusables(container = document.body, options = {}) {
59
59
  composed = false,
60
60
  filter,
61
61
  include,
62
+ skipNegativeTabIndexCheck = false,
62
63
  skipVisibilityCheck = false
63
64
  } = options;
64
65
  if (typeof composed !== "boolean") {
@@ -77,11 +78,22 @@ function getFocusables(container = document.body, options = {}) {
77
78
  );
78
79
  include = void 0;
79
80
  }
81
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
82
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
83
+ skipNegativeTabIndexCheck = false;
84
+ }
85
+ if (typeof skipVisibilityCheck !== "boolean") {
86
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
87
+ skipVisibilityCheck = false;
88
+ }
80
89
  const elements = [];
81
90
  if (composed || include) {
82
91
  let traverse2 = function(node) {
83
92
  if (node instanceof Element) {
84
- if (isFocusable(node, { skipVisibilityCheck }) || include?.(node)) {
93
+ if (isFocusable(node, {
94
+ skipNegativeTabIndexCheck,
95
+ skipVisibilityCheck
96
+ }) || include?.(node)) {
85
97
  elements[elements.length] = node;
86
98
  }
87
99
  }
@@ -102,7 +114,10 @@ function getFocusables(container = document.body, options = {}) {
102
114
  if (!(candidate instanceof Element)) {
103
115
  continue;
104
116
  }
105
- if (isFocusable(candidate, { skipVisibilityCheck })) {
117
+ if (isFocusable(candidate, {
118
+ skipNegativeTabIndexCheck,
119
+ skipVisibilityCheck
120
+ })) {
106
121
  elements[elements.length] = candidate;
107
122
  }
108
123
  }
@@ -115,7 +130,11 @@ function isFocusable(element, options = {}) {
115
130
  console.warn("Invalid element");
116
131
  return false;
117
132
  }
118
- let { skipVisibilityCheck = false } = options;
133
+ let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
134
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
135
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
136
+ skipNegativeTabIndexCheck = false;
137
+ }
119
138
  if (typeof skipVisibilityCheck !== "boolean") {
120
139
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
121
140
  skipVisibilityCheck = false;
@@ -123,10 +142,12 @@ function isFocusable(element, options = {}) {
123
142
  if (element.hasAttribute("hidden") || isInert(element)) {
124
143
  return false;
125
144
  }
126
- if (getTabIndex(element) < 0) {
145
+ if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
127
146
  return false;
128
147
  }
129
- if (!element.matches(FOCUSABLE_SELECTOR)) {
148
+ if (!element.matches(
149
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
150
+ )) {
130
151
  return false;
131
152
  }
132
153
  if (isDisabledDeep(element)) {
@@ -420,7 +441,7 @@ var RovingTabIndex = class {
420
441
  ...getFocusables(this.#container, {
421
442
  composed: true,
422
443
  filter: this.#selectorFilter,
423
- skipVisibilityCheck: true
444
+ skipNegativeTabIndexCheck: !this.#options.navigationOnly
424
445
  })
425
446
  ]);
426
447
  for (const focusable of this.#focusables) {
@@ -486,8 +507,7 @@ var RovingTabIndex = class {
486
507
  return getFocusables(this.#container, {
487
508
  composed: true,
488
509
  filter: this.#selectorFilter,
489
- include: (element) => this.#focusables.has(element),
490
- skipVisibilityCheck: true
510
+ skipNegativeTabIndexCheck: !this.#options.navigationOnly
491
511
  });
492
512
  }
493
513
  };
@@ -506,7 +526,7 @@ function getActiveElement() {
506
526
  * Lightweight roving tabindex utility with fully focus management.
507
527
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
508
528
  *
509
- * @version 1.3.1
529
+ * @version 2.0.0
510
530
  * @author Yusuke Kamiyamane
511
531
  * @license MIT
512
532
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -531,7 +551,7 @@ power-focusable/dist/index.js:
531
551
  * High-precision focus management utility with full composed tree support.
532
552
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
533
553
  *
534
- * @version 4.2.0
554
+ * @version 4.3.0
535
555
  * @author Yusuke Kamiyamane
536
556
  * @license MIT
537
557
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/roving-tabindex",
3
- "version": "1.3.1",
3
+ "version": "2.0.0",
4
4
  "description": "Lightweight roving tabindex utility with fully focus management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -50,7 +50,7 @@
50
50
  "devDependencies": {
51
51
  "@y14e/attributes-utils": "^1.0.5",
52
52
  "bun-types": "latest",
53
- "power-focusable": "^4.2.0",
53
+ "power-focusable": "^4.3.0",
54
54
  "tsup": "^8.0.0",
55
55
  "typescript": "^5.6.0"
56
56
  },