@clayui/shared
Version:
ClayShared component
55 lines (54 loc) • 1.88 kB
JavaScript
/**
* SPDX-FileCopyrightText: © 2019 Liferay, Inc. <https://liferay.com>
* SPDX-License-Identifier: BSD-3-Clause
*/
import { useProvider } from '@clayui/provider';
import classNames from 'classnames';
import React from 'react';
import { createPortal } from 'react-dom';
const ClayPortalContext = /*#__PURE__*/React.createContext(null);
ClayPortalContext.displayName = 'ClayPortalContext';
const createDivElement = (className, id) => {
const element = document.createElement('div');
if (className) {
element.setAttribute('class', className);
}
if (id) {
element.setAttribute('id', id);
}
return element;
};
export const ClayPortal = _ref => {
let {
children,
className,
containerRef,
id,
subPortalRef
} = _ref;
const {
theme
} = useProvider();
const parentPortalRef = React.useContext(ClayPortalContext);
const portalRef = React.useRef(typeof document !== 'undefined' ? createDivElement(classNames(theme, className), id) : null);
React.useEffect(() => {
const closestParent = parentPortalRef && parentPortalRef.current ? parentPortalRef.current : document.body;
const elToMountTo = containerRef && containerRef.current ? containerRef.current : closestParent;
if (elToMountTo && portalRef.current) {
elToMountTo.appendChild(portalRef.current);
}
return () => {
if (portalRef.current) {
if (typeof portalRef.current.remove === 'function') {
portalRef.current.remove();
} else if (elToMountTo) {
elToMountTo.removeChild(portalRef.current);
}
}
};
}, [containerRef, parentPortalRef]);
const content = /*#__PURE__*/React.createElement(ClayPortalContext.Provider, {
value: subPortalRef ? subPortalRef : portalRef
}, children);
return portalRef.current ? /*#__PURE__*/createPortal(content, portalRef.current) : content;
};