From 571d26fe3216f2f9ac4ff73abb8ead5e17d8da0b Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 21 Mar 2024 12:03:25 +0100 Subject: [PATCH 1/3] Support missing refs (fixes #531) --- .all-contributorsrc | 7 +++++++ .changeset/rare-icons-tickle.md | 5 +++++ .github/CONTRIBUTING.md | 3 +++ README.md | 5 ++++- packages/usehooks-ts/README.md | 5 ++++- .../useOnClickOuside.test.ts | 19 +++++++++++++++++++ .../useOnClickOutside/useOnClickOutside.ts | 4 +++- 7 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 .changeset/rare-icons-tickle.md diff --git a/.all-contributorsrc b/.all-contributorsrc index 4c8a8a85..32fd4f3a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1726,6 +1726,13 @@ "avatar_url": "https://avatars.githubusercontent.com/u/10504365?v=4", "profile": "https://github.com/Newbie012", "contributions": ["code"] + }, + { + "login": "isumix", + "name": "Igor Sukharev", + "avatar_url": "https://avatars.githubusercontent.com/u/16747416?v=4", + "profile": "https://github.com/isumix", + "contributions": ["bug"] } ], "contributorsPerLine": 7, diff --git a/.changeset/rare-icons-tickle.md b/.changeset/rare-icons-tickle.md new file mode 100644 index 00000000..605aa91a --- /dev/null +++ b/.changeset/rare-icons-tickle.md @@ -0,0 +1,5 @@ +--- +"usehooks-ts": patch +--- + +Support missing refs in `useOnClickOutside` (Fixes: #531) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index afd21f69..8417bb1b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -420,6 +420,9 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Luma
Luma

💻 Eliya Cohen
Eliya Cohen

💻 + + Igor Sukharev
Igor Sukharev

🐛 + diff --git a/README.md b/README.md index 77935804..8a8df7de 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-245-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-246-orange.svg?style=flat-square)](#contributors-)
@@ -432,6 +432,9 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Luma
Luma

💻 Eliya Cohen
Eliya Cohen

💻 + + Igor Sukharev
Igor Sukharev

🐛 + diff --git a/packages/usehooks-ts/README.md b/packages/usehooks-ts/README.md index 77935804..8a8df7de 100644 --- a/packages/usehooks-ts/README.md +++ b/packages/usehooks-ts/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-245-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-246-orange.svg?style=flat-square)](#contributors-)
@@ -432,6 +432,9 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Luma
Luma

💻 Eliya Cohen
Eliya Cohen

💻 + + Igor Sukharev
Igor Sukharev

🐛 + diff --git a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOuside.test.ts b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOuside.test.ts index af21d90a..d3d6a84c 100644 --- a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOuside.test.ts +++ b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOuside.test.ts @@ -40,6 +40,25 @@ describe('useOnClickOutside(', () => { expect(handler).toHaveBeenCalledTimes(1) }) + it('should call the handler when a clicking outside the element (multiple refs with a null)', () => { + const containerRef1 = { current: document.createElement('div') } + const containerRef2 = { current: null } + const handler = vitest.fn() + + renderHook(() => { + useOnClickOutside([containerRef1, containerRef2], handler) + }) + + expect(handler).toHaveBeenCalledTimes(0) + + // Simulate click outside the containers + act(() => { + fireEvent.mouseDown(document) + }) + + expect(handler).toHaveBeenCalledTimes(1) + }) + it('should NOT call the handler when a clicking inside the element', () => { const containerRef = { current: document.createElement('div') } const handler = vitest.fn() diff --git a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts index 61e93f25..6a79703c 100644 --- a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts +++ b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts @@ -36,7 +36,9 @@ export function useOnClickOutside( } const isOutside = Array.isArray(ref) - ? ref.every(r => r.current && !r.current.contains(target)) + ? ref + .filter(r => Boolean(r.current)) + .every(r => r.current && !r.current.contains(target)) : ref.current && !ref.current.contains(target) if (isOutside) { From a05d60d697126a807d37a841a3c4ebf3c39c8e43 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 21 Mar 2024 12:28:03 +0100 Subject: [PATCH 2/3] Add support for focus event to `useOnClickOutside` (Fixes: #522) --- .all-contributorsrc | 8 ++++++++ .changeset/five-impalas-suffer.md | 5 +++++ .github/CONTRIBUTING.md | 1 + README.md | 3 ++- packages/usehooks-ts/README.md | 3 ++- .../src/useOnClickOutside/useOnClickOutside.ts | 12 +++++++++--- 6 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 .changeset/five-impalas-suffer.md diff --git a/.all-contributorsrc b/.all-contributorsrc index 32fd4f3a..823c8712 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1733,8 +1733,16 @@ "avatar_url": "https://avatars.githubusercontent.com/u/16747416?v=4", "profile": "https://github.com/isumix", "contributions": ["bug"] + }, + { + "login": "pookmish", + "name": "pookmish", + "avatar_url": "https://avatars.githubusercontent.com/u/7185045?v=4", + "profile": "https://github.com/pookmish", + "contributions": ["ideas"] } ], "contributorsPerLine": 7, "commitType": "docs" } + diff --git a/.changeset/five-impalas-suffer.md b/.changeset/five-impalas-suffer.md new file mode 100644 index 00000000..1c0f02c3 --- /dev/null +++ b/.changeset/five-impalas-suffer.md @@ -0,0 +1,5 @@ +--- +"usehooks-ts": patch +--- + +Add support for focus event to `useOnClickOutside` (Fixes: #522) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8417bb1b..af50b5a1 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -422,6 +422,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 + pookmish
pookmish

🤔 diff --git a/README.md b/README.md index 8a8df7de..22fc0e1a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-246-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-247-orange.svg?style=flat-square)](#contributors-)
@@ -434,6 +434,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 + pookmish
pookmish

🤔 diff --git a/packages/usehooks-ts/README.md b/packages/usehooks-ts/README.md index 8a8df7de..22fc0e1a 100644 --- a/packages/usehooks-ts/README.md +++ b/packages/usehooks-ts/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-246-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-247-orange.svg?style=flat-square)](#contributors-)
@@ -434,6 +434,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 + pookmish
pookmish

🤔 diff --git a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts index 6a79703c..9d009ae0 100644 --- a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts +++ b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts @@ -3,13 +3,19 @@ import type { RefObject } from 'react' import { useEventListener } from '../useEventListener' /** Supported event types. */ -type EventType = 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' +type EventType = + | 'mousedown' + | 'mouseup' + | 'touchstart' + | 'touchend' + | 'focusin' + | 'focusout' /** * Custom hook that handles clicks outside a specified element. * @template T - The type of the element's reference. * @param {RefObject | RefObject[]} ref - The React ref object(s) representing the element(s) to watch for outside clicks. - * @param {(event: MouseEvent | TouchEvent) => void} handler - The callback function to be executed when a click outside the element occurs. + * @param {(event: MouseEvent | TouchEvent | FocusEvent) => void} handler - The callback function to be executed when a click outside the element occurs. * @param {EventType} [eventType] - The mouse event type to listen for (optional, default is 'mousedown'). * @returns {void} * @public @@ -24,7 +30,7 @@ type EventType = 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' */ export function useOnClickOutside( ref: RefObject | RefObject[], - handler: (event: MouseEvent | TouchEvent) => void, + handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, eventType: EventType = 'mousedown', ): void { useEventListener(eventType, event => { From 4f03894cddf5c7623701297417b44f0e327c1750 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 21 Mar 2024 17:47:50 +0100 Subject: [PATCH 3/3] Expose `AddEventListenerOptions` in `useOnClickOutside` (Fixes #554 from @metav-drimz) --- .all-contributorsrc | 7 ++++ .changeset/poor-forks-end.md | 5 +++ .github/CONTRIBUTING.md | 1 + README.md | 3 +- packages/usehooks-ts/README.md | 3 +- .../useOnClickOutside/useOnClickOutside.ts | 37 +++++++++++-------- 6 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 .changeset/poor-forks-end.md diff --git a/.all-contributorsrc b/.all-contributorsrc index 823c8712..cbac07ae 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1740,6 +1740,13 @@ "avatar_url": "https://avatars.githubusercontent.com/u/7185045?v=4", "profile": "https://github.com/pookmish", "contributions": ["ideas"] + }, + { + "login": "metav-drimz", + "name": "metav-drimz", + "avatar_url": "https://avatars.githubusercontent.com/u/113976282?v=4", + "profile": "https://github.com/metav-drimz", + "contributions": ["ideas"] } ], "contributorsPerLine": 7, diff --git a/.changeset/poor-forks-end.md b/.changeset/poor-forks-end.md new file mode 100644 index 00000000..4daa90b2 --- /dev/null +++ b/.changeset/poor-forks-end.md @@ -0,0 +1,5 @@ +--- +"usehooks-ts": patch +--- + +Expose `AddEventListenerOptions` in `useOnClickOutside` (Fixes #554 from @metav-drimz) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index af50b5a1..2e493cc1 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -423,6 +423,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 pookmish
pookmish

🤔 + metav-drimz
metav-drimz

🤔 diff --git a/README.md b/README.md index 22fc0e1a..19e363ce 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-247-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-248-orange.svg?style=flat-square)](#contributors-)
@@ -435,6 +435,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 pookmish
pookmish

🤔 + metav-drimz
metav-drimz

🤔 diff --git a/packages/usehooks-ts/README.md b/packages/usehooks-ts/README.md index 22fc0e1a..19e363ce 100644 --- a/packages/usehooks-ts/README.md +++ b/packages/usehooks-ts/README.md @@ -17,7 +17,7 @@ [![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts) ![npm](https://img.shields.io/npm/v/usehooks-ts) -[![All Contributors](https://img.shields.io/badge/all_contributors-247-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-248-orange.svg?style=flat-square)](#contributors-)
@@ -435,6 +435,7 @@ Big thanks go to all our contributors! [[Become a contributor](https://github.co Igor Sukharev
Igor Sukharev

🐛 pookmish
pookmish

🤔 + metav-drimz
metav-drimz

🤔 diff --git a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts index 9d009ae0..a0372d57 100644 --- a/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts +++ b/packages/usehooks-ts/src/useOnClickOutside/useOnClickOutside.ts @@ -17,6 +17,7 @@ type EventType = * @param {RefObject | RefObject[]} ref - The React ref object(s) representing the element(s) to watch for outside clicks. * @param {(event: MouseEvent | TouchEvent | FocusEvent) => void} handler - The callback function to be executed when a click outside the element occurs. * @param {EventType} [eventType] - The mouse event type to listen for (optional, default is 'mousedown'). + * @param {?AddEventListenerOptions} [eventListenerOptions] - The options object to be passed to the `addEventListener` method (optional). * @returns {void} * @public * @see [Documentation](https://usehooks-ts.com/react-hook/use-on-click-outside) @@ -32,23 +33,29 @@ export function useOnClickOutside( ref: RefObject | RefObject[], handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, eventType: EventType = 'mousedown', + eventListenerOptions: AddEventListenerOptions = {}, ): void { - useEventListener(eventType, event => { - const target = event.target as Node + useEventListener( + eventType, + event => { + const target = event.target as Node - // Do nothing if the target is not connected element with document - if (!target || !target.isConnected) { - return - } + // Do nothing if the target is not connected element with document + if (!target || !target.isConnected) { + return + } - const isOutside = Array.isArray(ref) - ? ref - .filter(r => Boolean(r.current)) - .every(r => r.current && !r.current.contains(target)) - : ref.current && !ref.current.contains(target) + const isOutside = Array.isArray(ref) + ? ref + .filter(r => Boolean(r.current)) + .every(r => r.current && !r.current.contains(target)) + : ref.current && !ref.current.contains(target) - if (isOutside) { - handler(event) - } - }) + if (isOutside) { + handler(event) + } + }, + undefined, + eventListenerOptions, + ) }