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 +15 -6
- package/dist/index.cjs +7 -7
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -7
- package/package.json +3 -3
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
|
|
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;
|
|
39
|
-
composed?: boolean;
|
|
40
|
-
filter?: (element: Element) => boolean;
|
|
41
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
],
|