UNPKG

@modern-kit/react

Version:
55 lines (52 loc) 1.85 kB
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