@react-aria/overlays 3.31.1 → 3.31.2

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.
Files changed (38) hide show
  1. package/dist/ariaHideOutside.main.js +52 -1
  2. package/dist/ariaHideOutside.main.js.map +1 -1
  3. package/dist/ariaHideOutside.mjs +53 -2
  4. package/dist/ariaHideOutside.module.js +53 -2
  5. package/dist/ariaHideOutside.module.js.map +1 -1
  6. package/dist/calculatePosition.main.js +28 -4
  7. package/dist/calculatePosition.main.js.map +1 -1
  8. package/dist/calculatePosition.mjs +28 -4
  9. package/dist/calculatePosition.module.js +28 -4
  10. package/dist/calculatePosition.module.js.map +1 -1
  11. package/dist/types.d.ts.map +1 -1
  12. package/dist/useCloseOnScroll.main.js +2 -2
  13. package/dist/useCloseOnScroll.main.js.map +1 -1
  14. package/dist/useCloseOnScroll.mjs +3 -3
  15. package/dist/useCloseOnScroll.module.js +3 -3
  16. package/dist/useCloseOnScroll.module.js.map +1 -1
  17. package/dist/useOverlay.main.js +5 -3
  18. package/dist/useOverlay.main.js.map +1 -1
  19. package/dist/useOverlay.mjs +5 -3
  20. package/dist/useOverlay.module.js +5 -3
  21. package/dist/useOverlay.module.js.map +1 -1
  22. package/dist/useOverlayPosition.main.js +6 -5
  23. package/dist/useOverlayPosition.main.js.map +1 -1
  24. package/dist/useOverlayPosition.mjs +7 -6
  25. package/dist/useOverlayPosition.module.js +7 -6
  26. package/dist/useOverlayPosition.module.js.map +1 -1
  27. package/dist/usePreventScroll.main.js +9 -4
  28. package/dist/usePreventScroll.main.js.map +1 -1
  29. package/dist/usePreventScroll.mjs +10 -5
  30. package/dist/usePreventScroll.module.js +10 -5
  31. package/dist/usePreventScroll.module.js.map +1 -1
  32. package/package.json +12 -11
  33. package/src/ariaHideOutside.ts +81 -2
  34. package/src/calculatePosition.ts +27 -5
  35. package/src/useCloseOnScroll.ts +3 -3
  36. package/src/useOverlay.ts +4 -3
  37. package/src/useOverlayPosition.ts +6 -5
  38. package/src/usePreventScroll.ts +13 -7
@@ -1,4 +1,5 @@
1
1
  var $4MDXc$reactariautils = require("@react-aria/utils");
2
+ var $4MDXc$reactstatelyflags = require("@react-stately/flags");
2
3
 
3
4
 
4
5
  function $parcel$export(e, n, v, s) {
@@ -18,6 +19,7 @@ $parcel$export(module.exports, "keepVisible", () => $08ef1685902b6011$export$102
18
19
  * OF ANY KIND, either express or implied. See the License for the specific language
19
20
  * governing permissions and limitations under the License.
20
21
  */
22
+
21
23
  const $08ef1685902b6011$var$supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;
22
24
  // Keeps a ref count of all hidden elements. Added to when hiding an element, and
23
25
  // subtracted from when showing it again. When it reaches zero, aria-hidden is removed.
@@ -46,6 +48,17 @@ function $08ef1685902b6011$export$1c3ebcada18427bf(targets, options) {
46
48
  element.inert = false;
47
49
  }
48
50
  };
51
+ let shadowRootsToWatch = new Set();
52
+ if ((0, $4MDXc$reactstatelyflags.shadowDOM)()) // find all shadow roots that are ancestors of the targets
53
+ // traverse upwards until the root is reached
54
+ for (let target of targets){
55
+ let node = target;
56
+ while(node && node !== root){
57
+ let root = node.getRootNode();
58
+ if ('shadowRoot' in root) shadowRootsToWatch.add(root.shadowRoot);
59
+ node = root.parentNode;
60
+ }
61
+ }
49
62
  let walk = (root)=>{
50
63
  // Keep live announcer and top layer elements (e.g. toasts) visible.
51
64
  for (let element of root.querySelectorAll('[data-live-announcer], [data-react-aria-top-layer]'))visibleNodes.add(element);
@@ -61,7 +74,7 @@ function $08ef1685902b6011$export$1c3ebcada18427bf(targets, options) {
61
74
  }
62
75
  return NodeFilter.FILTER_ACCEPT;
63
76
  };
64
- let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
77
+ let walker = (0, $4MDXc$reactariautils.createShadowTreeWalker)((0, $4MDXc$reactariautils.getOwnerDocument)(root), root, NodeFilter.SHOW_ELEMENT, {
65
78
  acceptNode: acceptNode
66
79
  });
67
80
  // TreeWalker does not include the root.
@@ -101,12 +114,49 @@ function $08ef1685902b6011$export$1c3ebcada18427bf(targets, options) {
101
114
  if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
102
115
  else if (node instanceof Element) walk(node);
103
116
  }
117
+ if ((0, $4MDXc$reactstatelyflags.shadowDOM)()) {
118
+ // if any of the observed shadow roots were removed, stop observing them
119
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
120
+ observer.disconnect();
121
+ break;
122
+ }
123
+ }
104
124
  }
