UNPKG

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