Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@react-md/portal

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-md/portal - npm Package Compare versions

Comparing version 2.0.0-alpha.0 to 2.0.0-alpha.1

es/getContainer.js

5

es/ConditionalPortal.js

@@ -8,7 +8,7 @@ import React from "react";

var ConditionalPortal = function (_a) {
var portal = _a.portal, portalInto = _a.portalInto, portalIntoId = _a.portalIntoId, visible = _a.visible, children = _a.children;
var portal = _a.portal, portalInto = _a.portalInto, portalIntoId = _a.portalIntoId, children = _a.children;
if (!portal && !portalInto && !portalIntoId) {
return children;
}
return (React.createElement(Portal, { into: portalInto, intoId: portalIntoId, visible: visible }, children));
return (React.createElement(Portal, { into: portalInto, intoId: portalIntoId }, children));
};

@@ -30,3 +30,2 @@ if (process.env.NODE_ENV !== "production") {

portalIntoId: PropTypes.string,
visible: PropTypes.bool.isRequired,
children: PropTypes.node,

@@ -33,0 +32,0 @@ };

46

es/hooks.js

@@ -1,2 +0,2 @@

import { useState, useEffect } from "react";
import { useState, useEffect, useRef, useCallback } from "react";
function getContainer(_a) {

@@ -45,28 +45,48 @@ var into = _a.into, intoId = _a.intoId;

}
/**
* This is an internal hook that will set the portal's container and validate that the portal
* target is valid in dev mode.
* @private
*/
export function usePortalState(props) {
var visible = props.visible;
var visible = props.visible, into = props.into, intoId = props.intoId;
var _a = useState(null), container = _a[0], setContainer = _a[1];
useEffect(function () {
setContainer(visible ? getContainer(props) : null);
}, [visible]);
}, [visible, into, intoId]);
return container;
}
/**
* This hook allows you to stagger the visibility of a portal so that it will stay visible
* until an exit animation has finished. This relies on the react-transition-group onExited
* hook to work.
*
* @param visible - Boolean if the main component should be visible. This will trigger the staggered
* animation in or out
* @param onExited - An optional onExited callback
* @return an object containing a boolean if the portal is visible as well as a merged `onExited` callback
* to apply to the react-transition-group child that is animating.
*/
export function useStaggeredVisibility(_a) {
var visible = _a.visible, onExited = _a.onExited;
var _b = useState(function () { return visible; }), portalVisible = _b[0], setPortalVisible = _b[1];
var _b = useState(visible), portalVisible = _b[0], setPortalVisible = _b[1];
if (visible && !portalVisible) {
setPortalVisible(true);
}
var ref = useRef(onExited);
useEffect(function () {
if (visible) {
setPortalVisible(true);
ref.current = onExited;
});
var handleExited = useCallback(function (node) {
var onExited = ref.current;
if (onExited) {
onExited(node);
}
}, [visible]);
setPortalVisible(false);
}, []);
return {
portalVisible: portalVisible,
onExited: function (node) {
if (onExited) {
onExited(node);
}
setPortalVisible(false);
},
onExited: handleExited,
};
}
//# sourceMappingURL=hooks.js.map

@@ -5,3 +5,2 @@ export { default as Portal } from "./Portal";

export * from "./ConditionalPortal";
export { useStaggeredVisibility } from "./hooks";
//# sourceMappingURL=index.js.map

@@ -0,7 +1,22 @@

