igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
241 lines (240 loc) • 10.1 kB
TypeScript
import type { ReactiveController, ReactiveControllerHost } from 'lit';
import type { Ref } from 'lit/directives/ref.js';
export declare const arrowLeft: "ArrowLeft";
export declare const arrowRight: "ArrowRight";
export declare const arrowUp: "ArrowUp";
export declare const arrowDown: "ArrowDown";
export declare const enterKey: "Enter";
export declare const spaceBar: " ";
export declare const escapeKey: "Escape";
export declare const homeKey: "Home";
export declare const endKey: "End";
export declare const pageUpKey: "PageUp";
export declare const pageDownKey: "PageDown";
export declare const tabKey: "Tab";
export declare const altKey: "Alt";
export declare const ctrlKey: "Control";
export declare const metaKey: "Meta";
export declare const shiftKey: "Shift";
type KeyBindingHandler = (event: KeyboardEvent) => void;
type KeyBindingObserverCleanup = {
unsubscribe: () => void;
};
/**
* Whether the current event should be ignored by the controller.
*
* @param node - The event target
* @param event - The event object
*
* When `true` is returned, the current event is ignored.
*/
type KeyBindingSkipCallback = (node: Element, event: KeyboardEvent) => boolean;
/**
* The event type which will trigger the bound handler.
*/
type KeyBindingTrigger = 'keydown' | 'keyup';
/**
* Configuration object for the controller.
* @ignore
*/
interface KeyBindingControllerOptions {
/**
* By default, the controller listens for keypress events in the context of the host element.
* If you pass a `ref`, you can limit the observation to a certain DOM part of the host scope.
*/
ref?: Ref;
/**
* Option to ignore key press events.
*
* If passed an array of CSS selectors, it will ignore key presses originating from elements in the event composed path
* that match one of the selectors.
* Otherwise you can pass a {@link KeyBindingSkipCallback} function.
*
* Defaults to `['input', 'textarea', 'select']`.
*
* @example
* ```ts
* {
* // Skip events originating from elements with `readonly` attribute
* skip: ['[readonly]']
* }
* ...
* {
* // Same as above but with a callback
* skip: (node: Element) => node.hasAttribute('readonly')
* }
* ```
*/
skip?: string[] | KeyBindingSkipCallback;
/**
* A set of KeyBindingOptions configuration which is applied to every handler
* that is added to the controller.
*
* Any additional KeyBindingOptions values passed when `set` is called
* will be merged with `bindingDefaults`.
*/
bindingDefaults?: KeyBindingOptions;
}
/**
* Configuration object for customizing the behavior of
* the registered handler.
*/
interface KeyBindingOptions {
/**
* The event type(s) on which the handler will be invoked.
*
* Defaults to `keydown` if not set.
*/
triggers?: KeyBindingTrigger[];
/**
* Whether the handler should fire on auto-repeated keydown events (i.e. when a key is held down).
*
* Defaults to `false`.
*/
repeat?: boolean;
/**
* Whether to call `preventDefault` on the target event before the handler is invoked.
*/
preventDefault?: boolean;
/**
* Whether to call `stopPropagation` on the target event before the handler is invoked.
*/
stopPropagation?: boolean;
}
/**
* Maps internal modifier names to their corresponding `KeyboardEvent` boolean property names.
* Needed because `ctrlKey` in the DOM is the property for the `'control'` modifier (not `'controlKey'`).
*/
export declare const MODIFIER_EVENT_KEYS: Record<string, string>;
/**
* A controller for managing key bindings on a host element. It allows you to register handlers for specific key combinations,
* with support for modifier keys and event options such as `preventDefault` and `stopPropagation`.
*
* The controller listens for keyboard events on the host element (or an optionally specified element) and invokes the appropriate handlers
* when the registered key combinations are detected.
*
*/
declare class KeyBindingController implements ReactiveController {
private static readonly _defaultOptions;
private readonly _host;
private readonly _ref?;
private readonly _abortHandle;
private readonly _bindings;
private readonly _allowedKeys;
private readonly _pressedKeys;
private readonly _options;
private readonly _skipSelector;
private _observedElement?;
private get _element();
constructor(host: ReactiveControllerHost & Element, options?: KeyBindingControllerOptions);
/**
* Applies the event modifiers specified in the binding options to the provided keyboard event.
* If `preventDefault` is set, it calls `event.preventDefault()`.
* If `stopPropagation` is set, it calls `event.stopPropagation()`.
*/
private _applyEventModifiers;
/**
* Determines whether the provided keyboard event matches the specified key binding,
* taking into account the event type and the binding's trigger options.
*/
private _bindingMatches;
/**
* Determines whether the provided event should be ignored based on the controller's configuration and the event's context.
* The method checks if the event's key is among the allowed keys, if the event originated from within the controller's scope,
* and if it matches any of the skip conditions defined in the controller's options.
*/
private _shouldSkip;
/** @internal */
hostConnected(): void;
/** @internal */
hostDisconnected(): void;
/**
* Handles the global blur event to clear the internal state of pressed keys.
*
* This is necessary to prevent "stuck" keys when the user switches to another application
* or tab while holding down a key.
*/
private _handleGlobalBlur;
/**
* Handles keyboard events on the observed element.
*
* It checks if the event should be skipped based on the controller's configuration,
* and if not, it determines if there is a registered handler for the combination of pressed keys and active modifiers.
*
* If a matching handler is found, it applies the specified event modifiers and invokes the handler.
* It also manages the internal state of currently pressed keys to accurately detect key combinations.
*
*/
private _handleKeyEvent;
/** @internal */
handleEvent(event: KeyboardEvent | FocusEvent): void;
/**
* Registers a key binding with the specified key(s), handler function, and optional configuration.
*
* The `key` parameter can be a single key or an array of keys, and can include modifier keys (e.g., 'ctrl+s', ['shift', 'a']).
* The `handler` is a function that will be called when the specified key combination is detected.
* The `bindingOptions` allow you to customize the behavior of the binding, such as which event types trigger the handler,
* whether it should fire on auto-repeated keydown events, and whether to call `preventDefault` or `stopPropagation`.
*
* The method returns the controller instance to allow for method chaining.
*/
set(key: string | string[], handler: KeyBindingHandler, bindingOptions?: KeyBindingOptions): this;
/**
* Registers the provided handler function to be called when either the Enter key or Space bar is pressed.
*
* This is a common pattern for activating buttons or interactive elements, and this method provides a convenient way to set up such bindings.
*
* The method accepts optional `KeyBindingOptions` which are applied to both the Enter key and Space bar bindings.
* It returns the controller instance to allow for method chaining.
*
*/
setActivateHandler(handler: KeyBindingHandler, options?: KeyBindingOptions): this;
/**
* Sets the controller to listen for keyboard events on an arbitrary `element` in the page context.
* All the configuration and event handlers are applied as well.
*
* Returns an object with an `unsubscribe` function which should be called when the observing of keyboard
* events on the `element` should cease.
*/
observeElement(element: Element): KeyBindingObserverCleanup;
}
/**
* Parses the provided key(s) and separates them into modifiers and regular keys.
*
* Modifiers are keys like Alt, Ctrl, Meta and Shift which modify the behavior of other keys when pressed in combination.
* Regular keys are all other keys which trigger the bound handler when pressed.
*
* The returned `keys` and `modifiers` are normalized to lowercase for consistency.
*
* @internal
*
* @param inputKeys - The key or keys to parse, provided as a string or an array of strings.
* @returns An object containing the separated `keys` and `modifiers`.
*/
export declare function parseKeys(inputKeys: string | string[]): {
keys: string[];
modifiers: string[];
};
/**
* Controller factory function which creates a {@link KeyBindingController} instance and attaches it to the provided host.
*
* @param element - The host element to which the controller will be attached.
* @param options - Optional configuration for the controller.
* @returns The created {@link KeyBindingController} instance.
*
* @example
* ```ts
* class MyComponent extends LitElement {
* private _keyBindings = addKeybindings(this, {
* skip: ['input', 'textarea'], // Optional: Skip key events originating from these elements
* bindingDefaults: { preventDefault: true }, // Optional: Default options for all bindings
* });
*
* constructor() {
* super();
* this._keyBindings.set('ctrl+s', this._handleSave); // Register a key binding
* }
* ```
*/
export declare function addKeybindings(element: ReactiveControllerHost & Element, options?: KeyBindingControllerOptions): KeyBindingController;
export type { KeyBindingController, KeyBindingControllerOptions, KeyBindingHandler, KeyBindingObserverCleanup, KeyBindingOptions, KeyBindingSkipCallback, KeyBindingTrigger, };