react-cool-onclickoutside
Advanced tools
Comparing version 0.0.2 to 0.0.3
@@ -1,1 +0,1 @@ | ||
import{useRef as n,useCallback as t,useEffect as e}from"react";var r=function(n){return!(!n.includes("touch")||!function(){if("undefined"==typeof window||"function"!=typeof window.addEventListener)return!1;var n=!1,t=Object.defineProperty({},"passive",{get:function(){n=!0}}),e=function(){};return window.addEventListener("test",e,t),window.removeEventListener("test",e,t),n}())&&{passive:!0}};export default function(o){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:["mousedown","touchstart"];if("undefined"!=typeof document&&document.createElement){var u=n([]),f=t((function(n){n&&u.current.push(n)}),[]),c=t((function(n){var t=u.current;if(t.length&&o){var e=!0,r=!1,i=void 0;try{for(var f,c=t[Symbol.iterator]();!(e=(f=c.next()).done);e=!0){if(f.value.contains(n.target))return}}catch(n){r=!0,i=n}finally{try{e||null==c.return||c.return()}finally{if(r)throw i}}o(n)}}),[u,o]);return e((function(){if(o)return i.forEach((function(n){document.addEventListener(n,c,r(n))})),function(){i.forEach((function(n){document.removeEventListener(n,c,r(n))}))}}),[o,i]),f}} | ||
import{useRef as n,useCallback as t,useEffect as e}from"react";var r=function(n){return document.documentElement.clientWidth<=n.clientX||document.documentElement.clientHeight<=n.clientY},o=function(n){return!(!n.includes("touch")||!function(){if("undefined"==typeof window||"function"!=typeof window.addEventListener)return!1;var n=!1,t=Object.defineProperty({},"passive",{get:function(){n=!0}}),e=function(){};return window.addEventListener("test",e,t),window.removeEventListener("test",e,t),n}())&&{passive:!0}};export default function(i){var u=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=u.eventTypes,d=void 0===c?["mousedown","touchstart"]:c,f=u.excludeScrollbar,a=void 0!==f&&f;if("undefined"==typeof document||!document.createElement)return function(){return null};var l=n([]),v=t((function(n){n&&l.current.push(n)}),[]),m=t((function(n){var t=l.current;if(t.length&&i&&(!a||!r(n))){var e=!0,o=!1,u=void 0;try{for(var c,d=t[Symbol.iterator]();!(e=(c=d.next()).done);e=!0){if(c.value.contains(n.target))return}}catch(n){o=!0,u=n}finally{try{e||null==d.return||d.return()}finally{if(o)throw u}}i(n)}}),[l,a,i]);return e((function(){return i?(d.forEach((function(n){document.addEventListener(n,m,o(n))})),function(){d.forEach((function(n){document.removeEventListener(n,m,o(n))}))}):function(){return null}}),[i,d]),v} |
@@ -1,1 +0,1 @@ | ||
"use strict";var react=require("react"),canUsePassiveEvents=function(){if("undefined"==typeof window||"function"!=typeof window.addEventListener)return!1;var e=!1,t=Object.defineProperty({},"passive",{get:function(){e=!0}}),n=function(){};return window.addEventListener("test",n,t),window.removeEventListener("test",n,t),e},getOpts=function(e){return!(!e.includes("touch")||!canUsePassiveEvents())&&{passive:!0}},index=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:["mousedown","touchstart"];if("undefined"!=typeof document&&document.createElement){var n=react.useRef([]),r=react.useCallback((function(e){e&&n.current.push(e)}),[]),i=react.useCallback((function(t){var r=n.current;if(r.length&&e){var i=!0,o=!1,u=void 0;try{for(var c,a=r[Symbol.iterator]();!(i=(c=a.next()).done);i=!0){if(c.value.contains(t.target))return}}catch(e){o=!0,u=e}finally{try{i||null==a.return||a.return()}finally{if(o)throw u}}e(t)}}),[n,e]);return react.useEffect((function(){if(e)return t.forEach((function(e){document.addEventListener(e,i,getOpts(e))})),function(){t.forEach((function(e){document.removeEventListener(e,i,getOpts(e))}))}}),[e,t]),r}};module.exports=index; | ||
"use strict";var react=require("react"),canUsePassiveEvents=function(){if("undefined"==typeof window||"function"!=typeof window.addEventListener)return!1;var e=!1,n=Object.defineProperty({},"passive",{get:function(){e=!0}}),t=function(){};return window.addEventListener("test",t,n),window.removeEventListener("test",t,n),e},clickedOnScrollbar=function(e){return document.documentElement.clientWidth<=e.clientX||document.documentElement.clientHeight<=e.clientY},getEventOptions=function(e){return!(!e.includes("touch")||!canUsePassiveEvents())&&{passive:!0}},index=function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=n.eventTypes,r=void 0===t?["mousedown","touchstart"]:t,i=n.excludeScrollbar,c=void 0!==i&&i;if("undefined"==typeof document||!document.createElement)return function(){return null};var o=react.useRef([]),u=react.useCallback((function(e){e&&o.current.push(e)}),[]),a=react.useCallback((function(n){var t=o.current;if(t.length&&e&&(!c||!clickedOnScrollbar(n))){var r=!0,i=!1,u=void 0;try{for(var a,d=t[Symbol.iterator]();!(r=(a=d.next()).done);r=!0){if(a.value.contains(n.target))return}}catch(e){i=!0,u=e}finally{try{r||null==d.return||d.return()}finally{if(i)throw u}}e(n)}}),[o,c,e]);return react.useEffect((function(){return e?(r.forEach((function(e){document.addEventListener(e,a,getEventOptions(e))})),function(){r.forEach((function(e){document.removeEventListener(e,a,getEventOptions(e))}))}):function(){return null}}),[e,r]),u};module.exports=index; |
{ | ||
"name": "react-cool-onclickoutside", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "React hook to listen for clicks outside of the component(s).", | ||
@@ -196,4 +196,3 @@ "license": "MIT", | ||
"@rollup/plugin-replace": "^2.3.0", | ||
"@rollup/plugin-url": "^4.0.0", | ||
"@testing-library/react": "^9.4.0", | ||
"@rollup/plugin-url": "^4.0.1", | ||
"@testing-library/react-hooks": "^3.2.1", | ||
@@ -218,3 +217,3 @@ "@types/jest": "^24.0.25", | ||
"eslint-plugin-react-hooks": "^2.3.0", | ||
"husky": "^4.0.0", | ||
"husky": "^4.0.1", | ||
"jest": "^24.9.0", | ||
@@ -229,3 +228,3 @@ "lint-staged": "^9.5.0", | ||
"rimraf": "^3.0.0", | ||
"rollup": "^1.28.0", | ||
"rollup": "^1.29.0", | ||
"rollup-plugin-babel": "^4.3.3", | ||
@@ -232,0 +231,0 @@ "rollup-plugin-commonjs": "^10.1.0", |
# React Cool Onclickoutside | ||
This is a React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook) to execute callback when user clicks outside of the target component(s) area. It's a useful logic for UI interaction design (IxD) like hide a dropdown menu or tooltip etc. Hop you guys ❤️ it! | ||
This is a React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook) to execute callback when user clicks outside of the target component(s) area. It's a useful logic for UI interaction design (IxD) like dismiss a dropdown menu, modal or tooltip etc. Hop you guys ❤️ it! | ||
@@ -12,22 +12,47 @@ ⚡️ Live demo: https://react-cool-onclickoutside.netlify.com | ||
- [x] Support multiple refs | ||
- [ ] Clicks on the scrollbar can be ignored | ||
- [x] Ignore callback triggered by clicks browser scrollbar | ||
- [ ] Unit testing | ||
- [ ] Typescript type definition | ||
- [ ] Demo website | ||
- [ ] Demo code | ||
- [ ] CI/CD | ||
- [ ] Documentation | ||
## Requirement | ||
To use `react-cool-onclickoutside`, you must use `react@16.8.0` or greater which includes hooks. | ||
## Installation | ||
This package is distributed via [npm](https://www.npmjs.com/package/react-cool-onclickoutside). | ||
```sh | ||
$ yarn add react-cool-onclickoutside | ||
# or | ||
$ npm install --save react-cool-onclickoutside | ||
``` | ||
## Usage | ||
General use case. | ||
Common use case. | ||
```js | ||
import useOnclickoutside from 'react-use-onclickoutside'; | ||
import useOnclickoutside from 'react-cool-onclickoutside'; | ||
const App = () => { | ||
const ref = useOnclickoutside(() => { | ||
// Handle outside clicked... | ||
const Dropdown = () => { | ||
const [openMenu, setOpenMenu] = useState(false); | ||
const rigisterRef = useOnclickoutside(() => { | ||
setOpenMenu(false); | ||
}); | ||
return <div ref={ref}>{'Dropdown'}</div>; | ||
const handleClickBtn = () => { | ||
setOpenMenu(true); | ||
}; | ||
return ( | ||
<div> | ||
<div onClick={handleClickBtn}>Button</div> | ||
{openMenu && <div ref={rigisterRef}>Menu</div>} | ||
</div> | ||
); | ||
}; | ||
@@ -39,14 +64,19 @@ ``` | ||
```js | ||
import useOnclickoutside from 'react-use-onclickoutside'; | ||
import useOnclickoutside from 'react-cool-onclickoutside'; | ||
const App = () => { | ||
const ref = useOnclickoutside(() => { | ||
// Handle outside clicked... | ||
const [showTips, setShowTips] = useState(true); | ||
const rigisterRef = useOnclickoutside(() => { | ||
setShowTips(false); | ||
}); | ||
return ( | ||
<> | ||
<div ref={ref}>{'Dropdown 1'}</div> | ||
<div ref={ref}>{'Dropdown 2'}</div> | ||
</> | ||
<div> | ||
{showTips && ( | ||
<> | ||
<Tooltip ref={rigisterRef} /> | ||
<Tooltip ref={rigisterRef} /> | ||
</> | ||
)} | ||
</div> | ||
); | ||
@@ -56,9 +86,31 @@ }; | ||
## Reference | ||
## API | ||
```js | ||
type UseOnclickoutside = ( | ||
callback: (event?: MouseEvent | TouchEvent) => void, | ||
eventTypes: string[] = ['mousedown', 'touchstart'] | ||
): (el: HTMLElement | null) => void | ||
const rigisterRef = useOnclickoutside(callback[, options]); | ||
``` | ||
### Parameters | ||
You must pass the `callback` for using this hook and you can access the [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) or [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) via the `event` parameter as below: | ||
```js | ||
const callback = event => { | ||
console.log('Event: ', event); | ||
}; | ||
``` | ||
The `options` object may contain the following keys. | ||
| Key | Type | Default | Description | | ||
| ------------------ | ------- | ----------------------------- | -------------------------------------------------------------- | | ||
| `eventTypes` | Array | `['mousedown', 'touchstart']` | Which events to listen for. | | ||
| `excludeScrollbar` | boolean | `false` | Whether or not to listen (ignore) to browser scrollbar clicks. | | ||
### Return | ||
A function to register the component(s) that `useOnclickoutside` hook should target to. | ||
## Inspiration | ||
- [react-onclickoutside](https://github.com/Pomax/react-onclickoutside) |
14240
54
15
114