<!--
@license
Copyright (C) 2016 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<!--

How to Add a Keyboard Shortcut
==============================

A keyboard shortcut is composed of the following parts:

  1. A semantic identifier (e.g. OPEN_CHANGE, NEXT_PAGE)
  2. Documentation for the keyboard shortcut help dialog
  3. A binding between key combos and the semantic identifier
  4. A binding between the semantic identifier and a listener

Parts (1) and (2) for all shortcuts are defined in this file. The semantic
identifier is declared in the Shortcut enum near the head of this script:

  const Shortcut = {
    // ...
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    // ...
  };

Immediately following the Shortcut enum definition, there is a _describe
function defined which is then invoked many times to populate the help dialog.
Add a new invocation here to document the shortcut:

  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');

When an attached view binds one or more key combos to this shortcut, the help
dialog will display this text in the given section (in this case, "Diffs"). See
the ShortcutSection enum immediately below for the list of supported sections.

Part (3), the actual key bindings, are declared by gr-app. In the future, this
system may be expanded to allow key binding customizations by plugins or user
preferences. Key bindings are defined in the following forms:

  // Ordinary shortcut with a single binding.
  this.bindShortcut(
      this.Shortcut.TOGGLE_LEFT_PANE, 'shift+a');

  // Ordinary shortcut with multiple bindings.
  this.bindShortcut(
      this.Shortcut.CURSOR_NEXT_FILE, 'j', 'down');

  // A "go-key" keyboard shortcut, which is combined with a previously and
  // continuously pressed "go" key (the go-key is hard-coded as 'g').
  this.bindShortcut(
      this.Shortcut.GO_TO_OPENED_CHANGES, this.GO_KEY, 'o');

  // A "doc-only" keyboard shortcut. This declares the key-binding for help
  // dialog purposes, but doesn't actually implement the binding. It is up
  // to some element to implement this binding using iron-a11y-keys-behavior's
  // keyBindings property.
  this.bindShortcut(
      this.Shortcut.EXPAND_ALL_COMMENT_THREADS, this.DOC_ONLY, 'e');

Part (4), the listener definitions, are declared by the view or element that
implements the shortcut behavior. This is done by implementing a method named
keyboardShortcuts() in an element that mixes in this behavior, returning an
object that maps semantic identifiers (as property names) to listener method
names, like this:

  keyboardShortcuts() {
    return {
      [this.Shortcut.TOGGLE_LEFT_PANE]: '_handleToggleLeftPane',
    };
  },

You can implement key bindings in an element that is hosted by a view IF that
element is always attached exactly once under that view (e.g. the search bar in
gr-app). When that is not the case, you will have to define a doc-only binding
in gr-app, declare the shortcut in the view that hosts the element, and use
iron-a11y-keys-behavior's keyBindings attribute to implement the binding in the
element. An example of this is in comment threads. A diff view supports actions
on comment threads, but there may be zero or many comment threads attached at
any given point. So the shortcut is declared as doc-only by the diff view and
by gr-app, and actually implemented by gr-comment-thread.

NOTE: doc-only shortcuts will not be customizable in the same way that other
shortcuts are.
-->
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">

