text: import { Host, h } from "@stencil/core";
  import { config } from '../../global/config';
  import { getIonMode } from '../../global/ionic-global';
  import { debounceEvent } from '../../utils/helpers';
  import { sanitizeDOMString } from '../../utils/sanitization';
  import { createColorClasses } from '../../utils/theme';
  /**
   * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
   */
  export class Searchbar {
      constructor() {
          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 cancel button icon. Only applies to `md` mode.
           */
          this.cancelButtonIcon = 'md-arrow-back';
          /**
           * Set the the cancel button text. Only applies to `ios` mode.
           */
          this.cancelButtonText = 'Cancel';
          /**
           * Set the amount of time, in milliseconds, to wait to trigger the `ionChange` event after each keystroke.
           */
          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';
          /**
           * The icon to use as the search icon.
           */
          this.searchIcon = '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';
          /**
           * If `true`, enable spellcheck on the input.
           */
          this.spellcheck = false;
          /**
           * Set the type of the input.
           */
          this.type = 'search';
          /**
           * the value of the searchbar.
           */
          this.value = '';
          /**
           * Clears the input field and triggers the control change.
           */
          this.onClearInput = (ev) => {
              this.ionClear.emit();
              if (ev) {
                  ev.preventDefault();
                  ev.stopPropagation();
              }
              // setTimeout() fixes https://github.com/ionic-team/ionic/issues/7527
              // wait for 4 frames
              setTimeout(() => {
                  const value = this.getValue();
                  if (value !== '') {
                      this.value = '';
                      this.ionInput.emit();
                  }
              }, 16 * 4);
          };
          /**
           * Clears the input field and tells the input to blur since
           * the clearInput function doesn't want the input to blur
           * then calls the custom cancel function if the user passed one in.
           */
          this.onCancelSearchbar = (ev) => {
              if (ev) {
                  ev.preventDefault();
                  ev.stopPropagation();
              }
              this.ionCancel.emit();
              this.onClearInput();
              if (this.nativeInput) {
                  this.nativeInput.blur();
              }
          };
          /**
           * Update the Searchbar input value when the input changes
           */
          this.onInput = (ev) => {
              const input = ev.target;
              if (input) {
                  this.value = input.value;
              }
              this.ionInput.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.ionBlur.emit();
              this.positionElements();
          };
          /**
           * Sets the Searchbar to focused and active on input focus.
           */
          this.onFocus = () => {
              this.focused = true;
              this.ionFocus.emit();
              this.positionElements();
          };
      }
      debounceChanged() {
          this.ionChange = debounceEvent(this.ionChange, this.debounce);
      }
      valueChanged() {
          const inputEl = this.nativeInput;
          const value = this.getValue();
          if (inputEl && inputEl.value !== value) {
              inputEl.value = value;
          }
          this.ionChange.emit({ value });
      }
      showCancelButtonChanged() {
          requestAnimationFrame(() => {
              this.positionElements();
              this.el.forceUpdate();
          });
      }
      componentDidLoad() {
          if (this.showCancelButton === 'false' || this.showCancelButton === false) {
              console.warn('The boolean values of showCancelButton are deprecated. Please use "never" instead of "false".');
          }
          if (this.showCancelButton === '' || this.showCancelButton === 'true' || this.showCancelButton === true) {
              console.warn('The boolean values of showCancelButton are deprecated. Please use "focus" instead of "true".');
          }
          this.positionElements();
          this.debounceChanged();
          setTimeout(() => {
              this.noAnimate = false;
          }, 300);
      }
      /**
       * Sets focus on the specified `ion-searchbar`. 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 mode = getIonMode(this);
          const shouldAlignLeft = (!this.animated || value.trim() !== '' || !!this.focused);
          this.shouldAlignLeft = shouldAlignLeft;
          if (mode !== 'ios') {
              return;
          }
          if (prevAlignLeft !== shouldAlignLeft) {
              this.positionPlaceholder();
          }
          if (this.animated) {
              this.positionCancelButton();
          }
      }
      /**
       * Positions the input placeholder
       */
      positionPlaceholder() {
          const inputEl = this.nativeInput;
          if (!inputEl) {
              return;
          }
          const isRTL = document.dir === 'rtl';
          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.innerHTML = sanitizeDOMString(this.placeholder) || '';
              doc.body.appendChild(tempSpan);
              // Get the width of the span then remove it
              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 (isRTL) {
                  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 isRTL = document.dir === 'rtl';
          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 (isRTL) {
                      cancelStyle.marginLeft = '0';
                  }
                  else {
                      cancelStyle.marginRight = '0';
                  }
              }
              else {
                  const offset = cancelButton.offsetWidth;
                  if (offset > 0) {
                      if (isRTL) {
                          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 (isCancelButtonSetToNever(this.showCancelButton) ||
              (isCancelButtonSetToFocus(this.showCancelButton) && !this.focused)) {
              return false;
          }
          return true;
      }
      render() {
          const animated = this.animated && config.getBoolean('animated', true);
          const mode = getIonMode(this);
          const clearIcon = this.clearIcon || (mode === 'ios' ? 'ios-close-circle' : 'md-close');
          const searchIcon = this.searchIcon;
          const cancelButton = !isCancelButtonSetToNever(this.showCancelButton) && (h("button", { "aria-label": "cancel", type: "button", tabIndex: mode === 'ios' && !this.shouldShowCancelButton() ? -1 : undefined, onMouseDown: this.onCancelSearchbar, onTouchStart: this.onCancelSearchbar, class: "searchbar-cancel-button" },
              h("div", null, mode === 'md'
                  ? h("ion-icon", { "aria-hidden": "true", mode: mode, icon: this.cancelButtonIcon, lazy: false })
                  : this.cancelButtonText)));
          return (h(Host, { role: "search", "aria-disabled": this.disabled ? 'true' : null, class: Object.assign({}, createColorClasses(this.color), { [mode]: true, 'searchbar-animated': animated, 'searchbar-disabled': this.disabled, 'searchbar-no-animate': animated && this.noAnimate, 'searchbar-has-value': this.hasValue(), 'searchbar-left-aligned': this.shouldAlignLeft, 'searchbar-has-focus': this.focused, '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", onInput: this.onInput, onBlur: this.onBlur, onFocus: this.onFocus, placeholder: this.placeholder, type: this.type, value: this.getValue(), autoComplete: this.autocomplete, autoCorrect: this.autocorrect, spellCheck: this.spellcheck }),
                  mode === 'md' && cancelButton,
                  h("ion-icon", { mode: mode, icon: searchIcon, lazy: false, class: "searchbar-search-icon" }),
                  h("button", { "aria-label": "reset", type: "button", "no-blur": true, class: "searchbar-clear-button", onMouseDown: this.onClearInput, onTouchStart: this.onClearInput },
                      h("ion-icon", { "aria-hidden": "true", mode: mode, icon: clearIcon, lazy: false, class: "searchbar-clear-icon" }))),
              mode === 'ios' && cancelButton));
      }
      static get is() { return "ion-searchbar"; }
      static get encapsulation() { return "scoped"; }
      static get originalStyleUrls() { return {
          "ios": ["searchbar.ios.scss"],
          "md": ["searchbar.md.scss"]
      }; }
      static get styleUrls() { return {
          "ios": ["searchbar.ios.css"],
          "md": ["searchbar.md.css"]
      }; }
      static get properties() { return {
          "color": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "Color",
                  "resolved": "string | undefined",
                  "references": {
                      "Color": {
                          "location": "import",
                          "path": "../../interface"
                      }
                  }
              },
              "required": false,
              "optional": true,
              "docs": {
                  "tags": [],
                  "text": "The color to use from your application's color palette.\nDefault options are: `\"primary\"`, `\"secondary\"`, `\"tertiary\"`, `\"success\"`, `\"warning\"`, `\"danger\"`, `\"light\"`, `\"medium\"`, and `\"dark\"`.\nFor more information on colors, see [theming](/docs/theming/basics)."
              },
              "attribute": "color",
              "reflect": false
          },
          "animated": {
              "type": "boolean",
              "mutable": false,
              "complexType": {
                  "original": "boolean",
                  "resolved": "boolean",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "If `true`, enable searchbar animation."
              },
              "attribute": "animated",
              "reflect": false,
              "defaultValue": "false"
          },
          "autocomplete": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "'on' | 'off'",
                  "resolved": "\"off\" | \"on\"",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the input's autocomplete property."
              },
              "attribute": "autocomplete",
              "reflect": false,
              "defaultValue": "'off'"
          },
          "autocorrect": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "'on' | 'off'",
                  "resolved": "\"off\" | \"on\"",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the input's autocorrect property."
              },
              "attribute": "autocorrect",
              "reflect": false,
              "defaultValue": "'off'"
          },
          "cancelButtonIcon": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "string",
                  "resolved": "string",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the cancel button icon. Only applies to `md` mode."
              },
              "attribute": "cancel-button-icon",
              "reflect": false,
              "defaultValue": "'md-arrow-back'"
          },
          "cancelButtonText": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "string",
                  "resolved": "string",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the the cancel button text. Only applies to `ios` mode."
              },
              "attribute": "cancel-button-text",
              "reflect": false,
              "defaultValue": "'Cancel'"
          },
          "clearIcon": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "string",
                  "resolved": "string | undefined",
                  "references": {}
              },
              "required": false,
              "optional": true,
              "docs": {
                  "tags": [],
                  "text": "Set the clear icon. Defaults to `\"close-circle\"` for `ios` and `\"close\"` for `md`."
              },
              "attribute": "clear-icon",
              "reflect": false
          },
          "debounce": {
              "type": "number",
              "mutable": false,
              "complexType": {
                  "original": "number",
                  "resolved": "number",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the amount of time, in milliseconds, to wait to trigger the `ionChange` event after each keystroke."
              },
              "attribute": "debounce",
              "reflect": false,
              "defaultValue": "250"
          },
          "disabled": {
              "type": "boolean",
              "mutable": false,
              "complexType": {
                  "original": "boolean",
                  "resolved": "boolean",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "If `true`, the user cannot interact with the input."
              },
              "attribute": "disabled",
              "reflect": false,
              "defaultValue": "false"
          },
          "placeholder": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "string",
                  "resolved": "string",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the input's placeholder.\n`placeholder` can accept either plaintext or HTML as a string.\nTo display characters normally reserved for HTML, they\nmust be escaped. For example `<Ionic>` would become\n`&lt;Ionic&gt;`\n\nFor more information: [Security Documentation](https://ionicframework.com/docs/faq/security)"
              },
              "attribute": "placeholder",
              "reflect": false,
              "defaultValue": "'Search'"
          },
          "searchIcon": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "string",
                  "resolved": "string",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "The icon to use as the search icon."
              },
              "attribute": "search-icon",
              "reflect": false,
              "defaultValue": "'search'"
          },
          "showCancelButton": {
              "type": "any",
              "mutable": false,
              "complexType": {
                  "original": "boolean | string",
                  "resolved": "boolean | string",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Sets the behavior for the cancel button. Defaults to `\"never\"`.\nSetting to `\"focus\"` shows the cancel button on focus.\nSetting to `\"never\"` hides the cancel button.\nSetting to `\"always\"` shows the cancel button regardless\nof focus state."
              },
              "attribute": "show-cancel-button",
              "reflect": false,
              "defaultValue": "'never'"
          },
          "spellcheck": {
              "type": "boolean",
              "mutable": false,
              "complexType": {
                  "original": "boolean",
                  "resolved": "boolean",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "If `true`, enable spellcheck on the input."
              },
              "attribute": "spellcheck",
              "reflect": false,
              "defaultValue": "false"
          },
          "type": {
              "type": "string",
              "mutable": false,
              "complexType": {
                  "original": "'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url'",
                  "resolved": "\"email\" | \"number\" | \"password\" | \"search\" | \"tel\" | \"text\" | \"url\"",
                  "references": {}
              },
              "required": false,
              "optional": false,
              "docs": {
                  "tags": [],
                  "text": "Set the type of the input."
              },
              "attribute": "type",
              "reflect": false,
              "defaultValue": "'search'"
          },
          "value": {
              "type": "string",
              "mutable": true,
              "complexType": {
                  "original": "string | null",
                  "resolved": "null | string | undefined",
                  "references": {}
              },
              "required": false,
              "optional": true,
              "docs": {
                  "tags": [],
                  "text": "the value of the searchbar."
              },
              "attribute": "value",
              "reflect": false,
              "defaultValue": "''"
          }
      }; }
      static get states() { return {
          "focused": {},
          "noAnimate": {}
      }; }
      static get events() { return [{
              "method": "ionInput",
              "name": "ionInput",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when a keyboard input ocurred."
              },
              "complexType": {
                  "original": "KeyboardEvent",
                  "resolved": "KeyboardEvent",
                  "references": {
                      "KeyboardEvent": {
                          "location": "global"
                      }
                  }
              }
          }, {
              "method": "ionChange",
              "name": "ionChange",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when the value has changed."
              },
              "complexType": {
                  "original": "SearchbarChangeEventDetail",
                  "resolved": "SearchbarChangeEventDetail",
                  "references": {
                      "SearchbarChangeEventDetail": {
                          "location": "import",
                          "path": "../../interface"
                      }
                  }
              }
          }, {
              "method": "ionCancel",
              "name": "ionCancel",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when the cancel button is clicked."
              },
              "complexType": {
                  "original": "void",
                  "resolved": "void",
                  "references": {}
              }
          }, {
              "method": "ionClear",
              "name": "ionClear",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when the clear input button is clicked."
              },
              "complexType": {
                  "original": "void",
                  "resolved": "void",
                  "references": {}
              }
          }, {
              "method": "ionBlur",
              "name": "ionBlur",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when the input loses focus."
              },
              "complexType": {
                  "original": "void",
                  "resolved": "void",
                  "references": {}
              }
          }, {
              "method": "ionFocus",
              "name": "ionFocus",
              "bubbles": true,
              "cancelable": true,
              "composed": true,
              "docs": {
                  "tags": [],
                  "text": "Emitted when the input has focus."
              },
              "complexType": {
                  "original": "void",
                  "resolved": "void",
                  "references": {}
              }
          }]; }
      static get methods() { return {
          "setFocus": {
              "complexType": {
                  "signature": "() => Promise<void>",
                  "parameters": [],
                  "references": {
                      "Promise": {
                          "location": "global"
                      }
                  },
                  "return": "Promise<void>"
              },
              "docs": {
                  "text": "Sets focus on the specified `ion-searchbar`. Use this method instead of the global\n`input.focus()`.",
                  "tags": []
              }
          },
          "getInputElement": {
              "complexType": {
                  "signature": "() => Promise<HTMLInputElement>",
                  "parameters": [],
                  "references": {
                      "Promise": {
                          "location": "global"
                      },
                      "HTMLInputElement": {
                          "location": "global"
                      }
                  },
                  "return": "Promise<HTMLInputElement>"
              },
              "docs": {
                  "text": "Returns the native `<input>` element used under the hood.",
                  "tags": []
              }
          }
      }; }
      static get elementRef() { return "el"; }
      static get watchers() { return [{
              "propName": "debounce",
              "methodName": "debounceChanged"
          }, {
              "propName": "value",
              "methodName": "valueChanged"
          }, {
              "propName": "showCancelButton",
              "methodName": "showCancelButtonChanged"
          }]; }
  }
  /**
   * Check if the cancel button should never be shown.
   *
   * TODO: Remove this when the `true` and `false`
   * options are removed.
   */
  const isCancelButtonSetToNever = (showCancelButton) => {
      return (showCancelButton === 'never' ||
          showCancelButton === 'false' ||
          showCancelButton === false);
  };
  /**
   * Check if the cancel button should be shown on focus.
   *
   * TODO: Remove this when the `true` and `false`
   * options are removed.
   */
  const isCancelButtonSetToFocus = (showCancelButton) => {
      return (showCancelButton === 'focus' ||
          showCancelButton === 'true' ||
          showCancelButton === true ||
          showCancelButton === '');
  };
  