@wordpress/compose
Version:
WordPress higher-order components (HOCs).
77 lines (76 loc) • 2.32 kB
JavaScript
// packages/compose/src/hooks/use-focus-outside/index.ts
import { useCallback, useEffect, useRef } from "@wordpress/element";
var INPUT_BUTTON_TYPES = ["button", "submit"];
function isFocusNormalizedButton(eventTarget) {
if (!(eventTarget instanceof window.HTMLElement)) {
return false;
}
switch (eventTarget.nodeName) {
case "A":
case "BUTTON":
return true;
case "INPUT":
return INPUT_BUTTON_TYPES.includes(
eventTarget.type
);
}
return false;
}
function useFocusOutside(onFocusOutside) {
const currentOnFocusOutsideRef = useRef(onFocusOutside);
useEffect(() => {
currentOnFocusOutsideRef.current = onFocusOutside;
}, [onFocusOutside]);
const preventBlurCheckRef = useRef(false);
const blurCheckTimeoutIdRef = useRef();
const cancelBlurCheck = useCallback(() => {
clearTimeout(blurCheckTimeoutIdRef.current);
}, []);
useEffect(() => {
if (!onFocusOutside) {
cancelBlurCheck();
}
}, [onFocusOutside, cancelBlurCheck]);
const normalizeButtonFocus = useCallback((event) => {
const { type, target } = event;
const isInteractionEnd = ["mouseup", "touchend"].includes(type);
if (isInteractionEnd) {
preventBlurCheckRef.current = false;
} else if (isFocusNormalizedButton(target)) {
preventBlurCheckRef.current = true;
}
}, []);
const queueBlurCheck = useCallback((event) => {
event.persist();
if (preventBlurCheckRef.current) {
return;
}
const ignoreForRelatedTarget = event.target.getAttribute(
"data-unstable-ignore-focus-outside-for-relatedtarget"
);
if (ignoreForRelatedTarget && event.relatedTarget?.closest(ignoreForRelatedTarget)) {
return;
}
blurCheckTimeoutIdRef.current = setTimeout(() => {
if (!document.hasFocus()) {
event.preventDefault();
return;
}
if ("function" === typeof currentOnFocusOutsideRef.current) {
currentOnFocusOutsideRef.current(event);
}
}, 0);
}, []);
return {
onFocus: cancelBlurCheck,
onMouseDown: normalizeButtonFocus,
onMouseUp: normalizeButtonFocus,
onTouchStart: normalizeButtonFocus,
onTouchEnd: normalizeButtonFocus,
onBlur: queueBlurCheck
};
}
export {
useFocusOutside as default
};
//# sourceMappingURL=index.js.map