UNPKG

3.1 kBJavaScriptView Raw
1import * as React from 'react';
2import * as ReactDOM from 'react-dom';
3import PropTypes from 'prop-types';
4import { exactProp, HTMLElementType, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useForkRef as useForkRef, unstable_setRef as setRef } from '@mui/utils';
5import { jsx as _jsx } from "react/jsx-runtime";
6function getContainer(container) {
7 return typeof container === 'function' ? container() : container;
8}
9
10/**
11 * Portals provide a first-class way to render children into a DOM node
12 * that exists outside the DOM hierarchy of the parent component.
13 *
14 * Demos:
15 *
16 * - [Portal](https://mui.com/base/react-portal/)
17 *
18 * API:
19 *
20 * - [Portal API](https://mui.com/base/react-portal/components-api/#portal)
21 */
22const Portal = /*#__PURE__*/React.forwardRef(function Portal(props, forwardedRef) {
23 const {
24 children,
25 container,
26 disablePortal = false
27 } = props;
28 const [mountNode, setMountNode] = React.useState(null);
29 // @ts-expect-error TODO upstream fix
30 const handleRef = useForkRef( /*#__PURE__*/React.isValidElement(children) ? children.ref : null, forwardedRef);
31 useEnhancedEffect(() => {
32 if (!disablePortal) {
33 setMountNode(getContainer(container) || document.body);
34 }
35 }, [container, disablePortal]);
36 useEnhancedEffect(() => {
37 if (mountNode && !disablePortal) {
38 setRef(forwardedRef, mountNode);
39 return () => {
40 setRef(forwardedRef, null);
41 };
42 }
43 return undefined;
44 }, [forwardedRef, mountNode, disablePortal]);
45 if (disablePortal) {
46 if ( /*#__PURE__*/React.isValidElement(children)) {
47 const newProps = {
48 ref: handleRef
49 };
50 return /*#__PURE__*/React.cloneElement(children, newProps);
51 }
52 return /*#__PURE__*/_jsx(React.Fragment, {
53 children: children
54 });
55 }
56 return /*#__PURE__*/_jsx(React.Fragment, {
57 children: mountNode ? /*#__PURE__*/ReactDOM.createPortal(children, mountNode) : mountNode
58 });
59});
60process.env.NODE_ENV !== "production" ? Portal.propTypes /* remove-proptypes */ = {
61 // ----------------------------- Warning --------------------------------
62 // | These PropTypes are generated from the TypeScript type definitions |
63 // | To update them edit TypeScript types and run "yarn proptypes" |
64 // ----------------------------------------------------------------------
65 /**
66 * The children to render into the `container`.
67 */
68 children: PropTypes.node,
69 /**
70 * An HTML element or function that returns one.
71 * The `container` will have the portal children appended to it.
72 *
73 * By default, it uses the body of the top-level document object,
74 * so it's simply `document.body` most of the time.
75 */
76 container: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([HTMLElementType, PropTypes.func]),
77 /**
78 * The `children` will be under the DOM hierarchy of the parent component.
79 * @default false
80 */
81 disablePortal: PropTypes.bool
82} : void 0;
83if (process.env.NODE_ENV !== 'production') {
84 // eslint-disable-next-line
85 Portal['propTypes' + ''] = exactProp(Portal.propTypes);
86}
87export default Portal;
\No newline at end of file