'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-b7293b2f.js');
const theme = require('./theme-1ac31ccf.js');

const comboBoxCss = ":host{--lu-combo-box-border-color:#686a6f;position:relative}:host .input-area{display:inline-flex;flex-wrap:wrap;width:100%;padding:9px 0 1px 4px;border:1px solid var(--lu-global-form-input-outline, var(--lu-combo-box-border-color));outline:none;background-color:#ffffff;font-size:var(--lu-global-form-input-font-size, 14px);line-height:26px;box-sizing:border-box}:host lu-input{flex-grow:1;width:15px;min-width:15px;margin-top:-8px}:host .selections{display:flex;position:absolute;right:0;left:0;flex-flow:column;border:1px solid var(--lu-global-form-input-outline, var(--lu-combo-box-border-color));border-top:none;background:#ffffff;z-index:5}:host .selection{padding:10px 17px 8px 17px;border:0;color:#222222;font:inherit;font-size:14px;line-height:16px;text-align:left;cursor:pointer}:host .selection .selection-no-value{margin-bottom:16px}:host button.selection{background:none;overflow:visible;-webkit-appearance:button;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}:host button.selection.active,:host button.selection:hover{background-color:#eef3f9}:host .selection-value{color:rgba(34, 34, 34, 0.5)}:host button.selection::-moz-focus-inner{padding:0;border:0}:host([is-valid]) .input-area{border:2px solid #00854e}:host([is-invalid]) .input-area{border:2px solid #e4002b}:host(.has-focus) .input-area{border:2px solid #1B2C56}:host(.has-focus) lu-input{min-width:250px}";

