@blocdigital/usetoplayerelement 0.0.1 → 0.0.3
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/cjs/useTopLayerElement.js +10 -14
- package/dist/esm/useTopLayerElement.js +11 -15
- package/package.json +27 -27
@@ -4,16 +4,16 @@ exports.default = useTopLayerElements;
|
|
4
4
|
const react_1 = require("react");
|
5
5
|
const topLayerElements = new Set();
|
6
6
|
// Custom event to notify elements when they are added/removed from the top layer
|
7
|
-
const topLayerEvent = (inTopLayer) => new CustomEvent(
|
8
|
-
if (typeof document !==
|
7
|
+
const topLayerEvent = (inTopLayer) => new CustomEvent('topLayer', { bubbles: true, detail: { inTopLayer } });
|
8
|
+
if (typeof document !== 'undefined') {
|
9
9
|
// Listen for elements being added/removed from the top layer
|
10
|
-
document.addEventListener(
|
10
|
+
document.addEventListener('toggle', ({ target }) => {
|
11
11
|
if (!target)
|
12
12
|
return;
|
13
13
|
const el = target;
|
14
|
-
if (!(el instanceof HTMLDialogElement || el.hasAttribute(
|
14
|
+
if (!(el instanceof HTMLDialogElement || el.hasAttribute('popover')))
|
15
15
|
return;
|
16
|
-
if (el.matches(
|
16
|
+
if (el.matches(':modal, :popover-open') && document.contains(el)) {
|
17
17
|
topLayerElements.add(el);
|
18
18
|
el.dispatchEvent(topLayerEvent(true));
|
19
19
|
}
|
@@ -24,7 +24,7 @@ if (typeof document !== "undefined") {
|
|
24
24
|
}, { capture: true });
|
25
25
|
// MutationObserver for automatic cleanup
|
26
26
|
const observer = new MutationObserver((mutations) => {
|
27
|
-
const nodes = mutations.flatMap(({ removedNodes }) =>
|
27
|
+
const nodes = mutations.flatMap(({ removedNodes }) => Array.from(removedNodes).filter((node) => node instanceof HTMLElement));
|
28
28
|
for (const node of nodes)
|
29
29
|
if (topLayerElements.delete(node))
|
30
30
|
document.dispatchEvent(topLayerEvent(false));
|
@@ -33,22 +33,18 @@ if (typeof document !== "undefined") {
|
|
33
33
|
}
|
34
34
|
function useTopLayerElements() {
|
35
35
|
const ref = (0, react_1.useRef)(null);
|
36
|
-
const [topLayerList, setTopLayerList] = (0, react_1.useState)([
|
37
|
-
...topLayerElements,
|
38
|
-
]);
|
36
|
+
const [topLayerList, setTopLayerList] = (0, react_1.useState)([...topLayerElements]);
|
39
37
|
const derivedState = (0, react_1.useMemo)(() => {
|
40
38
|
const topElement = topLayerList.length ? topLayerList.at(-1) || null : null;
|
41
|
-
const topDialog = topLayerList.findLast((el) => el.tagName ===
|
39
|
+
const topDialog = topLayerList.findLast((el) => el.tagName === 'DIALOG') || null;
|
42
40
|
const isTopElement = ref.current ? topElement === ref.current : false;
|
43
|
-
const isInTopLayer = ref.current
|
44
|
-
? topLayerList.includes(ref.current)
|
45
|
-
: false;
|
41
|
+
const isInTopLayer = ref.current ? topLayerList.includes(ref.current) : false;
|
46
42
|
return { topElement, topDialog, isTopElement, isInTopLayer };
|
47
43
|
}, [topLayerList]);
|
48
44
|
// Listen for top layer changes
|
49
45
|
(0, react_1.useEffect)(() => {
|
50
46
|
const ac = new AbortController();
|
51
|
-
document.addEventListener(
|
47
|
+
document.addEventListener('topLayer', () => setTopLayerList([...topLayerElements]), { signal: ac.signal });
|
52
48
|
return () => ac.abort();
|
53
49
|
}, []);
|
54
50
|
return (0, react_1.useMemo)(() => ({ ref, ...derivedState, topLayerList }), [derivedState, topLayerList]);
|
@@ -1,16 +1,16 @@
|
|
1
|
-
import { useEffect, useMemo, useRef, useState } from
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
2
2
|
const topLayerElements = new Set();
|
3
3
|
// Custom event to notify elements when they are added/removed from the top layer
|
4
|
-
const topLayerEvent = (inTopLayer) => new CustomEvent(
|
5
|
-
if (typeof document !==
|
4
|
+
const topLayerEvent = (inTopLayer) => new CustomEvent('topLayer', { bubbles: true, detail: { inTopLayer } });
|
5
|
+
if (typeof document !== 'undefined') {
|
6
6
|
// Listen for elements being added/removed from the top layer
|
7
|
-
document.addEventListener(
|
7
|
+
document.addEventListener('toggle', ({ target }) => {
|
8
8
|
if (!target)
|
9
9
|
return;
|
10
10
|
const el = target;
|
11
|
-
if (!(el instanceof HTMLDialogElement || el.hasAttribute(
|
11
|
+
if (!(el instanceof HTMLDialogElement || el.hasAttribute('popover')))
|
12
12
|
return;
|
13
|
-
if (el.matches(
|
13
|
+
if (el.matches(':modal, :popover-open') && document.contains(el)) {
|
14
14
|
topLayerElements.add(el);
|
15
15
|
el.dispatchEvent(topLayerEvent(true));
|
16
16
|
}
|
@@ -21,7 +21,7 @@ if (typeof document !== "undefined") {
|
|
21
21
|
}, { capture: true });
|
22
22
|
// MutationObserver for automatic cleanup
|
23
23
|
const observer = new MutationObserver((mutations) => {
|
24
|
-
const nodes = mutations.flatMap(({ removedNodes }) =>
|
24
|
+
const nodes = mutations.flatMap(({ removedNodes }) => Array.from(removedNodes).filter((node) => node instanceof HTMLElement));
|
25
25
|
for (const node of nodes)
|
26
26
|
if (topLayerElements.delete(node))
|
27
27
|
document.dispatchEvent(topLayerEvent(false));
|
@@ -30,22 +30,18 @@ if (typeof document !== "undefined") {
|
|
30
30
|
}
|
31
31
|
export default function useTopLayerElements() {
|
32
32
|
const ref = useRef(null);
|
33
|
-
const [topLayerList, setTopLayerList] = useState([
|
34
|
-
...topLayerElements,
|
35
|
-
]);
|
33
|
+
const [topLayerList, setTopLayerList] = useState([...topLayerElements]);
|
36
34
|
const derivedState = useMemo(() => {
|
37
35
|
const topElement = topLayerList.length ? topLayerList.at(-1) || null : null;
|
38
|
-
const topDialog = topLayerList.findLast((el) => el.tagName ===
|
36
|
+
const topDialog = topLayerList.findLast((el) => el.tagName === 'DIALOG') || null;
|
39
37
|
const isTopElement = ref.current ? topElement === ref.current : false;
|
40
|
-
const isInTopLayer = ref.current
|
41
|
-
? topLayerList.includes(ref.current)
|
42
|
-
: false;
|
38
|
+
const isInTopLayer = ref.current ? topLayerList.includes(ref.current) : false;
|
43
39
|
return { topElement, topDialog, isTopElement, isInTopLayer };
|
44
40
|
}, [topLayerList]);
|
45
41
|
// Listen for top layer changes
|
46
42
|
useEffect(() => {
|
47
43
|
const ac = new AbortController();
|
48
|
-
document.addEventListener(
|
44
|
+
document.addEventListener('topLayer', () => setTopLayerList([...topLayerElements]), { signal: ac.signal });
|
49
45
|
return () => ac.abort();
|
50
46
|
}, []);
|
51
47
|
return useMemo(() => ({ ref, ...derivedState, topLayerList }), [derivedState, topLayerList]);
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@blocdigital/usetoplayerelement",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.0.
|
4
|
+
"version": "0.0.3",
|
5
5
|
"description": "React hook for monitoring the top layer",
|
6
6
|
"author": "Bloc Digital <web@bloc.digital>",
|
7
7
|
"license": "MIT",
|
@@ -49,35 +49,35 @@
|
|
49
49
|
"preview": "vite preview",
|
50
50
|
"test": "jest"
|
51
51
|
},
|
52
|
-
"dependencies": {
|
53
|
-
"react": "^19.0.0",
|
54
|
-
"react-dom": "^19.0.0"
|
55
|
-
},
|
56
52
|
"devDependencies": {
|
57
|
-
"@babel/core": "^7.
|
58
|
-
"@babel/preset-env": "^7.
|
59
|
-
"@babel/preset-typescript": "^7.
|
60
|
-
"@testing-library/react": "^16.
|
61
|
-
"@types/jest": "^
|
62
|
-
"@types/react": "^19.
|
63
|
-
"@types/react-dom": "^19.
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
65
|
-
"@typescript-eslint/parser": "^8.
|
66
|
-
"@vitejs/plugin-react-swc": "^3.
|
67
|
-
"babel-jest": "^
|
68
|
-
"eslint": "^9.
|
69
|
-
"eslint-config-prettier": "^10.
|
70
|
-
"eslint-plugin-prettier": "^5.
|
71
|
-
"eslint-plugin-react": "^
|
72
|
-
"eslint-plugin-react-
|
73
|
-
"
|
74
|
-
"jest": "^
|
75
|
-
"jest-environment-jsdom": "^
|
76
|
-
"prettier": "^3.
|
77
|
-
"typescript": "^5.
|
78
|
-
"vite": "^
|
53
|
+
"@babel/core": "^7.28.0",
|
54
|
+
"@babel/preset-env": "^7.28.0",
|
55
|
+
"@babel/preset-typescript": "^7.27.1",
|
56
|
+
"@testing-library/react": "^16.3.0",
|
57
|
+
"@types/jest": "^30.0.0",
|
58
|
+
"@types/react": "^19.1.8",
|
59
|
+
"@types/react-dom": "^19.1.6",
|
60
|
+
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
61
|
+
"@typescript-eslint/parser": "^8.35.1",
|
62
|
+
"@vitejs/plugin-react-swc": "^3.10.2",
|
63
|
+
"babel-jest": "^30.0.4",
|
64
|
+
"eslint": "^9.30.1",
|
65
|
+
"eslint-config-prettier": "^10.1.5",
|
66
|
+
"eslint-plugin-prettier": "^5.5.1",
|
67
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
68
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
69
|
+
"globals": "^16.3.0",
|
70
|
+
"jest": "^30.0.4",
|
71
|
+
"jest-environment-jsdom": "^30.0.4",
|
72
|
+
"prettier": "^3.6.2",
|
73
|
+
"typescript": "^5.8.3",
|
74
|
+
"vite": "^7.0.2"
|
79
75
|
},
|
80
76
|
"bugs": {
|
81
77
|
"url": "https://github.com/bloc-digital/usetoplayerelement/issues"
|
78
|
+
},
|
79
|
+
"peerDependencies": {
|
80
|
+
"react": "^17 || ^18 || ^19",
|
81
|
+
"react-dom": "^17 || ^18 || ^19"
|
82
82
|
}
|
83
83
|
}
|