Skip to content

Commit 9c7ce89

Browse files
marek-nogiecyjose
andauthored
fix : Added Event argument to onOpen & onClose (#233)
* Added Event argument to onOpen & onClose * fix: fix events typing Co-authored-by: Youssouf EL Azizi <[email protected]>
1 parent 5d7a366 commit 9c7ce89

File tree

4 files changed

+39
-21
lines changed

4 files changed

+39
-21
lines changed

__test__/index.test.tsx

+11-3
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,17 @@ describe('Popup Component Render ', () => {
6868
render(<SimplePopup onOpen={onOpen} onClose={onClose} />);
6969

7070
fireEvent.click(screen.getByText('trigger'));
71-
await waitFor(() => expect(onOpen).toHaveBeenCalled());
72-
fireEvent.click(screen.getByText('trigger'));
73-
await waitFor(() => expect(onClose).toHaveBeenCalled());
71+
await waitFor(() => {
72+
expect(onOpen).toHaveBeenCalled();
73+
const [event] = onOpen.mock.calls[0];
74+
expect(event.hasOwnProperty('target')).toBe(true);
75+
});
76+
fireEvent.click(screen.getByText('trigger'));
77+
await waitFor(() => {
78+
expect(onClose).toHaveBeenCalled();
79+
const [event] = onClose.mock.calls[0];
80+
expect(event.hasOwnProperty('target')).toBe(true);
81+
});
7482
// expect(screen.getByRole('tooltip')).toBeInTheDocument();
7583
});
7684

src/hooks.tsx

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { useEffect, RefObject, useLayoutEffect } from 'react';
22

3-
export const useOnEscape = (handler: () => void, active = true) => {
3+
export const useOnEscape = (
4+
handler: (event: KeyboardEvent) => void,
5+
active = true
6+
) => {
47
useEffect(() => {
58
if (!active) return;
69
const listener = (event: KeyboardEvent) => {
710
// check if key is an Escape
8-
if (event.key === 'Escape') handler();
11+
if (event.key === 'Escape') handler(event);
912
};
1013
document.addEventListener('keyup', listener);
1114

@@ -34,24 +37,24 @@ export const useRepositionOnResize = (handler: () => void, active = true) => {
3437

3538
export const useOnClickOutside = (
3639
ref: RefObject<HTMLElement> | RefObject<HTMLElement>[],
37-
handler: () => void,
40+
handler: (event: TouchEvent | MouseEvent) => void,
3841
active = true
3942
) => {
4043
useEffect(() => {
4144
if (!active) return;
42-
const listener = (event: any) => {
45+
const listener = (event: TouchEvent | MouseEvent) => {
4346
// Do nothing if clicking ref's element or descendent elements
4447
const refs = Array.isArray(ref) ? ref : [ref];
4548

4649
let contains = false;
4750
refs.forEach(r => {
48-
if (!r.current || r.current.contains(event.target)) {
51+
if (!r.current || r.current.contains(event.target as Node)) {
4952
contains = true;
5053
return;
5154
}
5255
});
5356
event.stopPropagation();
54-
if (!contains) handler();
57+
if (!contains) handler(event);
5558
};
5659

5760
document.addEventListener('mousedown', listener);

src/index.tsx

+14-10
Original file line numberDiff line numberDiff line change
@@ -97,38 +97,42 @@ export const Popup = forwardRef<PopupActions, PopupProps>(
9797
}
9898
}, [open, disabled]);
9999

100-
const openPopup = () => {
100+
const openPopup = (event?: React.SyntheticEvent) => {
101101
if (isOpen || disabled) return;
102102
setIsOpen(true);
103-
setTimeout(onOpen, 0);
103+
setTimeout(() => onOpen(event), 0);
104104
};
105105

106-
const closePopup = () => {
106+
const closePopup = (
107+
event?: React.SyntheticEvent | KeyboardEvent | TouchEvent | MouseEvent
108+
) => {
107109
if (!isOpen || disabled) return;
108110
setIsOpen(false);
109111
if (isModal) (focusedElBeforeOpen.current as HTMLElement).focus();
110-
setTimeout(onClose, 0);
112+
setTimeout(() => onClose(event), 0);
111113
};
112114

113115
const togglePopup = (event?: React.SyntheticEvent) => {
114116
event?.stopPropagation();
115-
if (!isOpen) openPopup();
116-
else closePopup();
117+
if (!isOpen) openPopup(event);
118+
else closePopup(event);
117119
};
118120

119-
const onMouseEnter = () => {
121+
const onMouseEnter = (event?: React.SyntheticEvent) => {
120122
clearTimeout(timeOut.current);
121-
timeOut.current = setTimeout(openPopup, mouseEnterDelay);
123+
timeOut.current = setTimeout(() => openPopup(event), mouseEnterDelay);
122124
};
125+
123126
const onContextMenu = (event?: React.SyntheticEvent) => {
124127
event?.preventDefault();
125128
togglePopup();
126129
};
127130

128-
const onMouseLeave = () => {
131+
const onMouseLeave = (event?: React.SyntheticEvent) => {
129132
clearTimeout(timeOut.current);
130-
timeOut.current = setTimeout(closePopup, mouseLeaveDelay);
133+
timeOut.current = setTimeout(() => closePopup(event), mouseLeaveDelay);
131134
};
135+
132136
const lockScrolll = () => {
133137
if (isModal && lockScroll)
134138
document.getElementsByTagName('body')[0].style.overflow = 'hidden'; // migrate to document.body

src/types.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ export interface PopupProps {
4242
repositionOnResize?: boolean;
4343
mouseEnterDelay?: number;
4444
mouseLeaveDelay?: number;
45-
onOpen?: () => any;
46-
onClose?: () => any;
45+
onOpen?: (event?: React.SyntheticEvent) => void;
46+
// the popup can be closed depend on multiple factor: mouse click outside, keyboard esc, click a close button
47+
onClose?: (
48+
event?: React.SyntheticEvent | KeyboardEvent | TouchEvent | MouseEvent
49+
) => void;
4750
contentStyle?: React.CSSProperties;
4851
overlayStyle?: React.CSSProperties;
4952
arrowStyle?: React.CSSProperties;

0 commit comments

Comments
 (0)