fix: undo/redo action for international keyboard layouts (#8649)
Co-authored-by: Marcel Mraz <marcel@excalidraw.com>
This commit is contained in:
co-authored by
Marcel Mraz
parent
61623bbeba
commit
eb09b48ae6
@@ -1,4 +1,5 @@
|
||||
import { isDarwin } from "./constants";
|
||||
import type { ValueOf } from "./utility-types";
|
||||
|
||||
export const CODES = {
|
||||
EQUAL: "Equal",
|
||||
@@ -20,6 +21,7 @@ export const CODES = {
|
||||
H: "KeyH",
|
||||
V: "KeyV",
|
||||
Z: "KeyZ",
|
||||
Y: "KeyY",
|
||||
R: "KeyR",
|
||||
S: "KeyS",
|
||||
} as const;
|
||||
@@ -83,6 +85,54 @@ export const KEYS = {
|
||||
|
||||
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 ||
|
||||
|
||||
Reference in New Issue
Block a user