Source code for domonic.constants.keyboard

from __future__ import annotations

from typing import ClassVar, Final


class KeyLocation:
    """KeyboardEvent.location constants from the modern UI Events model."""

    STANDARD: ClassVar[int] = 0
    LEFT: ClassVar[int] = 1
    RIGHT: ClassVar[int] = 2
    NUMPAD: ClassVar[int] = 3


class Key:
    """Common KeyboardEvent.key values."""

    ENTER: ClassVar[str] = "Enter"
    TAB: ClassVar[str] = "Tab"
    SPACE: ClassVar[str] = " "
    ESCAPE: ClassVar[str] = "Escape"
    BACKSPACE: ClassVar[str] = "Backspace"
    DELETE: ClassVar[str] = "Delete"
    INSERT: ClassVar[str] = "Insert"
    HOME: ClassVar[str] = "Home"
    END: ClassVar[str] = "End"
    PAGE_UP: ClassVar[str] = "PageUp"
    PAGE_DOWN: ClassVar[str] = "PageDown"
    ARROW_LEFT: ClassVar[str] = "ArrowLeft"
    ARROW_RIGHT: ClassVar[str] = "ArrowRight"
    ARROW_UP: ClassVar[str] = "ArrowUp"
    ARROW_DOWN: ClassVar[str] = "ArrowDown"
    SHIFT: ClassVar[str] = "Shift"
    CONTROL: ClassVar[str] = "Control"
    ALT: ClassVar[str] = "Alt"
    META: ClassVar[str] = "Meta"
    CAPS_LOCK: ClassVar[str] = "CapsLock"
    NUM_LOCK: ClassVar[str] = "NumLock"
    SCROLL_LOCK: ClassVar[str] = "ScrollLock"
    CONTEXT_MENU: ClassVar[str] = "ContextMenu"

    F1: ClassVar[str] = "F1"
    F2: ClassVar[str] = "F2"
    F3: ClassVar[str] = "F3"
    F4: ClassVar[str] = "F4"
    F5: ClassVar[str] = "F5"
    F6: ClassVar[str] = "F6"
    F7: ClassVar[str] = "F7"
    F8: ClassVar[str] = "F8"
    F9: ClassVar[str] = "F9"
    F10: ClassVar[str] = "F10"
    F11: ClassVar[str] = "F11"
    F12: ClassVar[str] = "F12"

    A: ClassVar[str] = "a"
    B: ClassVar[str] = "b"
    C: ClassVar[str] = "c"
    D: ClassVar[str] = "d"
    E: ClassVar[str] = "e"
    F: ClassVar[str] = "f"
    G: ClassVar[str] = "g"
    H: ClassVar[str] = "h"
    I: ClassVar[str] = "i"
    J: ClassVar[str] = "j"
    K: ClassVar[str] = "k"
    L: ClassVar[str] = "l"
    M: ClassVar[str] = "m"
    N: ClassVar[str] = "n"
    O: ClassVar[str] = "o"
    P: ClassVar[str] = "p"
    Q: ClassVar[str] = "q"
    R: ClassVar[str] = "r"
    S: ClassVar[str] = "s"
    T: ClassVar[str] = "t"
    U: ClassVar[str] = "u"
    V: ClassVar[str] = "v"
    W: ClassVar[str] = "w"
    X: ClassVar[str] = "x"
    Y: ClassVar[str] = "y"
    Z: ClassVar[str] = "z"

    DIGIT_0: ClassVar[str] = "0"
    DIGIT_1: ClassVar[str] = "1"
    DIGIT_2: ClassVar[str] = "2"
    DIGIT_3: ClassVar[str] = "3"
    DIGIT_4: ClassVar[str] = "4"
    DIGIT_5: ClassVar[str] = "5"
    DIGIT_6: ClassVar[str] = "6"
    DIGIT_7: ClassVar[str] = "7"
    DIGIT_8: ClassVar[str] = "8"
    DIGIT_9: ClassVar[str] = "9"


