ngx-modialog-10
Version:
Modal / Dialog for Angular
465 lines • 34.4 kB
JavaScript
/**
* @fileoverview added by tsickle
* Generated from: lib/overlay/overlay.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { __extends } from "tslib";
import { Component, ElementRef, ViewChild, ViewContainerRef, ViewEncapsulation, Renderer2, TemplateRef, HostListener } from '@angular/core';
import { PromiseCompleter, supportsKey } from '../framework/utils';
import { DialogRef } from '../models/dialog-ref';
import { BaseDynamicComponent } from '../components/index';
// TODO: use DI factory for this.
// TODO: consolidate dup code
/** @type {?} */
var isDoc = !(typeof document === 'undefined' || !document);
/**
* @record
*/
export function EmbedComponentConfig() { }
if (false) {
/** @type {?} */
EmbedComponentConfig.prototype.component;
/** @type {?|undefined} */
EmbedComponentConfig.prototype.projectableNodes;
}
/**
* Represents the modal overlay.
*/
var ModalOverlay = /** @class */ (function (_super) {
__extends(ModalOverlay, _super);
function ModalOverlay(dialogRef, vcr, el, renderer) {
var _this = _super.call(this, el, renderer) || this;
_this.dialogRef = dialogRef;
_this.vcr = vcr;
_this.activateAnimationListener();
return _this;
}
/**
* @internal
*/
/**
* \@internal
* @template T
* @param {?} content
* @return {?}
*/
ModalOverlay.prototype.getProjectables = /**
* \@internal
* @template T
* @param {?} content
* @return {?}
*/
function (content) {
/** @type {?} */
var nodes;
if (typeof content === 'string') {
nodes = [[this.renderer.createText("" + content)]];
}
else if (content instanceof TemplateRef) {
nodes = [this.vcr.createEmbeddedView(content, { $implicit: this.dialogRef.context, dialogRef: this.dialogRef }).rootNodes];
}
else {
nodes = [this.embedComponent({ component: content }).rootNodes];
}
return nodes;
};
/**
* @param {?} config
* @return {?}
*/
ModalOverlay.prototype.embedComponent = /**
* @param {?} config
* @return {?}
*/
function (config) {
/** @type {?} */
var ctx = (/** @type {?} */ (config));
return this.vcr.createEmbeddedView(this.template, (/** @type {?} */ ({
$implicit: ctx
})));
};
/**
* @template T
* @param {?} type
* @param {?=} projectableNodes
* @return {?}
*/
ModalOverlay.prototype.addComponent = /**
* @template T
* @param {?} type
* @param {?=} projectableNodes
* @return {?}
*/
function (type, projectableNodes) {
if (projectableNodes === void 0) { projectableNodes = []; }
return _super.prototype._addComponent.call(this, {
component: type,
vcRef: this.innerVcr,
projectableNodes: projectableNodes
});
};
/**
* @return {?}
*/
ModalOverlay.prototype.fullscreen = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var style = {
position: 'fixed',
top: 0,
left: 0,
bottom: 0,
right: 0,
'z-index': 1500
};
Object.keys(style).forEach((/**
* @template THIS
* @this {THIS}
* @param {?} k
* @return {THIS}
*/
function (k) { return _this.setStyle(k, style[k]); }));
};
/**
* @return {?}
*/
ModalOverlay.prototype.insideElement = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var style = {
position: 'absolute',
overflow: 'hidden',
width: '100%',
height: '100%',
top: 0,
left: 0,
bottom: 0,
right: 0
};
Object.keys(style).forEach((/**
* @template THIS
* @this {THIS}
* @param {?} k
* @return {THIS}
*/
function (k) { return _this.setStyle(k, style[k]); }));
};
/**
* Set a specific inline style for the container of the whole dialog component
* The dialog component root element is the host of this component, it contains only 1 direct
* child which is the container.
*
* Structure:
*
* ```html
* <modal-overlay>
* <div>
* <!-- BACKDROP ELEMENT -->
* <!-- DIALOG CONTAINER ELEMENT -->
* </div>
* </modal-overlay>
* ```
*
* @param prop The style key
* @param value The value, undefined to remove
*/
/**
* Set a specific inline style for the container of the whole dialog component
* The dialog component root element is the host of this component, it contains only 1 direct
* child which is the container.
*
* Structure:
*
* ```html
* <modal-overlay>
* <div>
* <!-- BACKDROP ELEMENT -->
* <!-- DIALOG CONTAINER ELEMENT -->
* </div>
* </modal-overlay>
* ```
*
* @template THIS
* @this {THIS}
* @param {?} prop The style key
* @param {?} value The value, undefined to remove
* @return {THIS}
*/
ModalOverlay.prototype.setContainerStyle = /**
* Set a specific inline style for the container of the whole dialog component
* The dialog component root element is the host of this component, it contains only 1 direct
* child which is the container.
*
* Structure:
*
* ```html
* <modal-overlay>
* <div>
* <!-- BACKDROP ELEMENT -->
* <!-- DIALOG CONTAINER ELEMENT -->
* </div>
* </modal-overlay>
* ```
*
* @template THIS
* @this {THIS}
* @param {?} prop The style key
* @param {?} value The value, undefined to remove
* @return {THIS}
*/
function (prop, value) {
(/** @type {?} */ (this)).renderer.setStyle((/** @type {?} */ (this)).container.nativeElement, prop, value);
return (/** @type {?} */ (this));
};
/**
* Define an element that click inside it will not trigger modal close.
* Since events bubble, clicking on a dialog will bubble up to the overlay, a plugin
* must define an element that represent the dialog, the overlay will make sure no to close when
* it was clicked.
* @param element
*/
/**
* Define an element that click inside it will not trigger modal close.
* Since events bubble, clicking on a dialog will bubble up to the overlay, a plugin
* must define an element that represent the dialog, the overlay will make sure no to close when
* it was clicked.
* @param {?} element
* @return {?}
*/
ModalOverlay.prototype.setClickBoundary = /**
* Define an element that click inside it will not trigger modal close.
* Since events bubble, clicking on a dialog will bubble up to the overlay, a plugin
* must define an element that represent the dialog, the overlay will make sure no to close when
* it was clicked.
* @param {?} element
* @return {?}
*/
function (element) {
var _this = this;
/** @type {?} */
var target;
/** @type {?} */
var elListener = (/**
* @param {?} event
* @return {?}
*/
function (event) { return target = (/** @type {?} */ (event.target)); });
/** @type {?} */
var docListener = (/**
* @param {?} event
* @return {?}
*/
function (event) {
if (_this.dialogRef.context.isBlocking || !_this.dialogRef.overlay.isTopMost(_this.dialogRef)) {
return;
}
/** @type {?} */
var current = event.target;
// on click, this will hit.
if (current === target) {
return;
}
// on mouse down -> drag -> release the current might not be 'target', it might be
// a sibling or a child (i.e: not part of the tree-up direction). It might also be a release
// outside the dialog... so we compare to the boundary element
do {
if (current === element) {
return;
}
} while (current.parentNode && (current = current.parentNode));
_this.dialogRef.dismiss();
});
if (isDoc) {
this.dialogRef.onDestroy.subscribe((/**
* @return {?}
*/
function () {
element.removeEventListener('click', elListener, false);
element.removeEventListener('touchstart', elListener, false);
document.removeEventListener('click', docListener, false);
document.removeEventListener('touchend', docListener, false);
}));
setTimeout((/**
* @return {?}
*/
function () {
element.addEventListener('mousedown', elListener, false);
element.addEventListener('touchstart', docListener, false);
document.addEventListener('click', docListener, false);
document.addEventListener('touchend', docListener, false);
}));
}
};
/**
* Temp workaround for animation where destruction of the top level component does not
* trigger child animations. Solution should be found either in animation module or in design
* of the modal component tree.
*/
/**
* Temp workaround for animation where destruction of the top level component does not
* trigger child animations. Solution should be found either in animation module or in design
* of the modal component tree.
* @return {?}
*/
ModalOverlay.prototype.canDestroy = /**
* Temp workaround for animation where destruction of the top level component does not
* trigger child animations. Solution should be found either in animation module or in design
* of the modal component tree.
* @return {?}
*/
function () {
/** @type {?} */
var completer = new PromiseCompleter();
if (!Array.isArray(this.beforeDestroyHandlers)) {
completer.resolve();
}
else {
// run destroy notification but protect against halt.
/** @type {?} */
var id_1 = setTimeout((/**
* @return {?}
*/
function () {
id_1 = null;
completer.reject();
}), 1000);
/** @type {?} */
var resolve = (/**
* @return {?}
*/
function () {
if (id_1 === null) {
return;
}
clearTimeout(id_1);
completer.resolve();
});
Promise.all(this.beforeDestroyHandlers.map((/**
* @param {?} fn
* @return {?}
*/
function (fn) { return fn(); })))
.then(resolve)
.catch(resolve);
}
return completer.promise;
};
/**
* A handler running before destruction of the overlay
* use to delay destruction due to animation.
* This is part of the workaround for animation, see canDestroy.
*
* NOTE: There is no guarantee that the listeners will fire, use dialog.onDestory for that.
* @param fn
*/
/**
* A handler running before destruction of the overlay
* use to delay destruction due to animation.
* This is part of the workaround for animation, see canDestroy.
*
* NOTE: There is no guarantee that the listeners will fire, use dialog.onDestory for that.
* @param {?} fn
* @return {?}
*/
ModalOverlay.prototype.beforeDestroy = /**
* A handler running before destruction of the overlay
* use to delay destruction due to animation.
* This is part of the workaround for animation, see canDestroy.
*
* NOTE: There is no guarantee that the listeners will fire, use dialog.onDestory for that.
* @param {?} fn
* @return {?}
*/
function (fn) {
if (!this.beforeDestroyHandlers) {
this.beforeDestroyHandlers = [];
}
this.beforeDestroyHandlers.push(fn);
};
/**
* @param {?} event
* @return {?}
*/
ModalOverlay.prototype.documentKeypress = /**
* @param {?} event
* @return {?}
*/
function (event) {
// check that this modal is the last in the stack.
if (!this.dialogRef.overlay.isTopMost(this.dialogRef)) {
return;
}
if (supportsKey(event.keyCode, (/** @type {?} */ (this.dialogRef.context.keyboard)))) {
this.dialogRef.dismiss();
}
};
/**
* @return {?}
*/
ModalOverlay.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
_super.prototype.ngOnDestroy.call(this);
if (this.dialogRef.destroyed !== true) {
// if we're here the overlay is destroyed by an external event that is not user invoked.
// i.e: The user did no call dismiss or close and dialogRef.destroy() did not invoke.
// this will happen when routing or killing an element containing a blocked overlay (ngIf)
// we bail out, i.e gracefully shutting down.
this.dialogRef.bailOut();
}
};
ModalOverlay.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'modal-overlay',
encapsulation: ViewEncapsulation.None,
template: "<div #container>\n <ng-template #innerView></ng-template>\n</div>\n<ng-template #template let-ctx>\n <ng-container *ngComponentOutlet=\"ctx.component; injector: ctx.injector; content: ctx.projectableNodes\"></ng-container>\n</ng-template>"
}] }
];
/** @nocollapse */
ModalOverlay.ctorParameters = function () { return [
{ type: DialogRef },
{ type: ViewContainerRef },
{ type: ElementRef },
{ type: Renderer2 }
]; };
ModalOverlay.propDecorators = {
container: [{ type: ViewChild, args: ['container', { read: ElementRef, static: true },] }],
innerVcr: [{ type: ViewChild, args: ['innerView', { read: ViewContainerRef, static: true },] }],
template: [{ type: ViewChild, args: ['template', { static: true },] }],
documentKeypress: [{ type: HostListener, args: ['body:keydown', ['$event'],] }]
};
return ModalOverlay;
}(BaseDynamicComponent));
export { ModalOverlay };
if (false) {
/**
* @type {?}
* @private
*/
ModalOverlay.prototype.beforeDestroyHandlers;
/** @type {?} */
ModalOverlay.prototype.container;
/** @type {?} */
ModalOverlay.prototype.innerVcr;
/** @type {?} */
ModalOverlay.prototype.template;
/**
* @type {?}
* @private
*/
ModalOverlay.prototype.dialogRef;
/**
* @type {?}
* @private
*/
ModalOverlay.prototype.vcr;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3ZlcmxheS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtbW9kaWFsb2ctMTAvIiwic291cmNlcyI6WyJsaWIvb3ZlcmxheS9vdmVybGF5LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFFQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFVBQVUsRUFHVixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsV0FBVyxFQUFFLFlBQVksRUFDMUIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ25FLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVqRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7OztJQUlyRCxLQUFLLEdBQVksQ0FBQyxDQUFDLE9BQU8sUUFBUSxLQUFLLFdBQVcsSUFBSSxDQUFDLFFBQVEsQ0FBQzs7OztBQUV0RSwwQ0FHQzs7O0lBRkMseUNBQWU7O0lBQ2YsZ0RBQTJCOzs7OztBQU03QjtJQU9rQyxnQ0FBb0I7SUFPcEQsc0JBQW9CLFNBQXlCLEVBQ3pCLEdBQXFCLEVBQzdCLEVBQWMsRUFDZCxRQUFtQjtRQUgvQixZQUlFLGtCQUFNLEVBQUUsRUFBRSxRQUFRLENBQUMsU0FFcEI7UUFObUIsZUFBUyxHQUFULFNBQVMsQ0FBZ0I7UUFDekIsU0FBRyxHQUFILEdBQUcsQ0FBa0I7UUFJdkMsS0FBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7O0lBQ25DLENBQUM7SUFFRDs7T0FFRzs7Ozs7OztJQUNILHNDQUFlOzs7Ozs7SUFBZixVQUFtQixPQUF5Qjs7WUFFdEMsS0FBWTtRQUNoQixJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRTtZQUMvQixLQUFLLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEtB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QUN4Qzs7OztnQkFyQlEsU0FBUztnQkFQaEIsZ0JBQWdCO2dCQUpoQixVQUFVO2dCQU1WLFNBQVM7Ozs0QkErQlIsU0FBUyxTQUFDLFdBQVcsRUFBRSxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBQzsyQkFDdkQsU0FBUyxTQUFDLFdBQVcsRUFBRSxFQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFOzJCQUM5RCxTQUFTLFNBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTttQ0FtTXRDLFlBQVksU0FBQyxjQUFjLEVBQUUsQ0FBQyxRQUFRLENBQUM7O0lBdUIxQyxtQkFBQztDQUFBLEFBdE9ELENBT2tDLG9CQUFvQixHQStOckQ7U0EvTlksWUFBWTs7Ozs7O0lBQ3ZCLDZDQUEwRDs7SUFFMUQsaUNBQXVGOztJQUN2RixnQ0FBbUc7O0lBQ25HLGdDQUEyRTs7Ozs7SUFFL0QsaUNBQWlDOzs7OztJQUNqQywyQkFBNkIiLCJzb3VyY2VzQ29udGVudCI6WyJkZWNsYXJlIGNvbnN0IGNsZWFyVGltZW91dDogYW55O1xuXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFJlZixcbiAgRWxlbWVudFJlZixcbiAgRW1iZWRkZWRWaWV3UmVmLFxuICBJbmplY3RvcixcbiAgVmlld0NoaWxkLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgUmVuZGVyZXIyLFxuICBUZW1wbGF0ZVJlZiwgSG9zdExpc3RlbmVyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBQcm9taXNlQ29tcGxldGVyLCBzdXBwb3J0c0tleSB9IGZyb20gJy4uL2ZyYW1ld29yay91dGlscyc7XG5pbXBvcnQgeyBEaWFsb2dSZWYgfSBmcm9tICcuLi9tb2RlbHMvZGlhbG9nLXJlZic7XG5pbXBvcnQgeyBDb250YWluZXJDb250ZW50IH0gZnJvbSAnLi4vbW9kZWxzL3Rva2Vucyc7XG5pbXBvcnQgeyBCYXNlRHluYW1pY0NvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudHMvaW5kZXgnO1xuXG4vLyBUT0RPOiB1c2UgREkgZmFjdG9yeSBmb3IgdGhpcy5cbi8vIFRPRE86IGNvbnNvbGlkYXRlIGR1cCBjb2RlXG5jb25zdCBpc0RvYzogYm9vbGVhbiA9ICEodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJyB8fCAhZG9jdW1lbnQpO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVtYmVkQ29tcG9uZW50Q29uZmlnIHtcbiAgY29tcG9uZW50OiBhbnk7XG4gIHByb2plY3RhYmxlTm9kZXM/OiBhbnlbXVtdO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIG1vZGFsIG92ZXJsYXkuXG4gKi9cbkBDb21wb25lbnQoe1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Y29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnbW9kYWwtb3ZlcmxheScsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHRlbXBsYXRlVXJsOiAnLi9vdmVybGF5LmNvbXBvbmVudC5odG1sJ1xufSlcbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpjb21wb25lbnQtY2xhc3Mtc3VmZml4XG5leHBvcnQgY2xhc3MgTW9kYWxPdmVybGF5IGV4dGVuZHMgQmFzZUR5bmFtaWNDb21wb25lbnQge1xuICBwcml2YXRlIGJlZm9yZURlc3Ryb3lIYW5kbGVyczogQXJyYXk8KCkgPT4gUHJvbWlzZTx2b2lkPj47XG5cbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywge3JlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogdHJ1ZX0pIHB1YmxpYyBjb250YWluZXI6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ2lubmVyVmlldycsIHtyZWFkOiBWaWV3Q29udGFpbmVyUmVmLCBzdGF0aWM6IHRydWUgfSkgcHVibGljIGlubmVyVmNyOiBWaWV3Q29udGFpbmVyUmVmO1xuICBAVmlld0NoaWxkKCd0ZW1wbGF0ZScsIHsgc3RhdGljOiB0cnVlIH0pIHB1YmxpYyB0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGRpYWxvZ1JlZjogRGlhbG9nUmVmPGFueT4sXG4gICAgICAgICAgICAgIHByaXZhdGUgdmNyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgICAgICAgICAgICBlbDogRWxlbWVudFJlZixcbiAgICAgICAgICAgICAgcmVuZGVyZXI6IFJlbmRlcmVyMikge1xuICAgIHN1cGVyKGVsLCByZW5kZXJlcik7XG4gICAgdGhpcy5hY3RpdmF0ZUFuaW1hdGlvbkxpc3RlbmVyKCk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBnZXRQcm9qZWN0YWJsZXM8VD4oY29udGVudDogQ29udGFpbmVyQ29udGVudCk6IGFueVtdW10ge1xuXG4gICAgbGV0IG5vZGVzOiBhbnlbXTtcbiAgICBpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBub2RlcyA9IFtbdGhpcy5yZW5kZXJlci5jcmVhdGVUZXh0KGAke2NvbnRlbnR9YCldXTtcbiAgICB9IGVsc2UgaWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBUZW1wbGF0ZVJlZikge1xuICAgICAgbm9kZXMgPSBbdGhpcy52Y3IuY3JlYXRlRW1iZWRkZWRWaWV3KGNvbnRlbnQsIHskaW1wbGljaXQ6IHRoaXMuZGlhbG9nUmVmLmNvbnRleHQsIGRpYWxvZ1JlZjogdGhpcy5kaWFsb2dSZWZ9KS5yb290Tm9kZXNdO1xuICAgIH0gZWxzZSB7XG4gICAgICBub2RlcyA9IFt0aGlzLmVtYmVkQ29tcG9uZW50KHtjb21wb25lbnQ6IGNvbnRlbnR9KS5yb290Tm9kZXNdO1xuICAgIH1cblxuICAgIHJldHVybiBub2RlcztcbiAgfVxuXG4gIGVtYmVkQ29tcG9uZW50KGNvbmZpZzogRW1iZWRDb21wb25lbnRDb25maWcpOiBFbWJlZGRlZFZpZXdSZWY8RW1iZWRDb21wb25lbnRDb25maWc+IHtcbiAgICBjb25zdCBjdHg6IEVtYmVkQ29tcG9uZW50Q29uZmlnICYgeyBpbmplY3RvcjogSW5qZWN0b3IgfSA9IDxhbnk+Y29uZmlnO1xuXG4gICAgcmV0dXJuIHRoaXMudmNyLmNyZWF0ZUVtYmVkZGVkVmlldyh0aGlzLnRlbXBsYXRlLCA8YW55PntcbiAgICAgICRpbXBsaWNpdDogY3R4XG4gICAgfSk7XG4gIH1cblxuICBhZGRDb21wb25lbnQ8VD4odHlwZTogYW55LCBwcm9qZWN0YWJsZU5vZGVzOiBhbnlbXVtdID0gW10pOiBDb21wb25lbnRSZWY8VD4ge1xuICAgIHJldHVybiBzdXBlci5fYWRkQ29tcG9uZW50PFQ+KHtcbiAgICAgIGNvbXBvbmVudDogdHlwZSxcbiAgICAgIHZjUmVmOiB0aGlzLmlubmVyVmNyLFxuICAgICAgcHJvamVjdGFibGVOb2Rlc1xuICAgIH0pO1xuICB9XG5cbiAgZnVsbHNjcmVlbigpOiB2b2lkIHtcbiAgICBjb25zdCBzdHlsZSA9IHtcbiAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgdG9wOiAwLFxuICAgICAgbGVmdDogMCxcbiAgICAgIGJvdHRvbTogMCxcbiAgICAgIHJpZ2h0OiAwLFxuICAgICAgJ3otaW5kZXgnOiAxNTAwXG4gICAgfTtcbiAgICBPYmplY3Qua2V5cyhzdHlsZSkuZm9yRWFjaChrID0+IHRoaXMuc2V0U3R5bGUoaywgc3R5bGVba10pKTtcbiAgfVxuXG4gIGluc2lkZUVsZW1lbnQoKTogdm9pZCB7XG4gICAgY29uc3Qgc3R5bGUgPSB7XG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIG92ZXJmbG93OiAnaGlkZGVuJyxcbiAgICAgIHdpZHRoOiAnMTAwJScsXG4gICAgICBoZWlnaHQ6ICcxMDAlJyxcbiAgICAgIHRvcDogMCxcbiAgICAgIGxlZnQ6IDAsXG4gICAgICBib3R0b206IDAsXG4gICAgICByaWdodDogMFxuICAgIH07XG4gICAgT2JqZWN0LmtleXMoc3R5bGUpLmZvckVhY2goayA9PiB0aGlzLnNldFN0eWxlKGssIHN0eWxlW2tdKSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGEgc3BlY2lmaWMgaW5saW5lIHN0eWxlIGZvciB0aGUgY29udGFpbmVyIG9mIHRoZSB3aG9sZSBkaWFsb2cgY29tcG9uZW50XG4gICAqIFRoZSBkaWFsb2cgY29tcG9uZW50IHJvb3QgZWxlbWVudCBpcyB0aGUgaG9zdCBvZiB0aGlzIGNvbXBvbmVudCwgaXQgY29udGFpbnMgb25seSAxIGRpcmVjdFxuICAgKiBjaGlsZCB3aGljaCBpcyB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBTdHJ1Y3R1cmU6XG4gICAqXG4gICAqIGBgYGh0bWxcbiAgICogPG1vZGFsLW92ZXJsYXk+XG4gICAqICAgPGRpdj5cbiAgICogICAgIDwhLS0gQkFDS0RST1AgRUxFTUVOVCAtLT5cbiAgICogICAgIDwhLS0gRElBTE9HIENPTlRBSU5FUiBFTEVNRU5UIC0tPlxuICAgKiAgIDwvZGl2PlxuICAgKiA8L21vZGFsLW92ZXJsYXk+XG4gICAqIGBgYFxuICAgKlxuICAgKiBAcGFyYW0gcHJvcCBUaGUgc3R5bGUga2V5XG4gICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUsIHVuZGVmaW5lZCB0byByZW1vdmVcbiAgICovXG4gIHNldENvbnRhaW5lclN0eWxlKHByb3A6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jb250YWluZXIubmF0aXZlRWxlbWVudCwgcHJvcCwgdmFsdWUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZSBhbiBlbGVtZW50IHRoYXQgY2xpY2sgaW5zaWRlIGl0IHdpbGwgbm90IHRyaWdnZXIgbW9kYWwgY2xvc2UuXG4gICAqIFNpbmNlIGV2ZW50cyBidWJibGUsIGNsaWNraW5nIG9uIGEgZGlhbG9nIHdpbGwgYnViYmxlIHVwIHRvIHRoZSBvdmVybGF5LCBhIHBsdWdpblxuICAgKiBtdXN0IGRlZmluZSBhbiBlbGVtZW50IHRoYXQgcmVwcmVzZW50IHRoZSBkaWFsb2csIHRoZSBvdmVybGF5IHdpbGwgbWFrZSBzdXJlIG5vIHRvIGNsb3NlIHdoZW5cbiAgICogaXQgd2FzIGNsaWNrZWQuXG4gICAqIEBwYXJhbSBlbGVtZW50XG4gICAqL1xuICBzZXRDbGlja0JvdW5kYXJ5KGVsZW1lbnQ6IEVsZW1lbnQpOiB2b2lkIHtcbiAgICBsZXQgdGFyZ2V0OiBFbGVtZW50O1xuICAgIGNvbnN0IGVsTGlzdGVuZXIgPSBldmVudCA9PiB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgYW55O1xuICAgIGNvbnN0IGRvY0xpc3RlbmVyID0gZXZlbnQgPT4ge1xuICAgICAgaWYgKHRoaXMuZGlhbG9nUmVmLmNvbnRleHQuaXNCbG9ja2luZyB8fCAhdGhpcy5kaWFsb2dSZWYub3ZlcmxheS5pc1RvcE1vc3QodGhpcy5kaWFsb2dSZWYpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgbGV0IGN1cnJlbnQ6IGFueSA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgLy8gb24gY2xpY2ssIHRoaXMgd2lsbCBoaXQuXG4gICAgICBpZiAoY3VycmVudCA9PT0gdGFyZ2V0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gb24gbW91c2UgZG93biAtPiBkcmFnIC0+IHJlbGVhc2UgdGhlIGN1cnJlbnQgbWlnaHQgbm90IGJlICd0YXJnZXQnLCBpdCBtaWdodCBiZVxuICAgICAgLy8gYSBzaWJsaW5nIG9yIGEgY2hpbGQgKGkuZTogbm90IHBhcnQgb2YgdGhlIHRyZWUtdXAgZGlyZWN0aW9uKS4gSXQgbWlnaHQgYWxzbyBiZSBhIHJlbGVhc2VcbiAgICAgIC8vIG91dHNpZGUgdGhlIGRpYWxvZy4uLiBzbyB3ZSBjb21wYXJlIHRvIHRoZSBib3VuZGFyeSBlbGVtZW50XG4gICAgICBkbyB7XG4gICAgICAgIGlmIChjdXJyZW50ID09PSBlbGVtZW50KSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IHdoaWxlIChjdXJyZW50LnBhcmVudE5vZGUgJiYgKGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudE5vZGUpKTtcbiAgICAgIHRoaXMuZGlhbG9nUmVmLmRpc21pc3MoKTtcbiAgICB9O1xuXG4gICAgaWYgKGlzRG9jKSB7XG4gICAgICB0aGlzLmRpYWxvZ1JlZi5vbkRlc3Ryb3kuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIGVsTGlzdGVuZXIsIGZhbHNlKTtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgZWxMaXN0ZW5lciwgZmFsc2UpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIGRvY0xpc3RlbmVyLCBmYWxzZSk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgZG9jTGlzdGVuZXIsIGZhbHNlKTtcbiAgICAgIH0pO1xuXG5cbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGVsTGlzdGVuZXIsIGZhbHNlKTtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgZG9jTGlzdGVuZXIsIGZhbHNlKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBkb2NMaXN0ZW5lciwgZmFsc2UpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIGRvY0xpc3RlbmVyLCBmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGVtcCB3b3JrYXJvdW5kIGZvciBhbmltYXRpb24gd2hlcmUgZGVzdHJ1Y3Rpb24gb2YgdGhlIHRvcCBsZXZlbCBjb21wb25lbnQgZG9lcyBub3RcbiAgICogdHJpZ2dlciBjaGlsZCBhbmltYXRpb25zLiBTb2x1dGlvbiBzaG91bGQgYmUgZm91bmQgZWl0aGVyIGluIGFuaW1hdGlvbiBtb2R1bGUgb3IgaW4gZGVzaWduXG4gICAqIG9mIHRoZSBtb2RhbCBjb21wb25lbnQgdHJlZS5cbiAgICovXG4gIGNhbkRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29tcGxldGVyID0gbmV3IFByb21pc2VDb21wbGV0ZXI8dm9pZD4oKTtcblxuICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLmJlZm9yZURlc3Ryb3lIYW5kbGVycykpIHtcbiAgICAgIGNvbXBsZXRlci5yZXNvbHZlKCk7XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gcnVuIGRlc3Ryb3kgbm90aWZpY2F0aW9uIGJ1dCBwcm90ZWN0IGFnYWluc3QgaGFsdC5cbiAgICAgIGxldCBpZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZCA9IG51bGw7XG4gICAgICAgIGNvbXBsZXRlci5yZWplY3QoKTtcbiAgICAgIH0sIDEwMDApO1xuXG4gICAgICBjb25zdCByZXNvbHZlID0gKCkgPT4ge1xuICAgICAgICBpZiAoaWQgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjbGVhclRpbWVvdXQoaWQpO1xuICAgICAgICBjb21wbGV0ZXIucmVzb2x2ZSgpO1xuICAgICAgfTtcblxuICAgICAgUHJvbWlzZS5hbGwodGhpcy5iZWZvcmVEZXN0cm95SGFuZGxlcnMubWFwKGZuID0+IGZuKCkpKVxuICAgICAgICAudGhlbihyZXNvbHZlKVxuICAgICAgICAuY2F0Y2gocmVzb2x2ZSk7XG5cbiAgICB9XG5cbiAgICByZXR1cm4gY29tcGxldGVyLnByb21pc2U7XG4gIH1cblxuICAvKipcbiAgICogQSBoYW5kbGVyIHJ1bm5pbmcgYmVmb3JlIGRlc3RydWN0aW9uIG9mIHRoZSBvdmVybGF5XG4gICAqIHVzZSB0byBkZWxheSBkZXN0cnVjdGlvbiBkdWUgdG8gYW5pbWF0aW9uLlxuICAgKiBUaGlzIGlzIHBhcnQgb2YgdGhlIHdvcmthcm91bmQgZm9yIGFuaW1hdGlvbiwgc2VlIGNhbkRlc3Ryb3kuXG4gICAqXG4gICAqIE5PVEU6IFRoZXJlIGlzIG5vIGd1YXJhbnRlZSB0aGF0IHRoZSBsaXN0ZW5lcnMgd2lsbCBmaXJlLCB1c2UgZGlhbG9nLm9uRGVzdG9yeSBmb3IgdGhhdC5cbiAgICogQHBhcmFtIGZuXG4gICAqL1xuICBiZWZvcmVEZXN0cm95KGZuOiAoKSA9PiBQcm9taXNlPHZvaWQ+KSB7XG4gICAgaWYgKCF0aGlzLmJlZm9yZURlc3Ryb3lIYW5kbGVycykge1xuICAgICAgdGhpcy5iZWZvcmVEZXN0cm95SGFuZGxlcnMgPSBbXTtcbiAgICB9XG4gICAgdGhpcy5iZWZvcmVEZXN0cm95SGFuZGxlcnMucHVzaChmbik7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdib2R5OmtleWRvd24nLCBbJyRldmVudCddKVxuICBkb2N1bWVudEtleXByZXNzKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgLy8gY2hlY2sgdGhhdCB0aGlzIG1vZGFsIGlzIHRoZSBsYXN0IGluIHRoZSBzdGFjay5cbiAgICBpZiAoIXRoaXMuZGlhbG9nUmVmLm92ZXJsYXkuaXNUb3BNb3N0KHRoaXMuZGlhbG9nUmVmKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuXG4gICAgaWYgKHN1cHBvcnRzS2V5KGV2ZW50LmtleUNvZGUsIDxhbnk+dGhpcy5kaWFsb2dSZWYuY29udGV4dC5rZXlib2FyZCkpIHtcbiAgICAgIHRoaXMuZGlhbG9nUmVmLmRpc21pc3MoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBzdXBlci5uZ09uRGVzdHJveSgpO1xuICAgIGlmICh0aGlzLmRpYWxvZ1JlZi5kZXN0cm95ZWQgIT09IHRydWUpIHtcbiAgICAgIC8vIGlmIHdlJ3JlIGhlcmUgdGhlIG92ZXJsYXkgaXMgZGVzdHJveWVkIGJ5IGFuIGV4dGVybmFsIGV2ZW50IHRoYXQgaXMgbm90IHVzZXIgaW52b2tlZC5cbiAgICAgIC8vIGkuZTogVGhlIHVzZXIgZGlkIG5vIGNhbGwgZGlzbWlzcyBvciBjbG9zZSBhbmQgZGlhbG9nUmVmLmRlc3Ryb3koKSBkaWQgbm90IGludm9rZS5cbiAgICAgIC8vIHRoaXMgd2lsbCBoYXBwZW4gd2hlbiByb3V0aW5nIG9yIGtpbGxpbmcgYW4gZWxlbWVudCBjb250YWluaW5nIGEgYmxvY2tlZCBvdmVybGF5IChuZ0lmKVxuICAgICAgLy8gd2UgYmFpbCBvdXQsIGkuZSBncmFjZWZ1bGx5IHNodXR0aW5nIGRvd24uXG4gICAgICB0aGlzLmRpYWxvZ1JlZi5iYWlsT3V0KCk7XG4gICAgfVxuICB9XG59XG4iXX0=