power-focusable 4.1.4 → 4.1.6

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
@@ -105,11 +105,14 @@ getFocusables(container, { composed: true });
105
105
 
106
106
  // Uses custom filter function
107
107
  getFocusables(container, { filter: (element) => !element.matches('[data-skip-focus]') });
108
+
109
+ // Uses custom include function
110
+ getFocusables(container, { filter: (element) => element.matches('[data-roving-tabindex]') });
108
111
  ```
109
112
 
110
113
  ### `getNextFocusable`
111
114
 
112
- Returns the next focusable element within the container, starting from `document.activeElement`.
115
+ Returns the next focusable element within the container, starting from active element.
113
116
 
114
117
  ```ts
115
118
  getNextFocusable(container);
@@ -126,13 +129,16 @@ getNextFocusable(container, { composed: true });
126
129
  // Uses custom filter function
127
130
  getNextFocusable(container, { filter: (element) => !element.matches('[data-skip-focus]') });
128
131
 
132
+ // Uses custom include function
133
+ getNextFocusable(container, { filter: (element) => element.matches('[data-roving-tabindex]') });
134
+
129
135
  // Wraps around to the first element when reaching the end
130
136
  getNextFocusable(container, { wrap: true });
131
137
  ```
132
138
 
133
139
  ### `getPreviousFocusable`
134
140
 
135
- Returns the previous focusable element within the container, starting from `document.activeElement`.
141
+ Returns the previous focusable element within the container, starting from active element.
136
142
 
137
143
  ```ts
138
144
  getPreviousFocusable(container);
@@ -149,7 +155,10 @@ getPreviousFocusable(container, { composed: true });
149
155
  // Uses custom filter function
150
156
  getPreviousFocusable(container, { filter: (element) => !element.matches('[data-skip-focus]') });
151
157
 
152
- //Wraps around to the last element when reaching the end
158
+ // Uses custom include function
159
+ getPreviousFocusable(container, { filter: (element) => element.matches('[data-roving-tabindex]') });
160
+
161
+ // Wraps around to the last element when reaching the end
153
162
  getPreviousFocusable(container, { wrap: true });
154
163
 
155
164
  ```
@@ -169,6 +178,9 @@ hasFocusable(container, { composed: true });
169
178
 
170
179
  // Uses custom filter function
171
180
  hasFocusable(container, { filter: (element) => !element.matches('[data-skip-focus]') });
181
+
182
+ // Uses custom include function
183
+ hasFocusable(container, { filter: (element) => element.matches('[data-roving-tabindex]') });
172
184
  ```
173
185
 
174
186
  ### `inertOutside`
package/dist/index.cjs CHANGED
@@ -44,14 +44,17 @@ function getFocusables(container = document.body, options = {}) {
44
44
  console.warn("Invalid container element. Fallback: <body> element.");
45
45
  container = document.body;
46
46
  }
47
- const { composed = false } = options;
48
- let { filter, include } = options;
49
- if (filter && typeof filter !== "function") {
50
- console.warn("Invalid filter function");
47
+ let { composed = false, filter, include } = options;
48
+ if (typeof composed !== "boolean") {
49
+ console.warn("Invalid composed. Fallback: false.");
50
+ composed = false;
51
+ }
52
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
53
+ console.warn("Invalid filter. Fallback: no filter function (undefined).");
51
54
  filter = void 0;
52
55
  }