105
125
  });
106
126
  observer.observe(root, {
107
127
  childList: true,
108
128
  subtree: true
109
129
  });
130
+ let shadowObservers = new Set();
131
+ if ((0, $4MDXc$reactstatelyflags.shadowDOM)()) for (let shadowRoot of shadowRootsToWatch){
132
+ // Disconnect single target instead of all https://github.com/whatwg/dom/issues/126
133
+ let shadowObserver = new MutationObserver((changes)=>{
134
+ for (let change of changes){
135
+ if (change.type !== 'childList') continue;
136
+ // If the parent element of the added nodes is not within one of the targets,
137
+ // and not already inside a hidden node, hide all of the new children.
138
+ if (change.target.isConnected && ![
139
+ ...visibleNodes,
140
+ ...hiddenNodes
141
+ ].some((node)=>(0, $4MDXc$reactariautils.nodeContains)(node, change.target))) for (let node of change.addedNodes){
142
+ if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
143
+ else if (node instanceof Element) walk(node);
144
+ }
145
+ if ((0, $4MDXc$reactstatelyflags.shadowDOM)()) {
146
+ // if any of the observed shadow roots were removed, stop observing them
147
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
148
+ observer.disconnect();
149
+ break;
150
+ }
151
+ }
152
+ }
153
+ });
154
+ shadowObserver.observe(shadowRoot, {
155
+ childList: true,
156
+ subtree: true
157
+ });
158
+ shadowObservers.add(shadowObserver);
159
+ }
110
160
  let observerWrapper = {
111
161
  visibleNodes: visibleNodes,
112
162
  hiddenNodes: hiddenNodes,
@@ -123,6 +173,7 @@ function $08ef1685902b6011$export$1c3ebcada18427bf(targets, options) {
123
173
  $08ef1685902b6011$var$observerStack.push(observerWrapper);
124
174
  return ()=>{
125
175
  observer.disconnect();
176
+ if ((0, $4MDXc$reactstatelyflags.shadowDOM)()) for (let shadowObserver of shadowObservers)shadowObserver.disconnect();
126
177
  for (let node of hiddenNodes){
127
178
  let count = $08ef1685902b6011$var$refCountMap.get(node);
128
179
  if (count == null) continue;
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/overlays/src/ariaHideOutside.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {getOwnerWindow, nodeContains} from '@react-aria/utils';\nconst supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;\n\ninterface AriaHideOutsideOptions {\n root?: Element,\n shouldUseInert?: boolean\n}\n\n// Keeps a ref count of all hidden elements. Added to when hiding an element, and\n// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.\nlet refCountMap = new WeakMap<Element, number>();\ninterface ObserverWrapper {\n visibleNodes: Set<Element>,\n hiddenNodes: Set<Element>,\n observe: () => void,\n disconnect: () => void\n}\nlet observerStack: Array<ObserverWrapper> = [];\n\n/**\n * Hides all elements in the DOM outside the given targets from screen readers using aria-hidden,\n * and returns a function to revert these changes. In addition, changes to the DOM are watched\n * and new elements outside the targets are automatically hidden.\n * @param targets - The elements that should remain visible.\n * @param root - Nothing will be hidden above this element.\n * @returns - A function to restore all hidden elements.\n */\nexport function ariaHideOutside(targets: Element[], options?: AriaHideOutsideOptions | Element) {\n let windowObj = getOwnerWindow(targets?.[0]);\n let opts = options instanceof windowObj.Element ? {root: options} : options;\n let root = opts?.root ?? document.body;\n let shouldUseInert = opts?.shouldUseInert && supportsInert;\n let visibleNodes = new Set<Element>(targets);\n let hiddenNodes = new Set<Element>();\n\n let getHidden = (element: Element) => {\n return shouldUseInert && element instanceof windowObj.HTMLElement ? element.inert : element.getAttribute('aria-hidden') === 'true';\n };\n\n let setHidden = (element: Element, hidden: boolean) => {\n if (shouldUseInert && element instanceof windowObj.HTMLElement) {\n element.inert = hidden;\n } else if (hidden) {\n element.setAttribute('aria-hidden', 'true');\n } else {\n element.removeAttribute('aria-hidden');\n if (element instanceof windowObj.HTMLElement) {\n // We only ever call setHidden with hidden = false when the nodeCount is 1 aka\n // we are trying to make the element visible to screen readers again, so remove inert as well\n element.inert = false;\n }\n }\n };\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-react-aria-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 hiddenNodes.has(node) ||\n visibleNodes.has(node) ||\n (node.parentElement && 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 (nodeContains(node, target)) {\n return NodeFilter.FILTER_SKIP;\n }\n }\n\n return NodeFilter.FILTER_ACCEPT;\n };\n\n let walker = document.createTreeWalker(\n root,\n NodeFilter.SHOW_ELEMENT,\n {acceptNode}\n );\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 (getHidden(node) && refCount === 0) {\n return;\n }\n\n if (refCount === 0) {\n setHidden(node, true);\n }\n\n hiddenNodes.add(node);\n refCountMap.set(node, refCount + 1);\n };\n\n // If there is already a MutationObserver listening from a previous call,\n // disconnect it so the new on takes over.\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect();\n }\n\n walk(root);\n\n let observer = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n }\n });\n\n observer.observe(root, {childList: true, subtree: true});\n\n let observerWrapper: ObserverWrapper = {\n visibleNodes,\n hiddenNodes,\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 (): void => {\n observer.disconnect();\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node);\n if (count == null) {\n continue;\n }\n if (count === 1) {\n setHidden(node, false);\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 keepVisible(element: Element): (() => void) | undefined {\n let observer = observerStack[observerStack.length - 1];\n if (observer && !observer.visibleNodes.has(element)) {\n observer.visibleNodes.add(element);\n return () => {\n observer.visibleNodes.delete(element);\n };\n }\n}\n"],"names":[],"version":3,"file":"ariaHideOutside.main.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/overlays/src/ariaHideOutside.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {createShadowTreeWalker, getOwnerDocument, getOwnerWindow, nodeContains} from '@react-aria/utils';\nimport {shadowDOM} from '@react-stately/flags';\n\nconst supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;\n\ninterface AriaHideOutsideOptions {\n root?: Element,\n shouldUseInert?: boolean\n}\n\n// Keeps a ref count of all hidden elements. Added to when hiding an element, and\n// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.\nlet refCountMap = new WeakMap<Element, number>();\ninterface ObserverWrapper {\n visibleNodes: Set<Element>,\n hiddenNodes: Set<Element>,\n observe: () => void,\n disconnect: () => void\n}\nlet observerStack: Array<ObserverWrapper> = [];\n\n/**\n * Hides all elements in the DOM outside the given targets from screen readers using aria-hidden,\n * and returns a function to revert these changes. In addition, changes to the DOM are watched\n * and new elements outside the targets are automatically hidden.\n * @param targets - The elements that should remain visible.\n * @param root - Nothing will be hidden above this element.\n * @returns - A function to restore all hidden elements.\n */\nexport function ariaHideOutside(targets: Element[], options?: AriaHideOutsideOptions | Element) {\n let windowObj = getOwnerWindow(targets?.[0]);\n let opts = options instanceof windowObj.Element ? {root: options} : options;\n let root = opts?.root ?? document.body;\n let shouldUseInert = opts?.shouldUseInert && supportsInert;\n let visibleNodes = new Set<Element>(targets);\n let hiddenNodes = new Set<Element>();\n\n let getHidden = (element: Element) => {\n return shouldUseInert && element instanceof windowObj.HTMLElement ? element.inert : element.getAttribute('aria-hidden') === 'true';\n };\n\n let setHidden = (element: Element, hidden: boolean) => {\n if (shouldUseInert && element instanceof windowObj.HTMLElement) {\n element.inert = hidden;\n } else if (hidden) {\n element.setAttribute('aria-hidden', 'true');\n } else {\n element.removeAttribute('aria-hidden');\n if (element instanceof windowObj.HTMLElement) {\n // We only ever call setHidden with hidden = false when the nodeCount is 1 aka\n // we are trying to make the element visible to screen readers again, so remove inert as well\n element.inert = false;\n }\n }\n };\n\n let shadowRootsToWatch = new Set<ShadowRoot>();\n if (shadowDOM()) {\n // find all shadow roots that are ancestors of the targets\n // traverse upwards until the root is reached\n for (let target of targets) {\n let node = target;\n while (node && node !== root) {\n let root = node.getRootNode();\n if ('shadowRoot' in root) {\n shadowRootsToWatch.add(root.shadowRoot as ShadowRoot);\n }\n node = root.parentNode as Element;\n }\n }\n }\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-react-aria-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 hiddenNodes.has(node) ||\n visibleNodes.has(node) ||\n (node.parentElement && 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 (nodeContains(node, target)) {\n return NodeFilter.FILTER_SKIP;\n }\n }\n\n return NodeFilter.FILTER_ACCEPT;\n };\n\n let walker = createShadowTreeWalker(\n getOwnerDocument(root),\n root,\n NodeFilter.SHOW_ELEMENT,\n {acceptNode}\n );\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 (getHidden(node) && refCount === 0) {\n return;\n }\n\n if (refCount === 0) {\n setHidden(node, true);\n }\n\n hiddenNodes.add(node);\n refCountMap.set(node, refCount + 1);\n };\n\n // If there is already a MutationObserver listening from a previous call,\n // disconnect it so the new on takes over.\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect();\n }\n\n walk(root);\n\n let observer = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n\n if (shadowDOM()) {\n // if any of the observed shadow roots were removed, stop observing them\n for (let shadowRoot of shadowRootsToWatch) {\n if (!shadowRoot.isConnected) {\n observer.disconnect();\n break;\n }\n }\n }\n }\n });\n\n observer.observe(root, {childList: true, subtree: true});\n let shadowObservers = new Set<MutationObserver>();\n if (shadowDOM()) {\n for (let shadowRoot of shadowRootsToWatch) {\n // Disconnect single target instead of all https://github.com/whatwg/dom/issues/126\n let shadowObserver = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n\n if (shadowDOM()) {\n // if any of the observed shadow roots were removed, stop observing them\n for (let shadowRoot of shadowRootsToWatch) {\n if (!shadowRoot.isConnected) {\n observer.disconnect();\n break;\n }\n }\n }\n }\n });\n shadowObserver.observe(shadowRoot, {childList: true, subtree: true});\n shadowObservers.add(shadowObserver);\n }\n }\n\n let observerWrapper: ObserverWrapper = {\n visibleNodes,\n hiddenNodes,\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 (): void => {\n observer.disconnect();\n if (shadowDOM()) {\n for (let shadowObserver of shadowObservers) {\n shadowObserver.disconnect();\n }\n }\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node);\n if (count == null) {\n continue;\n }\n if (count === 1) {\n setHidden(node, false);\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 keepVisible(element: Element): (() => void) | undefined {\n let observer = observerStack[observerStack.length - 1];\n if (observer && !observer.visibleNodes.has(element)) {\n observer.visibleNodes.add(element);\n return () => {\n observer.visibleNodes.delete(element);\n };\n }\n}\n"],"names":[],"version":3,"file":"ariaHideOutside.main.js.map"}
@@ -1,4 +1,5 @@
1
- import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeContains} from "@react-aria/utils";
1
+ import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeContains, createShadowTreeWalker as $fF94N$createShadowTreeWalker, getOwnerDocument as $fF94N$getOwnerDocument} from "@react-aria/utils";
2
+ import {shadowDOM as $fF94N$shadowDOM} from "@react-stately/flags";
2
3
 
3
4
  /*
4
5
  * Copyright 2020 Adobe. All rights reserved.
@@ -11,6 +12,7 @@ import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeCont
11
12
  * OF ANY KIND, either express or implied. See the License for the specific language
12
13
  * governing permissions and limitations under the License.
13
14
  */
15
+
14
16
  const $5e3802645cc19319$var$supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;
15
17
  // Keeps a ref count of all hidden elements. Added to when hiding an element, and
16
18
  // subtracted from when showing it again. When it reaches zero, aria-hidden is removed.
@@ -39,6 +41,17 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
39
41
  element.inert = false;
40
42
  }
41
43
  };
