Socket
Socket
Sign inDemoInstall

@chakra-ui/portal

Package Overview
Dependencies
Maintainers
4
Versions
320
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@chakra-ui/portal - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

14

CHANGELOG.md
# Change Log
## 1.0.3
### Patch Changes
- [`a98817de`](https://github.com/chakra-ui/chakra-ui/commit/a98817de0849bf9eec89fae3faf4fbe085f21011)
Thanks [@segunadebayo](https://github.com/segunadebayo)! - - Fix issue where
`Portal` and `PortalManager` renders elements outside of view.
- Fixed issue where elements within portal used in an `iframe` got rendered
outside of the `iframe`. `Portal` now smartly detects it's document owner
and attaches its node to the correct `document.body`
- Removed extra DOM node `PortalManager` creates. Less is more!
## 1.0.2

@@ -4,0 +18,0 @@

52

dist/cjs/portal-manager.js
"use strict";
exports.__esModule = true;
exports.PortalManager = exports.usePortalManager = void 0;
exports.PortalManager = PortalManager;
exports.usePortalManager = void 0;
var React = _interopRequireWildcard(require("react"));
var _utils = require("@chakra-ui/utils");
var _hooks = require("@chakra-ui/hooks");
var React = _interopRequireWildcard(require("react"));

@@ -25,45 +24,12 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }

/**
* PortalManager
*
* Used to manage multiple portals within an application.
* It must be render only once, at the root of your application.
*
* Inspired by BaseWeb's LayerManager component
*/
var PortalManager = function PortalManager(props) {
function PortalManager(props) {
var children = props.children,
zIndex = props.zIndex;
/**
* The element that wraps the stacked layers
*/
var ref = React.useRef(null);
var forceUpdate = (0, _hooks.useForceUpdate)();
/**
* force an update on mount so the Provider works correctly
*/
(0, _hooks.useSafeLayoutEffect)(function () {
forceUpdate();
}, []);
/**
* let's detect if use has mutiple instances of this component
*/
var parentManager = usePortalManager();
var context = {
node: (parentManager == null ? void 0 : parentManager.node) || ref.current,
zIndex: zIndex
};
return /*#__PURE__*/React.createElement(PortalManagerContextProvider, {
value: context
}, children, /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-manager",
ref: ref
}));
};
value: {
zIndex: zIndex
}
}, children);
}
exports.PortalManager = PortalManager;
if (_utils.__DEV__) {

@@ -70,0 +36,0 @@ PortalManager.displayName = "PortalManager";

"use strict";
exports.__esModule = true;
exports.Portal = void 0;
exports.Portal = Portal;

@@ -12,3 +12,3 @@ var _hooks = require("@chakra-ui/hooks");

var ReactDOM = _interopRequireWildcard(require("react-dom"));
var _reactDom = require("react-dom");

@@ -28,2 +28,18 @@ var _portalManager = require("./portal-manager");

var Container = function Container(props) {
var children = props.children,
zIndex = props.zIndex;
return /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-zIndex",
style: {
position: "absolute",
zIndex: zIndex,
top: 0,
left: 0,
right: 0,
bottom: 0
}
}, children);
};
/**

@@ -34,94 +50,45 @@ * Portal

* that exists outside the DOM hierarchy of the parent component.
* There is no document link yet
*
* @see Docs https://chakra-ui.com/docs/overlay/portal
*/
var Portal = function Portal(props) {
var onMount = props.onMount,
onUnmount = props.onUnmount,
children = props.children,
getContainer = props.getContainer;
/**
* Generate the portal's dom node. We'll wrap the children
* in this dom node before mounting it.
*/
var _React$useState = React.useState(function () {
if (_utils.isBrowser) {
var div = document.createElement("div");
div.className = "chakra-portal";
return div;
} // for ssr
return null;
}),
portal = _React$useState[0];
/**
* This portal might be nested in another portal.
* Let's read from the portal context to check this.
*/
function Portal(props) {
var tempNode = React.useRef(null);
var portal = React.useRef(null);
var forceUpdate = (0, _hooks.useForceUpdate)();
var getContainer = (0, _hooks.useCallbackRef)(props.getContainer);
var onMount = (0, _hooks.useCallbackRef)(props.onMount);
var onUnmount = (0, _hooks.useCallbackRef)(props.onUnmount);
var parentPortal = usePortalContext();
/**
* If there's a PortalManager rendered, let's read from it.
* We use the portal manager to manage multiple portals
*/
var manager = (0, _portalManager.usePortalManager)();
var append = React.useCallback(function (container) {
// if user specified a mount node, do nothing.
if (!portal || !container) return; // else, simply append component to the portal node
container.appendChild(portal);
}, [portal]);
(0, _hooks.useSafeLayoutEffect)(function () {
var _ref, _ref2;
var _ref, _getContainer;
// get the custom container from the container prop
var customContainer = getContainer == null ? void 0 : getContainer();
/**
* We need to know where to mount this portal, we have 4 options:
* - If a mountRef is specified, we'll use that as the container
* - If portal is nested, use the parent portal node as container.
* - If it is not nested, use the manager's node as container
* - else use document.body as containers
*/
var container = (_ref = (_ref2 = customContainer != null ? customContainer : parentPortal) != null ? _ref2 : manager == null ? void 0 : manager.node) != null ? _ref : document.body;
/**
* Append portal node to the computed container
*/
append(container);
onMount == null ? void 0 : onMount();
if (!tempNode.current) return;
var doc = tempNode.current.ownerDocument;
portal.current = doc.createElement("div");
portal.current.className = Portal.className;
var host = (_ref = (_getContainer = getContainer()) != null ? _getContainer : parentPortal) != null ? _ref : doc.body;
host.appendChild(portal.current);
forceUpdate();
onMount();
var portalNode = portal.current;
return function () {
onUnmount == null ? void 0 : onUnmount();
if (!portal) return;
onUnmount();
if (container != null && container.contains(portal)) {
container == null ? void 0 : container.removeChild(portal);
if (host.contains(portalNode)) {
host.removeChild(portalNode);
}
};
}, [getContainer, portal, parentPortal, onMount, onUnmount, manager == null ? void 0 : manager.node, append]);
var portalChildren = manager != null && manager.zIndex ? /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-zIndex",
style: {
position: "absolute",
zIndex: manager.zIndex,
width: "100%"
}
}, children) : children;
}, []);
var childrenToRender = manager != null && manager.zIndex ? /*#__PURE__*/React.createElement(Container, null, props.children) : props.children;
return portal.current ? /*#__PURE__*/(0, _reactDom.createPortal)( /*#__PURE__*/React.createElement(PortalContextProvider, {
value: portal.current
}, childrenToRender), portal.current) : /*#__PURE__*/React.createElement("span", {
ref: tempNode
});
}
if (!portal) {
return /*#__PURE__*/React.createElement(React.Fragment, null, portalChildren);
}
Portal.className = "chakra-portal";
Portal.selector = "." + Portal.className;
return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(PortalContextProvider, {
value: portal
}, portalChildren), portal);
};
exports.Portal = Portal;
if (_utils.__DEV__) {

@@ -128,0 +95,0 @@ Portal.displayName = "Portal";

@@ -0,4 +1,3 @@

import { createContext, __DEV__ } from "@chakra-ui/utils";
import * as React from "react";
import { createContext, __DEV__ } from "@chakra-ui/utils";
import { useSafeLayoutEffect, useForceUpdate } from "@chakra-ui/hooks";
var [PortalManagerContextProvider, usePortalManager] = createContext({

@@ -9,12 +8,3 @@ strict: false,

export { usePortalManager };
/**
* PortalManager
*
* Used to manage multiple portals within an application.
* It must be render only once, at the root of your application.
*
* Inspired by BaseWeb's LayerManager component
*/
export var PortalManager = props => {
export function PortalManager(props) {
var {

@@ -24,31 +14,8 @@ children,

} = props;
/**
* The element that wraps the stacked layers
*/
var ref = React.useRef(null);
var forceUpdate = useForceUpdate();
/**
* force an update on mount so the Provider works correctly
*/
useSafeLayoutEffect(() => {
forceUpdate();
}, []);
/**
* let's detect if use has mutiple instances of this component
*/
var parentManager = usePortalManager();
var context = {
node: (parentManager == null ? void 0 : parentManager.node) || ref.current,
zIndex
};
return /*#__PURE__*/React.createElement(PortalManagerContextProvider, {
value: context
}, children, /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-manager",
ref: ref
}));
};
value: {
zIndex
}
}, children);
}

