@primer/react
Version:
An implementation of GitHub's Primer Design System using React
44 lines (43 loc) • 1.7 kB
JavaScript
import useIsomorphicLayoutEffect from "../utils/useIsomorphicLayoutEffect.js";
import { PortalContext } from "./PortalContext.js";
import { DEFAULT_PORTAL_CONTAINER_NAME, ensureDefaultPortal, getPortalRoot } from "./portalRoot.js";
import React, { useContext } from "react";
import { createPortal } from "react-dom";
//#region src/Portal/Portal.tsx
/**
* Creates a React Portal, placing all children in a separate physical DOM root node.
* @see https://reactjs.org/docs/portals.html
*/
const Portal = ({ children, onMount, containerName: _containerName }) => {
const { portalContainerName } = useContext(PortalContext);
const elementRef = React.useRef(null);
if (!elementRef.current) {
const div = document.createElement("div");
div.setAttribute("data-component", "Portal");
div.style.position = "relative";
div.style.zIndex = "1";
elementRef.current = div;
}
const element = elementRef.current;
useIsomorphicLayoutEffect(() => {
let containerName = _containerName !== null && _containerName !== void 0 ? _containerName : portalContainerName;
if (containerName === void 0) {
containerName = DEFAULT_PORTAL_CONTAINER_NAME;
ensureDefaultPortal();
}
const parentElement = getPortalRoot(containerName);
if (!parentElement) throw new Error(`Portal container '${containerName}' is not yet registered. Container must be registered with registerPortalRoot before use.`);
parentElement.appendChild(element);
onMount === null || onMount === void 0 || onMount();
return () => {
parentElement.removeChild(element);
};
}, [
element,
_containerName,
portalContainerName
]);
return /*#__PURE__*/ createPortal(children, element);
};
//#endregion
export { Portal };