ngx-editor
Version:
Rich Text Editor for angular using ProseMirror
217 lines • 25.6 kB
JavaScript
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