class Code:
    """Common KeyboardEvent.code values."""

    ENTER: ClassVar[str] = "Enter"
    TAB: ClassVar[str] = "Tab"
    SPACE: ClassVar[str] = "Space"
    ESCAPE: ClassVar[str] = "Escape"
    BACKSPACE: ClassVar[str] = "Backspace"
    DELETE: ClassVar[str] = "Delete"
    INSERT: ClassVar[str] = "Insert"
    HOME: ClassVar[str] = "Home"
    END: ClassVar[str] = "End"
    PAGE_UP: ClassVar[str] = "PageUp"
    PAGE_DOWN: ClassVar[str] = "PageDown"
    ARROW_LEFT: ClassVar[str] = "ArrowLeft"
    ARROW_RIGHT: ClassVar[str] = "ArrowRight"
    ARROW_UP: ClassVar[str] = "ArrowUp"
    ARROW_DOWN: ClassVar[str] = "ArrowDown"
    SHIFT_LEFT: ClassVar[str] = "ShiftLeft"
    SHIFT_RIGHT: ClassVar[str] = "ShiftRight"
    CONTROL_LEFT: ClassVar[str] = "ControlLeft"
    CONTROL_RIGHT: ClassVar[str] = "ControlRight"
    ALT_LEFT: ClassVar[str] = "AltLeft"
    ALT_RIGHT: ClassVar[str] = "AltRight"
    META_LEFT: ClassVar[str] = "MetaLeft"
    META_RIGHT: ClassVar[str] = "MetaRight"
    CAPS_LOCK: ClassVar[str] = "CapsLock"
    NUM_LOCK: ClassVar[str] = "NumLock"
    SCROLL_LOCK: ClassVar[str] = "ScrollLock"
    CONTEXT_MENU: ClassVar[str] = "ContextMenu"

    F1: ClassVar[str] = "F1"
    F2: ClassVar[str] = "F2"
    F3: ClassVar[str] = "F3"
    F4: ClassVar[str] = "F4"
    F5: ClassVar[str] = "F5"
    F6: ClassVar[str] = "F6"
    F7: ClassVar[str] = "F7"
    F8: ClassVar[str] = "F8"
    F9: ClassVar[str] = "F9"
    F10: ClassVar[str] = "F10"
    F11: ClassVar[str] = "F11"
    F12: ClassVar[str] = "F12"

    KEY_A: ClassVar[str] = "KeyA"
    KEY_B: ClassVar[str] = "KeyB"
    KEY_C: ClassVar[str] = "KeyC"
    KEY_D: ClassVar[str] = "KeyD"
    KEY_E: ClassVar[str] = "KeyE"
    KEY_F: ClassVar[str] = "KeyF"
    KEY_G: ClassVar[str] = "KeyG"
    KEY_H: ClassVar[str] = "KeyH"
    KEY_I: ClassVar[str] = "KeyI"
    KEY_J: ClassVar[str] = "KeyJ"
    KEY_K: ClassVar[str] = "KeyK"
    KEY_L: ClassVar[str] = "KeyL"
    KEY_M: ClassVar[str] = "KeyM"
    KEY_N: ClassVar[str] = "KeyN"
    KEY_O: ClassVar[str] = "KeyO"
    KEY_P: ClassVar[str] = "KeyP"
    KEY_Q: ClassVar[str] = "KeyQ"
    KEY_R: ClassVar[str] = "KeyR"
    KEY_S: ClassVar[str] = "KeyS"
    KEY_T: ClassVar[str] = "KeyT"
    KEY_U: ClassVar[str] = "KeyU"
    KEY_V: ClassVar[str] = "KeyV"
    KEY_W: ClassVar[str] = "KeyW"
    KEY_X: ClassVar[str] = "KeyX"
    KEY_Y: ClassVar[str] = "KeyY"
    KEY_Z: ClassVar[str] = "KeyZ"

    DIGIT_0: ClassVar[str] = "Digit0"
    DIGIT_1: ClassVar[str] = "Digit1"
    DIGIT_2: ClassVar[str] = "Digit2"
    DIGIT_3: ClassVar[str] = "Digit3"
    DIGIT_4: ClassVar[str] = "Digit4"
    DIGIT_5: ClassVar[str] = "Digit5"
    DIGIT_6: ClassVar[str] = "Digit6"
    DIGIT_7: ClassVar[str] = "Digit7"
    DIGIT_8: ClassVar[str] = "Digit8"
    DIGIT_9: ClassVar[str] = "Digit9"

    NUMPAD_0: ClassVar[str] = "Numpad0"
    NUMPAD_1: ClassVar[str] = "Numpad1"
    NUMPAD_2: ClassVar[str] = "Numpad2"
    NUMPAD_3: ClassVar[str] = "Numpad3"
    NUMPAD_4: ClassVar[str] = "Numpad4"
    NUMPAD_5: ClassVar[str] = "Numpad5"
    NUMPAD_6: ClassVar[str] = "Numpad6"
    NUMPAD_7: ClassVar[str] = "Numpad7"
    NUMPAD_8: ClassVar[str] = "Numpad8"
    NUMPAD_9: ClassVar[str] = "Numpad9"
    NUMPAD_ADD: ClassVar[str] = "NumpadAdd"
    NUMPAD_DECIMAL: ClassVar[str] = "NumpadDecimal"
    NUMPAD_DIVIDE: ClassVar[str] = "NumpadDivide"
    NUMPAD_ENTER: ClassVar[str] = "NumpadEnter"
    NUMPAD_MULTIPLY: ClassVar[str] = "NumpadMultiply"
    NUMPAD_SUBTRACT: ClassVar[str] = "NumpadSubtract"


