UNPKG

ngx-editor

Version:

Rich Text Editor for angular using ProseMirror

217 lines 25.6 kB
import { Component, HostBinding, HostListener, Input, } from '@angular/core'; import { NodeSelection } from 'prosemirror-state'; import { asyncScheduler, fromEvent } from 'rxjs'; import { throttleTime } from 'rxjs/operators'; import { computePosition, detectOverflow, offset, autoPlacement } from '@floating-ui/dom'; import { NgxEditorError } from 'ngx-editor/utils'; import * as i0 from "@angular/core"; import * as i1 from "../bubble/bubble.component"; import * as i2 from "@angular/common"; export class FloatingMenuComponent { constructor(el) { this.el = el; this.autoPlace = false; this.posLeft = 0; this.posTop = 0; this.showMenu = false; this.dragging = false; } get display() { return { visibility: this.showMenu ? 'visible' : 'hidden', opacity: this.showMenu ? '1' : '0', top: `${this.posTop}px`, left: `${this.posLeft}px`, }; } get view() { return this.editor.view; } onMouseDown(e) { const target = e.target; if (this.el.nativeElement.contains(target) && target.nodeName !== 'INPUT') { e.preventDefault(); return; } this.dragging = true; } onKeyDown(e) { const target = e.target; if (target.nodeName === 'INPUT') { return; } this.dragging = true; this.hide(); } onMouseUp(e) { const target = e.target; if (this.el.nativeElement.contains(target) || target.nodeName === 'INPUT') { e.preventDefault(); return; } this.dragging = false; this.useUpdate(); } onKeyUp(e) { const target = e.target; if (target.nodeName === 'INPUT') { return; } this.dragging = false; this.useUpdate(); } useUpdate() { if (!this.view) { return; } this.update(this.view); } hide() { this.showMenu = false; } show() { this.showMenu = true; } async calculateBubblePosition(view) { const { state: { selection } } = view; const { from, to } = selection; const start = view.coordsAtPos(from); const end = view.coordsAtPos(to); const selectionElement = { getBoundingClientRect() { if (selection instanceof NodeSelection) { const node = view.nodeDOM(from); return node.getBoundingClientRect(); } const { top, left } = start; const { bottom, right } = end; return { x: left, y: top, top, bottom, left, right, width: right - left, height: bottom - top, }; }, }; // the floating bubble itself const bubbleEl = this.el.nativeElement; const { x: left, y: top } = await computePosition(selectionElement, bubbleEl, { placement: 'top', middleware: [ offset(5), this.autoPlace && autoPlacement({ boundary: view.dom, padding: 5, allowedPlacements: ['top', 'bottom'], }), { // prevent overflow on right and left side // since only top and bottom placements are allowed // autoplacement can't handle overflows on the right and left name: 'overflowMiddleware', async fn(middlewareArgs) { const overflow = await detectOverflow(middlewareArgs, { boundary: view.dom, padding: 5, }); // overflows left if (overflow.left > 0) { return { x: middlewareArgs.x + overflow.left, }; } // overflows right if (overflow.right > 0) { return { x: middlewareArgs.x - overflow.right, }; } return {}; }, }, ].filter(Boolean), }); return { left, top, }; } canShowMenu(view) { const { state } = view; const { selection } = state; const { empty } = selection; if (selection instanceof NodeSelection) { if (selection.node.type.name === 'image') { return false; } } const hasFocus = this.view.hasFocus(); if (!hasFocus || empty || this.dragging) { this.hide(); return false; } return true; } update(view) { const canShowMenu = this.canShowMenu(view); if (!canShowMenu) { this.hide(); return; } this.calculateBubblePosition(this.view).then(({ top, left }) => { if (!this.canShowMenu) { this.hide(); return; } this.posLeft = left; this.posTop = top; this.show(); }); } ngOnInit() { if (!this.editor) { throw new NgxEditorError('Required editor instance to initialize floating menu component'); } this.updateSubscription = this.editor.update .subscribe((view) => { this.update(view); }); this.resizeSubscription = fromEvent(window, 'resize').pipe(throttleTime(500, asyncScheduler, { leading: true, trailing: true })).subscribe(() => { this.useUpdate(); }); } ngOnDestroy() { this.updateSubscription.unsubscribe(); this.resizeSubscription.unsubscribe(); } } FloatingMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FloatingMenuComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); FloatingMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: FloatingMenuComponent, selector: "ngx-editor-floating-menu", inputs: { editor: "editor", autoPlace: "autoPlace" }, host: { listeners: { "document:mousedown": "onMouseDown($event)", "document:keydown": "onKeyDown($event)", "document:mouseup": "onMouseUp($event)", "document:keyup": "onKeyUp($event)" }, properties: { "style": "this.display" } }, ngImport: i0, template: "<div #ref>\n <ng-content></ng-content>\n</div>\n<ng-container *ngIf=\"ref.children.length === 0\">\n <ngx-bubble [editor]=\"editor\"></ngx-bubble>\n</ng-container>\n", styles: ["*,*:before,*:after{box-sizing:border-box}:host{position:absolute;z-index:20;margin-bottom:5px;visibility:hidden;opacity:0}\n"], components: [{ type: i1.BubbleComponent, selector: "ngx-bubble", inputs: ["editor"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: FloatingMenuComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-editor-floating-menu', template: "<div #ref>\n <ng-content></ng-content>\n</div>\n<ng-container *ngIf=\"ref.children.length === 0\">\n <ngx-bubble [editor]=\"editor\"></ngx-bubble>\n</ng-container>\n", styles: ["*,*:before,*:after{box-sizing:border-box}:host{position:absolute;z-index:20;margin-bottom:5px;visibility:hidden;opacity:0}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { display: [{ type: HostBinding, args: ['style'] }], editor: [{ type: Input }], autoPlace: [{ type: Input }], onMouseDown: [{ type: HostListener, args: ['document:mousedown', ['$event']] }], onKeyDown: [{ type: HostListener, args: ['document:keydown', ['$event']] }], onMouseUp: [{ type: HostListener, args: ['document:mouseup', ['$event']] }], onKeyUp: [{ type: HostListener, args: ['document:keyup', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctbWVudS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2Zsb2F0aW5nLW1lbnUvZmxvYXRpbmctbWVudS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWRpdG9yL3NyYy9saWIvbW9kdWxlcy9tZW51L2Zsb2F0aW5nLW1lbnUvZmxvYXRpbmctbWVudS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFjLFdBQVcsRUFDbEMsWUFBWSxFQUFFLEtBQUssR0FDcEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWxELE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMvRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTFGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7OztBQWFsRCxNQUFNLE9BQU8scUJBQXFCO0lBQ2hDLFlBQW1CLEVBQTJCO1FBQTNCLE9BQUUsR0FBRixFQUFFLENBQXlCO1FBZ0JyQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRW5CLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWixXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUVqQixhQUFRLEdBQUcsS0FBSyxDQUFDO0lBdEJ5QixDQUFDO0lBRW5ELElBQTBCLE9BQU87UUFDL0IsT0FBTztZQUNMLFVBQVUsRUFBRSxJQUFJLENB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ckUsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2YsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3hDLENBQUM7O2tIQXBPVSxxQkFBcUI7c0dBQXJCLHFCQUFxQiw0VkN4QmxDLHlLQU1BOzJGRGtCYSxxQkFBcUI7a0JBTGpDLFNBQVM7K0JBQ0UsMEJBQTBCO2lHQU9WLE9BQU87c0JBQWhDLFdBQVc7dUJBQUMsT0FBTztnQkFhWCxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFTMEMsV0FBVztzQkFBMUQsWUFBWTt1QkFBQyxvQkFBb0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFXQSxTQUFTO3NCQUF0RCxZQUFZO3VCQUFDLGtCQUFrQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVdFLFNBQVM7c0JBQXRELFlBQVk7dUJBQUMsa0JBQWtCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBWUEsT0FBTztzQkFBbEQsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsXG4gIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5vZGVTZWxlY3Rpb24gfSBmcm9tICdwcm9zZW1pcnJvci1zdGF0ZSc7XG5pbXBvcnQgeyBFZGl0b3JWaWV3IH0gZnJvbSAncHJvc2VtaXJyb3Itdmlldyc7XG5pbXBvcnQgeyBhc3luY1NjaGVkdWxlciwgZnJvbUV2ZW50LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRocm90dGxlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB0eXBlIHsgVmlydHVhbEVsZW1lbnQgfSBmcm9tICdAZmxvYXRpbmctdWkvY29yZSc7XG5pbXBvcnQgeyBjb21wdXRlUG9zaXRpb24sIGRldGVjdE92ZXJmbG93LCBvZmZzZXQsIGF1dG9QbGFjZW1lbnQgfSBmcm9tICdAZmxvYXRpbmctdWkvZG9tJztcblxuaW1wb3J0IHsgTmd4RWRpdG9yRXJyb3IgfSBmcm9tICduZ3gtZWRpdG9yL3V0aWxzJztcbmltcG9ydCBFZGl0b3IgZnJvbSAnLi4vLi4vLi4vRWRpdG9yJztcblxuaW50ZXJmYWNlIEJ1YmJsZVBvc2l0aW9uIHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWVkaXRvci1mbG9hdGluZy1tZW51JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Zsb2F0aW5nLW1lbnUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9mbG9hdGluZy1tZW51LmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIEZsb2F0aW5nTWVudUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgY29uc3RydWN0b3IocHVibGljIGVsOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PikgeyB9XG5cbiAgQEhvc3RCaW5kaW5nKCdzdHlsZScpIGdldCBkaXNwbGF5KCk6IFBhcnRpYWw8Q1NTU3R5bGVEZWNsYXJhdGlvbj4ge1xuICAgIHJldHVybiB7XG4gICAgICB2aXNpYmlsaXR5OiB0aGlzLnNob3dNZW51ID8gJ3Zpc2libGUnIDogJ2hpZGRlbicsXG4gICAgICBvcGFjaXR5OiB0aGlzLnNob3dNZW51ID8gJzEnIDogJzAnLFxuICAgICAgdG9wOiBgJHt0aGlzLnBvc1RvcH1weGAsXG4gICAgICBsZWZ0OiBgJHt0aGlzLnBvc0xlZnR9cHhgLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGdldCB2aWV3KCk6IEVkaXRvclZpZXcge1xuICAgIHJldHVybiB0aGlzLmVkaXRvci52aWV3O1xuICB9XG5cbiAgQElucHV0KCkgZWRpdG9yOiBFZGl0b3I7XG4gIEBJbnB1dCgpIGF1dG9QbGFjZSA9IGZhbHNlO1xuXG4gIHByaXZhdGUgcG9zTGVmdCA9IDA7XG4gIHByaXZhdGUgcG9zVG9wID0gMDtcbiAgcHJpdmF0ZSBzaG93TWVudSA9IGZhbHNlO1xuICBwcml2YXRlIHVwZGF0ZVN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIGRyYWdnaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgcmVzaXplU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6bW91c2Vkb3duJywgWyckZXZlbnQnXSkgb25Nb3VzZURvd24oZTogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0IGFzIE5vZGU7XG5cbiAgICBpZiAodGhpcy5lbC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkgJiYgdGFyZ2V0Lm5vZGVOYW1lICE9PSAnSU5QVVQnKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kcmFnZ2luZyA9IHRydWU7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlkb3duJywgWyckZXZlbnQnXSkgb25LZXlEb3duKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXQgPSBlLnRhcmdldCBhcyBOb2RlO1xuXG4gICAgaWYgKHRhcmdldC5ub2RlTmFtZSA9PT0gJ0lOUFVUJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZHJhZ2dpbmcgPSB0cnVlO1xuICAgIHRoaXMuaGlkZSgpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6bW91c2V1cCcsIFsnJGV2ZW50J10pIG9uTW91c2VVcChlOiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgTm9kZTtcblxuICAgIGlmICh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuY29udGFpbnModGFyZ2V0KSB8fCB0YXJnZXQubm9kZU5hbWUgPT09ICdJTlBVVCcpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgdGhpcy51c2VVcGRhdGUoKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleXVwJywgWyckZXZlbnQnXSkgb25LZXlVcChlOiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZS50YXJnZXQgYXMgTm9kZTtcblxuICAgIGlmICh0YXJnZXQubm9kZU5hbWUgPT09ICdJTlBVVCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgdGhpcy51c2VVcGRhdGUoKTtcbiAgfVxuXG4gIHByaXZhdGUgdXNlVXBkYXRlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy52aWV3KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGUodGhpcy52aWV3KTtcbiAgfVxuXG4gIHByaXZhdGUgaGlkZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dNZW51ID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIHNob3coKTogdm9pZCB7XG4gICAgdGhpcy5zaG93TWVudSA9IHRydWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGN1bGF0ZUJ1YmJsZVBvc2l0aW9uKHZpZXc6IEVkaXRvclZpZXcpOiBQcm9taXNlPEJ1YmJsZVBvc2l0aW9uPiB7XG4gICAgY29uc3QgeyBzdGF0ZTogeyBzZWxlY3Rpb24gfSB9ID0gdmlldztcbiAgICBjb25zdCB7IGZyb20sIHRvIH0gPSBzZWxlY3Rpb247XG5cbiAgICBjb25zdCBzdGFydCA9IHZpZXcuY29vcmRzQXRQb3MoZnJvbSk7XG4gICAgY29uc3QgZW5kID0gdmlldy5jb29yZHNBdFBvcyh0byk7XG5cbiAgICBjb25zdCBzZWxlY3Rpb25FbGVtZW50OiBWaXJ0dWFsRWxlbWVudCA9IHtcbiAgICAgIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIHtcbiAgICAgICAgaWYgKHNlbGVjdGlvbiBpbnN0YW5jZW9mIE5vZGVTZWxlY3Rpb24pIHtcbiAgICAgICAgICBjb25zdCBub2RlID0gdmlldy5ub2RlRE9NKGZyb20pIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICAgIHJldHVybiBub2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyB0b3AsIGxlZnQgfSA9IHN0YXJ0O1xuICAgICAgICBjb25zdCB7IGJvdHRvbSwgcmlnaHQgfSA9IGVuZDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHg6IGxlZnQsXG4gICAgICAgICAgeTogdG9wLFxuICAgICAgICAgIHRvcCxcbiAgICAgICAgICBib3R0b20sXG4gICAgICAgICAgbGVmdCxcbiAgICAgICAgICByaWdodCxcbiAgICAgICAgICB3aWR0aDogcmlnaHQgLSBsZWZ0LFxuICAgICAgICAgIGhlaWdodDogYm90dG9tIC0gdG9wLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICB9O1xuXG4gICAgLy8gdGhlIGZsb2F0aW5nIGJ1YmJsZSBpdHNlbGZcbiAgICBjb25zdCBidWJibGVFbCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudDtcblxuICAgIGNvbnN0IHsgeDogbGVmdCwgeTogdG9wIH0gPSBhd2FpdCBjb21wdXRlUG9zaXRpb24oc2VsZWN0aW9uRWxlbWVudCwgYnViYmxlRWwsIHtcbiAgICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgICBtaWRkbGV3YXJlOiBbXG4gICAgICAgIG9mZnNldCg1KSxcbiAgICAgICAgdGhpcy5hdXRvUGxhY2UgJiYgYXV0b1BsYWNlbWVudCh7XG4gICAgICAgICAgYm91bmRhcnk6IHZpZXcuZG9tLFxuICAgICAgICAgIHBhZGRpbmc6IDUsXG4gICAgICAgICAgYWxsb3dlZFBsYWNlbWVudHM6IFsndG9wJywgJ2JvdHRvbSddLFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIC8vIHByZXZlbnQgb3ZlcmZsb3cgb24gcmlnaHQgYW5kIGxlZnQgc2lkZVxuICAgICAgICAgIC8vIHNpbmNlIG9ubHkgdG9wIGFuZCBib3R0b20gcGxhY2VtZW50cyBhcmUgYWxsb3dlZFxuICAgICAgICAgIC8vIGF1dG9wbGFjZW1lbnQgY2FuJ3QgaGFuZGxlIG92ZXJmbG93cyBvbiB0aGUgcmlnaHQgYW5kIGxlZnRcbiAgICAgICAgICBuYW1lOiAnb3ZlcmZsb3dNaWRkbGV3YXJlJyxcbiAgICAgICAgICBhc3luYyBmbihtaWRkbGV3YXJlQXJncykge1xuICAgICAgICAgICAgY29uc3Qgb3ZlcmZsb3cgPSBhd2FpdCBkZXRlY3RPdmVyZmxvdyhtaWRkbGV3YXJlQXJncywge1xuICAgICAgICAgICAgICBib3VuZGFyeTogdmlldy5kb20sXG4gICAgICAgICAgICAgIHBhZGRpbmc6IDUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gb3ZlcmZsb3dzIGxlZnRcbiAgICAgICAgICAgIGlmIChvdmVyZmxvdy5sZWZ0ID4gMCkge1xuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHg6IG1pZGRsZXdhcmVBcmdzLnggKyBvdmVyZmxvdy5sZWZ0LFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBvdmVyZmxvd3MgcmlnaHRcbiAgICAgICAgICAgIGlmIChvdmVyZmxvdy5yaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiBtaWRkbGV3YXJlQXJncy54IC0gb3ZlcmZsb3cucmlnaHQsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXS5maWx0ZXIoQm9vbGVhbiksXG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGVmdCxcbiAgICAgIHRvcCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5TaG93TWVudSh2aWV3OiBFZGl0b3JWaWV3KTogQm9vbGVhbiB7XG4gICAgY29uc3QgeyBzdGF0ZSB9ID0gdmlldztcbiAgICBjb25zdCB7IHNlbGVjdGlvbiB9ID0gc3RhdGU7XG4gICAgY29uc3QgeyBlbXB0eSB9ID0gc2VsZWN0aW9uO1xuXG4gICAgaWYgKHNlbGVjdGlvbiBpbnN0YW5jZW9mIE5vZGVTZWxlY3Rpb24pIHtcbiAgICAgIGlmIChzZWxlY3Rpb24ubm9kZS50eXBlLm5hbWUgPT09ICdpbWFnZScpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGhhc0ZvY3VzID0gdGhpcy52aWV3Lmhhc0ZvY3VzKCk7XG5cbiAgICBpZiAoIWhhc0ZvY3VzIHx8IGVtcHR5IHx8IHRoaXMuZHJhZ2dpbmcpIHtcbiAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGUodmlldzogRWRpdG9yVmlldyk6IHZvaWQge1xuICAgIGNvbnN0IGNhblNob3dNZW51ID0gdGhpcy5jYW5TaG93TWVudSh2aWV3KTtcblxuICAgIGlmICghY2FuU2hvd01lbnUpIHtcbiAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2FsY3VsYXRlQnViYmxlUG9zaXRpb24odGhpcy52aWV3KS50aGVuKCh7IHRvcCwgbGVmdCB9KSA9PiB7XG4gICAgICBpZiAoIXRoaXMuY2FuU2hvd01lbnUpIHtcbiAgICAgICAgdGhpcy5oaWRlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wb3NMZWZ0ID0gbGVmdDtcbiAgICAgIHRoaXMucG9zVG9wID0gdG9wO1xuXG4gICAgICB0aGlzLnNob3coKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5lZGl0b3IpIHtcbiAgICAgIHRocm93IG5ldyBOZ3hFZGl0b3JFcnJvcignUmVxdWlyZWQgZWRpdG9yIGluc3RhbmNlIHRvIGluaXRpYWxpemUgZmxvYXRpbmcgbWVudSBjb21wb25lbnQnKTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVN1YnNjcmlwdGlvbiA9IHRoaXMuZWRpdG9yLnVwZGF0ZVxuICAgICAgLnN1YnNjcmliZSgodmlldykgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZSh2aWV3KTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24gPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJykucGlwZShcbiAgICAgIHRocm90dGxlVGltZSg1MDAsIGFzeW5jU2NoZWR1bGVyLCB7IGxlYWRpbmc6IHRydWUsIHRyYWlsaW5nOiB0cnVlIH0pLFxuICAgICkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMudXNlVXBkYXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMucmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cbn1cbiIsIjxkaXYgI3JlZj5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG48bmctY29udGFpbmVyICpuZ0lmPVwicmVmLmNoaWxkcmVuLmxlbmd0aCA9PT0gMFwiPlxuICA8bmd4LWJ1YmJsZSBbZWRpdG9yXT1cImVkaXRvclwiPjwvbmd4LWJ1YmJsZT5cbjwvbmctY29udGFpbmVyPlxuIl19