ahooks
Version:
react hooks library
45 lines (44 loc) • 1.81 kB
JavaScript
import useLatest from '../useLatest';
import { getTargetElement } from '../utils/domTarget';
import getDocumentOrShadow from '../utils/getDocumentOrShadow';
import useEffectWithTarget from '../utils/useEffectWithTarget';
const normalizeOptions = (options) => {
var _a, _b;
if (typeof options === 'string' || Array.isArray(options)) {
return { eventName: options, enabled: true };
}
return {
eventName: (_a = options.eventName) !== null && _a !== void 0 ? _a : 'click',
enabled: (_b = options.enabled) !== null && _b !== void 0 ? _b : true,
};
};
const useClickAway = (onClickAway, target, eventNameOrOptions = 'click') => {
const onClickAwayRef = useLatest(onClickAway);
const { eventName, enabled } = normalizeOptions(eventNameOrOptions);
useEffectWithTarget(() => {
if (!enabled) {
return;
}
const handler = (event) => {
const targets = Array.isArray(target) ? target : [target];
if (targets.some((item) => {
const targetElement = getTargetElement(item);
return !targetElement || targetElement.contains(event.target);
})) {
return;
}
onClickAwayRef.current(event);
};
const documentOrShadow = getDocumentOrShadow(target);
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
eventNames.forEach((event) => {
documentOrShadow.addEventListener(event, handler);
});
return () => {
eventNames.forEach((event) => {
documentOrShadow.removeEventListener(event, handler);
});
};
}, [...(Array.isArray(eventName) ? eventName : [eventName]), enabled], target);
};
export default useClickAway;