fvtt-types
Version:
TypeScript type definitions for Foundry VTT
332 lines (276 loc) • 10.4 kB
text/typescript
import type { Brand, Identity, InexactPartial } from "#utils";
import type ClientKeybindings from "./client-keybindings.mjs";
/**
* A set of helpers and management functions for dealing with user input from keyboard events.
* {@link https://keycode.info/}
* @see {@linkcode foundry.Game.keyboard | Game#keyboard}
*/
declare class KeyboardManager {
/**
* @remarks
* @throws If `game.keyboard` is already initialized
*/
constructor();
/**
* Begin listening to keyboard events.
*/
protected _activateListeners(): void;
/**
* The set of key codes which are currently depressed (down)
*/
downKeys: Set<string>;
/**
* The set of movement keys which were recently pressed
*/
moveKeys: Set<string>;
/**
* Is logical keybindings active?
*/
static get isUniversalMode(): boolean;
/**
* Allowed modifier keys
*/
static MODIFIER_KEYS: KeyboardManager.ModifierKeys;
/**
* Track which KeyboardEvent#code presses associate with each modifier
* @defaultValue
* ```js
* {
* Alt: ["AltLeft", "AltRight"];
* Control: ["ControlLeft", "ControlRight", "MetaLeft", "MetaRight", "Meta", "OsLeft", "OsRight"];
* Shift: ["ShiftLeft", "ShiftRight"];
* }
* ```
*/
static MODIFIER_CODES: KeyboardManager.ModifierCodes;
/**
* Key codes which are "protected" and should not be used because they are reserved for browser-level actions.
* @defaultValue `["F5", "F11", "F12", "PrintScreen", "ScrollLock", "NumLock", "CapsLock"]`
*/
static PROTECTED_KEYS: string[];
/**
* The OS-specific string display for what their Command key is
* @defaultValue `navigator.appVersion.includes("Mac") ? "⌘" : "Control"`
*/
static CONTROL_KEY_STRING: string;
/**
* A special mapping of how special KeyboardEvent#code values should map to displayed strings or symbols.
* Values in this configuration object override any other display formatting rules which may be applied.
* @defaultValue
* ```js
* {
* ArrowLeft: "⬅",
* ArrowRight: "➡",
* ArrowUp: "⬆",
* ArrowDown: "⬇",
* Backquote: "`",
* Backslash: "\\",
* BracketLeft: "[",
* BracketRight: "]",
* Comma: ",",
* Control: this.CONTROL_KEY_STRING,
* Equal: "=",
* Meta: isMac ? "⌘" : "⊞",
* MetaLeft: isMac ? "⌘" : "⊞",
* MetaRight: isMac ? "⌘" : "⊞",
* OsLeft: isMac ? "⌘" : "⊞",
* OsRight: isMac ? "⌘" : "⊞",
* Minus: "-",
* NumpadAdd: "Numpad+",
* NumpadSubtract: "Numpad-",
* Period: ".",
* Quote: "'",
* Semicolon: ";",
* Slash: "/"
* }
* ```
*/
static KEYCODE_DISPLAY_MAPPING: Record<string, string>;
/**
* Matches any single graphic Unicode code-point (letters, digits, punctuation, symbols, including emoji).
* Non-printable identifiers like *ArrowLeft*, *ShiftLeft*, *Dead* never match.
*/
static PRINTABLE_CHAR_REGEX: RegExp;
/**
* Canonical identifier for a key press.
*/
static translateKey(event: KeyboardEvent): string;
/**
* Determines whether an `HTMLElement` currently has focus, which may influence keybinding actions.
*
* An element is considered to have focus if:
* 1. It has a `dataset.keyboardFocus` attribute explicitly set to `"true"` or an empty string (`""`).
* 2. It is an `<input>`, `<select>`, or `<textarea>` element, all of which inherently accept keyboard input.
* 3. It has the `isContentEditable` property set to `true`, meaning it is an editable element.
* 4. It is a `<button>` element inside a `<form>`, which suggests interactive use.
*
* An element is considered **not** focused if:
* 1. There is no currently active element (`document.activeElement` is not an `HTMLElement`).
* 2. It has a `dataset.keyboardFocus` attribute explicitly set to `"false"`.
*
* If none of these conditions are met, the element is assumed to be unfocused.
*/
get hasFocus(): boolean;
/**
* Emulates a key being pressed, triggering the Keyboard event workflow.
* @param up - If True, emulates the `keyup` Event. Else, the `keydown` event
* @param code - The {@linkcode KeyboardEvent.code | KeyboardEvent#code} which is being pressed
*/
static emulateKeypress(
up: boolean,
key: string,
options?: KeyboardManager.EmulateKeypressOptions,
): KeyboardManager.KeyboardEventContext;
/**
* Format a KeyboardEvent#code into a displayed string.
* @param code - The input code
* @returns The displayed string for this code
*/
static getKeycodeDisplayString(code: string): string;
/**
* Get a standardized keyboard context for a given event.
* Every individual keypress is uniquely identified using the KeyboardEvent#code property.
* A list of possible key codes is documented here: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
*
* @param event - The originating keypress event
* @param up - A flag for whether the key is down or up (default: `false`)
* @returns The standardized context of the event
*/
static getKeyboardEventContext(event: KeyboardEvent, up?: boolean): KeyboardManager.KeyboardEventContext;
/**
* Report whether a modifier in KeyboardManager.MODIFIER_KEYS is currently actively depressed.
* @param modifier - A modifier in MODIFIER_KEYS
* @returns Is this modifier key currently down (active)?
*/
isModifierActive(modifier: keyof KeyboardManager.ModifierKeys): boolean;
/**
* Report whether a core action key is currently actively depressed.
* @param action - The core action to verify (ex: "target")
* @returns Is this core action key currently down (active)?
*/
isCoreActionKeyActive(action: string): boolean;
/** @deprecated Removed in v13 (this warning will be removed in v14) */
protected static _getContextDisplayString(context: never, includeModifiers: never): never;
/**
* Given a keyboard-event context, return every registered keybinding that matches it (may be empty).
* @internal
*/
protected static _getMatchingActions(
context: KeyboardManager.KeyboardEventContext,
): ClientKeybindings.KeybindingAction[];
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _testContext(action: never, context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _executeKeybind(keybind: never, context: never): never;
/**
* Processes a keyboard event context, checking it against registered keybinding actions
* @param context - The keyboard event context
* @internal
*/
protected _processKeyboardContext(
context: KeyboardManager.KeyboardEventContext,
options?: KeyboardManager.ProcessKeyboardContextOptions,
): void;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _reset(): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _handleKeyboardEvent(event: never, up: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _onCompositionEnd(event: never): never;
/**
* Emulate a key-up event for any currently down keys. When emulating, we go backwards such that combinations such as
* "CONTROL + S" emulate the "S" first in order to capture modifiers.
* @param force - Force the keyup events to be handled.
*/
releaseKeys(options?: KeyboardManager.ReleaseKeysOptions): void;
/**
* Release any down keys when focusing a form element.
* @param event - The focus event.
*/
protected _onFocusIn(event: FocusEvent): void;
#KeyboardManager: true;
}
declare namespace KeyboardManager {
interface Any extends AnyKeyboardManager {}
interface AnyConstructor extends Identity<typeof AnyKeyboardManager> {}
type MODIFIER_KEYS = Brand<string, "KeyboardManager.MODIFIER_KEYS">;
interface ModifierKeys {
CONTROL: "Control" & MODIFIER_KEYS;
SHIFT: "Shift" & MODIFIER_KEYS;
ALT: "Alt" & MODIFIER_KEYS;
}
interface ModifierCodes {
Alt: string[];
Control: string[];
Shift: string[];
}
/** @internal */
type _EmulateKeypressOptions = InexactPartial<{
/**
* Emulate the ALT modifier as pressed
* @defaultValue `false`
*/
altKey: boolean;
/**
* Emulate the CONTROL modifier as pressed
* @defaultValue `false`
*/
ctrlKey: boolean;
/**
* Emulate the SHIFT modifier as pressed
* @defaultValue `false`
*/
shiftKey: boolean;
/**
* Emulate this as a repeat event
* @defaultValue `false`
*/
repeat: boolean;
/**
* Force the event to be handled.
* @defaultValue `false`
*/
force: boolean;
}>;
interface EmulateKeypressOptions extends _EmulateKeypressOptions {}
/**
* Keyboard event context
*/
interface KeyboardEventContext {
/** The normalized string key, such as "KeyA" */
key: string;
/** The logical string key, such as "a" */
logicalKey: string;
/** The originating keypress event */
event: KeyboardEvent;
/** Is the Shift modifier being pressed */
isShift: boolean;
/** Is the Control or Meta modifier being processed */
isControl: boolean;
/** Is the Alt modifier being pressed */
isAlt: boolean;
/** Are any of the modifiers being pressed */
hasModifier: boolean;
/** A list of string modifiers applied to this context, such as ["CONTROL"] */
modifiers: string[];
/** True if the Key is Up, else False if down */
up: boolean;
/** True if the given key is being held down such that it is automatically repeating. */
repeat: boolean;
/** The executing Keybinding Action. May be undefined until the action is known. */
action?: string | undefined;
}
interface ProcessKeyboardContextOptions extends Pick<EmulateKeypressOptions, "force"> {}
type _ReleaseKeysOptions = InexactPartial<{
/**
* Force the keyup events to be handled.
* @defaultValue `true`
*/
force: boolean;
}>;
interface ReleaseKeysOptions extends _ReleaseKeysOptions {}
}
export default KeyboardManager;
declare abstract class AnyKeyboardManager extends KeyboardManager {
constructor(...args: never);
}