Socket
Socket
Sign inDemoInstall

@zag-js/aria-hidden

Package Overview
Dependencies
1
Maintainers
1
Versions
664
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.0-dev-20230202113057 to 0.0.0-dev-20230504114722

11

dist/index.d.ts

@@ -1,3 +0,10 @@

declare function ariaHidden(targets: Array<HTMLElement | null>, rootEl?: HTMLElement): (() => void) | undefined;
type AriaHiddenOptions = {
rootEl?: HTMLElement;
defer?: boolean;
};
type MaybeElement = HTMLElement | null;
type Targets = Array<MaybeElement>;
type TargetsOrFn = Targets | (() => Targets);
declare function ariaHidden(targetsOrFn: TargetsOrFn, options?: AriaHiddenOptions): () => void;
export { ariaHidden };
export { AriaHiddenOptions, ariaHidden };

128

dist/index.js

@@ -26,7 +26,7 @@ "use strict";

module.exports = __toCommonJS(src_exports);
var elementCountMap = /* @__PURE__ */ new WeakMap();
function isLiveRegion(node, win) {
return node instanceof win.HTMLElement && node.dataset.liveAnnouncer === "true";
}
function ariaHidden(targets, rootEl) {
var import_dom_query = require("@zag-js/dom-query");
var refCountMap = /* @__PURE__ */ new WeakMap();
var observerStack = [];
function ariaHiddenImpl(targets, options = {}) {
const { rootEl } = options;
const exclude = targets.filter(Boolean);

@@ -40,47 +40,64 @@ if (exclude.length === 0)

const root = rootEl ?? doc.body;
const walker = doc.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
acceptNode(node2) {
if (isLiveRegion(node2, win)) {
visibleNodes.add(node2);
}
if (visibleNodes.has(node2) || hiddenNodes.has(node2.parentElement)) {
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;
}
if (node2 instanceof win.HTMLElement && node2.getAttribute("role") === "row") {
return NodeFilter.FILTER_SKIP;
for (let target of visibleNodes) {
if (node.contains(target)) {
return NodeFilter.FILTER_SKIP;
}
}
if (exclude.some((target) => node2.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);
}
});
const hide = (node2) => {
let refCount = elementCountMap.get(node2) ?? 0;
if (node2.getAttribute("aria-hidden") === "true" && refCount === 0) {
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) {
node2.setAttribute("aria-hidden", "true");
node.setAttribute("aria-hidden", "true");
}
hiddenNodes.add(node2);
elementCountMap.set(node2, refCount + 1);
hiddenNodes.add(node);
refCountMap.set(node, refCount + 1);
};
let node = walker.nextNode();
while (node != null) {
hide(node);
node = walker.nextNode();
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)
if (change.type !== "childList" || change.addedNodes.length === 0) {
continue;
if (![...visibleNodes, ...hiddenNodes].some((node2) => node2.contains(change.target))) {
for (const node2 of change.addedNodes) {
if (isLiveRegion(node2, win)) {
visibleNodes.add(node2);
} else if (node2 instanceof win.Element) {
hide(node2);
}
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);
}
}
}

@@ -90,17 +107,46 @@ }

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 node2 of hiddenNodes) {
let count = elementCountMap.get(node2);
for (let node of hiddenNodes) {
let count = refCountMap.get(node);
if (count === 1) {
node2.removeAttribute("aria-hidden");
elementCountMap.delete(node2);
continue;
node.removeAttribute("aria-hidden");
refCountMap.delete(node);
} else {
refCountMap.set(node, count - 1);
}
if (count !== void 0) {
elementCountMap.set(node2, 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?.());
};
}
// Annotate the CommonJS export names for ESM import in node:

@@ -107,0 +153,0 @@ 0 && (module.exports = {

{
"name": "@zag-js/aria-hidden",
"version": "0.0.0-dev-20230202113057",
"version": "0.0.0-dev-20230504114722",
"description": "Hide targets from screen readers",

@@ -26,2 +26,5 @@ "keywords": [

"main": "dist/index.js",
"dependencies": {
"@zag-js/dom-query": "0.1.4"
},
"devDependencies": {

@@ -28,0 +31,0 @@ "clean-package": "2.2.0"

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc