text: var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
  import { LitElement, html } from 'lit';
  import { customElement, property, state } from 'lit/decorators.js';
  import { repeat } from 'lit/directives/repeat.js';
  import { live } from 'lit/directives/live.js';
  import { createRef, ref } from 'lit-html/directives/ref.js';
  import { classMap } from 'lit/directives/class-map.js';
  import hotkeys from 'hotkeys-js';
  import './ninja-header.js';
  import './ninja-action.js';
  import { footerHtml } from './ninja-footer.js';
  import { baseStyles } from './base-styles.js';
  let NinjaKeys = class NinjaKeys extends LitElement {
      constructor() {
          super(...arguments);
          /**
           * Search placeholder text
           */
          this.placeholder = 'Type a command or search...';
          /**
           * If true will register all hotkey for all actions
           */
          this.disableHotkeys = false;
          /**
           * Show or hide breadcrumbs on header
           */
          this.hideBreadcrumbs = false;
          /**
           * Open or hide shorcut
           */
          this.openHotkey = 'cmd+k,ctrl+k';
          /**
           * Navigation Up hotkey
           */
          this.navigationUpHotkey = 'up,shift+tab';
          /**
           * Navigation Down hotkey
           */
          this.navigationDownHotkey = 'down,tab';
          /**
           * Close hotkey
           */
          this.closeHotkey = 'esc';
          /**
           * Go back on one level if has parent menu
           */
          this.goBackHotkey = 'backspace';
          /**
           * Select action and execute handler or open submenu
           */
          this.selectHotkey = 'enter'; // enter,space
          /**
           * Show or hide breadcrumbs on header
           */
          this.hotKeysJoinedView = false;
          /**
           * Disable load material icons font on connect
           * If you use custom icons.
           * Set this attribute to prevent load default icons font
           */
          this.noAutoLoadMdIcons = false;
          /**
           * Array of actions
           */
          this.data = [];
          /**
           * Show or hide element
           */
          this.visible = false;
          /**
           * Temproray used for animation effect. TODO: change to animate logic
           */
          this._bump = true;
          this._actionMatches = [];
          this._search = '';
          /**
           * Array of actions in flat structure
           */
          this._flatData = [];
          this._headerRef = createRef();
      }
      /**
       * Public methods
       */
      /**
       * Show a modal
       */
      open(options = {}) {
          this._bump = true;
          this.visible = true;
          this._headerRef.value.focusSearch();
          if (this._actionMatches.length > 0) {
              this._selected = this._actionMatches[0];
          }
          this.setParent(options.parent);
      }
      /**
       * Close modal
       */
      close() {
          this._bump = false;
          this.visible = false;
      }
      /**
       * Navigate to group of actions
       * @param parent id of parent group/action
       */
      setParent(parent) {
          if (!parent) {
              this._currentRoot = undefined;
              // this.breadcrumbs = [];
          }
          else {
              this._currentRoot = parent;
          }
          this._search = '';
          this._headerRef.value.setSearch('');
      }
      get breadcrumbs() {
          var _a;
          const path = [];
          let parentAction = (_a = this._selected) === null || _a === void 0 ? void 0 : _a.parent;
          if (parentAction) {
              path.push(parentAction);
              while (parentAction) {
                  const action = this._flatData.find((a) => a.id === parentAction);
                  if (action === null || action === void 0 ? void 0 : action.parent) {
                      path.push(action.parent);
                  }
                  parentAction = action ? action.parent : undefined;
              }
          }
          return path.reverse();
      }
      connectedCallback() {
          super.connectedCallback();
          if (!this.noAutoLoadMdIcons) {
              document.fonts.load('24px Material Icons', 'apps').then(() => { });
          }
          this._registerInternalHotkeys();
      }
      _flattern(members, parent) {
          let children = [];
          return members
              .map((mem) => {
              const alreadyFlatternByUser = mem.children &&
                  mem.children.some((value) => {
                      return typeof value == 'string';
                  });
              const m = { ...mem, parent: mem.parent || parent };
              if (alreadyFlatternByUser) {
                  return m;
              }
              else {
                  if (m.children && m.children.length) {
                      parent = mem.id;
                      children = [...children, ...m.children];
                  }
                  m.children = m.children ? m.children.map((c) => c.id) : [];
                  return m;
              }
          })
              .concat(children.length ? this._flattern(children, parent) : children);
      }
      update(changedProperties) {
          if (changedProperties.has('data') && !this.disableHotkeys) {
              this._flatData = this._flattern(this.data);
              this._flatData
                  .filter((action) => !!action.hotkey)
                  .forEach((action) => {
                  hotkeys(action.hotkey, (event) => {
                      event.preventDefault();
                      if (action.handler) {
                          action.handler(action);
                      }
                  });
              });
          }
          super.update(changedProperties);
      }
      _registerInternalHotkeys() {
          if (this.openHotkey) {
              hotkeys(this.openHotkey, (event) => {
                  event.preventDefault();
                  this.visible ? this.close() : this.open();
              });
          }
          if (this.selectHotkey) {
              hotkeys(this.selectHotkey, (event) => {
                  if (!this.visible) {
                      return;
                  }
                  event.preventDefault();
                  this._actionSelected(this._actionMatches[this._selectedIndex]);
              });
          }
          if (this.goBackHotkey) {
              hotkeys(this.goBackHotkey, (event) => {
                  if (!this.visible) {
                      return;
                  }
                  if (!this._search) {
                      event.preventDefault();
                      this._goBack();
                  }
              });
          }
          if (this.navigationDownHotkey) {
              hotkeys(this.navigationDownHotkey, (event) => {
                  if (!this.visible) {
                      return;
                  }
                  event.preventDefault();
                  if (this._selectedIndex >= this._actionMatches.length - 1) {
                      this._selected = this._actionMatches[0];
                  }
                  else {
                      this._selected = this._actionMatches[this._selectedIndex + 1];
                  }
              });
          }
          if (this.navigationUpHotkey) {
              hotkeys(this.navigationUpHotkey, (event) => {
                  if (!this.visible) {
                      return;
                  }
                  event.preventDefault();
                  if (this._selectedIndex === 0) {
                      this._selected = this._actionMatches[this._actionMatches.length - 1];
                  }
                  else {
                      this._selected = this._actionMatches[this._selectedIndex - 1];
                  }
              });
          }
          if (this.closeHotkey) {
              hotkeys(this.closeHotkey, () => {
                  if (!this.visible) {
                      return;
                  }
                  this.close();
              });
          }
      }
      _actionFocused(index, $event) {
          // this.selectedIndex = index;
          this._selected = index;
          $event.target.ensureInView();
      }
      _onTransitionEnd() {
          this._bump = false;
      }
      _goBack() {
          const parent = this.breadcrumbs.length > 1
              ? this.breadcrumbs[this.breadcrumbs.length - 2]
              : undefined;
          this.setParent(parent);
      }
      render() {
          const classes = {
              bump: this._bump,
              'modal-content': true,
          };
          const menuClasses = {
              visible: this.visible,
              modal: true,
          };
          this._actionMatches = this._flatData.filter((action) => {
              var _a;
              const regex = new RegExp(this._search, 'gi');
              const matcher = action.title.match(regex) || ((_a = action.keywords) === null || _a === void 0 ? void 0 : _a.match(regex));
              if (!this._currentRoot && this._search) {
                  // global search for items on root
                  return matcher;
              }
              return action.parent === this._currentRoot && matcher;
          });
          if (this._actionMatches.length > 0 && this._selectedIndex === -1) {
              this._selected = this._actionMatches[0];
          }
          if (this._actionMatches.length === 0) {
              this._selected = undefined;
          }
          const sections = this._actionMatches.reduce((entryMap, e) => entryMap.set(e.section, [...(entryMap.get(e.section) || []), e]), new Map());
          const actionsList = (actions) => html ` ${repeat(actions, (action) => action.id, (action) => {
              var _a;
              return html `<ninja-action
              exportparts="ninja-action,ninja-selected"
              .selected=${live(action.id === ((_a = this._selected) === null || _a === void 0 ? void 0 : _a.id))}
              .hotKeysJoinedView=${this.hotKeysJoinedView}
              @mouseover=${(event) => this._actionFocused(action, event)}
              @actionsSelected=${(event) => this._actionSelected(event.detail)}
              .action=${action}
            ></ninja-action>`;
          })}`;
          const itemTemplates = [];
          sections.forEach((actions, section) => {
              const header = section
                  ? html `<div class="group-header">${section}</div>`
                  : undefined;
              itemTemplates.push(html `${header}${actionsList(actions)}`);
          });
          return html `
        <div @click=${this._overlayClick} class=${classMap(menuClasses)}>
          <div class=${classMap(classes)} @animationend=${this._onTransitionEnd}>
            <ninja-header
              ${ref(this._headerRef)}
              .placeholder=${this.placeholder}
              .hideBreadcrumbs=${this.hideBreadcrumbs}
              .breadcrumbs=${this.breadcrumbs}
              @change=${this._handleInput}
              @setParent=${(event) => this.setParent(event.detail.parent)}
              @close=${this.close}
            >
            </ninja-header>
            <div class="modal-body">
              <div class="actions-list" part="actions-list">${itemTemplates}</div>
            </div>
            <slot name="footer"> ${footerHtml} </slot>
          </div>
        </div>
      `;
      }
      get _selectedIndex() {
          if (!this._selected) {
              return -1;
          }
          return this._actionMatches.indexOf(this._selected);
      }
      _actionSelected(action) {
          var _a;
          // fire selected event even when action is empty/not selected,
          // so possible handle api search for example
          this.dispatchEvent(new CustomEvent('selected', {
              detail: { search: this._search, action },
              bubbles: true,
              composed: true,
          }));
          if (!action) {
              return;
          }
          if (action.children && ((_a = action.children) === null || _a === void 0 ? void 0 : _a.length) > 0) {
              this._currentRoot = action.id;
              this._search = '';
          }
          this._headerRef.value.setSearch('');
          this._headerRef.value.focusSearch();
          if (action.handler) {
              const result = action.handler(action);
              if (!(result === null || result === void 0 ? void 0 : result.keepOpen)) {
                  this.close();
              }
          }
          this._bump = true;
      }
      async _handleInput(event) {
          this._search = event.detail.search;
          await this.updateComplete;
          this.dispatchEvent(new CustomEvent('change', {
              detail: { search: this._search, actions: this._actionMatches },
              bubbles: true,
              composed: true,
          }));
      }
      _overlayClick(event) {
          var _a;
          if ((_a = event.target) === null || _a === void 0 ? void 0 : _a.classList.contains('modal')) {
              this.close();
          }
      }
  };
  NinjaKeys.styles = [baseStyles];
  __decorate([
      property({ type: String })
  ], NinjaKeys.prototype, "placeholder", void 0);
  __decorate([
      property({ type: Boolean })
  ], NinjaKeys.prototype, "disableHotkeys", void 0);
  __decorate([
      property({ type: Boolean })
  ], NinjaKeys.prototype, "hideBreadcrumbs", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "openHotkey", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "navigationUpHotkey", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "navigationDownHotkey", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "closeHotkey", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "goBackHotkey", void 0);
  __decorate([
      property()
  ], NinjaKeys.prototype, "selectHotkey", void 0);
  __decorate([
      property({ type: Boolean })
  ], NinjaKeys.prototype, "hotKeysJoinedView", void 0);
  __decorate([
      property({ type: Boolean })
  ], NinjaKeys.prototype, "noAutoLoadMdIcons", void 0);
  __decorate([
      property({ type: Array })
  ], NinjaKeys.prototype, "data", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "visible", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_bump", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_actionMatches", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_search", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_currentRoot", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_flatData", void 0);
  __decorate([
      state()
  ], NinjaKeys.prototype, "breadcrumbs", null);
  __decorate([
      state()
  ], NinjaKeys.prototype, "_selected", void 0);
  NinjaKeys = __decorate([
      customElement('ninja-keys')
  ], NinjaKeys);
  export { NinjaKeys };
  //# sourceMappingURL=ninja-keys.js.map