import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { usePortalState } from "./hooks";
var Portal = function (props) {
var visible = props.visible, children = props.children;
var container = usePortalState(props);
if (!visible || !container) {
import getContainer from "./getContainer";
/**
* This component is a simple wrapper for the `createPortal` API from ReactDOM that will just ensure
* that `null` is always returned for server side rendering as well as a "nice" way to choose specific
* portal targets or just falling back to the `document.body`.
*/
var Portal = function (_a) {
var into = _a.into, intoId = _a.intoId, children = _a.children;
var _b = useState(null), container = _b[0], setContainer = _b[1];
// setting the container via useEffect instead of immediately in the render
// just so that it doesn't throw an error immediately if the dom hasn't fully
// painted after a SSR
useEffect(function () {
var nextContainer = getContainer(into, intoId);
if (container !== nextContainer) {
setContainer(nextContainer);
}
});
if (!container) {
return null;

@@ -25,3 +40,2 @@ }

intoId: PropTypes.string,
visible: PropTypes.bool.isRequired,
children: PropTypes.node,

@@ -28,0 +42,0 @@ };

@@ -13,7 +13,7 @@ "use strict";

var ConditionalPortal = function (_a) {
var portal = _a.portal, portalInto = _a.portalInto, portalIntoId = _a.portalIntoId, visible = _a.visible, children = _a.children;
var portal = _a.portal, portalInto = _a.portalInto, portalIntoId = _a.portalIntoId, children = _a.children;
if (!portal && !portalInto && !portalIntoId) {
return children;
}
return (react_1.default.createElement(Portal_1.default, { into: portalInto, intoId: portalIntoId, visible: visible }, children));
return (react_1.default.createElement(Portal_1.default, { into: portalInto, intoId: portalIntoId }, children));
};

@@ -35,3 +35,2 @@ if (process.env.NODE_ENV !== "production") {

portalIntoId: PropTypes.string,
visible: PropTypes.bool.isRequired,
children: PropTypes.node,

@@ -38,0 +37,0 @@ };

@@ -47,27 +47,47 @@ "use strict";

}
/**
* This is an internal hook that will set the portal's container and validate that the portal
* target is valid in dev mode.
* @private
*/
function usePortalState(props) {
var visible = props.visible;
var visible = props.visible, into = props.into, intoId = props.intoId;
var _a = react_1.useState(null), container = _a[0], setContainer = _a[1];
react_1.useEffect(function () {
setContainer(visible ? getContainer(props) : null);
}, [visible]);
}, [visible, into, intoId]);
return container;
}
exports.usePortalState = usePortalState;
/**
* This hook allows you to stagger the visibility of a portal so that it will stay visible
* until an exit animation has finished. This relies on the react-transition-group onExited
* hook to work.
*
* @param visible - Boolean if the main component should be visible. This will trigger the staggered
* animation in or out
* @param onExited - An optional onExited callback
* @return an object containing a boolean if the portal is visible as well as a merged `onExited` callback
* to apply to the react-transition-group child that is animating.
*/
function useStaggeredVisibility(_a) {
var visible = _a.visible, onExited = _a.onExited;
var _b = react_1.useState(function () { return visible; }), portalVisible = _b[0], setPortalVisible = _b[1];
var _b = react_1.useState(visible), portalVisible = _b[0], setPortalVisible = _b[1];
if (visible && !portalVisible) {
setPortalVisible(true);
}
var ref = react_1.useRef(onExited);
react_1.useEffect(function () {
if (visible) {
setPortalVisible(true);
ref.current = onExited;
});
var handleExited = react_1.useCallback(function (node) {
var onExited = ref.current;
if (onExited) {
onExited(node);
}
}, [visible]);
setPortalVisible(false);
}, []);
return {
portalVisible: portalVisible,
onExited: function (node) {
if (onExited) {
onExited(node);
}
setPortalVisible(false);
},
onExited: handleExited,
};

@@ -74,0 +94,0 @@ }

@@ -12,4 +12,2 @@ "use strict";

