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 { Inject, Injectable, Optional, PLATFORM_ID, NgModule, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
  import { isPlatformBrowser } from '@angular/common';
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  // Whether the current platform supports the V8 Break Iterator. The V8 check
  // is necessary to detect all Blink based browsers.
  /** @type {?} */
  import * as ɵngcc0 from '@angular/core';
  let hasV8BreakIterator;
  // We need a try/catch around the reference to `Intl`, because accessing it in some cases can
  // cause IE to throw. These cases are tied to particular versions of Windows and can happen if
  // the consumer is providing a polyfilled `Map`. See:
  // https://github.com/Microsoft/ChakraCore/issues/3189
  // https://github.com/angular/components/issues/15687
  try {
      hasV8BreakIterator = (typeof Intl !== 'undefined' && ((/** @type {?} */ (Intl))).v8BreakIterator);
  }
  catch (_a) {
      hasV8BreakIterator = false;
  }
  /**
   * Service to detect the current platform by comparing the userAgent strings and
   * checking browser-specific global properties.
   */
  class Platform {
      /**
       * \@breaking-change 8.0.0 remove optional decorator
       * @param {?=} _platformId
       */
      constructor(_platformId) {
          this._platformId = _platformId;
          /**
           * Whether the Angular application is being rendered in the browser.
           * We want to use the Angular platform check because if the Document is shimmed
           * without the navigator, the following checks will fail. This is preferred because
           * sometimes the Document may be shimmed without the user's knowledge or intention
           */
          this.isBrowser = this._platformId ?
              isPlatformBrowser(this._platformId) : typeof document === 'object' && !!document;
          /**
           * Whether the current browser is Microsoft Edge.
           */
          this.EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent);
          /**
           * Whether the current rendering engine is Microsoft Trident.
           */
          this.TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);
          /**
           * Whether the current rendering engine is Blink.
           */
          // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check.
          this.BLINK = this.isBrowser && (!!(((/** @type {?} */ (window))).chrome || hasV8BreakIterator) &&
              typeof CSS !== 'undefined' && !this.EDGE && !this.TRIDENT);
          /**
           * Whether the current rendering engine is WebKit.
           */
          // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
          // ensure that Webkit runs standalone and is not used as another engine's base.
          this.WEBKIT = this.isBrowser &&
              /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
          /**
           * Whether the current platform is Apple iOS.
           */
          this.IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) &&
              !('MSStream' in window);
          /**
           * Whether the current browser is Firefox.
           */
          // It's difficult to detect the plain Gecko engine, because most of the browsers identify
          // them self as Gecko-like browsers and modify the userAgent's according to that.
          // Since we only cover one explicit Firefox case, we can simply check for Firefox
          // instead of having an unstable check for Gecko.
          this.FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
          /**
           * Whether the current platform is Android.
           */
          // Trident on mobile adds the android platform to the userAgent to trick detections.
          this.ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT;
          /**
           * Whether the current browser is Safari.
           */
          // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake
          // this and just place the Safari keyword in the userAgent. To be more safe about Safari every
          // Safari browser should also use Webkit as its layout engine.
          this.SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;
      }
  }
  Platform.ɵfac = function Platform_Factory(t) { return new (t || Platform)(ɵngcc0.ɵɵinject(PLATFORM_ID, 8)); };
  Platform.ɵprov = ɵngcc0.ɵɵdefineInjectable({ token: Platform, factory: Platform.ɵfac, providedIn: 'root' });
  /** @nocollapse */
  Platform.ctorParameters = () => [
      { type: Object, decorators: [{ type: Optional }, { type: Inject, args: [PLATFORM_ID,] }] }
  ];
  /** @nocollapse */ Platform.ngInjectableDef = ɵɵdefineInjectable({ factory: function Platform_Factory() { return new Platform(ɵɵinject(PLATFORM_ID, 8)); }, token: Platform, providedIn: "root" });
  /*@__PURE__*/ (function () { ɵngcc0.ɵsetClassMetadata(Platform, [{
          type: Injectable,
          args: [{ providedIn: 'root' }]
      }], function () { return [{ type: Object, decorators: [{
                  type: Optional
              }, {
                  type: Inject,
                  args: [PLATFORM_ID]
              }] }]; }, null); })();
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  class PlatformModule {
  }
  PlatformModule.ɵmod = ɵngcc0.ɵɵdefineNgModule({ type: PlatformModule });
  PlatformModule.ɵinj = ɵngcc0.ɵɵdefineInjector({ factory: function PlatformModule_Factory(t) { return new (t || PlatformModule)(); } });
  /*@__PURE__*/ (function () { ɵngcc0.ɵsetClassMetadata(PlatformModule, [{
          type: NgModule,
          args: [{}]
      }], null, null); })();
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /**
   * Cached result Set of input types support by the current browser.
   * @type {?}
   */
  let supportedInputTypes;
  /**
   * Types of `<input>` that *might* be supported.
   * @type {?}
   */
  const candidateInputTypes = [
      // `color` must come first. Chrome 56 shows a warning if we change the type to `color` after
      // first changing it to something else:
      // The specified value "" does not conform to the required format.
      // The format is "#rrggbb" where rr, gg, bb are two-digit hexadecimal numbers.
      'color',
      'button',
      'checkbox',
      'date',
      'datetime-local',
      'email',
      'file',
      'hidden',
      'image',
      'month',
      'number',
      'password',
      'radio',
      'range',
      'reset',
      'search',
      'submit',
      'tel',
      'text',
      'time',
      'url',
      'week',
  ];
  /**
   * @return {?} The input types supported by this browser.
   */
  function getSupportedInputTypes() {
      // Result is cached.
      if (supportedInputTypes) {
          return supportedInputTypes;
      }
      // We can't check if an input type is not supported until we're on the browser, so say that
      // everything is supported when not on the browser. We don't use `Platform` here since it's
      // just a helper function and can't inject it.
      if (typeof document !== 'object' || !document) {
          supportedInputTypes = new Set(candidateInputTypes);
          return supportedInputTypes;
      }
      /** @type {?} */
      let featureTestInput = document.createElement('input');
      supportedInputTypes = new Set(candidateInputTypes.filter((/**
       * @param {?} value
       * @return {?}
       */
      value => {
          featureTestInput.setAttribute('type', value);
          return featureTestInput.type === value;
      })));
      return supportedInputTypes;
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /**
   * Cached result of whether the user's browser supports passive event listeners.
   * @type {?}
   */
  let supportsPassiveEvents;
  /**
   * Checks whether the user's browser supports passive event listeners.
   * See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
   * @return {?}
   */
  function supportsPassiveEventListeners() {
      if (supportsPassiveEvents == null && typeof window !== 'undefined') {
          try {
              window.addEventListener('test', (/** @type {?} */ (null)), Object.defineProperty({}, 'passive', {
                  get: (/**
                   * @return {?}
                   */
                  () => supportsPassiveEvents = true)
              }));
          }
          finally {
              supportsPassiveEvents = supportsPassiveEvents || false;
          }
      }
      return supportsPassiveEvents;
  }
  /**
   * Normalizes an `AddEventListener` object to something that can be passed
   * to `addEventListener` on any browser, no matter whether it supports the
   * `options` parameter.
   * @param {?} options Object to be normalized.
   * @return {?}
   */
  function normalizePassiveListenerOptions(options) {
      return supportsPassiveEventListeners() ? options : !!options.capture;
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /** @enum {number} */
  const RtlScrollAxisType = {
      /**
       * scrollLeft is 0 when scrolled all the way left and (scrollWidth - clientWidth) when scrolled
       * all the way right.
       */
      NORMAL: 0,
      /**
       * scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
       * all the way right.
       */
      NEGATED: 1,
      /**
       * scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
       * all the way right.
       */
      INVERTED: 2,
  };
  RtlScrollAxisType[RtlScrollAxisType.NORMAL] = 'NORMAL';
  RtlScrollAxisType[RtlScrollAxisType.NEGATED] = 'NEGATED';
  RtlScrollAxisType[RtlScrollAxisType.INVERTED] = 'INVERTED';
  /**
   * Cached result of the way the browser handles the horizontal scroll axis in RTL mode.
   * @type {?}
   */
  let rtlScrollAxisType;
  /**
   * Check whether the browser supports scroll behaviors.
   * @return {?}
   */
  function supportsScrollBehavior() {
      return !!(typeof document == 'object' && 'scrollBehavior' in (/** @type {?} */ (document.documentElement)).style);
  }
  /**
   * Checks the type of RTL scroll axis used by this browser. As of time of writing, Chrome is NORMAL,
   * Firefox & Safari are NEGATED, and IE & Edge are INVERTED.
   * @return {?}
   */
  function getRtlScrollAxisType() {
      // We can't check unless we're on the browser. Just assume 'normal' if we're not.
      if (typeof document !== 'object' || !document) {
          return RtlScrollAxisType.NORMAL;
      }
      if (!rtlScrollAxisType) {
          // Create a 1px wide scrolling container and a 2px wide content element.
          /** @type {?} */
          const scrollContainer = document.createElement('div');
          /** @type {?} */
          const containerStyle = scrollContainer.style;
          scrollContainer.dir = 'rtl';
          containerStyle.height = '1px';
          containerStyle.width = '1px';
          containerStyle.overflow = 'auto';
          containerStyle.visibility = 'hidden';
          containerStyle.pointerEvents = 'none';
          containerStyle.position = 'absolute';
          /** @type {?} */
          const content = document.createElement('div');
          /** @type {?} */
          const contentStyle = content.style;
          contentStyle.width = '2px';
          contentStyle.height = '1px';
          scrollContainer.appendChild(content);
          document.body.appendChild(scrollContainer);
          rtlScrollAxisType = RtlScrollAxisType.NORMAL;
          // The viewport starts scrolled all the way to the right in RTL mode. If we are in a NORMAL
          // browser this would mean that the scrollLeft should be 1. If it's zero instead we know we're
          // dealing with one of the other two types of browsers.
          if (scrollContainer.scrollLeft === 0) {
              // In a NEGATED browser the scrollLeft is always somewhere in [-maxScrollAmount, 0]. For an
              // INVERTED browser it is always somewhere in [0, maxScrollAmount]. We can determine which by
              // setting to the scrollLeft to 1. This is past the max for a NEGATED browser, so it will
              // return 0 when we read it again.
              scrollContainer.scrollLeft = 1;
              rtlScrollAxisType =
                  scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED;
          }
          (/** @type {?} */ (scrollContainer.parentNode)).removeChild(scrollContainer);
      }
      return rtlScrollAxisType;
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /** @type {?} */
  let shadowDomIsSupported;
  /**
   * Checks whether the user's browser support Shadow DOM.
   * @return {?}
   */
  function _supportsShadowDom() {
      if (shadowDomIsSupported == null) {
          /** @type {?} */
          const head = typeof document !== 'undefined' ? document.head : null;
          shadowDomIsSupported = !!(head && (((/** @type {?} */ (head))).createShadowRoot || head.attachShadow));
      }
      return shadowDomIsSupported;
  }
  
  /**
   * @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 { Platform, PlatformModule, getSupportedInputTypes, supportsPassiveEventListeners, normalizePassiveListenerOptions, supportsScrollBehavior, getRtlScrollAxisType, RtlScrollAxisType, _supportsShadowDom };
  
  //# sourceMappingURL=platform.js.map