@libs-ui/components-inputs-mention 0.2.10-6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,166 @@
1
+ import { ChangeDetectionStrategy, Component, model, signal, viewChild, viewChildren } from "@angular/core";
2
+ import { LibsUiComponentsAvatarComponent } from "@libs-ui/components-avatar";
3
+ import { LibsUiComponentsPopoverComponent } from "@libs-ui/components-popover";
4
+ import { set } from "@libs-ui/utils";
5
+ import { fromEvent, Subject, takeUntil } from "rxjs";
6
+ import { getCaretCoordinates } from "../defines/caret-coords.define";
7
+ import { KEY_ENTER } from "../defines/keyboard.define";
8
+ import { getContentEditableCaretCoords, isInputOrTextAreaElement } from "../defines/utils.define";
9
+ import * as i0 from "@angular/core";
10
+ export class LibsUiComponentsInputsMentionListComponent {
11
+ /* PROPERTY */
12
+ items = signal([]);
13
+ activeIndex = signal(0);
14
+ hidden = signal(false);
15
+ styleOff = signal(false);
16
+ parentHandlerKeyDown = signal(undefined);
17
+ dropUp = signal(false);
18
+ coords = signal({ top: 0, left: 0, bottom: 0 });
19
+ offset = signal(0);
20
+ nativeParentElement = signal(undefined);
21
+ onDestroy = new Subject();
22
+ /* INPUT */
23
+ labelKey = model('label');
24
+ zIndex = model(1000);
25
+ isIframe = model.required();
26
+ defaultAvatar = model();
27
+ /* VIEW CHILD */
28
+ elementEl = viewChild('element');
29
+ itemsEl = viewChildren('item');
30
+ ngOnInit() {
31
+ if (this.isIframe()) {
32
+ this.initEvent(window.parent, 'wheel');
33
+ this.initEvent(window.parent, 'resize');
34
+ return;
35
+ }
36
+ this.initEvent(window, 'wheel');
37
+ this.initEvent(window, 'resize');
38
+ }
39
+ /* FUNCTIONS */
40
+ initEvent(element, eventName) {
41
+ fromEvent(element, eventName).pipe(takeUntil(this.onDestroy)).subscribe((event) => {
42
+ if (eventName === 'resize' || !this.elementEl()?.nativeElement.contains(event.target)) {
43
+ this.handlerListenClose(event);
44
+ }
45
+ });
46
+ }
47
+ handlerListenClose(event) {
48
+ if (event.target !== this.elementEl()?.nativeElement) {
49
+ this.hidden.set(true);
50
+ }
51
+ }
52
+ // lots of confusion here between relative coordinates and containers
53
+ position(nativeParentElement, iframe, leftDiv) {
54
+ this.nativeParentElement.set(nativeParentElement);
55
+ if (isInputOrTextAreaElement(nativeParentElement)) {
56
+ // parent elements need to have postition:relative for this to work correctly?
57
+ this.coords.set(getCaretCoordinates(nativeParentElement, nativeParentElement.selectionStart));
58
+ this.coords.update(item => ({
59
+ ...item,
60
+ top: nativeParentElement.offsetTop + item.top - nativeParentElement.scrollTop,
61
+ left: nativeParentElement.offsetLeft + item.left - nativeParentElement.scrollLeft + nativeParentElement.getBoundingClientRect().left
62
+ }));
63
+ // getCretCoordinates() for text/input elements needs an additional offset to position the list correctly
64
+ this.offset.set(this.getBlockCursorDimensions(nativeParentElement).height);
65
+ this.positionElement();
66
+ return;
67
+ }
68
+ if (iframe) {
69
+ const context = { iframe: iframe, parent: window.parent.document.body, windowParent: true };
70
+ // const rect = iframe.getBoundingClientRect();
71
+ const caretRelativeToView = getContentEditableCaretCoords(context);
72
+ const doc = document.documentElement;
73
+ const scrollLeft = (window.scrollX || doc.scrollLeft) - (doc.clientLeft || 0);
74
+ this.coords.update(item => ({
75
+ ...item,
76
+ left: caretRelativeToView.left - scrollLeft - (leftDiv || 0),
77
+ bottom: window.parent.innerHeight - caretRelativeToView.top + 18
78
+ }));
79
+ if (caretRelativeToView.bottom && caretRelativeToView.bottom !== -1) {
80
+ this.coords.update(item => ({
81
+ ...item,
82
+ bottom: caretRelativeToView.bottom
83
+ }));
84
+ }
85
+ this.positionElement();
86
+ return;
87
+ }
88
+ const doc = document.documentElement;
89
+ const scrollLeft = (window.scrollX || doc.scrollLeft) - (doc.clientLeft || 0);
90
+ const scrollTop = (window.scrollX || doc.scrollTop) - (doc.clientTop || 0);
91
+ // bounding rectangles are relative to view, offsets are relative to container?
92
+ const caretRelativeToView = getContentEditableCaretCoords({ iframe, parent: null });
93
+ this.coords.update(item => ({
94
+ ...item,
95
+ top: caretRelativeToView.top - scrollTop + 10,
96
+ left: caretRelativeToView.left - scrollLeft - (leftDiv || 0),
97
+ bottom: caretRelativeToView.bottom
98
+ }));
99
+ this.positionElement();
100
+ }
101
+ get ActiveItem() {
102
+ return this.items()[this.activeIndex()];
103
+ }
104
+ handlerClick(event, index) {
105
+ event.stopPropagation();
106
+ this.activeIndex.set(index);
107
+ set(event, 'keyCode', KEY_ENTER);
108
+ this.parentHandlerKeyDown()?.(event, this.nativeParentElement());
109
+ }
110
+ activateNextItem() {
111
+ this.activeIndex.set(this.items().length - 1 > this.activeIndex() ? this.activeIndex() + 1 : this.activeIndex());
112
+ this.scrollToActive();
113
+ }
114
+ activatePreviousItem() {
115
+ this.activeIndex.set(this.activeIndex() > 0 ? this.activeIndex() - 1 : this.activeIndex());
116
+ this.scrollToActive();
117
+ }
118
+ positionElement(left = this.coords().left, top = this.coords().top, dropUp = this.dropUp(), bottom = this.coords().bottom || 0) {
119
+ const el = this.elementEl()?.nativeElement;
120
+ top += dropUp ? 0 : this.offset(); // top of list is next line
121
+ el.style.position = "absolute";
122
+ el.style.left = left + 'px';
123
+ el.style.top = bottom !== -1 ? 'auto' : top + 'px';
124
+ el.style.bottom = bottom === -1 ? 'auto' : bottom + 'px';
125
+ this.nativeParentElement()?.normalize();
126
+ }
127
+ getBlockCursorDimensions(nativeParentElement) {
128
+ const parentStyles = window.getComputedStyle(nativeParentElement);
129
+ return {
130
+ height: parseFloat(parentStyles.lineHeight),
131
+ width: parseFloat(parentStyles.fontSize)
132
+ };
133
+ }
134
+ handleActiveItem(event, index) {
135
+ event.stopPropagation();
136
+ this.activeIndex.set(index);
137
+ }
138
+ scrollToActive() {
139
+ if (!this.itemsEl() || (this.itemsEl().length <= this.activeIndex())) {
140
+ return;
141
+ }
142
+ this.itemsEl()[this.activeIndex()].nativeElement.scrollIntoView();
143
+ }
144
+ scrollContent() {
145
+ setTimeout(() => {
146
+ const element = this.elementEl();
147
+ if (element && element.nativeElement) {
148
+ element.nativeElement.scrollTop = 0;
149
+ }
150
+ });
151
+ }
152
+ ngOnDestroy() {
153
+ this.onDestroy.next();
154
+ this.onDestroy.complete();
155
+ }
156
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsInputsMentionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
157
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsInputsMentionListComponent, isStandalone: true, selector: "libs_ui-components-inputs-mention-list", inputs: { labelKey: { classPropertyName: "labelKey", publicName: "labelKey", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, isIframe: { classPropertyName: "isIframe", publicName: "isIframe", isSignal: true, isRequired: true, transformFunction: null }, defaultAvatar: { classPropertyName: "defaultAvatar", publicName: "defaultAvatar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { labelKey: "labelKeyChange", zIndex: "zIndexChange", isIframe: "isIframeChange", defaultAvatar: "defaultAvatarChange" }, viewQueries: [{ propertyName: "elementEl", first: true, predicate: ["element"], descendants: true, isSignal: true }, { propertyName: "itemsEl", predicate: ["item"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #element\n class=\"libs-ui-mention-list\"\n [style.zIndex]=\"zIndex()\"\n [class.hidden]=\"hidden()\">\n @for (item of items(); track item) {\n <div #item\n class=\"libs-ui-mention-list-item\"\n [class.libs-ui-mention-list-item-active]=\"$index === activeIndex()\"\n (mousedown)=\"handlerClick($event, $index)\"\n (mouseenter)=\"handleActiveItem($event, $index)\">\n <div class=\"px-[12px] py-[6px] flex items-center\">\n <libs_ui-components-avatar [size]=\"24\"\n [linkAvatar]=\"item.avatar\"\n [linkAvatarError]=\"defaultAvatar()\"\n [textAvatar]=\"item.name\"\n [idGenColor]=\"item.id\"\n [getLastTextAfterSpace]=\"true\" />\n <libs_ui-components-popover [classInclude]=\"'libs-ui-font-h5r'\"\n [type]=\"'text'\"\n [ignoreShowPopover]=\"true\"\n [config]=\"{width: 250}\">\n <!-- // ta.m \u1EA9n show tooltip v\u00EC ch\u01B0a x\u1EED l\u00FD \u0111c v\u1ECB tr\u00ED -->\n {{ item.name + ' (' + item.username + ')' }}\n </libs_ui-components-popover>\n </div>\n </div>\n }\n</div>\n", styles: [".libs-ui-mention-list{position:absolute;top:-999px;left:-9999px;z-index:1202;float:left;width:315px;padding:4px 0;background-color:#fff;border:solid 1px #e6e8ed;border-radius:5px;max-height:190px;overflow:auto;box-shadow:0 2px 10px 1px #3333331a}.libs-ui-mention-list .libs-ui-mention-list-item{background:#fff;cursor:pointer}.libs-ui-mention-list .libs-ui-mention-list-item:hover,.libs-ui-mention-list .libs-ui-mention-list-item-active{background-color:var(--libs-ui-color-light-3, #f4f8ff)}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAvatarComponent, selector: "libs_ui-components-avatar", inputs: ["getLastTextAfterSpace", "typeShape", "classInclude", "size", "linkAvatar", "linkAvatarError", "idGenColor", "textAvatar", "classImageInclude"], outputs: ["outAvatarError"] }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
158
+ }
159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsInputsMentionListComponent, decorators: [{
160
+ type: Component,
161
+ args: [{ selector: 'libs_ui-components-inputs-mention-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
162
+ LibsUiComponentsAvatarComponent,
163
+ LibsUiComponentsPopoverComponent
164
+ ], template: "<div #element\n class=\"libs-ui-mention-list\"\n [style.zIndex]=\"zIndex()\"\n [class.hidden]=\"hidden()\">\n @for (item of items(); track item) {\n <div #item\n class=\"libs-ui-mention-list-item\"\n [class.libs-ui-mention-list-item-active]=\"$index === activeIndex()\"\n (mousedown)=\"handlerClick($event, $index)\"\n (mouseenter)=\"handleActiveItem($event, $index)\">\n <div class=\"px-[12px] py-[6px] flex items-center\">\n <libs_ui-components-avatar [size]=\"24\"\n [linkAvatar]=\"item.avatar\"\n [linkAvatarError]=\"defaultAvatar()\"\n [textAvatar]=\"item.name\"\n [idGenColor]=\"item.id\"\n [getLastTextAfterSpace]=\"true\" />\n <libs_ui-components-popover [classInclude]=\"'libs-ui-font-h5r'\"\n [type]=\"'text'\"\n [ignoreShowPopover]=\"true\"\n [config]=\"{width: 250}\">\n <!-- // ta.m \u1EA9n show tooltip v\u00EC ch\u01B0a x\u1EED l\u00FD \u0111c v\u1ECB tr\u00ED -->\n {{ item.name + ' (' + item.username + ')' }}\n </libs_ui-components-popover>\n </div>\n </div>\n }\n</div>\n", styles: [".libs-ui-mention-list{position:absolute;top:-999px;left:-9999px;z-index:1202;float:left;width:315px;padding:4px 0;background-color:#fff;border:solid 1px #e6e8ed;border-radius:5px;max-height:190px;overflow:auto;box-shadow:0 2px 10px 1px #3333331a}.libs-ui-mention-list .libs-ui-mention-list-item{background:#fff;cursor:pointer}.libs-ui-mention-list .libs-ui-mention-list-item:hover,.libs-ui-mention-list .libs-ui-mention-list-item-active{background-color:var(--libs-ui-color-light-3, #f4f8ff)}\n"] }]
165
+ }] });
166
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW5wdXRzL21lbnRpb24vc3JjL2xpc3QvbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW5wdXRzL21lbnRpb24vc3JjL2xpc3QvbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFjLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUksT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0UsT0FBTyxFQUFFLGdDQUFnQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDL0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDdkQsT0FBTyxFQUFFLDZCQUE2QixFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUM7O0FBY2xHLE1BQU0sT0FBTywwQ0FBMEM7SUFFckQsY0FBYztJQUNQLEtBQUssR0FBRyxNQUFNLENBQTRDLEVBQUUsQ0FBQyxDQUFDO0lBQzlELFdBQVcsR0FBRyxNQUFNLENBQVMsQ0FBQyxDQUFDLENBQUM7SUFDaEMsTUFBTSxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNoQyxRQUFRLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLG9C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QUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRU8sY0FBYztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3JFLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNwRSxDQUFDO0lBRUQsYUFBYTtRQUNYLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDakMsSUFBSSxPQUFPLElBQUksT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUNyQyxPQUFPLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7WUFDdEMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDNUIsQ0FBQzt3R0F6S1UsMENBQTBDOzRGQUExQywwQ0FBMEMsdzhCQ3JCdkQsd25DQTRCQSx3aUJEWEksK0JBQStCLDZQQUMvQixnQ0FBZ0M7OzRGQUd2QiwwQ0FBMEM7a0JBWnRELFNBQVM7K0JBRUUsd0NBQXdDLGNBR3RDLElBQUksbUJBQ0MsdUJBQXVCLENBQUMsTUFBTSxXQUN0Qzt3QkFDUCwrQkFBK0I7d0JBQy9CLGdDQUFnQztxQkFDakMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBtb2RlbCwgT25EZXN0cm95LCBPbkluaXQsIHNpZ25hbCwgdmlld0NoaWxkLCB2aWV3Q2hpbGRyZW4gfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgTGlic1VpQ29tcG9uZW50c0F2YXRhckNvbXBvbmVudCB9IGZyb20gXCJAbGlicy11aS9jb21wb25lbnRzLWF2YXRhclwiO1xuaW1wb3J0IHsgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJDb21wb25lbnQgfSBmcm9tIFwiQGxpYnMtdWkvY29tcG9uZW50cy1wb3BvdmVyXCI7XG5pbXBvcnQgeyBzZXQgfSBmcm9tIFwiQGxpYnMtdWkvdXRpbHNcIjtcbmltcG9ydCB7IGZyb21FdmVudCwgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGdldENhcmV0Q29vcmRpbmF0ZXMgfSBmcm9tIFwiLi4vZGVmaW5lcy9jYXJldC1jb29yZHMuZGVmaW5lXCI7XG5pbXBvcnQgeyBLRVlfRU5URVIgfSBmcm9tIFwiLi4vZGVmaW5lcy9rZXlib2FyZC5kZWZpbmVcIjtcbmltcG9ydCB7IGdldENvbnRlbnRFZGl0YWJsZUNhcmV0Q29vcmRzLCBpc0lucHV0T3JUZXh0QXJlYUVsZW1lbnQgfSBmcm9tIFwiLi4vZGVmaW5lcy91dGlscy5kZWZpbmVcIjtcblxuQENvbXBvbmVudCh7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvY29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnbGlic191aS1jb21wb25lbnRzLWlucHV0cy1tZW50aW9uLWxpc3QnLFxuICB0ZW1wbGF0ZVVybDogJy4vbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2xpc3QuY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGltcG9ydHM6IFtcbiAgICBMaWJzVWlDb21wb25lbnRzQXZhdGFyQ29tcG9uZW50LFxuICAgIExpYnNVaUNvbXBvbmVudHNQb3BvdmVyQ29tcG9uZW50XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTGlic1VpQ29tcG9uZW50c0lucHV0c01lbnRpb25MaXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIC8qIFBST1BFUlRZICovXG4gIHB1YmxpYyBpdGVtcyA9IHNpZ25hbDxBcnJheTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+Pj4oW10pO1xuICBwdWJsaWMgYWN0aXZlSW5kZXggPSBzaWduYWw8bnVtYmVyPigwKTtcbiAgcHVibGljIGhpZGRlbiA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHB1YmxpYyBzdHlsZU9mZiA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHB1YmxpYyBwYXJlbnRIYW5kbGVyS2V5RG93biA9IHNpZ25hbDwoKGU6IEV2ZW50LCBlbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50IHwgdW5kZWZpbmVkKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuICBwcm90ZWN0ZWQgZHJvcFVwID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcblxuICBwcml2YXRlIGNvb3JkcyA9IHNpZ25hbDx7IHRvcDogbnVtYmVyLCBsZWZ0OiBudW1iZXIsIGJvdHRvbT86IG51bWJlciB9Pih7IHRvcDogMCwgbGVmdDogMCwgYm90dG9tOiAwIH0pO1xuICBwcml2YXRlIG9mZnNldCA9IHNpZ25hbDxudW1iZXI+KDApO1xuICBwcml2YXRlIG5hdGl2ZVBhcmVudEVsZW1lbnQgPSBzaWduYWw8SFRNTElucHV0RWxlbWVudCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgcHJpdmF0ZSBvbkRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIC8qIElOUFVUICovXG4gIGxhYmVsS2V5ID0gbW9kZWw8c3RyaW5nPignbGFiZWwnKTtcbiAgekluZGV4ID0gbW9kZWw8bnVtYmVyPigxMDAwKTtcbiAgaXNJZnJhbWUgPSBtb2RlbC5yZXF1aXJlZDxib29sZWFuPigpO1xuICBkZWZhdWx0QXZhdGFyID0gbW9kZWw8c3RyaW5nPigpO1xuXG4gIC8qIFZJRVcgQ0hJTEQgKi9cbiAgcmVhZG9ubHkgZWxlbWVudEVsID0gdmlld0NoaWxkPEVsZW1lbnRSZWY+KCdlbGVtZW50Jyk7XG4gIHJlYWRvbmx5IGl0ZW1zRWwgPSB2aWV3Q2hpbGRyZW48RWxlbWVudFJlZj4oJ2l0ZW0nKTtcblxuICBuZ09uSW5pdCgpIHtcbiAgICBpZiAodGhpcy5pc0lmcmFtZSgpKSB7XG4gICAgICB0aGlzLmluaXRFdmVudCh3aW5kb3cucGFyZW50LCAnd2hlZWwnKTtcbiAgICAgIHRoaXMuaW5pdEV2ZW50KHdpbmRvdy5wYXJlbnQsICdyZXNpemUnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5pbml0RXZlbnQod2luZG93LCAnd2hlZWwnKTtcbiAgICB0aGlzLmluaXRFdmVudCh3aW5kb3csICdyZXNpemUnKTtcbiAgfVxuXG4gIC8qIEZVTkNUSU9OUyAqL1xuICBwcml2YXRlIGluaXRFdmVudChlbGVtZW50OiBXaW5kb3csIGV2ZW50TmFtZTogc3RyaW5nKSB7XG4gICAgZnJvbUV2ZW50PEV2ZW50PihlbGVtZW50LCBldmVudE5hbWUpLnBpcGUodGFrZVVudGlsKHRoaXMub25EZXN0cm95KSkuc3Vic2NyaWJlKChldmVudDogRXZlbnQpID0+IHtcbiAgICAgIGlmIChldmVudE5hbWUgPT09ICdyZXNpemUnIHx8ICF0aGlzLmVsZW1lbnRFbCgpPy5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVyTGlzdGVuQ2xvc2UoZXZlbnQpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVyTGlzdGVuQ2xvc2UoZXZlbnQ6IEV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LnRhcmdldCAhPT0gdGhpcy5lbGVtZW50RWwoKT8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgdGhpcy5oaWRkZW4uc2V0KHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGxvdHMgb2YgY29uZnVzaW9uIGhlcmUgYmV0d2VlbiByZWxhdGl2ZSBjb29yZGluYXRlcyBhbmQgY29udGFpbmVyc1xuICBwb3NpdGlvbihuYXRpdmVQYXJlbnRFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50LCBpZnJhbWU/OiBIVE1MSUZyYW1lRWxlbWVudCwgbGVmdERpdj86IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMubmF0aXZlUGFyZW50RWxlbWVudC5zZXQobmF0aXZlUGFyZW50RWxlbWVudCk7XG4gICAgaWYgKGlzSW5wdXRPclRleHRBcmVhRWxlbWVudChuYXRpdmVQYXJlbnRFbGVtZW50KSkge1xuICAgICAgLy8gcGFyZW50IGVsZW1lbnRzIG5lZWQgdG8gaGF2ZSBwb3N0aXRpb246cmVsYXRpdmUgZm9yIHRoaXMgdG8gd29yayBjb3JyZWN0bHk/XG4gICAgICB0aGlzLmNvb3Jkcy5zZXQoZ2V0Q2FyZXRDb29yZGluYXRlcyhuYXRpdmVQYXJlbnRFbGVtZW50LCBuYXRpdmVQYXJlbnRFbGVtZW50LnNlbGVjdGlvblN0YXJ0KSk7XG4gICAgICB0aGlzLmNvb3Jkcy51cGRhdGUoaXRlbSA9PiAoe1xuICAgICAgICAuLi5pdGVtLFxuICAgICAgICB0b3A6IG5hdGl2ZVBhcmVudEVsZW1lbnQub2Zmc2V0VG9wICsgaXRlbS50b3AgLSBuYXRpdmVQYXJlbnRFbGVtZW50LnNjcm9sbFRvcCxcbiAgICAgICAgbGVmdDogbmF0aXZlUGFyZW50RWxlbWVudC5vZmZzZXRMZWZ0ICsgaXRlbS5sZWZ0IC0gbmF0aXZlUGFyZW50RWxlbWVudC5zY3JvbGxMZWZ0ICsgbmF0aXZlUGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0XG4gICAgICB9KSk7XG5cbiAgICAgIC8vIGdldENyZXRDb29yZGluYXRlcygpIGZvciB0ZXh0L2lucHV0IGVsZW1lbnRzIG5lZWRzIGFuIGFkZGl0aW9uYWwgb2Zmc2V0IHRvIHBvc2l0aW9uIHRoZSBsaXN0IGNvcnJlY3RseVxuICAgICAgdGhpcy5vZmZzZXQuc2V0KHRoaXMuZ2V0QmxvY2tDdXJzb3JEaW1lbnNpb25zKG5hdGl2ZVBhcmVudEVsZW1lbnQpLmhlaWdodCk7XG4gICAgICB0aGlzLnBvc2l0aW9uRWxlbWVudCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoaWZyYW1lKSB7XG4gICAgICBjb25zdCBjb250ZXh0OiB7IGlmcmFtZTogSFRNTElGcmFtZUVsZW1lbnQsIHBhcmVudDogRWxlbWVudCB8IG51bGwsIHdpbmRvd1BhcmVudD86IGJvb2xlYW4gfSA9IHsgaWZyYW1lOiBpZnJhbWUsIHBhcmVudDogd2luZG93LnBhcmVudC5kb2N1bWVudC5ib2R5LCB3aW5kb3dQYXJlbnQ6IHRydWUgfTtcbiAgICAgIC8vIGNvbnN0IHJlY3QgPSBpZnJhbWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBjb25zdCBjYXJldFJlbGF0aXZlVG9WaWV3ID0gZ2V0Q29udGVudEVkaXRhYmxlQ2FyZXRDb29yZHMoY29udGV4dCk7XG4gICAgICBjb25zdCBkb2MgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICBjb25zdCBzY3JvbGxMZWZ0ID0gKHdpbmRvdy5zY3JvbGxYIHx8IGRvYy5zY3JvbGxMZWZ0KSAtIChkb2MuY2xpZW50TGVmdCB8fCAwKTtcbiAgICAgIHRoaXMuY29vcmRzLnVwZGF0ZShpdGVtID0+ICh7XG4gICAgICAgIC4uLml0ZW0sXG4gICAgICAgIGxlZnQ6IGNhcmV0UmVsYXRpdmVUb1ZpZXcubGVmdCAtIHNjcm9sbExlZnQgLSAobGVmdERpdiB8fCAwKSxcbiAgICAgICAgYm90dG9tOiB3aW5kb3cucGFyZW50LmlubmVySGVpZ2h0IC0gY2FyZXRSZWxhdGl2ZVRvVmlldy50b3AgKyAxOFxuICAgICAgfSkpO1xuICAgICAgaWYgKGNhcmV0UmVsYXRpdmVUb1ZpZXcuYm90dG9tICYmIGNhcmV0UmVsYXRpdmVUb1ZpZXcuYm90dG9tICE9PSAtMSkge1xuICAgICAgICB0aGlzLmNvb3Jkcy51cGRhdGUoaXRlbSA9PiAoe1xuICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgYm90dG9tOiBjYXJldFJlbGF0aXZlVG9WaWV3LmJvdHRvbVxuICAgICAgICB9KSk7XG4gICAgICB9XG4gICAgICB0aGlzLnBvc2l0aW9uRWxlbWVudCgpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRvYyA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICBjb25zdCBzY3JvbGxMZWZ0ID0gKHdpbmRvdy5zY3JvbGxYIHx8IGRvYy5zY3JvbGxMZWZ0KSAtIChkb2MuY2xpZW50TGVmdCB8fCAwKTtcbiAgICBjb25zdCBzY3JvbGxUb3AgPSAod2luZG93LnNjcm9sbFggfHwgZG9jLnNjcm9sbFRvcCkgLSAoZG9jLmNsaWVudFRvcCB8fCAwKTtcbiAgICAvLyBib3VuZGluZyByZWN0YW5nbGVzIGFyZSByZWxhdGl2ZSB0byB2aWV3LCBvZmZzZXRzIGFyZSByZWxhdGl2ZSB0byBjb250YWluZXI/XG4gICAgY29uc3QgY2FyZXRSZWxhdGl2ZVRvVmlldyA9IGdldENvbnRlbnRFZGl0YWJsZUNhcmV0Q29vcmRzKHsgaWZyYW1lLCBwYXJlbnQ6IG51bGwgfSk7XG5cbiAgICB0aGlzLmNvb3Jkcy51cGRhdGUoaXRlbSA9PiAoe1xuICAgICAgLi4uaXRlbSxcbiAgICAgIHRvcDogY2FyZXRSZWxhdGl2ZVRvVmlldy50b3AgLSBzY3JvbGxUb3AgKyAxMCxcbiAgICAgIGxlZnQ6IGNhcmV0UmVsYXRpdmVUb1ZpZXcubGVmdCAtIHNjcm9sbExlZnQgLSAobGVmdERpdiB8fCAwKSxcbiAgICAgIGJvdHRvbTogY2FyZXRSZWxhdGl2ZVRvVmlldy5ib3R0b21cbiAgICB9KSlcbiAgICB0aGlzLnBvc2l0aW9uRWxlbWVudCgpO1xuICB9XG5cbiAgZ2V0IEFjdGl2ZUl0ZW0oKSB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXMoKVt0aGlzLmFjdGl2ZUluZGV4KCldO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJDbGljayhldmVudDogRXZlbnQsIGluZGV4OiBudW1iZXIpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLmFjdGl2ZUluZGV4LnNldChpbmRleCk7XG4gICAgc2V0KGV2ZW50LCAna2V5Q29kZScsIEtFWV9FTlRFUik7XG4gICAgdGhpcy5wYXJlbnRIYW5kbGVyS2V5RG93bigpPy4oZXZlbnQsIHRoaXMubmF0aXZlUGFyZW50RWxlbWVudCgpKTtcbiAgfVxuXG4gIGFjdGl2YXRlTmV4dEl0ZW0oKSB7XG4gICAgdGhpcy5hY3RpdmVJbmRleC5zZXQodGhpcy5pdGVtcygpLmxlbmd0aCAtIDEgPiB0aGlzLmFjdGl2ZUluZGV4KCkgPyB0aGlzLmFjdGl2ZUluZGV4KCkgKyAxIDogdGhpcy5hY3RpdmVJbmRleCgpKTtcbiAgICB0aGlzLnNjcm9sbFRvQWN0aXZlKCk7XG4gIH1cblxuICBhY3RpdmF0ZVByZXZpb3VzSXRlbSgpIHtcbiAgICB0aGlzLmFjdGl2ZUluZGV4LnNldCh0aGlzLmFjdGl2ZUluZGV4KCkgPiAwID8gdGhpcy5hY3RpdmVJbmRleCgpIC0gMSA6IHRoaXMuYWN0aXZlSW5kZXgoKSk7XG4gICAgdGhpcy5zY3JvbGxUb0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBwb3NpdGlvbkVsZW1lbnQobGVmdDogbnVtYmVyID0gdGhpcy5jb29yZHMoKS5sZWZ0LCB0b3A6IG51bWJlciA9IHRoaXMuY29vcmRzKCkudG9wLCBkcm9wVXA6IGJvb2xlYW4gPSB0aGlzLmRyb3BVcCgpLCBib3R0b206IG51bWJlciA9IHRoaXMuY29vcmRzKCkuYm90dG9tIHx8IDApIHtcbiAgICBjb25zdCBlbCA9IHRoaXMuZWxlbWVudEVsKCk/Lm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICB0b3AgKz0gZHJvcFVwID8gMCA6IHRoaXMub2Zmc2V0KCk7IC8vIHRvcCBvZiBsaXN0IGlzIG5leHQgbGluZVxuICAgIGVsLnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgIGVsLnN0eWxlLmxlZnQgPSBsZWZ0ICsgJ3B4JztcbiAgICBlbC5zdHlsZS50b3AgPSBib3R0b20gIT09IC0xID8gJ2F1dG8nIDogdG9wICsgJ3B4JztcbiAgICBlbC5zdHlsZS5ib3R0b20gPSBib3R0b20gPT09IC0xID8gJ2F1dG8nIDogYm90dG9tICsgJ3B4JztcbiAgICB0aGlzLm5hdGl2ZVBhcmVudEVsZW1lbnQoKT8ubm9ybWFsaXplKCk7XG4gIH1cblxuICBwcml2YXRlIGdldEJsb2NrQ3Vyc29yRGltZW5zaW9ucyhuYXRpdmVQYXJlbnRFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50KSB7XG4gICAgY29uc3QgcGFyZW50U3R5bGVzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUobmF0aXZlUGFyZW50RWxlbWVudCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaGVpZ2h0OiBwYXJzZUZsb2F0KHBhcmVudFN0eWxlcy5saW5lSGVpZ2h0KSxcbiAgICAgIHdpZHRoOiBwYXJzZUZsb2F0KHBhcmVudFN0eWxlcy5mb250U2l6ZSlcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZUFjdGl2ZUl0ZW0oZXZlbnQ6IEV2ZW50LCBpbmRleDogbnVtYmVyKSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5hY3RpdmVJbmRleC5zZXQoaW5kZXgpO1xuICB9XG5cbiAgcHJpdmF0ZSBzY3JvbGxUb0FjdGl2ZSgpIHtcbiAgICBpZiAoIXRoaXMuaXRlbXNFbCgpIHx8ICh0aGlzLml0ZW1zRWwoKS5sZW5ndGggPD0gdGhpcy5hY3RpdmVJbmRleCgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLml0ZW1zRWwoKVt0aGlzLmFjdGl2ZUluZGV4KCldLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSW50b1ZpZXcoKTtcbiAgfVxuXG4gIHNjcm9sbENvbnRlbnQoKSB7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5lbGVtZW50RWwoKTtcbiAgICAgIGlmIChlbGVtZW50ICYmIGVsZW1lbnQubmF0aXZlRWxlbWVudCkge1xuICAgICAgICBlbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gMDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMub25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLm9uRGVzdHJveS5jb21wbGV0ZSgpO1xuICB9XG5cbn1cbiIsIjxkaXYgI2VsZW1lbnRcbiAgY2xhc3M9XCJsaWJzLXVpLW1lbnRpb24tbGlzdFwiXG4gIFtzdHlsZS56SW5kZXhdPVwiekluZGV4KClcIlxuICBbY2xhc3MuaGlkZGVuXT1cImhpZGRlbigpXCI+XG4gIEBmb3IgKGl0ZW0gb2YgaXRlbXMoKTsgdHJhY2sgaXRlbSkge1xuICAgIDxkaXYgI2l0ZW1cbiAgICAgIGNsYXNzPVwibGlicy11aS1tZW50aW9uLWxpc3QtaXRlbVwiXG4gICAgICBbY2xhc3MubGlicy11aS1tZW50aW9uLWxpc3QtaXRlbS1hY3RpdmVdPVwiJGluZGV4ID09PSBhY3RpdmVJbmRleCgpXCJcbiAgICAgIChtb3VzZWRvd24pPVwiaGFuZGxlckNsaWNrKCRldmVudCwgJGluZGV4KVwiXG4gICAgICAobW91c2VlbnRlcik9XCJoYW5kbGVBY3RpdmVJdGVtKCRldmVudCwgJGluZGV4KVwiPlxuICAgICAgPGRpdiBjbGFzcz1cInB4LVsxMnB4XSBweS1bNnB4XSBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWF2YXRhciBbc2l6ZV09XCIyNFwiXG4gICAgICAgICAgW2xpbmtBdmF0YXJdPVwiaXRlbS5hdmF0YXJcIlxuICAgICAgICAgIFtsaW5rQXZhdGFyRXJyb3JdPVwiZGVmYXVsdEF2YXRhcigpXCJcbiAgICAgICAgICBbdGV4dEF2YXRhcl09XCJpdGVtLm5hbWVcIlxuICAgICAgICAgIFtpZEdlbkNvbG9yXT1cIml0ZW0uaWRcIlxuICAgICAgICAgIFtnZXRMYXN0VGV4dEFmdGVyU3BhY2VdPVwidHJ1ZVwiIC8+XG4gICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtcG9wb3ZlciBbY2xhc3NJbmNsdWRlXT1cIidsaWJzLXVpLWZvbnQtaDVyJ1wiXG4gICAgICAgICAgW3R5cGVdPVwiJ3RleHQnXCJcbiAgICAgICAgICBbaWdub3JlU2hvd1BvcG92ZXJdPVwidHJ1ZVwiXG4gICAgICAgICAgW2NvbmZpZ109XCJ7d2lkdGg6IDI1MH1cIj5cbiAgICAgICAgICA8IS0tIC8vIHRhLm0g4bqpbiBzaG93IHRvb2x0aXAgdsOsIGNoxrBhIHjhu60gbMO9IMSRYyB24buLIHRyw60gLS0+XG4gICAgICAgICAge3sgaXRlbS5uYW1lICsgJyAoJyArIGl0ZW0udXNlcm5hbWUgKyAnKScgfX1cbiAgICAgICAgPC9saWJzX3VpLWNvbXBvbmVudHMtcG9wb3Zlcj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICB9XG48L2Rpdj5cbiJdfQ==