@modern-kit/react
Version:
55 lines (52 loc) • 1.85 kB
JavaScript
import { jsx, Fragment } from 'react/jsx-runtime';
import { createContext, useContext, useCallback, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { useIsMounted } from '../../hooks/useIsMounted/index.mjs';
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect/index.mjs';
import '@modern-kit/utils';
const PortalContext = createContext({
parentPortalElement: null
});
const PORTAL_DEFAULT_CLASS = "portal";
function RenderPortal({
children,
className = PORTAL_DEFAULT_CLASS,
containerRef
}) {
const { parentPortalElement } = useContext(PortalContext);
const createPortalElement = useCallback(
(mountElement2) => {
const portalElement2 = mountElement2.ownerDocument.createElement("div");
portalElement2.classList.add(className);
return portalElement2;
},
[className]
);
const mountElement = useMemo(() => {
return parentPortalElement || containerRef?.current || document.body;
}, [parentPortalElement, containerRef]);
const portalElement = useMemo(() => {
return createPortalElement(mountElement);
}, [createPortalElement, mountElement]);
useIsomorphicLayoutEffect(() => {
mountElement.appendChild(portalElement);
return () => {
if (mountElement.contains(portalElement)) {
mountElement.removeChild(portalElement);
}
};
}, [portalElement, mountElement]);
return createPortal(
/* @__PURE__ */ jsx(PortalContext.Provider, { value: { parentPortalElement: portalElement }, children }),
portalElement
);
}
const Portal = ({ children, ...restProps }) => {
const isMounted = useIsMounted();
if (!isMounted) {
return /* @__PURE__ */ jsx(Fragment, {});
}
return /* @__PURE__ */ jsx(RenderPortal, { ...restProps, children });
};
export { Portal };
//# sourceMappingURL=index.mjs.map