mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
Some checks failed
Auto release excalidraw next / Auto-release-excalidraw-next (push) Failing after 2m36s
Build Docker image / build-docker (push) Failing after 6s
Cancel previous runs / cancel (push) Failing after 1s
Publish Docker / publish-docker (push) Failing after 31s
New Sentry production release / sentry (push) Failing after 2m3s
151 lines
3.8 KiB
TypeScript
151 lines
3.8 KiB
TypeScript
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;
|