_LEGACY_KEYCODE_TO_KEY: Final[dict[str, str]] = {
    "8": Key.BACKSPACE,
    "9": Key.TAB,
    "13": Key.ENTER,
    "16": Key.SHIFT,
    "17": Key.CONTROL,
    "18": Key.ALT,
    "20": Key.CAPS_LOCK,
    "27": Key.ESCAPE,
    "32": Key.SPACE,
    "33": Key.PAGE_UP,
    "34": Key.PAGE_DOWN,
    "35": Key.END,
    "36": Key.HOME,
    "37": Key.ARROW_LEFT,
    "38": Key.ARROW_UP,
    "39": Key.ARROW_RIGHT,
    "40": Key.ARROW_DOWN,
    "45": Key.INSERT,
    "46": Key.DELETE,
    "91": Key.META,
    "93": Key.CONTEXT_MENU,
    "144": Key.NUM_LOCK,
    "145": Key.SCROLL_LOCK,
}
_LEGACY_KEYCODE_TO_KEY.update({str(48 + i): str(i) for i in range(10)})
_LEGACY_KEYCODE_TO_KEY.update({str(65 + i): chr(97 + i) for i in range(26)})
_LEGACY_KEYCODE_TO_KEY.update({str(111 + i): f"F{i}" for i in range(1, 13)})

_KEY_TO_CODE: Final[dict[str, str]] = {
    Key.ENTER: Code.ENTER,
    Key.TAB: Code.TAB,
    Key.SPACE: Code.SPACE,
    Key.ESCAPE: Code.ESCAPE,
    Key.BACKSPACE: Code.BACKSPACE,
    Key.DELETE: Code.DELETE,
    Key.INSERT: Code.INSERT,
    Key.HOME: Code.HOME,
    Key.END: Code.END,
    Key.PAGE_UP: Code.PAGE_UP,
    Key.PAGE_DOWN: Code.PAGE_DOWN,
    Key.ARROW_LEFT: Code.ARROW_LEFT,
    Key.ARROW_RIGHT: Code.ARROW_RIGHT,
    Key.ARROW_UP: Code.ARROW_UP,
    Key.ARROW_DOWN: Code.ARROW_DOWN,
    Key.SHIFT: Code.SHIFT_LEFT,
    Key.CONTROL: Code.CONTROL_LEFT,
    Key.ALT: Code.ALT_LEFT,
    Key.META: Code.META_LEFT,
    Key.CAPS_LOCK: Code.CAPS_LOCK,
    Key.NUM_LOCK: Code.NUM_LOCK,
    Key.SCROLL_LOCK: Code.SCROLL_LOCK,
    Key.CONTEXT_MENU: Code.CONTEXT_MENU,
}
_KEY_TO_CODE.update({chr(97 + i): f"Key{chr(65 + i)}" for i in range(26)})
_KEY_TO_CODE.update({str(i): f"Digit{i}" for i in range(10)})
_KEY_TO_CODE.update({f"F{i}": f"F{i}" for i in range(1, 13)})

_KEY_TO_LEGACY_KEYCODE: Final[dict[str, int]] = {
    key: int(code) for code, key in _LEGACY_KEYCODE_TO_KEY.items()
}


