text: define(["exports","../polymer/polymer-legacy.js","../polymer/lib/legacy/polymer.dom.js"],function(_exports,_polymerLegacy,_polymerDom){"use strict";Object.defineProperty(_exports,"__esModule",{value:!0});_exports.IronFocusablesHelper=void 0;/**
  @license
  Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
  This code may only be used under the BSD style license found at
  http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
  http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
  found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
  part of the polymer project is also subject to an additional IP rights grant
  found at http://polymer.github.io/PATENTS.txt
  */var p=Element.prototype,matches=p.matches||p.matchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;class IronFocusablesHelperClass{/**
     * Returns a sorted array of tabbable nodes, including the root node.
     * It searches the tabbable nodes in the light and shadow dom of the chidren,
     * sorting the result by tabindex.
     * @param {!Node} node
     * @return {!Array<!HTMLElement>}
     */getTabbableNodes(node){var result=[],needsSortByTabIndex=this._collectTabbableNodes(node,result);// If there is at least one element with tabindex > 0, we need to sort
  // the final array by tabindex.
  if(needsSortByTabIndex){return this._sortByTabIndex(result)}return result}/**
     * Returns if a element is focusable.
     * @param {!HTMLElement} element
     * @return {boolean}
     */isFocusable(element){// From http://stackoverflow.com/a/1600194/4228703:
  // There isn't a definite list, it's up to the browser. The only
  // standard we have is DOM Level 2 HTML
  // https://www.w3.org/TR/DOM-Level-2-HTML/html.html, according to which the
  // only elements that have a focus() method are HTMLInputElement,
  // HTMLSelectElement, HTMLTextAreaElement and HTMLAnchorElement. This
  // notably omits HTMLButtonElement and HTMLAreaElement. Referring to these
  // tests with tabbables in different browsers
  // http://allyjs.io/data-tables/focusable.html
  // Elements that cannot be focused if they have [disabled] attribute.
  if(matches.call(element,"input, select, textarea, button, object")){return matches.call(element,":not([disabled])")}// Elements that can be focused even if they have [disabled] attribute.
  return matches.call(element,"a[href], area[href], iframe, [tabindex], [contentEditable]")}/**
     * Returns if a element is tabbable. To be tabbable, a element must be
     * focusable, visible, and with a tabindex !== -1.
     * @param {!HTMLElement} element
     * @return {boolean}
     */isTabbable(element){return this.isFocusable(element)&&matches.call(element,":not([tabindex=\"-1\"])")&&this._isVisible(element)}/**
     * Returns the normalized element tabindex. If not focusable, returns -1.
     * It checks for the attribute "tabindex" instead of the element property
     * `tabIndex` since browsers assign different values to it.
     * e.g. in Firefox `<div contenteditable>` has `tabIndex = -1`
     * @param {!HTMLElement} element
     * @return {!number}
     * @private
     */_normalizedTabIndex(element){if(this.isFocusable(element)){var tabIndex=element.getAttribute("tabindex")||0;return+tabIndex}return-1}/**
     * Searches for nodes that are tabbable and adds them to the `result` array.
     * Returns if the `result` array needs to be sorted by tabindex.
     * @param {!Node} node The starting point for the search; added to `result`
     * if tabbable.
     * @param {!Array<!HTMLElement>} result
     * @return {boolean}
     * @private
     */_collectTabbableNodes(node,result){// If not an element or not visible, no need to explore children.
  if(node.nodeType!==Node.ELEMENT_NODE){return!1}var element=/** @type {!HTMLElement} */node;if(!this._isVisible(element)){return!1}var tabIndex=this._normalizedTabIndex(element),needsSort=0<tabIndex;if(0<=tabIndex){result.push(element)}// In ShadowDOM v1, tab order is affected by the order of distrubution.
  // E.g. getTabbableNodes(#root) in ShadowDOM v1 should return [#A, #B];
  // in ShadowDOM v0 tab order is not affected by the distrubution order,
  // in fact getTabbableNodes(#root) returns [#B, #A].
  //  <div id="root">
  //   <!-- shadow -->
  //     <slot name="a">
  //     <slot name="b">
  //   <!-- /shadow -->
  //   <input id="A" slot="a">
  //   <input id="B" slot="b" tabindex="1">
  //  </div>
  // TODO(valdrin) support ShadowDOM v1 when upgrading to Polymer v2.0.
  var children;if("content"===element.localName||"slot"===element.localName){children=(0,_polymerDom.dom)(element).getDistributedNodes()}else{// Use shadow root if possible, will check for distributed nodes.
  children=(0,_polymerDom.dom)(element.root||element).children}for(var i=0;i<children.length;i++){// Ensure method is always invoked to collect tabbable children.
  needsSort=this._collectTabbableNodes(children[i],result)||needsSort}return needsSort}/**
     * Returns false if the element has `visibility: hidden` or `display: none`
     * @param {!HTMLElement} element
     * @return {boolean}
     * @private
     */_isVisible(element){// Check inline style first to save a re-flow. If looks good, check also
  // computed style.
  var style=element.style;if("hidden"!==style.visibility&&"none"!==style.display){style=window.getComputedStyle(element);return"hidden"!==style.visibility&&"none"!==style.display}return!1}/**
     * Sorts an array of tabbable elements by tabindex. Returns a new array.
     * @param {!Array<!HTMLElement>} tabbables
     * @return {!Array<!HTMLElement>}
     * @private
     */_sortByTabIndex(tabbables){// Implement a merge sort as Array.prototype.sort does a non-stable sort
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
  var len=tabbables.length;if(2>len){return tabbables}var pivot=Math.ceil(len/2),left=this._sortByTabIndex(tabbables.slice(0,pivot)),right=this._sortByTabIndex(tabbables.slice(pivot));return this._mergeSortByTabIndex(left,right)}/**
     * Merge sort iterator, merges the two arrays into one, sorted by tab index.
     * @param {!Array<!HTMLElement>} left
     * @param {!Array<!HTMLElement>} right
     * @return {!Array<!HTMLElement>}
     * @private
     */_mergeSortByTabIndex(left,right){var result=[];while(0<left.length&&0<right.length){if(this._hasLowerTabOrder(left[0],right[0])){result.push(right.shift())}else{result.push(left.shift())}}return result.concat(left,right)}/**
     * Returns if element `a` has lower tab order compared to element `b`
     * (both elements are assumed to be focusable and tabbable).
     * Elements with tabindex = 0 have lower tab order compared to elements
     * with tabindex > 0.
     * If both have same tabindex, it returns false.
     * @param {!HTMLElement} a
     * @param {!HTMLElement} b
     * @return {boolean}
     * @private
     */_hasLowerTabOrder(a,b){// Normalize tabIndexes
  // e.g. in Firefox `<div contenteditable>` has `tabIndex = -1`
  var ati=Math.max(a.tabIndex,0),bti=Math.max(b.tabIndex,0);return 0===ati||0===bti?bti>ati:ati>bti}}const IronFocusablesHelper=new IronFocusablesHelperClass;_exports.IronFocusablesHelper=IronFocusablesHelper});