147 lines
7.6 KiB
Plaintext
147 lines
7.6 KiB
Plaintext
import {getOwnerWindow as $fF94N$getOwnerWindow} from "@react-aria/utils";
|
|
|
|
/*
|
|
* Copyright 2020 Adobe. All rights reserved.
|
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
* governing permissions and limitations under the License.
|
|
*/
|
|
const $5e3802645cc19319$var$supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;
|
|
// Keeps a ref count of all hidden elements. Added to when hiding an element, and
|
|
// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.
|
|
let $5e3802645cc19319$var$refCountMap = new WeakMap();
|
|
let $5e3802645cc19319$var$observerStack = [];
|
|
function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
|
|
let windowObj = (0, $fF94N$getOwnerWindow)(targets === null || targets === void 0 ? void 0 : targets[0]);
|
|
let opts = options instanceof windowObj.Element ? {
|
|
root: options
|
|
} : options;
|
|
var _opts_root;
|
|
let root = (_opts_root = opts === null || opts === void 0 ? void 0 : opts.root) !== null && _opts_root !== void 0 ? _opts_root : document.body;
|
|
let shouldUseInert = (opts === null || opts === void 0 ? void 0 : opts.shouldUseInert) && $5e3802645cc19319$var$supportsInert;
|
|
let visibleNodes = new Set(targets);
|
|
let hiddenNodes = new Set();
|
|
let getHidden = (element)=>{
|
|
return shouldUseInert && element instanceof windowObj.HTMLElement ? element.inert : element.getAttribute('aria-hidden') === 'true';
|
|
};
|
|
let setHidden = (element, hidden)=>{
|
|
if (shouldUseInert && element instanceof windowObj.HTMLElement) element.inert = hidden;
|
|
else if (hidden) element.setAttribute('aria-hidden', 'true');
|
|
else {
|
|
element.removeAttribute('aria-hidden');
|
|
if (element instanceof windowObj.HTMLElement) // We only ever call setHidden with hidden = false when the nodeCount is 1 aka
|
|
// we are trying to make the element visible to screen readers again, so remove inert as well
|
|
element.inert = false;
|
|
}
|
|
};
|
|
let walk = (root)=>{
|
|
// Keep live announcer and top layer elements (e.g. toasts) visible.
|
|
for (let element of root.querySelectorAll('[data-live-announcer], [data-react-aria-top-layer]'))visibleNodes.add(element);
|
|
let acceptNode = (node)=>{
|
|
// Skip this node and its children if it is one of the target nodes, or a live announcer.
|
|
// Also skip children of already hidden nodes, as aria-hidden is recursive. An exception is
|
|
// made for elements with role="row" since VoiceOver on iOS has issues hiding elements with role="row".
|
|
// For that case we want to hide the cells inside as well (https://bugs.webkit.org/show_bug.cgi?id=222623).
|
|
if (hiddenNodes.has(node) || visibleNodes.has(node) || node.parentElement && hiddenNodes.has(node.parentElement) && node.parentElement.getAttribute('role') !== 'row') return NodeFilter.FILTER_REJECT;
|
|
// Skip this node but continue to children if one of the targets is inside the node.
|
|
for (let target of visibleNodes){
|
|
if (node.contains(target)) return NodeFilter.FILTER_SKIP;
|
|
}
|
|
return NodeFilter.FILTER_ACCEPT;
|
|
};
|
|
let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
|
|
acceptNode: acceptNode
|
|
});
|
|
// TreeWalker does not include the root.
|
|
let acceptRoot = acceptNode(root);
|
|
if (acceptRoot === NodeFilter.FILTER_ACCEPT) hide(root);
|
|
if (acceptRoot !== NodeFilter.FILTER_REJECT) {
|
|
let node = walker.nextNode();
|
|
while(node != null){
|
|
hide(node);
|
|
node = walker.nextNode();
|
|
}
|
|
}
|
|
};
|
|
let hide = (node)=>{
|
|
var _refCountMap_get;
|
|
let refCount = (_refCountMap_get = $5e3802645cc19319$var$refCountMap.get(node)) !== null && _refCountMap_get !== void 0 ? _refCountMap_get : 0;
|
|
// If already aria-hidden, and the ref count is zero, then this element
|
|
// was already hidden and there's nothing for us to do.
|
|
if (getHidden(node) && refCount === 0) return;
|
|
if (refCount === 0) setHidden(node, true);
|
|
hiddenNodes.add(node);
|
|
$5e3802645cc19319$var$refCountMap.set(node, refCount + 1);
|
|
};
|
|
// If there is already a MutationObserver listening from a previous call,
|
|
// disconnect it so the new on takes over.
|
|
if ($5e3802645cc19319$var$observerStack.length) $5e3802645cc19319$var$observerStack[$5e3802645cc19319$var$observerStack.length - 1].disconnect();
|
|
walk(root);
|
|
let observer = new MutationObserver((changes)=>{
|
|
for (let change of changes){
|
|
if (change.type !== 'childList') continue;
|
|
// If the parent element of the added nodes is not within one of the targets,
|
|
// and not already inside a hidden node, hide all of the new children.
|
|
if (![
|
|
...visibleNodes,
|
|
...hiddenNodes
|
|
].some((node)=>node.contains(change.target))) for (let node of change.addedNodes){
|
|
if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
|
|
else if (node instanceof Element) walk(node);
|
|
}
|
|
}
|
|
});
|
|
observer.observe(root, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
let observerWrapper = {
|
|
visibleNodes: visibleNodes,
|
|
hiddenNodes: hiddenNodes,
|
|
observe () {
|
|
observer.observe(root, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
},
|
|
disconnect () {
|
|
observer.disconnect();
|
|
}
|
|
};
|
|
$5e3802645cc19319$var$observerStack.push(observerWrapper);
|
|
return ()=>{
|
|
observer.disconnect();
|
|
for (let node of hiddenNodes){
|
|
let count = $5e3802645cc19319$var$refCountMap.get(node);
|
|
if (count == null) continue;
|
|
if (count === 1) {
|
|
setHidden(node, false);
|
|
$5e3802645cc19319$var$refCountMap.delete(node);
|
|
} else $5e3802645cc19319$var$refCountMap.set(node, count - 1);
|
|
}
|
|
// Remove this observer from the stack, and start the previous one.
|
|
if (observerWrapper === $5e3802645cc19319$var$observerStack[$5e3802645cc19319$var$observerStack.length - 1]) {
|
|
$5e3802645cc19319$var$observerStack.pop();
|
|
if ($5e3802645cc19319$var$observerStack.length) $5e3802645cc19319$var$observerStack[$5e3802645cc19319$var$observerStack.length - 1].observe();
|
|
} else $5e3802645cc19319$var$observerStack.splice($5e3802645cc19319$var$observerStack.indexOf(observerWrapper), 1);
|
|
};
|
|
}
|
|
function $5e3802645cc19319$export$1020fa7f77e17884(element) {
|
|
let observer = $5e3802645cc19319$var$observerStack[$5e3802645cc19319$var$observerStack.length - 1];
|
|
if (observer && !observer.visibleNodes.has(element)) {
|
|
observer.visibleNodes.add(element);
|
|
return ()=>{
|
|
observer.visibleNodes.delete(element);
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
export {$5e3802645cc19319$export$1c3ebcada18427bf as ariaHideOutside, $5e3802645cc19319$export$1020fa7f77e17884 as keepVisible};
|
|
//# sourceMappingURL=ariaHideOutside.module.js.map
|