@cqa-lib/cqa-ui 1.1.269 → 1.1.271

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.
Files changed (24) hide show
  1. package/esm2020/lib/dashboards/dashboard-header/dashboard-header.component.mjs +38 -19
  2. package/esm2020/lib/dashboards/workspace-selector/workspace-selector.component.mjs +499 -0
  3. package/esm2020/lib/execution-screen/api-step/api-step.component.mjs +31 -1
  4. package/esm2020/lib/execution-screen/basic-step/basic-step.component.mjs +31 -1
  5. package/esm2020/lib/execution-screen/db-verification-step/db-verification-step.component.mjs +31 -1
  6. package/esm2020/lib/execution-screen/live-execution-step/live-execution-step.component.mjs +31 -1
  7. package/esm2020/lib/execution-screen/loop-step/loop-step.component.mjs +31 -1
  8. package/esm2020/lib/ui-kit.module.mjs +6 -1
  9. package/esm2020/public-api.mjs +2 -1
  10. package/fesm2015/cqa-lib-cqa-ui.mjs +738 -42
  11. package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
  12. package/fesm2020/cqa-lib-cqa-ui.mjs +708 -42
  13. package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
  14. package/lib/dashboards/dashboard-header/dashboard-header.component.d.ts +20 -6
  15. package/lib/dashboards/workspace-selector/workspace-selector.component.d.ts +118 -0
  16. package/lib/execution-screen/api-step/api-step.component.d.ts +1 -0
  17. package/lib/execution-screen/basic-step/basic-step.component.d.ts +1 -0
  18. package/lib/execution-screen/db-verification-step/db-verification-step.component.d.ts +1 -0
  19. package/lib/execution-screen/live-execution-step/live-execution-step.component.d.ts +1 -0
  20. package/lib/execution-screen/loop-step/loop-step.component.d.ts +1 -0
  21. package/lib/ui-kit.module.d.ts +130 -129
  22. package/package.json +1 -1
  23. package/public-api.d.ts +1 -0
  24. package/styles.css +1 -1