const ComboBox = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.luNewSearchResultRequested = index.createEvent(this, "luNewSearchResultRequested", 7);
    this.luBlur = index.createEvent(this, "luBlur", 7);
    this.luFocus = index.createEvent(this, "luFocus", 7);
    this.luChange = index.createEvent(this, "luChange", 7);
    this.comboBoxId = `lu-combo-box-${comboBoxIds++}`;
    this.hasFocus = false;
    /**
     * active index
     */
    this.activeIndex = -1;
    /**
     * This is used to hold the currently displayed search results
     */
    this.displayedSearchResults = [];
    /**
     * @internal - used by the form group element to declare it's presence
     */
    this.hasFormGroup = false;
    /**
     * Adds a loading state to the mix so we can show animated skeleton text
     */
    this.isLoading = false;
    /**
     * prevents bad validation event when resetting
     */
    this.isResetting = false;
    /**
     * Current text of the input
     */
    this.text = '';
    /**
     * used to prevent default blur actions
     */
    this.shouldPreventDefaultBlurActions = false;
    /**
     * Provides a way for users to specify the labeling elements. Pass the id's, separated by a space, to this prop.
     */
    this.ariaLabeledByAddition = '';
    /**
     * If `true`, the user cannot interact with the textarea.
     */
    this.disabled = false;
    /**
     * type defines how to validate the values as well as sets the type on the contained input
     * text | email
     */
    this.type = 'text';
    //todo: add pattern validation
    /**
     * Allows for multiple entries or selections - THIS COMPONENT ONLY SUPPORTS THIS RIGHT NOW. WE NEED A DESIGN FOR SINGLE SELECTION.
     */
    // todo: this is not working at all ... its set to false?
    this.multipleSelections = true;
    /**
     * Search functionality enabled
     */
    this.autoSuggestEnabled = true;
    /**
     * Keeps track of selected options
     */
    this.value = [];
    /**
     * This specifies the combo box is for email.
     * It helps the display of the selected box by allowing it to only show the before @ symbol part.
     */
    this.forEmail = false;
    /**
     * Provided search results from requested input
     */
    this.searchResults = [];
    /**
     * Declares input as invalid
     */
    this.invalid = false;
    /**
     * The name of the control, which is submitted with the form data.
     */
    this.name = this.comboBoxId;
    /**
     * Declares input as validated
     */
    this.valid = false;
    /**
     * Notes that element is required
     */
    this.required = false;
    this.deleteSelection = (ev) => {
      this.value = [...this.value.filter((sel) => sel.value !== ev.detail)];
      this.emitValueChange();
    };
    this.onChange = (ev) => {
      ev.stopPropagation();
      const { value } = ev.detail;
      this.clearData();
      if (value && value.length > 1 && typeof value === 'string' && (value.charAt(value.length - 1) === ',' || value.charAt(value.length - 1) === ' ')) {
        this.value = [...this.value, {
            value: value.substring(0, value.length - 1)
          }];
        this.emitValueChange();
        this.clearInput();
      }
      else if (!value) {
        this.isLoading = false;
        this.text = '';
      }
      else {
        this.isLoading = true;
        this.text = value;
        this.luNewSearchResultRequested.emit({
          purpose: this.purpose,
          searchText: this.text,
          comboBoxId: this.comboBoxId
        });
      }
    };
    this.onBlur = (ev) => {
      if (!this.shouldPreventDefaultBlurActions) {
        const value = ev.target.value;
        this.clearData();
        if (value) {
          this.value = [...this.value, {
              value
            }];
          this.emitValueChange();
        }
        this.clearInput();
        this.luBlur.emit(this.value);
      }
      else {
        this.shouldPreventDefaultBlurActions = false;
      }
    };
    this.onFocus = (_ev) => {
      this.luFocus.emit();
    };
    this.onClearInputButtonPressed = (ev) => {
      ev.preventDefault();
      setTimeout(() => {
        this.luInputElement.setFocus();
      }, 20);
    };
    this.onInputStyleEmit = (ev) => {
      this.hasFocus = ev.detail['has-focus'];
    };
  }
  onApiErrorCountChange(newValue, oldValue) {
    if ((!!oldValue || oldValue === 0) && newValue > oldValue) {
      this.clearData();
      this.isLoading = false;
    }
  }
  onSearchResultsChange(newValue, oldValue) {
    if (!!this.text && (((oldValue.length === 0 || this.displayedSearchResults.length == 0) && newValue.length > 0) || (newValue && newValue.length > 0 && JSON.stringify(newValue) !== JSON.stringify(oldValue)))) {
      this.displayedSearchResults = [...newValue];
      this.isLoading = false;
      this.activeIndex = 0;
    }
    if (newValue.length === 0) {
      this.displayedSearchResults = [];
      this.isLoading = false;
    }
  }
  connectedCallback() {
    if (this.searchResults && this.searchResults.length > 0) {
      this.displayedSearchResults = [...this.searchResults];
    }
  }
  componentDidLoad() {
    this.nativeInputsId = this.luInputElement.id.replace('-wrapper', '');
  }
  onLuUpdatedComboBoxSearchResults(ev) {
    const data = ev.detail;
    const relevantData = data.filter((res) => res.comboBoxId.toLowerCase() === this.comboBoxId.toLowerCase())[0];
    if (relevantData) {
      this.searchResults = [...relevantData.searchResults];
    }
  }
  handleKeyDown(ev) {
    let keyCode = 0;
    // preparing for removal of keyCode
    if (ev.key !== undefined) {
      if (ev.key.toLowerCase() === 'arrowup') {
        keyCode = 38;
      }
      if (ev.key.toLowerCase() === 'arrowdown') {
        keyCode = 40;
      }
      if (ev.key.toLowerCase() === 'enter') {
        keyCode = 13;
      }
      if (ev.key.toLowerCase() === 'tab') {
        keyCode = 9;
      }
      if (ev.key.toLowerCase() === 'escape') {
        keyCode = 27;
      }
      if (ev.key.toLowerCase() === 'backspace') {
        keyCode = 8;
      }
    }
    else if (ev.keyCode !== undefined) {
      keyCode = ev.keyCode;
    }
    if (!!this.luInputElement.classList.contains('has-value') && !!this.luInputElement.classList.contains('has-focus') && keyCode === 9) {
      ev.preventDefault();
      this.shouldPreventDefaultBlurActions = true;
      const suffixIcon = this.luInputElement.shadowRoot.querySelector('.suffix-icon');
      suffixIcon.focus();
    }
    if (keyCode === 27) { // esc
      this.handleClose();
      this.clearData();
      this.clearInput();
    }
    if (this.displayedSearchResults.length > 0) {
      if (keyCode === 40 || keyCode === 38) { // up/down arrows
        ev.preventDefault();
        this.handleActivation(keyCode == 40);
      }
      else if (keyCode === 9) { //tab
        ev.preventDefault();
        this.clearData();
      }
      else if (keyCode === 13) { // enter
        if (this.activeIndex !== -1) {
          ev.preventDefault();
          this.handleSelection(this.activeIndex);
        }
      }
    }
    else {
      if (keyCode === 13 && this.luInputElement.classList.contains('has-value') && !!this.luInputElement.value) {
        this.value = [...this.value, { value: this.luInputElement.value }];
        this.emitValueChange();
        this.clearInput();
      }
    }
    if (this.value.length > 0 && keyCode === 8 && !this.text) {
      this.value = [...this.value.slice(0, -1)];
      this.emitValueChange();
    }
  }
  hasValue() {
    return this.value.length > 0;
  }
  handleActivation(next = true) {
    if (this.displayedSearchResults.length > 0) {
      if (next && (this.activeIndex + 1) < this.displayedSearchResults.length) {
        this.activeIndex += 1;
      }
      else if (next) {
        this.activeIndex = 0;
      }
      else if (!next && (this.activeIndex) > 0) {
        this.activeIndex -= 1;
      }
      else if (!next) {
        this.activeIndex = this.displayedSearchResults.length - 1;
      }
    }
  }
  handleSelection(index) {
    if (index >= 0 && index < this.displayedSearchResults.length) {
      this.value = [...this.value, this.displayedSearchResults[index]];
      this.emitValueChange();
      this.clearData();
      this.clearInput();
    }
  }
  emitValueChange() {
    this.luChange.emit({ value: this.value, isResetting: this.isResetting });
    this.isResetting = false;
  }
  handleClose() {
    this.clearInput();
    this.clearData();
  }
  clearData() {
    this.displayedSearchResults = [];
    this.activeIndex = -1;
  }
  clearInput() {
    this.isLoading = false;
    this.text = '';
    this.luInputElement.updateValue('');
  }
  /**
   * this gives us a handle to set focus on the element
   */
  async setFocus() {
    if (this.luInputElement) {
      this.luInputElement.setFocus();
    }
  }
  /**
   * this is used by the form validation/ form group to reset Value without initiating a validity check
   * @param update
   */
  async updateValue(update) {
    this.isResetting = true;
    this.value = update;
    this.emitValueChange();
  }
  render() {
    const expanded = !!(this.isLoading || (this.displayedSearchResults && this.displayedSearchResults.length > 0));
    return (index.h(index.Host, { "aria-disabled": this.disabled ? 'true' : null, class: Object.assign(Object.assign({}, theme.createColorClasses(this.color)), { 'is-combo-box': true, 'has-value': this.hasValue(), 'has-focus': this.hasFocus }), "is-invalid": this.invalid, "is-valid": this.valid, id: this.comboBoxId }, index.h("div", { class: "input-area", "aria-haspopup": "listbox", role: "combobox", "aria-expanded": expanded ? 'true' : 'false', "aria-owns": this.comboBoxId + '-listbox' }, this.value.map((selection) => index.h("lu-combo-box-selection", { onLuComboBoxDeleteSelectionRequest: this.deleteSelection, selection: selection })), index.h("lu-input", Object.assign({ noBorder: true, disabled: this.disabled, type: this.type, ref: (ref) => this.luInputElement = ref, onLuChange: this.onChange, clearInput: true, onLuBlur: this.onBlur, onLuStyle: this.onInputStyleEmit, onLuSuffixClickedOrTapped: this.onClearInputButtonPressed, ariaAutoComplete: "both", ariaControls: this.comboBoxId + '-listbox', ariaActiveDescendant: this.comboBoxId + '-listbox-option-' + this.activeIndex }, (this.hasFormGroup || (this.ariaLabeledByAddition && this.ariaLabeledByAddition.length > 0)) &&
      { 'aria-labelledby': `${this.ariaLabeledByAddition} ` + (this.hasFormGroup ? this.comboBoxId + '-label' : '') }))), !!expanded &&
      index.h("div", { class: 'selections', role: "listbox", id: this.comboBoxId + '-listbox' }, this.displayedSearchResults.map((res, index$1) => (index.h("button", { class: 'selection' + (this.activeIndex === index$1 ? ' active' : ''), onMouseDown: (ev) => {
          ev.preventDefault();
          this.handleSelection(index$1);
        }, role: "option", "aria-selected": this.activeIndex === index$1 ? 'true' : undefined, id: this.comboBoxId + '-listbox-option-' + index$1 }, res.name && index.h("div", { class: "selection-name" }, res.name), index.h("div", { class: res.name ? 'selection-value' : 'selection-name selection-no-value' }, res.value)))), this.isLoading && [0, 1, 2].map(() => (index.h("div", { class: 'selection' }, index.h("lu-skeleton-text", { width: '50%', shouldAnimate: true })))))));
  }
  get el() { return index.getElement(this); }
  static get watchers() { return {
    "apiErrorCount": ["onApiErrorCountChange"],
    "searchResults": ["onSearchResultsChange"]
  }; }
};
let comboBoxIds = 0;
ComboBox.style = comboBoxCss;

exports.lu_combo_box = ComboBox;

//# sourceMappingURL=lu-combo-box.cjs.entry.js.map