@doku-dev/doku-fragment
Version:
A new Angular UI library that moving away from Bootstrap and built from scratch.
185 lines • 32 kB
JavaScript
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input, Optional, Self, ViewEncapsulation, } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BehaviorSubject, ReplaySubject, combineLatest, distinctUntilChanged, takeUntil, map, delay, of, switchMap, } from 'rxjs';
import { DOKU_FORM_FIELD_ACCESSOR, } from '../form-field';
import { DokuSpinner } from '../spinner';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common";
export class DokuInputFileUpload {
/**
* Whether input file upload should be on disabled state. The default is `false`.
*/
get disabled() {
return this._disabled;
}
set disabled(val) {
this._disabled = val;
setTimeout(() => {
this.onDisable?.(this._disabled);
}, 0);
}
/**
* Whether input file upload should be on loading state. The default is `false`.
*/
get loading() {
return this._loading;
}
set loading(val) {
this._loading = val != null && `${val}` !== 'false';
}
constructor(cdr, ngControl) {
this.cdr = cdr;
this.ngControl = ngControl;
this.value = undefined;
this.fieldOptions = { withoutInputStyle: true };
this.loadingChanges$ = new BehaviorSubject(false);
this.destroy$ = new ReplaySubject();
/**
* Text that is shown as an input title.
*/
this.title = 'Upload File';
/**
* Text that is shown as an input subtitle.
*/
this.subtitle = 'Tap here to upload file';
/**
* Text that is shown in loading state.
*/
this.loadingText = 'loading...';
/**
* Comma-separated list of one or more file types, or unique file type specifiers,
* describing which file types to allow. The default is "*".
*/
this.accept = '*';
this._disabled = false;
this._loading = false;
if (this.ngControl) {
this.ngControl.valueAccessor = this;
}
}
ngAfterViewInit() {
this._listenNgControlStatus();
}
onFileSelected(e) {
const files = e.target.files;
if (!files)
return;
const file = files[0];
if (this._checkFileIsImage(file)) {
this._showImagePreview(file);
}
this.title = file.name;
this.subtitle = 'Tap here to change file';
this.value = file;
this.onChange?.(file);
}
ngOnChanges(changes) {
if (changes['loading']?.currentValue !== changes['loading']?.previousValue) {
this.loadingChanges$.next(changes['loading']?.currentValue);
}
if (changes['disabled']?.previousValue !== changes['disabled']?.currentValue) {
this.onDisable?.(!!this.disabled);
}
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.cdr.detectChanges();
}
/**
* Listen and assign NgControl status to `doku-form-field`
* to complete behavior and functionality of the field
* (hint, error, success message, and styling).
*/
_listenNgControlStatus() {
combineLatest([
this.loadingChanges$,
of(true).pipe(switchMap(() => this.ngControl?.statusChanges || of(null)), map((status) => ({
status: status,
state: {
pristine: this.ngControl?.control?.pristine,
untouched: this.ngControl?.control?.untouched,
},
})), delay(0), distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr))),
])
?.pipe(distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)), takeUntil(this.destroy$))
.subscribe(([loading, statusObj]) => {
if (!this.value)
return;
const status = statusObj?.status;
const state = statusObj?.state;
if (status === 'VALID' && !loading) {
this.onValidate?.('valid', state);
}
else if (status === 'INVALID' && !loading) {
this.onValidate?.('invalid', state);
}
else {
this.onValidate?.(undefined, state);
}
});
}
_showImagePreview(file) {
if (file instanceof File) {
this.imagePreviewSrc = URL.createObjectURL(file);
return;
}
this.imagePreviewSrc = file;
}
_checkFileIsImage(file) {
if (file instanceof File) {
return file.type.startsWith('image/');
}
return false;
}
_checkStringIsImage(str) {
return /\.(jpg|jpeg|png|webp|avif|gif|svg)(\??.*)$/.test(str);
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.complete();
}
writeValue(value) {
if ((typeof value === 'string' && this._checkStringIsImage(value)) ||
(value instanceof File && this._checkFileIsImage(value))) {
this._showImagePreview(value);
}
this.value = value;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
registerOnDisable(fn) {
this.onDisable = fn;
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnValidate(fn) {
this.onValidate = fn;
}
}
DokuInputFileUpload.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DokuInputFileUpload, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
DokuInputFileUpload.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: DokuInputFileUpload, isStandalone: true, selector: "doku-input-file-upload", inputs: { title: "title", subtitle: "subtitle", loadingText: "loadingText", accept: "accept", disabled: "disabled", loading: "loading" }, providers: [{ provide: DOKU_FORM_FIELD_ACCESSOR, useExisting: DokuInputFileUpload }], exportAs: ["dokuInputFileUpload"], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"d-input-file-container\"\n [class.d-input-file-loading]=\"loading\"\n (click)=\"!loading && inputFileDefault.click()\"\n>\n <div class=\"d-input-file-preview\">\n <img *ngIf=\"imagePreviewSrc\" [src]=\"imagePreviewSrc\" />\n <ng-container *ngIf=\"!imagePreviewSrc && value\" [ngTemplateOutlet]=\"iconDocs\"></ng-container>\n <ng-container *ngIf=\"!imagePreviewSrc && !value\" [ngTemplateOutlet]=\"iconPlus\"></ng-container>\n </div>\n <div class=\"d-input-file-wrapper\">\n <div class=\"d-input-file-desc\">\n <span class=\"d-input-file-name\">{{ title }}</span>\n <span class=\"d-input-file-status\">{{ loading ? loadingText : subtitle }}</span>\n </div>\n <doku-spinner *ngIf=\"loading\" [diameter]=\"16\" [strokeWidth]=\"1\"></doku-spinner>\n </div>\n</div>\n<input\n #inputFileDefault\n type=\"file\"\n class=\"d-input-file-default\"\n (change)=\"onFileSelected($event)\"\n [disabled]=\"disabled\"\n [accept]=\"accept\"\n/>\n\n<ng-template #iconPlus>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.92849 6.57147V7.07147H9.42849H13.7142C13.964 7.07147 14.1666 7.2741 14.1666 7.52385V8.47623C14.1666 8.72598 13.964 8.92861 13.7142 8.92861H9.42849H8.92849V9.42861V13.7143C8.92849 13.9641 8.72586 14.1667 8.47611 14.1667H7.52373C7.27398 14.1667 7.07135 13.9641 7.07135 13.7143V9.42861V8.92861H6.57135H2.28563C2.03588 8.92861 1.83325 8.72598 1.83325 8.47623V7.52385C1.83325 7.2741 2.03588 7.07147 2.28563 7.07147H6.57135H7.07135V6.57147V2.28576C7.07135 2.036 7.27398 1.83337 7.52373 1.83337H8.47611C8.72586 1.83337 8.92849 2.036 8.92849 2.28576V6.57147Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n />\n </svg>\n</ng-template>\n\n<ng-template #iconDocs>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.83333 4.87498V1.33331H3.625C3.27865 1.33331 3 1.61196 3 1.95831V14.0416C3 14.388 3.27865 14.6666 3.625 14.6666H12.375C12.7214 14.6666 13 14.388 13 14.0416V5.49998H9.45833C9.11458 5.49998 8.83333 5.21873 8.83333 4.87498ZM13 4.50779V4.66665H9.66667V1.33331H9.82552C9.99219 1.33331 10.151 1.39842 10.2682 1.5156L12.8177 4.06769C12.9349 4.18488 13 4.34373 13 4.50779Z\"\n fill=\"currentColor\"\n />\n </svg>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: DokuSpinner, selector: "doku-spinner", inputs: ["size", "diameter", "strokeWidth"], exportAs: ["dokuSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DokuInputFileUpload, decorators: [{
type: Component,
args: [{ selector: 'doku-input-file-upload', exportAs: 'dokuInputFileUpload', standalone: true, imports: [CommonModule, FormsModule, DokuSpinner], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: DOKU_FORM_FIELD_ACCESSOR, useExisting: DokuInputFileUpload }], template: "<div\n class=\"d-input-file-container\"\n [class.d-input-file-loading]=\"loading\"\n (click)=\"!loading && inputFileDefault.click()\"\n>\n <div class=\"d-input-file-preview\">\n <img *ngIf=\"imagePreviewSrc\" [src]=\"imagePreviewSrc\" />\n <ng-container *ngIf=\"!imagePreviewSrc && value\" [ngTemplateOutlet]=\"iconDocs\"></ng-container>\n <ng-container *ngIf=\"!imagePreviewSrc && !value\" [ngTemplateOutlet]=\"iconPlus\"></ng-container>\n </div>\n <div class=\"d-input-file-wrapper\">\n <div class=\"d-input-file-desc\">\n <span class=\"d-input-file-name\">{{ title }}</span>\n <span class=\"d-input-file-status\">{{ loading ? loadingText : subtitle }}</span>\n </div>\n <doku-spinner *ngIf=\"loading\" [diameter]=\"16\" [strokeWidth]=\"1\"></doku-spinner>\n </div>\n</div>\n<input\n #inputFileDefault\n type=\"file\"\n class=\"d-input-file-default\"\n (change)=\"onFileSelected($event)\"\n [disabled]=\"disabled\"\n [accept]=\"accept\"\n/>\n\n<ng-template #iconPlus>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.92849 6.57147V7.07147H9.42849H13.7142C13.964 7.07147 14.1666 7.2741 14.1666 7.52385V8.47623C14.1666 8.72598 13.964 8.92861 13.7142 8.92861H9.42849H8.92849V9.42861V13.7143C8.92849 13.9641 8.72586 14.1667 8.47611 14.1667H7.52373C7.27398 14.1667 7.07135 13.9641 7.07135 13.7143V9.42861V8.92861H6.57135H2.28563C2.03588 8.92861 1.83325 8.72598 1.83325 8.47623V7.52385C1.83325 7.2741 2.03588 7.07147 2.28563 7.07147H6.57135H7.07135V6.57147V2.28576C7.07135 2.036 7.27398 1.83337 7.52373 1.83337H8.47611C8.72586 1.83337 8.92849 2.036 8.92849 2.28576V6.57147Z\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n />\n </svg>\n</ng-template>\n\n<ng-template #iconDocs>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.83333 4.87498V1.33331H3.625C3.27865 1.33331 3 1.61196 3 1.95831V14.0416C3 14.388 3.27865 14.6666 3.625 14.6666H12.375C12.7214 14.6666 13 14.388 13 14.0416V5.49998H9.45833C9.11458 5.49998 8.83333 5.21873 8.83333 4.87498ZM13 4.50779V4.66665H9.66667V1.33331H9.82552C9.99219 1.33331 10.151 1.39842 10.2682 1.5156L12.8177 4.06769C12.9349 4.18488 13 4.34373 13 4.50779Z\"\n fill=\"currentColor\"\n />\n </svg>\n</ng-template>\n" }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.NgControl, decorators: [{
type: Optional
}, {
type: Self
}] }]; }, propDecorators: { title: [{
type: Input
}], subtitle: [{
type: Input
}], loadingText: [{
type: Input
}], accept: [{
type: Input
}], disabled: [{
type: Input
}], loading: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtZmlsZS11cGxvYWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9rdS1mcmFnbWVudC9zcmMvbGliL2lucHV0LWZpbGUtdXBsb2FkL2lucHV0LWZpbGUtdXBsb2FkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rva3UtZnJhZ21lbnQvc3JjL2xpYi9pbnB1dC1maWxlLXVwbG9hZC9pbnB1dC1maWxlLXVwbG9hZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUVMLHVCQUF1QixFQUV2QixTQUFTLEVBQ1QsS0FBSyxFQUdMLFFBQVEsRUFDUixJQUFJLEVBRUosaUJBQWlCLEdBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsV0FBVyxFQUFhLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUUsT0FBTyxFQUNMLGVBQWUsRUFDZixhQUFhLEVBQ2IsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixTQUFTLEVBQ1QsR0FBRyxFQUNILEtBQUssRUFDTCxFQUFFLEVBQ0YsU0FBUyxHQUNWLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUNMLHdCQUF3QixHQUt6QixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sWUFBWSxDQUFDOzs7O0FBWXpDLE1BQU0sT0FBTyxtQkFBbUI7SUFzQzlCOztPQUVHO0lBQ0gsSUFDSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFDRCxJQUFJLFFBQVEsQ0FBQyxHQUFZO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDO1FBRXJCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsU0FBUyxF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QURYLEtBQUs7Z0JBaUJGLE9BQU87c0JBRFYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgU2VsZixcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEZvcm1zTW9kdWxlLCBOZ0NvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICBCZWhhdmlvclN1YmplY3QsXG4gIFJlcGxheVN1YmplY3QsXG4gIGNvbWJpbmVMYXRlc3QsXG4gIGRpc3RpbmN0VW50aWxDaGFuZ2VkLFxuICB0YWtlVW50aWwsXG4gIG1hcCxcbiAgZGVsYXksXG4gIG9mLFxuICBzd2l0Y2hNYXAsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgRE9LVV9GT1JNX0ZJRUxEX0FDQ0VTU09SLFxuICBEb2t1Rm9ybUZpZWxkQWNjZXNzb3IsXG4gIERva3VGb3JtRmllbGRBY2Nlc3NvclZhbGlkYXRlU3RhdGUsXG4gIERva3VGb3JtRmllbGRBY2Nlc3NvclZhbGlkYXRlVmFsdWUsXG4gIERva3VGb3JtRmllbGRPcHRpb25zLFxufSBmcm9tICcuLi9mb3JtLWZpZWxkJztcbmltcG9ydCB7IERva3VTcGlubmVyIH0gZnJvbSAnLi4vc3Bpbm5lcic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Rva3UtaW5wdXQtZmlsZS11cGxvYWQnLFxuICBleHBvcnRBczogJ2Rva3VJbnB1dEZpbGVVcGxvYWQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgRG9rdVNwaW5uZXJdLFxuICB0ZW1wbGF0ZVVybDogJy4vaW5wdXQtZmlsZS11cGxvYWQuY29tcG9uZW50Lmh0bWwnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgcHJvdmlkZXJzOiBbeyBwcm92aWRlOiBET0tVX0ZPUk1fRklFTERfQUNDRVNTT1IsIHVzZUV4aXN0aW5nOiBEb2t1SW5wdXRGaWxlVXBsb2FkIH1dLFxufSlcbmV4cG9ydCBjbGFzcyBEb2t1SW5wdXRGaWxlVXBsb2FkXG4gIGltcGxlbWVudHMgRG9rdUZvcm1GaWVsZEFjY2Vzc29yLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3lcbntcbiAgb25DaGFuZ2U/OiAodmFsdWU6IEZpbGUpID0+IHZvaWQ7XG4gIG9uVG91Y2hlZD86ICgpID0+IHZvaWQ7XG4gIG9uRGlzYWJsZT86ICh2YWx1ZTogYm9vbGVhbikgPT4gdm9pZDtcbiAgb25WYWxpZGF0ZT86IChcbiAgICB2YWx1ZT86IERva3VGb3JtRmllbGRBY2Nlc3NvclZhbGlkYXRlVmFsdWUsXG4gICAgc3RhdGU/OiBEb2t1Rm9ybUZpZWxkQWNjZXNzb3JWYWxpZGF0ZVN0YXRlXG4gICkgPT4gdm9pZDtcblxuICB2YWx1ZT86IEZpbGUgfCBzdHJpbmcgPSB1bmRlZmluZWQ7XG4gIGZpZWxkT3B0aW9ucz86IERva3VGb3JtRmllbGRPcHRpb25zID0geyB3aXRob3V0SW5wdXRTdHlsZTogdHJ1ZSB9O1xuICBwcml2YXRlIGxvYWRpbmdDaGFuZ2VzJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoZmFsc2UpO1xuICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFJlcGxheVN1YmplY3QoKTtcbiAgcHJvdGVjdGVkIGltYWdlUHJldmlld1NyYz86IHN0cmluZztcblxuICAvKipcbiAgICogVGV4dCB0aGF0IGlzIHNob3duIGFzIGFuIGlucHV0IHRpdGxlLlxuICAgKi9cbiAgQElucHV0KCkgdGl0bGUgPSAnVXBsb2FkIEZpbGUnO1xuXG4gIC8qKlxuICAgKiBUZXh0IHRoYXQgaXMgc2hvd24gYXMgYW4gaW5wdXQgc3VidGl0bGUuXG4gICAqL1xuICBASW5wdXQoKSBzdWJ0aXRsZSA9ICdUYXAgaGVyZSB0byB1cGxvYWQgZmlsZSc7XG5cbiAgLyoqXG4gICAqIFRleHQgdGhhdCBpcyBzaG93biBpbiBsb2FkaW5nIHN0YXRlLlxuICAgKi9cbiAgQElucHV0KCkgbG9hZGluZ1RleHQgPSAnbG9hZGluZy4uLic7XG5cbiAgLyoqXG4gICAqIENvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIG9uZSBvciBtb3JlIGZpbGUgdHlwZXMsIG9yIHVuaXF1ZSBmaWxlIHR5cGUgc3BlY2lmaWVycyxcbiAgICogZGVzY3JpYmluZyB3aGljaCBmaWxlIHR5cGVzIHRvIGFsbG93LiBUaGUgZGVmYXVsdCBpcyBcIipcIi5cbiAgICovXG4gIEBJbnB1dCgpIGFjY2VwdCA9ICcqJztcblxuICAvKipcbiAgICogV2hldGhlciBpbnB1dCBmaWxlIHVwbG9hZCBzaG91bGQgYmUgb24gZGlzYWJsZWQgc3RhdGUuIFRoZSBkZWZhdWx0IGlzIGBmYWxzZWAuXG4gICAqL1xuICBASW5wdXQoKVxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVkO1xuICB9XG4gIHNldCBkaXNhYmxlZCh2YWw6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IHZhbDtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5vbkRpc2FibGU/Lih0aGlzLl9kaXNhYmxlZCk7XG4gICAgfSwgMCk7XG4gIH1cbiAgcHJpdmF0ZSBfZGlzYWJsZWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogV2hldGhlciBpbnB1dCBmaWxlIHVwbG9hZCBzaG91bGQgYmUgb24gbG9hZGluZyBzdGF0ZS4gVGhlIGRlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGdldCBsb2FkaW5nKCkge1xuICAgIHJldHVybiB0aGlzLl9sb2FkaW5nO1xuICB9XG4gIHNldCBsb2FkaW5nKHZhbDogdW5rbm93bikge1xuICAgIHRoaXMuX2xvYWRpbmcgPSB2YWwgIT0gbnVsbCAmJiBgJHt2YWx9YCAhPT0gJ2ZhbHNlJztcbiAgfVxuICBwcml2YXRlIF9sb2FkaW5nID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLCBAT3B0aW9uYWwoKSBAU2VsZigpIHByaXZhdGUgbmdDb250cm9sPzogTmdDb250cm9sKSB7XG4gICAgaWYgKHRoaXMubmdDb250cm9sKSB7XG4gICAgICB0aGlzLm5nQ29udHJvbC52YWx1ZUFjY2Vzc29yID0gdGhpcztcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5fbGlzdGVuTmdDb250cm9sU3RhdHVzKCk7XG4gIH1cblxuICBvbkZpbGVTZWxlY3RlZChlOiBFdmVudCkge1xuICAgIGNvbnN0IGZpbGVzID0gKGUudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLmZpbGVzO1xuXG4gICAgaWYgKCFmaWxlcykgcmV0dXJuO1xuXG4gICAgY29uc3QgZmlsZSA9IGZpbGVzWzBdO1xuXG4gICAgaWYgKHRoaXMuX2NoZWNrRmlsZUlzSW1hZ2UoZmlsZSkpIHtcbiAgICAgIHRoaXMuX3Nob3dJbWFnZVByZXZpZXcoZmlsZSk7XG4gICAgfVxuXG4gICAgdGhpcy50aXRsZSA9IGZpbGUubmFtZTtcbiAgICB0aGlzLnN1YnRpdGxlID0gJ1RhcCBoZXJlIHRvIGNoYW5nZSBmaWxlJztcbiAgICB0aGlzLnZhbHVlID0gZmlsZTtcbiAgICB0aGlzLm9uQ2hhbmdlPy4oZmlsZSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXNbJ2xvYWRpbmcnXT8uY3VycmVudFZhbHVlICE9PSBjaGFuZ2VzWydsb2FkaW5nJ10/LnByZXZpb3VzVmFsdWUpIHtcbiAgICAgIHRoaXMubG9hZGluZ0NoYW5nZXMkLm5leHQoY2hhbmdlc1snbG9hZGluZyddPy5jdXJyZW50VmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VzWydkaXNhYmxlZCddPy5wcmV2aW91c1ZhbHVlICE9PSBjaGFuZ2VzWydkaXNhYmxlZCddPy5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMub25EaXNhYmxlPy4oISF0aGlzLmRpc2FibGVkKTtcbiAgICB9XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlPyhpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG5cbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuIGFuZCBhc3NpZ24gTmdDb250cm9sIHN0YXR1cyB0byBgZG9rdS1mb3JtLWZpZWxkYFxuICAgKiB0byBjb21wbGV0ZSBiZWhhdmlvciBhbmQgZnVuY3Rpb25hbGl0eSBvZiB0aGUgZmllbGRcbiAgICogKGhpbnQsIGVycm9yLCBzdWNjZXNzIG1lc3NhZ2UsIGFuZCBzdHlsaW5nKS5cbiAgICovXG4gIHByaXZhdGUgX2xpc3Rlbk5nQ29udHJvbFN0YXR1cygpIHtcbiAgICBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMubG9hZGluZ0NoYW5nZXMkLFxuICAgICAgb2YodHJ1ZSkucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMubmdDb250cm9sPy5zdGF0dXNDaGFuZ2VzIHx8IG9mKG51bGwpKSxcbiAgICAgICAgbWFwKChzdGF0dXMpID0+ICh7XG4gICAgICAgICAgc3RhdHVzOiBzdGF0dXMsXG4gICAgICAgICAgc3RhdGU6IHtcbiAgICAgICAgICAgIHByaXN0aW5lOiB0aGlzLm5nQ29udHJvbD8uY29udHJvbD8ucHJpc3RpbmUsXG4gICAgICAgICAgICB1bnRvdWNoZWQ6IHRoaXMubmdDb250cm9sPy5jb250cm9sPy51bnRvdWNoZWQsXG4gICAgICAgICAgfSBhcyBEb2t1Rm9ybUZpZWxkQWNjZXNzb3JWYWxpZGF0ZVN0YXRlLFxuICAgICAgICB9KSksXG4gICAgICAgIGRlbGF5KDApLFxuICAgICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgocHJldiwgY3VycikgPT4gSlNPTi5zdHJpbmdpZnkocHJldikgPT09IEpTT04uc3RyaW5naWZ5KGN1cnIpKVxuICAgICAgKSxcbiAgICBdKVxuICAgICAgPy5waXBlKFxuICAgICAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgocHJldiwgY3VycikgPT4gSlNPTi5zdHJpbmdpZnkocHJldikgPT09IEpTT04uc3RyaW5naWZ5KGN1cnIpKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChbbG9hZGluZywgc3RhdHVzT2JqXSkgPT4ge1xuICAgICAgICBpZiAoIXRoaXMudmFsdWUpIHJldHVybjtcblxuICAgICAgICBjb25zdCBzdGF0dXMgPSBzdGF0dXNPYmo/LnN0YXR1cztcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBzdGF0dXNPYmo/LnN0YXRlO1xuICAgICAgICBpZiAoc3RhdHVzID09PSAnVkFMSUQnICYmICFsb2FkaW5nKSB7XG4gICAgICAgICAgdGhpcy5vblZhbGlkYXRlPy4oJ3ZhbGlkJywgc3RhdGUpO1xuICAgICAgICB9IGVsc2UgaWYgKHN0YXR1cyA9PT0gJ0lOVkFMSUQnICYmICFsb2FkaW5nKSB7XG4gICAgICAgICAgdGhpcy5vblZhbGlkYXRlPy4oJ2ludmFsaWQnLCBzdGF0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5vblZhbGlkYXRlPy4odW5kZWZpbmVkLCBzdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2hvd0ltYWdlUHJldmlldyhmaWxlOiBGaWxlIHwgc3RyaW5nKSB7XG4gICAgaWYgKGZpbGUgaW5zdGFuY2VvZiBGaWxlKSB7XG4gICAgICB0aGlzLmltYWdlUHJldmlld1NyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmltYWdlUHJldmlld1NyYyA9IGZpbGU7XG4gIH1cblxuICBwcml2YXRlIF9jaGVja0ZpbGVJc0ltYWdlKGZpbGU6IEZpbGUpOiBib29sZWFuIHtcbiAgICBpZiAoZmlsZSBpbnN0YW5jZW9mIEZpbGUpIHtcbiAgICAgIHJldHVybiBmaWxlLnR5cGUuc3RhcnRzV2l0aCgnaW1hZ2UvJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tTdHJpbmdJc0ltYWdlKHN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIC9cXC4oanBnfGpwZWd8cG5nfHdlYnB8YXZpZnxnaWZ8c3ZnKShcXD8/LiopJC8udGVzdChzdHIpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWU6IEZpbGUgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB0aGlzLl9jaGVja1N0cmluZ0lzSW1hZ2UodmFsdWUpKSB8fFxuICAgICAgKHZhbHVlIGluc3RhbmNlb2YgRmlsZSAmJiB0aGlzLl9jaGVja0ZpbGVJc0ltYWdlKHZhbHVlKSlcbiAgICApIHtcbiAgICAgIHRoaXMuX3Nob3dJbWFnZVByZXZpZXcodmFsdWUpO1xuICAgIH1cblxuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25EaXNhYmxlKGZuOiAodmFsdWU6IGJvb2xlYW4pID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uRGlzYWJsZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBGaWxlKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblZhbGlkYXRlKGZuOiAodmFsdWU/OiBEb2t1Rm9ybUZpZWxkQWNjZXNzb3JWYWxpZGF0ZVZhbHVlKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vblZhbGlkYXRlID0gZm47XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJkLWlucHV0LWZpbGUtY29udGFpbmVyXCJcbiAgW2NsYXNzLmQtaW5wdXQtZmlsZS1sb2FkaW5nXT1cImxvYWRpbmdcIlxuICAoY2xpY2spPVwiIWxvYWRpbmcgJiYgaW5wdXRGaWxlRGVmYXVsdC5jbGljaygpXCJcbj5cbiAgPGRpdiBjbGFzcz1cImQtaW5wdXQtZmlsZS1wcmV2aWV3XCI+XG4gICAgPGltZyAqbmdJZj1cImltYWdlUHJldmlld1NyY1wiIFtzcmNdPVwiaW1hZ2VQcmV2aWV3U3JjXCIgLz5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWltYWdlUHJldmlld1NyYyAmJiB2YWx1ZVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImljb25Eb2NzXCI+PC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpbWFnZVByZXZpZXdTcmMgJiYgIXZhbHVlXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaWNvblBsdXNcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJkLWlucHV0LWZpbGUtd3JhcHBlclwiPlxuICAgIDxkaXYgY2xhc3M9XCJkLWlucHV0LWZpbGUtZGVzY1wiPlxuICAgICAgPHNwYW4gY2xhc3M9XCJkLWlucHV0LWZpbGUtbmFtZVwiPnt7IHRpdGxlIH19PC9zcGFuPlxuICAgICAgPHNwYW4gY2xhc3M9XCJkLWlucHV0LWZpbGUtc3RhdHVzXCI+e3sgbG9hZGluZyA/IGxvYWRpbmdUZXh0IDogc3VidGl0bGUgfX08L3NwYW4+XG4gICAgPC9kaXY+XG4gICAgPGRva3Utc3Bpbm5lciAqbmdJZj1cImxvYWRpbmdcIiBbZGlhbWV0ZXJdPVwiMTZcIiBbc3Ryb2tlV2lkdGhdPVwiMVwiPjwvZG9rdS1zcGlubmVyPlxuICA8L2Rpdj5cbjwvZGl2PlxuPGlucHV0XG4gICNpbnB1dEZpbGVEZWZhdWx0XG4gIHR5cGU9XCJmaWxlXCJcbiAgY2xhc3M9XCJkLWlucHV0LWZpbGUtZGVmYXVsdFwiXG4gIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiXG4gIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gIFthY2NlcHRdPVwiYWNjZXB0XCJcbi8+XG5cbjxuZy10ZW1wbGF0ZSAjaWNvblBsdXM+XG4gIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAxNiAxNlwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiPlxuICAgIDxwYXRoXG4gICAgICBkPVwiTTguOTI4NDkgNi41NzE0N1Y3LjA3MTQ3SDkuNDI4NDlIMTMuNzE0MkMxMy45NjQgNy4wNzE0NyAxNC4xNjY2IDcuMjc0MSAxNC4xNjY2IDcuNTIzODVWOC40NzYyM0MxNC4xNjY2IDguNzI1OTggMTMuOTY0IDguOTI4NjEgMTMuNzE0MiA4LjkyODYxSDkuNDI4NDlIOC45Mjg0OVY5LjQyODYxVjEzLjcxNDNDOC45Mjg0OSAxMy45NjQxIDguNzI1ODYgMTQuMTY2NyA4LjQ3NjExIDE0LjE2NjdINy41MjM3M0M3LjI3Mzk4IDE0LjE2NjcgNy4wNzEzNSAxMy45NjQxIDcuMDcxMzUgMTMuNzE0M1Y5LjQyODYxVjguOTI4NjFINi41NzEzNUgyLjI4NTYzQzIuMDM1ODggOC45Mjg2MSAxLjgzMzI1IDguNzI1OTggMS44MzMyNSA4LjQ3NjIzVjcuNTIzODVDMS44MzMyNSA3LjI3NDEgMi4wMzU4OCA3LjA3MTQ3IDIuMjg1NjMgNy4wNzE0N0g2LjU3MTM1SDcuMDcxMzVWNi41NzE0N1YyLjI4NTc2QzcuMDcxMzUgMi4wMzYgNy4yNzM5OCAxLjgzMzM3IDcuNTIzNzMgMS44MzMzN0g4LjQ3NjExQzguNzI1ODYgMS44MzMzNyA4LjkyODQ5IDIuMDM2IDguOTI4NDkgMi4yODU3NlY2LjU3MTQ3WlwiXG4gICAgICBmaWxsPVwiY3VycmVudENvbG9yXCJcbiAgICAgIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG4gICAgLz5cbiAgPC9zdmc+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2ljb25Eb2NzPlxuICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIHZpZXdCb3g9XCIwIDAgMTYgMTZcIiBmaWxsPVwibm9uZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIj5cbiAgICA8cGF0aFxuICAgICAgZD1cIk04LjgzMzMzIDQuODc0OThWMS4zMzMzMUgzLjYyNUMzLjI3ODY1IDEuMzMzMzEgMyAxLjYxMTk2IDMgMS45NTgzMVYxNC4wNDE2QzMgMTQuMzg4IDMuMjc4NjUgMTQuNjY2NiAzLjYyNSAxNC42NjY2SDEyLjM3NUMxMi43MjE0IDE0LjY2NjYgMTMgMTQuMzg4IDEzIDE0LjA0MTZWNS40OTk5OEg5LjQ1ODMzQzkuMTE0NTggNS40OTk5OCA4LjgzMzMzIDUuMjE4NzMgOC44MzMzMyA0Ljg3NDk4Wk0xMyA0LjUwNzc5VjQuNjY2NjVIOS42NjY2N1YxLjMzMzMxSDkuODI1NTJDOS45OTIxOSAxLjMzMzMxIDEwLjE1MSAxLjM5ODQyIDEwLjI2ODIgMS41MTU2TDEyLjgxNzcgNC4wNjc2OUMxMi45MzQ5IDQuMTg0ODggMTMgNC4zNDM3MyAxMyA0LjUwNzc5WlwiXG4gICAgICBmaWxsPVwiY3VycmVudENvbG9yXCJcbiAgICAvPlxuICA8L3N2Zz5cbjwvbmctdGVtcGxhdGU+XG4iXX0=