UNPKG

@ng-bootstrap/ng-bootstrap

Version:
230 lines 30.2 kB
import { DOCUMENT } from '@angular/common'; import { Component, ElementRef, EventEmitter, inject, Input, NgZone, Output, ViewChild, ViewEncapsulation, } from '@angular/core'; import { fromEvent, Subject, zip } from 'rxjs'; import { filter, switchMap, take, takeUntil, tap } from 'rxjs/operators'; import { getFocusableBoundaryElements } from '../util/focus-trap'; import { Key } from '../util/key'; import { ModalDismissReasons } from './modal-dismiss-reasons'; import { ngbRunTransition } from '../util/transition/ngbTransition'; import { isString, reflow } from '../util/util'; import * as i0 from "@angular/core"; export class NgbModalWindow { constructor() { this._document = inject(DOCUMENT); this._elRef = inject((ElementRef)); this._zone = inject(NgZone); this._closed$ = new Subject(); this._elWithFocus = null; // element that is focused prior to modal opening this.backdrop = true; this.keyboard = true; this.dismissEvent = new EventEmitter(); this.shown = new Subject(); this.hidden = new Subject(); } get fullscreenClass() { return this.fullscreen === true ? ' modal-fullscreen' : isString(this.fullscreen) ? ` modal-fullscreen-${this.fullscreen}-down` : ''; } dismiss(reason) { this.dismissEvent.emit(reason); } ngOnInit() { this._elWithFocus = this._document.activeElement; this._zone.onStable .asObservable() .pipe(take(1)) .subscribe(() => { this._show(); }); } ngOnDestroy() { this._disableEventHandling(); } hide() { const { nativeElement } = this._elRef; const context = { animation: this.animation, runningTransition: 'stop' }; const windowTransition$ = ngbRunTransition(this._zone, nativeElement, () => nativeElement.classList.remove('show'), context); const dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => { }, context); const transitions$ = zip(windowTransition$, dialogTransition$); transitions$.subscribe(() => { this.hidden.next(); this.hidden.complete(); }); this._disableEventHandling(); this._restoreFocus(); return transitions$; } _show() { const context = { animation: this.animation, runningTransition: 'continue' }; const windowTransition$ = ngbRunTransition(this._zone, this._elRef.nativeElement, (element, animation) => { if (animation) { reflow(element); } element.classList.add('show'); }, context); const dialogTransition$ = ngbRunTransition(this._zone, this._dialogEl.nativeElement, () => { }, context); zip(windowTransition$, dialogTransition$).subscribe(() => { this.shown.next(); this.shown.complete(); }); this._enableEventHandling(); this._setFocus(); } _enableEventHandling() { const { nativeElement } = this._elRef; this._zone.runOutsideAngular(() => { fromEvent(nativeElement, 'keydown') .pipe(takeUntil(this._closed$), /* eslint-disable-next-line deprecation/deprecation */ filter((e) => e.which === Key.Escape)) .subscribe((event) => { if (this.keyboard) { requestAnimationFrame(() => { if (!event.defaultPrevented) { this._zone.run(() => this.dismiss(ModalDismissReasons.ESC)); } }); } else if (this.backdrop === 'static') { this._bumpBackdrop(); } }); // We're listening to 'mousedown' and 'mouseup' to prevent modal from closing when pressing the mouse // inside the modal dialog and releasing it outside let preventClose = false; fromEvent(this._dialogEl.nativeElement, 'mousedown') .pipe(takeUntil(this._closed$), tap(() => (preventClose = false)), switchMap(() => fromEvent(nativeElement, 'mouseup').pipe(takeUntil(this._closed$), take(1))), filter(({ target }) => nativeElement === target)) .subscribe(() => { preventClose = true; }); // We're listening to 'click' to dismiss modal on modal window click, except when: // 1. clicking on modal dialog itself // 2. closing was prevented by mousedown/up handlers // 3. clicking on scrollbar when the viewport is too small and modal doesn't fit (click is not triggered at all) fromEvent(nativeElement, 'click') .pipe(takeUntil(this._closed$)) .subscribe(({ target }) => { if (nativeElement === target) { if (this.backdrop === 'static') { this._bumpBackdrop(); } else if (this.backdrop === true && !preventClose) { this._zone.run(() => this.dismiss(ModalDismissReasons.BACKDROP_CLICK)); } } preventClose = false; }); }); } _disableEventHandling() { this._closed$.next(); } _setFocus() { const { nativeElement } = this._elRef; if (!nativeElement.contains(document.activeElement)) { const autoFocusable = nativeElement.querySelector(`[ngbAutofocus]`); const firstFocusable = getFocusableBoundaryElements(nativeElement)[0]; const elementToFocus = autoFocusable || firstFocusable || nativeElement; elementToFocus.focus(); } } _restoreFocus() { const body = this._document.body; const elWithFocus = this._elWithFocus; let elementToFocus; if (elWithFocus && elWithFocus['focus'] && body.contains(elWithFocus)) { elementToFocus = elWithFocus; } else { elementToFocus = body; } this._zone.runOutsideAngular(() => { setTimeout(() => elementToFocus.focus()); this._elWithFocus = null; }); } _bumpBackdrop() { if (this.backdrop === 'static') { ngbRunTransition(this._zone, this._elRef.nativeElement, ({ classList }) => { classList.add('modal-static'); return () => classList.remove('modal-static'); }, { animation: this.animation, runningTransition: 'continue' }); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbModalWindow, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0", type: NgbModalWindow, isStandalone: true, selector: "ngb-modal-window", inputs: { animation: "animation", ariaLabelledBy: "ariaLabelledBy", ariaDescribedBy: "ariaDescribedBy", backdrop: "backdrop", centered: "centered", fullscreen: "fullscreen", keyboard: "keyboard", scrollable: "scrollable", size: "size", windowClass: "windowClass", modalDialogClass: "modalDialogClass" }, outputs: { dismissEvent: "dismiss" }, host: { attributes: { "role": "dialog", "tabindex": "-1" }, properties: { "class": "\"modal d-block\" + (windowClass ? \" \" + windowClass : \"\")", "class.fade": "animation", "attr.aria-modal": "true", "attr.aria-labelledby": "ariaLabelledBy", "attr.aria-describedby": "ariaDescribedBy" } }, viewQueries: [{ propertyName: "_dialogEl", first: true, predicate: ["dialog"], descendants: true, static: true }], ngImport: i0, template: ` <div #dialog [class]=" 'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') + fullscreenClass + (scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '') " role="document" > <div class="modal-content"><ng-content /></div> </div> `, isInline: true, styles: ["ngb-modal-window .component-host-scrollable{display:flex;flex-direction:column;overflow:hidden}\n"], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: NgbModalWindow, decorators: [{ type: Component, args: [{ selector: 'ngb-modal-window', standalone: true, host: { '[class]': '"modal d-block" + (windowClass ? " " + windowClass : "")', '[class.fade]': 'animation', role: 'dialog', tabindex: '-1', '[attr.aria-modal]': 'true', '[attr.aria-labelledby]': 'ariaLabelledBy', '[attr.aria-describedby]': 'ariaDescribedBy', }, template: ` <div #dialog [class]=" 'modal-dialog' + (size ? ' modal-' + size : '') + (centered ? ' modal-dialog-centered' : '') + fullscreenClass + (scrollable ? ' modal-dialog-scrollable' : '') + (modalDialogClass ? ' ' + modalDialogClass : '') " role="document" > <div class="modal-content"><ng-content /></div> </div> `, encapsulation: ViewEncapsulation.None, styles: ["ngb-modal-window .component-host-scrollable{display:flex;flex-direction:column;overflow:hidden}\n"] }] }], propDecorators: { _dialogEl: [{ type: ViewChild, args: ['dialog', { static: true }] }], animation: [{ type: Input }], ariaLabelledBy: [{ type: Input }], ariaDescribedBy: [{ type: Input }], backdrop: [{ type: Input }], centered: [{ type: Input }], fullscreen: [{ type: Input }], keyboard: [{ type: Input }], scrollable: [{ type: Input }], size: [{ type: Input }], windowClass: [{ type: Input }], modalDialogClass: [{ type: Input }], dismissEvent: [{ type: Output, args: ['dismiss'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtd2luZG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL21vZGFsL21vZGFsLXdpbmRvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNOLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUdOLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEdBQ2pCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxTQUFTLEVBQWMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXpFLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGdCQUFnQixFQUF3QixNQUFNLGtDQUFrQyxDQUFDO0FBQzFGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sY0FBYyxDQUFDOztBQWlDaEQsTUFBTSxPQUFPLGNBQWM7SUEvQjNCO1FBZ0NTLGNBQVMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsV0FBTSxHQUFHLE1BQU0sQ0FBQyxDQUFBLFVBQXVCLENBQUEsQ0FBQyxDQUFDO1FBQ3pDLFVBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFdkIsYUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7UUFDL0IsaUJBQVksR0FBbUIsSUFBSSxDQUFDLENBQUMs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ZVQsaUJBQ2MsaUJBQWlCLENBQUMsSUFBSTs4QkFXVSxTQUFTO3NCQUF2RCxTQUFTO3VCQUFDLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRTVCLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRWEsWUFBWTtzQkFBOUIsTUFBTTt1QkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRFbGVtZW50UmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGluamVjdCxcblx0SW5wdXQsXG5cdE5nWm9uZSxcblx0T25EZXN0cm95LFxuXHRPbkluaXQsXG5cdE91dHB1dCxcblx0Vmlld0NoaWxkLFxuXHRWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IGZyb21FdmVudCwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgemlwIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIHN3aXRjaE1hcCwgdGFrZSwgdGFrZVVudGlsLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGdldEZvY3VzYWJsZUJvdW5kYXJ5RWxlbWVudHMgfSBmcm9tICcuLi91dGlsL2ZvY3VzLXRyYXAnO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSAnLi4vdXRpbC9rZXknO1xuaW1wb3J0IHsgTW9kYWxEaXNtaXNzUmVhc29ucyB9IGZyb20gJy4vbW9kYWwtZGlzbWlzcy1yZWFzb25zJztcbmltcG9ydCB7IG5nYlJ1blRyYW5zaXRpb24sIE5nYlRyYW5zaXRpb25PcHRpb25zIH0gZnJvbSAnLi4vdXRpbC90cmFuc2l0aW9uL25nYlRyYW5zaXRpb24nO1xuaW1wb3J0IHsgaXNTdHJpbmcsIHJlZmxvdyB9IGZyb20gJy4uL3V0aWwvdXRpbCc7XG5cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogJ25nYi1tb2RhbC13aW5kb3cnLFxuXHRzdGFuZGFsb25lOiB0cnVlLFxuXHRob3N0OiB7XG5cdFx0J1tjbGFzc10nOiAnXCJtb2RhbCBkLWJsb2NrXCIgKyAod2luZG93Q2xhc3MgPyBcIiBcIiArIHdpbmRvd0NsYXNzIDogXCJcIiknLFxuXHRcdCdbY2xhc3MuZmFkZV0nOiAnYW5pbWF0aW9uJyxcblx0XHRyb2xlOiAnZGlhbG9nJyxcblx0XHR0YWJpbmRleDogJy0xJyxcblx0XHQnW2F0dHIuYXJpYS1tb2RhbF0nOiAndHJ1ZScsXG5cdFx0J1thdHRyLmFyaWEtbGFiZWxsZWRieV0nOiAnYXJpYUxhYmVsbGVkQnknLFxuXHRcdCdbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XSc6ICdhcmlhRGVzY3JpYmVkQnknLFxuXHR9LFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxkaXZcblx0XHRcdCNkaWFsb2dcblx0XHRcdFtjbGFzc109XCJcblx0XHRcdFx0J21vZGFsLWRpYWxvZycgK1xuXHRcdFx0XHQoc2l6ZSA/ICcgbW9kYWwtJyArIHNpemUgOiAnJykgK1xuXHRcdFx0XHQoY2VudGVyZWQgPyAnIG1vZGFsLWRpYWxvZy1jZW50ZXJlZCcgOiAnJykgK1xuXHRcdFx0XHRmdWxsc2NyZWVuQ2xhc3MgK1xuXHRcdFx0XHQoc2Nyb2xsYWJsZSA/ICcgbW9kYWwtZGlhbG9nLXNjcm9sbGFibGUnIDogJycpICtcblx0XHRcdFx0KG1vZGFsRGlhbG9nQ2xhc3MgPyAnICcgKyBtb2RhbERpYWxvZ0NsYXNzIDogJycpXG5cdFx0XHRcIlxuXHRcdFx0cm9sZT1cImRvY3VtZW50XCJcblx0XHQ+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtY29udGVudFwiPjxuZy1jb250ZW50IC8+PC9kaXY+XG5cdFx0PC9kaXY+XG5cdGAsXG5cdGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG5cdHN0eWxlVXJsOiAnLi9tb2RhbC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgTmdiTW9kYWxXaW5kb3cgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG5cdHByaXZhdGUgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcblx0cHJpdmF0ZSBfZWxSZWYgPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pO1xuXHRwcml2YXRlIF96b25lID0gaW5qZWN0KE5nWm9uZSk7XG5cblx0cHJpdmF0ZSBfY2xvc2VkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cdHByaXZhdGUgX2VsV2l0aEZvY3VzOiBFbGVtZW50IHwgbnVsbCA9IG51bGw7IC8vIGVsZW1lbnQgdGhhdCBpcyBmb2N1c2VkIHByaW9yIHRvIG1vZGFsIG9wZW5pbmdcblxuXHRAVmlld0NoaWxkKCdkaWFsb2cnLCB7IHN0YXRpYzogdHJ1ZSB9KSBwcml2YXRlIF9kaWFsb2dFbDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG5cblx0QElucHV0KCkgYW5pbWF0aW9uOiBib29sZWFuO1xuXHRASW5wdXQoKSBhcmlhTGFiZWxsZWRCeTogc3RyaW5nO1xuXHRASW5wdXQoKSBhcmlhRGVzY3JpYmVkQnk6IHN0cmluZztcblx0QElucHV0KCkgYmFja2Ryb3A6IGJvb2xlYW4gfCBzdHJpbmcgPSB0cnVlO1xuXHRASW5wdXQoKSBjZW50ZXJlZDogc3RyaW5nO1xuXHRASW5wdXQoKSBmdWxsc2NyZWVuOiBzdHJpbmcgfCBib29sZWFuO1xuXHRASW5wdXQoKSBrZXlib2FyZCA9IHRydWU7XG5cdEBJbnB1dCgpIHNjcm9sbGFibGU6IHN0cmluZztcblx0QElucHV0KCkgc2l6ZTogc3RyaW5nO1xuXHRASW5wdXQoKSB3aW5kb3dDbGFzczogc3RyaW5nO1xuXHRASW5wdXQoKSBtb2RhbERpYWxvZ0NsYXNzOiBzdHJpbmc7XG5cblx0QE91dHB1dCgnZGlzbWlzcycpIGRpc21pc3NFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHRzaG93biA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cdGhpZGRlbiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cblx0Z2V0IGZ1bGxzY3JlZW5DbGFzcygpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLmZ1bGxzY3JlZW4gPT09IHRydWVcblx0XHRcdD8gJyBtb2RhbC1mdWxsc2NyZWVuJ1xuXHRcdFx0OiBpc1N0cmluZyh0aGlzLmZ1bGxzY3JlZW4pXG5cdFx0XHQgID8gYCBtb2RhbC1mdWxsc2NyZWVuLSR7dGhpcy5mdWxsc2NyZWVufS1kb3duYFxuXHRcdFx0ICA6ICcnO1xuXHR9XG5cblx0ZGlzbWlzcyhyZWFzb24pOiB2b2lkIHtcblx0XHR0aGlzLmRpc21pc3NFdmVudC5lbWl0KHJlYXNvbik7XG5cdH1cblxuXHRuZ09uSW5pdCgpIHtcblx0XHR0aGlzLl9lbFdpdGhGb2N1cyA9IHRoaXMuX2RvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cdFx0dGhpcy5fem9uZS5vblN0YWJsZVxuXHRcdFx0LmFzT2JzZXJ2YWJsZSgpXG5cdFx0XHQucGlwZSh0YWtlKDEpKVxuXHRcdFx0LnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdHRoaXMuX3Nob3coKTtcblx0XHRcdH0pO1xuXHR9XG5cblx0bmdPbkRlc3Ryb3koKSB7XG5cdFx0dGhpcy5fZGlzYWJsZUV2ZW50SGFuZGxpbmcoKTtcblx0fVxuXG5cdGhpZGUoKTogT2JzZXJ2YWJsZTxhbnk+IHtcblx0XHRjb25zdCB7IG5hdGl2ZUVsZW1lbnQgfSA9IHRoaXMuX2VsUmVmO1xuXHRcdGNvbnN0IGNvbnRleHQ6IE5nYlRyYW5zaXRpb25PcHRpb25zPGFueT4gPSB7IGFuaW1hdGlvbjogdGhpcy5hbmltYXRpb24sIHJ1bm5pbmdUcmFuc2l0aW9uOiAnc3RvcCcgfTtcblxuXHRcdGNvbnN0IHdpbmRvd1RyYW5zaXRpb24kID0gbmdiUnVuVHJhbnNpdGlvbihcblx0XHRcdHRoaXMuX3pvbmUsXG5cdFx0XHRuYXRpdmVFbGVtZW50LFxuXHRcdFx0KCkgPT4gbmF0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdzaG93JyksXG5cdFx0XHRjb250ZXh0LFxuXHRcdCk7XG5cdFx0Y29uc3QgZGlhbG9nVHJhbnNpdGlvbiQgPSBuZ2JSdW5UcmFuc2l0aW9uKHRoaXMuX3pvbmUsIHRoaXMuX2RpYWxvZ0VsLm5hdGl2ZUVsZW1lbnQsICgpID0+IHt9LCBjb250ZXh0KTtcblxuXHRcdGNvbnN0IHRyYW5zaXRpb25zJCA9IHppcCh3aW5kb3dUcmFuc2l0aW9uJCwgZGlhbG9nVHJhbnNpdGlvbiQpO1xuXHRcdHRyYW5zaXRpb25zJC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0dGhpcy5oaWRkZW4ubmV4dCgpO1xuXHRcdFx0dGhpcy5oaWRkZW4uY29tcGxldGUoKTtcblx0XHR9KTtcblxuXHRcdHRoaXMuX2Rpc2FibGVFdmVudEhhbmRsaW5nKCk7XG5cdFx0dGhpcy5fcmVzdG9yZUZvY3VzKCk7XG5cblx0XHRyZXR1cm4gdHJhbnNpdGlvbnMkO1xuXHR9XG5cblx0cHJpdmF0ZSBfc2hvdygpIHtcblx0XHRjb25zdCBjb250ZXh0OiBOZ2JUcmFuc2l0aW9uT3B0aW9uczxhbnk+ID0geyBhbmltYXRpb246IHRoaXMuYW5pbWF0aW9uLCBydW5uaW5nVHJhbnNpdGlvbjogJ2NvbnRpbnVlJyB9O1xuXG5cdFx0Y29uc3Qgd2luZG93VHJhbnNpdGlvbiQgPSBuZ2JSdW5UcmFuc2l0aW9uKFxuXHRcdFx0dGhpcy5fem9uZSxcblx0XHRcdHRoaXMuX2VsUmVmLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHQoZWxlbWVudDogSFRNTEVsZW1lbnQsIGFuaW1hdGlvbjogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRpZiAoYW5pbWF0aW9uKSB7XG5cdFx0XHRcdFx0cmVmbG93KGVsZW1lbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnc2hvdycpO1xuXHRcdFx0fSxcblx0XHRcdGNvbnRleHQsXG5cdFx0KTtcblx0XHRjb25zdCBkaWFsb2dUcmFuc2l0aW9uJCA9IG5nYlJ1blRyYW5zaXRpb24odGhpcy5fem9uZSwgdGhpcy5fZGlhbG9nRWwubmF0aXZlRWxlbWVudCwgKCkgPT4ge30sIGNvbnRleHQpO1xuXG5cdFx0emlwKHdpbmRvd1RyYW5zaXRpb24kLCBkaWFsb2dUcmFuc2l0aW9uJCkuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdHRoaXMuc2hvd24ubmV4dCgpO1xuXHRcdFx0dGhpcy5zaG93bi5jb21wbGV0ZSgpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5fZW5hYmxlRXZlbnRIYW5kbGluZygpO1xuXHRcdHRoaXMuX3NldEZvY3VzKCk7XG5cdH1cblxuXHRwcml2YXRlIF9lbmFibGVFdmVudEhhbmRsaW5nKCkge1xuXHRcdGNvbnN0IHsgbmF0aXZlRWxlbWVudCB9ID0gdGhpcy5fZWxSZWY7XG5cdFx0dGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG5cdFx0XHRmcm9tRXZlbnQ8S2V5Ym9hcmRFdmVudD4obmF0aXZlRWxlbWVudCwgJ2tleWRvd24nKVxuXHRcdFx0XHQucGlwZShcblx0XHRcdFx0XHR0YWtlVW50aWwodGhpcy5fY2xvc2VkJCksXG5cdFx0XHRcdFx0LyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uICovXG5cdFx0XHRcdFx0ZmlsdGVyKChlKSA9PiBlLndoaWNoID09PSBLZXkuRXNjYXBlKSxcblx0XHRcdFx0KVxuXHRcdFx0XHQuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuXHRcdFx0XHRcdGlmICh0aGlzLmtleWJvYXJkKSB7XG5cdFx0XHRcdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAoIWV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLl96b25lLnJ1bigoKSA9PiB0aGlzLmRpc21pc3MoTW9kYWxEaXNtaXNzUmVhc29ucy5FU0MpKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLmJhY2tkcm9wID09PSAnc3RhdGljJykge1xuXHRcdFx0XHRcdFx0dGhpcy5fYnVtcEJhY2tkcm9wKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0Ly8gV2UncmUgbGlzdGVuaW5nIHRvICdtb3VzZWRvd24nIGFuZCAnbW91c2V1cCcgdG8gcHJldmVudCBtb2RhbCBmcm9tIGNsb3Npbmcgd2hlbiBwcmVzc2luZyB0aGUgbW91c2Vcblx0XHRcdC8vIGluc2lkZSB0aGUgbW9kYWwgZGlhbG9nIGFuZCByZWxlYXNpbmcgaXQgb3V0c2lkZVxuXHRcdFx0bGV0IHByZXZlbnRDbG9zZSA9IGZhbHNlO1xuXHRcdFx0ZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KHRoaXMuX2RpYWxvZ0VsLm5hdGl2ZUVsZW1lbnQsICdtb3VzZWRvd24nKVxuXHRcdFx0XHQucGlwZShcblx0XHRcdFx0XHR0YWtlVW50aWwodGhpcy5fY2xvc2VkJCksXG5cdFx0XHRcdFx0dGFwKCgpID0+IChwcmV2ZW50Q2xvc2UgPSBmYWxzZSkpLFxuXHRcdFx0XHRcdHN3aXRjaE1hcCgoKSA9PiBmcm9tRXZlbnQ8TW91c2VFdmVudD4obmF0aXZlRWxlbWVudCwgJ21vdXNldXAnKS5waXBlKHRha2VVbnRpbCh0aGlzLl9jbG9zZWQkKSwgdGFrZSgxKSkpLFxuXHRcdFx0XHRcdGZpbHRlcigoeyB0YXJnZXQgfSkgPT4gbmF0aXZlRWxlbWVudCA9PT0gdGFyZ2V0KSxcblx0XHRcdFx0KVxuXHRcdFx0XHQuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdFx0XHRwcmV2ZW50Q2xvc2UgPSB0cnVlO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0Ly8gV2UncmUgbGlzdGVuaW5nIHRvICdjbGljaycgdG8gZGlzbWlzcyBtb2RhbCBvbiBtb2RhbCB3aW5kb3cgY2xpY2ssIGV4Y2VwdCB3aGVuOlxuXHRcdFx0Ly8gMS4gY2xpY2tpbmcgb24gbW9kYWwgZGlhbG9nIGl0c2VsZlxuXHRcdFx0Ly8gMi4gY2xvc2luZyB3YXMgcHJldmVudGVkIGJ5IG1vdXNlZG93bi91cCBoYW5kbGVyc1xuXHRcdFx0Ly8gMy4gY2xpY2tpbmcgb24gc2Nyb2xsYmFyIHdoZW4gdGhlIHZpZXdwb3J0IGlzIHRvbyBzbWFsbCBhbmQgbW9kYWwgZG9lc24ndCBmaXQgKGNsaWNrIGlzIG5vdCB0cmlnZ2VyZWQgYXQgYWxsKVxuXHRcdFx0ZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KG5hdGl2ZUVsZW1lbnQsICdjbGljaycpXG5cdFx0XHRcdC5waXBlKHRha2VVbnRpbCh0aGlzLl9jbG9zZWQkKSlcblx0XHRcdFx0LnN1YnNjcmliZSgoeyB0YXJnZXQgfSkgPT4ge1xuXHRcdFx0XHRcdGlmIChuYXRpdmVFbGVtZW50ID09PSB0YXJnZXQpIHtcblx0XHRcdFx0XHRcdGlmICh0aGlzLmJhY2tkcm9wID09PSAnc3RhdGljJykge1xuXHRcdFx0XHRcdFx0XHR0aGlzLl9idW1wQmFja2Ryb3AoKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5iYWNrZHJvcCA9PT0gdHJ1ZSAmJiAhcHJldmVudENsb3NlKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX3pvbmUucnVuKCgpID0+IHRoaXMuZGlzbWlzcyhNb2RhbERpc21pc3NSZWFzb25zLkJBQ0tEUk9QX0NMSUNLKSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cHJldmVudENsb3NlID0gZmFsc2U7XG5cdFx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfZGlzYWJsZUV2ZW50SGFuZGxpbmcoKSB7XG5cdFx0dGhpcy5fY2xvc2VkJC5uZXh0KCk7XG5cdH1cblxuXHRwcml2YXRlIF9zZXRGb2N1cygpIHtcblx0XHRjb25zdCB7IG5hdGl2ZUVsZW1lbnQgfSA9IHRoaXMuX2VsUmVmO1xuXHRcdGlmICghbmF0aXZlRWxlbWVudC5jb250YWlucyhkb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuXHRcdFx0Y29uc3QgYXV0b0ZvY3VzYWJsZSA9IG5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihgW25nYkF1dG9mb2N1c11gKSBhcyBIVE1MRWxlbWVudDtcblx0XHRcdGNvbnN0IGZpcnN0Rm9jdXNhYmxlID0gZ2V0Rm9jdXNhYmxlQm91bmRhcnlFbGVtZW50cyhuYXRpdmVFbGVtZW50KVswXTtcblxuXHRcdFx0Y29uc3QgZWxlbWVudFRvRm9jdXMgPSBhdXRvRm9jdXNhYmxlIHx8IGZpcnN0Rm9jdXNhYmxlIHx8IG5hdGl2ZUVsZW1lbnQ7XG5cdFx0XHRlbGVtZW50VG9Gb2N1cy5mb2N1cygpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgX3Jlc3RvcmVGb2N1cygpIHtcblx0XHRjb25zdCBib2R5ID0gdGhpcy5fZG9jdW1lbnQuYm9keTtcblx0XHRjb25zdCBlbFdpdGhGb2N1cyA9IHRoaXMuX2VsV2l0aEZvY3VzO1xuXG5cdFx0bGV0IGVsZW1lbnRUb0ZvY3VzO1xuXHRcdGlmIChlbFdpdGhGb2N1cyAmJiBlbFdpdGhGb2N1c1snZm9jdXMnXSAmJiBib2R5LmNvbnRhaW5zKGVsV2l0aEZvY3VzKSkge1xuXHRcdFx0ZWxlbWVudFRvRm9jdXMgPSBlbFdpdGhGb2N1cztcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZWxlbWVudFRvRm9jdXMgPSBib2R5O1xuXHRcdH1cblx0XHR0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4gZWxlbWVudFRvRm9jdXMuZm9jdXMoKSk7XG5cdFx0XHR0aGlzLl9lbFdpdGhGb2N1cyA9IG51bGw7XG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIF9idW1wQmFja2Ryb3AoKSB7XG5cdFx0aWYgKHRoaXMuYmFja2Ryb3AgPT09ICdzdGF0aWMnKSB7XG5cdFx0XHRuZ2JSdW5UcmFuc2l0aW9uKFxuXHRcdFx0XHR0aGlzLl96b25lLFxuXHRcdFx0XHR0aGlzLl9lbFJlZi5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XHQoeyBjbGFzc0xpc3QgfSkgPT4ge1xuXHRcdFx0XHRcdGNsYXNzTGlzdC5hZGQoJ21vZGFsLXN0YXRpYycpO1xuXHRcdFx0XHRcdHJldHVybiAoKSA9PiBjbGFzc0xpc3QucmVtb3ZlKCdtb2RhbC1zdGF0aWMnKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0eyBhbmltYXRpb246IHRoaXMuYW5pbWF0aW9uLCBydW5uaW5nVHJhbnNpdGlvbjogJ2NvbnRpbnVlJyB9LFxuXHRcdFx0KTtcblx0XHR9XG5cdH1cbn1cbiJdfQ==