@zag-js/aria-hidden 0.2.1 → 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 +89 -45
- package/dist/index.mjs +89 -45
- 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,85 +23,129 @@ __export(src_exports, {
|
|
|
23
23
|
ariaHidden: () => ariaHidden
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(src_exports);
|
|
26
|
-
var
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
var _a;
|
|
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;
|
|
32
31
|
const exclude = targets.filter(Boolean);
|
|
33
32
|
if (exclude.length === 0)
|
|
34
33
|
return;
|
|
35
34
|
const doc = exclude[0].ownerDocument || document;
|
|
36
|
-
const win =
|
|
35
|
+
const win = doc.defaultView ?? window;
|
|
37
36
|
const visibleNodes = new Set(exclude);
|
|
38
37
|
const hiddenNodes = /* @__PURE__ */ new Set();
|
|
39
|
-
const root = rootEl
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (visibleNodes.has(
|
|
38
|
+
const root = rootEl ?? doc.body;
|
|
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") {
|
|
46
45
|
return NodeFilter.FILTER_REJECT;
|
|
47
46
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return NodeFilter.FILTER_SKIP;
|
|
47
|
+
for (let target of visibleNodes) {
|
|
48
|
+
if (node.contains(target)) {
|
|
49
|
+
return NodeFilter.FILTER_SKIP;
|
|
50
|
+
}
|
|
53
51
|
}
|
|
54
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);
|
|
55
58
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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) {
|
|
61
70
|
return;
|
|
62
71
|
}
|
|
63
72
|
if (refCount === 0) {
|
|
64
|
-
|
|
73
|
+
node.setAttribute("aria-hidden", "true");
|
|
65
74
|
}
|
|
66
|
-
hiddenNodes.add(
|
|
67
|
-
|
|
75
|
+
hiddenNodes.add(node);
|
|
76
|
+
refCountMap.set(node, refCount + 1);
|
|
68
77
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
hide(node);
|
|
72
|
-
node = walker.nextNode();
|
|
78
|
+
if (observerStack.length) {
|
|
79
|
+
observerStack[observerStack.length - 1].disconnect();
|
|
73
80
|
}
|
|
81
|
+
walk(root);
|
|
74
82
|
const observer = new win.MutationObserver((changes) => {
|
|
75
83
|
for (let change of changes) {
|
|
76
|
-
if (change.type !== "childList" || change.addedNodes.length === 0)
|
|
84
|
+
if (change.type !== "childList" || change.addedNodes.length === 0) {
|
|
77
85
|
continue;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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);
|
|
84
99
|
}
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
103
|
});
|
|
89
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);
|
|
90
114
|
return () => {
|
|
91
115
|
observer.disconnect();
|
|
92
|
-
for (let
|
|
93
|
-
let count =
|
|
116
|
+
for (let node of hiddenNodes) {
|
|
117
|
+
let count = refCountMap.get(node);
|
|
94
118
|
if (count === 1) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
119
|
+
node.removeAttribute("aria-hidden");
|
|
120
|
+
refCountMap.delete(node);
|
|
121
|
+
} else {
|
|
122
|
+
refCountMap.set(node, count - 1);
|
|
98
123
|
}
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
}
|
|
125
|
+
if (observerWrapper === observerStack[observerStack.length - 1]) {
|
|
126
|
+
observerStack.pop();
|
|
127
|
+
if (observerStack.length) {
|
|
128
|
+
observerStack[observerStack.length - 1].observe();
|
|
101
129
|
}
|
|
130
|
+
} else {
|
|
131
|
+
observerStack.splice(observerStack.indexOf(observerWrapper), 1);
|
|
102
132
|
}
|
|
103
133
|
};
|
|
104
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
|
+
}
|
|
105
149
|
// Annotate the CommonJS export names for ESM import in node:
|
|
106
150
|
0 && (module.exports = {
|
|
107
151
|
ariaHidden
|
package/dist/index.mjs
CHANGED
|
@@ -1,83 +1,127 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
var _a;
|
|
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;
|
|
8
7
|
const exclude = targets.filter(Boolean);
|
|
9
8
|
if (exclude.length === 0)
|
|
10
9
|
return;
|
|
11
10
|
const doc = exclude[0].ownerDocument || document;
|
|
12
|
-
const win =
|
|
11
|
+
const win = doc.defaultView ?? window;
|
|
13
12
|
const visibleNodes = new Set(exclude);
|
|
14
13
|
const hiddenNodes = /* @__PURE__ */ new Set();
|
|
15
|
-
const root = rootEl
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (visibleNodes.has(
|
|
14
|
+
const root = rootEl ?? doc.body;
|
|
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") {
|
|
22
21
|
return NodeFilter.FILTER_REJECT;
|
|
23
22
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return NodeFilter.FILTER_SKIP;
|
|
23
|
+
for (let target of visibleNodes) {
|
|
24
|
+
if (node.contains(target)) {
|
|
25
|
+
return NodeFilter.FILTER_SKIP;
|
|
26
|
+
}
|
|
29
27
|
}
|
|
30
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);
|
|
31
34
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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) {
|
|
37
46
|
return;
|
|
38
47
|
}
|
|
39
48
|
if (refCount === 0) {
|
|
40
|
-
|
|
49
|
+
node.setAttribute("aria-hidden", "true");
|
|
41
50
|
}
|
|
42
|
-
hiddenNodes.add(
|
|
43
|
-
|
|
51
|
+
hiddenNodes.add(node);
|
|
52
|
+
refCountMap.set(node, refCount + 1);
|
|
44
53
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
hide(node);
|
|
48
|
-
node = walker.nextNode();
|
|
54
|
+
if (observerStack.length) {
|
|
55
|
+
observerStack[observerStack.length - 1].disconnect();
|
|
49
56
|
}
|
|
57
|
+
walk(root);
|
|
50
58
|
const observer = new win.MutationObserver((changes) => {
|
|
51
59
|
for (let change of changes) {
|
|
52
|
-
if (change.type !== "childList" || change.addedNodes.length === 0)
|
|
60
|
+
if (change.type !== "childList" || change.addedNodes.length === 0) {
|
|
53
61
|
continue;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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);
|
|
60
75
|
}
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
});
|
|
65
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);
|
|
66
90
|
return () => {
|
|
67
91
|
observer.disconnect();
|
|
68
|
-
for (let
|
|
69
|
-
let count =
|
|
92
|
+
for (let node of hiddenNodes) {
|
|
93
|
+
let count = refCountMap.get(node);
|
|
70
94
|
if (count === 1) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
node.removeAttribute("aria-hidden");
|
|
96
|
+
refCountMap.delete(node);
|
|
97
|
+
} else {
|
|
98
|
+
refCountMap.set(node, count - 1);
|
|
74
99
|
}
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
}
|
|
101
|
+
if (observerWrapper === observerStack[observerStack.length - 1]) {
|
|
102
|
+
observerStack.pop();
|
|
103
|
+
if (observerStack.length) {
|
|
104
|
+
observerStack[observerStack.length - 1].observe();
|
|
77
105
|
}
|
|
106
|
+
} else {
|
|
107
|
+
observerStack.splice(observerStack.indexOf(observerWrapper), 1);
|
|
78
108
|
}
|
|
79
109
|
};
|
|
80
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
|
+
}
|
|
81
125
|
export {
|
|
82
126
|
ariaHidden
|
|
83
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
|
},
|