Repository: wagtail/wagtail
File: client/src/controllers/KeyboardController.ts (TypeScript)

Code before:
 *   <button type="button" id="my-button" data-w-kbd-target="element">My Button</button>
 * </section>
 * ```
 */
export class KeyboardController extends Controller<
  HTMLButtonElement | HTMLAnchorElement
> {
  static targets = ['element'];

  static values = {
    key: { default: '', type: String },
    scope: { default: '', type: String },
    action: { default: KeyboardAction.CLICK, type: String },
  };

  /** Keyboard shortcut string. */
  declare keyValue: string;
  /** Scope of the keyboard shortcut, defaults to the normal MouseTrap (non-input) scope. */
  declare scopeValue: '' | 'global';

  /** Allow an explicit target to be the element that the keyboard activates instead of the controlled element. */
  declare readonly elementTargets: (
    | HTMLButtonElement
    | HTMLAnchorElement
    | HTMLInputElement
  )[];

  /** The action to perform when the keyboard shortcut is triggered, defaults to `"click"`. */
  declare actionValue: KeyboardAction;

  /**
   * If custom keyboard shortcuts are disabled by user in settings then controller will not be loaded.
   */
  static get shouldLoad() {
    return !!WAGTAIL_CONFIG.KEYBOARD_SHORTCUTS_ENABLED;
  }

  /**
   * Set up the handleKey binding and check for an aria-keyshortcuts attribute to
   * use as a fallback if the key value is not set.
   */
  initialize() {
    this.handleKey = this.handleKey.bind(this);

    if (!this.keyValue) {
      const ariaKeyShortcuts = [...this.elementTargets, this.element]
        .find((element) => element.hasAttribute('aria-keyshortcuts'))
        ?.getAttribute('aria-keyshortcuts');

      if (ariaKeyShortcuts) {
        this.keyValue = ariaKeyShortcuts;

Review comment (suggestion):
We no longer need this change, let's just make it simple and use `HTMLElement`. I can do this when merging.

Code after:
 *   <button type="button" id="my-button" data-w-kbd-target="element">My Button</button>
 * </section>
 * ```
 *
 * @example - trigger a focus instead of a click
 * ```html
 * <input type="text" data-controller="w-kbd" data-w-kbd-action-value="focus" data-w-kbd-key-value="x">
 *   Focus on this input with the <kbd>x</kbd> key.
 * </input>
 * ```
 */
export class KeyboardController extends Controller<
  HTMLButtonElement | HTMLAnchorElement
> {
  static targets = ['element'];

  static values = {
    action: { default: '', type: String },
    key: { default: '', type: String },
    scope: { default: '', type: String },
  };

  /** The action to perform when the keyboard shortcut is triggered, uses `"click"` if not defined. */
  declare actionValue: KeyboardAction;
  /** Keyboard shortcut string. */
  declare keyValue: string;
  /** Scope of the keyboard shortcut, defaults to the normal MouseTrap (non-input) scope. */
  declare scopeValue: '' | 'global';

  /** Allow an explicit target to be the element that the keyboard activates instead of the controlled element. */
  declare readonly elementTargets: HTMLElement[];

  /**
   * If custom keyboard shortcuts are disabled by user in settings then controller will not be loaded.
   */
  static get shouldLoad() {
    return !!WAGTAIL_CONFIG.KEYBOARD_SHORTCUTS_ENABLED;
  }

  /**
   * Set up the handleKey binding and check for an aria-keyshortcuts attribute to
   * use as a fallback if the key value is not set.
   */
  initialize() {
    this.handleKey = this.handleKey.bind(this);

    if (!this.keyValue) {
      const ariaKeyShortcuts = [...this.elementTargets, this.element]
        .find((element) => element.hasAttribute('aria-keyshortcuts'))
        ?.getAttribute('aria-keyshortcuts');