kbind
Version:
Library for working with keybinds
294 lines (293 loc) • 13.4 kB
TypeScript
import { default as AnyOrderArray } from './types/AnyOrderArray';
import { default as Handler } from './types/Handler';
import { modifierKeys, primaryKeys } from './data';
import { default as Key } from './enums/Key';
import { default as EnumValuesToValues } from './types/EnumValuesToValues';
import { default as EnumValueToValue } from './types/EnumValueToValue';
/**
* KeyBinder class provides functionality to manage keyboard event listeners,
* layers, and modifier keys. It allows registering and unregistering listeners
* and layers, handling key events, and validating events based on custom
* validators.
*/
declare class KeyBinder {
private static state;
/**
* An array of event validator functions used to determine the validity of keyboard events.
*
* It's necessary in case you don't want to trigger some listeners under certain conditions,
* e.g. `Ctrl+A` in a text field.
*
* @type {KeyBinder.EventValidator[]}
*/
static eventValidators: KeyBinder.EventValidator[];
/**
* Checks if either the left or right Control key is currently pressed.
*
* @returns {boolean} `true` if either ControlLeft or ControlRight key is pressed,
* otherwise `false`.
*/
static get isControlPressed(): boolean;
/**
* Checks if either the left or right Shift key is currently pressed.
*
* @returns {boolean} `true` if either ShiftLeft or ShiftRight key is pressed,
* otherwise `false`
*/
static get isShiftPressed(): boolean;
/**
* Checks if either the left or right Alt key is currently pressed.
*
* @returns {boolean} `true` if either AltLeft or AltRight key is pressed,
* otherwise `false`.
*/
static get isAltPressed(): boolean;
/**
* Gets the sorted list of layer ids based on their priority.
*
* NOTE: heavy operation, use it wisely.
*
* @returns {string[]} An array of layer IDs sorted in descending order of their priority.
*/
static get layerIds(): string[];
/**
* Gets the sorted list of listener ids based on their priority.
*
* NOTE: heavy operation, use it wisely.
*
* @returns {string[]} An array of listener IDs sorted in descending order of their priority.
*/
static get listenerIds(): string[];
/**
* Gets the highest priority of the layer in the stack.
*
* NOTE: heavy operation, use it wisely.
*
* @returns {number | undefined} The highest priority of the layer in the stack.
*/
static get highestLayerPriority(): number | undefined;
/**
* Mounts the KeyBinder event listeners to the window object.
* This method attaches the following event listeners:
* - 'blur': Calls the `blurHandler` method when the window loses focus.
* - 'keydown': Calls the `keyDownHandler` method when a key is pressed down.
* - 'keyup': Calls the `keyUpHandler` method when a key is released.
*/
static mount(): void;
/**
* Unmounts the KeyBinder by removing event listeners for 'blur', 'keydown', and 'keyup' events.
* This method should be called to clean up event listeners when the KeyBinder is no longer
* needed.
*/
static unmount(): void;
/**
* Handles the blur event by resetting the state of modifier keys.
* This method is called when the window loses focus.
*/
static blurHandler(): void;
/**
* Handles the key down event by processing the key code and updating the state of modifier
* keys.
*
* @param event - The keyboard event triggered by a key press.
*/
static keyDownHandler(event: KeyboardEvent): void;
/**
* Handles the key up event for modifier keys.
*
* @param event - The keyboard event triggered on key up.
*/
static keyUpHandler(event: KeyboardEvent): void;
/**
* Checks if the given key code is a modifier key.
*
* @param key - The key code to check.
* @returns `true` if the key is a modifier key, otherwise `false`.
*/
static isModifierKeyCode(key: string): key is KeyBinder.ModifierKey;
/**
* Checks if the given key code is a primary key.
*
* @param key - The key code to check.
* @returns `true` if the key is a primary key, otherwise `false`.
*/
static isPrimaryKeyCode(key: string): key is KeyBinder.PrimaryKey;
/**
* Converts a given key code to its corresponding key name.
*
* @param key - The key code to convert.
* @returns The key name corresponding to the key code,
* or the key code itself if no key name is found.
*/
static normalizeKey(key: KeyBinder.KeyCode): "Alt" | "AltLeft" | "AltRight" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "ArrowUp" | "Backspace" | "CapsLock" | "ControlLeft" | "ControlRight" | "Delete" | "End" | "Enter" | "Escape" | "Home" | "Insert" | "IntlBackslash" | "IntlRo" | "IntlYen" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12" | "F13" | "F14" | "F15" | "F16" | "F17" | "F18" | "F19" | "F20" | "F21" | "F22" | "F23" | "F24" | "PageUp" | "PageDown" | "Pause" | "ScrollLock" | "Shift" | "ShiftLeft" | "ShiftRight" | "Space" | "Tab" | "`" | "\\" | "[" | "]" | "," | "Ctrl" | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "-" | "=" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "Numpad 0" | "Numpad 1" | "Numpad 2" | "Numpad 3" | "Numpad 4" | "Numpad 5" | "Numpad 6" | "Numpad 7" | "Numpad 8" | "Numpad 9" | "+" | "*" | "/" | "." | "\"" | ";";
/**
* Converts a key binding to an array of key names.
*
* @param keyBind - The key binding to convert.
* @returns An array of key names corresponding to the key binding.
*/
static normalizeKeyBind(keyBind: KeyBinder.KeyBind): ("Alt" | "AltLeft" | "AltRight" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "ArrowUp" | "Backspace" | "CapsLock" | "ControlLeft" | "ControlRight" | "Delete" | "End" | "Enter" | "Escape" | "Home" | "Insert" | "IntlBackslash" | "IntlRo" | "IntlYen" | "F1" | "F2" | "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10" | "F11" | "F12" | "F13" | "F14" | "F15" | "F16" | "F17" | "F18" | "F19" | "F20" | "F21" | "F22" | "F23" | "F24" | "PageUp" | "PageDown" | "Pause" | "ScrollLock" | "Shift" | "ShiftLeft" | "ShiftRight" | "Space" | "Tab" | "`" | "\\" | "[" | "]" | "," | "Ctrl" | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "-" | "=" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "Numpad 0" | "Numpad 1" | "Numpad 2" | "Numpad 3" | "Numpad 4" | "Numpad 5" | "Numpad 6" | "Numpad 7" | "Numpad 8" | "Numpad 9" | "+" | "*" | "/" | "." | "\"" | ";")[];
/**
* Gets the highest priority of the listener in the stack.
*
* NOTE: heavy operation, use it wisely.
*
* @param layerId - The id of the layer to get the highest listener priority from.
* @returns {number | undefined} The highest priority of the listener in the given layer stack.
*/
static getHighestListenerPriority(layerId: KeyBinder.State.Layer.Id): number | undefined;
/**
* Registers a listener with a specified id.
*
* @param id - The unique identifier for the listener.
* @param listener - The listener metadata object containing the callback and other properties.
*/
static registerListener(id: KeyBinder.State.Listener.Id, listener: KeyBinder.State.Listener): void;
/**
* Removes a listener from the state by its unique id.
*
* @param id - The unique identifier for the listener.
*/
static unregisterListener(id: KeyBinder.State.Listener.Id): void;
/**
* Registers a layer with a specified id.
*
* @param id - The unique identifier for the layer.
* @param layer - The layer metadata object containing the priority and propagation properties
*/
static registerLayer(id: KeyBinder.State.Layer.Id, layer: KeyBinder.State.Layer): void;
/**
* Removes a layer from the state by its unique id.
*
* @param id - The unique identifier for the layer.
*/
static unregisterLayer(id: KeyBinder.State.Layer.Id): void;
private static isValidEvent;
private static checkIfBindModifierKeysPressed;
private static findListenerIdByPressedKey;
private static emit;
}
declare namespace KeyBinder {
/**
* Represents a type that corresponds to one of the modifier keys.
*/
type ModifierKey = (typeof modifierKeys)[number];
/**
* Represents a type that corresponds to one of the primary keys.
* Primary keys are the keys that are not modifiers and can be used in key binding.
*/
type PrimaryKey = (typeof primaryKeys)[number];
/**
* Represents a type that corresponds to the keys of the `Key` object.
* This type is used to define all valid key codes that can be used.
*/
type KeyCode = keyof typeof Key;
/**
* Represents a type that corresponds to the key codes that can be used in key binding as
* modifier keys.
*/
type ModifierKeys = [
Key.Control | Key.ControlLeft | Key.ControlRight,
Key.Shift | Key.ShiftLeft | Key.ShiftRight,
Key.Alt | Key.AltLeft | Key.AltRight
];
/**
* A type representing a function that validates a keyboard event.
*
* @callback EventValidator
* @param {KeyboardEvent} event - The keyboard event to validate.
* @returns {boolean} - Returns `true` if the event is valid, otherwise `false`.
*/
type EventValidator = (event: KeyboardEvent) => boolean;
/**
* Represents a key binding that consists of a combination of modifier keys and a primary key.
*/
type KeyBind = [...KeyBind.Modifiers, KeyBind.PressKey];
namespace KeyBind {
/**
* Represents a type that corresponds to the modifier keys that can be used in key binding.
*/
type Modifiers = EnumValuesToValues<AnyOrderArray<ModifierKeys>>;
/**
* Represents a type that corresponds to the primary keys that can be used in key binding.
*/
type PressKey = EnumValueToValue<PrimaryKey>;
}
/**
* Represents the state of the key binder.
*
* @interface State
* @property {ModifierKey[]} modifierKeys - An array of modifier keys currently active.
* @property {Record<State.Listener.Id, State.Listener>} listeners - A record of listeners
* identified by their unique ids.
* @property {Record<State.Layer.Id, State.Layer>} layers - A record of layers identified by
* their unique ids.
*/
interface State {
modifierKeys: ModifierKey[];
listeners: Record<State.Listener.Id, State.Listener>;
layers: Record<State.Layer.Id, State.Layer>;
}
namespace State {
/**
* Represents a layer in the key binding system.
*
* @interface Layer
* @property {number} priority - The priority of the layer. Higher numbers indicate higher
* priority.
* @property {boolean} propagate - Determines whether the key event should propagate to
* lower priority layers.
*/
interface Layer {
priority: number;
propagate: boolean;
}
namespace Layer {
/**
* Represents a unique identifier of the layer as a string.
*/
type Id = string;
}
/**
* Represents a listener in the key binding system.
*
* @interface Listener
*
* @property {Layer.Id} layerId - Optional identifier for the layer
* (default value: `default`).
* @property {number} priority - The priority of the listener.
* @property {KeyBind | null} bind - Optional key binding associated with the listener
* (e.g. `['Control', 'KeyB']`).
* @property {Handler<KeyboardEvent>} handler - Optional handler function for the keyboard
* event. The handler is called when the key binding is pressed.
* @property {Listener.Options} options - Optional additional options for the listener.
*/
interface Listener {
layerId?: Layer.Id;
priority: number;
bind?: KeyBind | null;
handler?: Handler<KeyboardEvent>;
options?: Listener.Options;
}
namespace Listener {
/**
* Represents a unique identifier of the listener as a string.
*/
type Id = string;
/**
* Options for configuring listener key binding behavior.
*
* @interface Options
* @property {boolean} [preventDefault] - If `true`, the default action of the event
* will be prevented.
* @property {boolean} [stopPropagation] - If `true`, the event will not propagate
* further.
*/
interface Options {
preventDefault?: boolean;
stopPropagation?: boolean;
}
}
}
}
export default KeyBinder;