44
+ let shadowRootsToWatch = new Set();
45
+ if ((0, $fF94N$shadowDOM)()) // find all shadow roots that are ancestors of the targets
46
+ // traverse upwards until the root is reached
47
+ for (let target of targets){
48
+ let node = target;
49
+ while(node && node !== root){
50
+ let root = node.getRootNode();
51
+ if ('shadowRoot' in root) shadowRootsToWatch.add(root.shadowRoot);
52
+ node = root.parentNode;
53
+ }
54
+ }
42
55
  let walk = (root)=>{
43
56
  // Keep live announcer and top layer elements (e.g. toasts) visible.
44
57
  for (let element of root.querySelectorAll('[data-live-announcer], [data-react-aria-top-layer]'))visibleNodes.add(element);
@@ -54,7 +67,7 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
54
67
  }
55
68
  return NodeFilter.FILTER_ACCEPT;
56
69
  };
57
- let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
70
+ let walker = (0, $fF94N$createShadowTreeWalker)((0, $fF94N$getOwnerDocument)(root), root, NodeFilter.SHOW_ELEMENT, {
58
71
  acceptNode: acceptNode
59
72
  });
60
73
  // TreeWalker does not include the root.
@@ -94,12 +107,49 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
94
107
  if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
95
108
  else if (node instanceof Element) walk(node);
