text: /**
   * @license
   * Copyright 2018 Google Inc.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  import { __assign, __extends } from "tslib";
  import { MDCFoundation } from '../base/foundation';
  import { numbers, strings } from './constants';
  var ACCEPTABLE_KEYS = new Set();
  // IE11 has no support for new Set with iterable so we need to initialize this by hand
  ACCEPTABLE_KEYS.add(strings.ARROW_LEFT_KEY);
  ACCEPTABLE_KEYS.add(strings.ARROW_RIGHT_KEY);
  ACCEPTABLE_KEYS.add(strings.END_KEY);
  ACCEPTABLE_KEYS.add(strings.HOME_KEY);
  ACCEPTABLE_KEYS.add(strings.ENTER_KEY);
  ACCEPTABLE_KEYS.add(strings.SPACE_KEY);
  var KEYCODE_MAP = new Map();
  // IE11 has no support for new Map with iterable so we need to initialize this by hand
  KEYCODE_MAP.set(numbers.ARROW_LEFT_KEYCODE, strings.ARROW_LEFT_KEY);
  KEYCODE_MAP.set(numbers.ARROW_RIGHT_KEYCODE, strings.ARROW_RIGHT_KEY);
  KEYCODE_MAP.set(numbers.END_KEYCODE, strings.END_KEY);
  KEYCODE_MAP.set(numbers.HOME_KEYCODE, strings.HOME_KEY);
  KEYCODE_MAP.set(numbers.ENTER_KEYCODE, strings.ENTER_KEY);
  KEYCODE_MAP.set(numbers.SPACE_KEYCODE, strings.SPACE_KEY);
  var MDCTabBarFoundation = /** @class */ (function (_super) {
      __extends(MDCTabBarFoundation, _super);
      function MDCTabBarFoundation(adapter) {
          var _this = _super.call(this, __assign(__assign({}, MDCTabBarFoundation.defaultAdapter), adapter)) || this;
          _this.useAutomaticActivation = false;
          return _this;
      }
      Object.defineProperty(MDCTabBarFoundation, "strings", {
          get: function () {
              return strings;
          },
          enumerable: false,
          configurable: true
      });
      Object.defineProperty(MDCTabBarFoundation, "numbers", {
          get: function () {
              return numbers;
          },
          enumerable: false,
          configurable: true
      });
      Object.defineProperty(MDCTabBarFoundation, "defaultAdapter", {
          get: function () {
              // tslint:disable:object-literal-sort-keys Methods should be in the same order as the adapter interface.
              return {
                  scrollTo: function () { return undefined; },
                  incrementScroll: function () { return undefined; },
                  getScrollPosition: function () { return 0; },
                  getScrollContentWidth: function () { return 0; },
                  getOffsetWidth: function () { return 0; },
                  isRTL: function () { return false; },
                  setActiveTab: function () { return undefined; },
                  activateTabAtIndex: function () { return undefined; },
                  deactivateTabAtIndex: function () { return undefined; },
                  focusTabAtIndex: function () { return undefined; },
                  getTabIndicatorClientRectAtIndex: function () { return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 }); },
                  getTabDimensionsAtIndex: function () { return ({ rootLeft: 0, rootRight: 0, contentLeft: 0, contentRight: 0 }); },
                  getPreviousActiveTabIndex: function () { return -1; },
                  getFocusedTabIndex: function () { return -1; },
                  getIndexOfTabById: function () { return -1; },
                  getTabListLength: function () { return 0; },
                  notifyTabActivated: function () { return undefined; },
              };
              // tslint:enable:object-literal-sort-keys
          },
          enumerable: false,
          configurable: true
      });
      /**
       * Switches between automatic and manual activation modes.
       * See https://www.w3.org/TR/wai-aria-practices/#tabpanel for examples.
       */
      MDCTabBarFoundation.prototype.setUseAutomaticActivation = function (useAutomaticActivation) {
          this.useAutomaticActivation = useAutomaticActivation;
      };
      MDCTabBarFoundation.prototype.activateTab = function (index) {
          var previousActiveIndex = this.adapter.getPreviousActiveTabIndex();
          if (!this.indexIsInRange(index) || index === previousActiveIndex) {
              return;
          }
          var previousClientRect;
          if (previousActiveIndex !== -1) {
              this.adapter.deactivateTabAtIndex(previousActiveIndex);
              previousClientRect =
                  this.adapter.getTabIndicatorClientRectAtIndex(previousActiveIndex);
          }
          this.adapter.activateTabAtIndex(index, previousClientRect);
          this.scrollIntoView(index);
          this.adapter.notifyTabActivated(index);
      };
      MDCTabBarFoundation.prototype.handleKeyDown = function (evt) {
          // Get the key from the event
          var key = this.getKeyFromEvent(evt);
          // Early exit if the event key isn't one of the keyboard navigation keys
          if (key === undefined) {
              return;
          }
          // Prevent default behavior for movement keys, but not for activation keys, since :active is used to apply ripple
          if (!this.isActivationKey(key)) {
              evt.preventDefault();
          }
          if (this.useAutomaticActivation) {
              if (this.isActivationKey(key)) {
                  return;
              }
              var index = this.determineTargetFromKey(this.adapter.getPreviousActiveTabIndex(), key);
              this.adapter.setActiveTab(index);
              this.scrollIntoView(index);
          }
          else {
              var focusedTabIndex = this.adapter.getFocusedTabIndex();
              if (this.isActivationKey(key)) {
                  this.adapter.setActiveTab(focusedTabIndex);
              }
              else {
                  var index = this.determineTargetFromKey(focusedTabIndex, key);
                  this.adapter.focusTabAtIndex(index);
                  this.scrollIntoView(index);
              }
          }
      };
      /**
       * Handles the MDCTab:interacted event
       */
      MDCTabBarFoundation.prototype.handleTabInteraction = function (evt) {
          this.adapter.setActiveTab(this.adapter.getIndexOfTabById(evt.detail.tabId));
      };
      /**
       * Scrolls the tab at the given index into view
       * @param index The tab index to make visible
       */
      MDCTabBarFoundation.prototype.scrollIntoView = function (index) {
          // Early exit if the index is out of range
          if (!this.indexIsInRange(index)) {
              return;
          }
          // Always scroll to 0 if scrolling to the 0th index
          if (index === 0) {
              this.adapter.scrollTo(0);
              return;
          }
          // Always scroll to the max value if scrolling to the Nth index
          // MDCTabScroller.scrollTo() will never scroll past the max possible value
          if (index === this.adapter.getTabListLength() - 1) {
              this.adapter.scrollTo(this.adapter.getScrollContentWidth());
              return;
          }
          if (this.isRTL()) {
              this.scrollIntoViewImplRTL(index);
              return;
          }
          this.scrollIntoViewImpl(index);
      };
      /**
       * Private method for determining the index of the destination tab based on what key was pressed
       * @param origin The original index from which to determine the destination
       * @param key The name of the key
       */
      MDCTabBarFoundation.prototype.determineTargetFromKey = function (origin, key) {
          var isRTL = this.isRTL();
          var maxIndex = this.adapter.getTabListLength() - 1;
          var shouldGoToEnd = key === strings.END_KEY;
          var shouldDecrement = key === strings.ARROW_LEFT_KEY && !isRTL || key === strings.ARROW_RIGHT_KEY && isRTL;
          var shouldIncrement = key === strings.ARROW_RIGHT_KEY && !isRTL || key === strings.ARROW_LEFT_KEY && isRTL;
          var index = origin;
          if (shouldGoToEnd) {
              index = maxIndex;
          }
          else if (shouldDecrement) {
              index -= 1;
          }
          else if (shouldIncrement) {
              index += 1;
          }
          else {
              index = 0;
          }
          if (index < 0) {
              index = maxIndex;
          }
          else if (index > maxIndex) {
              index = 0;
          }
          return index;
      };
      /**
       * Calculates the scroll increment that will make the tab at the given index visible
       * @param index The index of the tab
       * @param nextIndex The index of the next tab
       * @param scrollPosition The current scroll position
       * @param barWidth The width of the Tab Bar
       */
      MDCTabBarFoundation.prototype.calculateScrollIncrement = function (index, nextIndex, scrollPosition, barWidth) {
          var nextTabDimensions = this.adapter.getTabDimensionsAtIndex(nextIndex);
          var relativeContentLeft = nextTabDimensions.contentLeft - scrollPosition - barWidth;
          var relativeContentRight = nextTabDimensions.contentRight - scrollPosition;
          var leftIncrement = relativeContentRight - numbers.EXTRA_SCROLL_AMOUNT;
          var rightIncrement = relativeContentLeft + numbers.EXTRA_SCROLL_AMOUNT;
          if (nextIndex < index) {
              return Math.min(leftIncrement, 0);
          }
          return Math.max(rightIncrement, 0);
      };
      /**
       * Calculates the scroll increment that will make the tab at the given index visible in RTL
       * @param index The index of the tab
       * @param nextIndex The index of the next tab
       * @param scrollPosition The current scroll position
       * @param barWidth The width of the Tab Bar
       * @param scrollContentWidth The width of the scroll content
       */
      MDCTabBarFoundation.prototype.calculateScrollIncrementRTL = function (index, nextIndex, scrollPosition, barWidth, scrollContentWidth) {
          var nextTabDimensions = this.adapter.getTabDimensionsAtIndex(nextIndex);
          var relativeContentLeft = scrollContentWidth - nextTabDimensions.contentLeft - scrollPosition;
          var relativeContentRight = scrollContentWidth - nextTabDimensions.contentRight - scrollPosition - barWidth;
          var leftIncrement = relativeContentRight + numbers.EXTRA_SCROLL_AMOUNT;
          var rightIncrement = relativeContentLeft - numbers.EXTRA_SCROLL_AMOUNT;
          if (nextIndex > index) {
              return Math.max(leftIncrement, 0);
          }
          return Math.min(rightIncrement, 0);
      };
      /**
       * Determines the index of the adjacent tab closest to either edge of the Tab Bar
       * @param index The index of the tab
       * @param tabDimensions The dimensions of the tab
       * @param scrollPosition The current scroll position
       * @param barWidth The width of the tab bar
       */
      MDCTabBarFoundation.prototype.findAdjacentTabIndexClosestToEdge = function (index, tabDimensions, scrollPosition, barWidth) {
          /**
           * Tabs are laid out in the Tab Scroller like this:
           *
           *    Scroll Position
           *    +---+
           *    |   |   Bar Width
           *    |   +-----------------------------------+
           *    |   |                                   |
           *    |   V                                   V
           *    |   +-----------------------------------+
           *    V   |             Tab Scroller          |
           *    +------------+--------------+-------------------+
           *    |    Tab     |      Tab     |        Tab        |
           *    +------------+--------------+-------------------+
           *        |                                   |
           *        +-----------------------------------+
           *
           * To determine the next adjacent index, we look at the Tab root left and
           * Tab root right, both relative to the scroll position. If the Tab root
           * left is less than 0, then we know it's out of view to the left. If the
           * Tab root right minus the bar width is greater than 0, we know the Tab is
           * out of view to the right. From there, we either increment or decrement
           * the index.
           */
          var relativeRootLeft = tabDimensions.rootLeft - scrollPosition;
          var relativeRootRight = tabDimensions.rootRight - scrollPosition - barWidth;
          var relativeRootDelta = relativeRootLeft + relativeRootRight;
          var leftEdgeIsCloser = relativeRootLeft < 0 || relativeRootDelta < 0;
          var rightEdgeIsCloser = relativeRootRight > 0 || relativeRootDelta > 0;
          if (leftEdgeIsCloser) {
              return index - 1;
          }
          if (rightEdgeIsCloser) {
              return index + 1;
          }
          return -1;
      };
      /**
       * Determines the index of the adjacent tab closest to either edge of the Tab Bar in RTL
       * @param index The index of the tab
       * @param tabDimensions The dimensions of the tab
       * @param scrollPosition The current scroll position
       * @param barWidth The width of the tab bar
       * @param scrollContentWidth The width of the scroller content
       */
      MDCTabBarFoundation.prototype.findAdjacentTabIndexClosestToEdgeRTL = function (index, tabDimensions, scrollPosition, barWidth, scrollContentWidth) {
          var rootLeft = scrollContentWidth - tabDimensions.rootLeft - barWidth - scrollPosition;
          var rootRight = scrollContentWidth - tabDimensions.rootRight - scrollPosition;
          var rootDelta = rootLeft + rootRight;
          var leftEdgeIsCloser = rootLeft > 0 || rootDelta > 0;
          var rightEdgeIsCloser = rootRight < 0 || rootDelta < 0;
          if (leftEdgeIsCloser) {
              return index + 1;
          }
          if (rightEdgeIsCloser) {
              return index - 1;
          }
          return -1;
      };
      /**
       * Returns the key associated with a keydown event
       * @param evt The keydown event
       */
      MDCTabBarFoundation.prototype.getKeyFromEvent = function (evt) {
          if (ACCEPTABLE_KEYS.has(evt.key)) {
              return evt.key;
          }
          return KEYCODE_MAP.get(evt.keyCode);
      };
      MDCTabBarFoundation.prototype.isActivationKey = function (key) {
          return key === strings.SPACE_KEY || key === strings.ENTER_KEY;
      };
      /**
       * Returns whether a given index is inclusively between the ends
       * @param index The index to test
       */
      MDCTabBarFoundation.prototype.indexIsInRange = function (index) {
          return index >= 0 && index < this.adapter.getTabListLength();
      };
      /**
       * Returns the view's RTL property
       */
      MDCTabBarFoundation.prototype.isRTL = function () {
          return this.adapter.isRTL();
      };
      /**
       * Scrolls the tab at the given index into view for left-to-right user agents.
       * @param index The index of the tab to scroll into view
       */
      MDCTabBarFoundation.prototype.scrollIntoViewImpl = function (index) {
          var scrollPosition = this.adapter.getScrollPosition();
          var barWidth = this.adapter.getOffsetWidth();
          var tabDimensions = this.adapter.getTabDimensionsAtIndex(index);
          var nextIndex = this.findAdjacentTabIndexClosestToEdge(index, tabDimensions, scrollPosition, barWidth);
          if (!this.indexIsInRange(nextIndex)) {
              return;
          }
          var scrollIncrement = this.calculateScrollIncrement(index, nextIndex, scrollPosition, barWidth);
          this.adapter.incrementScroll(scrollIncrement);
      };
      /**
       * Scrolls the tab at the given index into view in RTL
       * @param index The tab index to make visible
       */
      MDCTabBarFoundation.prototype.scrollIntoViewImplRTL = function (index) {
          var scrollPosition = this.adapter.getScrollPosition();
          var barWidth = this.adapter.getOffsetWidth();
          var tabDimensions = this.adapter.getTabDimensionsAtIndex(index);
          var scrollWidth = this.adapter.getScrollContentWidth();
          var nextIndex = this.findAdjacentTabIndexClosestToEdgeRTL(index, tabDimensions, scrollPosition, barWidth, scrollWidth);
          if (!this.indexIsInRange(nextIndex)) {
              return;
          }
          var scrollIncrement = this.calculateScrollIncrementRTL(index, nextIndex, scrollPosition, barWidth, scrollWidth);
          this.adapter.incrementScroll(scrollIncrement);
      };
      return MDCTabBarFoundation;
  }(MDCFoundation));
  export { MDCTabBarFoundation };
  // tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
  export default MDCTabBarFoundation;
  //# sourceMappingURL=foundation.js.map