<script>
(function(window) {
  'use strict';

  const DOC_ONLY = 'DOC_ONLY';
  const GO_KEY = 'GO_KEY';

  // The maximum age of a keydown event to be used in a jump navigation. This
  // is only for cases when the keyup event is lost.
  const GO_KEY_TIMEOUT_MS = 1000;

  const ShortcutSection = {
    ACTIONS: 'Actions',
    DIFFS: 'Diffs',
    EVERYWHERE: 'Everywhere',
    FILE_LIST: 'File list',
    NAVIGATION: 'Navigation',
    REPLY_DIALOG: 'Reply dialog',
  };

  const Shortcut = {
    OPEN_SHORTCUT_HELP_DIALOG: 'OPEN_SHORTCUT_HELP_DIALOG',
    GO_TO_USER_DASHBOARD: 'GO_TO_USER_DASHBOARD',
    GO_TO_OPENED_CHANGES: 'GO_TO_OPENED_CHANGES',
    GO_TO_MERGED_CHANGES: 'GO_TO_MERGED_CHANGES',
    GO_TO_ABANDONED_CHANGES: 'GO_TO_ABANDONED_CHANGES',
    GO_TO_WATCHED_CHANGES: 'GO_TO_WATCHED_CHANGES',

    CURSOR_NEXT_CHANGE: 'CURSOR_NEXT_CHANGE',
    CURSOR_PREV_CHANGE: 'CURSOR_PREV_CHANGE',
    OPEN_CHANGE: 'OPEN_CHANGE',
    NEXT_PAGE: 'NEXT_PAGE',
    PREV_PAGE: 'PREV_PAGE',
    TOGGLE_CHANGE_REVIEWED: 'TOGGLE_CHANGE_REVIEWED',
    TOGGLE_CHANGE_STAR: 'TOGGLE_CHANGE_STAR',
    REFRESH_CHANGE_LIST: 'REFRESH_CHANGE_LIST',

    OPEN_REPLY_DIALOG: 'OPEN_REPLY_DIALOG',
    OPEN_DOWNLOAD_DIALOG: 'OPEN_DOWNLOAD_DIALOG',
    EXPAND_ALL_MESSAGES: 'EXPAND_ALL_MESSAGES',
    COLLAPSE_ALL_MESSAGES: 'COLLAPSE_ALL_MESSAGES',
    UP_TO_DASHBOARD: 'UP_TO_DASHBOARD',
    UP_TO_CHANGE: 'UP_TO_CHANGE',
    TOGGLE_DIFF_MODE: 'TOGGLE_DIFF_MODE',
    REFRESH_CHANGE: 'REFRESH_CHANGE',
    EDIT_TOPIC: 'EDIT_TOPIC',

    NEXT_LINE: 'NEXT_LINE',
    PREV_LINE: 'PREV_LINE',
    NEXT_CHUNK: 'NEXT_CHUNK',
    PREV_CHUNK: 'PREV_CHUNK',
    EXPAND_ALL_DIFF_CONTEXT: 'EXPAND_ALL_DIFF_CONTEXT',
    NEXT_COMMENT_THREAD: 'NEXT_COMMENT_THREAD',
    PREV_COMMENT_THREAD: 'PREV_COMMENT_THREAD',
    EXPAND_ALL_COMMENT_THREADS: 'EXPAND_ALL_COMMENT_THREADS',
    COLLAPSE_ALL_COMMENT_THREADS: 'COLLAPSE_ALL_COMMENT_THREADS',
    LEFT_PANE: 'LEFT_PANE',
    RIGHT_PANE: 'RIGHT_PANE',
    TOGGLE_LEFT_PANE: 'TOGGLE_LEFT_PANE',
    NEW_COMMENT: 'NEW_COMMENT',
    SAVE_COMMENT: 'SAVE_COMMENT',
    OPEN_DIFF_PREFS: 'OPEN_DIFF_PREFS',
    TOGGLE_DIFF_REVIEWED: 'TOGGLE_DIFF_REVIEWED',

    NEXT_FILE: 'NEXT_FILE',
    PREV_FILE: 'PREV_FILE',
    NEXT_FILE_WITH_COMMENTS: 'NEXT_FILE_WITH_COMMENTS',
    PREV_FILE_WITH_COMMENTS: 'PREV_FILE_WITH_COMMENTS',
    NEXT_UNREVIEWED_FILE: 'NEXT_UNREVIEWED_FILE',
    CURSOR_NEXT_FILE: 'CURSOR_NEXT_FILE',
    CURSOR_PREV_FILE: 'CURSOR_PREV_FILE',
    OPEN_FILE: 'OPEN_FILE',
    TOGGLE_FILE_REVIEWED: 'TOGGLE_FILE_REVIEWED',
    TOGGLE_ALL_INLINE_DIFFS: 'TOGGLE_ALL_INLINE_DIFFS',
    TOGGLE_INLINE_DIFF: 'TOGGLE_INLINE_DIFF',

    OPEN_FIRST_FILE: 'OPEN_FIRST_FILE',
    OPEN_LAST_FILE: 'OPEN_LAST_FILE',

    SEARCH: 'SEARCH',
    SEND_REPLY: 'SEND_REPLY',
  };

  const _help = new Map();

  function _describe(shortcut, section, text) {
    if (!_help.has(section)) {
      _help.set(section, []);
    }
    _help.get(section).push({shortcut, text});
  }

  _describe(Shortcut.SEARCH, ShortcutSection.EVERYWHERE, 'Search');
  _describe(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, ShortcutSection.EVERYWHERE,
      'Show this dialog');
  _describe(Shortcut.GO_TO_USER_DASHBOARD, ShortcutSection.EVERYWHERE,
      'Go to User Dashboard');
  _describe(Shortcut.GO_TO_OPENED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Opened Changes');
  _describe(Shortcut.GO_TO_MERGED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Merged Changes');
  _describe(Shortcut.GO_TO_ABANDONED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Abandoned Changes');
  _describe(Shortcut.GO_TO_WATCHED_CHANGES, ShortcutSection.EVERYWHERE,
      'Go to Watched Changes');

  _describe(Shortcut.CURSOR_NEXT_CHANGE, ShortcutSection.ACTIONS,
      'Select next change');
  _describe(Shortcut.CURSOR_PREV_CHANGE, ShortcutSection.ACTIONS,
      'Select previous change');
  _describe(Shortcut.OPEN_CHANGE, ShortcutSection.ACTIONS,
      'Show selected change');
  _describe(Shortcut.NEXT_PAGE, ShortcutSection.ACTIONS, 'Go to next page');
  _describe(Shortcut.PREV_PAGE, ShortcutSection.ACTIONS, 'Go to previous page');
  _describe(Shortcut.OPEN_REPLY_DIALOG, ShortcutSection.ACTIONS,
      'Open reply dialog to publish comments and add reviewers');
  _describe(Shortcut.OPEN_DOWNLOAD_DIALOG, ShortcutSection.ACTIONS,
      'Open download overlay');
  _describe(Shortcut.EXPAND_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Expand all messages');
  _describe(Shortcut.COLLAPSE_ALL_MESSAGES, ShortcutSection.ACTIONS,
      'Collapse all messages');
  _describe(Shortcut.REFRESH_CHANGE, ShortcutSection.ACTIONS,
      'Reload the change at the latest patch');
  _describe(Shortcut.TOGGLE_CHANGE_REVIEWED, ShortcutSection.ACTIONS,
      'Mark/unmark change as reviewed');
  _describe(Shortcut.TOGGLE_FILE_REVIEWED, ShortcutSection.ACTIONS,
      'Toggle review flag on selected file');
  _describe(Shortcut.REFRESH_CHANGE_LIST, ShortcutSection.ACTIONS,
      'Refresh list of changes');
  _describe(Shortcut.TOGGLE_CHANGE_STAR, ShortcutSection.ACTIONS,
      'Star/unstar change');
  _describe(Shortcut.EDIT_TOPIC, ShortcutSection.ACTIONS,
      'Add a change topic');

  _describe(Shortcut.NEXT_LINE, ShortcutSection.DIFFS, 'Go to next line');
  _describe(Shortcut.PREV_LINE, ShortcutSection.DIFFS, 'Go to previous line');
  _describe(Shortcut.NEXT_CHUNK, ShortcutSection.DIFFS,
      'Go to next diff chunk');
  _describe(Shortcut.PREV_CHUNK, ShortcutSection.DIFFS,
      'Go to previous diff chunk');
  _describe(Shortcut.EXPAND_ALL_DIFF_CONTEXT, ShortcutSection.DIFFS,
      'Expand all diff context');
  _describe(Shortcut.NEXT_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to next comment thread');
  _describe(Shortcut.PREV_COMMENT_THREAD, ShortcutSection.DIFFS,
      'Go to previous comment thread');
  _describe(Shortcut.EXPAND_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Expand all comment threads');
  _describe(Shortcut.COLLAPSE_ALL_COMMENT_THREADS, ShortcutSection.DIFFS,
      'Collapse all comment threads');
  _describe(Shortcut.LEFT_PANE, ShortcutSection.DIFFS, 'Select left pane');
  _describe(Shortcut.RIGHT_PANE, ShortcutSection.DIFFS, 'Select right pane');
  _describe(Shortcut.TOGGLE_LEFT_PANE, ShortcutSection.DIFFS,
      'Hide/show left diff');
  _describe(Shortcut.NEW_COMMENT, ShortcutSection.DIFFS, 'Draft new comment');
  _describe(Shortcut.SAVE_COMMENT, ShortcutSection.DIFFS, 'Save comment');
  _describe(Shortcut.OPEN_DIFF_PREFS, ShortcutSection.DIFFS,
      'Show diff preferences');
  _describe(Shortcut.TOGGLE_DIFF_REVIEWED, ShortcutSection.DIFFS,
      'Mark/unmark file as reviewed');
  _describe(Shortcut.TOGGLE_DIFF_MODE, ShortcutSection.DIFFS,
      'Toggle unified/side-by-side diff');
  _describe(Shortcut.NEXT_UNREVIEWED_FILE, ShortcutSection.DIFFS,
      'Mark file as reviewed and go to next unreviewed file');

  _describe(Shortcut.NEXT_FILE, ShortcutSection.NAVIGATION, 'Select next file');
  _describe(Shortcut.PREV_FILE, ShortcutSection.NAVIGATION,
      'Select previous file');
  _describe(Shortcut.NEXT_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select next file that has comments');
  _describe(Shortcut.PREV_FILE_WITH_COMMENTS, ShortcutSection.NAVIGATION,
      'Select previous file that has comments');
  _describe(Shortcut.OPEN_FIRST_FILE, ShortcutSection.NAVIGATION,
      'Show first file');
  _describe(Shortcut.OPEN_LAST_FILE, ShortcutSection.NAVIGATION,
      'Show last file');
  _describe(Shortcut.UP_TO_DASHBOARD, ShortcutSection.NAVIGATION,
      'Up to dashboard');
  _describe(Shortcut.UP_TO_CHANGE, ShortcutSection.NAVIGATION, 'Up to change');

  _describe(Shortcut.CURSOR_NEXT_FILE, ShortcutSection.FILE_LIST,
      'Select next file');
  _describe(Shortcut.CURSOR_PREV_FILE, ShortcutSection.FILE_LIST,
      'Select previous file');
  _describe(Shortcut.OPEN_FILE, ShortcutSection.FILE_LIST,
      'Go to selected file');
  _describe(Shortcut.TOGGLE_ALL_INLINE_DIFFS, ShortcutSection.FILE_LIST,
      'Show/hide all inline diffs');
  _describe(Shortcut.TOGGLE_INLINE_DIFF, ShortcutSection.FILE_LIST,
      'Show/hide selected inline diff');

  _describe(Shortcut.SEND_REPLY, ShortcutSection.REPLY_DIALOG, 'Send reply');

  // Must be declared outside behavior implementation to be accessed inside
  // behavior functions.

  /** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
  const getKeyboardEvent = function(e) {
    e = Polymer.dom(e.detail ? e.detail.keyboardEvent : e);
    // When e is a keyboardEvent, e.event is not null.
    if (e.event) { e = e.event; }
    return e;
  };

  class ShortcutManager {
    constructor() {
      this.activeHosts = new Map();
      this.bindings = new Map();
      this.listeners = new Set();
    }

    bindShortcut(shortcut, ...bindings) {
      this.bindings.set(shortcut, bindings);
    }

    getBindingsForShortcut(shortcut) {
      return this.bindings.get(shortcut);
    }

    attachHost(host) {
      if (!host.keyboardShortcuts) { return; }
      const shortcuts = host.keyboardShortcuts();
      this.activeHosts.set(host, new Map(Object.entries(shortcuts)));
      this.notifyListeners();
      return shortcuts;
    }

    detachHost(host) {
      if (this.activeHosts.delete(host)) {
        this.notifyListeners();
        return true;
      }
      return false;
    }

    addListener(listener) {
      this.listeners.add(listener);
      listener(this.directoryView());
    }

    removeListener(listener) {
      return this.listeners.delete(listener);
    }

    activeShortcutsBySection() {
      const activeShortcuts = new Set();
      this.activeHosts.forEach(shortcuts => {
        shortcuts.forEach((_, shortcut) => activeShortcuts.add(shortcut));
      });

      const activeShortcutsBySection = new Map();
      _help.forEach((shortcutList, section) => {
        shortcutList.forEach(shortcutHelp => {
          if (activeShortcuts.has(shortcutHelp.shortcut)) {
            if (!activeShortcutsBySection.has(section)) {
              activeShortcutsBySection.set(section, []);
            }
            activeShortcutsBySection.get(section).push(shortcutHelp);
          }
        });
      });
      return activeShortcutsBySection;
    }

    directoryView() {
      const view = new Map();
      this.activeShortcutsBySection().forEach((shortcutHelps, section) => {
        const sectionView = [];
        shortcutHelps.forEach(shortcutHelp => {
          const bindingDesc = this.describeBindings(shortcutHelp.shortcut);
          if (!bindingDesc) { return; }
          this.distributeBindingDesc(bindingDesc).forEach(bindingDesc => {
            sectionView.push({
              binding: bindingDesc,
              text: shortcutHelp.text,
            });
          });
        });
        view.set(section, sectionView);
      });
      return view;
    }

    distributeBindingDesc(bindingDesc) {
      if (bindingDesc.length === 1 ||
          this.comboSetDisplayWidth(bindingDesc) < 21) {
        return [bindingDesc];
      }
      // Find the largest prefix of bindings that is under the
      // size threshold.
      const head = [bindingDesc[0]];
      for (let i = 1; i < bindingDesc.length; i++) {
        head.push(bindingDesc[i]);
        if (this.comboSetDisplayWidth(head) >= 21) {
          head.pop();
          return [head].concat(
              this.distributeBindingDesc(bindingDesc.slice(i)));
        }
      }
    }

    comboSetDisplayWidth(bindingDesc) {
      const bindingSizer = binding => binding.reduce(
          (acc, key) => acc + key.length, 0);
      // Width is the sum of strings + (n-1) * 2 to account for the word
      // "or" joining them.
      return bindingDesc.reduce(
          (acc, binding) => acc + bindingSizer(binding), 0) +
          2 * (bindingDesc.length - 1);
    }

    describeBindings(shortcut) {
      const bindings = this.bindings.get(shortcut);
      if (!bindings) { return null; }
      if (bindings[0] === GO_KEY) {
        return [['g'].concat(bindings.slice(1))];
      }
      return bindings
          .filter(binding => binding !== DOC_ONLY)
          .map(binding => this.describeBinding(binding));
    }

    describeBinding(binding) {
      return binding.split(':')[0].split('+').map(part => {
        switch (part) {
          case 'shift':
            return 'Shift';
          case 'meta':
            return 'Meta';
          case 'ctrl':
            return 'Ctrl';
          case 'enter':
            return 'Enter';
          case 'up':
            return '↑';
          case 'down':
            return '↓';
          case 'left':
            return '←';
          case 'right':
            return '→';
          default:
            return part;
        }
      });
    }

    notifyListeners() {
      const view = this.directoryView();
      this.listeners.forEach(listener => listener(view));
    }
  }

  const shortcutManager = new ShortcutManager();

  window.Gerrit = window.Gerrit || {};

  /** @polymerBehavior KeyboardShortcutBehavior */
  Gerrit.KeyboardShortcutBehavior = [
    Polymer.IronA11yKeysBehavior,
    {
      // Exports for convenience. Note: Closure compiler crashes when
      // object-shorthand syntax is used here.
      // eslint-disable-next-line object-shorthand
      DOC_ONLY: DOC_ONLY,
      // eslint-disable-next-line object-shorthand
      GO_KEY: GO_KEY,
      // eslint-disable-next-line object-shorthand
      Shortcut: Shortcut,

      properties: {
        _shortcut_go_key_last_pressed: {
          type: Number,
          value: null,
        },

        _shortcut_go_table: {
          type: Array,
          value() { return new Map(); },
        },
      },

      modifierPressed(e) {
        e = getKeyboardEvent(e);
        return e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
      },

      isModifierPressed(e, modifier) {
        return getKeyboardEvent(e)[modifier];
      },

      shouldSuppressKeyboardShortcut(e) {
        e = getKeyboardEvent(e);
        const tagName = Polymer.dom(e).rootTarget.tagName;
        if (tagName === 'INPUT' || tagName === 'TEXTAREA' ||
            (e.keyCode === 13 && tagName === 'A')) {
          // Suppress shortcuts if the key is 'enter' and target is an anchor.
          return true;
        }
        for (let i = 0; e.path && i < e.path.length; i++) {
          if (e.path[i].tagName === 'GR-OVERLAY') { return true; }
        }
        return false;
      },

      // Alias for getKeyboardEvent.
      /** @return {!(Event|PolymerDomApi|PolymerEventApi)} */
      getKeyboardEvent(e) {
        return getKeyboardEvent(e);
      },

      getRootTarget(e) {
        return Polymer.dom(getKeyboardEvent(e)).rootTarget;
      },

      bindShortcut(shortcut, ...bindings) {
        shortcutManager.bindShortcut(shortcut, ...bindings);
      },

      _addOwnKeyBindings(shortcut, handler) {
        const bindings = shortcutManager.getBindingsForShortcut(shortcut);
        if (!bindings) {
          return;
        }
        if (bindings[0] === DOC_ONLY) {
          return;
        }
        if (bindings[0] === GO_KEY) {
          this._shortcut_go_table.set(bindings[1], handler);
        } else {
          this.addOwnKeyBinding(bindings.join(' '), handler);
        }
      },

      attached() {
        const shortcuts = shortcutManager.attachHost(this);
        if (!shortcuts) { return; }

        for (const key of Object.keys(shortcuts)) {
          this._addOwnKeyBindings(key, shortcuts[key]);
        }

        // If any of the shortcuts utilized GO_KEY, then they are handled
        // directly by this behavior.
        if (this._shortcut_go_table.size > 0) {
          this.addOwnKeyBinding('g:keydown', '_handleGoKeyDown');
          this.addOwnKeyBinding('g:keyup', '_handleGoKeyUp');
          this._shortcut_go_table.forEach((handler, key) => {
            this.addOwnKeyBinding(key, '_handleGoAction');
          });
        }
      },

      detached() {
        if (shortcutManager.detachHost(this)) {
          this.removeOwnKeyBindings();
        }
      },

      keyboardShortcuts() {
        return {};
      },

      addKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.addListener(listener);
      },

      removeKeyboardShortcutDirectoryListener(listener) {
        shortcutManager.removeListener(listener);
      },

      _handleGoKeyDown(e) {
        if (this.modifierPressed(e)) { return; }
        this._shortcut_go_key_last_pressed = Date.now();
      },

      _handleGoKeyUp(e) {
        this._shortcut_go_key_last_pressed = null;
      },

      _handleGoAction(e) {
        if (!this._shortcut_go_key_last_pressed ||
            (Date.now() - this._shortcut_go_key_last_pressed >
                GO_KEY_TIMEOUT_MS) ||
            !this._shortcut_go_table.has(e.detail.key) ||
            this.shouldSuppressKeyboardShortcut(e)) {
          return;
        }
        e.preventDefault();
        const handler = this._shortcut_go_table.get(e.detail.key);
        this[handler](e);
      },
    },
  ];

  Gerrit.KeyboardShortcutBinder = {
    DOC_ONLY,
    GO_KEY,
    Shortcut,
    ShortcutManager,
    ShortcutSection,

    bindShortcut(shortcut, ...bindings) {
      shortcutManager.bindShortcut(shortcut, ...bindings);
    },
  };
})(window);
</script>