53
- if (include && typeof include !== "function") {
54
- console.warn("Invalid include function");
56
+ if (typeof include !== "undefined" && typeof include !== "function") {
57
+ console.warn("Invalid include. Fallback: no include function (undefined).");
55
58
  include = void 0;
56
59
  }
57
60
  const elements = [];
@@ -88,24 +91,12 @@ function getFocusables(container = document.body, options = {}) {
88
91
  return filter ? unfiltered.filter(filter) : unfiltered;
89
92
  }
90
93
  function getNextFocusable(container = document.body, options = {}) {
91
- if (!(container instanceof Element)) {
92
- console.warn("Invalid container element. Fallback: <body> element.");
93
- container = document.body;
94
- }
95
94
  return getRelativeFocusable(container, 1, options);
96
95
  }
97
96
  function getPreviousFocusable(container = document.body, options = {}) {
98
- if (!(container instanceof Element)) {
99
- console.warn("Invalid container element. Fallback: <body> element.");
100
- container = document.body;
101
- }
102
97
  return getRelativeFocusable(container, -1, options);
103
98
  }
104
99
  function hasFocusable(container = document.body, options = {}) {
105
- if (!(container instanceof Element)) {
106
- console.warn("Invalid container element. Fallback: <body> element.");
107
- container = document.body;
108
- }
109
100
  return !!getFocusables(container, options).length;
110
101
  }
111
102
  function inertOutside(element) {
@@ -164,8 +155,13 @@ function isFocusable(element) {
164
155
  return true;
165
156
  }
166
157
  function getRelativeFocusable(container, offset, options) {
167
- let anchor = options.anchor ?? getActiveElement();
168
- const { composed = false, filter, include, wrap = false } = options;
158
+ let {
159
+ anchor = getActiveElement(),
160
+ composed = false,
161
+ filter,
162
+ include,
163
+ wrap = false
164
+ } = options;
169
165
  if (!(anchor instanceof Element)) {
170
166
  const active = getActiveElement();
171
167
  if (active instanceof Element) {
@@ -180,6 +176,22 @@ function getRelativeFocusable(container, offset, options) {
180
176
  console.warn("Anchor (active) element not within container");
181
177
  return null;
182
178
  }
179
+ if (typeof composed !== "boolean") {
180
+ console.warn("Invalid composed. Fallback: false.");
181
+ composed = false;
182
+ }
183
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
184
+ console.warn("Invalid filter. Fallback: no filter function (undefined).");
185
+ filter = void 0;
186
+ }
187
+ if (typeof include !== "undefined" && typeof include !== "function") {
188
+ console.warn("Invalid include. Fallback: no include function (undefined).");
189
+ include = void 0;
190
+ }
191
+ if (typeof wrap !== "boolean") {
192
+ console.warn("Invalid wrap. Fallback: false.");
193
+ wrap = false;
194
+ }
183
195
  const focusables = getFocusables(container, { composed, filter, include });
184
196
  const { length } = focusables;
185
197
  if (!length) {
@@ -345,7 +357,7 @@ function applyInert(element) {
345
357
  }
346
358
  const count = inertRefCounts.get(element) ?? 0;
347
359
  inertRefCounts.set(element, count + 1);
348
- count === 0 && element.toggleAttribute("inert", true);
360
+ count === 0 && element.setAttribute("inert", "");
349
361
  return true;
350
362
  }
351
363
  function restoreInert(element) {
@@ -355,7 +367,7 @@ function restoreInert(element) {
355
367
  }
356
368
  if (count === 1) {
357
369
  inertRefCounts.delete(element);
358
- element.toggleAttribute("inert", false);
370
+ element.removeAttribute("inert");
359
371
  return;
360
372
  }
361
373
  inertRefCounts.set(element, count - 1);
@@ -411,7 +423,7 @@ function isUngroupedRadio(element) {
411
423
  * High-precision focus management utility with full composed tree support.
412
424
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
413
425
  *
414
- * @version 4.1.4
426
+ * @version 4.1.6
415
427
  * @author Yusuke Kamiyamane
416
428
  * @license MIT
417
429
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@
3
3
  * High-precision focus management utility with full composed tree support.
4
4
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
5
5
  *
6
- * @version 4.1.4
6
+ * @version 4.1.6
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
  * High-precision focus management utility with full composed tree support.
4
4
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
5
5
  *
6
- * @version 4.1.4
6
+ * @version 4.1.6
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -42,14 +42,17 @@ function getFocusables(container = document.body, options = {}) {
42
42
  console.warn("Invalid container element. Fallback: <body> element.");
43
43
  container = document.body;
44
44
  }
45
- const { composed = false } = options;
46
- let { filter, include } = options;
47
- if (filter && typeof filter !== "function") {
48
- console.warn("Invalid filter function");
45
+ let { composed = false, filter, include } = options;
46
+ if (typeof composed !== "boolean") {
47
+ console.warn("Invalid composed. Fallback: false.");
48
+ composed = false;
49
+ }
50
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
51
+ console.warn("Invalid filter. Fallback: no filter function (undefined).");
49
52
  filter = void 0;
50
53
  }
51
- if (include && typeof include !== "function") {
52
- console.warn("Invalid include function");
54
+ if (typeof include !== "undefined" && typeof include !== "function") {
55
+ console.warn("Invalid include. Fallback: no include function (undefined).");
53
56
  include = void 0;
54
57
  }
55
58
  const elements = [];
@@ -86,24 +89,12 @@ function getFocusables(container = document.body, options = {}) {
86
89
  return filter ? unfiltered.filter(filter) : unfiltered;
87
90
  }
88
91
  function getNextFocusable(container = document.body, options = {}) {
89
- if (!(container instanceof Element)) {
90
- console.warn("Invalid container element. Fallback: <body> element.");
91
- container = document.body;
92
- }
93
92
  return getRelativeFocusable(container, 1, options);
94
93
  }
95
94
  function getPreviousFocusable(container = document.body, options = {}) {
96
- if (!(container instanceof Element)) {
97
- console.warn("Invalid container element. Fallback: <body> element.");
98
- container = document.body;
99
- }
100
95
  return getRelativeFocusable(container, -1, options);
101
96
  }
102
97
  function hasFocusable(container = document.body, options = {}) {
103
- if (!(container instanceof Element)) {
104
- console.warn("Invalid container element. Fallback: <body> element.");
105
- container = document.body;
106
- }
107
98
  return !!getFocusables(container, options).length;
108
99
  }
109
100
  function inertOutside(element) {
@@ -162,8 +153,13 @@ function isFocusable(element) {
162
153
  return true;
163
154
  }
164
155
  function getRelativeFocusable(container, offset, options) {
165
- let anchor = options.anchor ?? getActiveElement();
166
- const { composed = false, filter, include, wrap = false } = options;
156
+ let {
157
+ anchor = getActiveElement(),
158
+ composed = false,
159
+ filter,
160
+ include,
161
+ wrap = false
162
+ } = options;
167
163
  if (!(anchor instanceof Element)) {
168
164
  const active = getActiveElement();
169
165
  if (active instanceof Element) {
@@ -178,6 +174,22 @@ function getRelativeFocusable(container, offset, options) {
178
174
  console.warn("Anchor (active) element not within container");
179
175
  return null;
180
176
  }
177
+ if (typeof composed !== "boolean") {
178
+ console.warn("Invalid composed. Fallback: false.");
179
+ composed = false;
180
+ }
181
+ if (typeof filter !== "undefined" && typeof filter !== "function") {
182
+ console.warn("Invalid filter. Fallback: no filter function (undefined).");
183
+ filter = void 0;
184
+ }
185
+ if (typeof include !== "undefined" && typeof include !== "function") {
186
+ console.warn("Invalid include. Fallback: no include function (undefined).");
187
+ include = void 0;
188
+ }
189
+ if (typeof wrap !== "boolean") {
190
+ console.warn("Invalid wrap. Fallback: false.");
191
+ wrap = false;
192
+ }
181
193
  const focusables = getFocusables(container, { composed, filter, include });
182
194
  const { length } = focusables;
183
195
  if (!length) {
@@ -343,7 +355,7 @@ function applyInert(element) {
343
355
  }
344
356
  const count = inertRefCounts.get(element) ?? 0;
345
357
  inertRefCounts.set(element, count + 1);
346
- count === 0 && element.toggleAttribute("inert", true);
358
+ count === 0 && element.setAttribute("inert", "");
347
359
  return true;
348
360
  }
349
361
  function restoreInert(element) {
@@ -353,7 +365,7 @@ function restoreInert(element) {
353
365
  }
354
366
  if (count === 1) {
355
367
  inertRefCounts.delete(element);
356
- element.toggleAttribute("inert", false);
368
+ element.removeAttribute("inert");
357
369
  return;
358
370
  }
359
371
  inertRefCounts.set(element, count - 1);
@@ -409,7 +421,7 @@ function isUngroupedRadio(element) {
409
421
  * High-precision focus management utility with full composed tree support.
410
422
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
411
423
  *
412
- * @version 4.1.4
424
+ * @version 4.1.6
413
425
  * @author Yusuke Kamiyamane
414
426
  * @license MIT
415
427
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-focusable",
3
- "version": "4.1.4",
3
+ "version": "4.1.6",
4
4
  "description": "High-precision focus management utility with full composed tree support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",