util.ts (1749B)
1 /** 2 * @license 3 * Copyright 2024 Google Inc. 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 const HIDDEN_VISIBILITY_VALUES = ['hidden', 'collapse']; 7 8 /** 9 * @internal 10 */ 11 export const checkVisibility = ( 12 node: Node | null, 13 visible?: boolean, 14 ): Node | boolean => { 15 if (!node) { 16 return visible === false; 17 } 18 if (visible === undefined) { 19 return node; 20 } 21 const element = ( 22 node.nodeType === Node.TEXT_NODE ? node.parentElement : node 23 ) as Element; 24 25 const style = window.getComputedStyle(element); 26 const isVisible = 27 style && 28 !HIDDEN_VISIBILITY_VALUES.includes(style.visibility) && 29 !isBoundingBoxEmpty(element); 30 return visible === isVisible ? node : false; 31 }; 32 33 function isBoundingBoxEmpty(element: Element): boolean { 34 const rect = element.getBoundingClientRect(); 35 return rect.width === 0 || rect.height === 0; 36 } 37 38 const hasShadowRoot = (node: Node): node is Node & {shadowRoot: ShadowRoot} => { 39 return 'shadowRoot' in node && node.shadowRoot instanceof ShadowRoot; 40 }; 41 42 /** 43 * @internal 44 */ 45 export function* pierce(root: Node): IterableIterator<Node | ShadowRoot> { 46 if (hasShadowRoot(root)) { 47 yield root.shadowRoot; 48 } else { 49 yield root; 50 } 51 } 52 53 /** 54 * @internal 55 */ 56 export function* pierceAll(root: Node): IterableIterator<Node | ShadowRoot> { 57 root = pierce(root).next().value; 58 yield root; 59 const walkers = [document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)]; 60 for (const walker of walkers) { 61 let node: Element | null; 62 while ((node = walker.nextNode() as Element | null)) { 63 if (!node.shadowRoot) { 64 continue; 65 } 66 yield node.shadowRoot; 67 walkers.push( 68 document.createTreeWalker(node.shadowRoot, NodeFilter.SHOW_ELEMENT), 69 ); 70 } 71 } 72 }