power-focusable 4.3.6 → 4.3.7
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 +3 -3
- package/dist/index.cjs +37 -18
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,11 +24,11 @@ import {
|
|
|
24
24
|
} from 'power-focusable';
|
|
25
25
|
|
|
26
26
|
// CDNs
|
|
27
|
-
import { ... } 'https://esm.sh/power-focusable@4.3.
|
|
27
|
+
import { ... } 'https://esm.sh/power-focusable@4.3.7';
|
|
28
28
|
// or
|
|
29
|
-
import { ... } 'https://cdn.jsdelivr.net/npm/power-focusable@4.3.
|
|
29
|
+
import { ... } 'https://cdn.jsdelivr.net/npm/power-focusable@4.3.7/+esm';
|
|
30
30
|
// or
|
|
31
|
-
import { ... } 'https://esm.unpkg.com/power-focusable@4.3.
|
|
31
|
+
import { ... } 'https://esm.unpkg.com/power-focusable@4.3.7';
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
## 🪄 Options
|
package/dist/index.cjs
CHANGED
|
@@ -4,22 +4,49 @@
|
|
|
4
4
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
5
5
|
function createFocusTrap(container = document.body) {
|
|
6
6
|
if (!(container instanceof Element)) {
|
|
7
|
-
|
|
7
|
+
console.warn("Invalid container element");
|
|
8
|
+
return () => {
|
|
9
|
+
};
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const trap = new FocusTrap(container);
|
|
12
|
+
return () => trap.destroy();
|
|
13
|
+
}
|
|
14
|
+
var FocusTrap = class {
|
|
15
|
+
#container;
|
|
16
|
+
#controller = null;
|
|
17
|
+
#isDestroyed = false;
|
|
18
|
+
constructor(container) {
|
|
19
|
+
this.#container = container;
|
|
20
|
+
this.#initialize();
|
|
21
|
+
}
|
|
22
|
+
destroy() {
|
|
23
|
+
if (this.#isDestroyed) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.#isDestroyed = true;
|
|
27
|
+
this.#controller?.abort();
|
|
28
|
+
this.#controller = null;
|
|
13
29
|
}
|
|
14
|
-
|
|
15
|
-
|
|
30
|
+
#initialize() {
|
|
31
|
+
this.#controller = new AbortController();
|
|
32
|
+
if (!(this.#container instanceof HTMLElement)) {
|
|
16
33
|
return;
|
|
17
34
|
}
|
|
35
|
+
this.#container.addEventListener("keydown", this.#onKeyDown, {
|
|
36
|
+
signal: this.#controller.signal
|
|
37
|
+
});
|
|
38
|
+
focusElement(this.#container);
|
|
39
|
+
if (getActiveElement() !== this.#container) {
|
|
40
|
+
const first = getFocusables(this.#container, { composed: true })[0];
|
|
41
|
+
first && focusElement(first);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
#onKeyDown = (event) => {
|
|
18
45
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
19
46
|
if (key !== "Tab" || altKey || ctrlKey || metaKey) {
|
|
20
47
|
return;
|
|
21
48
|
}
|
|
22
|
-
const focusable = getRelativeFocusable(container, shiftKey ? -1 : 1, {
|
|
49
|
+
const focusable = getRelativeFocusable(this.#container, shiftKey ? -1 : 1, {
|
|
23
50
|
composed: true,
|
|
24
51
|
wrap: true
|
|
25
52
|
});
|
|
@@ -27,16 +54,8 @@ function createFocusTrap(container = document.body) {
|
|
|
27
54
|
event.preventDefault();
|
|
28
55
|
focusElement(focusable);
|
|
29
56
|
}
|
|
30
|
-
}
|
|
31
|
-
let controller = new AbortController();
|
|
32
|
-
document.addEventListener("keydown", onKeyDown, {
|
|
33
|
-
signal: controller.signal
|
|
34
|
-
});
|
|
35
|
-
return () => {
|
|
36
|
-
controller?.abort();
|
|
37
|
-
controller = null;
|
|
38
57
|
};
|
|
39
|
-
}
|
|
58
|
+
};
|
|
40
59
|
function getFocusables(container = document.body, options = {}) {
|
|
41
60
|
if (!(container instanceof Element)) {
|
|
42
61
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
@@ -457,7 +476,7 @@ function isUngroupedRadio(element) {
|
|
|
457
476
|
* High-precision focus management utility with full composed tree support.
|
|
458
477
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
459
478
|
*
|
|
460
|
-
* @version 4.3.
|
|
479
|
+
* @version 4.3.7
|
|
461
480
|
* @author Yusuke Kamiyamane
|
|
462
481
|
* @license MIT
|
|
463
482
|
* @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.3.
|
|
6
|
+
* @version 4.3.7
|
|
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.3.
|
|
6
|
+
* @version 4.3.7
|
|
7
7
|
* @author Yusuke Kamiyamane
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.js
CHANGED
|
@@ -2,22 +2,49 @@
|
|
|
2
2
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
3
3
|
function createFocusTrap(container = document.body) {
|
|
4
4
|
if (!(container instanceof Element)) {
|
|
5
|
-
|
|
5
|
+
console.warn("Invalid container element");
|
|
6
|
+
return () => {
|
|
7
|
+
};
|
|
6
8
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const trap = new FocusTrap(container);
|
|
10
|
+
return () => trap.destroy();
|
|
11
|
+
}
|
|
12
|
+
var FocusTrap = class {
|
|
13
|
+
#container;
|
|
14
|
+
#controller = null;
|
|
15
|
+
#isDestroyed = false;
|
|
16
|
+
constructor(container) {
|
|
17
|
+
this.#container = container;
|
|
18
|
+
this.#initialize();
|
|
19
|
+
}
|
|
20
|
+
destroy() {
|
|
21
|
+
if (this.#isDestroyed) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.#isDestroyed = true;
|
|
25
|
+
this.#controller?.abort();
|
|
26
|
+
this.#controller = null;
|
|
11
27
|
}
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
#initialize() {
|
|
29
|
+
this.#controller = new AbortController();
|
|
30
|
+
if (!(this.#container instanceof HTMLElement)) {
|
|
14
31
|
return;
|
|
15
32
|
}
|
|
33
|
+
this.#container.addEventListener("keydown", this.#onKeyDown, {
|
|
34
|
+
signal: this.#controller.signal
|
|
35
|
+
});
|
|
36
|
+
focusElement(this.#container);
|
|
37
|
+
if (getActiveElement() !== this.#container) {
|
|
38
|
+
const first = getFocusables(this.#container, { composed: true })[0];
|
|
39
|
+
first && focusElement(first);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
#onKeyDown = (event) => {
|
|
16
43
|
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
17
44
|
if (key !== "Tab" || altKey || ctrlKey || metaKey) {
|
|
18
45
|
return;
|
|
19
46
|
}
|
|
20
|
-
const focusable = getRelativeFocusable(container, shiftKey ? -1 : 1, {
|
|
47
|
+
const focusable = getRelativeFocusable(this.#container, shiftKey ? -1 : 1, {
|
|
21
48
|
composed: true,
|
|
22
49
|
wrap: true
|
|
23
50
|
});
|
|
@@ -25,16 +52,8 @@ function createFocusTrap(container = document.body) {
|
|
|
25
52
|
event.preventDefault();
|
|
26
53
|
focusElement(focusable);
|
|
27
54
|
}
|
|
28
|
-
}
|
|
29
|
-
let controller = new AbortController();
|
|
30
|
-
document.addEventListener("keydown", onKeyDown, {
|
|
31
|
-
signal: controller.signal
|
|
32
|
-
});
|
|
33
|
-
return () => {
|
|
34
|
-
controller?.abort();
|
|
35
|
-
controller = null;
|
|
36
55
|
};
|
|
37
|
-
}
|
|
56
|
+
};
|
|
38
57
|
function getFocusables(container = document.body, options = {}) {
|
|
39
58
|
if (!(container instanceof Element)) {
|
|
40
59
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
@@ -455,7 +474,7 @@ function isUngroupedRadio(element) {
|
|
|
455
474
|
* High-precision focus management utility with full composed tree support.
|
|
456
475
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
457
476
|
*
|
|
458
|
-
* @version 4.3.
|
|
477
|
+
* @version 4.3.7
|
|
459
478
|
* @author Yusuke Kamiyamane
|
|
460
479
|
* @license MIT
|
|
461
480
|
* @copyright Copyright (c) Yusuke Kamiyamane
|