You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
success/packages/excalidraw/keys.ts

151 lines
3.8 KiB
TypeScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { isDarwin } from "./constants";
import type { ValueOf } from "./utility-types";
export const CODES = {
EQUAL: "Equal",
MINUS: "Minus",
NUM_ADD: "NumpadAdd",
NUM_SUBTRACT: "NumpadSubtract",
NUM_ZERO: "Numpad0",
BRACKET_RIGHT: "BracketRight",
BRACKET_LEFT: "BracketLeft",
ONE: "Digit1",
TWO: "Digit2",
THREE: "Digit3",
NINE: "Digit9",
QUOTE: "Quote",
ZERO: "Digit0",
SLASH: "Slash",
C: "KeyC",
D: "KeyD",
H: "KeyH",
V: "KeyV",
Z: "KeyZ",
Y: "KeyY",
R: "KeyR",
S: "KeyS",
} as const;
export const KEYS = {
ARROW_DOWN: "ArrowDown",
ARROW_LEFT: "ArrowLeft",
ARROW_RIGHT: "ArrowRight",
ARROW_UP: "ArrowUp",
PAGE_UP: "PageUp",
PAGE_DOWN: "PageDown",
BACKSPACE: "Backspace",
ALT: "Alt",
CTRL_OR_CMD: isDarwin ? "metaKey" : "ctrlKey",
DELETE: "Delete",
ENTER: "Enter",
ESCAPE: "Escape",
QUESTION_MARK: "?",
SPACE: " ",
TAB: "Tab",
CHEVRON_LEFT: "<",
CHEVRON_RIGHT: ">",
PERIOD: ".",
COMMA: ",",
SUBTRACT: "-",
SLASH: "/",
A: "a",
C: "c",
D: "d",
E: "e",
F: "f",
G: "g",
H: "h",
I: "i",
L: "l",
O: "o",
P: "p",
Q: "q",
R: "r",
S: "s",
T: "t",
V: "v",
X: "x",
Y: "y",
Z: "z",
K: "k",
W: "w",
0: "0",
1: "1",
2: "2",
3: "3",
4: "4",
5: "5",
6: "6",
7: "7",
8: "8",
9: "9",
} as const;
export type Key = keyof typeof KEYS;
// defines key code mapping for matching codes as fallback to respective keys on non-latin keyboard layouts
export const KeyCodeMap = new Map<ValueOf<typeof KEYS>, ValueOf<typeof CODES>>([
[KEYS.Z, CODES.Z],
[KEYS.Y, CODES.Y],
]);
export const isLatinChar = (key: string) => /^[a-z]$/.test(key.toLowerCase());
/**
* Used to match key events for any keyboard layout, especially on Windows and Linux,
* where non-latin character with modified (CMD) is not substituted with latin-based alternative.
*
* Uses `event.key` when it's latin, otherwise fallbacks to `event.code` (if mapping exists).
*
* Example of pressing "z" on different layouts, with the chosen key or code highlighted in []:
*
* Layout | Code | Key | Comment
* --------------------- | ----- | --- | -------
* U.S. | KeyZ | [z] |
* Czech | KeyY | [z] |
* Turkish | KeyN | [z] |
* French | KeyW | [z] |
* Macedonian | [KeyZ] | з | z with cmd; з is Cyrillic equivalent of z
* Russian | [KeyZ] | я | z with cmd
* Serbian | [KeyZ] | ѕ | z with cmd
* Greek | [KeyZ] | ζ | z with cmd; also ζ is Greek equivalent of z
* Hebrew | [KeyZ] | ז | z with cmd; also ז is Hebrew equivalent of z
* Pinyin - Simplified | KeyZ | [z] | due to IME
* Cangije - Traditional | [KeyZ] | 重 | z with cmd
* Japanese | [KeyZ] | つ | z with cmd
* 2-Set Korean | [KeyZ] | ㅋ | z with cmd
*
* More details in https://github.com/excalidraw/excalidraw/pull/5944
*/
export const matchKey = (
event: KeyboardEvent | React.KeyboardEvent<Element>,
key: ValueOf<typeof KEYS>,
): boolean => {
// for latin layouts use key
if (key === event.key.toLowerCase()) {
return true;
}
// non-latin layouts fallback to code
const code = KeyCodeMap.get(key);
return Boolean(code && !isLatinChar(event.key) && event.code === code);
};
export const isArrowKey = (key: string) =>
key === KEYS.ARROW_LEFT ||
key === KEYS.ARROW_RIGHT ||
key === KEYS.ARROW_DOWN ||
key === KEYS.ARROW_UP;
export const shouldResizeFromCenter = (event: MouseEvent | KeyboardEvent) =>
event.altKey;
export const shouldMaintainAspectRatio = (event: MouseEvent | KeyboardEvent) =>
event.shiftKey;
export const shouldRotateWithDiscreteAngle = (
event: MouseEvent | KeyboardEvent | React.PointerEvent<HTMLCanvasElement>,
) => event.shiftKey;