All files / src/components Portal.ts

100% Statements 17/17
100% Branches 6/6
100% Functions 1/1
100% Lines 17/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 341x               1x 3x 3x         3x 1x 2x   3x       3x 3x 4x 4x 4x 3x 3x   3x 3x  
import { onCleanup } from '../lifecycle/lifecycle';
 
/**
 * Renders children into a different part of the DOM.
 * Returns a placeholder comment node to mark its position in the original tree.
 *
 * @param props An object containing the mount target and the children to render.
 */
export function Portal(props: { mount: Element; children: Node }): Comment {
  const { mount, children } = props;
  const placeholder = document.createComment('portal');
 
  // Track actual nodes to handle DocumentFragments correctly.
  // Fragments are emptied upon insertion, so we must track their children
  // to ensure proper cleanup and prevent NotFoundError crashes.
  const nodes = children instanceof DocumentFragment
    ? Array.from(children.childNodes)
    : [children];
 
  nodes.forEach(node => mount.appendChild(node));
 
  // When the Portal's owner scope is cleaned up, remove the children
  // from the mount target.
  onCleanup(() => {
    nodes.forEach(node => {
      if (node.parentNode === mount) {
        mount.removeChild(node);
      }
    });
  });
 
  return placeholder;
}