Socket
Socket
Sign inDemoInstall

react-useportal

Package Overview
Dependencies
9
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.3 to 1.0.4

9

dist/usePortal.d.ts

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

import { DOMAttributes, EventHandler, SyntheticEvent, MutableRefObject } from 'react';
import { DOMAttributes, SyntheticEvent, MutableRefObject } from 'react';
declare type HTMLElRef = MutableRefObject<HTMLElement>;

@@ -9,4 +9,4 @@ declare type CustomEvent = {

declare type CustomEventHandler = (customEvent: CustomEvent) => void | HTMLElRef;
declare type EventHandlers = {
[K in keyof DOMAttributes<K>]?: EventHandler<SyntheticEvent<any, Event>>;
declare type CustomEventHandlers = {
[K in keyof DOMAttributes<K>]?: CustomEventHandler;
};

@@ -18,8 +18,7 @@ declare type UsePortalOptions = {

isOpen?: boolean;
stateful?: boolean;
onOpen?: CustomEventHandler;
onClose?: CustomEventHandler;
} & EventHandlers;
} & CustomEventHandlers;
export default function usePortal({ closeOnOutsideClick, closeOnEsc, bindTo, // attach the portal to this node in the DOM
isOpen: defaultIsOpen, onOpen, onClose, ...eventHandlers }?: UsePortalOptions): any;
export {};

@@ -45,3 +45,5 @@ "use strict";

const handleEvent = react_1.useCallback((func, event) => {
if (event && event.currentTarget)
if (!func || isServer)
return;
if (event && event.currentTarget && event.currentTarget !== document)
targetEl.current = event.currentTarget;

@@ -51,2 +53,9 @@ // i.e. onClick, etc. inside usePortal({ onClick({ portal, targetEl }) {} })

}, [portal, targetEl]);
// this should handle all eventHandlers like onClick, onMouseOver, etc. passed into the config
const customEventHandlers = Object
.entries(eventHandlers)
.reduce((acc, [handlerName, eventHandler]) => {
acc[handlerName] = (event) => handleEvent(eventHandler, event);
return acc;
}, {});
const openPortal = react_1.useCallback((event) => {

@@ -96,2 +105,4 @@ if (isServer)

}, [isServer, closePortal, closeOnOutsideClick, portal]);
// used to remove the event listeners on unmount
const eventListeners = react_1.useRef({});
react_1.useEffect(() => {

@@ -102,9 +113,30 @@ if (isServer)

return;
// TODO: eventually will need to figure out a better solution for this.
// Surely we can find a way to map onScroll/onWheel -> scroll/wheel better,
// but for all other event handlers. For now this works.
const eventHandlerMap = {
onScroll: 'scroll',
onWheel: 'wheel',
};
const node = portal.current;
elToMountTo.appendChild(portal.current);
document && document.addEventListener('keydown', handleKeydown);
document && document.addEventListener('mousedown', handleOutsideMouseClick);
// handles all special case handlers. Currently only onScroll and onWheel
Object.entries(eventHandlerMap).forEach(([handlerName /* onScroll */, eventListenerName /* scroll */]) => {
if (!eventHandlers[handlerName])
return;
eventListeners.current[handlerName] = (e) => handleEvent(eventHandlers[handlerName], e);
document.addEventListener(eventListenerName, eventListeners.current[handlerName]);
});
document.addEventListener('keydown', handleKeydown);
document.addEventListener('mousedown', handleOutsideMouseClick);
return () => {
document && document.removeEventListener('keydown', handleKeydown);
document && document.removeEventListener('mousedown', handleOutsideMouseClick);
// handles all special case handlers. Currently only onScroll and onWheel
Object.entries(eventHandlerMap).forEach(([handlerName, eventListenerName]) => {
if (!eventHandlers[handlerName])
return;
document.removeEventListener(eventListenerName, eventListeners.current[handlerName]);
delete eventListeners.current[handlerName];
});
document.removeEventListener('keydown', handleKeydown);
document.removeEventListener('mousedown', handleOutsideMouseClick);
elToMountTo.removeChild(node);

@@ -118,9 +150,2 @@ };

}, [portal]);
// this should handle all eventHandlers like onClick, onMouseOver, etc. passed into the config
const customEventHandlers = Object
.entries(eventHandlers)
.reduce((acc, [handlerName, eventHandler]) => {
acc[handlerName] = (event) => handleEvent(eventHandler, event);
return acc;
}, {});
return Object.assign([openPortal, closePortal, open.current, Portal, togglePortal], Object.assign(Object.assign({ isOpen: open.current, openPortal, ref: targetEl, closePortal,

@@ -127,0 +152,0 @@ togglePortal,

{
"name": "react-useportal",
"version": "1.0.3",
"version": "1.0.4",
"homepage": "https://codesandbox.io/s/w6jp7z4pkk",

@@ -38,2 +38,3 @@ "main": "dist/usePortal.js",

"devDependencies": {
"@testing-library/react-hooks": "^2.0.1",
"@types/jest": "^24.0.18",

@@ -53,3 +54,2 @@ "@types/react": "^16.9.2",

"react-dom": "^16.8.6",
"react-hooks-testing-library": "^0.6.0",
"react-test-renderer": "^16.8.6",

@@ -56,0 +56,0 @@ "react-testing-library": "^8.0.0",

@@ -55,3 +55,3 @@ <p style="text-align: center;" align="center">

### Examples
- [Modal Example - Next.js - codesandbox container](https://codesandbox.io/s/useportal-in-nextjs-codesandbox-container-9rm5o) (sometimes buggy, if so try [this example](https://codesandbox.io/s/useportal-in-nextjs-ux9nb))
- [SSR Example - Next.js - codesandbox container](https://codesandbox.io/s/useportal-in-nextjs-codesandbox-container-9rm5o) (sometimes buggy, if so try [this example](https://codesandbox.io/s/useportal-in-nextjs-ux9nb))
- [Modal Example (useModal) - create-react-app](https://codesandbox.io/s/w6jp7z4pkk)

@@ -152,3 +152,3 @@ - [Dropdown Example (useDropdown) - Next.js](https://codesandbox.io/s/useportal-usedropdown-587fo)

### Customizing the Portal directly
By using `onOpen`, `onClose` or any other event handler, you can modify the `Portal` and return it. See [useDropdown](https://codesandbox.io/s/useportal-usedropdown-587fo) for a working example. It's important that you pass the `event` object to `openPortal` otherwise you will need to attach a ref to the clicked element.
By using `onOpen`, `onClose` or any other event handler, you can modify the `Portal` and return it. See [useDropdown](https://codesandbox.io/s/useportal-usedropdown-587fo) for a working example. It's important that you pass the `event` object to `openPortal` and `togglePortal` otherwise you will need to attach a `ref` to the clicked element.

@@ -191,4 +191,32 @@ ```jsx

**Make sure you are passing the html synthetic event to the `openPortal`. i.e. `onClick={e => openPortal(e)}`**
**Make sure you are passing the html synthetic event to the `openPortal` and `togglePortal` . i.e. `onClick={e => openPortal(e)}`**
### Usage with a `ref`
If for some reason, you don't want to pass around the `event` to `openPortal` or `togglePortal`, you can use a `ref` like this.
```jsx
import usePortal from 'react-useportal'
const App = () => {
var { ref, openPortal, closePortal, isOpen, Portal } = usePortal()
return (
<>
{/* see below how I don't have to pass the event if I use the ref */}
<button ref={ref} onClick={() => openPortal()}>
Open Portal
</button>
{isOpen && (
<Portal>
<p>
This Portal handles its own state.{' '}
<button onClick={closePortal}>Close me!</button>, hit ESC or
click outside of me.
</p>
</Portal>
)}
</>
)
}
```
Options

@@ -228,2 +256,3 @@ -----

------
- [ ] add correct return types
- [ ] add support for popup windows [resource 1](https://javascript.info/popup-windows) [resource 2](https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202). Maybe something like

@@ -238,5 +267,2 @@ ```jsx

- [ ] maybe have a `<Provider order={['Portal', 'openPortal']} />` then you can change the order of the array destructuring syntax
- [ ] make work without requiring the html synthetic event
- [ ] add example for tooltip (like [this one](https://codepen.io/davidgilbertson/pen/ooXVyw))
- [ ] add as many examples as possible 😊
- [ ] fix code so maintainability is A

@@ -246,5 +272,2 @@ - [ ] set up code climate test coverage

- [ ] add code climate test coverage badge
- [X] document when you are required to have synthetic event
- [X] make isomorphic
- [X] continuous integration
- [X] greenkeeper
- [ ] add example to docs with using a `ref` instead of the `event` in `openPortal`, etc.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc