@grafana/ui
Version:
Grafana Components Library
68 lines (65 loc) • 2.09 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { css } from '@emotion/css';
import * as React from 'react';
import { useRef, useLayoutEffect } from 'react';
import ReactDOM from 'react-dom';
import { selectors } from '@grafana/e2e-selectors';
import { useTheme2, useStyles2 } from '../../themes/ThemeContext.mjs';
;
function Portal(props) {
var _a;
const { children, className, root, forwardedRef } = props;
const theme = useTheme2();
const node = useRef(null);
const portalRoot = root != null ? root : getPortalContainer();
if (!node.current) {
node.current = document.createElement("div");
if (className) {
node.current.className = className;
}
node.current.style.position = "relative";
node.current.style.zIndex = `${(_a = props.zIndex) != null ? _a : theme.zIndex.portal}`;
}
useLayoutEffect(() => {
if (node.current) {
portalRoot.appendChild(node.current);
}
return () => {
if (node.current) {
portalRoot.removeChild(node.current);
}
};
}, [portalRoot]);
return ReactDOM.createPortal(/* @__PURE__ */ jsx("div", { ref: forwardedRef, children }), node.current);
}
function getPortalContainer() {
var _a;
return (_a = window.document.getElementById("grafana-portal-container")) != null ? _a : document.body;
}
function PortalContainer() {
const styles = useStyles2(getStyles);
return /* @__PURE__ */ jsx(
"div",
{
id: "grafana-portal-container",
"data-testid": selectors.components.Portal.container,
className: styles.grafanaPortalContainer
}
);
}
const getStyles = (theme) => {
return {
grafanaPortalContainer: css({
position: "fixed",
top: 0,
width: "100%",
zIndex: theme.zIndex.portal
})
};
};
const RefForwardingPortal = React.forwardRef((props, ref) => {
return /* @__PURE__ */ jsx(Portal, { ...props, forwardedRef: ref });
});
RefForwardingPortal.displayName = "RefForwardingPortal";
export { Portal, PortalContainer, RefForwardingPortal, getPortalContainer };
//# sourceMappingURL=Portal.mjs.map