[docs] class KeyCode: """Legacy KeyboardEvent.keyCode constants kept for compatibility.""" A: ClassVar[str] = "65" B: ClassVar[str] = "66" C: ClassVar[str] = "67" D: ClassVar[str] = "68" E: ClassVar[str] = "69" F: ClassVar[str] = "70" G: ClassVar[str] = "71" H: ClassVar[str] = "72" I: ClassVar[str] = "73" J: ClassVar[str] = "74" K: ClassVar[str] = "75" L: ClassVar[str] = "76" M: ClassVar[str] = "77" N: ClassVar[str] = "78" O: ClassVar[str] = "79" P: ClassVar[str] = "80" Q: ClassVar[str] = "81" R: ClassVar[str] = "82" S: ClassVar[str] = "83" T: ClassVar[str] = "84" U: ClassVar[str] = "85" V: ClassVar[str] = "86" W: ClassVar[str] = "87" X: ClassVar[str] = "88" Y: ClassVar[str] = "89" Z: ClassVar[str] = "90" NUMBER_0: ClassVar[str] = "48" NUMBER_1: ClassVar[str] = "49" NUMBER_2: ClassVar[str] = "50" NUMBER_3: ClassVar[str] = "51" NUMBER_4: ClassVar[str] = "52" NUMBER_5: ClassVar[str] = "53" NUMBER_6: ClassVar[str] = "54" NUMBER_7: ClassVar[str] = "55" NUMBER_8: ClassVar[str] = "56" NUMBER_9: ClassVar[str] = "57" NUMPAD_0: ClassVar[str] = "96" NUMPAD_1: ClassVar[str] = "97" NUMPAD_2: ClassVar[str] = "98" NUMPAD_3: ClassVar[str] = "99" NUMPAD_4: ClassVar[str] = "100" NUMPAD_5: ClassVar[str] = "101" NUMPAD_6: ClassVar[str] = "102" NUMPAD_7: ClassVar[str] = "103" NUMPAD_8: ClassVar[str] = "104" NUMPAD_9: ClassVar[str] = "105" NUMPAD_MULTIPLY: ClassVar[str] = "106" NUMPAD_ADD: ClassVar[str] = "107" NUMPAD_ENTER: ClassVar[str] = "108" NUMPAD_SUBTRACT: ClassVar[str] = "109" NUMPAD_DECIMAL: ClassVar[str] = "110" NUMPAD_DIVIDE: ClassVar[str] = "111" F1: ClassVar[str] = "112" F2: ClassVar[str] = "113" F3: ClassVar[str] = "114" F4: ClassVar[str] = "115" F5: ClassVar[str] = "116" F6: ClassVar[str] = "117" F7: ClassVar[str] = "118" F8: ClassVar[str] = "119" F9: ClassVar[str] = "120" F10: ClassVar[str] = "121" F11: ClassVar[str] = "122" F12: ClassVar[str] = "123" BACKSPACE: ClassVar[str] = "8" TAB: ClassVar[str] = "9" ENTER: ClassVar[str] = "13" SHIFT: ClassVar[str] = "16" CONTROL: ClassVar[str] = "17" ALT: ClassVar[str] = "18" CAPS_LOCK: ClassVar[str] = "20" ESCAPE: ClassVar[str] = "27" SPACE: ClassVar[str] = "32" PAGE_UP: ClassVar[str] = "33" PAGE_DOWN: ClassVar[str] = "34" END: ClassVar[str] = "35" HOME: ClassVar[str] = "36" LEFT: ClassVar[str] = "37" UP: ClassVar[str] = "38" RIGHT: ClassVar[str] = "39" DOWN: ClassVar[str] = "40" INSERT: ClassVar[str] = "45" DELETE: ClassVar[str] = "46" LEFT_COMMAND: ClassVar[str] = "91" RIGHT_COMMAND: ClassVar[str] = "93" WINDOWS: ClassVar[str] = "91" MENU: ClassVar[str] = "93" NUM_LOCK: ClassVar[str] = "144" SCROLL_LOCK: ClassVar[str] = "145" MODIFIER_KEYS: ClassVar[frozenset[str]] = frozenset( {SHIFT, CONTROL, ALT, LEFT_COMMAND, RIGHT_COMMAND, CAPS_LOCK, NUM_LOCK, SCROLL_LOCK} ) @classmethod def is_modifier(cls, key_code: str) -> bool: return key_code in cls.MODIFIER_KEYS @classmethod def to_key(cls, key_code: str | int) -> str | None: return _LEGACY_KEYCODE_TO_KEY.get(str(key_code)) @classmethod def to_code(cls, key_code: str | int) -> str | None: key = cls.to_key(key_code) return _KEY_TO_CODE.get(key) if key is not None else None @classmethod def from_key(cls, key: str) -> int | None: return _KEY_TO_LEGACY_KEYCODE.get(normalize_key(key))
def normalize_key(key: str | None) -> str: """Normalize browser-ish key strings to the modern KeyboardEvent.key form.""" if key in (None, ""): return "" aliases = { "Esc": Key.ESCAPE, "Spacebar": Key.SPACE, "Left": Key.ARROW_LEFT, "Right": Key.ARROW_RIGHT, "Up": Key.ARROW_UP, "Down": Key.ARROW_DOWN, "Del": Key.DELETE, "OS": Key.META, } normalized = aliases.get(key, key) if len(normalized) == 1 and normalized.isalpha(): return normalized.lower() return normalized def normalize_code(code: str | None) -> str: """Normalize shorthand physical key names to KeyboardEvent.code values.""" if code in (None, ""): return "" if len(code) == 1 and code.isalpha(): return f"Key{code.upper()}" if len(code) == 1 and code.isdigit(): return f"Digit{code}" return code __all__ = ["Code", "Key", "KeyCode", "KeyLocation", "normalize_code", "normalize_key"]