mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-06-11 09:55:59 +00:00
Guard global shortcut key handling
This commit is contained in:
@@ -19,16 +19,22 @@ interface Shortcut {
|
||||
export function useGlobalShortcuts(shortcuts: Shortcut[]) {
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (typeof event.key !== "string" || event.key.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const meta = event.metaKey || event.ctrlKey;
|
||||
const eventKey = event.key.toLowerCase();
|
||||
|
||||
for (const shortcut of shortcuts) {
|
||||
const shortcutKey = shortcut.key.toLowerCase();
|
||||
if (
|
||||
event.key.toLowerCase() === shortcut.key.toLowerCase() &&
|
||||
eventKey === shortcutKey &&
|
||||
meta === shortcut.meta &&
|
||||
(shortcut.shift ?? false) === event.shiftKey
|
||||
) {
|
||||
// Allow Cmd+K even in inputs (standard command palette behavior)
|
||||
if (shortcut.key !== "k") {
|
||||
if (shortcutKey !== "k") {
|
||||
const target = event.target as HTMLElement;
|
||||
const tag = target.tagName;
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
|
||||
type KeydownHandler = (event: KeyboardEvent) => void;
|
||||
|
||||
async function loadHookWithCapturedHandler() {
|
||||
let cleanup: (() => void) | undefined;
|
||||
let keydownHandler: KeydownHandler | undefined;
|
||||
|
||||
const addEventListener = vi.fn(
|
||||
(type: string, listener: EventListenerOrEventListenerObject) => {
|
||||
if (type === "keydown" && typeof listener === "function") {
|
||||
keydownHandler = listener as KeydownHandler;
|
||||
}
|
||||
},
|
||||
);
|
||||
const removeEventListener = vi.fn();
|
||||
|
||||
vi.resetModules();
|
||||
vi.doMock("react", () => ({
|
||||
useEffect: (effect: () => void | (() => void)) => {
|
||||
const result = effect();
|
||||
cleanup = typeof result === "function" ? result : undefined;
|
||||
},
|
||||
}));
|
||||
vi.stubGlobal("window", { addEventListener, removeEventListener });
|
||||
|
||||
const { useGlobalShortcuts } = await import("@/hooks/use-global-shortcuts");
|
||||
|
||||
return {
|
||||
cleanup: () => cleanup?.(),
|
||||
getKeydownHandler: () => keydownHandler,
|
||||
useGlobalShortcuts,
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.doUnmock("react");
|
||||
vi.unstubAllGlobals();
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("useGlobalShortcuts", () => {
|
||||
test("ignores keydown events without a key", async () => {
|
||||
const action = vi.fn();
|
||||
const { getKeydownHandler, useGlobalShortcuts } =
|
||||
await loadHookWithCapturedHandler();
|
||||
|
||||
useGlobalShortcuts([{ key: "k", meta: true, action }]);
|
||||
|
||||
const keydownHandler = getKeydownHandler();
|
||||
expect(keydownHandler).toBeDefined();
|
||||
expect(() =>
|
||||
keydownHandler?.({
|
||||
ctrlKey: false,
|
||||
metaKey: true,
|
||||
shiftKey: false,
|
||||
} as KeyboardEvent),
|
||||
).not.toThrow();
|
||||
expect(action).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user