@zag-js/aria-hidden 0.53.0 → 0.54.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.js CHANGED
@@ -1,2 +1,153 @@
1
- "use strict";var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);var src_exports={};__export(src_exports,{ariaHidden:()=>ariaHidden});module.exports=__toCommonJS(src_exports);var import_dom_query=require("@zag-js/dom-query");var refCountMap=new WeakMap;var observerStack=[];function ariaHiddenImpl(targets,options={}){const{rootEl}=options;const exclude=targets.filter(Boolean);if(exclude.length===0)return;const doc=exclude[0].ownerDocument||document;const win=doc.defaultView??window;const visibleNodes=new Set(exclude);const hiddenNodes=new Set;const root=rootEl??doc.body;let walk=root2=>{for(let element of root2.querySelectorAll("[data-live-announcer], [data-zag-top-layer]")){visibleNodes.add(element)}let acceptNode=node=>{if(visibleNodes.has(node)||hiddenNodes.has(node.parentElement)&&node.parentElement.getAttribute("role")!=="row"){return NodeFilter.FILTER_REJECT}for(let target of visibleNodes){if(node.contains(target)){return NodeFilter.FILTER_SKIP}}return NodeFilter.FILTER_ACCEPT};let walker=doc.createTreeWalker(root2,NodeFilter.SHOW_ELEMENT,{acceptNode});let acceptRoot=acceptNode(root2);if(acceptRoot===NodeFilter.FILTER_ACCEPT){hide(root2)}if(acceptRoot!==NodeFilter.FILTER_REJECT){let node=walker.nextNode();while(node!=null){hide(node);node=walker.nextNode()}}};let hide=node=>{let refCount=refCountMap.get(node)??0;if(node.getAttribute("aria-hidden")==="true"&&refCount===0){return}if(refCount===0){node.setAttribute("aria-hidden","true")}hiddenNodes.add(node);refCountMap.set(node,refCount+1)};if(observerStack.length){observerStack[observerStack.length-1].disconnect()}walk(root);const observer=new win.MutationObserver(changes=>{for(let change of changes){if(change.type!=="childList"||change.addedNodes.length===0){continue}if(![...visibleNodes,...hiddenNodes].some(node=>node.contains(change.target))){for(let node of change.removedNodes){if(node instanceof win.Element){visibleNodes.delete(node);hiddenNodes.delete(node)}}for(let node of change.addedNodes){if((node instanceof win.HTMLElement||node instanceof win.SVGElement)&&(node.dataset.liveAnnouncer==="true"||node.dataset.zagTopLayer==="true")){visibleNodes.add(node)}else if(node instanceof win.Element){walk(node)}}}}});observer.observe(root,{childList:true,subtree:true});let observerWrapper={observe(){observer.observe(root,{childList:true,subtree:true})},disconnect(){observer.disconnect()}};observerStack.push(observerWrapper);return()=>{observer.disconnect();for(let node of hiddenNodes){let count=refCountMap.get(node);if(count===1){node.removeAttribute("aria-hidden");refCountMap.delete(node)}else{refCountMap.set(node,count-1)}}if(observerWrapper===observerStack[observerStack.length-1]){observerStack.pop();if(observerStack.length){observerStack[observerStack.length-1].observe()}}else{observerStack.splice(observerStack.indexOf(observerWrapper),1)}}}function ariaHidden(targetsOrFn,options={}){const{defer}=options;const func=defer?import_dom_query.raf:v=>v();const cleanups=[];cleanups.push(func(()=>{const targets=typeof targetsOrFn==="function"?targetsOrFn():targetsOrFn;cleanups.push(ariaHiddenImpl(targets,options))}));return()=>{cleanups.forEach(fn=>fn?.())}}0&&(module.exports={ariaHidden});
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ ariaHidden: () => ariaHidden
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
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
+ const exclude = targets.filter(Boolean);
32
+ if (exclude.length === 0)
33
+ return;
34
+ const doc = exclude[0].ownerDocument || document;
35
+ const win = doc.defaultView ?? window;
36
+ const visibleNodes = new Set(exclude);
37
+ const hiddenNodes = /* @__PURE__ */ new Set();
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") {
45
+ return NodeFilter.FILTER_REJECT;
46
+ }
47
+ for (let target of visibleNodes) {
48
+ if (node.contains(target)) {
49
+ return NodeFilter.FILTER_SKIP;
50
+ }
51
+ }
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);
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) {
70
+ return;
71
+ }
72
+ if (refCount === 0) {
73
+ node.setAttribute("aria-hidden", "true");
74
+ }
75
+ hiddenNodes.add(node);
76
+ refCountMap.set(node, refCount + 1);
77
+ };
78
+ if (observerStack.length) {
79
+ observerStack[observerStack.length - 1].disconnect();
80
+ }
81
+ walk(root);
82
+ const observer = new win.MutationObserver((changes) => {
83
+ for (let change of changes) {
84
+ if (change.type !== "childList" || change.addedNodes.length === 0) {
85
+ continue;
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);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ });
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);
114
+ return () => {
115
+ observer.disconnect();
116
+ for (let node of hiddenNodes) {
117
+ let count = refCountMap.get(node);
118
+ if (count === 1) {
119
+ node.removeAttribute("aria-hidden");
120
+ refCountMap.delete(node);
121
+ } else {
122
+ refCountMap.set(node, count - 1);
123
+ }
124
+ }
125
+ if (observerWrapper === observerStack[observerStack.length - 1]) {
126
+ observerStack.pop();
127
+ if (observerStack.length) {
128
+ observerStack[observerStack.length - 1].observe();
129
+ }
130
+ } else {
131
+ observerStack.splice(observerStack.indexOf(observerWrapper), 1);
132
+ }
133
+ };
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
+ }
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ ariaHidden
152
+ });
2
153
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Credits: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/overlays/src/ariaHideOutside.ts\nimport { raf } from \"@zag-js/dom-query\"\n\nconst refCountMap = new WeakMap<Element, number>()\nconst observerStack: any[] = []\n\nexport interface AriaHiddenOptions {\n rootEl?: HTMLElement\n defer?: boolean\n}\n\ntype MaybeElement = HTMLElement | null\ntype Targets = Array<MaybeElement>\ntype TargetsOrFn = Targets | (() => Targets)\n\nfunction ariaHiddenImpl(targets: Targets, options: AriaHiddenOptions = {}) {\n const { rootEl } = options\n\n const exclude = targets.filter(Boolean) as HTMLElement[]\n if (exclude.length === 0) return\n\n const doc = exclude[0].ownerDocument || document\n const win = doc.defaultView ?? window\n\n const visibleNodes = new Set<Element>(exclude)\n const hiddenNodes = new Set<Element>()\n\n const root = rootEl ?? doc.body\n\n let walk = (root: Element) => {\n // Keep live announcer and top layer elements (e.g. toasts) visible.\n for (let element of root.querySelectorAll(\"[data-live-announcer], [data-zag-top-layer]\")) {\n visibleNodes.add(element)\n }\n\n let acceptNode = (node: Element) => {\n // Skip this node and its children if it is one of the target nodes, or a live announcer.\n // Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is\n // made for elements with role=\"row\" since VoiceOver on iOS has issues hiding elements with role=\"row\".\n // For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).\n if (\n visibleNodes.has(node) ||\n (hiddenNodes.has(node.parentElement!) && node.parentElement!.getAttribute(\"role\") !== \"row\")\n ) {\n return NodeFilter.FILTER_REJECT\n }\n\n // Skip this node but continue to children if one of the targets is inside the node.\n for (let target of visibleNodes) {\n if (node.contains(target)) {\n return NodeFilter.FILTER_SKIP\n }\n }\n\n return NodeFilter.FILTER_ACCEPT\n }\n\n let walker = doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode })\n\n // TreeWalker does not include the root.\n let acceptRoot = acceptNode(root)\n if (acceptRoot === NodeFilter.FILTER_ACCEPT) {\n hide(root)\n }\n\n if (acceptRoot !== NodeFilter.FILTER_REJECT) {\n let node = walker.nextNode() as Element\n while (node != null) {\n hide(node)\n node = walker.nextNode() as Element\n }\n }\n }\n\n let hide = (node: Element) => {\n let refCount = refCountMap.get(node) ?? 0\n\n // If already aria-hidden, and the ref count is zero, then this element\n // was already hidden and there's nothing for us to do.\n if (node.getAttribute(\"aria-hidden\") === \"true\" && refCount === 0) {\n return\n }\n\n if (refCount === 0) {\n node.setAttribute(\"aria-hidden\", \"true\")\n }\n\n hiddenNodes.add(node)\n refCountMap.set(node, refCount + 1)\n }\n\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect()\n }\n\n walk(root)\n\n const observer = new win.MutationObserver((changes) => {\n for (let change of changes) {\n if (change.type !== \"childList\" || change.addedNodes.length === 0) {\n continue\n }\n\n // If the parent element of the added nodes is not within one of the targets,\n // and not already inside a hidden node, hide all of the new children.\n if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {\n for (let node of change.removedNodes) {\n if (node instanceof win.Element) {\n visibleNodes.delete(node)\n hiddenNodes.delete(node)\n }\n }\n\n for (let node of change.addedNodes) {\n if (\n (node instanceof win.HTMLElement || node instanceof win.SVGElement) &&\n (node.dataset.liveAnnouncer === \"true\" || node.dataset.zagTopLayer === \"true\")\n ) {\n visibleNodes.add(node)\n } else if (node instanceof win.Element) {\n walk(node)\n }\n }\n }\n }\n })\n\n observer.observe(root, { childList: true, subtree: true })\n\n let observerWrapper = {\n observe() {\n observer.observe(root, { childList: true, subtree: true })\n },\n disconnect() {\n observer.disconnect()\n },\n }\n\n observerStack.push(observerWrapper)\n\n return () => {\n observer.disconnect()\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node)\n if (count === 1) {\n node.removeAttribute(\"aria-hidden\")\n refCountMap.delete(node)\n } else {\n refCountMap.set(node, count! - 1)\n }\n }\n\n // Remove this observer from the stack, and start the previous one.\n if (observerWrapper === observerStack[observerStack.length - 1]) {\n observerStack.pop()\n if (observerStack.length) {\n observerStack[observerStack.length - 1].observe()\n }\n } else {\n observerStack.splice(observerStack.indexOf(observerWrapper), 1)\n }\n }\n}\n\nexport function ariaHidden(targetsOrFn: TargetsOrFn, options: AriaHiddenOptions = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const targets = typeof targetsOrFn === \"function\" ? targetsOrFn() : targetsOrFn\n cleanups.push(ariaHiddenImpl(targets, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n"],"mappings":"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","names":["root"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Credits: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/overlays/src/ariaHideOutside.ts\nimport { raf } from \"@zag-js/dom-query\"\n\nconst refCountMap = new WeakMap<Element, number>()\nconst observerStack: any[] = []\n\nexport interface AriaHiddenOptions {\n rootEl?: HTMLElement\n defer?: boolean\n}\n\ntype MaybeElement = HTMLElement | null\ntype Targets = Array<MaybeElement>\ntype TargetsOrFn = Targets | (() => Targets)\n\nfunction ariaHiddenImpl(targets: Targets, options: AriaHiddenOptions = {}) {\n const { rootEl } = options\n\n const exclude = targets.filter(Boolean) as HTMLElement[]\n if (exclude.length === 0) return\n\n const doc = exclude[0].ownerDocument || document\n const win = doc.defaultView ?? window\n\n const visibleNodes = new Set<Element>(exclude)\n const hiddenNodes = new Set<Element>()\n\n const root = rootEl ?? doc.body\n\n let walk = (root: Element) => {\n // Keep live announcer and top layer elements (e.g. toasts) visible.\n for (let element of root.querySelectorAll(\"[data-live-announcer], [data-zag-top-layer]\")) {\n visibleNodes.add(element)\n }\n\n let acceptNode = (node: Element) => {\n // Skip this node and its children if it is one of the target nodes, or a live announcer.\n // Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is\n // made for elements with role=\"row\" since VoiceOver on iOS has issues hiding elements with role=\"row\".\n // For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).\n if (\n visibleNodes.has(node) ||\n (hiddenNodes.has(node.parentElement!) && node.parentElement!.getAttribute(\"role\") !== \"row\")\n ) {\n return NodeFilter.FILTER_REJECT\n }\n\n // Skip this node but continue to children if one of the targets is inside the node.\n for (let target of visibleNodes) {\n if (node.contains(target)) {\n return NodeFilter.FILTER_SKIP\n }\n }\n\n return NodeFilter.FILTER_ACCEPT\n }\n\n let walker = doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode })\n\n // TreeWalker does not include the root.\n let acceptRoot = acceptNode(root)\n if (acceptRoot === NodeFilter.FILTER_ACCEPT) {\n hide(root)\n }\n\n if (acceptRoot !== NodeFilter.FILTER_REJECT) {\n let node = walker.nextNode() as Element\n while (node != null) {\n hide(node)\n node = walker.nextNode() as Element\n }\n }\n }\n\n let hide = (node: Element) => {\n let refCount = refCountMap.get(node) ?? 0\n\n // If already aria-hidden, and the ref count is zero, then this element\n // was already hidden and there's nothing for us to do.\n if (node.getAttribute(\"aria-hidden\") === \"true\" && refCount === 0) {\n return\n }\n\n if (refCount === 0) {\n node.setAttribute(\"aria-hidden\", \"true\")\n }\n\n hiddenNodes.add(node)\n refCountMap.set(node, refCount + 1)\n }\n\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect()\n }\n\n walk(root)\n\n const observer = new win.MutationObserver((changes) => {\n for (let change of changes) {\n if (change.type !== \"childList\" || change.addedNodes.length === 0) {\n continue\n }\n\n // If the parent element of the added nodes is not within one of the targets,\n // and not already inside a hidden node, hide all of the new children.\n if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {\n for (let node of change.removedNodes) {\n if (node instanceof win.Element) {\n visibleNodes.delete(node)\n hiddenNodes.delete(node)\n }\n }\n\n for (let node of change.addedNodes) {\n if (\n (node instanceof win.HTMLElement || node instanceof win.SVGElement) &&\n (node.dataset.liveAnnouncer === \"true\" || node.dataset.zagTopLayer === \"true\")\n ) {\n visibleNodes.add(node)\n } else if (node instanceof win.Element) {\n walk(node)\n }\n }\n }\n }\n })\n\n observer.observe(root, { childList: true, subtree: true })\n\n let observerWrapper = {\n observe() {\n observer.observe(root, { childList: true, subtree: true })\n },\n disconnect() {\n observer.disconnect()\n },\n }\n\n observerStack.push(observerWrapper)\n\n return () => {\n observer.disconnect()\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node)\n if (count === 1) {\n node.removeAttribute(\"aria-hidden\")\n refCountMap.delete(node)\n } else {\n refCountMap.set(node, count! - 1)\n }\n }\n\n // Remove this observer from the stack, and start the previous one.\n if (observerWrapper === observerStack[observerStack.length - 1]) {\n observerStack.pop()\n if (observerStack.length) {\n observerStack[observerStack.length - 1].observe()\n }\n } else {\n observerStack.splice(observerStack.indexOf(observerWrapper), 1)\n }\n }\n}\n\nexport function ariaHidden(targetsOrFn: TargetsOrFn, options: AriaHiddenOptions = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const targets = typeof targetsOrFn === \"function\" ? targetsOrFn() : targetsOrFn\n cleanups.push(ariaHiddenImpl(targets, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n"],"mappings":"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","names":["root"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,128 @@
1
- import{raf}from"@zag-js/dom-query";var refCountMap=new WeakMap;var observerStack=[];function ariaHiddenImpl(targets,options={}){const{rootEl}=options;const exclude=targets.filter(Boolean);if(exclude.length===0)return;const doc=exclude[0].ownerDocument||document;const win=doc.defaultView??window;const visibleNodes=new Set(exclude);const hiddenNodes=new Set;const root=rootEl??doc.body;let walk=root2=>{for(let element of root2.querySelectorAll("[data-live-announcer], [data-zag-top-layer]")){visibleNodes.add(element)}let acceptNode=node=>{if(visibleNodes.has(node)||hiddenNodes.has(node.parentElement)&&node.parentElement.getAttribute("role")!=="row"){return NodeFilter.FILTER_REJECT}for(let target of visibleNodes){if(node.contains(target)){return NodeFilter.FILTER_SKIP}}return NodeFilter.FILTER_ACCEPT};let walker=doc.createTreeWalker(root2,NodeFilter.SHOW_ELEMENT,{acceptNode});let acceptRoot=acceptNode(root2);if(acceptRoot===NodeFilter.FILTER_ACCEPT){hide(root2)}if(acceptRoot!==NodeFilter.FILTER_REJECT){let node=walker.nextNode();while(node!=null){hide(node);node=walker.nextNode()}}};let hide=node=>{let refCount=refCountMap.get(node)??0;if(node.getAttribute("aria-hidden")==="true"&&refCount===0){return}if(refCount===0){node.setAttribute("aria-hidden","true")}hiddenNodes.add(node);refCountMap.set(node,refCount+1)};if(observerStack.length){observerStack[observerStack.length-1].disconnect()}walk(root);const observer=new win.MutationObserver(changes=>{for(let change of changes){if(change.type!=="childList"||change.addedNodes.length===0){continue}if(![...visibleNodes,...hiddenNodes].some(node=>node.contains(change.target))){for(let node of change.removedNodes){if(node instanceof win.Element){visibleNodes.delete(node);hiddenNodes.delete(node)}}for(let node of change.addedNodes){if((node instanceof win.HTMLElement||node instanceof win.SVGElement)&&(node.dataset.liveAnnouncer==="true"||node.dataset.zagTopLayer==="true")){visibleNodes.add(node)}else if(node instanceof win.Element){walk(node)}}}}});observer.observe(root,{childList:true,subtree:true});let observerWrapper={observe(){observer.observe(root,{childList:true,subtree:true})},disconnect(){observer.disconnect()}};observerStack.push(observerWrapper);return()=>{observer.disconnect();for(let node of hiddenNodes){let count=refCountMap.get(node);if(count===1){node.removeAttribute("aria-hidden");refCountMap.delete(node)}else{refCountMap.set(node,count-1)}}if(observerWrapper===observerStack[observerStack.length-1]){observerStack.pop();if(observerStack.length){observerStack[observerStack.length-1].observe()}}else{observerStack.splice(observerStack.indexOf(observerWrapper),1)}}}function ariaHidden(targetsOrFn,options={}){const{defer}=options;const func=defer?raf:v=>v();const cleanups=[];cleanups.push(func(()=>{const targets=typeof targetsOrFn==="function"?targetsOrFn():targetsOrFn;cleanups.push(ariaHiddenImpl(targets,options))}));return()=>{cleanups.forEach(fn=>fn?.())}}export{ariaHidden};
1
+ // src/index.ts
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
+ const exclude = targets.filter(Boolean);
8
+ if (exclude.length === 0)
9
+ return;
10
+ const doc = exclude[0].ownerDocument || document;
11
+ const win = doc.defaultView ?? window;
12
+ const visibleNodes = new Set(exclude);
13
+ const hiddenNodes = /* @__PURE__ */ new Set();
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") {
21
+ return NodeFilter.FILTER_REJECT;
22
+ }
23
+ for (let target of visibleNodes) {
24
+ if (node.contains(target)) {
25
+ return NodeFilter.FILTER_SKIP;
26
+ }
27
+ }
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);
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) {
46
+ return;
47
+ }
48
+ if (refCount === 0) {
49
+ node.setAttribute("aria-hidden", "true");
50
+ }
51
+ hiddenNodes.add(node);
52
+ refCountMap.set(node, refCount + 1);
53
+ };
54
+ if (observerStack.length) {
55
+ observerStack[observerStack.length - 1].disconnect();
56
+ }
57
+ walk(root);
58
+ const observer = new win.MutationObserver((changes) => {
59
+ for (let change of changes) {
60
+ if (change.type !== "childList" || change.addedNodes.length === 0) {
61
+ continue;
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);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ });
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);
90
+ return () => {
91
+ observer.disconnect();
92
+ for (let node of hiddenNodes) {
93
+ let count = refCountMap.get(node);
94
+ if (count === 1) {
95
+ node.removeAttribute("aria-hidden");
96
+ refCountMap.delete(node);
97
+ } else {
98
+ refCountMap.set(node, count - 1);
99
+ }
100
+ }
101
+ if (observerWrapper === observerStack[observerStack.length - 1]) {
102
+ observerStack.pop();
103
+ if (observerStack.length) {
104
+ observerStack[observerStack.length - 1].observe();
105
+ }
106
+ } else {
107
+ observerStack.splice(observerStack.indexOf(observerWrapper), 1);
108
+ }
109
+ };
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
+ }
125
+ export {
126
+ ariaHidden
127
+ };
2
128
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Credits: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/overlays/src/ariaHideOutside.ts\nimport { raf } from \"@zag-js/dom-query\"\n\nconst refCountMap = new WeakMap<Element, number>()\nconst observerStack: any[] = []\n\nexport interface AriaHiddenOptions {\n rootEl?: HTMLElement\n defer?: boolean\n}\n\ntype MaybeElement = HTMLElement | null\ntype Targets = Array<MaybeElement>\ntype TargetsOrFn = Targets | (() => Targets)\n\nfunction ariaHiddenImpl(targets: Targets, options: AriaHiddenOptions = {}) {\n const { rootEl } = options\n\n const exclude = targets.filter(Boolean) as HTMLElement[]\n if (exclude.length === 0) return\n\n const doc = exclude[0].ownerDocument || document\n const win = doc.defaultView ?? window\n\n const visibleNodes = new Set<Element>(exclude)\n const hiddenNodes = new Set<Element>()\n\n const root = rootEl ?? doc.body\n\n let walk = (root: Element) => {\n // Keep live announcer and top layer elements (e.g. toasts) visible.\n for (let element of root.querySelectorAll(\"[data-live-announcer], [data-zag-top-layer]\")) {\n visibleNodes.add(element)\n }\n\n let acceptNode = (node: Element) => {\n // Skip this node and its children if it is one of the target nodes, or a live announcer.\n // Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is\n // made for elements with role=\"row\" since VoiceOver on iOS has issues hiding elements with role=\"row\".\n // For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).\n if (\n visibleNodes.has(node) ||\n (hiddenNodes.has(node.parentElement!) && node.parentElement!.getAttribute(\"role\") !== \"row\")\n ) {\n return NodeFilter.FILTER_REJECT\n }\n\n // Skip this node but continue to children if one of the targets is inside the node.\n for (let target of visibleNodes) {\n if (node.contains(target)) {\n return NodeFilter.FILTER_SKIP\n }\n }\n\n return NodeFilter.FILTER_ACCEPT\n }\n\n let walker = doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode })\n\n // TreeWalker does not include the root.\n let acceptRoot = acceptNode(root)\n if (acceptRoot === NodeFilter.FILTER_ACCEPT) {\n hide(root)\n }\n\n if (acceptRoot !== NodeFilter.FILTER_REJECT) {\n let node = walker.nextNode() as Element\n while (node != null) {\n hide(node)\n node = walker.nextNode() as Element\n }\n }\n }\n\n let hide = (node: Element) => {\n let refCount = refCountMap.get(node) ?? 0\n\n // If already aria-hidden, and the ref count is zero, then this element\n // was already hidden and there's nothing for us to do.\n if (node.getAttribute(\"aria-hidden\") === \"true\" && refCount === 0) {\n return\n }\n\n if (refCount === 0) {\n node.setAttribute(\"aria-hidden\", \"true\")\n }\n\n hiddenNodes.add(node)\n refCountMap.set(node, refCount + 1)\n }\n\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect()\n }\n\n walk(root)\n\n const observer = new win.MutationObserver((changes) => {\n for (let change of changes) {\n if (change.type !== \"childList\" || change.addedNodes.length === 0) {\n continue\n }\n\n // If the parent element of the added nodes is not within one of the targets,\n // and not already inside a hidden node, hide all of the new children.\n if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {\n for (let node of change.removedNodes) {\n if (node instanceof win.Element) {\n visibleNodes.delete(node)\n hiddenNodes.delete(node)\n }\n }\n\n for (let node of change.addedNodes) {\n if (\n (node instanceof win.HTMLElement || node instanceof win.SVGElement) &&\n (node.dataset.liveAnnouncer === \"true\" || node.dataset.zagTopLayer === \"true\")\n ) {\n visibleNodes.add(node)\n } else if (node instanceof win.Element) {\n walk(node)\n }\n }\n }\n }\n })\n\n observer.observe(root, { childList: true, subtree: true })\n\n let observerWrapper = {\n observe() {\n observer.observe(root, { childList: true, subtree: true })\n },\n disconnect() {\n observer.disconnect()\n },\n }\n\n observerStack.push(observerWrapper)\n\n return () => {\n observer.disconnect()\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node)\n if (count === 1) {\n node.removeAttribute(\"aria-hidden\")\n refCountMap.delete(node)\n } else {\n refCountMap.set(node, count! - 1)\n }\n }\n\n // Remove this observer from the stack, and start the previous one.\n if (observerWrapper === observerStack[observerStack.length - 1]) {\n observerStack.pop()\n if (observerStack.length) {\n observerStack[observerStack.length - 1].observe()\n }\n } else {\n observerStack.splice(observerStack.indexOf(observerWrapper), 1)\n }\n }\n}\n\nexport function ariaHidden(targetsOrFn: TargetsOrFn, options: AriaHiddenOptions = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const targets = typeof targetsOrFn === \"function\" ? targetsOrFn() : targetsOrFn\n cleanups.push(ariaHiddenImpl(targets, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n"],"mappings":"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","names":["root"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Credits: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/overlays/src/ariaHideOutside.ts\nimport { raf } from \"@zag-js/dom-query\"\n\nconst refCountMap = new WeakMap<Element, number>()\nconst observerStack: any[] = []\n\nexport interface AriaHiddenOptions {\n rootEl?: HTMLElement\n defer?: boolean\n}\n\ntype MaybeElement = HTMLElement | null\ntype Targets = Array<MaybeElement>\ntype TargetsOrFn = Targets | (() => Targets)\n\nfunction ariaHiddenImpl(targets: Targets, options: AriaHiddenOptions = {}) {\n const { rootEl } = options\n\n const exclude = targets.filter(Boolean) as HTMLElement[]\n if (exclude.length === 0) return\n\n const doc = exclude[0].ownerDocument || document\n const win = doc.defaultView ?? window\n\n const visibleNodes = new Set<Element>(exclude)\n const hiddenNodes = new Set<Element>()\n\n const root = rootEl ?? doc.body\n\n let walk = (root: Element) => {\n // Keep live announcer and top layer elements (e.g. toasts) visible.\n for (let element of root.querySelectorAll(\"[data-live-announcer], [data-zag-top-layer]\")) {\n visibleNodes.add(element)\n }\n\n let acceptNode = (node: Element) => {\n // Skip this node and its children if it is one of the target nodes, or a live announcer.\n // Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is\n // made for elements with role=\"row\" since VoiceOver on iOS has issues hiding elements with role=\"row\".\n // For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).\n if (\n visibleNodes.has(node) ||\n (hiddenNodes.has(node.parentElement!) && node.parentElement!.getAttribute(\"role\") !== \"row\")\n ) {\n return NodeFilter.FILTER_REJECT\n }\n\n // Skip this node but continue to children if one of the targets is inside the node.\n for (let target of visibleNodes) {\n if (node.contains(target)) {\n return NodeFilter.FILTER_SKIP\n }\n }\n\n return NodeFilter.FILTER_ACCEPT\n }\n\n let walker = doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, { acceptNode })\n\n // TreeWalker does not include the root.\n let acceptRoot = acceptNode(root)\n if (acceptRoot === NodeFilter.FILTER_ACCEPT) {\n hide(root)\n }\n\n if (acceptRoot !== NodeFilter.FILTER_REJECT) {\n let node = walker.nextNode() as Element\n while (node != null) {\n hide(node)\n node = walker.nextNode() as Element\n }\n }\n }\n\n let hide = (node: Element) => {\n let refCount = refCountMap.get(node) ?? 0\n\n // If already aria-hidden, and the ref count is zero, then this element\n // was already hidden and there's nothing for us to do.\n if (node.getAttribute(\"aria-hidden\") === \"true\" && refCount === 0) {\n return\n }\n\n if (refCount === 0) {\n node.setAttribute(\"aria-hidden\", \"true\")\n }\n\n hiddenNodes.add(node)\n refCountMap.set(node, refCount + 1)\n }\n\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect()\n }\n\n walk(root)\n\n const observer = new win.MutationObserver((changes) => {\n for (let change of changes) {\n if (change.type !== \"childList\" || change.addedNodes.length === 0) {\n continue\n }\n\n // If the parent element of the added nodes is not within one of the targets,\n // and not already inside a hidden node, hide all of the new children.\n if (![...visibleNodes, ...hiddenNodes].some((node) => node.contains(change.target))) {\n for (let node of change.removedNodes) {\n if (node instanceof win.Element) {\n visibleNodes.delete(node)\n hiddenNodes.delete(node)\n }\n }\n\n for (let node of change.addedNodes) {\n if (\n (node instanceof win.HTMLElement || node instanceof win.SVGElement) &&\n (node.dataset.liveAnnouncer === \"true\" || node.dataset.zagTopLayer === \"true\")\n ) {\n visibleNodes.add(node)\n } else if (node instanceof win.Element) {\n walk(node)\n }\n }\n }\n }\n })\n\n observer.observe(root, { childList: true, subtree: true })\n\n let observerWrapper = {\n observe() {\n observer.observe(root, { childList: true, subtree: true })\n },\n disconnect() {\n observer.disconnect()\n },\n }\n\n observerStack.push(observerWrapper)\n\n return () => {\n observer.disconnect()\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node)\n if (count === 1) {\n node.removeAttribute(\"aria-hidden\")\n refCountMap.delete(node)\n } else {\n refCountMap.set(node, count! - 1)\n }\n }\n\n // Remove this observer from the stack, and start the previous one.\n if (observerWrapper === observerStack[observerStack.length - 1]) {\n observerStack.pop()\n if (observerStack.length) {\n observerStack[observerStack.length - 1].observe()\n }\n } else {\n observerStack.splice(observerStack.indexOf(observerWrapper), 1)\n }\n }\n}\n\nexport function ariaHidden(targetsOrFn: TargetsOrFn, options: AriaHiddenOptions = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const targets = typeof targetsOrFn === \"function\" ? targetsOrFn() : targetsOrFn\n cleanups.push(ariaHiddenImpl(targets, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n"],"mappings":"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","names":["root"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/aria-hidden",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "description": "Hide targets from screen readers",
5
5
  "keywords": [
6
6
  "js",
@@ -25,7 +25,7 @@
25
25
  "clean-package": "../../../clean-package.config.json",
26
26
  "main": "dist/index.js",
27
27
  "dependencies": {
28
- "@zag-js/dom-query": "0.53.0"
28
+ "@zag-js/dom-query": "0.54.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "clean-package": "2.2.0"