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, };
