/*!
 * (C) Gasco https://gasco-web-component.herokuapp.com/ - MIT License
 */
import { r as registerInstance, c as createEvent, h, i as forceUpdate, H as Host, a as getElement } from './index-211ca8fb.js';
import { i as closeSharp, s as searchSharp } from './index-69a9be18.js';
import { c as config } from './config-47f2ca98.js';
import { e as debounceEvent, r as raf } from './helpers-4b2cb009.js';
import { i as isRTL } from './dir-9d8431cb.js';
import { c as createColorClasses } from './theme-c4ea3043.js';

const gascoAutocompleteMdCss = ":host{--box-shadow:0px 4px 10px rgba(171, 190, 209, 0.4);--placeholder-color:var(--gasco-color-medium, #999999);--placeholder-font-style:initial;--placeholder-font-weight:initial;--placeholder-opacity:.5;--background:transparent;--border-style:solid;--border-width:1px;--border-color:var(--gasco-color-medium, #999999);--color:var(--gasco-color-medium, #999999);border-radius:var(--border-radius);-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:flex;position:relative;align-items:center;width:100%;color:var(--color);font-family:var(--gasco-font-family, inherit);box-sizing:border-box;border-style:var(--border-style);border-color:var(--border-color);border-width:var(--border-width);background:var(--background);transition:300ms}:host(.gasco-color){color:var(--gasco-color-contrast)}:host(.gasco-color) .searchbar-input{background:var(--gasco-color-base)}:host(.gasco-color) .searchbar-clear-button,:host(.gasco-color) .searchbar-cancel-button,:host(.gasco-color) .searchbar-search-icon{color:inherit}.searchbar-search-icon{color:var(--icon-color);pointer-events:none}.searchbar-input-container{display:block;position:relative;flex-shrink:1;width:100%}.searchbar-input{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;transition:300ms;display:block;width:100%;border:0;outline:none;background:var(--background);font-family:inherit;box-sizing:border-box;appearance:none}.searchbar-input::placeholder{color:var(--placeholder-color);font-family:inherit;font-style:var(--placeholder-font-style);font-weight:var(--placeholder-font-weight);opacity:var(--placeholder-opacity)}.searchbar-input::-webkit-search-cancel-button,.searchbar-input::-ms-clear{display:none}.searchbar-cancel-button{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;display:none;height:100%;border:0;outline:none;color:var(--cancel-button-color);cursor:pointer;appearance:none}.searchbar-cancel-button>div{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.searchbar-clear-button{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;display:none;min-height:0;outline:none;color:var(--clear-button-color);appearance:none}:host(.searchbar-has-value.searchbar-should-show-clear) .searchbar-clear-button{display:block}:host(.searchbar-disabled){cursor:default;pointer-events:none;--border-color:var(--gasco-color-light, #F1F1F1) !important;--background:var(--gasco-color-light, #F1F1F1) !important;background:var(--gasco-color-light, #F1F1F1) !important}:host(.searchbar-disabled){opacity:0.8}:host(.searchbar-disabled) .native-input-label{--background:var(--gasco-color-light, #F1F1F1)}:host(.searchbar-has-focus){pointer-events:none;--border-color:var(--gasco-color-primary, #00A3E0) !important}:host(.searchbar-has-focus) .searchbar-input-label,:host(.searchbar-has-focus) .searchbar-input-textHelp,:host(.searchbar-has-focus) .searchbar-input-limit{color:var(--gasco-color-primary, #00A3E0)}:host(.searchbar-has-focus) [slot=start]{color:var(--gasco-color-primary, #00A3E0)}:host(.searchbar-has-focus) input,:host(.searchbar-has-focus) a,:host(.searchbar-has-focus) button{pointer-events:auto}@media (any-hover: hover){:host(:not([disabled]):hover){box-shadow:var(--box-shadow);--border-color:var(--gasco-color-dark, #222428);border-radius:var(--border-radius)}}:host{--border-radius:8px;--cancel-button-color:var(--gasco-color-step-900, #1a1a1a);--clear-button-color:initial;--color:var(--gasco-color-step-850, #262626);--icon-color:var(--gasco-color-step-600, #666666);padding-left:16px;padding-right:16px;padding-top:14px;padding-bottom:14px;height:48px;background-color:#FFFFFF}@supports (margin-inline-start: 0) or (-webkit-margin-start: 0){:host{padding-left:unset;padding-right:unset;-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px}}.searchbar-search-icon{right:8px;top:6px;width:21px;height:21px}[dir=rtl] .searchbar-search-icon,:host-context([dir=rtl]) .searchbar-search-icon{left:unset;right:unset;left:8px}.searchbar-cancel-button{left:5px;top:0;background-color:transparent;font-size:1.6em}[dir=rtl] .searchbar-cancel-button,:host-context([dir=rtl]) .searchbar-cancel-button{left:unset;right:unset;right:5px}.searchbar-search-icon,.searchbar-cancel-button{position:absolute}.searchbar-search-icon.gasco-activated,.searchbar-cancel-button.gasco-activated{background-color:transparent}.searchbar-input{background-position:left 8px center;font-size:16px;font-weight:400;line-height:30px}[dir=rtl] .searchbar-input,:host-context([dir=rtl]) .searchbar-input{background-position:right 8px center}.searchbar-clear-button{right:8px;top:0;padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;position:absolute;height:100%;border:0;background-color:transparent}[dir=rtl] .searchbar-clear-button,:host-context([dir=rtl]) .searchbar-clear-button{left:unset;right:unset;left:8px}.searchbar-clear-button.gasco-activated{background-color:transparent}.searchbar-clear-icon{width:22px;height:100%}:host(.searchbar-has-focus) .searchbar-search-icon{display:block}:host(.searchbar-has-focus) .searchbar-cancel-button,:host(.searchbar-should-show-cancel) .searchbar-cancel-button{display:block}:host(.searchbar-has-focus) .searchbar-cancel-button+.searchbar-search-icon,:host(.searchbar-should-show-cancel) .searchbar-cancel-button+.searchbar-search-icon{display:none}:host(.searchbar-has-value) gasco-list,:host(.searchbar-has-focus) gasco-list{position:absolute;top:50px;left:0;width:100%;max-width:100%;z-index:10;background:#FFFFFF;box-shadow:0px 2px 4px rgba(171, 190, 209, 0.6);border-radius:4px}";

