power-focusable 4.0.2 → 4.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
@@ -1,6 +1,6 @@
1
1
  # Power Focusable
2
2
 
3
- High-precision focus management utility with full composed tree support. Handles complex focus rules including tabindex ordering, radio groups, inert, and shadow DOM.
3
+ High-precision focus management utility with full composed tree support. Handles complex focus rules including tabindex ordering, radio groups, inert.
4
4
 
5
5
  > [!NOTE]
6
6
  > Supports shadow DOM traversal via the composed tree. Only open shadow roots are included; closed shadow roots are not accessible.
@@ -35,10 +35,11 @@ import { ... } 'https://unpkg.com/power-focusable/dist/index.js';
35
35
 
36
36
  ```ts
37
37
  interface PowerFocusableOptions {
38
- anchor?: Element | null; // default: document.activeElement
39
- composed?: boolean; // default: false
40
- filter?: (element: Element) => boolean; // default: () => true
41
- wrap?: boolean; // default: false
38
+ anchor?: Element | null; // default: document.activeElement
39
+ composed?: boolean; // default: false
40
+ filter?: (element: Element) => boolean; // default: () => true
41
+ include?: (element: Element) => boolean; // default: undefined
42
+ wrap?: boolean; // default: false
42
43
  }
43
44
  ```
44
45
 