__export(require("./ConditionalPortal"));
var hooks_1 = require("./hooks");
exports.useStaggeredVisibility = hooks_1.useStaggeredVisibility;
//# sourceMappingURL=index.js.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var react_dom_1 = require("react-dom");
var hooks_1 = require("./hooks");
var Portal = function (props) {
var visible = props.visible, children = props.children;
var container = hooks_1.usePortalState(props);
if (!visible || !container) {
var getContainer_1 = __importDefault(require("./getContainer"));
/**
* This component is a simple wrapper for the `createPortal` API from ReactDOM that will just ensure
* that `null` is always returned for server side rendering as well as a "nice" way to choose specific
* portal targets or just falling back to the `document.body`.
*/
var Portal = function (_a) {
var into = _a.into, intoId = _a.intoId, children = _a.children;
var _b = react_1.useState(null), container = _b[0], setContainer = _b[1];
// setting the container via useEffect instead of immediately in the render
// just so that it doesn't throw an error immediately if the dom hasn't fully
// painted after a SSR
react_1.useEffect(function () {
var nextContainer = getContainer_1.default(into, intoId);
if (container !== nextContainer) {
setContainer(nextContainer);
}
});
if (!container) {
return null;

@@ -27,3 +45,2 @@ }

intoId: PropTypes.string,
visible: PropTypes.bool.isRequired,
children: PropTypes.node,

@@ -30,0 +47,0 @@ };

{
"name": "@react-md/portal",
"version": "2.0.0-alpha.0",
"version": "2.0.0-alpha.1",
"description": "This package is for including icons within react-md. There is included support for both font icons and SVG icons. There is also a helper component for applying spacing between icons and text.",

@@ -41,3 +41,3 @@ "scripts": {

"dependencies": {
"@react-md/transition": "^2.0.0-alpha.0"
"@react-md/transition": "^2.0.0-alpha.1"
},

@@ -47,3 +47,3 @@ "publishConfig": {

},
"gitHead": "cc5de21740e62c1fd5da8f832f562c48eb028717"
"gitHead": "9197bcdf38df3cff304499431696dc8e950b4b17"
}
# @react-md/portal
The Portal component is a simple wrapper with React's `createPortal` API that
will automatically generate portal nodes behind the scenes as needed.
will automatically generate portal nodes behind the scenes as needed. Unlike the
majority of `react-md` packages, this package does not export any styles.

@@ -11,1 +12,57 @@ ## Installation

```
<!-- DOCS_REMOVE -->
## Documentation
You should check out the
[full documentation](https://react-md.dev/packages/portal) for live examples and
more customization information, but an example usage is shown below.
<!-- DOCS_REMOVE_END -->
<!-- INCLUDING_STYLES -->
## Usage
The main purpose of the `Portal` is to be able to fix overflow issues for fixed
elements within the page. If you have `overflow` set to anything other than the
default value, fixed elements might not appear correctly. To work around this,
you can portal that fixed element to a different part of the page and it'll fix
the problem. If none of this makes sense to you at a first glance, you probably
don't need this package.
The example below will just show the API for the portal and not a real world
example.
```tsx
import React, { useState } from "react";
import { render } from "react-dom";
import { Portal } from "@react-md/portal";
const App = () => {
const [visible, setVisible] = useState(false);
return (
<Fragment>
<button
id="example-button"
type="button"
onClick={() => setVisible(prevVisible => !prevVisible)}
>
Show Portal
</button>
<Portal>
{visible && (
<h3>
This is some portalled text that will only appear when{" "}
<code>visible</code>
</h3>
)}
</Portal>
</Fragment>
);
};
render(<App />, document.getElementById("root"));
```

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

export { PortalInto } from "./getContainer";
export { default as Portal } from "./Portal";

@@ -6,4 +8,1 @@ export * from "./Portal";

export * from "./ConditionalPortal";
export { useStaggeredVisibility } from "./hooks";
export * from "./types.d";
import { FunctionComponent, ReactElement } from "react";
import { PortalInto } from "./types.d";
import { PortalInto } from "./getContainer";
/**

@@ -23,6 +23,2 @@ * If any of these props are defined on a component, the component will

/**
* Boolean if the portal would be visible if one of the other portal props are defined or enabled.
*/
visible: boolean;
/**
* This children to render.

@@ -29,0 +25,0 @@ */

import { PortalProps, StaggerablePortalProps } from "./types.d";
/**
* This is an internal hook that will set the portal's container and validate that the portal
* target is valid in dev mode.
* @private
*/
export declare function usePortalState(props: PortalProps): HTMLElement | null;
/**
* This hook allows you to stagger the visibility of a portal so that it will stay visible
* until an exit animation has finished. This relies on the react-transition-group onExited
* hook to work.
*
* @param visible - Boolean if the main component should be visible. This will trigger the staggered
* animation in or out
* @param onExited - An optional onExited callback
* @return an object containing a boolean if the portal is visible as well as a merged `onExited` callback
* to apply to the react-transition-group child that is animating.
*/
export declare function useStaggeredVisibility({ visible, onExited, }: StaggerablePortalProps): {

@@ -4,0 +20,0 @@ portalVisible: boolean;

@@ -0,1 +1,2 @@

export { PortalInto } from "./getContainer";
export { default as Portal } from "./Portal";

@@ -5,3 +6,1 @@ export * from "./Portal";

export * from "./ConditionalPortal";
export { useStaggeredVisibility } from "./hooks";
export * from "./types.d";

@@ -1,4 +0,28 @@

import { FunctionComponent } from "react";
import { PortalProps } from "./types.d";
import { FunctionComponent, ReactNode } from "react";
import { PortalInto } from "./getContainer";
export interface PortalProps {
/**
* Either a function that returns an HTMLElement, an HTMLElement, or a `document.querySelector`
* string that will return the HTMLElement to render the children into. If both the `into` and
* `intoId` props are `undefined`, the `document.body` will be chosen instead.
*
* If the `querySelector` string does not return a valid HTMLElement, an error will be thrown.
*/
into?: PortalInto;
/**
* The id of an element that the portal should be rendered into. If an element with the provided
* id can not be found on the page at the time of mounting, an error will be thrown.
*/
intoId?: string;
/**
* The children to render within the portal.
*/
children?: ReactNode;
}
/**
* This component is a simple wrapper for the `createPortal` API from ReactDOM that will just ensure
* that `null` is always returned for server side rendering as well as a "nice" way to choose specific
* portal targets or just falling back to the `document.body`.
*/
declare const Portal: FunctionComponent<PortalProps>;
export default Portal;

@@ -13,7 +13,2 @@ import { ReactNode } from "react";

/**
* Boolean if the portal is currently visible.
*/
visible: boolean;
/**
* Either a function that returns an HTMLElement, an HTMLElement, or a `document.querySelector`

@@ -37,4 +32,1 @@ * string that will return the HTMLElement to render the children into. If both the `into` and

}
export type StaggerablePortalProps = Pick<PortalProps, "visible"> &
Pick<TransitionProps, "onExited">;

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

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

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