const GascoAutocomplete = class {
  constructor(hostRef) {
    registerInstance(this, hostRef);
    this.gascoInput = createEvent(this, "gascoInput", 7);
    this.gascoChange = createEvent(this, "gascoChange", 7);
    this.gascoClear = createEvent(this, "gascoClear", 7);
    this.gascoBlur = createEvent(this, "gascoBlur", 7);
    this.gascoFocus = createEvent(this, "gascoFocus", 7);
    this.gascoStyle = createEvent(this, "gascoStyle", 7);
    this.isCancelVisible = false;
    this.shouldAlignLeft = true;
    this.focused = false;
    this.noAnimate = true;
    /**
     * If `true`, enable searchbar animation.
     */
    this.animated = false;
    /**
     * Set the input's autocomplete property.
     */
    this.autocomplete = 'off';
    /**
     * Set the input's autocorrect property.
     */
    this.autocorrect = 'off';
    /**
     * Set the amount of time, in milliseconds, to wait to trigger the `gascoChange` event after each keystroke. This also impacts form bindings such as `ngModel` or `v-model`.
     */
    this.debounce = 250;
    /**
     * If `true`, the user cannot interact with the input.
     */
    this.disabled = false;
    /**
     * Set the input's placeholder.
     * `placeholder` can accept either plaintext or HTML as a string.
     * To display characters normally reserved for HTML, they
     * must be escaped. For example `<Ionic>` would become
     * `&lt;Ionic&gt;`
     *
     * For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
     */
    this.placeholder = 'Search';
    /**
     * Sets the behavior for the cancel button. Defaults to `"never"`.
     * Setting to `"focus"` shows the cancel button on focus.
     * Setting to `"never"` hides the cancel button.
     * Setting to `"always"` shows the cancel button regardless
     * of focus state.
     */
    this.showCancelButton = 'never';
    /**
     * Sets the behavior for the clear button. Defaults to `"focus"`.
     * Setting to `"focus"` shows the clear button on focus if the
     * input is not empty.
     * Setting to `"never"` hides the clear button.
     * Setting to `"always"` shows the clear button regardless
     * of focus state, but only if the input is not empty.
     */
    this.showClearButton = 'always';
    /**
     * If `true`, enable spellcheck on the input.
     */
    this.spellcheck = false;
    /**
     * Set the type of the input.
     */
    this.type = 'text';
    /**
     * the value of the searchbar.
     */
    this.value = '';
    this.inputValue = '';
    this.suggestionArr = [];
    /** Values that the auto-complete textbox should search for */
    this.suggestionlist = [];
    this.findMatch = (searchTerm) => {
      if (searchTerm.length === 0) {
        return [];
      }
      return this.suggestionlist.filter((term) => term.slice(0, searchTerm.length) === searchTerm && term !== searchTerm);
    };
    this.onKeyDown = (e) => {
      switch (e.key) {
        case 'ArrowUp':
          if (this.suggestionArr.length > 0) {
            this.selectedSuggestionIndex =
              (this.selectedSuggestionIndex === undefined || this.selectedSuggestionIndex === 0) ?
                this.suggestionArr.length - 1 : this.selectedSuggestionIndex - 1;
          }
          break;
        case 'ArrowDown':
          if (this.suggestionArr.length > 0) {
            this.selectedSuggestionIndex =
              (this.selectedSuggestionIndex === undefined || this.selectedSuggestionIndex === this.suggestionArr.length - 1) ?
                0 : this.selectedSuggestionIndex + 1;
          }
          break;
      }
    };
    this.onKeyPress = (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        if (this.selectedSuggestionIndex !== undefined) {
          this.onSelect(this.suggestionArr[this.selectedSuggestionIndex]);
        }
      }
    };
    this.onSelect = (selection) => {
      const value = this.getValue();
      this.inputValue = selection;
      this.value = selection;
      this.selectedSuggestionIndex = undefined;
      this.showSuggestions = false;
      this.gascoChange.emit({ value });
    };
    this.getSuggestionItem = (suggestion) => {
      const isSelected = this.selectedSuggestionIndex !== undefined
        && suggestion === this.suggestionArr[this.selectedSuggestionIndex];
      return (h("gasco-item", { class: 'xeph-li ' + (isSelected ? 'xeph-selected' : ''), onClick: () => this.onSelect(suggestion) }, suggestion));
    };
    /**
     * Clears the input field and triggers the control change.
     */
    this.onClearInput = (ev, shouldFocus) => {
      this.gascoClear.emit();
      if (ev) {
        ev.preventDefault();
        ev.stopPropagation();
      }
      // wait for 4 frames
      setTimeout(() => {
        const value = this.getValue();
        if (value !== '') {
          this.value = '';
          this.gascoInput.emit();
          /**
           * When tapping clear button
           * ensure input is focused after
           * clearing input so users
           * can quickly start typing.
           */
          if (shouldFocus && !this.focused) {
            this.setFocus();
          }
        }
      }, 16 * 4);
    };
    // };
    /**
     * Update the Searchbar input value when the input changes
     */
    this.onInput = (ev) => {
      const input = ev.target;
      if (input) {
        this.value = input.value;
        this.inputValue = input.value;
        this.suggestionArr = this.findMatch(this.inputValue);
        this.showSuggestions = true;
      }
      this.gascoInput.emit(ev);
    };
    /**
     * Sets the Searchbar to not focused and checks if it should align left
     * based on whether there is a value in the searchbar or not.
     */
    this.onBlur = () => {
      this.focused = false;
      this.gascoBlur.emit();
      this.positionElements();
    };
    /**
     * Sets the Searchbar to focused and active on input focus.
     */
    this.onFocus = () => {
      this.focused = true;
      this.showSuggestions = true;
      this.selectedSuggestionIndex = undefined;
      this.suggestionArr = this.findMatch(this.inputValue);
      this.gascoFocus.emit();
      this.positionElements();
    };
  }
  debounceChanged() {
    this.gascoChange = debounceEvent(this.gascoChange, this.debounce);
  }
  validateSuggestionlist(newValue) {
    const sortedArr = newValue.slice().sort();
    let results = [];
    for (let i = 0; i < sortedArr.length - 1; i++) {
      if (sortedArr[i + 1] == sortedArr[i]) {
        results.push(sortedArr[i]);
      }
    }
    if (results.length > 0) {
      throw new Error(`suggestion list contains duplicate values: ${results.toLocaleString()}`);
    }
  }
  valueChanged() {
    const inputEl = this.nativeInput;
    const value = this.getValue();
    if (inputEl && inputEl.value !== value) {
      inputEl.value = value;
    }
  }
  showCancelButtonChanged() {
    requestAnimationFrame(() => {
      this.positionElements();
      forceUpdate(this);
    });
  }
  connectedCallback() {
    this.emitStyle();
  }
  componentDidLoad() {
    this.positionElements();
    this.debounceChanged();
    setTimeout(() => {
      this.noAnimate = false;
    }, 300);
  }
  componentWillLoad() {
    this.validateSuggestionlist(this.suggestionlist);
  }
  emitStyle() {
    this.gascoStyle.emit({
      searchbar: true,
    });
  }
  /**
   * Sets focus on the specified `gasco-autocomplete`. Use this method instead of the global
   * `input.focus()`.
   */
  async setFocus() {
    if (this.nativeInput) {
      this.nativeInput.focus();
    }
  }
  /**
   * Returns the native `<input>` element used under the hood.
   */
  getInputElement() {
    return Promise.resolve(this.nativeInput);
  }
  /**
   * Positions the input search icon, placeholder, and the cancel button
   * based on the input value and if it is focused. (ios only)
   */
  positionElements() {
    const value = this.getValue();
    const prevAlignLeft = this.shouldAlignLeft;
    const shouldAlignLeft = !this.animated || value.trim() !== '' || !!this.focused;
    this.shouldAlignLeft = shouldAlignLeft;
    if (prevAlignLeft !== shouldAlignLeft) {
      this.positionPlaceholder();
    }
    if (this.animated) {
      this.positionCancelButton();
    }
  }
  /**
   * Positions the input placeholder
   */
  positionPlaceholder() {
    const inputEl = this.nativeInput;
    if (!inputEl) {
      return;
    }
    const rtl = isRTL(this.el);
    const iconEl = (this.el.shadowRoot || this.el).querySelector('.searchbar-search-icon');
    if (this.shouldAlignLeft) {
      inputEl.removeAttribute('style');
      iconEl.removeAttribute('style');
    }
    else {
      // Create a dummy span to get the placeholder width
      const doc = document;
      const tempSpan = doc.createElement('span');
      tempSpan.innerText = this.placeholder || '';
      doc.body.appendChild(tempSpan);
      // Get the width of the span then remove it
      raf(() => {
        const textWidth = tempSpan.offsetWidth;
        tempSpan.remove();
        // Calculate the input padding
        const inputLeft = 'calc(50% - ' + textWidth / 2 + 'px)';
        // Calculate the icon margin
        const iconLeft = 'calc(50% - ' + (textWidth / 2 + 30) + 'px)';
        // Set the input padding start and icon margin start
        if (rtl) {
          inputEl.style.paddingRight = inputLeft;
          iconEl.style.marginRight = iconLeft;
        }
        else {
          inputEl.style.paddingLeft = inputLeft;
          iconEl.style.marginLeft = iconLeft;
        }
      });
    }
  }
  /**
   * Show the iOS Cancel button on focus, hide it offscreen otherwise
   */
  positionCancelButton() {
    const rtl = isRTL(this.el);
    const cancelButton = (this.el.shadowRoot || this.el).querySelector('.searchbar-cancel-button');
    const shouldShowCancel = this.shouldShowCancelButton();
    if (cancelButton && shouldShowCancel !== this.isCancelVisible) {
      const cancelStyle = cancelButton.style;
      this.isCancelVisible = shouldShowCancel;
      if (shouldShowCancel) {
        if (rtl) {
          cancelStyle.marginLeft = '0';
        }
        else {
          cancelStyle.marginRight = '0';
        }
      }
      else {
        const offset = cancelButton.offsetWidth;
        if (offset > 0) {
          if (rtl) {
            cancelStyle.marginLeft = -offset + 'px';
          }
          else {
            cancelStyle.marginRight = -offset + 'px';
          }
        }
      }
    }
  }
  getValue() {
    return this.value || '';
  }
  hasValue() {
    return this.getValue() !== '';
  }
  /**
   * Determines whether or not the cancel button should be visible onscreen.
   * Cancel button should be shown if one of two conditions applies:
   * 1. `showCancelButton` is set to `always`.
   * 2. `showCancelButton` is set to `focus`, and the searchbar has been focused.
   */
  shouldShowCancelButton() {
    if (this.showCancelButton === 'never' || (this.showCancelButton === 'focus' && !this.focused)) {
      return false;
    }
    return true;
  }
  /**
   * Determines whether or not the clear button should be visible onscreen.
   * Clear button should be shown if one of two conditions applies:
   * 1. `showClearButton` is set to `always`.
   * 2. `showClearButton` is set to `focus`, and the searchbar has been focused.
   */
  shouldShowClearButton() {
    if (this.showClearButton === 'never' || (this.showClearButton === 'focus' && !this.focused)) {
      return false;
    }
    return true;
  }
  render() {
    const animated = this.animated && config.getBoolean('animated', true);
    const clearIcon = this.clearIcon || closeSharp;
    const searchIcon = this.searchIcon || searchSharp;
    return (h(Host, { role: "search", "aria-disabled": this.disabled ? 'true' : null, class: createColorClasses(this.color, {
        'searchbar-animated': animated,
        'searchbar-disabled': this.disabled,
        'searchbar-has-focus': this.focused,
        'searchbar-has-value': this.hasValue(),
        'searchbar-left-aligned': this.shouldAlignLeft,
        'searchbar-no-animate': animated && this.noAnimate,
        'searchbar-should-show-clear': this.shouldShowClearButton(),
        'searchbar-should-show-cancel': this.shouldShowCancelButton(),
      }) }, h("div", { class: "searchbar-input-container" }, h("input", { "aria-label": "search text", disabled: this.disabled, ref: (el) => (this.nativeInput = el), class: "searchbar-input", inputMode: this.inputmode, enterKeyHint: this.enterkeyhint, onInput: this.onInput, onBlur: this.onBlur, onFocus: this.onFocus, onKeyDown: this.onKeyDown, onKeyPress: this.onKeyPress, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellcheck: this.spellcheck }), this.value.length < 1 && (h("ion-icon", { lazy: false, icon: searchIcon, "aria-hidden": "true", class: "searchbar-search-icon" })), h("button", { "no-blur": true, type: "button", "aria-label": "reset", class: "searchbar-clear-button", onMouseDown: (ev) => this.onClearInput(ev, true), onTouchStart: (ev) => this.onClearInput(ev, true) }, h("ion-icon", { lazy: false, icon: clearIcon, "aria-hidden": "true", class: "searchbar-clear-icon" }))), this.showSuggestions && this.getValue().length > 0 && (h("gasco-list", { role: 'listbox', hidden: !this.showSuggestions }, this.suggestionArr.map(suggestion => this.getSuggestionItem(suggestion))))));
  }
  get el() { return getElement(this); }
  static get watchers() { return {
    "debounce": ["debounceChanged"],
    "suggestionlist": ["validateSuggestionlist"],
    "value": ["valueChanged"],
    "showCancelButton": ["showCancelButtonChanged"]
  }; }
};
GascoAutocomplete.style = gascoAutocompleteMdCss;

export { GascoAutocomplete as gasco_autocomplete };