@@ -56,12 +57,20 @@ Used by `getFocusables`, `getNextFocusable`, `getPreviousFocusable`, and `hasFoc
56
57
 
57
58
  ### `filter`
58
59
 
59
- Custom filter function for excluding elements from focus traversal. Useful for advanced focus management such as portals, virtual focus regions, temporary exclusions, or custom focus scopes.
60
+ Custom filter function for excluding elements from focus traversal.
60
61
 
61
62
  The function should return `true` to include the element, or `false` to exclude it.
62
63
 
63
64
  Used by `getFocusables`, `getNextFocusable`, `getPreviousFocusable`, and `hasFocusable`.
64
65
 
66
+ ### `include`
67
+
68
+ Custom include function for adding elements to focus traversal even if they are not normally focusable.
69
+
70
+ The function should return `true` to include the element, or `false` to ignore it.
71
+
72
+ Used by `getFocusables`, `getNextFocusable`, `getPreviousFocusable`, and `hasFocusable`.
73
+
65
74
  ### `wrap`
66
75
 
67
76
  If `true`, wraps around to the first or last element when reaching the end.
package/dist/index.cjs CHANGED
@@ -44,12 +44,12 @@ 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, filter = () => true } = options;
47
+ const { composed = false, filter = () => true, include } = options;
48
48
  const elements = [];
49
- if (composed) {
49
+ if (composed || typeof include === "function") {
50
50
  let traverse2 = function(node) {
51
51
  if (node instanceof Element) {
52
- if (isFocusable(node)) {
52
+ if (isFocusable(node) || include?.(node)) {
53
53
  elements[elements.length] = node;
54
54
  }
55
55
  }
@@ -158,9 +158,10 @@ function getRelativeFocusable(container, offset, options) {
158
158
  anchor = getActiveElement(),
159
159
  composed = false,
160
160
  filter = () => true,
161
+ include,
161
162
  wrap = false
162
163
  } = options;
163
- const focusables = getFocusables(container, { composed, filter });
164
+ const focusables = getFocusables(container, { composed, filter, include });
164
165
  const { length } = focusables;
165
166
  if (!length) {
166
167
  return null;
@@ -395,10 +396,9 @@ function isUngroupedRadio(element) {
395
396
  /**
396
397
  * Power Focusable
397
398
  * High-precision focus management utility with full composed tree support.
398
- * Handles complex focus rules including tabindex ordering, radio groups, inert,
399
- * and shadow DOM.
399
+ * Handles complex focus rules including tabindex ordering, radio groups, inert.
400
400
  *
401
- * @version 4.0.2
401
+ * @version 4.1.0
402
402
  * @author Yusuke Kamiyamane
403
403
  * @license MIT
404
404
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Power Focusable
3
3
  * High-precision focus management utility with full composed tree support.
4
- * Handles complex focus rules including tabindex ordering, radio groups, inert,
5
- * and shadow DOM.
4
+ * Handles complex focus rules including tabindex ordering, radio groups, inert.
6
5
  *
7
- * @version 4.0.2
6
+ * @version 4.1.0
8
7
  * @author Yusuke Kamiyamane
9
8
  * @license MIT
10
9
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -14,6 +13,7 @@ interface PowerFocusableOptions {
14
13
  readonly anchor?: Element | null;
15
14
  readonly composed?: boolean;
16
15
  readonly filter?: (element: Element) => boolean;
16
+ readonly include?: ((element: Element) => boolean) | undefined;
17
17
  readonly wrap?: boolean;
18
18
  }
19
19
  declare function createFocusTrap(container?: Element): () => void;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * Power Focusable
3
3
  * High-precision focus management utility with full composed tree support.
4
- * Handles complex focus rules including tabindex ordering, radio groups, inert,
5
- * and shadow DOM.
4
+ * Handles complex focus rules including tabindex ordering, radio groups, inert.
6
5
  *
7
- * @version 4.0.2
6
+ * @version 4.1.0
8
7
  * @author Yusuke Kamiyamane
9
8
  * @license MIT
10
9
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -14,6 +13,7 @@ interface PowerFocusableOptions {
14
13
  readonly anchor?: Element | null;
15
14
  readonly composed?: boolean;
16
15
  readonly filter?: (element: Element) => boolean;
16
+ readonly include?: ((element: Element) => boolean) | undefined;
17
17
  readonly wrap?: boolean;
18
18
  }
19
19
  declare function createFocusTrap(container?: Element): () => void;
package/dist/index.js CHANGED
@@ -42,12 +42,12 @@ 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, filter = () => true } = options;
45
+ const { composed = false, filter = () => true, include } = options;
46
46
  const elements = [];
47
- if (composed) {
47
+ if (composed || typeof include === "function") {
48
48
  let traverse2 = function(node) {
49
49
  if (node instanceof Element) {
50
- if (isFocusable(node)) {
50
+ if (isFocusable(node) || include?.(node)) {
51
51
  elements[elements.length] = node;
52
52
  }
53
53
  }
@@ -156,9 +156,10 @@ function getRelativeFocusable(container, offset, options) {
156
156
  anchor = getActiveElement(),
157
157
  composed = false,
158
158
  filter = () => true,
159
+ include,
159
160
  wrap = false
160
161
  } = options;
161
- const focusables = getFocusables(container, { composed, filter });
162
+ const focusables = getFocusables(container, { composed, filter, include });
162
163
  const { length } = focusables;
163
164
  if (!length) {
164
165
  return null;
@@ -393,10 +394,9 @@ function isUngroupedRadio(element) {
393
394
  /**
394
395
  * Power Focusable
395
396
  * High-precision focus management utility with full composed tree support.
396
- * Handles complex focus rules including tabindex ordering, radio groups, inert,
397
- * and shadow DOM.
397
+ * Handles complex focus rules including tabindex ordering, radio groups, inert.
398
398
  *
399
- * @version 4.0.2
399
+ * @version 4.1.0
400
400
  * @author Yusuke Kamiyamane
401
401
  * @license MIT
402
402
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-focusable",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "High-precision focus management utility with full composed tree support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -25,13 +25,13 @@
25
25
  "lint": "tsc --noEmit"
26
26
  },
27
27
  "keywords": [
28
+ "a11y",
29
+ "accessibility",
28
30
  "focus",
29
31
  "focus-management",
30
32
  "focusable",
31
33
  "shadow-dom",
32
34
  "shadowdom",
33
- "a11y",
34
- "accessibility",
35
35
  "typescript",
36
36
  "utility"
37
37
  ],