@polymer/iron-overlay-behavior
Advanced tools
Comparing version 3.0.2 to 3.0.3
@@ -12,1 +12,22 @@ /** | ||
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js'; | ||
declare 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. | ||
*/ | ||
getTabbableNodes(node: Node): HTMLElement[]; | ||
/** | ||
* Returns if a element is focusable. | ||
*/ | ||
isFocusable(element: HTMLElement): boolean; | ||
/** | ||
* Returns if a element is tabbable. To be tabbable, a element must be | ||
* focusable, visible, and with a tabindex !== -1. | ||
*/ | ||
isTabbable(element: HTMLElement): boolean; | ||
} |
@@ -19,4 +19,3 @@ /** | ||
export const IronFocusablesHelper = { | ||
class IronFocusablesHelperClass { | ||
/** | ||
@@ -29,3 +28,3 @@ * Returns a sorted array of tabbable nodes, including the root node. | ||
*/ | ||
getTabbableNodes: function(node) { | ||
getTabbableNodes(node) { | ||
var result = []; | ||
@@ -39,3 +38,3 @@ // If there is at least one element with tabindex > 0, we need to sort | ||
return result; | ||
}, | ||
} | ||
@@ -47,3 +46,3 @@ /** | ||
*/ | ||
isFocusable: function(element) { | ||
isFocusable(element) { | ||
// From http://stackoverflow.com/a/1600194/4228703: | ||
@@ -66,3 +65,3 @@ // There isn't a definite list, it's up to the browser. The only | ||
element, 'a[href], area[href], iframe, [tabindex], [contentEditable]'); | ||
}, | ||
} | ||
@@ -75,7 +74,7 @@ /** | ||
*/ | ||
isTabbable: function(element) { | ||
isTabbable(element) { | ||
return this.isFocusable(element) && | ||
matches.call(element, ':not([tabindex="-1"])') && | ||
this._isVisible(element); | ||
}, | ||
} | ||
@@ -91,3 +90,3 @@ /** | ||
*/ | ||
_normalizedTabIndex: function(element) { | ||
_normalizedTabIndex(element) { | ||
if (this.isFocusable(element)) { | ||
@@ -98,3 +97,3 @@ var tabIndex = element.getAttribute('tabindex') || 0; | ||
return -1; | ||
}, | ||
} | ||
@@ -110,8 +109,11 @@ /** | ||
*/ | ||
_collectTabbableNodes: function(node, result) { | ||
_collectTabbableNodes(node, result) { | ||
// If not an element or not visible, no need to explore children. | ||
if (node.nodeType !== Node.ELEMENT_NODE || !this._isVisible(node)) { | ||
if (node.nodeType !== Node.ELEMENT_NODE) { | ||
return false; | ||
} | ||
var element = /** @type {!HTMLElement} */ (node); | ||
if (!this._isVisible(element)) { | ||
return false; | ||
} | ||
var tabIndex = this._normalizedTabIndex(element); | ||
@@ -122,3 +124,2 @@ var needsSort = tabIndex > 0; | ||
} | ||
// In ShadowDOM v1, tab order is affected by the order of distrubution. | ||
@@ -149,3 +150,3 @@ // E.g. getTabbableNodes(#root) in ShadowDOM v1 should return [#A, #B]; | ||
return needsSort; | ||
}, | ||
} | ||
@@ -158,3 +159,3 @@ /** | ||
*/ | ||
_isVisible: function(element) { | ||
_isVisible(element) { | ||
// Check inline style first to save a re-flow. If looks good, check also | ||
@@ -168,3 +169,3 @@ // computed style. | ||
return false; | ||
}, | ||
} | ||
@@ -177,3 +178,3 @@ /** | ||
*/ | ||
_sortByTabIndex: function(tabbables) { | ||
_sortByTabIndex(tabbables) { | ||
// Implement a merge sort as Array.prototype.sort does a non-stable sort | ||
@@ -189,3 +190,3 @@ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort | ||
return this._mergeSortByTabIndex(left, right); | ||
}, | ||
} | ||
@@ -199,3 +200,3 @@ /** | ||
*/ | ||
_mergeSortByTabIndex: function(left, right) { | ||
_mergeSortByTabIndex(left, right) { | ||
var result = []; | ||
@@ -211,3 +212,3 @@ while ((left.length > 0) && (right.length > 0)) { | ||
return result.concat(left, right); | ||
}, | ||
} | ||
@@ -225,3 +226,3 @@ /** | ||
*/ | ||
_hasLowerTabOrder: function(a, b) { | ||
_hasLowerTabOrder(a, b) { | ||
// Normalize tabIndexes | ||
@@ -233,2 +234,4 @@ // e.g. in Firefox `<div contenteditable>` has `tabIndex = -1` | ||
} | ||
}; | ||
} | ||
export const IronFocusablesHelper = new IronFocusablesHelperClass(); |
@@ -33,2 +33,3 @@ /** | ||
Polymer({ | ||
/** @override */ | ||
_template: html` | ||
@@ -79,2 +80,3 @@ <style> | ||
/** @override */ | ||
created: function() { | ||
@@ -85,2 +87,3 @@ // Used to cancel previous requestAnimationFrame calls when opened changes. | ||
/** @override */ | ||
attached: function() { | ||
@@ -87,0 +90,0 @@ this.opened && this._openedChanged(this.opened); |
@@ -17,2 +17,4 @@ /** | ||
import {IronOverlayManagerClass} from './iron-overlay-manager.js'; | ||
import {pushScrollLock, removeScrollLock} from './iron-scroll-manager.js'; | ||
@@ -19,0 +21,0 @@ |
@@ -19,3 +19,3 @@ /** | ||
import {IronFocusablesHelper} from './iron-focusables-helper.js'; | ||
import {IronOverlayManager} from './iron-overlay-manager.js'; | ||
import {IronOverlayManager, IronOverlayManagerClass} from './iron-overlay-manager.js'; | ||
import {pushScrollLock, removeScrollLock} from './iron-scroll-manager.js'; | ||
@@ -204,2 +204,3 @@ | ||
/** @override */ | ||
attached: function() { | ||
@@ -213,4 +214,16 @@ // Call _openedChanged here so that position can be computed correctly. | ||
/** @override */ | ||
detached: function() { | ||
dom(this).unobserveNodes(this._observer); | ||
// TODO(bicknellr): Per spec, checking `this._observer` should never be | ||
// necessary because `connectedCallback` and `disconnectedCallback` should | ||
// always be called in alternating order. However, the custom elements | ||
// polyfill doesn't implement the reactions stack, so this can sometimes | ||
// happen, particularly if ShadyDOM is in noPatch mode where the custom | ||
// elements polyfill is installed before ShadyDOM. We should investigate | ||
// whether or not we can either implement the reactions stack without major | ||
// performance implications or patch ShadyDOM's functions to restore the | ||
// typical ShadyDOM-then-custom-elements order and remove this workaround. | ||
if (this._observer) { | ||
dom(this).unobserveNodes(this._observer); | ||
} | ||
this._observer = null; | ||
@@ -444,3 +457,3 @@ for (var cb in this.__rafs) { | ||
if (activeElement === document.body || | ||
dom(this).deepContains(activeElement)) { | ||
composedContains(this, activeElement)) { | ||
this.__restoreFocusNode.focus(); | ||
@@ -481,3 +494,3 @@ } | ||
} else { | ||
this._focusedChild = path[0]; | ||
this._focusedChild = /** @type {Node} */ (path[0]); | ||
} | ||
@@ -758,2 +771,14 @@ }, | ||
const composedParent = node => | ||
node.assignedSlot || node.parentNode || node.host; | ||
const composedContains = (ancestor, descendant) => { | ||
for (let element = descendant; element; element = composedParent(element)) { | ||
if (element === ancestor) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
/** | ||
@@ -760,0 +785,0 @@ Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden |
@@ -16,1 +16,58 @@ /** | ||
import * as gestures from '@polymer/polymer/lib/utils/gestures.js'; | ||
export {IronOverlayManagerClass}; | ||
declare class IronOverlayManagerClass { | ||
/** | ||
* The shared backdrop element. | ||
*/ | ||
readonly backdropElement: Element; | ||
/** | ||
* The deepest active element. | ||
*/ | ||
readonly deepActiveElement: Element; | ||
constructor(); | ||
/** | ||
* Adds the overlay and updates its z-index if it's opened, or removes it if | ||
* it's closed. Also updates the backdrop z-index. | ||
*/ | ||
addOrRemoveOverlay(overlay: Element): void; | ||
/** | ||
* Tracks overlays for z-index and focus management. | ||
* Ensures the last added overlay with always-on-top remains on top. | ||
*/ | ||
addOverlay(overlay: Element): void; | ||
removeOverlay(overlay: Element): void; | ||
/** | ||
* Returns the current overlay. | ||
*/ | ||
currentOverlay(): Element|undefined; | ||
/** | ||
* Returns the current overlay z-index. | ||
*/ | ||
currentOverlayZ(): number; | ||
/** | ||
* Ensures that the minimum z-index of new overlays is at least `minimumZ`. | ||
* This does not effect the z-index of any existing overlays. | ||
*/ | ||
ensureMinimumZ(minimumZ: number): void; | ||
focusOverlay(): void; | ||
/** | ||
* Updates the backdrop z-index. | ||
*/ | ||
trackBackdrop(): void; | ||
getBackdrops(): Element[]; | ||
/** | ||
* Returns the z-index for the backdrop. | ||
*/ | ||
backdropZ(): number; | ||
} |
@@ -19,43 +19,39 @@ /** | ||
/** | ||
* @struct | ||
* @constructor | ||
* @private | ||
* @package | ||
*/ | ||
export const IronOverlayManagerClass = function() { | ||
/** | ||
* Used to keep track of the opened overlays. | ||
* @private {!Array<!Element>} | ||
*/ | ||
this._overlays = []; | ||
export class IronOverlayManagerClass { | ||
constructor() { | ||
/** | ||
* Used to keep track of the opened overlays. | ||
* @private {!Array<!Element>} | ||
*/ | ||
this._overlays = []; | ||
/** | ||
* iframes have a default z-index of 100, | ||
* so this default should be at least that. | ||
* @private {number} | ||
*/ | ||
this._minimumZ = 101; | ||
/** | ||
* iframes have a default z-index of 100, | ||
* so this default should be at least that. | ||
* @private {number} | ||
*/ | ||
this._minimumZ = 101; | ||
/** | ||
* Memoized backdrop element. | ||
* @private {Element|null} | ||
*/ | ||
this._backdropElement = null; | ||
/** | ||
* Memoized backdrop element. | ||
* @private {Element|null} | ||
*/ | ||
this._backdropElement = null; | ||
// Enable document-wide tap recognizer. | ||
// NOTE: Use useCapture=true to avoid accidentally prevention of the closing | ||
// of an overlay via event.stopPropagation(). The only way to prevent | ||
// closing of an overlay should be through its APIs. | ||
// NOTE: enable tap on <html> to workaround Polymer/polymer#4459 | ||
// Pass no-op function because MSEdge 15 doesn't handle null as 2nd argument | ||
// https://github.com/Microsoft/ChakraCore/issues/3863 | ||
gestures.add(document.documentElement, 'tap', function() {}); | ||
document.addEventListener('tap', this._onCaptureClick.bind(this), true); | ||
document.addEventListener('focus', this._onCaptureFocus.bind(this), true); | ||
document.addEventListener('keydown', this._onCaptureKeyDown.bind(this), true); | ||
}; | ||
// Enable document-wide tap recognizer. | ||
// NOTE: Use useCapture=true to avoid accidentally prevention of the closing | ||
// of an overlay via event.stopPropagation(). The only way to prevent | ||
// closing of an overlay should be through its APIs. | ||
// NOTE: enable tap on <html> to workaround Polymer/polymer#4459 | ||
// Pass no-op function because MSEdge 15 doesn't handle null as 2nd argument | ||
// https://github.com/Microsoft/ChakraCore/issues/3863 | ||
gestures.addListener(document.documentElement, 'tap', function() {}); | ||
document.addEventListener('tap', this._onCaptureClick.bind(this), true); | ||
document.addEventListener('focus', this._onCaptureFocus.bind(this), true); | ||
document.addEventListener( | ||
'keydown', this._onCaptureKeyDown.bind(this), true); | ||
} | ||
IronOverlayManagerClass.prototype = { | ||
constructor: IronOverlayManagerClass, | ||
/** | ||
@@ -70,3 +66,3 @@ * The shared backdrop element. | ||
return this._backdropElement; | ||
}, | ||
} | ||
@@ -90,3 +86,3 @@ /** | ||
return active; | ||
}, | ||
} | ||
@@ -98,3 +94,3 @@ /** | ||
*/ | ||
_bringOverlayAtIndexToFront: function(i) { | ||
_bringOverlayAtIndexToFront(i) { | ||
var overlay = this._overlays[i]; | ||
@@ -127,3 +123,3 @@ if (!overlay) { | ||
this._overlays[lastI] = overlay; | ||
}, | ||
} | ||
@@ -135,3 +131,3 @@ /** | ||
*/ | ||
addOrRemoveOverlay: function(overlay) { | ||
addOrRemoveOverlay(overlay) { | ||
if (overlay.opened) { | ||
@@ -142,3 +138,3 @@ this.addOverlay(overlay); | ||
} | ||
}, | ||
} | ||
@@ -150,3 +146,3 @@ /** | ||
*/ | ||
addOverlay: function(overlay) { | ||
addOverlay(overlay) { | ||
var i = this._overlays.indexOf(overlay); | ||
@@ -181,3 +177,3 @@ if (i >= 0) { | ||
this.trackBackdrop(); | ||
}, | ||
} | ||
@@ -187,3 +183,3 @@ /** | ||
*/ | ||
removeOverlay: function(overlay) { | ||
removeOverlay(overlay) { | ||
var i = this._overlays.indexOf(overlay); | ||
@@ -196,3 +192,3 @@ if (i === -1) { | ||
this.trackBackdrop(); | ||
}, | ||
} | ||
@@ -203,6 +199,6 @@ /** | ||
*/ | ||
currentOverlay: function() { | ||
currentOverlay() { | ||
var i = this._overlays.length - 1; | ||
return this._overlays[i]; | ||
}, | ||
} | ||
@@ -213,5 +209,5 @@ /** | ||
*/ | ||
currentOverlayZ: function() { | ||
currentOverlayZ() { | ||
return this._getZ(this.currentOverlay()); | ||
}, | ||
} | ||
@@ -223,7 +219,7 @@ /** | ||
*/ | ||
ensureMinimumZ: function(minimumZ) { | ||
ensureMinimumZ(minimumZ) { | ||
this._minimumZ = Math.max(this._minimumZ, minimumZ); | ||
}, | ||
} | ||
focusOverlay: function() { | ||
focusOverlay() { | ||
var current = /** @type {?} */ (this.currentOverlay()); | ||
@@ -233,3 +229,3 @@ if (current) { | ||
} | ||
}, | ||
} | ||
@@ -239,3 +235,3 @@ /** | ||
*/ | ||
trackBackdrop: function() { | ||
trackBackdrop() { | ||
var overlay = this._overlayWithBackdrop(); | ||
@@ -252,3 +248,3 @@ // Avoid creating the backdrop if there is no overlay with backdrop. | ||
this.backdropElement.prepare(); | ||
}, | ||
} | ||
@@ -258,3 +254,3 @@ /** | ||
*/ | ||
getBackdrops: function() { | ||
getBackdrops() { | ||
var backdrops = []; | ||
@@ -267,3 +263,3 @@ for (var i = 0; i < this._overlays.length; i++) { | ||
return backdrops; | ||
}, | ||
} | ||
@@ -274,5 +270,5 @@ /** | ||
*/ | ||
backdropZ: function() { | ||
backdropZ() { | ||
return this._getZ(this._overlayWithBackdrop()) - 1; | ||
}, | ||
} | ||
@@ -284,3 +280,3 @@ /** | ||
*/ | ||
_overlayWithBackdrop: function() { | ||
_overlayWithBackdrop() { | ||
for (var i = this._overlays.length - 1; i >= 0; i--) { | ||
@@ -291,3 +287,3 @@ if (this._overlays[i].withBackdrop) { | ||
} | ||
}, | ||
} | ||
@@ -299,3 +295,3 @@ /** | ||
*/ | ||
_getZ: function(overlay) { | ||
_getZ(overlay) { | ||
var z = this._minimumZ; | ||
@@ -312,3 +308,3 @@ if (overlay) { | ||
return z; | ||
}, | ||
} | ||
@@ -320,5 +316,5 @@ /** | ||
*/ | ||
_setZ: function(element, z) { | ||
_setZ(element, z) { | ||
element.style.zIndex = z; | ||
}, | ||
} | ||
@@ -330,5 +326,5 @@ /** | ||
*/ | ||
_applyOverlayZ: function(overlay, aboveZ) { | ||
_applyOverlayZ(overlay, aboveZ) { | ||
this._setZ(overlay, aboveZ + 2); | ||
}, | ||
} | ||
@@ -342,3 +338,3 @@ /** | ||
*/ | ||
_overlayInPath: function(path) { | ||
_overlayInPath(path) { | ||
path = path || []; | ||
@@ -350,3 +346,3 @@ for (var i = 0; i < path.length; i++) { | ||
} | ||
}, | ||
} | ||
@@ -358,3 +354,3 @@ /** | ||
*/ | ||
_onCaptureClick: function(event) { | ||
_onCaptureClick(event) { | ||
var i = this._overlays.length - 1; | ||
@@ -375,3 +371,3 @@ if (i === -1) | ||
} | ||
}, | ||
} | ||
@@ -383,3 +379,3 @@ /** | ||
*/ | ||
_onCaptureFocus: function(event) { | ||
_onCaptureFocus(event) { | ||
var overlay = /** @type {?} */ (this.currentOverlay()); | ||
@@ -389,3 +385,3 @@ if (overlay) { | ||
} | ||
}, | ||
} | ||
@@ -397,3 +393,3 @@ /** | ||
*/ | ||
_onCaptureKeyDown: function(event) { | ||
_onCaptureKeyDown(event) { | ||
var overlay = /** @type {?} */ (this.currentOverlay()); | ||
@@ -407,3 +403,3 @@ if (overlay) { | ||
} | ||
}, | ||
} | ||
@@ -418,3 +414,3 @@ /** | ||
*/ | ||
_shouldBeBehindOverlay: function(overlay1, overlay2) { | ||
_shouldBeBehindOverlay(overlay1, overlay2) { | ||
return !overlay1.alwaysOnTop && overlay2.alwaysOnTop; | ||
@@ -421,0 +417,0 @@ } |
@@ -69,1 +69,44 @@ /** | ||
declare function _unlockScrollInteractions(): void; | ||
export {_shouldPreventScrolling}; | ||
/** | ||
* Returns true if the event causes scroll outside the current locking | ||
* element, e.g. pointer/keyboard interactions, or scroll "leaking" | ||
* outside the locking element when it is already at its scroll boundaries. | ||
*/ | ||
declare function _shouldPreventScrolling(event: Event): boolean; | ||
export {_getScrollableNodes}; | ||
/** | ||
* Returns an array of scrollable nodes up to the current locking element, | ||
* which is included too if scrollable. | ||
* | ||
* @returns scrollables | ||
*/ | ||
declare function _getScrollableNodes(nodes: Node[]): Node[]; | ||
export {_getScrollingNode}; | ||
/** | ||
* Returns the node that is scrolling. If there is no scrolling, | ||
* returns undefined. | ||
*/ | ||
declare function _getScrollingNode(nodes: Node[], deltaX: number, deltaY: number): Node|undefined; | ||
export {_getScrollInfo}; | ||
/** | ||
* Returns scroll `deltaX` and `deltaY`. | ||
* | ||
* @returns Object containing the | ||
* x-axis scroll delta (positive: scroll right, negative: scroll left, | ||
* 0: no scroll), and the y-axis scroll delta (positive: scroll down, | ||
* negative: scroll up, 0: no scroll). | ||
*/ | ||
declare function _getScrollInfo(event: Event): {deltaX: number, deltaY: number}; |
@@ -44,20 +44,11 @@ /** | ||
var _boundScrollHandler; | ||
var currentLockingElement; | ||
/** | ||
* The IronScrollManager is intended to provide a central source | ||
* of authority and control over which elements in a document are currently | ||
* allowed to scroll. | ||
* | ||
*/ | ||
`TODO(modulizer): A namespace named Polymer.IronScrollManager was | ||
declared here. The surrounding comments should be reviewed, | ||
and this string can then be deleted`; | ||
/** | ||
* The current element that defines the DOM boundaries of the | ||
* scroll lock. This is always the most recently locking element. | ||
* | ||
* @return {!Node|undefined} | ||
* @type {!Node|undefined} | ||
*/ | ||
var currentLockingElement; | ||
export {currentLockingElement}; | ||
@@ -218,3 +209,3 @@ | ||
/** | ||
* @private | ||
* @package | ||
*/ | ||
@@ -249,3 +240,3 @@ export {_boundScrollHandler}; | ||
* @return {boolean} | ||
* @private | ||
* @package | ||
*/ | ||
@@ -281,7 +272,8 @@ export function _shouldPreventScrolling(event) { | ||
* @return {!Array<!Node>} scrollables | ||
* @private | ||
* @package | ||
*/ | ||
export function _getScrollableNodes(nodes) { | ||
var scrollables = []; | ||
var lockingIndex = nodes.indexOf(currentLockingElement); | ||
var lockingIndex = | ||
nodes.indexOf(/** @type {!Node} */ (currentLockingElement)); | ||
// Loop from root target to locking element (included). | ||
@@ -313,3 +305,3 @@ for (var i = 0; i <= lockingIndex; i++) { | ||
* @return {!Node|undefined} | ||
* @private | ||
* @package | ||
*/ | ||
@@ -351,3 +343,3 @@ export function _getScrollingNode(nodes, deltaX, deltaY) { | ||
* negative: scroll up, 0: no scroll). | ||
* @private | ||
* @package | ||
*/ | ||
@@ -354,0 +346,0 @@ export function _getScrollInfo(event) { |
@@ -29,3 +29,3 @@ { | ||
}, | ||
"version": "3.0.2", | ||
"version": "3.0.3", | ||
"main": "iron-overlay-behavior.js", | ||
@@ -32,0 +32,0 @@ "author": "The Polymer Authors", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
112190
2395
1