96
109
  }
110
+ if ((0, $fF94N$shadowDOM)()) {
111
+ // if any of the observed shadow roots were removed, stop observing them
112
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
113
+ observer.disconnect();
114
+ break;
115
+ }
116
+ }
97
117
  }
98
118
  });
99
119
  observer.observe(root, {
100
120
  childList: true,
101
121
  subtree: true
102
122
  });
123
+ let shadowObservers = new Set();
124
+ if ((0, $fF94N$shadowDOM)()) for (let shadowRoot of shadowRootsToWatch){
125
+ // Disconnect single target instead of all https://github.com/whatwg/dom/issues/126
126
+ let shadowObserver = new MutationObserver((changes)=>{
127
+ for (let change of changes){
128
+ if (change.type !== 'childList') continue;
129
+ // If the parent element of the added nodes is not within one of the targets,
130
+ // and not already inside a hidden node, hide all of the new children.
131
+ if (change.target.isConnected && ![
132
+ ...visibleNodes,
133
+ ...hiddenNodes
134
+ ].some((node)=>(0, $fF94N$nodeContains)(node, change.target))) for (let node of change.addedNodes){
135
+ if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
136
+ else if (node instanceof Element) walk(node);
137
+ }
138
+ if ((0, $fF94N$shadowDOM)()) {
139
+ // if any of the observed shadow roots were removed, stop observing them
140
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
141
+ observer.disconnect();
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ });
147
+ shadowObserver.observe(shadowRoot, {
148
+ childList: true,
149
+ subtree: true
150
+ });
151
+ shadowObservers.add(shadowObserver);
152
+ }
103
153
  let observerWrapper = {
104
154
  visibleNodes: visibleNodes,
105
155
  hiddenNodes: hiddenNodes,
@@ -116,6 +166,7 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
116
166
  $5e3802645cc19319$var$observerStack.push(observerWrapper);
117
167
  return ()=>{
118
168
  observer.disconnect();
169
+ if ((0, $fF94N$shadowDOM)()) for (let shadowObserver of shadowObservers)shadowObserver.disconnect();
119
170
  for (let node of hiddenNodes){
120
171
  let count = $5e3802645cc19319$var$refCountMap.get(node);
121
172
  if (count == null) continue;
@@ -1,4 +1,5 @@
1
- import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeContains} from "@react-aria/utils";
1
+ import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeContains, createShadowTreeWalker as $fF94N$createShadowTreeWalker, getOwnerDocument as $fF94N$getOwnerDocument} from "@react-aria/utils";
2
+ import {shadowDOM as $fF94N$shadowDOM} from "@react-stately/flags";
2
3
 
3
4
  /*
4
5
  * Copyright 2020 Adobe. All rights reserved.
@@ -11,6 +12,7 @@ import {getOwnerWindow as $fF94N$getOwnerWindow, nodeContains as $fF94N$nodeCont
11
12
  * OF ANY KIND, either express or implied. See the License for the specific language
12
13
  * governing permissions and limitations under the License.
13
14
  */
15
+
14
16
  const $5e3802645cc19319$var$supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;
15
17
  // Keeps a ref count of all hidden elements. Added to when hiding an element, and
16
18
  // subtracted from when showing it again. When it reaches zero, aria-hidden is removed.
@@ -39,6 +41,17 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
39
41
  element.inert = false;
40
42
  }
41
43
  };
44
+ let shadowRootsToWatch = new Set();
45
+ if ((0, $fF94N$shadowDOM)()) // find all shadow roots that are ancestors of the targets
46
+ // traverse upwards until the root is reached
47
+ for (let target of targets){
48
+ let node = target;
49
+ while(node && node !== root){
50
+ let root = node.getRootNode();
51
+ if ('shadowRoot' in root) shadowRootsToWatch.add(root.shadowRoot);
52
+ node = root.parentNode;
53
+ }
54
+ }
42
55
  let walk = (root)=>{
43
56
  // Keep live announcer and top layer elements (e.g. toasts) visible.
44
57
  for (let element of root.querySelectorAll('[data-live-announcer], [data-react-aria-top-layer]'))visibleNodes.add(element);
@@ -54,7 +67,7 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
54
67
  }
55
68
  return NodeFilter.FILTER_ACCEPT;
56
69
  };
