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 { 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,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
   */
  class MatTextareaAutosize extends CdkTextareaAutosize {
      /**
       * @return {?}
       */
      get matAutosizeMinRows() { return this.minRows; }
      /**
       * @param {?} value
       * @return {?}
       */
      set matAutosizeMinRows(value) { this.minRows = value; }
      /**
       * @return {?}
       */
      get matAutosizeMaxRows() { return this.maxRows; }
      /**
       * @param {?} value
       * @return {?}
       */
      set matAutosizeMaxRows(value) { this.maxRows = value; }
      /**
       * @return {?}
       */
      get matAutosize() { return this.enabled; }
      /**
       * @param {?} value
       * @return {?}
       */
      set matAutosize(value) { this.enabled = value; }
      /**
       * @return {?}
       */
      get matTextareaAutosize() { return this.enabled; }
      /**
       * @param {?} value
       * @return {?}
       */
      set matTextareaAutosize(value) { this.enabled = value; }
  }
  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 }]
  };
  // TODO(devversion): workaround for https://github.com/angular/material2/issues/12760
  (/** @type {?} */ (MatTextareaAutosize))['ctorParameters'] = () => (/** @type {?} */ (CdkTextareaAutosize))['ctorParameters'];
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,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,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 {?} */
  const MAT_INPUT_VALUE_ACCESSOR = new InjectionToken('MAT_INPUT_VALUE_ACCESSOR');
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
   */
  /** @type {?} */
  const MAT_INPUT_INVALID_TYPES = [
      'button',
      'checkbox',
      'file',
      'hidden',
      'image',
      'radio',
      'range',
      'reset',
      'submit'
  ];
  /** @type {?} */
  let nextUniqueId = 0;
  /**
   * \@docs-private
   */
  class MatInputBase {
      /**
       * @param {?} _defaultErrorStateMatcher
       * @param {?} _parentForm
       * @param {?} _parentFormGroup
       * @param {?} ngControl
       */
      constructor(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) {
          this._defaultErrorStateMatcher = _defaultErrorStateMatcher;
          this._parentForm = _parentForm;
          this._parentFormGroup = _parentFormGroup;
          this.ngControl = ngControl;
      }
  }
  /** @type {?} */
  const _MatInputMixinBase = mixinErrorState(MatInputBase);
  /**
   * Directive that allows a native input to work inside a `MatFormField`.
   */
  class MatInput extends _MatInputMixinBase {
      /**
       * @param {?} _elementRef
       * @param {?} _platform
       * @param {?} ngControl
       * @param {?} _parentForm
       * @param {?} _parentFormGroup
       * @param {?} _defaultErrorStateMatcher
       * @param {?} inputValueAccessor
       * @param {?} _autofillMonitor
       * @param {?} ngZone
       */
      constructor(_elementRef, _platform, /** @docs-private */
      ngControl, _parentForm, _parentFormGroup, _defaultErrorStateMatcher, inputValueAccessor, _autofillMonitor, ngZone) {
          super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl);
          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(t => getSupportedInputTypes().has(t));
          /** @type {?} */
          const 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(() => {
                  _elementRef.nativeElement.addEventListener('keyup', (event) => {
                      /** @type {?} */
                      let 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';
          }
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get disabled() {
          if (this.ngControl && this.ngControl.disabled !== null) {
              return this.ngControl.disabled;
          }
          return this._disabled;
      }
      /**
       * @param {?} value
       * @return {?}
       */
      set disabled(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();
          }
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get id() { return this._id; }
      /**
       * @param {?} value
       * @return {?}
       */
      set id(value) { this._id = value || this._uid; }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get required() { return this._required; }
      /**
       * @param {?} value
       * @return {?}
       */
      set required(value) { this._required = coerceBooleanProperty(value); }
      /**
       * Input type of the element.
       * @return {?}
       */
      get type() { return this._type; }
      /**
       * @param {?} value
       * @return {?}
       */
      set type(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;
          }
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get value() { return this._inputValueAccessor.value; }
      /**
       * @param {?} value
       * @return {?}
       */
      set value(value) {
          if (value !== this.value) {
              this._inputValueAccessor.value = value;
              this.stateChanges.next();
          }
      }
      /**
       * Whether the element is readonly.
       * @return {?}
       */
      get readonly() { return this._readonly; }
      /**
       * @param {?} value
       * @return {?}
       */
      set readonly(value) { this._readonly = coerceBooleanProperty(value); }
      /**
       * @return {?}
       */
      ngOnInit() {
          if (this._platform.isBrowser) {
              this._autofillMonitor.monitor(this._elementRef.nativeElement).subscribe(event => {
                  this.autofilled = event.isAutofilled;
                  this.stateChanges.next();
              });
          }
      }
      /**
       * @return {?}
       */
      ngOnChanges() {
          this.stateChanges.next();
      }
      /**
       * @return {?}
       */
      ngOnDestroy() {
          this.stateChanges.complete();
          if (this._platform.isBrowser) {
              this._autofillMonitor.stopMonitoring(this._elementRef.nativeElement);
          }
      }
      /**
       * @return {?}
       */
      ngDoCheck() {
          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.
       * @return {?}
       */
      focus() { this._elementRef.nativeElement.focus(); }
      /**
       * Callback for the cases where the focused state of the input changes.
       * @param {?} isFocused
       * @return {?}
       */
      _focusChanged(isFocused) {
          if (isFocused !== this.focused && !this.readonly) {
              this.focused = isFocused;
              this.stateChanges.next();
          }
      }
      /**
       * @return {?}
       */
      _onInput() {
          // 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.
       * @return {?}
       */
      _dirtyCheckNativeValue() {
          /** @type {?} */
          const newValue = this._elementRef.nativeElement.value;
          if (this._previousNativeValue !== newValue) {
              this._previousNativeValue = newValue;
              this.stateChanges.next();
          }
      }
      /**
       * Make sure the input is a supported type.
       * @return {?}
       */
      _validateType() {
          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.
       * @return {?}
       */
      _isNeverEmpty() {
          return this._neverEmptyInputTypes.indexOf(this._type) > -1;
      }
      /**
       * Checks whether the input is invalid based on the native validation.
       * @return {?}
       */
      _isBadInput() {
          /** @type {?} */
          let validity = (/** @type {?} */ (this._elementRef.nativeElement)).validity;
          return validity && validity.badInput;
      }
      /**
       * Determines if the component host is a textarea.
       * @return {?}
       */
      _isTextarea() {
          return this._elementRef.nativeElement.nodeName.toLowerCase() === 'textarea';
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get empty() {
          return !this._isNeverEmpty() && !this._elementRef.nativeElement.value && !this._isBadInput() &&
              !this.autofilled;
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      get shouldLabelFloat() {
          if (this._isNativeSelect) {
              /** @type {?} */
              const selectElement = /** @type {?} */ (this._elementRef.nativeElement);
              return selectElement.multiple || !this.empty || !!selectElement.options[0].label ||
                  this.focused;
          }
          else {
              return this.focused || !this.empty;
          }
      }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @param {?} ids
       * @return {?}
       */
      setDescribedByIds(ids) { this._ariaDescribedby = ids.join(' '); }
      /**
       * Implemented as part of MatFormFieldControl.
       * \@docs-private
       * @return {?}
       */
      onContainerClick() {
          // 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/material2/issues/12849
          if (!this.focused) {
              this.focus();
          }
      }
  }
  MatInput.decorators = [
      { type: Directive, args: [{
                  selector: `input[matInput], textarea[matInput], select[matNativeControl],
        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 = () => [
      { 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 }]
  };
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
   */
  class MatInputModule {
  }
  MatInputModule.decorators = [
      { type: NgModule, args: [{
                  declarations: [MatInput, MatTextareaAutosize],
                  imports: [
                      CommonModule,
                      TextFieldModule,
                      MatFormFieldModule,
                  ],
                  exports: [
                      TextFieldModule,
                      MatFormFieldModule,
                      MatInput,
                      MatTextareaAutosize,
                  ],
                  providers: [ErrorStateMatcher],
              },] },
  ];
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
   */
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
   */
  
  export { MatTextareaAutosize, MatInputBase, _MatInputMixinBase, MatInput, getMatInputUnsupportedTypeError, MatInputModule, MAT_INPUT_VALUE_ACCESSOR };
  //# sourceMappingURL=input.js.map
  