fvtt-types
Version:
TypeScript type definitions for Foundry VTT
434 lines (356 loc) • 17.1 kB
text/typescript
import type { Brand, Identity, InexactPartial } from "#utils";
import type KeyboardManager from "./keyboard-manager.d.mts";
/**
* A class responsible for managing defined game keybinding.
* Each keybinding is a string key/value pair belonging to a certain namespace and a certain store scope.
*
* When Foundry Virtual Tabletop is initialized, a singleton instance of this class is constructed within the global
* Game object as as game.keybindings.
*
* @see {@linkcode foundry.Game.keybindings | Game#keybindings}
* @see {@linkcode foundry.applications.sidebar.apps.ControlsConfig | ControlsConfig}
*/
declare class ClientKeybindings {
constructor();
/** Registered Keybinding actions */
actions: Map<`${string}.${string}`, ClientKeybindings.StoredKeybindingActionConfig>;
/** A mapping of a string key to possible Actions that might execute off it */
activeKeys: Map<string, ClientKeybindings.KeybindingAction[]>;
/**
* A stored cache of Keybind Actions Ids to Bindings
* @remarks This is only undefined before the "ready" hook.
*/
bindings: Map<string, ClientKeybindings.StoredKeybindingActionBinding[]> | undefined;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _registered: never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _moveTime: never;
static MOVEMENT_DIRECTIONS: ClientKeybindings.MovementDirections;
static ZOOM_DIRECTIONS: ClientKeybindings.ZoomDirections;
/**
* An alias of the movement key set tracked by the keyboard
*/
get moveKeys(): Set<string>;
/**
* Initializes the keybinding values for all registered actions
* @remarks Called just after the `setup` hook, and every time the `core.keybindings` setting changes
*/
initialize(): void;
/**
* Register a new keybinding
*
* @param namespace - The namespace the Keybinding Action belongs to
* @param action - A unique machine-readable id for the Keybinding Action
* @param data - Configuration for keybinding data
*
* @example Define a keybinding which shows a notification
* ```typescript
* game.keybindings.register("myModule", "showNotification", {
* name: "My Settings Keybinding",
* hint: "A description of what will occur when the Keybinding is executed.",
* uneditable: [
* {
* key: "Digit1",
* modifiers: ["Control"]
* }
* ],
* editable: [
* {
* key: "F1"
* }
* ],
* onDown: () => { ui.notifications.info("Pressed!") },
* onUp: () => {},
* restricted: true, // Restrict this Keybinding to gamemaster only?
* reservedModifiers: ["Alt"], // If the ALT modifier is pressed, the notification is permanent instead of temporary
* precedence: CONST.KEYBINDING_PRECEDENCE.NORMAL
* }
* ```
* @remarks
* @throws if called after `this.bindings` has been initialized.
*/
register(namespace: string, action: string, data: ClientKeybindings.KeybindingActionConfig): void;
/**
* Get the current Bindings of a given namespace's Keybinding Action
*
* @param namespace - The namespace under which the setting is registered
* @param action - The keybind action to retrieve
*
* @example Retrieve the current Keybinding Action Bindings
* ```typescript
* game.keybindings.get("myModule", "showNotification");
* ```
*/
get(namespace: string, action: string): ClientKeybindings.StoredKeybindingActionBinding[];
/**
* Set the editable Bindings of a Keybinding Action for a certain namespace and Action
*
* @param namespace - The namespace under which the Keybinding is registered
* @param action - The Keybinding action to set
* @param bindings - The Bindings to assign to the Keybinding
*
* @example Update the current value of a keybinding
* ```typescript
* game.keybindings.set("myModule", "showNotification", [
* {
* key: "F2",
* modifiers: [ "CONTROL" ]
* }
* ]);
* ```
* @remarks Passing `undefined` or nothing as `bindings` deletes stored values for this key, effectively resetting to the values provided at registration
*/
set(namespace: string, action: string, bindings?: ClientKeybindings.KeybindingActionBinding[]): Promise<void>;
/** Reset all client keybindings back to their default configuration. */
resetDefaults(): Promise<void>;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _validateBindings(values: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _validateModifiers(keys: never): never;
/**
* Compares two Keybinding Actions based on their Order
* @param a - The first Keybinding Action
* @param b - the second Keybinding Action
* @internal
*/
protected static _compareActions(
a: ClientKeybindings.ActionComparison,
b: ClientKeybindings.ActionComparison,
): number;
/**
* Register core keybindings.
* @param view - The active game view
*/
protected _registerCoreKeybindings(view: foundry.Game.View): void;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onSelectAllObjects(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onCycleView(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onDismiss(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onToggleCharacterSheet(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onTarget(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _handleMovement(context: never, layer: never): never;
/** @deprecated Removed in v13 (this warning will be removed in v14) */
protected static _onMeasuredRulerMovement(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onPause(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onHighlight(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected _onPan(context: never, movementDirections: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onMacroExecute(context: never, number: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onMacroPageSwap(context: never, page: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onCopy(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onPaste(context: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onUndo(context: never): never;
/** @deprecated Removed in v13 (this warning will be removed in v14) */
protected static _onZoom(context: never, zoomDirection: never): never;
/** @deprecated Made hard private in v13 (this warning will be removed in v14) */
protected static _onFocusChat(context: never): never;
#ClientKeybindings: true;
}
declare namespace ClientKeybindings {
interface Any extends AnyClientKeybindings {}
interface AnyConstructor extends Identity<typeof AnyClientKeybindings> {}
/**
* Properties of {@linkcode StoredKeybindActionConfig} that are neither computed nor provided defaults by {@linkcode ClientKeybindings.register | #register}
* @internal
*/
type _KeybindActionConfigOptional = InexactPartial<{
/** An additional human readable hint */
hint: string;
/**
* A function to execute when a key down event occurs. If True is returned, the event is consumed and no further keybinds execute.
* @remarks Not passing at least one of `onUp` or `onDown` will lead to a fairly useless keybinding
*/
onDown: (ctx: KeyboardManager.KeyboardEventContext) => boolean | void;
/**
* A function to execute when a key up event occurs. If True is returned, the event is consumed and no further keybinds execute.
* @remarks Not passing at least one of `onUp` or `onDown` will lead to a fairly useless keybinding
*/
onUp: (ctx: KeyboardManager.KeyboardEventContext) => boolean | void;
/** If true, only a GM can edit and execute this Action */
restricted: boolean;
}>;
/**
* A Client Keybinding Action Configuration
* @remarks The shape of stored ({@linkcode ClientKeybindings.actions | #actions}) action configs, after defaults provided by
* {@linkcode ClientKeybindings.register | #register} are applied.
*/
interface StoredKeybindingActionConfig extends _KeybindActionConfigOptional {
/**
* The namespace within which the action was registered
* @remarks e.g `"core"`, `"my-package"`
*
* Not included in {@linkcode KeybindActionConfig}, as it's separated out into the first argument of {@linkcode ClientKeybindings.register | #register}
*/
namespace: string;
/** The human readable name */
name: string;
/**
* The default bindings that can never be changed nor removed.
* @defaultValue `[]`
* @remarks The output of `ClientSettings##validateBindings`, run on either the value provided to {@linkcode ClientKeybindings.register | #register},
* or `[]` if none
*/
uneditable: KeybindingActionBinding[];
/**
* The default bindings that can be changed by the user.
* @defaultValue `[]`
* @remarks The output of `ClientSettings##validateBindings`, run on either the value provided to {@linkcode ClientKeybindings.register | #register},
* or `[]` if none
*/
editable: KeybindingActionBinding[];
/**
* If True, allows Repeat events to execute the Action's onDown. Defaults to false.
* @defaultValue `false`
*/
repeat: boolean;
/**
* Modifiers such as [ "CONTROL" ] that can be also pressed when executing this Action. Prevents using one of these modifiers as a Binding.
* @defaultValue `[]`
* @remarks The output of `ClientSettings##validateModifiers`, run on either the value provided to {@linkcode ClientKeybindings.register | #register},
* or `[]` if none
*/
reservedModifiers: string[];
/**
* The preferred precedence of running this Keybinding Action
* @defaultValue {@linkcode CONST.KEYBINDING_PRECEDENCE.NORMAL}
*/
precedence: CONST.KEYBINDING_PRECEDENCE;
/**
* The recorded registration order of the action
* @remarks Always computed by {@linkcode ClientKeybindings.register | #register}; not included in {@linkcode KeybindActionConfig}
*/
order: number;
}
/**
* Omitted fields are overwritten by {@link ClientKeybindings.register | #register} regardless of passed values
* @internal
*/
type _PassableKeybindingActionConfig = Omit<StoredKeybindingActionConfig, "namespace" | "order">;
/** @internal */
type _KeybindingActionConfig = Pick<_PassableKeybindingActionConfig, "name"> &
InexactPartial<Pick<_PassableKeybindingActionConfig, Exclude<keyof _PassableKeybindingActionConfig, "name">>>;
/**
* The interface to be passed to {@link ClientKeybindings.register | #register}. `name` is always required.
*/
interface KeybindingActionConfig extends _KeybindingActionConfig {}
/** @internal */
type _StoredKeybindingActionBindingComputed = InexactPartial<{
/**
* A numeric index which tracks this bindings position during form rendering
* @remarks Appears to never exist on stored bindings in {@linkcode ClientKeybindings.bindings | ClientKeybindings#bindings},
* only existing on values in the `ControlsConfig##pendingEdits` private Map during a binding setting operation in the UI
*/
index: number;
}>;
interface StoredKeybindingActionBinding extends _StoredKeybindingActionBindingComputed {
/**
* The {@linkcode KeyboardEvent.code | KeyboardEvent#code} value from {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values}
* @remarks Registration will throw if one of {@linkcode KeyboardManager.PROTECTED_KEYS} is passed
*/
key: string;
/**
* The Keyboard logical code if universal mode is enable (it is code otherwise)
* @remarks Foundry marks this property as required but based upon actual usage it is not.
*/
logicalKey?: string | undefined;
/**
* An array of modifiers keys from {@linkcode KeyboardManager.MODIFIER_KEYS} which are required for this binding to be activated
* @defaultValue `[]`
* @remarks Always provided by `ClientKeybindings##validateBindings`, which calls `##validateModifiers` with an `?? []` default
*
* The `keyof ... ` (UPPERCASE values) part of this union has a "For backwards compatibility" comment attached by foundry; no deprecation warning or `until` provided
*/
modifiers: (KeyboardManager.MODIFIER_KEYS | keyof KeyboardManager.ModifierKeys)[];
}
/**
* See {@linkcode _StoredKeybindingActionBindingComputed.index}
* @internal
*/
interface _PassableActionBinding extends Omit<StoredKeybindingActionBinding, "index"> {}
/**
* `modifiers` is optional because `##validateModifiers` is always called with a `?? []` default
* @internal
*/
type _KeybindingActionBinding = Pick<_PassableActionBinding, "key" | "logicalKey"> &
InexactPartial<Pick<_PassableActionBinding, Exclude<keyof _PassableActionBinding, "key" | "logicalKey">>>;
/**
* A Client Keybinding Action Binding
* @remarks The type passed to {@linkcode ClientKeybindings.set | ClientKeybindings#set}. All properties are optional except for `key`
*/
interface KeybindingActionBinding extends _KeybindingActionBinding {}
/**
* An action that can occur when a key is pressed
* @remarks This is the type generated by {@linkcode ClientKeybindings.initialize | ClientKeybindings#initialize} from registered
* {@linkcode ClientKeybindings.actions | actions}, and put into the {@linkcode ClientKeybindings.activeKeys | ClientKeybindings#activeKeys}
* array for its `key`.
*
* All keys are required because they are all provided by `#initialize`, but keys that are neither computed there nor provided defaults by
* {@linkcode ClientKeybindings.register | ClientKeybindings#register} are `| undefined`
*/
interface KeybindingAction {
/**
* The namespaced machine identifier of the Action
* @remarks e.g `"core.target"`, `"my-package.my-action"`
*/
action: string;
/**
* The Keyboard key
* @remarks e.g `"KeyA"`, `"CapsLock"`
*/
key: string;
/** The human readable name */
name: string;
/** Required modifiers */
requiredModifiers: KeyboardManager.MODIFIER_KEYS[];
/** Optional (reserved) modifiers */
optionalModifiers: KeyboardManager.MODIFIER_KEYS[];
/** The handler that executes onDown */
onDown: ((ctx: KeyboardManager.KeyboardEventContext) => boolean | void) | undefined;
/** The handler that executes onUp */
onUp: ((ctx: KeyboardManager.KeyboardEventContext) => boolean | void) | undefined;
/** If True, allows Repeat events to execute this Action's onDown */
repeat: boolean;
/** If true, only a GM can execute this Action */
restricted: boolean | undefined;
/** The registration precedence */
precedence: number;
/** The registration order */
order: number;
}
/**
* @remarks The only two properties that {@linkcode ClientKeybindings._compareActions} care about.
* Its JSDoc provides this type as an anonymous inline `Pick`, but in actual use it's always passed
* full {@linkcode KeybindingAction}s, so it's somewhat redundant.
*/
interface ActionComparison extends Pick<KeybindingAction, "precedence" | "order"> {}
type MOVEMENT_DIRECTIONS = Brand<string, "ClientKeybindings.MOVEMENT_DIRECTIONS">;
interface MovementDirections {
UP: "up" & MOVEMENT_DIRECTIONS;
LEFT: "left" & MOVEMENT_DIRECTIONS;
DOWN: "down" & MOVEMENT_DIRECTIONS;
RIGHT: "right" & MOVEMENT_DIRECTIONS;
DESCEND: "descend" & MOVEMENT_DIRECTIONS;
ASCEND: "ascend" & MOVEMENT_DIRECTIONS;
}
type ZOOM_DIRECTIONS = Brand<string, "ClientKeybindings.ZOOM_DIRECTIONS">;
interface ZoomDirections {
IN: "in" & ZOOM_DIRECTIONS;
OUT: "out" & ZOOM_DIRECTIONS;
}
}
export default ClientKeybindings;
declare abstract class AnyClientKeybindings extends ClientKeybindings {
constructor(...args: never);
}