57
- let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
70
+ let walker = (0, $fF94N$createShadowTreeWalker)((0, $fF94N$getOwnerDocument)(root), root, NodeFilter.SHOW_ELEMENT, {
58
71
  acceptNode: acceptNode
59
72
  });
60
73
  // TreeWalker does not include the root.
@@ -94,12 +107,49 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
94
107
  if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
95
108
  else if (node instanceof Element) walk(node);
96
109
  }
110
+ if ((0, $fF94N$shadowDOM)()) {
111
+ // if any of the observed shadow roots were removed, stop observing them
112
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
113
+ observer.disconnect();
114
+ break;
115
+ }
116
+ }
97
117
  }
98
118
  });
99
119
  observer.observe(root, {
100
120
  childList: true,
101
121
  subtree: true
102
122
  });
123
+ let shadowObservers = new Set();
124
+ if ((0, $fF94N$shadowDOM)()) for (let shadowRoot of shadowRootsToWatch){
125
+ // Disconnect single target instead of all https://github.com/whatwg/dom/issues/126
126
+ let shadowObserver = new MutationObserver((changes)=>{
127
+ for (let change of changes){
128
+ if (change.type !== 'childList') continue;
129
+ // If the parent element of the added nodes is not within one of the targets,
130
+ // and not already inside a hidden node, hide all of the new children.
131
+ if (change.target.isConnected && ![
132
+ ...visibleNodes,
133
+ ...hiddenNodes
134
+ ].some((node)=>(0, $fF94N$nodeContains)(node, change.target))) for (let node of change.addedNodes){
135
+ if ((node instanceof HTMLElement || node instanceof SVGElement) && (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')) visibleNodes.add(node);
136
+ else if (node instanceof Element) walk(node);
137
+ }
138
+ if ((0, $fF94N$shadowDOM)()) {
139
+ // if any of the observed shadow roots were removed, stop observing them
140
+ for (let shadowRoot of shadowRootsToWatch)if (!shadowRoot.isConnected) {
141
+ observer.disconnect();
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ });
147
+ shadowObserver.observe(shadowRoot, {
148
+ childList: true,
149
+ subtree: true
150
+ });
151
+ shadowObservers.add(shadowObserver);
152
+ }
103
153
  let observerWrapper = {
104
154
  visibleNodes: visibleNodes,
105
155
  hiddenNodes: hiddenNodes,
@@ -116,6 +166,7 @@ function $5e3802645cc19319$export$1c3ebcada18427bf(targets, options) {
116
166
  $5e3802645cc19319$var$observerStack.push(observerWrapper);
117
167
  return ()=>{
118
168
  observer.disconnect();
169
+ if ((0, $fF94N$shadowDOM)()) for (let shadowObserver of shadowObservers)shadowObserver.disconnect();
119
170
  for (let node of hiddenNodes){
120
171
  let count = $5e3802645cc19319$var$refCountMap.get(node);
121
172
  if (count == null) continue;
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/overlays/src/ariaHideOutside.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {getOwnerWindow, nodeContains} from '@react-aria/utils';\nconst supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;\n\ninterface AriaHideOutsideOptions {\n root?: Element,\n shouldUseInert?: boolean\n}\n\n// Keeps a ref count of all hidden elements. Added to when hiding an element, and\n// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.\nlet refCountMap = new WeakMap<Element, number>();\ninterface ObserverWrapper {\n visibleNodes: Set<Element>,\n hiddenNodes: Set<Element>,\n observe: () => void,\n disconnect: () => void\n}\nlet observerStack: Array<ObserverWrapper> = [];\n\n/**\n * Hides all elements in the DOM outside the given targets from screen readers using aria-hidden,\n * and returns a function to revert these changes. In addition, changes to the DOM are watched\n * and new elements outside the targets are automatically hidden.\n * @param targets - The elements that should remain visible.\n * @param root - Nothing will be hidden above this element.\n * @returns - A function to restore all hidden elements.\n */\nexport function ariaHideOutside(targets: Element[], options?: AriaHideOutsideOptions | Element) {\n let windowObj = getOwnerWindow(targets?.[0]);\n let opts = options instanceof windowObj.Element ? {root: options} : options;\n let root = opts?.root ?? document.body;\n let shouldUseInert = opts?.shouldUseInert && supportsInert;\n let visibleNodes = new Set<Element>(targets);\n let hiddenNodes = new Set<Element>();\n\n let getHidden = (element: Element) => {\n return shouldUseInert && element instanceof windowObj.HTMLElement ? element.inert : element.getAttribute('aria-hidden') === 'true';\n };\n\n let setHidden = (element: Element, hidden: boolean) => {\n if (shouldUseInert && element instanceof windowObj.HTMLElement) {\n element.inert = hidden;\n } else if (hidden) {\n element.setAttribute('aria-hidden', 'true');\n } else {\n element.removeAttribute('aria-hidden');\n if (element instanceof windowObj.HTMLElement) {\n // We only ever call setHidden with hidden = false when the nodeCount is 1 aka\n // we are trying to make the element visible to screen readers again, so remove inert as well\n element.inert = false;\n }\n }\n };\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-react-aria-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 hiddenNodes.has(node) ||\n visibleNodes.has(node) ||\n (node.parentElement && 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 (nodeContains(node, target)) {\n return NodeFilter.FILTER_SKIP;\n }\n }\n\n return NodeFilter.FILTER_ACCEPT;\n };\n\n let walker = document.createTreeWalker(\n root,\n NodeFilter.SHOW_ELEMENT,\n {acceptNode}\n );\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 (getHidden(node) && refCount === 0) {\n return;\n }\n\n if (refCount === 0) {\n setHidden(node, true);\n }\n\n hiddenNodes.add(node);\n refCountMap.set(node, refCount + 1);\n };\n\n // If there is already a MutationObserver listening from a previous call,\n // disconnect it so the new on takes over.\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect();\n }\n\n walk(root);\n\n let observer = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n }\n });\n\n observer.observe(root, {childList: true, subtree: true});\n\n let observerWrapper: ObserverWrapper = {\n visibleNodes,\n hiddenNodes,\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 (): void => {\n observer.disconnect();\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node);\n if (count == null) {\n continue;\n }\n if (count === 1) {\n setHidden(node, false);\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 keepVisible(element: Element): (() => void) | undefined {\n let observer = observerStack[observerStack.length - 1];\n if (observer && !observer.visibleNodes.has(element)) {\n observer.visibleNodes.add(element);\n return () => {\n observer.visibleNodes.delete(element);\n };\n }\n}\n"],"names":[],"version":3,"file":"ariaHideOutside.module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/overlays/src/ariaHideOutside.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {createShadowTreeWalker, getOwnerDocument, getOwnerWindow, nodeContains} from '@react-aria/utils';\nimport {shadowDOM} from '@react-stately/flags';\n\nconst supportsInert = typeof HTMLElement !== 'undefined' && 'inert' in HTMLElement.prototype;\n\ninterface AriaHideOutsideOptions {\n root?: Element,\n shouldUseInert?: boolean\n}\n\n// Keeps a ref count of all hidden elements. Added to when hiding an element, and\n// subtracted from when showing it again. When it reaches zero, aria-hidden is removed.\nlet refCountMap = new WeakMap<Element, number>();\ninterface ObserverWrapper {\n visibleNodes: Set<Element>,\n hiddenNodes: Set<Element>,\n observe: () => void,\n disconnect: () => void\n}\nlet observerStack: Array<ObserverWrapper> = [];\n\n/**\n * Hides all elements in the DOM outside the given targets from screen readers using aria-hidden,\n * and returns a function to revert these changes. In addition, changes to the DOM are watched\n * and new elements outside the targets are automatically hidden.\n * @param targets - The elements that should remain visible.\n * @param root - Nothing will be hidden above this element.\n * @returns - A function to restore all hidden elements.\n */\nexport function ariaHideOutside(targets: Element[], options?: AriaHideOutsideOptions | Element) {\n let windowObj = getOwnerWindow(targets?.[0]);\n let opts = options instanceof windowObj.Element ? {root: options} : options;\n let root = opts?.root ?? document.body;\n let shouldUseInert = opts?.shouldUseInert && supportsInert;\n let visibleNodes = new Set<Element>(targets);\n let hiddenNodes = new Set<Element>();\n\n let getHidden = (element: Element) => {\n return shouldUseInert && element instanceof windowObj.HTMLElement ? element.inert : element.getAttribute('aria-hidden') === 'true';\n };\n\n let setHidden = (element: Element, hidden: boolean) => {\n if (shouldUseInert && element instanceof windowObj.HTMLElement) {\n element.inert = hidden;\n } else if (hidden) {\n element.setAttribute('aria-hidden', 'true');\n } else {\n element.removeAttribute('aria-hidden');\n if (element instanceof windowObj.HTMLElement) {\n // We only ever call setHidden with hidden = false when the nodeCount is 1 aka\n // we are trying to make the element visible to screen readers again, so remove inert as well\n element.inert = false;\n }\n }\n };\n\n let shadowRootsToWatch = new Set<ShadowRoot>();\n if (shadowDOM()) {\n // find all shadow roots that are ancestors of the targets\n // traverse upwards until the root is reached\n for (let target of targets) {\n let node = target;\n while (node && node !== root) {\n let root = node.getRootNode();\n if ('shadowRoot' in root) {\n shadowRootsToWatch.add(root.shadowRoot as ShadowRoot);\n }\n node = root.parentNode as Element;\n }\n }\n }\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-react-aria-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 hiddenNodes.has(node) ||\n visibleNodes.has(node) ||\n (node.parentElement && 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 (nodeContains(node, target)) {\n return NodeFilter.FILTER_SKIP;\n }\n }\n\n return NodeFilter.FILTER_ACCEPT;\n };\n\n let walker = createShadowTreeWalker(\n getOwnerDocument(root),\n root,\n NodeFilter.SHOW_ELEMENT,\n {acceptNode}\n );\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 (getHidden(node) && refCount === 0) {\n return;\n }\n\n if (refCount === 0) {\n setHidden(node, true);\n }\n\n hiddenNodes.add(node);\n refCountMap.set(node, refCount + 1);\n };\n\n // If there is already a MutationObserver listening from a previous call,\n // disconnect it so the new on takes over.\n if (observerStack.length) {\n observerStack[observerStack.length - 1].disconnect();\n }\n\n walk(root);\n\n let observer = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n\n if (shadowDOM()) {\n // if any of the observed shadow roots were removed, stop observing them\n for (let shadowRoot of shadowRootsToWatch) {\n if (!shadowRoot.isConnected) {\n observer.disconnect();\n break;\n }\n }\n }\n }\n });\n\n observer.observe(root, {childList: true, subtree: true});\n let shadowObservers = new Set<MutationObserver>();\n if (shadowDOM()) {\n for (let shadowRoot of shadowRootsToWatch) {\n // Disconnect single target instead of all https://github.com/whatwg/dom/issues/126\n let shadowObserver = new MutationObserver(changes => {\n for (let change of changes) {\n if (change.type !== 'childList') {\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 (\n change.target.isConnected &&\n ![...visibleNodes, ...hiddenNodes].some((node) =>\n nodeContains(node, change.target)\n )\n ) {\n for (let node of change.addedNodes) {\n if (\n (node instanceof HTMLElement || node instanceof SVGElement) &&\n (node.dataset.liveAnnouncer === 'true' || node.dataset.reactAriaTopLayer === 'true')\n ) {\n visibleNodes.add(node);\n } else if (node instanceof Element) {\n walk(node);\n }\n }\n }\n\n if (shadowDOM()) {\n // if any of the observed shadow roots were removed, stop observing them\n for (let shadowRoot of shadowRootsToWatch) {\n if (!shadowRoot.isConnected) {\n observer.disconnect();\n break;\n }\n }\n }\n }\n });\n shadowObserver.observe(shadowRoot, {childList: true, subtree: true});\n shadowObservers.add(shadowObserver);\n }\n }\n\n let observerWrapper: ObserverWrapper = {\n visibleNodes,\n hiddenNodes,\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 (): void => {\n observer.disconnect();\n if (shadowDOM()) {\n for (let shadowObserver of shadowObservers) {\n shadowObserver.disconnect();\n }\n }\n\n for (let node of hiddenNodes) {\n let count = refCountMap.get(node);\n if (count == null) {\n continue;\n }\n if (count === 1) {\n setHidden(node, false);\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 keepVisible(element: Element): (() => void) | undefined {\n let observer = observerStack[observerStack.length - 1];\n if (observer && !observer.visibleNodes.has(element)) {\n observer.visibleNodes.add(element);\n return () => {\n observer.visibleNodes.delete(element);\n };\n }\n}\n"],"names":[],"version":3,"file":"ariaHideOutside.module.js.map"}
@@ -333,10 +333,34 @@ function $5935ba4d7da2c103$export$b3ceb0cbf1056d98(opts) {
333
333
  // Otherwise this returns the height/width of a arbitrary boundary element, and its top/left with respect to the viewport (NOTE THIS MEANS IT DOESNT INCLUDE SCROLL)
334
334
  let boundaryDimensions = $5935ba4d7da2c103$var$getContainerDimensions(boundaryElement, visualViewport);
335
335
  let containerDimensions = $5935ba4d7da2c103$var$getContainerDimensions(container, visualViewport);
336
- // If the container is the HTML element wrapping the body element, the retrieved scrollTop/scrollLeft will be equal to the
337
- // body element's scroll. Set the container's scroll values to 0 since the overlay's edge position value in getDelta don't then need to be further offset
338
- // by the container scroll since they are essentially the same containing element and thus in the same coordinate system
339
- let containerOffsetWithBoundary = $5935ba4d7da2c103$var$getPosition(boundaryElement, container, false);
336
+ // There are several difference cases of how to calculate the containerOffsetWithBoundary:
337
+ // - boundaryElement is body or HTML and the container is an arbitrary element in the boundary (aka submenu with parent menu as container in v3)
338
+ // - boundaryElement and container are both body or HTML element (aka standard popover case)
339
+ // - boundaryElement is customized by the user. Container can also be arbitrary (either body/HTML or some other element)
340
+ // containerOffsetWithBoundary should always return a value that is the boundary's coordinate offset with respect to the container coord system (container is 0, 0)
341
+ let containerOffsetWithBoundary;
342
+ if ((boundaryElement.tagName === 'BODY' || boundaryElement.tagName === 'HTML') && !isViewportContainer) {
343
+ // Use getRect instead of getOffset because boundaryDimensions for BODY/HTML is in viewport coordinate space,
344
+ // not document coordinate space
345
+ let containerRect = $5935ba4d7da2c103$export$4b834cebd9e5cebe(container, false);
346
+ // the offset should be negative because if container is at viewport position x,y, then viewport top (aka 0)
347
+ // is at position -x,y in container-relative coordinates
348
+ containerOffsetWithBoundary = {
349
+ top: -(containerRect.top - boundaryDimensions.top),
350
+ left: -(containerRect.left - boundaryDimensions.left),
351
+ width: 0,
352
+ height: 0
353
+ };
354
+ } else if ((boundaryElement.tagName === 'BODY' || boundaryElement.tagName === 'HTML') && isViewportContainer) // both are the same viewport container, no offset needed
355
+ containerOffsetWithBoundary = {
356
+ top: 0,
357
+ left: 0,
358
+ width: 0,
359
+ height: 0
360
+ };
361
+ else // This returns the boundary's coordinate with respect to the container. This case captures cases such as when you provide a custom boundary
362
+ // like in ScrollingBoundaryContainerExample in Popover.stories.
363
+ containerOffsetWithBoundary = $5935ba4d7da2c103$var$getPosition(boundaryElement, container, false);
340
364
  let isContainerDescendentOfBoundary = (0, $6E71I$reactariautils.nodeContains)(boundaryElement, container);
341
365
  return $5935ba4d7da2c103$export$6839422d1f33cee9(placement, childOffset, overlaySize, scrollSize, margins, padding, shouldFlip, boundaryDimensions, containerDimensions, containerOffsetWithBoundary, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset, isContainerDescendentOfBoundary, visualViewport);
342
366
  }