-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathuseOverlayListener.js
82 lines (73 loc) · 2.99 KB
/
useOverlayListener.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* eslint-disable */
import * as React from 'react';
import { DomHandler } from '../utils/Utils';
import { useEventListener } from './useEventListener';
import { useOverlayScrollListener } from './useOverlayScrollListener';
import { useResizeListener } from './useResizeListener';
import { useUnmountEffect } from './useUnmountEffect';
export const useOverlayListener = ({ target, overlay, listener, when = true }) => {
const targetRef = React.useRef(null);
const overlayRef = React.useRef(null);
/**
* The parameters of the 'listener' method in the following event handlers;
* @param {Event} event A click event of the document.
* @param {string} options.type The custom type to detect event.
* @param {boolean} options.valid It is controlled by PrimeReact. It is determined whether it is valid or not according to some custom validation.
*/
const [bindDocumentClickListener, unbindDocumentClickListener] = useEventListener({
type: 'click',
listener: (event) => {
listener && listener(event, { type: 'outside', valid: event.which !== 3 && isOutsideClicked(event) });
}
});
const [bindWindowResizeListener, unbindWindowResizeListener] = useResizeListener({
listener: (event) => {
listener && listener(event, { type: 'resize', valid: !DomHandler.isTouchDevice() });
}
});
const [bindWindowOrientationChangeListener, unbindWindowOrientationChangeListener] = useEventListener({
target: 'window',
type: 'orientationchange',
listener: (event) => {
listener && listener(event, { type: 'orientationchange', valid: true });
}
});
const [bindOverlayScrollListener, unbindOverlayScrollListener] = useOverlayScrollListener({
target,
listener: (event) => {
listener && listener(event, { type: 'scroll', valid: true });
}
});
const isOutsideClicked = (event) => {
return targetRef.current && !(targetRef.current.isSameNode(event.target) || targetRef.current.contains(event.target) || (overlayRef.current && overlayRef.current.contains(event.target)));
};
const bind = () => {
bindDocumentClickListener();
bindWindowResizeListener();
bindWindowOrientationChangeListener();
bindOverlayScrollListener();
};
const unbind = () => {
unbindDocumentClickListener();
unbindWindowResizeListener();
unbindWindowOrientationChangeListener();
unbindOverlayScrollListener();
};
React.useEffect(() => {
if (when) {
targetRef.current = DomHandler.getTargetElement(target);
overlayRef.current = DomHandler.getTargetElement(overlay);
} else {
unbind();
targetRef.current = overlayRef.current = null;
}
}, [target, overlay, when]);
React.useEffect(() => {
unbind();
}, [when]);
useUnmountEffect(() => {
unbind();
});
return [bind, unbind];
};
/* eslint-enable */