web-ui-pack
Version:
Web package with UI elements
48 lines (47 loc) • 1.61 kB
JavaScript
import onEvent from "./onEvent";
let isMouseDown = false;
let rstEvent;
let rstCnt = 0;
const onMouseUp = [];
function setEvent() {
++rstCnt;
if (rstEvent) {
return;
}
const r1 = onEvent(document, "mousedown", ({ button, defaultPrevented }) => (isMouseDown = !button && !defaultPrevented), { passive: true, capture: true });
const r2 = onEvent(document, "click", () => {
onMouseUp.forEach((f) => f());
onMouseUp.length = 0;
isMouseDown = false;
}, { passive: true, capture: true });
rstEvent = () => {
if (--rstCnt === 0) {
onMouseUp.length = 0;
isMouseDown = false;
r1();
r2();
rstEvent = undefined;
}
};
}
export default function onFocusLost(element, listener, options) {
setEvent();
const remove = () => {
element.removeEventListener("focusout", focusout);
rstEvent?.call(element);
};
const focusout = (e, isNext) => {
if (!isNext && isMouseDown) {
onMouseUp.push(() => setTimeout(() => focusout(e, true), options?.debounceMs || 100));
return;
}
const isFocused = (a) => a && (element === a || element.contains(a));
const isStillFocused = e.relatedTarget instanceof Node && isFocused(e.relatedTarget);
if (!isStillFocused && !isFocused(document.activeElement)) {
listener.call(element, e);
options?.once && remove();
}
};
element.addEventListener("focusout", focusout, { passive: true, ...options, once: false });
return remove;
}