text: /**
   * @license
   * Copyright Google LLC All Rights Reserved.
   *
   * Use of this source code is governed by an MIT-style license that can be
   * found in the LICENSE file at https://angular.io/license
   */
  import { __extends } from 'tslib';
  import { CdkTextareaAutosize, AutofillMonitor, TextFieldModule } from '@angular/cdk/text-field';
  import { Directive, Input, InjectionToken, ElementRef, Inject, NgZone, Optional, Self, NgModule } from '@angular/core';
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
  import { getSupportedInputTypes, Platform } from '@angular/cdk/platform';
  import { FormGroupDirective, NgControl, NgForm } from '@angular/forms';
  import { ErrorStateMatcher, mixinErrorState } from '@angular/material/core';
  import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
  import { Subject } from 'rxjs';
  import { CommonModule } from '@angular/common';
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * Directive to automatically resize a textarea to fit its content.
   * @deprecated Use `cdkTextareaAutosize` from `\@angular/cdk/text-field` instead.
   * \@breaking-change 8.0.0
   */
  var MatTextareaAutosize = /** @class */ (function (_super) {
      __extends(MatTextareaAutosize, _super);
      function MatTextareaAutosize() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      Object.defineProperty(MatTextareaAutosize.prototype, "matAutosizeMinRows", {
          get: /**
           * @return {?}
           */
          function () { return this.minRows; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this.minRows = value; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatTextareaAutosize.prototype, "matAutosizeMaxRows", {
          get: /**
           * @return {?}
           */
          function () { return this.maxRows; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this.maxRows = value; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatTextareaAutosize.prototype, "matAutosize", {
          get: /**
           * @return {?}
           */
          function () { return this.enabled; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this.enabled = value; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatTextareaAutosize.prototype, "matTextareaAutosize", {
          get: /**
           * @return {?}
           */
          function () { return this.enabled; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this.enabled = value; },
          enumerable: true,
          configurable: true
      });
      MatTextareaAutosize.decorators = [
          { type: Directive, args: [{
                      selector: 'textarea[mat-autosize], textarea[matTextareaAutosize]',
                      exportAs: 'matTextareaAutosize',
                      inputs: ['cdkAutosizeMinRows', 'cdkAutosizeMaxRows'],
                      host: {
                          'class': 'cdk-textarea-autosize mat-autosize',
                          // Textarea elements that have the directive applied should have a single row by default.
                          // Browsers normally show two rows by default and therefore this limits the minRows binding.
                          'rows': '1',
                          '(input)': '_noopInputHandler()',
                      },
                  },] },
      ];
      MatTextareaAutosize.propDecorators = {
          matAutosizeMinRows: [{ type: Input }],
          matAutosizeMaxRows: [{ type: Input }],
          matAutosize: [{ type: Input, args: ['mat-autosize',] }],
          matTextareaAutosize: [{ type: Input }]
      };
      return MatTextareaAutosize;
  }(CdkTextareaAutosize));
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /**
   * \@docs-private
   * @param {?} type
   * @return {?}
   */
  function getMatInputUnsupportedTypeError(type) {
      return Error("Input type \"" + type + "\" isn't supported by matInput.");
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * This token is used to inject the object whose value should be set into `MatInput`. If none is
   * provided, the native `HTMLInputElement` is used. Directives like `MatDatepickerInput` can provide
   * themselves for this token, in order to make `MatInput` delegate the getting and setting of the
   * value to them.
   * @type {?}
   */
  var MAT_INPUT_VALUE_ACCESSOR = new InjectionToken('MAT_INPUT_VALUE_ACCESSOR');
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  // Invalid input type. Using one of these will throw an MatInputUnsupportedTypeError.
  /** @type {?} */
  var MAT_INPUT_INVALID_TYPES = [
      'button',
      'checkbox',
      'file',
      'hidden',
      'image',
      'radio',
      'range',
      'reset',
      'submit'
  ];
  /** @type {?} */
  var nextUniqueId = 0;
  // Boilerplate for applying mixins to MatInput.
  /**
   * \@docs-private
   */
  var 
  // Boilerplate for applying mixins to MatInput.
  /**
   * \@docs-private
   */
  MatInputBase = /** @class */ (function () {
      function MatInputBase(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) {
          this._defaultErrorStateMatcher = _defaultErrorStateMatcher;
          this._parentForm = _parentForm;
          this._parentFormGroup = _parentFormGroup;
          this.ngControl = ngControl;
      }
      return MatInputBase;
  }());
  /** @type {?} */
  var _MatInputMixinBase = mixinErrorState(MatInputBase);
  /**
   * Directive that allows a native input to work inside a `MatFormField`.
   */
  var MatInput = /** @class */ (function (_super) {
      __extends(MatInput, _super);
      function MatInput(_elementRef, _platform, ngControl, _parentForm, _parentFormGroup, _defaultErrorStateMatcher, inputValueAccessor, _autofillMonitor, ngZone) {
          var _this = _super.call(this, _defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) || this;
          _this._elementRef = _elementRef;
          _this._platform = _platform;
          _this.ngControl = ngControl;
          _this._autofillMonitor = _autofillMonitor;
          _this._uid = "mat-input-" + nextUniqueId++;
          /**
           * Whether the component is being rendered on the server.
           */
          _this._isServer = false;
          /**
           * Whether the component is a native html select.
           */
          _this._isNativeSelect = false;
          /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           */
          _this.focused = false;
          /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           */
          _this.stateChanges = new Subject();
          /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           */
          _this.controlType = 'mat-input';
          /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           */
          _this.autofilled = false;
          _this._disabled = false;
          _this._required = false;
          _this._type = 'text';
          _this._readonly = false;
          _this._neverEmptyInputTypes = [
              'date',
              'datetime',
              'datetime-local',
              'month',
              'time',
              'week'
          ].filter((/**
           * @param {?} t
           * @return {?}
           */
          function (t) { return getSupportedInputTypes().has(t); }));
          /** @type {?} */
          var element = _this._elementRef.nativeElement;
          // If no input value accessor was explicitly specified, use the element as the input value
          // accessor.
          _this._inputValueAccessor = inputValueAccessor || element;
          _this._previousNativeValue = _this.value;
          // Force setter to be called in case id was not specified.
          _this.id = _this.id;
          // On some versions of iOS the caret gets stuck in the wrong place when holding down the delete
          // key. In order to get around this we need to "jiggle" the caret loose. Since this bug only
          // exists on iOS, we only bother to install the listener on iOS.
          if (_platform.IOS) {
              ngZone.runOutsideAngular((/**
               * @return {?}
               */
              function () {
                  _elementRef.nativeElement.addEventListener('keyup', (/**
                   * @param {?} event
                   * @return {?}
                   */
                  function (event) {
                      /** @type {?} */
                      var el = (/** @type {?} */ (event.target));
                      if (!el.value && !el.selectionStart && !el.selectionEnd) {
                          // Note: Just setting `0, 0` doesn't fix the issue. Setting
                          // `1, 1` fixes it for the first time that you type text and
                          // then hold delete. Toggling to `1, 1` and then back to
                          // `0, 0` seems to completely fix it.
                          el.setSelectionRange(1, 1);
                          el.setSelectionRange(0, 0);
                      }
                  }));
              }));
          }
          _this._isServer = !_this._platform.isBrowser;
          _this._isNativeSelect = element.nodeName.toLowerCase() === 'select';
          if (_this._isNativeSelect) {
              _this.controlType = ((/** @type {?} */ (element))).multiple ? 'mat-native-select-multiple' :
                  'mat-native-select';
          }
          return _this;
      }
      Object.defineProperty(MatInput.prototype, "disabled", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () {
              if (this.ngControl && this.ngControl.disabled !== null) {
                  return this.ngControl.disabled;
              }
              return this._disabled;
          },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) {
              this._disabled = coerceBooleanProperty(value);
              // Browsers may not fire the blur event if the input is disabled too quickly.
              // Reset from here to ensure that the element doesn't become stuck.
              if (this.focused) {
                  this.focused = false;
                  this.stateChanges.next();
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "id", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () { return this._id; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this._id = value || this._uid; },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "required", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () { return this._required; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this._required = coerceBooleanProperty(value); },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "type", {
          /** Input type of the element. */
          get: /**
           * Input type of the element.
           * @return {?}
           */
          function () { return this._type; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) {
              this._type = value || 'text';
              this._validateType();
              // When using Angular inputs, developers are no longer able to set the properties on the native
              // input element. To ensure that bindings for `type` work, we need to sync the setter
              // with the native property. Textarea elements don't support the type property or attribute.
              if (!this._isTextarea() && getSupportedInputTypes().has(this._type)) {
                  ((/** @type {?} */ (this._elementRef.nativeElement))).type = this._type;
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "value", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () { return this._inputValueAccessor.value; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) {
              if (value !== this.value) {
                  this._inputValueAccessor.value = value;
                  this.stateChanges.next();
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "readonly", {
          /** Whether the element is readonly. */
          get: /**
           * Whether the element is readonly.
           * @return {?}
           */
          function () { return this._readonly; },
          set: /**
           * @param {?} value
           * @return {?}
           */
          function (value) { this._readonly = coerceBooleanProperty(value); },
          enumerable: true,
          configurable: true
      });
      /**
       * @return {?}
       */
      MatInput.prototype.ngOnInit = /**
       * @return {?}
       */
      function () {
          var _this = this;
          if (this._platform.isBrowser) {
              this._autofillMonitor.monitor(this._elementRef.nativeElement).subscribe((/**
               * @param {?} event
               * @return {?}
               */
              function (event) {
                  _this.autofilled = event.isAutofilled;
                  _this.stateChanges.next();
              }));
          }
      };
      /**
       * @return {?}
       */
      MatInput.prototype.ngOnChanges = /**
       * @return {?}
       */
      function () {
          this.stateChanges.next();
      };
      /**
       * @return {?}
       */
      MatInput.prototype.ngOnDestroy = /**
       * @return {?}
       */
      function () {
          this.stateChanges.complete();
          if (this._platform.isBrowser) {
              this._autofillMonitor.stopMonitoring(this._elementRef.nativeElement);
          }
      };
      /**
       * @return {?}
       */
      MatInput.prototype.ngDoCheck = /**
       * @return {?}
       */
      function () {
          if (this.ngControl) {
              // We need to re-evaluate this on every change detection cycle, because there are some
              // error triggers that we can't subscribe to (e.g. parent form submissions). This means
              // that whatever logic is in here has to be super lean or we risk destroying the performance.
              this.updateErrorState();
          }
          // We need to dirty-check the native element's value, because there are some cases where
          // we won't be notified when it changes (e.g. the consumer isn't using forms or they're
          // updating the value using `emitEvent: false`).
          this._dirtyCheckNativeValue();
      };
      /** Focuses the input. */
      /**
       * Focuses the input.
       * @return {?}
       */
      MatInput.prototype.focus = /**
       * Focuses the input.
       * @return {?}
       */
      function () {
          this._elementRef.nativeElement.focus();
      };
      /** Callback for the cases where the focused state of the input changes. */
      /**
       * Callback for the cases where the focused state of the input changes.
       * @param {?} isFocused
       * @return {?}
       */
      MatInput.prototype._focusChanged = /**
       * Callback for the cases where the focused state of the input changes.
       * @param {?} isFocused
       * @return {?}
       */
      function (isFocused) {
          if (isFocused !== this.focused && (!this.readonly || !isFocused)) {
              this.focused = isFocused;
              this.stateChanges.next();
          }
      };
      /**
       * @return {?}
       */
      MatInput.prototype._onInput = /**
       * @return {?}
       */
      function () {
          // This is a noop function and is used to let Angular know whenever the value changes.
          // Angular will run a new change detection each time the `input` event has been dispatched.
          // It's necessary that Angular recognizes the value change, because when floatingLabel
          // is set to false and Angular forms aren't used, the placeholder won't recognize the
          // value changes and will not disappear.
          // Listening to the input event wouldn't be necessary when the input is using the
          // FormsModule or ReactiveFormsModule, because Angular forms also listens to input events.
      };
      /** Does some manual dirty checking on the native input `value` property. */
      /**
       * Does some manual dirty checking on the native input `value` property.
       * @protected
       * @return {?}
       */
      MatInput.prototype._dirtyCheckNativeValue = /**
       * Does some manual dirty checking on the native input `value` property.
       * @protected
       * @return {?}
       */
      function () {
          /** @type {?} */
          var newValue = this._elementRef.nativeElement.value;
          if (this._previousNativeValue !== newValue) {
              this._previousNativeValue = newValue;
              this.stateChanges.next();
          }
      };
      /** Make sure the input is a supported type. */
      /**
       * Make sure the input is a supported type.
       * @protected
       * @return {?}
       */
      MatInput.prototype._validateType = /**
       * Make sure the input is a supported type.
       * @protected
       * @return {?}
       */
      function () {
          if (MAT_INPUT_INVALID_TYPES.indexOf(this._type) > -1) {
              throw getMatInputUnsupportedTypeError(this._type);
          }
      };
      /** Checks whether the input type is one of the types that are never empty. */
      /**
       * Checks whether the input type is one of the types that are never empty.
       * @protected
       * @return {?}
       */
      MatInput.prototype._isNeverEmpty = /**
       * Checks whether the input type is one of the types that are never empty.
       * @protected
       * @return {?}
       */
      function () {
          return this._neverEmptyInputTypes.indexOf(this._type) > -1;
      };
      /** Checks whether the input is invalid based on the native validation. */
      /**
       * Checks whether the input is invalid based on the native validation.
       * @protected
       * @return {?}
       */
      MatInput.prototype._isBadInput = /**
       * Checks whether the input is invalid based on the native validation.
       * @protected
       * @return {?}
       */
      function () {
          // The `validity` property won't be present on platform-server.
          /** @type {?} */
          var validity = ((/** @type {?} */ (this._elementRef.nativeElement))).validity;
          return validity && validity.badInput;
      };
      /** Determines if the component host is a textarea. */
      /**
       * Determines if the component host is a textarea.
       * @protected
       * @return {?}
       */
      MatInput.prototype._isTextarea = /**
       * Determines if the component host is a textarea.
       * @protected
       * @return {?}
       */
      function () {
          return this._elementRef.nativeElement.nodeName.toLowerCase() === 'textarea';
      };
      Object.defineProperty(MatInput.prototype, "empty", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () {
              return !this._isNeverEmpty() && !this._elementRef.nativeElement.value && !this._isBadInput() &&
                  !this.autofilled;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(MatInput.prototype, "shouldLabelFloat", {
          /**
           * Implemented as part of MatFormFieldControl.
           * @docs-private
           */
          get: /**
           * Implemented as part of MatFormFieldControl.
           * \@docs-private
           * @return {?}
           */
          function () {
              if (this._isNativeSelect) {
                  // For a single-selection `<select>`, the label should float when the selected option has
                  // a non-empty display value. For a `<select multiple>`, the label *always* floats to avoid
                  // overlapping the label with the options.
                  /** @type {?} */
                  var selectElement = (/** @type {?} */ (this._elementRef.nativeElement));
                  /** @type {?} */
                  var firstOption = selectElement.options[0];
                  // On most browsers the `selectedIndex` will always be 0, however on IE and Edge it'll be
                  // -1 if the `value` is set to something, that isn't in the list of options, at a later point.
                  return this.focused || selectElement.multiple || !this.empty ||
                      !!(selectElement.selectedIndex > -1 && firstOption && firstOption.label);
              }
              else {
                  return this.focused || !this.empty;
              }
          },
          enumerable: true,
          configurable: true
      });
      /**
       * Implemented as part of MatFormFieldControl.
       * @docs-private
       */
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @param {?} ids
       * @return {?}
       */
      MatInput.prototype.setDescribedByIds = /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @param {?} ids
       * @return {?}
       */
      function (ids) {
          this._ariaDescribedby = ids.join(' ');
      };
      /**
       * Implemented as part of MatFormFieldControl.
       * @docs-private
       */
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      MatInput.prototype.onContainerClick = /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      function () {
          // Do not re-focus the input element if the element is already focused. Otherwise it can happen
          // that someone clicks on a time input and the cursor resets to the "hours" field while the
          // "minutes" field was actually clicked. See: https://github.com/angular/components/issues/12849
          if (!this.focused) {
              this.focus();
          }
      };
      MatInput.decorators = [
          { type: Directive, args: [{
                      selector: "input[matInput], textarea[matInput], select[matNativeControl],\n      input[matNativeControl], textarea[matNativeControl]",
                      exportAs: 'matInput',
                      host: {
                          /**
                           * \@breaking-change 8.0.0 remove .mat-form-field-autofill-control in favor of AutofillMonitor.
                           */
                          'class': 'mat-input-element mat-form-field-autofill-control',
                          '[class.mat-input-server]': '_isServer',
                          // Native input properties that are overwritten by Angular inputs need to be synced with
                          // the native input element. Otherwise property bindings for those don't work.
                          '[attr.id]': 'id',
                          '[attr.placeholder]': 'placeholder',
                          '[disabled]': 'disabled',
                          '[required]': 'required',
                          '[attr.readonly]': 'readonly && !_isNativeSelect || null',
                          '[attr.aria-describedby]': '_ariaDescribedby || null',
                          '[attr.aria-invalid]': 'errorState',
                          '[attr.aria-required]': 'required.toString()',
                          '(blur)': '_focusChanged(false)',
                          '(focus)': '_focusChanged(true)',
                          '(input)': '_onInput()',
                      },
                      providers: [{ provide: MatFormFieldControl, useExisting: MatInput }],
                  },] },
      ];
      /** @nocollapse */
      MatInput.ctorParameters = function () { return [
          { type: ElementRef },
          { type: Platform },
          { type: NgControl, decorators: [{ type: Optional }, { type: Self }] },
          { type: NgForm, decorators: [{ type: Optional }] },
          { type: FormGroupDirective, decorators: [{ type: Optional }] },
          { type: ErrorStateMatcher },
          { type: undefined, decorators: [{ type: Optional }, { type: Self }, { type: Inject, args: [MAT_INPUT_VALUE_ACCESSOR,] }] },
          { type: AutofillMonitor },
          { type: NgZone }
      ]; };
      MatInput.propDecorators = {
          disabled: [{ type: Input }],
          id: [{ type: Input }],
          placeholder: [{ type: Input }],
          required: [{ type: Input }],
          type: [{ type: Input }],
          errorStateMatcher: [{ type: Input }],
          value: [{ type: Input }],
          readonly: [{ type: Input }]
      };
      return MatInput;
  }(_MatInputMixinBase));
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  var MatInputModule = /** @class */ (function () {
      function MatInputModule() {
      }
      MatInputModule.decorators = [
          { type: NgModule, args: [{
                      declarations: [MatInput, MatTextareaAutosize],
                      imports: [
                          CommonModule,
                          TextFieldModule,
                          MatFormFieldModule,
                      ],
                      exports: [
                          TextFieldModule,
                          // We re-export the `MatFormFieldModule` since `MatInput` will almost always
                          // be used together with `MatFormField`.
                          MatFormFieldModule,
                          MatInput,
                          MatTextareaAutosize,
                      ],
                      providers: [ErrorStateMatcher],
                  },] },
      ];
      return MatInputModule;
  }());
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  export { MatTextareaAutosize, MatInput, getMatInputUnsupportedTypeError, MatInputModule, MAT_INPUT_VALUE_ACCESSOR };
  //# sourceMappingURL=input.es5.js.map
  