Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 83 84 85 86 87 88 89 90 91 92 93 94 95 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 18x 18x 18x 16x 16x 16x 16x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 122x 94x 94x 94x 94x 94x 94x 94x 94x 28x 28x 28x 28x 28x 28x 28x 1x 1x 1x 1x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 122x 22x 22x 21x 21x 122x 122x 1x 1x 1x 1x 1x 17x 17x 17x 17x 31x 31x 31x 31x 31x 31x 31x 12x 12x 31x 17x 1x 1x 1x | import { pipeline } from "@ogre-tools/fp";
import { filter, isString } from "lodash/fp";
import { getInjectable } from "@ogre-tools/injectable";
import {
Binding,
KeyboardShortcut,
keyboardShortcutInjectionToken,
} from "./keyboard-shortcut-injection-token";
import platformInjectable from "./platform.injectable";
export type InvokeShortcut = (event: KeyboardEvent) => void;
const toShortcutsWithMatchingScope = (shortcut: KeyboardShortcut) => {
const activeScopeElement = document.activeElement?.closest("[data-keyboard-shortcut-scope]");
if (!activeScopeElement) {
const shortcutIsRootLevel = !shortcut.scope;
return shortcutIsRootLevel;
}
const castedActiveScopeElementHtml = activeScopeElement as HTMLDivElement;
// eslint-disable-next-line xss/no-mixed-html
const activeScope = castedActiveScopeElementHtml.dataset.keyboardShortcutScope;
return shortcut.scope === activeScope;
};
const toBindingWithDefaults = (binding: Binding) =>
isString(binding)
? {
code: binding,
shift: false,
ctrl: false,
altOrOption: false,
meta: false,
ctrlOrCommand: false,
}
: {
ctrl: false,
shift: false,
altOrOption: false,
meta: false,
ctrlOrCommand: false,
...binding,
};
const toShortcutsWithMatchingBinding =
(event: KeyboardEvent, platform: string) => (shortcut: KeyboardShortcut) => {
const binding = toBindingWithDefaults(shortcut.binding);
const shiftModifierMatches = binding.shift === event.shiftKey;
const altModifierMatches = binding.altOrOption === event.altKey;
const isMac = platform === "darwin";
const ctrlModifierMatches =
binding.ctrl === event.ctrlKey || (!isMac && binding.ctrlOrCommand === event.ctrlKey);
const metaModifierMatches =
binding.meta === event.metaKey || (isMac && binding.ctrlOrCommand === event.metaKey);
return (
event.code === binding.code &&
shiftModifierMatches &&
ctrlModifierMatches &&
altModifierMatches &&
metaModifierMatches
);
};
const invokeShortcutInjectable = getInjectable({
id: "invoke-shortcut",
instantiate: (di): InvokeShortcut => {
const getShortcuts = () => di.injectMany(keyboardShortcutInjectionToken);
const platform = di.inject(platformInjectable);
return (event) => {
const shortcutsToInvoke = pipeline(
getShortcuts(),
filter(toShortcutsWithMatchingBinding(event, platform)),
filter(toShortcutsWithMatchingScope),
);
if (shortcutsToInvoke.length) {
shortcutsToInvoke.forEach((shortcut) => shortcut.invoke());
}
};
},
});
export default invokeShortcutInjectable;
|