@acusti/use-keyboard-events
Version:
React hook that takes keyboard event handlers and attaches them to the document
194 lines (193 loc) • 5.89 kB
JavaScript
import { c } from "react/compiler-runtime";
import { useEffect } from "react";
const handlersData = {
config: /* @__PURE__ */ new Map(),
keydown: [],
keypress: [],
keyup: []
};
const PRIORITY_MIN = -50;
const PRIORITY_MAX = 50;
const PRIORITY_MODIFIER = PRIORITY_MIN * -1;
const noop = () => {
};
function addHandler({
eventType,
handler,
ignoreUsedKeyboardEvents = true,
priority: _priority
}) {
if (!handler) return noop;
const priority = Math.min(PRIORITY_MAX + PRIORITY_MODIFIER, Math.max(0, (_priority ?? 0) + PRIORITY_MODIFIER));
const handlersByPriority = handlersData[eventType];
handlersByPriority[priority] ?? (handlersByPriority[priority] = /* @__PURE__ */ new Set());
handlersByPriority[priority].add(handler);
handlersData.config.set(handler, {
ignoreUsedKeyboardEvents,
priority
});
return () => {
handlersData.config.delete(handler);
if (handlersByPriority[priority] == null) return;
handlersByPriority[priority].delete(handler);
if (!handlersByPriority[priority].size) {
delete handlersByPriority[priority];
for (let index = priority; index > -1 && handlersByPriority[index] == null && handlersByPriority.length === index + 1; index--) {
handlersByPriority.length = index;
}
}
};
}
const IS_APPLE_REGEXP = /mac|iphone|ipad|ipod/i;
function isPrimaryModifierPressed(event) {
var _a;
const platform = ((_a = globalThis.navigator) == null ? void 0 : _a.platform) ?? "";
return IS_APPLE_REGEXP.test(platform) ? event.metaKey : event.ctrlKey;
}
const NON_TEXT_INPUT_TYPES = /* @__PURE__ */ new Set(["button", "checkbox", "color", "file", "hidden", "image", "radio", "range", "reset", "submit"]);
const NON_TEXT_INPUT_USES_KEYS = /* @__PURE__ */ new Set([" ", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowUp", "Enter"]);
const usesKeyEvents = (target) => target.isContentEditable || target.tagName === "TEXTAREA" || target.tagName === "INPUT";
const isEventTargetUsingKeyEvent = (event) => {
const target = event.target;
if (target == null || !usesKeyEvents(target)) return false;
if (target.tagName !== "INPUT") return true;
if (!NON_TEXT_INPUT_TYPES.has(target.type)) return true;
return NON_TEXT_INPUT_USES_KEYS.has(event.key);
};
function addHandlers(doc) {
if (!(doc == null ? void 0 : doc.defaultView) || doc.defaultView.__useKeyboardEventsAttached__) {
return;
}
doc.defaultView.__useKeyboardEventsAttached__ = true;
doc.addEventListener("keydown", handleKeyboardEvent);
doc.addEventListener("keypress", handleKeyboardEvent);
doc.addEventListener("keyup", handleKeyboardEvent);
return () => {
if (doc.defaultView) {
doc.defaultView.__useKeyboardEventsAttached__ = false;
}
doc.removeEventListener("keydown", handleKeyboardEvent);
doc.removeEventListener("keypress", handleKeyboardEvent);
doc.removeEventListener("keyup", handleKeyboardEvent);
};
}
function handleKeyboardEvent(event) {
const eventType = event.type;
const handlersByPriority = handlersData[eventType];
let index = handlersByPriority.length;
const targetUsesKeyEvents = isEventTargetUsingKeyEvent(event);
while (index--) {
const handlers = handlersByPriority[index];
if (handlers != null) {
for (const handler of handlers) {
const config = handlersData.config.get(handler);
if (!targetUsesKeyEvents || (config == null ? void 0 : config.ignoreUsedKeyboardEvents) === false) {
const shouldPropagate = handler(event);
if (shouldPropagate === false) return;
}
}
}
}
}
function useKeyboardEvents(t0) {
const $ = c(16);
const {
ignoreUsedKeyboardEvents,
onKeyDown,
onKeyPress,
onKeyUp,
priority
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = [];
$[0] = t1;
} else {
t1 = $[0];
}
useEffect(_temp2, t1);
let t2;
let t3;
if ($[1] !== ignoreUsedKeyboardEvents || $[2] !== onKeyDown || $[3] !== priority) {
t2 = () => addHandler({
eventType: "keydown",
handler: onKeyDown,
ignoreUsedKeyboardEvents,
priority
});
t3 = [ignoreUsedKeyboardEvents, onKeyDown, priority];
$[1] = ignoreUsedKeyboardEvents;
$[2] = onKeyDown;
$[3] = priority;
$[4] = t2;
$[5] = t3;
} else {
t2 = $[4];
t3 = $[5];
}
useEffect(t2, t3);
let t4;
let t5;
if ($[6] !== ignoreUsedKeyboardEvents || $[7] !== onKeyPress || $[8] !== priority) {
t4 = () => addHandler({
eventType: "keypress",
handler: onKeyPress,
ignoreUsedKeyboardEvents,
priority
});
t5 = [ignoreUsedKeyboardEvents, onKeyPress, priority];
$[6] = ignoreUsedKeyboardEvents;
$[7] = onKeyPress;
$[8] = priority;
$[9] = t4;
$[10] = t5;
} else {
t4 = $[9];
t5 = $[10];
}
useEffect(t4, t5);
let t6;
let t7;
if ($[11] !== ignoreUsedKeyboardEvents || $[12] !== onKeyUp || $[13] !== priority) {
t6 = () => addHandler({
eventType: "keyup",
handler: onKeyUp,
ignoreUsedKeyboardEvents,
priority
});
t7 = [ignoreUsedKeyboardEvents, onKeyUp, priority];
$[11] = ignoreUsedKeyboardEvents;
$[12] = onKeyUp;
$[13] = priority;
$[14] = t6;
$[15] = t7;
} else {
t6 = $[14];
t7 = $[15];
}
useEffect(t6, t7);
}
function _temp2() {
addHandlers(document);
document.querySelectorAll("iframe").forEach(_temp);
}
function _temp(iframe) {
if (!isSameOriginFrame(iframe) || !iframe.contentDocument) {
return;
}
addHandlers(iframe.contentDocument);
}
function isSameOriginFrame(iframe) {
try {
return typeof iframe.contentWindow.location.href === "string";
} catch (err) {
return false;
}
}
export {
useKeyboardEvents as default,
isEventTargetUsingKeyEvent,
isPrimaryModifierPressed,
usesKeyEvents
};
//# sourceMappingURL=useKeyboardEvents.js.map