@ng-bootstrap/ng-bootstrap
Version:
Angular powered Bootstrap
228 lines • 34.7 kB
JavaScript
import { DOCUMENT } from '@angular/common';
import { ApplicationRef, createComponent, EnvironmentInjector, EventEmitter, inject, Injectable, Injector, NgZone, TemplateRef, } from '@angular/core';
import { Subject } from 'rxjs';
import { ngbFocusTrap } from '../util/focus-trap';
import { ContentRef } from '../util/popup';
import { ScrollBar } from '../util/scrollbar';
import { isDefined, isString } from '../util/util';
import { NgbModalBackdrop } from './modal-backdrop';
import { NgbActiveModal, NgbModalRef } from './modal-ref';
import { NgbModalWindow } from './modal-window';
import { take } from 'rxjs/operators';
import * as i0 from "@angular/core";
export class NgbModalStack {
constructor() {
this._applicationRef = inject(ApplicationRef);
this._injector = inject(Injector);
this._environmentInjector = inject(EnvironmentInjector);
this._document = inject(DOCUMENT);
this._scrollBar = inject(ScrollBar);
this._activeWindowCmptHasChanged = new Subject();
this._ariaHiddenValues = new Map();
this._scrollBarRestoreFn = null;
this._modalRefs = [];
this._windowCmpts = [];
this._activeInstances = new EventEmitter();
const ngZone = inject(NgZone);
// Trap focus on active WindowCmpt
this._activeWindowCmptHasChanged.subscribe(() => {
if (this._windowCmpts.length) {
const activeWindowCmpt = this._windowCmpts[this._windowCmpts.length - 1];
ngbFocusTrap(ngZone, activeWindowCmpt.location.nativeElement, this._activeWindowCmptHasChanged);
this._revertAriaHidden();
this._setAriaHidden(activeWindowCmpt.location.nativeElement);
}
});
}
_restoreScrollBar() {
const scrollBarRestoreFn = this._scrollBarRestoreFn;
if (scrollBarRestoreFn) {
this._scrollBarRestoreFn = null;
scrollBarRestoreFn();
}
}
_hideScrollBar() {
if (!this._scrollBarRestoreFn) {
this._scrollBarRestoreFn = this._scrollBar.hide();
}
}
open(contentInjector, content, options) {
const containerEl = options.container instanceof HTMLElement
? options.container
: isDefined(options.container)
? this._document.querySelector(options.container)
: this._document.body;
if (!containerEl) {
throw new Error(`The specified modal container "${options.container || 'body'}" was not found in the DOM.`);
}
this._hideScrollBar();
const activeModal = new NgbActiveModal();
contentInjector = options.injector || contentInjector;
const environmentInjector = contentInjector.get(EnvironmentInjector, null) || this._environmentInjector;
const contentRef = this._getContentRef(contentInjector, environmentInjector, content, activeModal, options);
let backdropCmptRef = options.backdrop !== false ? this._attachBackdrop(containerEl) : undefined;
let windowCmptRef = this._attachWindowComponent(containerEl, contentRef.nodes);
let ngbModalRef = new NgbModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);
this._registerModalRef(ngbModalRef);
this._registerWindowCmpt(windowCmptRef);
// We have to cleanup DOM after the last modal when BOTH 'hidden' was emitted and 'result' promise was resolved:
// - with animations OFF, 'hidden' emits synchronously, then 'result' is resolved asynchronously
// - with animations ON, 'result' is resolved asynchronously, then 'hidden' emits asynchronously
ngbModalRef.hidden.pipe(take(1)).subscribe(() => Promise.resolve(true).then(() => {
if (!this._modalRefs.length) {
this._document.body.classList.remove('modal-open');
this._restoreScrollBar();
this._revertAriaHidden();
}
}));
activeModal.close = (result) => {
ngbModalRef.close(result);
};
activeModal.dismiss = (reason) => {
ngbModalRef.dismiss(reason);
};
activeModal.update = (options) => {
ngbModalRef.update(options);
};
ngbModalRef.update(options);
if (this._modalRefs.length === 1) {
this._document.body.classList.add('modal-open');
}
if (backdropCmptRef && backdropCmptRef.instance) {
backdropCmptRef.changeDetectorRef.detectChanges();
}
windowCmptRef.changeDetectorRef.detectChanges();
return ngbModalRef;
}
get activeInstances() {
return this._activeInstances;
}
dismissAll(reason) {
this._modalRefs.forEach((ngbModalRef) => ngbModalRef.dismiss(reason));
}
hasOpenModals() {
return this._modalRefs.length > 0;
}
_attachBackdrop(containerEl) {
let backdropCmptRef = createComponent(NgbModalBackdrop, {
environmentInjector: this._applicationRef.injector,
elementInjector: this._injector,
});
this._applicationRef.attachView(backdropCmptRef.hostView);
containerEl.appendChild(backdropCmptRef.location.nativeElement);
return backdropCmptRef;
}
_attachWindowComponent(containerEl, projectableNodes) {
let windowCmptRef = createComponent(NgbModalWindow, {
environmentInjector: this._applicationRef.injector,
elementInjector: this._injector,
projectableNodes,
});
this._applicationRef.attachView(windowCmptRef.hostView);
containerEl.appendChild(windowCmptRef.location.nativeElement);
return windowCmptRef;
}
_getContentRef(contentInjector, environmentInjector, content, activeModal, options) {
if (!content) {
return new ContentRef([]);
}
else if (content instanceof TemplateRef) {
return this._createFromTemplateRef(content, activeModal);
}
else if (isString(content)) {
return this._createFromString(content);
}
else {
return this._createFromComponent(contentInjector, environmentInjector, content, activeModal, options);
}
}
_createFromTemplateRef(templateRef, activeModal) {
const context = {
$implicit: activeModal,
close(result) {
activeModal.close(result);
},
dismiss(reason) {
activeModal.dismiss(reason);
},
};
const viewRef = templateRef.createEmbeddedView(context);
this._applicationRef.attachView(viewRef);
return new ContentRef([viewRef.rootNodes], viewRef);
}
_createFromString(content) {
const component = this._document.createTextNode(`${content}`);
return new ContentRef([[component]]);
}
_createFromComponent(contentInjector, environmentInjector, componentType, context, options) {
const elementInjector = Injector.create({
providers: [{ provide: NgbActiveModal, useValue: context }],
parent: contentInjector,
});
const componentRef = createComponent(componentType, {
environmentInjector,
elementInjector,
});
const componentNativeEl = componentRef.location.nativeElement;
if (options.scrollable) {
componentNativeEl.classList.add('component-host-scrollable');
}
this._applicationRef.attachView(componentRef.hostView);
// FIXME: we should here get rid of the component nativeElement
// and use `[Array.from(componentNativeEl.childNodes)]` instead and remove the above CSS class.
return new ContentRef([[componentNativeEl]], componentRef.hostView, componentRef);
}
_setAriaHidden(element) {
const parent = element.parentElement;
if (parent && element !== this._document.body) {
Array.from(parent.children).forEach((sibling) => {
if (sibling !== element && sibling.nodeName !== 'SCRIPT') {
this._ariaHiddenValues.set(sibling, sibling.getAttribute('aria-hidden'));
sibling.setAttribute('aria-hidden', 'true');
}
});
this._setAriaHidden(parent);
}
}
_revertAriaHidden() {
this._ariaHiddenValues.forEach((value, element) => {
if (value) {
element.setAttribute('aria-hidden', value);
}
else {
element.removeAttribute('aria-hidden');
}
});
this._ariaHiddenValues.clear();
}
_registerModalRef(ngbModalRef) {
const unregisterModalRef = () => {
const index = this._modalRefs.indexOf(ngbModalRef);
if (index > -1) {
this._modalRefs.splice(index, 1);
this._activeInstances.emit(this._modalRefs);
}
};
this._modalRefs.push(ngbModalRef);
this._activeInstances.emit(this._modalRefs);
ngbModalRef.result.then(unregisterModalRef, unregisterModalRef);
}
_registerWindowCmpt(ngbWindowCmpt) {
this._windowCmpts.push(ngbWindowCmpt);
this._activeWindowCmptHasChanged.next();
ngbWindowCmpt.onDestroy(() => {
const index = this._windowCmpts.indexOf(ngbWindowCmpt);
if (index > -1) {
this._windowCmpts.splice(index, 1);
this._activeWindowCmptHasChanged.next();
}
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbModalStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbModalStack, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbModalStack, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbW9kYWwvbW9kYWwtc3RhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFDTixjQUFjLEVBRWQsZUFBZSxFQUNmLG1CQUFtQixFQUNuQixZQUFZLEVBQ1osTUFBTSxFQUNOLFVBQVUsRUFDVixRQUFRLEVBQ1IsTUFBTSxFQUNOLFdBQVcsR0FFWCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRS9CLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNuRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUd0QyxNQUFNLE9BQU8sYUFBYTtJQWN6QjtRQWJRLG9CQUFlLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3pDLGNBQVMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IseUJBQW9CLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDbkQsY0FBUyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3QixlQUFV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LEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksRUFBRSxDQUFDO2FBQ3hDO1FBQ0YsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDOzhHQTNQVyxhQUFhO2tIQUFiLGFBQWEsY0FEQSxNQUFNOzsyRkFDbkIsYUFBYTtrQkFEekIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuXHRBcHBsaWNhdGlvblJlZixcblx0Q29tcG9uZW50UmVmLFxuXHRjcmVhdGVDb21wb25lbnQsXG5cdEVudmlyb25tZW50SW5qZWN0b3IsXG5cdEV2ZW50RW1pdHRlcixcblx0aW5qZWN0LFxuXHRJbmplY3RhYmxlLFxuXHRJbmplY3Rvcixcblx0Tmdab25lLFxuXHRUZW1wbGF0ZVJlZixcblx0VHlwZSxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IG5nYkZvY3VzVHJhcCB9IGZyb20gJy4uL3V0aWwvZm9jdXMtdHJhcCc7XG5pbXBvcnQgeyBDb250ZW50UmVmIH0gZnJvbSAnLi4vdXRpbC9wb3B1cCc7XG5pbXBvcnQgeyBTY3JvbGxCYXIgfSBmcm9tICcuLi91dGlsL3Njcm9sbGJhcic7XG5pbXBvcnQgeyBpc0RlZmluZWQsIGlzU3RyaW5nIH0gZnJvbSAnLi4vdXRpbC91dGlsJztcbmltcG9ydCB7IE5nYk1vZGFsQmFja2Ryb3AgfSBmcm9tICcuL21vZGFsLWJhY2tkcm9wJztcbmltcG9ydCB7IE5nYk1vZGFsT3B0aW9ucywgTmdiTW9kYWxVcGRhdGFibGVPcHRpb25zIH0gZnJvbSAnLi9tb2RhbC1jb25maWcnO1xuaW1wb3J0IHsgTmdiQWN0aXZlTW9kYWwsIE5nYk1vZGFsUmVmIH0gZnJvbSAnLi9tb2RhbC1yZWYnO1xuaW1wb3J0IHsgTmdiTW9kYWxXaW5kb3cgfSBmcm9tICcuL21vZGFsLXdpbmRvdyc7XG5pbXBvcnQgeyB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIE5nYk1vZGFsU3RhY2sge1xuXHRwcml2YXRlIF9hcHBsaWNhdGlvblJlZiA9IGluamVjdChBcHBsaWNhdGlvblJlZik7XG5cdHByaXZhdGUgX2luamVjdG9yID0gaW5qZWN0KEluamVjdG9yKTtcblx0cHJpdmF0ZSBfZW52aXJvbm1lbnRJbmplY3RvciA9IGluamVjdChFbnZpcm9ubWVudEluamVjdG9yKTtcblx0cHJpdmF0ZSBfZG9jdW1lbnQgPSBpbmplY3QoRE9DVU1FTlQpO1xuXHRwcml2YXRlIF9zY3JvbGxCYXIgPSBpbmplY3QoU2Nyb2xsQmFyKTtcblxuXHRwcml2YXRlIF9hY3RpdmVXaW5kb3dDbXB0SGFzQ2hhbmdlZCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cdHByaXZhdGUgX2FyaWFIaWRkZW5WYWx1ZXM6IE1hcDxFbGVtZW50LCBzdHJpbmcgfCBudWxsPiA9IG5ldyBNYXAoKTtcblx0cHJpdmF0ZSBfc2Nyb2xsQmFyUmVzdG9yZUZuOiBudWxsIHwgKCgpID0+IHZvaWQpID0gbnVsbDtcblx0cHJpdmF0ZSBfbW9kYWxSZWZzOiBOZ2JNb2RhbFJlZltdID0gW107XG5cdHByaXZhdGUgX3dpbmRvd0NtcHRzOiBDb21wb25lbnRSZWY8TmdiTW9kYWxXaW5kb3c+W10gPSBbXTtcblx0cHJpdmF0ZSBfYWN0aXZlSW5zdGFuY2VzOiBFdmVudEVtaXR0ZXI8TmdiTW9kYWxSZWZbXT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0Y29uc3Qgbmdab25lID0gaW5qZWN0KE5nWm9uZSk7XG5cblx0XHQvLyBUcmFwIGZvY3VzIG9uIGFjdGl2ZSBXaW5kb3dDbXB0XG5cdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdGlmICh0aGlzLl93aW5kb3dDbXB0cy5sZW5ndGgpIHtcblx0XHRcdFx0Y29uc3QgYWN0aXZlV2luZG93Q21wdCA9IHRoaXMuX3dpbmRvd0NtcHRzW3RoaXMuX3dpbmRvd0NtcHRzLmxlbmd0aCAtIDFdO1xuXHRcdFx0XHRuZ2JGb2N1c1RyYXAobmdab25lLCBhY3RpdmVXaW5kb3dDbXB0LmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQsIHRoaXMuX2FjdGl2ZVdpbmRvd0NtcHRIYXNDaGFuZ2VkKTtcblx0XHRcdFx0dGhpcy5fcmV2ZXJ0QXJpYUhpZGRlbigpO1xuXHRcdFx0XHR0aGlzLl9zZXRBcmlhSGlkZGVuKGFjdGl2ZVdpbmRvd0NtcHQubG9jYXRpb24ubmF0aXZlRWxlbWVudCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIF9yZXN0b3JlU2Nyb2xsQmFyKCkge1xuXHRcdGNvbnN0IHNjcm9sbEJhclJlc3RvcmVGbiA9IHRoaXMuX3Njcm9sbEJhclJlc3RvcmVGbjtcblx0XHRpZiAoc2Nyb2xsQmFyUmVzdG9yZUZuKSB7XG5cdFx0XHR0aGlzLl9zY3JvbGxCYXJSZXN0b3JlRm4gPSBudWxsO1xuXHRcdFx0c2Nyb2xsQmFyUmVzdG9yZUZuKCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfaGlkZVNjcm9sbEJhcigpIHtcblx0XHRpZiAoIXRoaXMuX3Njcm9sbEJhclJlc3RvcmVGbikge1xuXHRcdFx0dGhpcy5fc2Nyb2xsQmFyUmVzdG9yZUZuID0gdGhpcy5fc2Nyb2xsQmFyLmhpZGUoKTtcblx0XHR9XG5cdH1cblxuXHRvcGVuKGNvbnRlbnRJbmplY3RvcjogSW5qZWN0b3IsIGNvbnRlbnQ6IGFueSwgb3B0aW9uczogTmdiTW9kYWxPcHRpb25zKTogTmdiTW9kYWxSZWYge1xuXHRcdGNvbnN0IGNvbnRhaW5lckVsID1cblx0XHRcdG9wdGlvbnMuY29udGFpbmVyIGluc3RhbmNlb2YgSFRNTEVsZW1lbnRcblx0XHRcdFx0PyBvcHRpb25zLmNvbnRhaW5lclxuXHRcdFx0XHQ6IGlzRGVmaW5lZChvcHRpb25zLmNvbnRhaW5lcilcblx0XHRcdFx0ICA/IHRoaXMuX2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iob3B0aW9ucy5jb250YWluZXIhKVxuXHRcdFx0XHQgIDogdGhpcy5fZG9jdW1lbnQuYm9keTtcblxuXHRcdGlmICghY29udGFpbmVyRWwpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgVGhlIHNwZWNpZmllZCBtb2RhbCBjb250YWluZXIgXCIke29wdGlvbnMuY29udGFpbmVyIHx8ICdib2R5J31cIiB3YXMgbm90IGZvdW5kIGluIHRoZSBET00uYCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5faGlkZVNjcm9sbEJhcigpO1xuXG5cdFx0Y29uc3QgYWN0aXZlTW9kYWwgPSBuZXcgTmdiQWN0aXZlTW9kYWwoKTtcblxuXHRcdGNvbnRlbnRJbmplY3RvciA9IG9wdGlvbnMuaW5qZWN0b3IgfHwgY29udGVudEluamVjdG9yO1xuXHRcdGNvbnN0IGVudmlyb25tZW50SW5qZWN0b3IgPSBjb250ZW50SW5qZWN0b3IuZ2V0KEVudmlyb25tZW50SW5qZWN0b3IsIG51bGwpIHx8IHRoaXMuX2Vudmlyb25tZW50SW5qZWN0b3I7XG5cdFx0Y29uc3QgY29udGVudFJlZiA9IHRoaXMuX2dldENvbnRlbnRSZWYoY29udGVudEluamVjdG9yLCBlbnZpcm9ubWVudEluamVjdG9yLCBjb250ZW50LCBhY3RpdmVNb2RhbCwgb3B0aW9ucyk7XG5cblx0XHRsZXQgYmFja2Ryb3BDbXB0UmVmOiBDb21wb25lbnRSZWY8TmdiTW9kYWxCYWNrZHJvcD4gfCB1bmRlZmluZWQgPVxuXHRcdFx0b3B0aW9ucy5iYWNrZHJvcCAhPT0gZmFsc2UgPyB0aGlzLl9hdHRhY2hCYWNrZHJvcChjb250YWluZXJFbCkgOiB1bmRlZmluZWQ7XG5cdFx0bGV0IHdpbmRvd0NtcHRSZWY6IENvbXBvbmVudFJlZjxOZ2JNb2RhbFdpbmRvdz4gPSB0aGlzLl9hdHRhY2hXaW5kb3dDb21wb25lbnQoY29udGFpbmVyRWwsIGNvbnRlbnRSZWYubm9kZXMpO1xuXHRcdGxldCBuZ2JNb2RhbFJlZjogTmdiTW9kYWxSZWYgPSBuZXcgTmdiTW9kYWxSZWYod2luZG93Q21wdFJlZiwgY29udGVudFJlZiwgYmFja2Ryb3BDbXB0UmVmLCBvcHRpb25zLmJlZm9yZURpc21pc3MpO1xuXG5cdFx0dGhpcy5fcmVnaXN0ZXJNb2RhbFJlZihuZ2JNb2RhbFJlZik7XG5cdFx0dGhpcy5fcmVnaXN0ZXJXaW5kb3dDbXB0KHdpbmRvd0NtcHRSZWYpO1xuXG5cdFx0Ly8gV2UgaGF2ZSB0byBjbGVhbnVwIERPTSBhZnRlciB0aGUgbGFzdCBtb2RhbCB3aGVuIEJPVEggJ2hpZGRlbicgd2FzIGVtaXR0ZWQgYW5kICdyZXN1bHQnIHByb21pc2Ugd2FzIHJlc29sdmVkOlxuXHRcdC8vIC0gd2l0aCBhbmltYXRpb25zIE9GRiwgJ2hpZGRlbicgZW1pdHMgc3luY2hyb25vdXNseSwgdGhlbiAncmVzdWx0JyBpcyByZXNvbHZlZCBhc3luY2hyb25vdXNseVxuXHRcdC8vIC0gd2l0aCBhbmltYXRpb25zIE9OLCAncmVzdWx0JyBpcyByZXNvbHZlZCBhc3luY2hyb25vdXNseSwgdGhlbiAnaGlkZGVuJyBlbWl0cyBhc3luY2hyb25vdXNseVxuXHRcdG5nYk1vZGFsUmVmLmhpZGRlbi5waXBlKHRha2UoMSkpLnN1YnNjcmliZSgoKSA9PlxuXHRcdFx0UHJvbWlzZS5yZXNvbHZlKHRydWUpLnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRpZiAoIXRoaXMuX21vZGFsUmVmcy5sZW5ndGgpIHtcblx0XHRcdFx0XHR0aGlzLl9kb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ21vZGFsLW9wZW4nKTtcblx0XHRcdFx0XHR0aGlzLl9yZXN0b3JlU2Nyb2xsQmFyKCk7XG5cdFx0XHRcdFx0dGhpcy5fcmV2ZXJ0QXJpYUhpZGRlbigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KSxcblx0XHQpO1xuXG5cdFx0YWN0aXZlTW9kYWwuY2xvc2UgPSAocmVzdWx0OiBhbnkpID0+IHtcblx0XHRcdG5nYk1vZGFsUmVmLmNsb3NlKHJlc3VsdCk7XG5cdFx0fTtcblx0XHRhY3RpdmVNb2RhbC5kaXNtaXNzID0gKHJlYXNvbjogYW55KSA9PiB7XG5cdFx0XHRuZ2JNb2RhbFJlZi5kaXNtaXNzKHJlYXNvbik7XG5cdFx0fTtcblxuXHRcdGFjdGl2ZU1vZGFsLnVwZGF0ZSA9IChvcHRpb25zOiBOZ2JNb2RhbFVwZGF0YWJsZU9wdGlvbnMpID0+IHtcblx0XHRcdG5nYk1vZGFsUmVmLnVwZGF0ZShvcHRpb25zKTtcblx0XHR9O1xuXG5cdFx0bmdiTW9kYWxSZWYudXBkYXRlKG9wdGlvbnMpO1xuXHRcdGlmICh0aGlzLl9tb2RhbFJlZnMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHR0aGlzLl9kb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ21vZGFsLW9wZW4nKTtcblx0XHR9XG5cblx0XHRpZiAoYmFja2Ryb3BDbXB0UmVmICYmIGJhY2tkcm9wQ21wdFJlZi5pbnN0YW5jZSkge1xuXHRcdFx0YmFja2Ryb3BDbXB0UmVmLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcblx0XHR9XG5cdFx0d2luZG93Q21wdFJlZi5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0cmV0dXJuIG5nYk1vZGFsUmVmO1xuXHR9XG5cblx0Z2V0IGFjdGl2ZUluc3RhbmNlcygpIHtcblx0XHRyZXR1cm4gdGhpcy5fYWN0aXZlSW5zdGFuY2VzO1xuXHR9XG5cblx0ZGlzbWlzc0FsbChyZWFzb24/OiBhbnkpIHtcblx0XHR0aGlzLl9tb2RhbFJlZnMuZm9yRWFjaCgobmdiTW9kYWxSZWYpID0+IG5nYk1vZGFsUmVmLmRpc21pc3MocmVhc29uKSk7XG5cdH1cblxuXHRoYXNPcGVuTW9kYWxzKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLl9tb2RhbFJlZnMubGVuZ3RoID4gMDtcblx0fVxuXG5cdHByaXZhdGUgX2F0dGFjaEJhY2tkcm9wKGNvbnRhaW5lckVsOiBFbGVtZW50KTogQ29tcG9uZW50UmVmPE5nYk1vZGFsQmFja2Ryb3A+IHtcblx0XHRsZXQgYmFja2Ryb3BDbXB0UmVmID0gY3JlYXRlQ29tcG9uZW50KE5nYk1vZGFsQmFja2Ryb3AsIHtcblx0XHRcdGVudmlyb25tZW50SW5qZWN0b3I6IHRoaXMuX2FwcGxpY2F0aW9uUmVmLmluamVjdG9yLFxuXHRcdFx0ZWxlbWVudEluamVjdG9yOiB0aGlzLl9pbmplY3Rvcixcblx0XHR9KTtcblx0XHR0aGlzLl9hcHBsaWNhdGlvblJlZi5hdHRhY2hWaWV3KGJhY2tkcm9wQ21wdFJlZi5ob3N0Vmlldyk7XG5cdFx0Y29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoYmFja2Ryb3BDbXB0UmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdHJldHVybiBiYWNrZHJvcENtcHRSZWY7XG5cdH1cblxuXHRwcml2YXRlIF9hdHRhY2hXaW5kb3dDb21wb25lbnQoY29udGFpbmVyRWw6IEVsZW1lbnQsIHByb2plY3RhYmxlTm9kZXM6IE5vZGVbXVtdKTogQ29tcG9uZW50UmVmPE5nYk1vZGFsV2luZG93PiB7XG5cdFx0bGV0IHdpbmRvd0NtcHRSZWYgPSBjcmVhdGVDb21wb25lbnQoTmdiTW9kYWxXaW5kb3csIHtcblx0XHRcdGVudmlyb25tZW50SW5qZWN0b3I6IHRoaXMuX2FwcGxpY2F0aW9uUmVmLmluamVjdG9yLFxuXHRcdFx0ZWxlbWVudEluamVjdG9yOiB0aGlzLl9pbmplY3Rvcixcblx0XHRcdHByb2plY3RhYmxlTm9kZXMsXG5cdFx0fSk7XG5cdFx0dGhpcy5fYXBwbGljYXRpb25SZWYuYXR0YWNoVmlldyh3aW5kb3dDbXB0UmVmLmhvc3RWaWV3KTtcblx0XHRjb250YWluZXJFbC5hcHBlbmRDaGlsZCh3aW5kb3dDbXB0UmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdHJldHVybiB3aW5kb3dDbXB0UmVmO1xuXHR9XG5cblx0cHJpdmF0ZSBfZ2V0Q29udGVudFJlZihcblx0XHRjb250ZW50SW5qZWN0b3I6IEluamVjdG9yLFxuXHRcdGVudmlyb25tZW50SW5qZWN0b3I6IEVudmlyb25tZW50SW5qZWN0b3IsXG5cdFx0Y29udGVudDogVHlwZTxhbnk+IHwgVGVtcGxhdGVSZWY8YW55PiB8IHN0cmluZyxcblx0XHRhY3RpdmVNb2RhbDogTmdiQWN0aXZlTW9kYWwsXG5cdFx0b3B0aW9uczogTmdiTW9kYWxPcHRpb25zLFxuXHQpOiBDb250ZW50UmVmIHtcblx0XHRpZiAoIWNvbnRlbnQpIHtcblx0XHRcdHJldHVybiBuZXcgQ29udGVudFJlZihbXSk7XG5cdFx0fSBlbHNlIGlmIChjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYpIHtcblx0XHRcdHJldHVybiB0aGlzLl9jcmVhdGVGcm9tVGVtcGxhdGVSZWYoY29udGVudCwgYWN0aXZlTW9kYWwpO1xuXHRcdH0gZWxzZSBpZiAoaXNTdHJpbmcoY29udGVudCkpIHtcblx0XHRcdHJldHVybiB0aGlzLl9jcmVhdGVGcm9tU3RyaW5nKGNvbnRlbnQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlRnJvbUNvbXBvbmVudChjb250ZW50SW5qZWN0b3IsIGVudmlyb25tZW50SW5qZWN0b3IsIGNvbnRlbnQsIGFjdGl2ZU1vZGFsLCBvcHRpb25zKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF9jcmVhdGVGcm9tVGVtcGxhdGVSZWYodGVtcGxhdGVSZWY6IFRlbXBsYXRlUmVmPGFueT4sIGFjdGl2ZU1vZGFsOiBOZ2JBY3RpdmVNb2RhbCk6IENvbnRlbnRSZWYge1xuXHRcdGNvbnN0IGNvbnRleHQgPSB7XG5cdFx0XHQkaW1wbGljaXQ6IGFjdGl2ZU1vZGFsLFxuXHRcdFx0Y2xvc2UocmVzdWx0KSB7XG5cdFx0XHRcdGFjdGl2ZU1vZGFsLmNsb3NlKHJlc3VsdCk7XG5cdFx0XHR9LFxuXHRcdFx0ZGlzbWlzcyhyZWFzb24pIHtcblx0XHRcdFx0YWN0aXZlTW9kYWwuZGlzbWlzcyhyZWFzb24pO1xuXHRcdFx0fSxcblx0XHR9O1xuXHRcdGNvbnN0IHZpZXdSZWYgPSB0ZW1wbGF0ZVJlZi5jcmVhdGVFbWJlZGRlZFZpZXcoY29udGV4dCk7XG5cdFx0dGhpcy5fYXBwbGljYXRpb25SZWYuYXR0YWNoVmlldyh2aWV3UmVmKTtcblx0XHRyZXR1cm4gbmV3IENvbnRlbnRSZWYoW3ZpZXdSZWYucm9vdE5vZGVzXSwgdmlld1JlZik7XG5cdH1cblxuXHRwcml2YXRlIF9jcmVhdGVGcm9tU3RyaW5nKGNvbnRlbnQ6IHN0cmluZyk6IENvbnRlbnRSZWYge1xuXHRcdGNvbnN0IGNvbXBvbmVudCA9IHRoaXMuX2RvY3VtZW50LmNyZWF0ZVRleHROb2RlKGAke2NvbnRlbnR9YCk7XG5cdFx0cmV0dXJuIG5ldyBDb250ZW50UmVmKFtbY29tcG9uZW50XV0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfY3JlYXRlRnJvbUNvbXBvbmVudChcblx0XHRjb250ZW50SW5qZWN0b3I6IEluamVjdG9yLFxuXHRcdGVudmlyb25tZW50SW5qZWN0b3I6IEVudmlyb25tZW50SW5qZWN0b3IsXG5cdFx0Y29tcG9uZW50VHlwZTogVHlwZTxhbnk+LFxuXHRcdGNvbnRleHQ6IE5nYkFjdGl2ZU1vZGFsLFxuXHRcdG9wdGlvbnM6IE5nYk1vZGFsT3B0aW9ucyxcblx0KTogQ29udGVudFJlZiB7XG5cdFx0Y29uc3QgZWxlbWVudEluamVjdG9yID0gSW5qZWN0b3IuY3JlYXRlKHtcblx0XHRcdHByb3ZpZGVyczogW3sgcHJvdmlkZTogTmdiQWN0aXZlTW9kYWwsIHVzZVZhbHVlOiBjb250ZXh0IH1dLFxuXHRcdFx0cGFyZW50OiBjb250ZW50SW5qZWN0b3IsXG5cdFx0fSk7XG5cdFx0Y29uc3QgY29tcG9uZW50UmVmID0gY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudFR5cGUsIHtcblx0XHRcdGVudmlyb25tZW50SW5qZWN0b3IsXG5cdFx0XHRlbGVtZW50SW5qZWN0b3IsXG5cdFx0fSk7XG5cdFx0Y29uc3QgY29tcG9uZW50TmF0aXZlRWwgPSBjb21wb25lbnRSZWYubG9jYXRpb24ubmF0aXZlRWxlbWVudDtcblx0XHRpZiAob3B0aW9ucy5zY3JvbGxhYmxlKSB7XG5cdFx0XHQoY29tcG9uZW50TmF0aXZlRWwgYXMgSFRNTEVsZW1lbnQpLmNsYXNzTGlzdC5hZGQoJ2NvbXBvbmVudC1ob3N0LXNjcm9sbGFibGUnKTtcblx0XHR9XG5cdFx0dGhpcy5fYXBwbGljYXRpb25SZWYuYXR0YWNoVmlldyhjb21wb25lbnRSZWYuaG9zdFZpZXcpO1xuXHRcdC8vIEZJWE1FOiB3ZSBzaG91bGQgaGVyZSBnZXQgcmlkIG9mIHRoZSBjb21wb25lbnQgbmF0aXZlRWxlbWVudFxuXHRcdC8vIGFuZCB1c2UgYFtBcnJheS5mcm9tKGNvbXBvbmVudE5hdGl2ZUVsLmNoaWxkTm9kZXMpXWAgaW5zdGVhZCBhbmQgcmVtb3ZlIHRoZSBhYm92ZSBDU1MgY2xhc3MuXG5cdFx0cmV0dXJuIG5ldyBDb250ZW50UmVmKFtbY29tcG9uZW50TmF0aXZlRWxdXSwgY29tcG9uZW50UmVmLmhvc3RWaWV3LCBjb21wb25lbnRSZWYpO1xuXHR9XG5cblx0cHJpdmF0ZSBfc2V0QXJpYUhpZGRlbihlbGVtZW50OiBFbGVtZW50KSB7XG5cdFx0Y29uc3QgcGFyZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50O1xuXHRcdGlmIChwYXJlbnQgJiYgZWxlbWVudCAhPT0gdGhpcy5fZG9jdW1lbnQuYm9keSkge1xuXHRcdFx0QXJyYXkuZnJvbShwYXJlbnQuY2hpbGRyZW4pLmZvckVhY2goKHNpYmxpbmcpID0+IHtcblx0XHRcdFx0aWYgKHNpYmxpbmcgIT09IGVsZW1lbnQgJiYgc2libGluZy5ub2RlTmFtZSAhPT0gJ1NDUklQVCcpIHtcblx0XHRcdFx0XHR0aGlzLl9hcmlhSGlkZGVuVmFsdWVzLnNldChzaWJsaW5nLCBzaWJsaW5nLmdldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKSk7XG5cdFx0XHRcdFx0c2libGluZy5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgJ3RydWUnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMuX3NldEFyaWFIaWRkZW4ocGFyZW50KTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF9yZXZlcnRBcmlhSGlkZGVuKCkge1xuXHRcdHRoaXMuX2FyaWFIaWRkZW5WYWx1ZXMuZm9yRWFjaCgodmFsdWUsIGVsZW1lbnQpID0+IHtcblx0XHRcdGlmICh2YWx1ZSkge1xuXHRcdFx0XHRlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCB2YWx1ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHR0aGlzLl9hcmlhSGlkZGVuVmFsdWVzLmNsZWFyKCk7XG5cdH1cblxuXHRwcml2YXRlIF9yZWdpc3Rlck1vZGFsUmVmKG5nYk1vZGFsUmVmOiBOZ2JNb2RhbFJlZikge1xuXHRcdGNvbnN0IHVucmVnaXN0ZXJNb2RhbFJlZiA9ICgpID0+IHtcblx0XHRcdGNvbnN0IGluZGV4ID0gdGhpcy5fbW9kYWxSZWZzLmluZGV4T2YobmdiTW9kYWxSZWYpO1xuXHRcdFx0aWYgKGluZGV4ID4gLTEpIHtcblx0XHRcdFx0dGhpcy5fbW9kYWxSZWZzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0XHRcdHRoaXMuX2FjdGl2ZUluc3RhbmNlcy5lbWl0KHRoaXMuX21vZGFsUmVmcyk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHR0aGlzLl9tb2RhbFJlZnMucHVzaChuZ2JNb2RhbFJlZik7XG5cdFx0dGhpcy5fYWN0aXZlSW5zdGFuY2VzLmVtaXQodGhpcy5fbW9kYWxSZWZzKTtcblx0XHRuZ2JNb2RhbFJlZi5yZXN1bHQudGhlbih1bnJlZ2lzdGVyTW9kYWxSZWYsIHVucmVnaXN0ZXJNb2RhbFJlZik7XG5cdH1cblxuXHRwcml2YXRlIF9yZWdpc3RlcldpbmRvd0NtcHQobmdiV2luZG93Q21wdDogQ29tcG9uZW50UmVmPE5nYk1vZGFsV2luZG93Pikge1xuXHRcdHRoaXMuX3dpbmRvd0NtcHRzLnB1c2gobmdiV2luZG93Q21wdCk7XG5cdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuXG5cdFx0bmdiV2luZG93Q21wdC5vbkRlc3Ryb3koKCkgPT4ge1xuXHRcdFx0Y29uc3QgaW5kZXggPSB0aGlzLl93aW5kb3dDbXB0cy5pbmRleE9mKG5nYldpbmRvd0NtcHQpO1xuXHRcdFx0aWYgKGluZGV4ID4gLTEpIHtcblx0XHRcdFx0dGhpcy5fd2luZG93Q21wdHMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHRcdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG4iXX0=