UNPKG

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