@@ -0,0 +1,499 @@
1
+ import { ChangeDetectionStrategy, Component, Input, ViewChild, ElementRef, HostListener, Output, EventEmitter } from '@angular/core';
2
+ import { FormGroup, FormControl } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/cdk/scrolling";
5
+ import * as i2 from "@angular/forms";
6
+ import * as i3 from "@angular/common";
7
+ export class WorkspaceSelectorComponent {
8
+ constructor() {
9
+ /** Emits the selected workspace object when selection changes */
10
+ this.valueChange = new EventEmitter();
11
+ this.selectionChange = new EventEmitter();
12
+ this.selectClick = new EventEmitter();
13
+ /** Emits when user types in search box (useful for server search) */
14
+ this.searchChange = new EventEmitter();
15
+ /** Emits when the component requests more data for the current query */
16
+ this.loadMore = new EventEmitter();
17
+ this.searchText = '';
18
+ this.isOpen = false;
19
+ this.loadingMore = false;
20
+ this.lastOptionsLength = 0;
21
+ this.hasScrolledSinceOpen = false;
22
+ this.onPanelScroll = () => {
23
+ this.hasScrolledSinceOpen = true;
24
+ if (!this.config?.hasMore || this.loadingMore)
25
+ return;
26
+ const el = this.panelScrollEl;
27
+ if (!el)
28
+ return;
29
+ const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 48;
30
+ if (nearBottom) {
31
+ this.loadingMore = true;
32
+ const key = this.config?.key || '';
33
+ const q = this.searchText || '';
34
+ this.loadMore.emit({ key, query: q });
35
+ try {
36
+ this.config.onLoadMore?.(q);
37
+ }
38
+ catch { }
39
+ }
40
+ };
41
+ this.trackByOption = (index, opt) => {
42
+ if (!opt)
43
+ return `index-${index}`;
44
+ // Use a simple identifier that doesn't require calling methods
45
+ return opt.id ?? opt.value ?? `option-${index}`;
46
+ };
47
+ this.internalControl = new FormControl();
48
+ this.internalForm = new FormGroup({
49
+ value: this.internalControl
50
+ });
51
+ }
52
+ ngOnInit() {
53
+ if (!this.config) {
54
+ throw new Error('cqa-workspace-selector: input "config" is required.');
55
+ }
56
+ this.syncValueFromInput();
57
+ this.applySelectedValueIfNeeded();
58
+ this.syncDisabledState();
59
+ this.lastOptionsLength = (this.config?.options || []).length;
60
+ }
61
+ ngOnChanges(changes) {
62
+ if ('config' in changes || 'form' in changes || 'value' in changes) {
63
+ this.syncDisabledState();
64
+ }
65
+ if ('value' in changes && !this.form) {
66
+ // Sync internal control when value changes (for direct binding mode)
67
+ this.syncValueFromInput();
68
+ }
69
+ if ('config' in changes) {
70
+ this.syncControlValueForMultipleMode();
71
+ this.applySelectedValueIfNeeded();
72
+ if (this.config?.isLoading !== undefined) {
73
+ this.loadingMore = this.config.isLoading;
74
+ }
75
+ const len = (this.config?.options || []).length;
76
+ if (len > this.lastOptionsLength) {
77
+ if (this.config?.isLoading === false) {
78
+ this.loadingMore = false;
79
+ }
80
+ else if (this.config?.isLoading === undefined) {
81
+ this.loadingMore = false;
82
+ }
83
+ }
84
+ this.lastOptionsLength = len;
85
+ if (!this.config?.hasMore) {
86
+ if (this.config?.isLoading === false) {
87
+ this.loadingMore = false;
88
+ }
89
+ else if (this.config?.isLoading === undefined) {
90
+ this.loadingMore = false;
91
+ }
92
+ }
93
+ }
94
+ if ('form' in changes && !changes['form'].firstChange) {
95
+ this.applySelectedValueIfNeeded();
96
+ }
97
+ }
98
+ syncValueFromInput() {
99
+ if (!this.form && this.value !== undefined) {
100
+ // Sync the internal control with the direct value binding
101
+ // Ensure value is not an array (single selection only)
102
+ if (Array.isArray(this.value)) {
103
+ this.value = this.value.length ? this.value[0] : null;
104
+ }
105
+ this.internalControl.setValue(this.value ?? null, { emitEvent: false });
106
+ }
107
+ }
108
+ get currentForm() {
109
+ return this.form || this.internalForm;
110
+ }
111
+ get controlKey() {
112
+ return this.config?.key || 'value';
113
+ }
114
+ get currentControl() {
115
+ return this.currentForm.get(this.controlKey) || this.internalControl;
116
+ }
117
+ /** Get current value - from form control if form provided, otherwise from direct value binding */
118
+ get currentValue() {
119
+ if (this.form) {
120
+ return this.currentControl.value;
121
+ }
122
+ // Ensure value is not an array (single selection only)
123
+ if (Array.isArray(this.value)) {
124
+ return this.value.length ? this.value[0] : null;
125
+ }
126
+ return this.value ?? null;
127
+ }
128
+ /** Set current value - to form control if form provided, otherwise update direct value */
129
+ set currentValue(val) {
130
+ if (this.form) {
131
+ this.currentControl.setValue(val, { emitEvent: false });
132
+ }
133
+ else {
134
+ // Ensure value is not an array (single selection only)
135
+ this.value = Array.isArray(val) ? (val.length ? val[0] : null) : val;
136
+ // Sync internal control for display purposes
137
+ this.internalControl.setValue(this.value, { emitEvent: false });
138
+ }
139
+ }
140
+ get isDisabled() {
141
+ return this.toBoolean(this.config?.disabled);
142
+ }
143
+ get displayPlaceholder() {
144
+ const currentVal = this.currentValue;
145
+ return this.hasExistingValue(currentVal) ? undefined : (this.config?.placeholder || 'Select...');
146
+ }
147
+ get displayValue() {
148
+ const value = this.currentValue;
149
+ if (value == null)
150
+ return '';
151
+ // If value is already a SelectOption-like object with name/label, use it directly
152
+ if (typeof value === 'object' && value !== null) {
153
+ const workspaceObj = value;
154
+ if (workspaceObj.name || workspaceObj.label) {
155
+ return workspaceObj.name ?? workspaceObj.label ?? String(workspaceObj.value ?? workspaceObj.id ?? '');
156
+ }
157
+ }
158
+ // Otherwise, look up the value in options list
159
+ const option = this.config?.options?.find(opt => this.getOptionValue(opt) === value);
160
+ return option ? this.getOptionLabel(option) : String(value);
161
+ }
162
+ get itemSize() {
163
+ return this.config?.itemSize || 35;
164
+ }
165
+ get viewportHeight() {
166
+ // If viewportHeight is explicitly set in config, use it
167
+ if (this.config?.viewportHeight !== undefined) {
168
+ return this.config.viewportHeight;
169
+ }
170
+ // Otherwise, calculate based on number of options
171
+ const optionCount = this.displayedOptions.length;
172
+ const maxHeight = 300; // Maximum height
173
+ const minHeight = 100; // Minimum height
174
+ const calculatedHeight = optionCount * this.itemSize;
175
+ // Return calculated height, but clamp between min and max
176
+ return Math.min(Math.max(calculatedHeight, minHeight), maxHeight);
177
+ }
178
+ get displayedOptions() {
179
+ return this.filteredOptions();
180
+ }
181
+ toBoolean(value) {
182
+ if (typeof value === 'string') {
183
+ const v = value.trim().toLowerCase();
184
+ if (v === 'true' || v === '1')
185
+ return true;
186
+ if (v === 'false' || v === '0' || v === '')
187
+ return false;
188
+ return true;
189
+ }
190
+ if (typeof value === 'number') {
191
+ return value !== 0;
192
+ }
193
+ return !!value;
194
+ }
195
+ getOptionValue(opt) {
196
+ if (!opt)
197
+ return undefined;
198
+ if (this.config?.valueBy) {
199
+ return opt[this.config.valueBy];
200
+ }
201
+ return opt.id ?? opt.value;
202
+ }
203
+ getOptionLabel(opt) {
204
+ return opt.name ?? opt.label ?? opt.value ?? '';
205
+ }
206
+ syncDisabledState() {
207
+ const shouldDisable = this.toBoolean(this.config?.disabled);
208
+ if (this.form) {
209
+ if (shouldDisable) {
210
+ this.currentControl.disable({ emitEvent: false });
211
+ }
212
+ else {
213
+ this.currentControl.enable({ emitEvent: false });
214
+ }
215
+ }
216
+ // For direct value binding, disabled state is handled via [disabled] binding in template
217
+ }
218
+ syncControlValueForMultipleMode() {
219
+ // No longer needed - single selection only
220
+ const currentVal = this.currentValue;
221
+ if (Array.isArray(currentVal)) {
222
+ this.currentValue = currentVal.length ? currentVal[0] : null;
223
+ }
224
+ }
225
+ applySelectedValueIfNeeded() {
226
+ const currentVal = this.currentValue;
227
+ if (this.hasExistingValue(currentVal)) {
228
+ return;
229
+ }
230
+ // Check both config.selectedValue and direct value input
231
+ const selectedValue = this.value !== undefined ? this.value : this.config?.selectedValue;
232
+ if (selectedValue === undefined || selectedValue === null) {
233
+ return;
234
+ }
235
+ // Ensure selectedValue is not an array (single selection only)
236
+ const normalized = Array.isArray(selectedValue)
237
+ ? (selectedValue.length ? selectedValue[0] : undefined)
238
+ : selectedValue;
239
+ if (normalized === undefined)
240
+ return;
241
+ this.currentValue = normalized;
242
+ }
243
+ hasExistingValue(value) {
244
+ if (value === null || value === undefined) {
245
+ return false;
246
+ }
247
+ if (Array.isArray(value)) {
248
+ return value.some((val) => val !== null && val !== undefined && val !== '');
249
+ }
250
+ if (typeof value === 'string') {
251
+ return value.trim().length > 0;
252
+ }
253
+ return true;
254
+ }
255
+ isOptionSelected(opt) {
256
+ const currentVal = this.currentValue;
257
+ if (currentVal == null)
258
+ return false;
259
+ const optionValue = this.getOptionValue(opt);
260
+ // If currentVal is an object with id/value, extract it for comparison
261
+ if (typeof currentVal === 'object' && currentVal !== null) {
262
+ const workspaceObj = currentVal;
263
+ const currentId = this.config?.valueBy
264
+ ? workspaceObj[this.config.valueBy]
265
+ : (workspaceObj.id ?? workspaceObj.value);
266
+ return currentId === optionValue;
267
+ }
268
+ // Otherwise, compare directly
269
+ return currentVal === optionValue;
270
+ }
271
+ filteredOptions() {
272
+ const t = this.searchText.toLowerCase().trim();
273
+ const allOptions = this.config.options || [];
274
+ if (this.config?.serverSearch) {
275
+ // For server search, return all options as-is (server handles filtering)
276
+ return allOptions;
277
+ }
278
+ if (!t) {
279
+ // No search - return all options
280
+ return allOptions;
281
+ }
282
+ // Local search - filter options by search text only
283
+ return allOptions.filter((opt) => {
284
+ const text = this.getOptionLabel(opt).toLowerCase();
285
+ return text.includes(t);
286
+ });
287
+ }
288
+ getSelectedIds() {
289
+ const value = this.currentValue;
290
+ return value !== undefined && value !== null ? [value] : [];
291
+ }
292
+ onOptionClick(opt) {
293
+ if (this.isDisabled)
294
+ return;
295
+ // Emit the full option object (with name, id, etc.) instead of just the value
296
+ // This allows the parent to receive the complete workspace object
297
+ const newValue = opt;
298
+ const selectedOption = opt;
299
+ // Close dropdown after selection (unless closeOnSelect is false)
300
+ if (this.config?.closeOnSelect !== false) {
301
+ this.closeDropdown();
302
+ }
303
+ // Update value
304
+ if (this.form) {
305
+ this.currentControl.setValue(newValue, { emitEvent: true });
306
+ }
307
+ else {
308
+ this.value = newValue;
309
+ this.syncValueFromInput();
310
+ }
311
+ this.onSelectionChange(newValue, selectedOption);
312
+ }
313
+ onSelectionChange(newValue, selectedOption) {
314
+ const value = newValue !== undefined ? newValue : this.currentValue;
315
+ // Emit valueChange for two-way binding
316
+ this.valueChange.emit(value);
317
+ if (typeof this.config?.onChange === 'function') {
318
+ try {
319
+ this.config.onChange(value);
320
+ }
321
+ catch (error) {
322
+ console.error('cqa-workspace-selector onChange handler error:', error);
323
+ }
324
+ }
325
+ this.selectionChange.emit({
326
+ key: this.config?.key || '',
327
+ value,
328
+ option: selectedOption,
329
+ });
330
+ }
331
+ onSearchInput(value) {
332
+ this.searchText = value ?? '';
333
+ if (this.config?.serverSearch) {
334
+ try {
335
+ this.config.onSearch?.(value ?? '');
336
+ }
337
+ catch { }
338
+ this.searchChange.emit({ key: this.config?.key || '', query: value ?? '' });
339
+ this.loadingMore = false;
340
+ this.lastOptionsLength = (this.config?.options || []).length;
341
+ }
342
+ }
343
+ toggleDropdown() {
344
+ if (this.isDisabled)
345
+ return;
346
+ if (this.isOpen) {
347
+ this.closeDropdown();
348
+ }
349
+ else {
350
+ this.openDropdown();
351
+ }
352
+ }
353
+ openDropdown() {
354
+ if (this.isDisabled)
355
+ return;
356
+ this.isOpen = true;
357
+ this.selectClick.emit();
358
+ this.hasScrolledSinceOpen = false;
359
+ if ((this.config?.options || []).length > 0) {
360
+ this.loadingMore = false;
361
+ }
362
+ if (this.config?.serverSearch && this.toBoolean(this.config?.initialFetchOnOpen)) {
363
+ const q = this.searchText || '';
364
+ try {
365
+ this.config.onSearch?.(q);
366
+ }
367
+ catch { }
368
+ this.searchChange.emit({ key: this.config?.key || '', query: q });
369
+ }
370
+ setTimeout(() => {
371
+ this.setupScrollListener();
372
+ if (this.config?.searchable) {
373
+ const input = this.dropdownPanel?.nativeElement?.querySelector('.workspace-search-input');
374
+ input?.focus();
375
+ }
376
+ }, 0);
377
+ }
378
+ closeDropdown() {
379
+ this.isOpen = false;
380
+ this.searchText = '';
381
+ if (this.panelScrollEl) {
382
+ try {
383
+ this.panelScrollEl.removeEventListener('scroll', this.onPanelScroll);
384
+ }
385
+ catch { }
386
+ this.panelScrollEl = undefined;
387
+ }
388
+ this.loadingMore = false;
389
+ }
390
+ setupScrollListener() {
391
+ if (!this.config?.hasMore)
392
+ return;
393
+ const panel = this.dropdownPanel?.nativeElement?.querySelector('.workspace-options-container');
394
+ if (panel) {
395
+ this.panelScrollEl = panel;
396
+ panel.addEventListener('scroll', this.onPanelScroll, { passive: true });
397
+ }
398
+ }
399
+ onScrolledIndexChange(index) {
400
+ this.hasScrolledSinceOpen = true;
401
+ if (!this.config?.hasMore || this.loadingMore)
402
+ return;
403
+ const viewport = this.viewport?.elementRef?.nativeElement;
404
+ if (!viewport)
405
+ return;
406
+ const itemCount = this.displayedOptions.length;
407
+ const visibleItems = Math.ceil(viewport.clientHeight / this.itemSize);
408
+ if (index + visibleItems >= itemCount - 1) {
409
+ this.loadingMore = true;
410
+ const key = this.config?.key || '';
411
+ const q = this.searchText || '';
412
+ this.loadMore.emit({ key, query: q });
413
+ try {
414
+ this.config.onLoadMore?.(q);
415
+ }
416
+ catch { }
417
+ }
418
+ }
419
+ highlightText(text) {
420
+ if (!text || !this.config?.highlightPattern) {
421
+ return this.escapeHtml(text);
422
+ }
423
+ const pattern = this.config.highlightPattern;
424
+ if (typeof pattern === 'function') {
425
+ return pattern(text);
426
+ }
427
+ let regex;
428
+ if (typeof pattern === 'string') {
429
+ try {
430
+ regex = new RegExp(pattern, 'gi');
431
+ }
432
+ catch (e) {
433
+ console.warn('Invalid highlight pattern:', pattern);
434
+ return this.escapeHtml(text);
435
+ }
436
+ }
437
+ else {
438
+ regex = pattern;
439
+ }
440
+ const escaped = this.escapeHtml(text);
441
+ return escaped.replace(regex, (match) => `<span class="cqa-text-primary">${match}</span>`);
442
+ }
443
+ escapeHtml(text) {
444
+ if (!text)
445
+ return '';
446
+ const div = document.createElement('div');
447
+ div.textContent = text;
448
+ return div.innerHTML;
449
+ }
450
+ get hasHighlighting() {
451
+ return !!this.config?.highlightPattern;
452
+ }
453
+ handleDocumentClick(event) {
454
+ if (!this.isOpen)
455
+ return;
456
+ const target = event.target;
457
+ if (!target)
458
+ return;
459
+ if (this.hostEl?.nativeElement && this.hostEl.nativeElement.contains(target)) {
460
+ return;
461
+ }
462
+ this.closeDropdown();
463
+ }
464
+ }
465
+ WorkspaceSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: WorkspaceSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
466
+ WorkspaceSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: WorkspaceSelectorComponent, selector: "cqa-workspace-selector", inputs: { form: "form", config: "config", value: "value" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, host: { listeners: { "document:click": "handleDocumentClick($event)" }, classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }, { propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }, { propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" #host>\n <ng-container [formGroup]=\"currentForm\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n \n <div class=\"workspace-selector-wrapper cqa-relative cqa-w-full\">\n <!-- Trigger Button -->\n <button\n type=\"button\"\n class=\"workspace-selector-trigger cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-px-4 cqa-py-2 cqa-border-solid cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-bg-white cqa-text-left cqa-cursor-pointer hover:cqa-border-[#9CA3AF] focus:cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#4F46E5] focus:cqa-ring-offset-1 disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"isDisabled\"\n (click)=\"toggleDropdown()\"\n [attr.aria-expanded]=\"isOpen\"\n aria-haspopup=\"listbox\">\n <span class=\"cqa-flex-1 cqa-truncate cqa-text-[14px] cqa-text-[#0A0A0A]\"\n [class.cqa-text-[#9CA3AF]]=\"!displayValue\">\n {{ displayValue || displayPlaceholder }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-shrink-0\">\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-animate-spin\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n [class.cqa-rotate-180]=\"isOpen\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Panel -->\n <div\n #dropdownPanel\n *ngIf=\"isOpen\"\n class=\"workspace-selector-panel cqa-absolute cqa-z-50 cqa-w-full cqa-mt-1 cqa-bg-white cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-shadow-lg cqa-overflow-hidden\">\n \n <!-- Search Input -->\n <div *ngIf=\"config.searchable\" class=\"workspace-search-container cqa-p-2 cqa-border-b cqa-border-[#E5E7EB]\">\n <input\n type=\"text\"\n class=\"workspace-search-input cqa-w-full cqa-px-3 cqa-py-2 cqa-border cqa-border-[#D1D5DB] cqa-rounded-[6px] cqa-text-[14px] cqa-text-[#0A0A0A] focus:cqa-outline-none\"\n placeholder=\"Search...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" />\n </div>\n\n <!-- Options Container with Virtual Scroll -->\n <div class=\"workspace-options-container\">\n <!-- No results state -->\n <div *ngIf=\"displayedOptions.length === 0 && !(config?.isLoading || loadingMore)\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#9CA3AF] cqa-text-center\">\n No results\n </div>\n\n <cdk-virtual-scroll-viewport\n *ngIf=\"displayedOptions.length > 0\"\n #viewport\n [itemSize]=\"itemSize\"\n minBufferPx=\"200\"\n maxBufferPx=\"400\"\n [style.height.px]=\"viewportHeight\"\n style=\"width: 100%; display: block; overflow: auto;\"\n (scrolledIndexChange)=\"onScrolledIndexChange($event)\">\n \n <div\n *cdkVirtualFor=\"let opt of displayedOptions; trackBy: trackByOption\"\n class=\"workspace-option cqa-px-4 cqa-py-3 cqa-cursor-pointer hover:cqa-bg-[#F3F4F6] cqa-border-b cqa-border-[#E5E7EB] last:cqa-border-b-0\"\n [style.height.px]=\"itemSize\"\n [style.display]=\"'flex'\"\n [style.align-items]=\"'center'\"\n [class.cqa-bg-[#F3F4F6]]=\"isOptionSelected(opt)\"\n [class.cqa-bg-[#EEF2FF]]=\"isOptionSelected(opt)\"\n (click)=\"onOptionClick(opt)\">\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"hasHighlighting\"\n [innerHTML]=\"highlightText(getOptionLabel(opt))\"></span>\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"!hasHighlighting\">\n {{ getOptionLabel(opt) }}\n </span>\n </div>\n </cdk-virtual-scroll-viewport>\n\n <!-- Loading more indicator -->\n <div *ngIf=\"config?.hasMore && (loadingMore || config?.isLoading) && displayedOptions.length > 0\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#6B7280] cqa-text-center cqa-border-t cqa-border-[#E5E7EB]\">\n Loading...\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</div>\n\n", components: [{ type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], directives: [{ type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
467
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: WorkspaceSelectorComponent, decorators: [{
468
+ type: Component,
469
+ args: [{ selector: 'cqa-workspace-selector', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-ui-root\" #host>\n <ng-container [formGroup]=\"currentForm\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n \n <div class=\"workspace-selector-wrapper cqa-relative cqa-w-full\">\n <!-- Trigger Button -->\n <button\n type=\"button\"\n class=\"workspace-selector-trigger cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-px-4 cqa-py-2 cqa-border-solid cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-bg-white cqa-text-left cqa-cursor-pointer hover:cqa-border-[#9CA3AF] focus:cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#4F46E5] focus:cqa-ring-offset-1 disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"isDisabled\"\n (click)=\"toggleDropdown()\"\n [attr.aria-expanded]=\"isOpen\"\n aria-haspopup=\"listbox\">\n <span class=\"cqa-flex-1 cqa-truncate cqa-text-[14px] cqa-text-[#0A0A0A]\"\n [class.cqa-text-[#9CA3AF]]=\"!displayValue\">\n {{ displayValue || displayPlaceholder }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-shrink-0\">\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-animate-spin\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n [class.cqa-rotate-180]=\"isOpen\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Panel -->\n <div\n #dropdownPanel\n *ngIf=\"isOpen\"\n class=\"workspace-selector-panel cqa-absolute cqa-z-50 cqa-w-full cqa-mt-1 cqa-bg-white cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-shadow-lg cqa-overflow-hidden\">\n \n <!-- Search Input -->\n <div *ngIf=\"config.searchable\" class=\"workspace-search-container cqa-p-2 cqa-border-b cqa-border-[#E5E7EB]\">\n <input\n type=\"text\"\n class=\"workspace-search-input cqa-w-full cqa-px-3 cqa-py-2 cqa-border cqa-border-[#D1D5DB] cqa-rounded-[6px] cqa-text-[14px] cqa-text-[#0A0A0A] focus:cqa-outline-none\"\n placeholder=\"Search...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" />\n </div>\n\n <!-- Options Container with Virtual Scroll -->\n <div class=\"workspace-options-container\">\n <!-- No results state -->\n <div *ngIf=\"displayedOptions.length === 0 && !(config?.isLoading || loadingMore)\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#9CA3AF] cqa-text-center\">\n No results\n </div>\n\n <cdk-virtual-scroll-viewport\n *ngIf=\"displayedOptions.length > 0\"\n #viewport\n [itemSize]=\"itemSize\"\n minBufferPx=\"200\"\n maxBufferPx=\"400\"\n [style.height.px]=\"viewportHeight\"\n style=\"width: 100%; display: block; overflow: auto;\"\n (scrolledIndexChange)=\"onScrolledIndexChange($event)\">\n \n <div\n *cdkVirtualFor=\"let opt of displayedOptions; trackBy: trackByOption\"\n class=\"workspace-option cqa-px-4 cqa-py-3 cqa-cursor-pointer hover:cqa-bg-[#F3F4F6] cqa-border-b cqa-border-[#E5E7EB] last:cqa-border-b-0\"\n [style.height.px]=\"itemSize\"\n [style.display]=\"'flex'\"\n [style.align-items]=\"'center'\"\n [class.cqa-bg-[#F3F4F6]]=\"isOptionSelected(opt)\"\n [class.cqa-bg-[#EEF2FF]]=\"isOptionSelected(opt)\"\n (click)=\"onOptionClick(opt)\">\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"hasHighlighting\"\n [innerHTML]=\"highlightText(getOptionLabel(opt))\"></span>\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"!hasHighlighting\">\n {{ getOptionLabel(opt) }}\n </span>\n </div>\n </cdk-virtual-scroll-viewport>\n\n <!-- Loading more indicator -->\n <div *ngIf=\"config?.hasMore && (loadingMore || config?.isLoading) && displayedOptions.length > 0\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#6B7280] cqa-text-center cqa-border-t cqa-border-[#E5E7EB]\">\n Loading...\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</div>\n\n" }]
470
+ }], ctorParameters: function () { return []; }, propDecorators: { form: [{
471
+ type: Input
472
+ }], config: [{
473
+ type: Input
474
+ }], value: [{
475
+ type: Input
476
+ }], valueChange: [{
477
+ type: Output
478
+ }], selectionChange: [{
479
+ type: Output
480
+ }], selectClick: [{
481
+ type: Output
482
+ }], searchChange: [{
483
+ type: Output
484
+ }], loadMore: [{
485
+ type: Output
486
+ }], hostEl: [{
487
+ type: ViewChild,
488
+ args: ['host', { static: false, read: ElementRef }]
489
+ }], dropdownPanel: [{
490
+ type: ViewChild,
491
+ args: ['dropdownPanel', { static: false }]
492
+ }], viewport: [{
493
+ type: ViewChild,
494
+ args: ['viewport', { static: false }]
495
+ }], handleDocumentClick: [{
496
+ type: HostListener,
497
+ args: ['document:click', ['$event']]
498
+ }] } });
499
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZGFzaGJvYXJkcy93b3Jrc3BhY2Utc2VsZWN0b3Ivd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZGFzaGJvYXJkcy93b3Jrc3BhY2Utc2VsZWN0b3Ivd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFvQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZLLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBOEN4RCxNQUFNLE9BQU8sMEJBQTBCO0lBNENyQztRQXZDQSxpRUFBaUU7UUFDdkQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ3RDLG9CQUFlLEdBQUcsSUFBSSxZQUFZLEVBQXNELENBQUM7UUFDekYsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ2pELHFFQUFxRTtRQUMzRCxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFrQyxDQUFDO1FBQzVFLHdFQUF3RTtRQUM5RCxhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQWtDLENBQUM7UUFVeEUsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUN4QixXQUFNLEdBQVksS0FBSyxDQUFDO1FBQ3hCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ1osc0JBQWlCLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLHlCQUFvQixHQUFHLEtBQUssQ0FBQztRQUc3QixrQkFBYSxHQUFHLEdBQUcsRUFBRTtZQUMzQixJQUFJLENBQUMsb0JBQW9CLEdB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LFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsUUFBUTtzQkFBakIsTUFBTTtnQkFFaUQsTUFBTTtzQkFBN0QsU0FBUzt1QkFBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBQ1AsYUFBYTtzQkFBM0QsU0FBUzt1QkFBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUNILFFBQVE7c0JBQWpELFNBQVM7dUJBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFvZHhDLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkLCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgU2VsZWN0T3B0aW9uIH0gZnJvbSAnLi4vLi4vZHluYW1pYy1zZWxlY3QvZHluYW1pYy1zZWxlY3QtZmllbGQuY29tcG9uZW50JztcblxuZXhwb3J0IGludGVyZmFjZSBXb3Jrc3BhY2VTZWxlY3RvckNvbmZpZyB7XG4gIGtleT86IHN0cmluZztcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICBkaXNhYmxlZD86IGJvb2xlYW47XG4gIHNlYXJjaGFibGU/OiBib29sZWFuO1xuICAvKiogSWYgdHJ1ZSwgY2xvc2UgdGhlIHBhbmVsIHdoZW4gYW4gb3B0aW9uIGlzIHNlbGVjdGVkLiAqL1xuICBjbG9zZU9uU2VsZWN0PzogYm9vbGVhbjtcbiAgLyoqIFByb3ZpZGUgYSBkZWZhdWx0IHNlbGVjdGVkIHZhbHVlIGlmIHRoZSBjb250cm9sIGhhcyBubyB2YWx1ZSB5ZXQuICovXG4gIHNlbGVjdGVkVmFsdWU/OiBhbnk7XG4gIC8qKiBPcHRpb25hbCBjYWxsYmFjayBpbnZva2VkIHdoZW5ldmVyIHRoZSBzZWxlY3Rpb24gY2hhbmdlcy4gKi9cbiAgb25DaGFuZ2U/OiAodmFsdWU6IGFueSkgPT4gdm9pZDtcbiAgLyoqIEVuYWJsZSBzZXJ2ZXItc2lkZSBzZWFyY2ggbW9kZTsgY29tcG9uZW50IHdpbGwgZW1pdCBzZWFyY2ggaW5zdGVhZCBvZiBsb2NhbCBmaWx0ZXJpbmcuICovXG4gIHNlcnZlclNlYXJjaD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGVuIHRydWUsIHRyaWdnZXJzIGFuIGluaXRpYWwgc2VhcmNoIGVtaXQgb24gcGFuZWwgb3BlbiAoc2VydmVyU2VhcmNoIG1vZGUgb25seSkuXG4gICAqIERlZmF1bHRzIHRvIGZhbHNlIHNvIG9wZW5pbmcgdGhlIGRyb3Bkb3duIGRvZXMgTk9UIGNhbGwgdGhlIEFQSS5cbiAgICovXG4gIGluaXRpYWxGZXRjaE9uT3Blbj86IGJvb2xlYW47XG4gIC8qKiBJbmRpY2F0ZXMgbW9yZSByZXN1bHRzIGFyZSBhdmFpbGFibGUgZm9yIGluZmluaXRlIHNjcm9sbC4gKi9cbiAgaGFzTW9yZT86IGJvb2xlYW47XG4gIC8qKiBPcHRpb25hbCBsb2FkaW5nIGZsYWcgY29udHJvbGxlZCBieSBjb25zdW1lciB0byBzaG93IGxvYWRpbmcgc3RhdGUuICovXG4gIGlzTG9hZGluZz86IGJvb2xlYW47XG4gIC8qKiBPcHRpb25hbCBjYWxsYmFjayBmb3Igc2VydmVyLXNpZGUgc2VhcmNoIHdoZW4gcXVlcnkgY2hhbmdlcy4gKi9cbiAgb25TZWFyY2g/OiAocXVlcnk6IHN0cmluZykgPT4gdm9pZDtcbiAgLyoqIE9wdGlvbmFsIGNhbGxiYWNrIHdoZW4gbW9yZSBkYXRhIGlzIHJlcXVlc3RlZCAoaW5maW5pdGUgc2Nyb2xsKS4gKi9cbiAgb25Mb2FkTW9yZT86IChxdWVyeT86IHN0cmluZykgPT4gdm9pZDtcbiAgLyoqIE9wdGlvbmFsIHJlZ2V4IHBhdHRlcm4gb3IgZnVuY3Rpb24gdG8gaGlnaGxpZ2h0IHBhcnRzIG9mIG9wdGlvbiB0ZXh0LiAqL1xuICBoaWdobGlnaHRQYXR0ZXJuPzogUmVnRXhwIHwgc3RyaW5nIHwgKCh0ZXh0OiBzdHJpbmcpID0+IHN0cmluZyk7XG4gIG9wdGlvbnM6IFNlbGVjdE9wdGlvbltdO1xuICB2YWx1ZUJ5Pzogc3RyaW5nO1xuICAvKiogSXRlbSBzaXplIGZvciB2aXJ0dWFsIHNjcm9sbCAoZGVmYXVsdDogNDgpICovXG4gIGl0ZW1TaXplPzogbnVtYmVyO1xuICAvKiogVmlld3BvcnQgaGVpZ2h0IGZvciB2aXJ0dWFsIHNjcm9sbCBpbiBwaXhlbHMgKGRlZmF1bHQ6IDMwMCkgKi9cbiAgdmlld3BvcnRIZWlnaHQ/OiBudW1iZXI7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NxYS13b3Jrc3BhY2Utc2VsZWN0b3InLFxuICB0ZW1wbGF0ZVVybDogJy4vd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHsgY2xhc3M6ICdjcWEtdWktcm9vdCcgfVxufSlcbmV4cG9ydCBjbGFzcyBXb3Jrc3BhY2VTZWxlY3RvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgZm9ybT86IEZvcm1Hcm91cDtcbiAgQElucHV0KCkgY29uZmlnITogV29ya3NwYWNlU2VsZWN0b3JDb25maWc7XG4gIC8qKiBEaXJlY3QgdmFsdWUgYmluZGluZyAtIHNlbGVjdGVkIHdvcmtzcGFjZSBvYmplY3QuIFVzZSB0aGlzIGluc3RlYWQgb2YgZm9ybSBjb250cm9sLiAqL1xuICBASW5wdXQoKSB2YWx1ZT86IGFueTtcbiAgLyoqIEVtaXRzIHRoZSBzZWxlY3RlZCB3b3Jrc3BhY2Ugb2JqZWN0IHdoZW4gc2VsZWN0aW9uIGNoYW5nZXMgKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBzZWxlY3Rpb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHsga2V5OiBzdHJpbmc7IHZhbHVlOiBhbnk7IG9wdGlvbj86IFNlbGVjdE9wdGlvbiB9PigpO1xuICBAT3V0cHV0KCkgc2VsZWN0Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHVzZXIgdHlwZXMgaW4gc2VhcmNoIGJveCAodXNlZnVsIGZvciBzZXJ2ZXIgc2VhcmNoKSAqL1xuICBAT3V0cHV0KCkgc2VhcmNoQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7IGtleTogc3RyaW5nOyBxdWVyeTogc3RyaW5nIH0+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHRoZSBjb21wb25lbnQgcmVxdWVzdHMgbW9yZSBkYXRhIGZvciB0aGUgY3VycmVudCBxdWVyeSAqL1xuICBAT3V0cHV0KCkgbG9hZE1vcmUgPSBuZXcgRXZlbnRFbWl0dGVyPHsga2V5OiBzdHJpbmc7IHF1ZXJ5OiBzdHJpbmcgfT4oKTtcblxuICBAVmlld0NoaWxkKCdob3N0JywgeyBzdGF0aWM6IGZhbHNlLCByZWFkOiBFbGVtZW50UmVmIH0pIGhvc3RFbD86IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCdkcm9wZG93blBhbmVsJywgeyBzdGF0aWM6IGZhbHNlIH0pIGRyb3Bkb3duUGFuZWw/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgndmlld3BvcnQnLCB7IHN0YXRpYzogZmFsc2UgfSkgdmlld3BvcnQ/OiBhbnk7XG5cbiAgLy8gSW50ZXJuYWwgZm9ybSBjb250cm9sIGlmIG5vIGZvcm0gaXMgcHJvdmlkZWRcbiAgaW50ZXJuYWxGb3JtOiBGb3JtR3JvdXA7XG4gIGludGVybmFsQ29udHJvbDogRm9ybUNvbnRyb2w7XG5cbiAgc2VhcmNoVGV4dDogc3RyaW5nID0gJyc7XG4gIGlzT3BlbjogYm9vbGVhbiA9IGZhbHNlO1xuICBsb2FkaW5nTW9yZSA9IGZhbHNlO1xuICBwcml2YXRlIGxhc3RPcHRpb25zTGVuZ3RoID0gMDtcbiAgcHJpdmF0ZSBoYXNTY3JvbGxlZFNpbmNlT3BlbiA9IGZhbHNlO1xuICBwcml2YXRlIHBhbmVsU2Nyb2xsRWw/OiBIVE1MRWxlbWVudDtcblxuICBwcml2YXRlIG9uUGFuZWxTY3JvbGwgPSAoKSA9PiB7XG4gICAgdGhpcy5oYXNTY3JvbGxlZFNpbmNlT3BlbiA9IHRydWU7XG4gICAgaWYgKCF0aGlzLmNvbmZpZz8uaGFzTW9yZSB8fCB0aGlzLmxvYWRpbmdNb3JlKSByZXR1cm47XG4gICAgY29uc3QgZWwgPSB0aGlzLnBhbmVsU2Nyb2xsRWw7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuICAgIGNvbnN0IG5lYXJCb3R0b20gPSBlbC5zY3JvbGxUb3AgKyBlbC5jbGllbnRIZWlnaHQgPj0gZWwuc2Nyb2xsSGVpZ2h0IC0gNDg7XG4gICAgaWYgKG5lYXJCb3R0b20pIHtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSB0cnVlO1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5jb25maWc/LmtleSB8fCAnJztcbiAgICAgIGNvbnN0IHEgPSB0aGlzLnNlYXJjaFRleHQgfHwgJyc7XG4gICAgICB0aGlzLmxvYWRNb3JlLmVtaXQoeyBrZXksIHF1ZXJ5OiBxIH0pO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25Mb2FkTW9yZT8uKHEpOyB9IGNhdGNoIHt9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuaW50ZXJuYWxDb250cm9sID0gbmV3IEZvcm1Db250cm9sKCk7XG4gICAgdGhpcy5pbnRlcm5hbEZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgIHZhbHVlOiB0aGlzLmludGVybmFsQ29udHJvbFxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjcWEtd29ya3NwYWNlLXNlbGVjdG9yOiBpbnB1dCBcImNvbmZpZ1wiIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cbiAgICB0aGlzLnN5bmNWYWx1ZUZyb21JbnB1dCgpO1xuICAgIHRoaXMuYXBwbHlTZWxlY3RlZFZhbHVlSWZOZWVkZWQoKTtcbiAgICB0aGlzLnN5bmNEaXNhYmxlZFN0YXRlKCk7XG4gICAgdGhpcy5sYXN0T3B0aW9uc0xlbmd0aCA9ICh0aGlzLmNvbmZpZz8ub3B0aW9ucyB8fCBbXSkubGVuZ3RoO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmICgnY29uZmlnJyBpbiBjaGFuZ2VzIHx8ICdmb3JtJyBpbiBjaGFuZ2VzIHx8ICd2YWx1ZScgaW4gY2hhbmdlcykge1xuICAgICAgdGhpcy5zeW5jRGlzYWJsZWRTdGF0ZSgpO1xuICAgIH1cbiAgICBpZiAoJ3ZhbHVlJyBpbiBjaGFuZ2VzICYmICF0aGlzLmZvcm0pIHtcbiAgICAgIC8vIFN5bmMgaW50ZXJuYWwgY29udHJvbCB3aGVuIHZhbHVlIGNoYW5nZXMgKGZvciBkaXJlY3QgYmluZGluZyBtb2RlKVxuICAgICAgdGhpcy5zeW5jVmFsdWVGcm9tSW5wdXQoKTtcbiAgICB9XG4gICAgaWYgKCdjb25maWcnIGluIGNoYW5nZXMpIHtcbiAgICAgIHRoaXMuc3luY0NvbnRyb2xWYWx1ZUZvck11bHRpcGxlTW9kZSgpO1xuICAgICAgdGhpcy5hcHBseVNlbGVjdGVkVmFsdWVJZk5lZWRlZCgpO1xuICAgICAgaWYgKHRoaXMuY29uZmlnPy5pc0xvYWRpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gdGhpcy5jb25maWcuaXNMb2FkaW5nO1xuICAgICAgfVxuICAgICAgY29uc3QgbGVuID0gKHRoaXMuY29uZmlnPy5vcHRpb25zIHx8IFtdKS5sZW5ndGg7XG4gICAgICBpZiAobGVuID4gdGhpcy5sYXN0T3B0aW9uc0xlbmd0aCkge1xuICAgICAgICBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmxhc3RPcHRpb25zTGVuZ3RoID0gbGVuO1xuICAgICAgaWYgKCF0aGlzLmNvbmZpZz8uaGFzTW9yZSkge1xuICAgICAgICBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgnZm9ybScgaW4gY2hhbmdlcyAmJiAhY2hhbmdlc1snZm9ybSddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICB0aGlzLmFwcGx5U2VsZWN0ZWRWYWx1ZUlmTmVlZGVkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzeW5jVmFsdWVGcm9tSW5wdXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmZvcm0gJiYgdGhpcy52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBTeW5jIHRoZSBpbnRlcm5hbCBjb250cm9sIHdpdGggdGhlIGRpcmVjdCB2YWx1ZSBiaW5kaW5nXG4gICAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLnZhbHVlKSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS5sZW5ndGggPyB0aGlzLnZhbHVlWzBdIDogbnVsbDtcbiAgICAgIH1cbiAgICAgIHRoaXMuaW50ZXJuYWxDb250cm9sLnNldFZhbHVlKHRoaXMudmFsdWUgPz8gbnVsbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBjdXJyZW50Rm9ybSgpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmZvcm0gfHwgdGhpcy5pbnRlcm5hbEZvcm07XG4gIH1cblxuICBnZXQgY29udHJvbEtleSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZz8ua2V5IHx8ICd2YWx1ZSc7XG4gIH1cblxuICBnZXQgY3VycmVudENvbnRyb2woKTogRm9ybUNvbnRyb2wge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRGb3JtLmdldCh0aGlzLmNvbnRyb2xLZXkpIGFzIEZvcm1Db250cm9sIHx8IHRoaXMuaW50ZXJuYWxDb250cm9sO1xuICB9XG5cbiAgLyoqIEdldCBjdXJyZW50IHZhbHVlIC0gZnJvbSBmb3JtIGNvbnRyb2wgaWYgZm9ybSBwcm92aWRlZCwgb3RoZXJ3aXNlIGZyb20gZGlyZWN0IHZhbHVlIGJpbmRpbmcgKi9cbiAgZ2V0IGN1cnJlbnRWYWx1ZSgpOiBhbnkge1xuICAgIGlmICh0aGlzLmZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRDb250cm9sLnZhbHVlO1xuICAgIH1cbiAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy52YWx1ZSkpIHtcbiAgICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aCA/IHRoaXMudmFsdWVbMF0gOiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZSA/PyBudWxsO1xuICB9XG5cbiAgLyoqIFNldCBjdXJyZW50IHZhbHVlIC0gdG8gZm9ybSBjb250cm9sIGlmIGZvcm0gcHJvdmlkZWQsIG90aGVyd2lzZSB1cGRhdGUgZGlyZWN0IHZhbHVlICovXG4gIHNldCBjdXJyZW50VmFsdWUodmFsOiBhbnkpIHtcbiAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICB0aGlzLmN1cnJlbnRDb250cm9sLnNldFZhbHVlKHZhbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgICB0aGlzLnZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWwpID8gKHZhbC5sZW5ndGggPyB2YWxbMF0gOiBudWxsKSA6IHZhbDtcbiAgICAgIC8vIFN5bmMgaW50ZXJuYWwgY29udHJvbCBmb3IgZGlzcGxheSBwdXJwb3Nlc1xuICAgICAgdGhpcy5pbnRlcm5hbENvbnRyb2wuc2V0VmFsdWUodGhpcy52YWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc0Rpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRvQm9vbGVhbih0aGlzLmNvbmZpZz8uZGlzYWJsZWQpO1xuICB9XG5cbiAgZ2V0IGRpc3BsYXlQbGFjZWhvbGRlcigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGN1cnJlbnRWYWwgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICByZXR1cm4gdGhpcy5oYXNFeGlzdGluZ1ZhbHVlKGN1cnJlbnRWYWwpID8gdW5kZWZpbmVkIDogKHRoaXMuY29uZmlnPy5wbGFjZWhvbGRlciB8fCAnU2VsZWN0Li4uJyk7XG4gIH1cblxuICBnZXQgZGlzcGxheVZhbHVlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuICcnO1xuICAgIFxuICAgIC8vIElmIHZhbHVlIGlzIGFscmVhZHkgYSBTZWxlY3RPcHRpb24tbGlrZSBvYmplY3Qgd2l0aCBuYW1lL2xhYmVsLCB1c2UgaXQgZGlyZWN0bHlcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgY29uc3Qgd29ya3NwYWNlT2JqID0gdmFsdWUgYXMgYW55O1xuICAgICAgaWYgKHdvcmtzcGFjZU9iai5uYW1lIHx8IHdvcmtzcGFjZU9iai5sYWJlbCkge1xuICAgICAgICByZXR1cm4gd29ya3NwYWNlT2JqLm5hbWUgPz8gd29ya3NwYWNlT2JqLmxhYmVsID8/IFN0cmluZyh3b3Jrc3BhY2VPYmoudmFsdWUgPz8gd29ya3NwYWNlT2JqLmlkID8/ICcnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gT3RoZXJ3aXNlLCBsb29rIHVwIHRoZSB2YWx1ZSBpbiBvcHRpb25zIGxpc3RcbiAgICBjb25zdCBvcHRpb24gPSB0aGlzLmNvbmZpZz8ub3B0aW9ucz8uZmluZChvcHQgPT4gdGhpcy5nZXRPcHRpb25WYWx1ZShvcHQpID09PSB2YWx1ZSk7XG4gICAgcmV0dXJuIG9wdGlvbiA/IHRoaXMuZ2V0T3B0aW9uTGFiZWwob3B0aW9uKSA6IFN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBnZXQgaXRlbVNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc/Lml0ZW1TaXplIHx8IDM1O1xuICB9XG5cbiAgZ2V0IHZpZXdwb3J0SGVpZ2h0KCk6IG51bWJlciB7XG4gICAgLy8gSWYgdmlld3BvcnRIZWlnaHQgaXMgZXhwbGljaXRseSBzZXQgaW4gY29uZmlnLCB1c2UgaXRcbiAgICBpZiAodGhpcy5jb25maWc/LnZpZXdwb3J0SGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy52aWV3cG9ydEhlaWdodDtcbiAgICB9XG4gICAgXG4gICAgLy8gT3RoZXJ3aXNlLCBjYWxjdWxhdGUgYmFzZWQgb24gbnVtYmVyIG9mIG9wdGlvbnNcbiAgICBjb25zdCBvcHRpb25Db3VudCA9IHRoaXMuZGlzcGxheWVkT3B0aW9ucy5sZW5ndGg7XG4gICAgY29uc3QgbWF4SGVpZ2h0ID0gMzAwOyAvLyBNYXhpbXVtIGhlaWdodFxuICAgIGNvbnN0IG1pbkhlaWdodCA9IDEwMDsgLy8gTWluaW11bSBoZWlnaHRcbiAgICBjb25zdCBjYWxjdWxhdGVkSGVpZ2h0ID0gb3B0aW9uQ291bnQgKiB0aGlzLml0ZW1TaXplO1xuICAgIFxuICAgIC8vIFJldHVybiBjYWxjdWxhdGVkIGhlaWdodCwgYnV0IGNsYW1wIGJldHdlZW4gbWluIGFuZCBtYXhcbiAgICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgoY2FsY3VsYXRlZEhlaWdodCwgbWluSGVpZ2h0KSwgbWF4SGVpZ2h0KTtcbiAgfVxuXG4gIGdldCBkaXNwbGF5ZWRPcHRpb25zKCk6IFNlbGVjdE9wdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJlZE9wdGlvbnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgdG9Cb29sZWFuKHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHYgPSB2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICh2ID09PSAndHJ1ZScgfHwgdiA9PT0gJzEnKSByZXR1cm4gdHJ1ZTtcbiAgICAgIGlmICh2ID09PSAnZmFsc2UnIHx8IHYgPT09ICcwJyB8fCB2ID09PSAnJykgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gdmFsdWUgIT09IDA7XG4gICAgfVxuICAgIHJldHVybiAhIXZhbHVlO1xuICB9XG5cbiAgZ2V0T3B0aW9uVmFsdWUob3B0OiBTZWxlY3RPcHRpb24gfCBudWxsIHwgdW5kZWZpbmVkKTogYW55IHtcbiAgICBpZiAoIW9wdCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5jb25maWc/LnZhbHVlQnkpIHtcbiAgICAgIHJldHVybiAob3B0IGFzIGFueSlbdGhpcy5jb25maWcudmFsdWVCeV07XG4gICAgfVxuICAgIHJldHVybiBvcHQuaWQgPz8gb3B0LnZhbHVlO1xuICB9XG5cbiAgZ2V0T3B0aW9uTGFiZWwob3B0OiBTZWxlY3RPcHRpb24pOiBzdHJpbmcge1xuICAgIHJldHVybiBvcHQubmFtZSA/PyBvcHQubGFiZWwgPz8gb3B0LnZhbHVlID8/ICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW5jRGlzYWJsZWRTdGF0ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzaG91bGREaXNhYmxlID0gdGhpcy50b0Jvb2xlYW4odGhpcy5jb25maWc/LmRpc2FibGVkKTtcbiAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICBpZiAoc2hvdWxkRGlzYWJsZSkge1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250cm9sLmRpc2FibGUoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udHJvbC5lbmFibGUoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBGb3IgZGlyZWN0IHZhbHVlIGJpbmRpbmcsIGRpc2FibGVkIHN0YXRlIGlzIGhhbmRsZWQgdmlhIFtkaXNhYmxlZF0gYmluZGluZyBpbiB0ZW1wbGF0ZVxuICB9XG5cbiAgcHJpdmF0ZSBzeW5jQ29udHJvbFZhbHVlRm9yTXVsdGlwbGVNb2RlKCk6IHZvaWQge1xuICAgIC8vIE5vIGxvbmdlciBuZWVkZWQgLSBzaW5nbGUgc2VsZWN0aW9uIG9ubHlcbiAgICBjb25zdCBjdXJyZW50VmFsID0gdGhpcy5jdXJyZW50VmFsdWU7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY3VycmVudFZhbCkpIHtcbiAgICAgIHRoaXMuY3VycmVudFZhbHVlID0gY3VycmVudFZhbC5sZW5ndGggPyBjdXJyZW50VmFsWzBdIDogbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFwcGx5U2VsZWN0ZWRWYWx1ZUlmTmVlZGVkKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRWYWwgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICBpZiAodGhpcy5oYXNFeGlzdGluZ1ZhbHVlKGN1cnJlbnRWYWwpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIENoZWNrIGJvdGggY29uZmlnLnNlbGVjdGVkVmFsdWUgYW5kIGRpcmVjdCB2YWx1ZSBpbnB1dFxuICAgIGNvbnN0IHNlbGVjdGVkVmFsdWUgPSB0aGlzLnZhbHVlICE9PSB1bmRlZmluZWQgPyB0aGlzLnZhbHVlIDogdGhpcy5jb25maWc/LnNlbGVjdGVkVmFsdWU7XG4gICAgaWYgKHNlbGVjdGVkVmFsdWUgPT09IHVuZGVmaW5lZCB8fCBzZWxlY3RlZFZhbHVlID09PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIHNlbGVjdGVkVmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IEFycmF5LmlzQXJyYXkoc2VsZWN0ZWRWYWx1ZSlcbiAgICAgID8gKHNlbGVjdGVkVmFsdWUubGVuZ3RoID8gc2VsZWN0ZWRWYWx1ZVswXSA6IHVuZGVmaW5lZClcbiAgICAgIDogc2VsZWN0ZWRWYWx1ZTtcbiAgICBpZiAobm9ybWFsaXplZCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdGhpcy5jdXJyZW50VmFsdWUgPSBub3JtYWxpemVkO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNFeGlzdGluZ1ZhbHVlKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5zb21lKCh2YWwpID0+IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09ICcnKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB2YWx1ZS50cmltKCkubGVuZ3RoID4gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpc09wdGlvblNlbGVjdGVkKG9wdDogU2VsZWN0T3B0aW9uKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY3VycmVudFZhbCA9IHRoaXMuY3VycmVudFZhbHVlO1xuICAgIGlmIChjdXJyZW50VmFsID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgICBcbiAgICBjb25zdCBvcHRpb25WYWx1ZSA9IHRoaXMuZ2V0T3B0aW9uVmFsdWUob3B0KTtcbiAgICBcbiAgICAvLyBJZiBjdXJyZW50VmFsIGlzIGFuIG9iamVjdCB3aXRoIGlkL3ZhbHVlLCBleHRyYWN0IGl0IGZvciBjb21wYXJpc29uXG4gICAgaWYgKHR5cGVvZiBjdXJyZW50VmFsID09PSAnb2JqZWN0JyAmJiBjdXJyZW50VmFsICE9PSBudWxsKSB7XG4gICAgICBjb25zdCB3b3Jrc3BhY2VPYmogPSBjdXJyZW50VmFsIGFzIGFueTtcbiAgICAgIGNvbnN0IGN1cnJlbnRJZCA9IHRoaXMuY29uZmlnPy52YWx1ZUJ5IFxuICAgICAgICA/IHdvcmtzcGFjZU9ialt0aGlzLmNvbmZpZy52YWx1ZUJ5XVxuICAgICAgICA6ICh3b3Jrc3BhY2VPYmouaWQgPz8gd29ya3NwYWNlT2JqLnZhbHVlKTtcbiAgICAgIHJldHVybiBjdXJyZW50SWQgPT09IG9wdGlvblZhbHVlO1xuICAgIH1cbiAgICBcbiAgICAvLyBPdGhlcndpc2UsIGNvbXBhcmUgZGlyZWN0bHlcbiAgICByZXR1cm4gY3VycmVudFZhbCA9PT0gb3B0aW9uVmFsdWU7XG4gIH1cblxuICBmaWx0ZXJlZE9wdGlvbnMoKTogU2VsZWN0T3B0aW9uW10ge1xuICAgIGNvbnN0IHQgPSB0aGlzLnNlYXJjaFRleHQudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgY29uc3QgYWxsT3B0aW9ucyA9IHRoaXMuY29uZmlnLm9wdGlvbnMgfHwgW107XG5cbiAgICBpZiAodGhpcy5jb25maWc/LnNlcnZlclNlYXJjaCkge1xuICAgICAgLy8gRm9yIHNlcnZlciBzZWFyY2gsIHJldHVybiBhbGwgb3B0aW9ucyBhcy1pcyAoc2VydmVyIGhhbmRsZXMgZmlsdGVyaW5nKVxuICAgICAgcmV0dXJuIGFsbE9wdGlvbnM7XG4gICAgfVxuICAgIFxuICAgIGlmICghdCkge1xuICAgICAgLy8gTm8gc2VhcmNoIC0gcmV0dXJuIGFsbCBvcHRpb25zXG4gICAgICByZXR1cm4gYWxsT3B0aW9ucztcbiAgICB9XG5cbiAgICAvLyBMb2NhbCBzZWFyY2ggLSBmaWx0ZXIgb3B0aW9ucyBieSBzZWFyY2ggdGV4dCBvbmx5XG4gICAgcmV0dXJuIGFsbE9wdGlvbnMuZmlsdGVyKChvcHQpID0+IHtcbiAgICAgIGNvbnN0IHRleHQgPSB0aGlzLmdldE9wdGlvbkxhYmVsKG9wdCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJldHVybiB0ZXh0LmluY2x1ZGVzKHQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTZWxlY3RlZElkcygpOiBhbnlbXSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICByZXR1cm4gdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCA/IFt2YWx1ZV0gOiBbXTtcbiAgfVxuXG4gIG9uT3B0aW9uQ2xpY2sob3B0OiBTZWxlY3RPcHRpb24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKSByZXR1cm47XG4gICAgXG4gICAgLy8gRW1pdCB0aGUgZnVsbCBvcHRpb24gb2JqZWN0ICh3aXRoIG5hbWUsIGlkLCBldGMuKSBpbnN0ZWFkIG9mIGp1c3QgdGhlIHZhbHVlXG4gICAgLy8gVGhpcyBhbGxvd3MgdGhlIHBhcmVudCB0byByZWNlaXZlIHRoZSBjb21wbGV0ZSB3b3Jrc3BhY2Ugb2JqZWN0XG4gICAgY29uc3QgbmV3VmFsdWUgPSBvcHQ7XG4gICAgY29uc3Qgc2VsZWN0ZWRPcHRpb24gPSBvcHQ7XG4gICAgXG4gICAgLy8gQ2xvc2UgZHJvcGRvd24gYWZ0ZXIgc2VsZWN0aW9uICh1bmxlc3MgY2xvc2VPblNlbGVjdCBpcyBmYWxzZSlcbiAgICBpZiAodGhpcy5jb25maWc/LmNsb3NlT25TZWxlY3QgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLmNsb3NlRHJvcGRvd24oKTtcbiAgICB9XG4gICAgXG4gICAgLy8gVXBkYXRlIHZhbHVlXG4gICAgaWYgKHRoaXMuZm9ybSkge1xuICAgICAgdGhpcy5jdXJyZW50Q29udHJvbC5zZXRWYWx1ZShuZXdWYWx1ZSwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgIHRoaXMuc3luY1ZhbHVlRnJvbUlucHV0KCk7XG4gICAgfVxuICAgIFxuICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2UobmV3VmFsdWUsIHNlbGVjdGVkT3B0aW9uKTtcbiAgfVxuXG4gIG9uU2VsZWN0aW9uQ2hhbmdlKG5ld1ZhbHVlPzogYW55LCBzZWxlY3RlZE9wdGlvbj86IFNlbGVjdE9wdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID0gbmV3VmFsdWUgIT09IHVuZGVmaW5lZCA/IG5ld1ZhbHVlIDogdGhpcy5jdXJyZW50VmFsdWU7XG4gICAgXG4gICAgLy8gRW1pdCB2YWx1ZUNoYW5nZSBmb3IgdHdvLXdheSBiaW5kaW5nXG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgICBcbiAgICBpZiAodHlwZW9mIHRoaXMuY29uZmlnPy5vbkNoYW5nZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5jb25maWcub25DaGFuZ2UodmFsdWUpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignY3FhLXdvcmtzcGFjZS1zZWxlY3RvciBvbkNoYW5nZSBoYW5kbGVyIGVycm9yOicsIGVycm9yKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2UuZW1pdCh7XG4gICAgICBrZXk6IHRoaXMuY29uZmlnPy5rZXkgfHwgJycsXG4gICAgICB2YWx1ZSxcbiAgICAgIG9wdGlvbjogc2VsZWN0ZWRPcHRpb24sXG4gICAgfSk7XG4gIH1cblxuICBvblNlYXJjaElucHV0KHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnNlYXJjaFRleHQgPSB2YWx1ZSA/PyAnJztcbiAgICBpZiAodGhpcy5jb25maWc/LnNlcnZlclNlYXJjaCkge1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25TZWFyY2g/Lih2YWx1ZSA/PyAnJyk7IH0gY2F0Y2gge31cbiAgICAgIHRoaXMuc2VhcmNoQ2hhbmdlLmVtaXQoeyBrZXk6IHRoaXMuY29uZmlnPy5rZXkgfHwgJycsIHF1ZXJ5OiB2YWx1ZSA/PyAnJyB9KTtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSBmYWxzZTtcbiAgICAgIHRoaXMubGFzdE9wdGlvbnNMZW5ndGggPSAodGhpcy5jb25maWc/Lm9wdGlvbnMgfHwgW10pLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVEcm9wZG93bigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKSByZXR1cm47XG4gICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICB0aGlzLmNsb3NlRHJvcGRvd24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGVuRHJvcGRvd24oKTtcbiAgICB9XG4gIH1cblxuICBvcGVuRHJvcGRvd24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEaXNhYmxlZCkgcmV0dXJuO1xuICAgIHRoaXMuaXNPcGVuID0gdHJ1ZTtcbiAgICB0aGlzLnNlbGVjdENsaWNrLmVtaXQoKTtcbiAgICB0aGlzLmhhc1Njcm9sbGVkU2luY2VPcGVuID0gZmFsc2U7XG4gICAgXG4gICAgaWYgKCh0aGlzLmNvbmZpZz8ub3B0aW9ucyB8fCBbXSkubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZz8uc2VydmVyU2VhcmNoICYmIHRoaXMudG9Cb29sZWFuKHRoaXMuY29uZmlnPy5pbml0aWFsRmV0Y2hPbk9wZW4pKSB7XG4gICAgICBjb25zdCBxID0gdGhpcy5zZWFyY2hUZXh0IHx8ICcnO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25TZWFyY2g/LihxKTsgfSBjYXRjaCB7fVxuICAgICAgdGhpcy5zZWFyY2hDaGFuZ2UuZW1pdCh7IGtleTogdGhpcy5jb25maWc/LmtleSB8fCAnJywgcXVlcnk6IHEgfSk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNldHVwU2Nyb2xsTGlzdGVuZXIoKTtcbiAgICAgIGlmICh0aGlzLmNvbmZpZz8uc2VhcmNoYWJsZSkge1xuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuZHJvcGRvd25QYW5lbD8ubmF0aXZlRWxlbWVudD8ucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PignLndvcmtzcGFjZS1zZWFyY2gtaW5wdXQnKTtcbiAgICAgICAgaW5wdXQ/LmZvY3VzKCk7XG4gICAgICB9XG4gICAgfSwgMCk7XG4gIH1cblxuICBjbG9zZURyb3Bkb3duKCk6IHZvaWQge1xuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgdGhpcy5zZWFyY2hUZXh0ID0gJyc7XG4gICAgaWYgKHRoaXMucGFuZWxTY3JvbGxFbCkge1xuICAgICAgdHJ5IHsgdGhpcy5wYW5lbFNjcm9sbEVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMub25QYW5lbFNjcm9sbCk7IH0gY2F0Y2gge31cbiAgICAgIHRoaXMucGFuZWxTY3JvbGxFbCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFNjcm9sbExpc3RlbmVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWc/Lmhhc01vcmUpIHJldHVybjtcbiAgICBjb25zdCBwYW5lbCA9IHRoaXMuZHJvcGRvd25QYW5lbD8ubmF0aXZlRWxlbWVudD8ucXVlcnlTZWxlY3RvcignLndvcmtzcGFjZS1vcHRpb25zLWNvbnRhaW5lcicpIGFzIEhUTUxFbGVtZW50O1xuICAgIGlmIChwYW5lbCkge1xuICAgICAgdGhpcy5wYW5lbFNjcm9sbEVsID0gcGFuZWw7XG4gICAgICBwYW5lbC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLm9uUGFuZWxTY3JvbGwsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH1cblxuICBvblNjcm9sbGVkSW5kZXhDaGFuZ2UoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuaGFzU2Nyb2xsZWRTaW5jZU9wZW4gPSB0cnVlO1xuICAgIGlmICghdGhpcy5jb25maWc/Lmhhc01vcmUgfHwgdGhpcy5sb2FkaW5nTW9yZSkgcmV0dXJuO1xuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy52aWV3cG9ydD8uZWxlbWVudFJlZj8ubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIXZpZXdwb3J0KSByZXR1cm47XG4gICAgY29uc3QgaXRlbUNvdW50ID0gdGhpcy5kaXNwbGF5ZWRPcHRpb25zLmxlbmd0aDtcbiAgICBjb25zdCB2aXNpYmxlSXRlbXMgPSBNYXRoLmNlaWwodmlld3BvcnQuY2xpZW50SGVpZ2h0IC8gdGhpcy5pdGVtU2l6ZSk7XG4gICAgaWYgKGluZGV4ICsgdmlzaWJsZUl0ZW1zID49IGl0ZW1Db3VudCAtIDEpIHtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSB0cnVlO1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5jb25maWc/LmtleSB8fCAnJztcbiAgICAgIGNvbnN0IHEgPSB0aGlzLnNlYXJjaFRleHQgfHwgJyc7XG4gICAgICB0aGlzLmxvYWRNb3JlLmVtaXQoeyBrZXksIHF1ZXJ5OiBxIH0pO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25Mb2FkTW9yZT8uKHEpOyB9IGNhdGNoIHt9XG4gICAgfVxuICB9XG5cbiAgdHJhY2tCeU9wdGlvbiA9IChpbmRleDogbnVtYmVyLCBvcHQ6IFNlbGVjdE9wdGlvbiB8IG51bGwgfCB1bmRlZmluZWQpOiBhbnkgPT4ge1xuICAgIGlmICghb3B0KSByZXR1cm4gYGluZGV4LSR7aW5kZXh9YDtcbiAgICAvLyBVc2UgYSBzaW1wbGUgaWRlbnRpZmllciB0aGF0IGRvZXNuJ3QgcmVxdWlyZSBjYWxsaW5nIG1ldGhvZHNcbiAgICByZXR1cm4gb3B0LmlkID8/IG9wdC52YWx1ZSA/PyBgb3B0aW9uLSR7aW5kZXh9YDtcbiAgfVxuXG4gIGhpZ2hsaWdodFRleHQodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXRleHQgfHwgIXRoaXMuY29uZmlnPy5oaWdobGlnaHRQYXR0ZXJuKSB7XG4gICAgICByZXR1cm4gdGhpcy5lc2NhcGVIdG1sKHRleHQpO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLmNvbmZpZy5oaWdobGlnaHRQYXR0ZXJuO1xuICAgIGlmICh0eXBlb2YgcGF0dGVybiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHBhdHRlcm4odGV4dCk7XG4gICAgfVxuXG4gICAgbGV0IHJlZ2V4OiBSZWdFeHA7XG4gICAgaWYgKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHBhdHRlcm4sICdnaScpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0ludmFsaWQgaGlnaGxpZ2h0IHBhdHRlcm46JywgcGF0dGVybik7XG4gICAgICAgIHJldHVybiB0aGlzLmVzY2FwZUh0bWwodGV4dCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlZ2V4ID0gcGF0dGVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlc2NhcGVkID0gdGhpcy5lc2NhcGVIdG1sKHRleHQpO1xuICAgIHJldHVybiBlc2NhcGVkLnJlcGxhY2UocmVnZXgsIChtYXRjaCkgPT4gYDxzcGFuIGNsYXNzPVwiY3FhLXRleHQtcHJpbWFyeVwiPiR7bWF0Y2h9PC9zcGFuPmApO1xuICB9XG5cbiAgcHJpdmF0ZSBlc2NhcGVIdG1sKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCF0ZXh0KSByZXR1cm4gJyc7XG4gICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICByZXR1cm4gZGl2LmlubmVySFRNTDtcbiAgfVxuXG4gIGdldCBoYXNIaWdobGlnaHRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5jb25maWc/LmhpZ2hsaWdodFBhdHRlcm47XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gIGhhbmRsZURvY3VtZW50Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNPcGVuKSByZXR1cm47XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICBpZiAoIXRhcmdldCkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmhvc3RFbD8ubmF0aXZlRWxlbWVudCAmJiB0aGlzLmhvc3RFbC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jbG9zZURyb3Bkb3duKCk7XG4gIH1cbn1cblxuIiwiPGRpdiBjbGFzcz1cImNxYS11aS1yb290XCIgI2hvc3Q+XG4gIDxuZy1jb250YWluZXIgW2Zvcm1Hcm91cF09XCJjdXJyZW50Rm9ybVwiPlxuICAgIDxsYWJlbCAqbmdJZj1cImNvbmZpZy5sYWJlbFwiXG4gICAgICBjbGFzcz1cImZvcm0tbGFiZWwgY3FhLXRleHQtWyMzNzQxNTFdIGNxYS10ZXh0LVsxNHB4XSBjcWEtZm9udC1tZWRpdW0gY3FhLWJsb2NrIGNxYS1sZWFkaW5nLVsxLjRdIGNxYS1tYi0yXCI+e3tcbiAgICAgIGNvbmZpZy5sYWJlbCB9fTwvbGFiZWw+XG4gICAgXG4gICAgPGRpdiBjbGFzcz1cIndvcmtzcGFjZS1zZWxlY3Rvci13cmFwcGVyIGNxYS1yZWxhdGl2ZSBjcWEtdy1mdWxsXCI+XG4gICAgICA8IS0tIFRyaWdnZXIgQnV0dG9uIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VsZWN0b3ItdHJpZ2dlciBjcWEtdy1mdWxsIGNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktYmV0d2VlbiBjcWEtcHgtNCBjcWEtcHktMiBjcWEtYm9yZGVyLXNvbGlkIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1bI0QxRDVEQl0gY3FhLXJvdW5kZWQtWzhweF0gY3FhLWJnLXdoaXRlIGNxYS10ZXh0LWxlZnQgY3FhLWN1cnNvci1wb2ludGVyIGhvdmVyOmNxYS1ib3JkZXItWyM5Q0EzQUZdIGZvY3VzOmNxYS1vdXRsaW5lLW5vbmUgZm9jdXM6Y3FhLXJpbmctMiBmb2N1czpjcWEtcmluZy1bIzRGNDZFNV0gZm9jdXM6Y3FhLXJpbmctb2Zmc2V0LTEgZGlzYWJsZWQ6Y3FhLW9wYWNpdHktNTAgZGlzYWJsZWQ6Y3FhLWN1cnNvci1ub3QtYWxsb3dlZFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcbiAgICAgICAgKGNsaWNrKT1cInRvZ2dsZURyb3Bkb3duKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImlzT3BlblwiXG4gICAgICAgIGFyaWEtaGFzcG9wdXA9XCJsaXN0Ym94XCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtdHJ1bmNhdGUgY3FhLXRleHQtWzE0cHhdIGNxYS10ZXh0LVsjMEEwQTBBXVwiXG4gICAgICAgICAgW2NsYXNzLmNxYS10ZXh0LVsjOUNBM0FGXV09XCIhZGlzcGxheVZhbHVlXCI+XG4gICAgICAgICAge3sgZGlzcGxheVZhbHVlIHx8IGRpc3BsYXlQbGFjZWhvbGRlciB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMiBjcWEtZmxleC1zaHJpbmstMFwiPlxuICAgICAgICAgIDxzdmcgKm5nSWY9XCJsb2FkaW5nTW9yZSB8fCBjb25maWc/LmlzTG9hZGluZ1wiIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIHZpZXdCb3g9XCIwIDAgNTAgNTBcIiBhcmlhLWxhYmVsPVwibG9hZGluZ1wiXG4gICAgICAgICAgICAgICB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgY2xhc3M9XCJjcWEtYW5pbWF0ZS1zcGluXCI+XG4gICAgICAgICAgICA8Y2lyY2xlIGN4PVwiMjVcIiBjeT1cIjI1XCIgcj1cIjIwXCIgc3Ryb2tlPVwiI0U1RTdFQlwiIHN0cm9rZS13aWR0aD1cIjZcIiBmaWxsPVwibm9uZVwiLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNNDUgMjVhMjAgMjAgMCAwIDAtMjAtMjBcIiBzdHJva2U9XCIjNEY0NkU1XCIgc3Ryb2tlLXdpZHRoPVwiNlwiIGZpbGw9XCJub25lXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiPlxuICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPVwidHJhbnNmb3JtXCIgdHlwZT1cInJvdGF0ZVwiIGZyb209XCIwIDI1IDI1XCIgdG89XCIzNjAgMjUgMjVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdXI9XCIwLjhzXCIgcmVwZWF0Q291bnQ9XCJpbmRlZmluaXRlXCIvPlxuICAgICAgICAgICAgPC9wYXRoPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAxNiAxNlwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiXG4gICAgICAgICAgICAgICBbY2xhc3MuY3FhLXJvdGF0ZS0xODBdPVwiaXNPcGVuXCI+XG4gICAgICAgICAgICA8cGF0aCBkPVwiTTQgNkw4IDEwTDEyIDZcIiBzdHJva2U9XCIjMEEwQTBBXCIgc3Ryb2tlLXdpZHRoPVwiMS4zMzMzM1wiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIlxuICAgICAgICAgICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gRHJvcGRvd24gUGFuZWwgLS0+XG4gICAgICA8ZGl2XG4gICAgICAgICNkcm9wZG93blBhbmVsXG4gICAgICAgICpuZ0lmPVwiaXNPcGVuXCJcbiAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VsZWN0b3ItcGFuZWwgY3FhLWFic29sdXRlIGNxYS16LTUwIGNxYS13LWZ1bGwgY3FhLW10LTEgY3FhLWJnLXdoaXRlIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1bI0QxRDVEQl0gY3FhLXJvdW5kZWQtWzhweF0gY3FhLXNoYWRvdy1sZyBjcWEtb3ZlcmZsb3ctaGlkZGVuXCI+XG4gICAgICAgIFxuICAgICAgICA8IS0tIFNlYXJjaCBJbnB1dCAtLT5cbiAgICAgICAgPGRpdiAqbmdJZj1cImNvbmZpZy5zZWFyY2hhYmxlXCIgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VhcmNoLWNvbnRhaW5lciBjcWEtcC0yIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLVsjRTVFN0VCXVwiPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VhcmNoLWlucHV0IGNxYS13LWZ1bGwgY3FhLXB4LTMgY3FhLXB5LTIgY3FhLWJvcmRlciBjcWEtYm9yZGVyLVsjRDFENURCXSBjcWEtcm91bmRlZC1bNnB4XSBjcWEtdGV4dC1bMTRweF0gY3FhLXRleHQtWyMwQTBBMEFdIGZvY3VzOmNxYS1vdXRsaW5lLW5vbmVcIlxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2guLi5cIlxuICAgICAgICAgICAgW3ZhbHVlXT1cInNlYXJjaFRleHRcIlxuICAgICAgICAgICAgKGlucHV0KT1cIm9uU2VhcmNoSW5wdXQoJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAobW91c2Vkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAoa2V5ZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIiAvPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIE9wdGlvbnMgQ29udGFpbmVyIHdpdGggVmlydHVhbCBTY3JvbGwgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ3b3Jrc3BhY2Utb3B0aW9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICA8IS0tIE5vIHJlc3VsdHMgc3RhdGUgLS0+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cImRpc3BsYXllZE9wdGlvbnMubGVuZ3RoID09PSAwICYmICEoY29uZmlnPy5pc0xvYWRpbmcgfHwgbG9hZGluZ01vcmUpXCJcbiAgICAgICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTMgY3FhLXRleHQtWzE0cHhdIGNxYS10ZXh0LVsjOUNBM0FGXSBjcWEtdGV4dC1jZW50ZXJcIj5cbiAgICAgICAgICAgIE5vIHJlc3VsdHNcbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcbiAgICAgICAgICAgICpuZ0lmPVwiZGlzcGxheWVkT3B0aW9ucy5sZW5ndGggPiAwXCJcbiAgICAgICAgICAgICN2aWV3cG9ydFxuICAgICAgICAgICAgW2l0ZW1TaXplXT1cIml0ZW1TaXplXCJcbiAgICAgICAgICAgIG1pbkJ1ZmZlclB4PVwiMjAwXCJcbiAgICAgICAgICAgIG1heEJ1ZmZlclB4PVwiNDAwXCJcbiAgICAgICAgICAgIFtzdHlsZS5oZWlnaHQucHhdPVwidmlld3BvcnRIZWlnaHRcIlxuICAgICAgICAgICAgc3R5bGU9XCJ3aWR0aDogMTAwJTsgZGlzcGxheTogYmxvY2s7IG92ZXJmbG93OiBhdXRvO1wiXG4gICAgICAgICAgICAoc2Nyb2xsZWRJbmRleENoYW5nZSk9XCJvblNjcm9sbGVkSW5kZXhDaGFuZ2UoJGV2ZW50KVwiPlxuICAgICAgICAgICAgXG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwibGV0IG9wdCBvZiBkaXNwbGF5ZWRPcHRpb25zOyB0cmFja0J5OiB0cmFja0J5T3B0aW9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utb3B0aW9uIGNxYS1weC00IGNxYS1weS0zIGNxYS1jdXJzb3ItcG9pbnRlciBob3ZlcjpjcWEtYmctWyNGM0Y0RjZdIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLVsjRTVFN0VCXSBsYXN0OmNxYS1ib3JkZXItYi0wXCJcbiAgICAgICAgICAgICAgW3N0eWxlLmhlaWdodC5weF09XCJpdGVtU2l6ZVwiXG4gICAgICAgICAgICAgIFtzdHlsZS5kaXNwbGF5XT1cIidmbGV4J1wiXG4gICAgICAgICAgICAgIFtzdHlsZS5hbGlnbi1pdGVtc109XCInY2VudGVyJ1wiXG4gICAgICAgICAgICAgIFtjbGFzcy5jcWEtYmctWyNGM0Y0RjZdXT1cImlzT3B0aW9uU2VsZWN0ZWQob3B0KVwiXG4gICAgICAgICAgICAgIFtjbGFzcy5jcWEtYmctWyNFRUYyRkZdXT1cImlzT3B0aW9uU2VsZWN0ZWQob3B0KVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbk9wdGlvbkNsaWNrKG9wdClcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjcWEtdGV4dC1bMTRweF0gY3FhLXRleHQtWyMwQTBBMEFdXCJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImhhc0hpZ2hsaWdodGluZ1wiXG4gICAgICAgICAgICAgICAgW2lubmVySFRNTF09XCJoaWdobGlnaHRUZXh0KGdldE9wdGlvbkxhYmVsKG9wdCkpXCI+PC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LVsxNHB4XSBjcWEtdGV4dC1bIzBBMEEwQV1cIlxuICAgICAgICAgICAgICAgICpuZ0lmPVwiIWhhc0hpZ2hsaWdodGluZ1wiPlxuICAgICAgICAgICAgICAgIHt7IGdldE9wdGlvbkxhYmVsKG9wdCkgfX1cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG5cbiAgICAgICAgICA8IS0tIExvYWRpbmcgbW9yZSBpbmRpY2F0b3IgLS0+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cImNvbmZpZz8uaGFzTW9yZSAmJiAobG9hZGluZ01vcmUgfHwgY29uZmlnPy5pc0xvYWRpbmcpICYmIGRpc3BsYXllZE9wdGlvbnMubGVuZ3RoID4gMFwiXG4gICAgICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0zIGNxYS10ZXh0LVsxNHB4XSBjcWEtdGV4dC1bIzZCNzI4MF0gY3FhLXRleHQtY2VudGVyIGNxYS1ib3JkZXItdCBjcWEtYm9yZGVyLVsjRTVFN0VCXVwiPlxuICAgICAgICAgICAgTG9hZGluZy4uLlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG4iXX0=