@zag-js/aria-hidden 0.2.2 → 0.8.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/dist/index.d.ts +9 -2
- package/dist/index.js +87 -41
- package/dist/index.mjs +87 -41
- package/package.json +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
type AriaHiddenOptions = {
|
|
2
|
+
rootEl?: HTMLElement;
|
|
3
|
+
defer?: boolean;
|
|
4
|
+
};
|
|
5
|
+
type MaybeElement = HTMLElement | null;
|
|
6
|
+
type Targets = Array<MaybeElement>;
|
|
7
|
+
type TargetsOrFn = Targets | (() => Targets);
|
|
8
|
+
declare function ariaHidden(targetsOrFn: TargetsOrFn, options?: AriaHiddenOptions): () => void;
|
|
2
9
|
|
|
3
|
-
export { ariaHidden };
|
|
10
|
+
export { AriaHiddenOptions, ariaHidden };
|
package/dist/index.js
CHANGED
|
@@ -23,11 +23,11 @@ __export(src_exports, {
|
|
|
23
23
|
ariaHidden: () => ariaHidden
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(src_exports);
|
|
26
|
-
var
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
26
|
+
var import_dom_query = require("@zag-js/dom-query");
|
|
27
|
+
var refCountMap = /* @__PURE__ */ new WeakMap();
|
|
28
|
+
var observerStack = [];
|
|
29
|
+
function ariaHiddenImpl(targets, options = {}) {
|
|
30
|
+
const { rootEl } = options;
|
|
31
31
|
const exclude = targets.filter(Boolean);
|
|
32
32
|
if (exclude.length === 0)
|
|
33
33
|
return;
|
|
@@ -36,70 +36,116 @@ function ariaHidden(targets, rootEl) {
|
|
|
36
36
|
const visibleNodes = new Set(exclude);
|
|
37
37
|
const hiddenNodes = /* @__PURE__ */ new Set();
|
|
38
38
|
const root = rootEl ?? doc.body;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (visibleNodes.has(
|
|
39
|
+
let walk = (root2) => {
|
|
40
|
+
for (let element of root2.querySelectorAll("[data-live-announcer], [data-zag-top-layer]")) {
|
|
41
|
+
visibleNodes.add(element);
|
|
42
|
+
}
|
|
43
|
+
let acceptNode = (node) => {
|
|
44
|
+
if (visibleNodes.has(node) || hiddenNodes.has(node.parentElement) && node.parentElement.getAttribute("role") !== "row") {
|
|
45
45
|
return NodeFilter.FILTER_REJECT;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return NodeFilter.FILTER_SKIP;
|
|
47
|
+
for (let target of visibleNodes) {
|
|
48
|
+
if (node.contains(target)) {
|
|
49
|
+
return NodeFilter.FILTER_SKIP;
|
|
50
|
+
}
|
|
52
51
|
}
|
|
53
52
|
return NodeFilter.FILTER_ACCEPT;
|
|
53
|
+
};
|
|
54
|
+
let walker = doc.createTreeWalker(root2, NodeFilter.SHOW_ELEMENT, { acceptNode });
|
|
55
|
+
let acceptRoot = acceptNode(root2);
|
|
56
|
+
if (acceptRoot === NodeFilter.FILTER_ACCEPT) {
|
|
57
|
+
hide(root2);
|
|
54
58
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
if (acceptRoot !== NodeFilter.FILTER_REJECT) {
|
|
60
|
+
let node = walker.nextNode();
|
|
61
|
+
while (node != null) {
|
|
62
|
+
hide(node);
|
|
63
|
+
node = walker.nextNode();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
let hide = (node) => {
|
|
68
|
+
let refCount = refCountMap.get(node) ?? 0;
|
|
69
|
+
if (node.getAttribute("aria-hidden") === "true" && refCount === 0) {
|
|
59
70
|
return;
|
|
60
71
|
}
|
|
61
72
|
if (refCount === 0) {
|
|
62
|
-
|
|
73
|
+
node.setAttribute("aria-hidden", "true");
|
|
63
74
|
}
|
|
64
|
-
hiddenNodes.add(
|
|
65
|
-
|
|
75
|
+
hiddenNodes.add(node);
|
|
76
|
+
refCountMap.set(node, refCount + 1);
|
|
66
77
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
hide(node);
|
|
70
|
-
node = walker.nextNode();
|
|
78
|
+
if (observerStack.length) {
|
|
79
|
+
observerStack[observerStack.length - 1].disconnect();
|
|
71
80
|
}
|
|
81
|
+
walk(root);
|
|
72
82
|
const observer = new win.MutationObserver((changes) => {
|
|
73
83
|
for (let change of changes) {
|
|
74
|
-
if (change.type !== "childList" || change.addedNodes.length === 0)
|
|
84
|
+
if (change.type !== "childList" || change.addedNodes.length === 0) {
|
|
75
85
|
continue;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
}
|
|
87
|
+
if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {
|
|
88
|
+
for (let node of change.removedNodes) {
|
|
89
|
+
if (node instanceof win.Element) {
|
|
90
|
+
visibleNodes.delete(node);
|
|
91
|
+
hiddenNodes.delete(node);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (let node of change.addedNodes) {
|
|
95
|
+
if ((node instanceof win.HTMLElement || node instanceof win.SVGElement) && (node.dataset.liveAnnouncer === "true" || node.dataset.zagTopLayer === "true")) {
|
|
96
|
+
visibleNodes.add(node);
|
|
97
|
+
} else if (node instanceof win.Element) {
|
|
98
|
+
walk(node);
|
|
82
99
|
}
|
|
83
100
|
}
|
|
84
101
|
}
|
|
85
102
|
}
|
|
86
103
|
});
|
|
87
104
|
observer.observe(root, { childList: true, subtree: true });
|
|
105
|
+
let observerWrapper = {
|
|
106
|
+
observe() {
|
|
107
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
108
|
+
},
|
|
109
|
+
disconnect() {
|
|
110
|
+
observer.disconnect();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
observerStack.push(observerWrapper);
|
|
88
114
|
return () => {
|
|
89
115
|
observer.disconnect();
|
|
90
|
-
for (let
|
|
91
|
-
let count =
|
|
116
|
+
for (let node of hiddenNodes) {
|
|
117
|
+
let count = refCountMap.get(node);
|
|
92
118
|
if (count === 1) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
119
|
+
node.removeAttribute("aria-hidden");
|
|
120
|
+
refCountMap.delete(node);
|
|
121
|
+
} else {
|
|
122
|
+
refCountMap.set(node, count - 1);
|
|
96
123
|
}
|
|
97
|
-
|
|
98
|
-
|
|
124
|
+
}
|
|
125
|
+
if (observerWrapper === observerStack[observerStack.length - 1]) {
|
|
126
|
+
observerStack.pop();
|
|
127
|
+
if (observerStack.length) {
|
|
128
|
+
observerStack[observerStack.length - 1].observe();
|
|
99
129
|
}
|
|
130
|
+
} else {
|
|
131
|
+
observerStack.splice(observerStack.indexOf(observerWrapper), 1);
|
|
100
132
|
}
|
|
101
133
|
};
|
|
102
134
|
}
|
|
135
|
+
function ariaHidden(targetsOrFn, options = {}) {
|
|
136
|
+
const { defer } = options;
|
|
137
|
+
const func = defer ? import_dom_query.raf : (v) => v();
|
|
138
|
+
const cleanups = [];
|
|
139
|
+
cleanups.push(
|
|
140
|
+
func(() => {
|
|
141
|
+
const targets = typeof targetsOrFn === "function" ? targetsOrFn() : targetsOrFn;
|
|
142
|
+
cleanups.push(ariaHiddenImpl(targets, options));
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
return () => {
|
|
146
|
+
cleanups.forEach((fn) => fn?.());
|
|
147
|
+
};
|
|
148
|
+
}
|
|
103
149
|
// Annotate the CommonJS export names for ESM import in node:
|
|
104
150
|
0 && (module.exports = {
|
|
105
151
|
ariaHidden
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
2
|
+
import { raf } from "@zag-js/dom-query";
|
|
3
|
+
var refCountMap = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
var observerStack = [];
|
|
5
|
+
function ariaHiddenImpl(targets, options = {}) {
|
|
6
|
+
const { rootEl } = options;
|
|
7
7
|
const exclude = targets.filter(Boolean);
|
|
8
8
|
if (exclude.length === 0)
|
|
9
9
|
return;
|
|
@@ -12,70 +12,116 @@ function ariaHidden(targets, rootEl) {
|
|
|
12
12
|
const visibleNodes = new Set(exclude);
|
|
13
13
|
const hiddenNodes = /* @__PURE__ */ new Set();
|
|
14
14
|
const root = rootEl ?? doc.body;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (visibleNodes.has(
|
|
15
|
+
let walk = (root2) => {
|
|
16
|
+
for (let element of root2.querySelectorAll("[data-live-announcer], [data-zag-top-layer]")) {
|
|
17
|
+
visibleNodes.add(element);
|
|
18
|
+
}
|
|
19
|
+
let acceptNode = (node) => {
|
|
20
|
+
if (visibleNodes.has(node) || hiddenNodes.has(node.parentElement) && node.parentElement.getAttribute("role") !== "row") {
|
|
21
21
|
return NodeFilter.FILTER_REJECT;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return NodeFilter.FILTER_SKIP;
|
|
23
|
+
for (let target of visibleNodes) {
|
|
24
|
+
if (node.contains(target)) {
|
|
25
|
+
return NodeFilter.FILTER_SKIP;
|
|
26
|
+
}
|
|
28
27
|
}
|
|
29
28
|
return NodeFilter.FILTER_ACCEPT;
|
|
29
|
+
};
|
|
30
|
+
let walker = doc.createTreeWalker(root2, NodeFilter.SHOW_ELEMENT, { acceptNode });
|
|
31
|
+
let acceptRoot = acceptNode(root2);
|
|
32
|
+
if (acceptRoot === NodeFilter.FILTER_ACCEPT) {
|
|
33
|
+
hide(root2);
|
|
30
34
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
if (acceptRoot !== NodeFilter.FILTER_REJECT) {
|
|
36
|
+
let node = walker.nextNode();
|
|
37
|
+
while (node != null) {
|
|
38
|
+
hide(node);
|
|
39
|
+
node = walker.nextNode();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
let hide = (node) => {
|
|
44
|
+
let refCount = refCountMap.get(node) ?? 0;
|
|
45
|
+
if (node.getAttribute("aria-hidden") === "true" && refCount === 0) {
|
|
35
46
|
return;
|
|
36
47
|
}
|
|
37
48
|
if (refCount === 0) {
|
|
38
|
-
|
|
49
|
+
node.setAttribute("aria-hidden", "true");
|
|
39
50
|
}
|
|
40
|
-
hiddenNodes.add(
|
|
41
|
-
|
|
51
|
+
hiddenNodes.add(node);
|
|
52
|
+
refCountMap.set(node, refCount + 1);
|
|
42
53
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
hide(node);
|
|
46
|
-
node = walker.nextNode();
|
|
54
|
+
if (observerStack.length) {
|
|
55
|
+
observerStack[observerStack.length - 1].disconnect();
|
|
47
56
|
}
|
|
57
|
+
walk(root);
|
|
48
58
|
const observer = new win.MutationObserver((changes) => {
|
|
49
59
|
for (let change of changes) {
|
|
50
|
-
if (change.type !== "childList" || change.addedNodes.length === 0)
|
|
60
|
+
if (change.type !== "childList" || change.addedNodes.length === 0) {
|
|
51
61
|
continue;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
}
|
|
63
|
+
if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {
|
|
64
|
+
for (let node of change.removedNodes) {
|
|
65
|
+
if (node instanceof win.Element) {
|
|
66
|
+
visibleNodes.delete(node);
|
|
67
|
+
hiddenNodes.delete(node);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (let node of change.addedNodes) {
|
|
71
|
+
if ((node instanceof win.HTMLElement || node instanceof win.SVGElement) && (node.dataset.liveAnnouncer === "true" || node.dataset.zagTopLayer === "true")) {
|
|
72
|
+
visibleNodes.add(node);
|
|
73
|
+
} else if (node instanceof win.Element) {
|
|
74
|
+
walk(node);
|
|
58
75
|
}
|
|
59
76
|
}
|
|
60
77
|
}
|
|
61
78
|
}
|
|
62
79
|
});
|
|
63
80
|
observer.observe(root, { childList: true, subtree: true });
|
|
81
|
+
let observerWrapper = {
|
|
82
|
+
observe() {
|
|
83
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
84
|
+
},
|
|
85
|
+
disconnect() {
|
|
86
|
+
observer.disconnect();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
observerStack.push(observerWrapper);
|
|
64
90
|
return () => {
|
|
65
91
|
observer.disconnect();
|
|
66
|
-
for (let
|
|
67
|
-
let count =
|
|
92
|
+
for (let node of hiddenNodes) {
|
|
93
|
+
let count = refCountMap.get(node);
|
|
68
94
|
if (count === 1) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
95
|
+
node.removeAttribute("aria-hidden");
|
|
96
|
+
refCountMap.delete(node);
|
|
97
|
+
} else {
|
|
98
|
+
refCountMap.set(node, count - 1);
|
|
72
99
|
}
|
|
73
|
-
|
|
74
|
-
|
|
100
|
+
}
|
|
101
|
+
if (observerWrapper === observerStack[observerStack.length - 1]) {
|
|
102
|
+
observerStack.pop();
|
|
103
|
+
if (observerStack.length) {
|
|
104
|
+
observerStack[observerStack.length - 1].observe();
|
|
75
105
|
}
|
|
106
|
+
} else {
|
|
107
|
+
observerStack.splice(observerStack.indexOf(observerWrapper), 1);
|
|
76
108
|
}
|
|
77
109
|
};
|
|
78
110
|
}
|
|
111
|
+
function ariaHidden(targetsOrFn, options = {}) {
|
|
112
|
+
const { defer } = options;
|
|
113
|
+
const func = defer ? raf : (v) => v();
|
|
114
|
+
const cleanups = [];
|
|
115
|
+
cleanups.push(
|
|
116
|
+
func(() => {
|
|
117
|
+
const targets = typeof targetsOrFn === "function" ? targetsOrFn() : targetsOrFn;
|
|
118
|
+
cleanups.push(ariaHiddenImpl(targets, options));
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
return () => {
|
|
122
|
+
cleanups.forEach((fn) => fn?.());
|
|
123
|
+
};
|
|
124
|
+
}
|
|
79
125
|
export {
|
|
80
126
|
ariaHidden
|
|
81
127
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/aria-hidden",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Hide targets from screen readers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -23,6 +23,9 @@
|
|
|
23
23
|
},
|
|
24
24
|
"clean-package": "../../../clean-package.config.json",
|
|
25
25
|
"main": "dist/index.js",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@zag-js/dom-query": "0.1.4"
|
|
28
|
+
},
|
|
26
29
|
"devDependencies": {
|
|
27
30
|
"clean-package": "2.2.0"
|
|
28
31
|
},
|