import { isHTMLElement } from './is.js'; | |
/** | |
* Get an element's ancestor which has a `data-portal` attribute. | |
* This is used to handle nested portals/overlays/dialogs/popovers. | |
*/ | |
function getPortalParent(node) { | |
let parent = node.parentElement; | |
while (isHTMLElement(parent) && !parent.hasAttribute('data-portal')) { | |
parent = parent.parentElement; | |
} | |
return parent || 'body'; | |
} | |
/** | |
* Gets the destination for a portal given the node and a user-specified portal prop. | |
* If a portal prop is not `undefined`, it is used as the destination. | |
*/ | |
export function getPortalDestination(node, portalProp) { | |
// user-specified portal prop, use it | |
if (portalProp !== undefined) | |
return portalProp; | |
// find the closest portal parent, or the body if none is found | |
const portalParent = getPortalParent(node); | |
// if the portalParent is the body, we portal to the body | |
// making it a "top-level" portal | |
if (portalParent === 'body') | |
return document.body; | |
// if the portalParent is not the body, we have a portal parent | |
// and shouldn't portal to anything so it remains within that parent | |
// so we return `null` | |
return null; | |
} | |