@@ -55,0 +22,0 @@ if (__DEV__) {

@@ -1,5 +0,5 @@

import { useSafeLayoutEffect } from "@chakra-ui/hooks";
import { createContext, isBrowser, __DEV__ } from "@chakra-ui/utils";
import { useCallbackRef, useForceUpdate, useSafeLayoutEffect } from "@chakra-ui/hooks";
import { createContext, __DEV__ } from "@chakra-ui/utils";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { createPortal } from "react-dom";
import { usePortalManager } from "./portal-manager";

@@ -11,2 +11,20 @@ var [PortalContextProvider, usePortalContext] = createContext({

var Container = props => {
var {
children,
zIndex
} = props;
return /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-zIndex",
style: {
position: "absolute",
zIndex,
top: 0,
left: 0,
right: 0,
bottom: 0
}
}, children);
};
/**

@@ -17,92 +35,44 @@ * Portal

* that exists outside the DOM hierarchy of the parent component.
* There is no document link yet
*
* @see Docs https://chakra-ui.com/docs/overlay/portal
*/
export var Portal = props => {
var {
onMount,
onUnmount,
children,
getContainer
} = props;
/**
* Generate the portal's dom node. We'll wrap the children
* in this dom node before mounting it.
*/
var [portal] = React.useState(() => {
if (isBrowser) {
var div = document.createElement("div");
div.className = "chakra-portal";
return div;
} // for ssr
return null;
});
/**
* This portal might be nested in another portal.
* Let's read from the portal context to check this.
*/
export function Portal(props) {
var tempNode = React.useRef(null);
var portal = React.useRef(null);
var forceUpdate = useForceUpdate();
var getContainer = useCallbackRef(props.getContainer);
var onMount = useCallbackRef(props.onMount);
var onUnmount = useCallbackRef(props.onUnmount);
var parentPortal = usePortalContext();
/**
* If there's a PortalManager rendered, let's read from it.
* We use the portal manager to manage multiple portals
*/
var manager = usePortalManager();
var append = React.useCallback(container => {
// if user specified a mount node, do nothing.
if (!portal || !container) return; // else, simply append component to the portal node
container.appendChild(portal);
}, [portal]);
useSafeLayoutEffect(() => {
var _ref, _ref2;
var _ref, _getContainer;
// get the custom container from the container prop
var customContainer = getContainer == null ? void 0 : getContainer();
/**
* We need to know where to mount this portal, we have 4 options:
* - If a mountRef is specified, we'll use that as the container
* - If portal is nested, use the parent portal node as container.
* - If it is not nested, use the manager's node as container
* - else use document.body as containers
*/
var container = (_ref = (_ref2 = customContainer != null ? customContainer : parentPortal) != null ? _ref2 : manager == null ? void 0 : manager.node) != null ? _ref : document.body;
/**
* Append portal node to the computed container
*/
append(container);
onMount == null ? void 0 : onMount();
if (!tempNode.current) return;
var doc = tempNode.current.ownerDocument;
portal.current = doc.createElement("div");
portal.current.className = Portal.className;
var host = (_ref = (_getContainer = getContainer()) != null ? _getContainer : parentPortal) != null ? _ref : doc.body;
host.appendChild(portal.current);
forceUpdate();
onMount();
var portalNode = portal.current;
return () => {
onUnmount == null ? void 0 : onUnmount();
if (!portal) return;
onUnmount();
if (container != null && container.contains(portal)) {
container == null ? void 0 : container.removeChild(portal);
if (host.contains(portalNode)) {
host.removeChild(portalNode);
}
};
}, [getContainer, portal, parentPortal, onMount, onUnmount, manager == null ? void 0 : manager.node, append]);
var portalChildren = manager != null && manager.zIndex ? /*#__PURE__*/React.createElement("div", {
className: "chakra-portal-zIndex",
style: {
position: "absolute",
zIndex: manager.zIndex,
width: "100%"
}
}, children) : children;
}, []);
var childrenToRender = manager != null && manager.zIndex ? /*#__PURE__*/React.createElement(Container, null, props.children) : props.children;
return portal.current ? /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(PortalContextProvider, {
value: portal.current
}, childrenToRender), portal.current) : /*#__PURE__*/React.createElement("span", {
ref: tempNode
});
}
Portal.className = "chakra-portal";
Portal.selector = "." + Portal.className;
if (!portal) {
return /*#__PURE__*/React.createElement(React.Fragment, null, portalChildren);
}
return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(PortalContextProvider, {
value: portal
}, portalChildren), portal);
};
if (__DEV__) {

@@ -109,0 +79,0 @@ Portal.displayName = "Portal";

import * as React from "react";
interface PortalManagerContext {
node: HTMLElement;
zIndex?: number;
}
declare const usePortalManager: () => PortalManagerContext;
declare const usePortalManager: () => PortalManagerContext | null;
export { usePortalManager };
export interface PortalManagerProps {
/**
* Child elements of the Portal manager
* Ideally, it should be at the top-level
* of your application
*/
children?: React.ReactNode;
/**
* [Z-Index war] If your has multiple elements
* with z-index clashing, you might need to
* apply a z-index to the Portal manager
* with z-index clashing, you might need to apply a z-index to the Portal manager
*/
zIndex?: number;
}
/**
* PortalManager
*
* Used to manage multiple portals within an application.
* It must be render only once, at the root of your application.
*
* Inspired by BaseWeb's LayerManager component
*/
export declare const PortalManager: React.FC<PortalManagerProps>;
export declare function PortalManager(props: PortalManagerProps): JSX.Element;
export declare namespace PortalManager {
var displayName: string;
}

@@ -19,3 +19,3 @@ import * as React from "react";

*/
children?: React.ReactNode;
children: React.ReactNode;
}

@@ -27,5 +27,10 @@ /**

* that exists outside the DOM hierarchy of the parent component.
* There is no document link yet
*
* @see Docs https://chakra-ui.com/docs/overlay/portal
*/
export declare const Portal: React.FC<PortalProps>;
export declare function Portal(props: PortalProps): JSX.Element;
export declare namespace Portal {
var className: string;
var selector: string;
var displayName: string;
}
{
"name": "@chakra-ui/portal",
"version": "1.0.2",
"version": "1.0.3",
"description": "React component used to render children outside the DOM hierarchy of the parent component",

@@ -59,9 +59,11 @@ "keywords": [

"peerDependencies": {
"react": "16.x || 17.x",
"react-dom": "16.x || 17.x"
"react": ">=16.8.6",
"react-dom": ">=16.8.6"
},
"devDependencies": {
"@types/react-frame-component": "^4.1.1",
"react": "^17.0.1",
"react-dom": "^17.0.1"
"react-dom": "^17.0.1",
"react-frame-component": "^4.1.3"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc