@ruc-lib/drawer 2.0.0 → 3.1.0

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.
@@ -1,412 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, ChangeDetectorRef, HostListener, ViewChild, ViewContainerRef } from '@angular/core';
2
- import { trigger, state, style, transition, animate } from '@angular/animations';
3
- import * as i0 from "@angular/core";
4
- import * as i1 from "@angular/common";
5
- import * as i2 from "@angular/material/button";
6
- import * as i3 from "@angular/material/icon";
7
- import * as i4 from "@angular/material/sidenav";
8
- import * as i5 from "../../pipes/pipes/safe-html.pipe";
9
- /**
10
- * @Component RuclibDrawerComponent
11
- * @description A highly configurable drawer component that can slide in from any of the four directions (left, right, top, bottom).
12
- * It uses custom Angular animations for smooth transitions and supports theming.
13
- */
14
- export class RuclibDrawerComponent {
15
- constructor(cdr) {
16
- this.cdr = cdr;
17
- /**
18
- * Input data for configuring the drawer's appearance and behavior.
19
- * @see RuclibDrawerInput interface for detailed properties.
20
- */
21
- this.rucInputData = {};
22
- /**
23
- * EventEmitter for various drawer events.
24
- * Emits objects with `type` (e.g., 'openedStart', 'closedStart', 'openedChange', 'drawerToggle')
25
- * and `opened` (boolean) and `position` (string) properties.
26
- */
27
- this.rucEvent = new EventEmitter();
28
- /** Reference to the dynamically created component. */
29
- this.dynamicComponentRef = null;
30
- /**
31
- * Current animation state of the drawer ('in' or 'out').
32
- * @public
33
- */
34
- this.drawerAnimationState = 'out';
35
- /**
36
- * Current active position of the drawer.
37
- * @public
38
- * @default 'left'
39
- */
40
- this.currentDrawerPosition = 'left'; // Default
41
- /**
42
- * Stores the next position if the drawer is currently open and a new position is requested.
43
- * Used to sequence close and open animations.
44
- * @private
45
- */
46
- this.pendingDrawerPosition = null;
47
- /**
48
- * Flag to indicate if an animation is currently in progress to prevent rapid toggling.
49
- * @public
50
- */
51
- this.isAnimating = false;
52
- /**
53
- * Effective animation duration for the drawer, derived from input or default.
54
- * @public
55
- * @default '300ms'
56
- */
57
- this.effectiveAnimationDuration = '300ms';
58
- /**
59
- * Mode of the drawer, primarily for determining backdrop behavior with custom animations.
60
- * @public
61
- * @default 'side'
62
- */
63
- this.matDrawerMode = 'side';
64
- /**
65
- * Actual position ('start' or 'end') used by Angular Material's MatDrawer if it were directly used.
66
- * Retained for logical consistency in determining layout.
67
- * @public
68
- * @default 'start'
69
- */
70
- this.matActualPosition = 'start';
71
- /**
72
- * Flag indicating if the drawer is in a vertical layout (top/bottom).
73
- * Helps determine if width or height should be 100%.
74
- * @public
75
- */
76
- this.isVerticalLayout = false;
77
- /**
78
- * Effective dimension (width or height) of the drawer panel.
79
- * @public
80
- * @default '250px'
81
- */
82
- this.effectiveDrawerDimension = '250px';
83
- }
84
- /**
85
- * Angular lifecycle hook that is called after data-bound properties of a directive are initialized.
86
- */
87
- ngOnInit() {
88
- this.applyInputs();
89
- this.drawerAnimationState = 'out';
90
- this.loadDynamicContent();
91
- }
92
- /**
93
- * Angular lifecycle hook that is called after Angular has fully initialized a component's view.
94
- */
95
- ngAfterViewInit() {
96
- if (this.rucInputData.initialOpenedState && this.drawerAnimationState === 'out') {
97
- // Defer state update to the next microtask queue.
98
- // This helps avoid ExpressionChangedAfterItHasBeenCheckedError when initializing the drawer's open state.
99
- Promise.resolve().then(() => this.setDrawerOpenState(true));
100
- }
101
- }
102
- /**
103
- * Angular lifecycle hook that is called when any data-bound property of a directive changes.
104
- * @param changes - Object containing the changed properties.
105
- */
106
- ngOnChanges(changes) {
107
- if (changes['rucInputData']) {
108
- const previousRucInputData = changes['rucInputData'].previousValue || {};
109
- const currentRucInputData = changes['rucInputData'].currentValue || {};
110
- const oldPosition = previousRucInputData.drawerPosition ?? this.currentDrawerPosition;
111
- const wasOpen = this.drawerAnimationState === 'in';
112
- this.currentDrawerPosition = currentRucInputData.drawerPosition ?? 'left';
113
- this.applyInputs();
114
- const newPosition = this.currentDrawerPosition;
115
- const shouldBeOpen = this.rucInputData.initialOpenedState ?? false;
116
- if (wasOpen && oldPosition !== newPosition) {
117
- this.pendingDrawerPosition = newPosition;
118
- this.setDrawerOpenState(false);
119
- }
120
- else if (wasOpen !== shouldBeOpen) {
121
- setTimeout(() => {
122
- this.setDrawerOpenState(shouldBeOpen);
123
- });
124
- }
125
- else {
126
- this.loadDynamicContent();
127
- }
128
- this.cdr.detectChanges();
129
- }
130
- }
131
- /**
132
- * Applies input data to component properties, calculating dimensions and positions.
133
- * @private
134
- */
135
- applyInputs() {
136
- this.matDrawerMode = this.rucInputData.mode ?? 'side';
137
- this.effectiveAnimationDuration = this.rucInputData.animationDuration || '300ms';
138
- const getDimension = (inputDimension, defaultDimension) => {
139
- return (inputDimension && inputDimension.trim() !== '') ? inputDimension : defaultDimension;
140
- };
141
- switch (this.currentDrawerPosition) {
142
- case 'right':
143
- this.matActualPosition = 'end';
144
- this.isVerticalLayout = false;
145
- this.effectiveDrawerDimension = getDimension(this.rucInputData.drawerWidth, '250px');
146
- break;
147
- case 'top':
148
- this.matActualPosition = 'start';
149
- this.isVerticalLayout = true;
150
- this.effectiveDrawerDimension = getDimension(this.rucInputData.drawerHeight, '200px');
151
- break;
152
- case 'bottom':
153
- this.matActualPosition = 'end';
154
- this.isVerticalLayout = true;
155
- this.effectiveDrawerDimension = getDimension(this.rucInputData.drawerHeight, '200px');
156
- break;
157
- case 'left':
158
- default:
159
- this.matActualPosition = 'start';
160
- this.isVerticalLayout = false;
161
- this.effectiveDrawerDimension = getDimension(this.rucInputData.drawerWidth, '250px');
162
- break;
163
- }
164
- }
165
- /**
166
- * Toggles the drawer's open/close state or switches to a new position.
167
- * @param requestedPosition - The desired position to open the drawer from. If not provided, uses `currentDrawerPosition`.
168
- */
169
- toggleDrawer(requestedPosition) {
170
- if (this.isAnimating && !this.pendingDrawerPosition) {
171
- return;
172
- }
173
- const positionToToggle = requestedPosition || this.currentDrawerPosition;
174
- const isDrawerOpen = this.drawerAnimationState === 'in';
175
- const isSamePosition = this.currentDrawerPosition === positionToToggle;
176
- if (isDrawerOpen) {
177
- if (isSamePosition) {
178
- this.setDrawerOpenState(false);
179
- }
180
- else {
181
- this.pendingDrawerPosition = positionToToggle;
182
- this.setDrawerOpenState(false);
183
- }
184
- }
185
- else {
186
- if (!isSamePosition) {
187
- this.currentDrawerPosition = positionToToggle;
188
- this.applyInputs();
189
- }
190
- this.setDrawerOpenState(true);
191
- }
192
- }
193
- /**
194
- * Sets the drawer's open state and triggers the animation.
195
- * @param open - Boolean indicating whether to open (true) or close (false) the drawer.
196
- * @private
197
- */
198
- setDrawerOpenState(open) {
199
- if (this.isAnimating && !this.pendingDrawerPosition && open === (this.drawerAnimationState === 'in')) {
200
- return;
201
- }
202
- this.isAnimating = true;
203
- this.drawerAnimationState = open ? 'in' : 'out';
204
- this.rucEvent.emit({
205
- type: open ? 'openedStart' : 'closedStart',
206
- opened: open,
207
- position: this.currentDrawerPosition
208
- });
209
- this.cdr.detectChanges();
210
- }
211
- /**
212
- * Callback for when a drawer animation finishes.
213
- * Manages state transitions, especially when switching between open drawers.
214
- * @param event - The Angular AnimationEvent.
215
- */
216
- onAnimationDone(event) {
217
- if (event.element.classList.contains('dynamic-drawer')) {
218
- if (event.toState === 'out') {
219
- this.rucEvent.emit({ type: 'openedChange', opened: false, position: this.currentDrawerPosition });
220
- this.rucEvent.emit({ type: 'drawerToggle', opened: false, position: this.currentDrawerPosition });
221
- if (this.pendingDrawerPosition) {
222
- this.currentDrawerPosition = this.pendingDrawerPosition;
223
- this.pendingDrawerPosition = null;
224
- this.applyInputs();
225
- setTimeout(() => {
226
- this.setDrawerOpenState(true);
227
- });
228
- return;
229
- }
230
- }
231
- else if (event.toState === 'in') {
232
- this.rucEvent.emit({ type: 'openedChange', opened: true, position: this.currentDrawerPosition });
233
- this.rucEvent.emit({ type: 'drawerToggle', opened: true, position: this.currentDrawerPosition });
234
- }
235
- this.isAnimating = false;
236
- this.cdr.detectChanges();
237
- }
238
- }
239
- /**
240
- * Loads the dynamic component into the drawer if specified in rucInputData.
241
- * Clears existing dynamic component if any.
242
- * @private
243
- */
244
- loadDynamicContent() {
245
- this.clearDynamicContent();
246
- const componentType = this.rucInputData.content?.drawerContentComponent;
247
- if (componentType && this.drawerComponentHost) {
248
- this.dynamicComponentRef = this.drawerComponentHost.createComponent(componentType);
249
- if (this.dynamicComponentRef.instance) {
250
- this.dynamicComponentRef.changeDetectorRef.detectChanges();
251
- }
252
- if (this.rucInputData.drawerContentComponentData && this.dynamicComponentRef.instance) {
253
- Object.keys(this.rucInputData.drawerContentComponentData).forEach(key => {
254
- if (key in this.dynamicComponentRef.instance) {
255
- this.dynamicComponentRef.instance[key] = this.rucInputData.drawerContentComponentData[key];
256
- }
257
- });
258
- this.dynamicComponentRef.changeDetectorRef.detectChanges();
259
- }
260
- this.cdr.detectChanges();
261
- }
262
- }
263
- /**
264
- * Getter for the current animation parameters to be passed to the animation triggers in the template.
265
- * Includes the current animation state ('in' or 'out') and the effective duration.
266
- */
267
- get animationParams() {
268
- return { value: this.drawerAnimationState, params: { duration: this.effectiveAnimationDuration } };
269
- }
270
- /**
271
- * Getter for the backdrop animation parameters.
272
- * Typically uses a faster duration than the main drawer animation.
273
- */
274
- get backdropAnimationParams() {
275
- let durationMs = 0;
276
- if (this.effectiveAnimationDuration.endsWith('ms')) {
277
- durationMs = parseInt(this.effectiveAnimationDuration, 10);
278
- }
279
- else if (this.effectiveAnimationDuration.endsWith('s')) {
280
- durationMs = parseFloat(this.effectiveAnimationDuration) * 1000;
281
- }
282
- else {
283
- durationMs = parseInt(this.effectiveAnimationDuration, 10) || 300; // Fallback if format is unexpected
284
- }
285
- const backdropDurationValue = Math.floor(durationMs / 2); // Ensure integer for ms
286
- const backdropDuration = backdropDurationValue > 0 ? `${backdropDurationValue}ms` : '150ms'; // Fallback if calculated duration is 0 or less
287
- return { value: this.drawerAnimationState, params: { duration: backdropDuration } };
288
- }
289
- /**
290
- * Generates an accessible label for the toggle button based on the drawer's state and position.
291
- * @returns The ARIA label string for the toggle button.
292
- */
293
- getToggleButtonAriaLabel() {
294
- const defaultOpen = `Open ${this.currentDrawerPosition} Drawer`;
295
- const defaultClose = `Close ${this.currentDrawerPosition} Drawer`;
296
- const openText = this.rucInputData.toggleButtonText?.open || defaultOpen;
297
- const closeText = this.rucInputData.toggleButtonText?.close || defaultClose;
298
- return this.drawerAnimationState === 'in' ? closeText : openText;
299
- }
300
- /**
301
- * Handles clicks on the backdrop.
302
- * Closes the drawer only if `disableClose` is not true.
303
- * @public
304
- */
305
- handleBackdropClick() {
306
- if (!(this.rucInputData.disableClose ?? false)) {
307
- this.toggleDrawer(this.currentDrawerPosition);
308
- }
309
- }
310
- /**
311
- * Listens for Escape key presses on the document.
312
- * Closes the drawer if it's open and `disableClose` is not true.
313
- * @param event - The KeyboardEvent.
314
- */
315
- onKeydownHandler(event) {
316
- if (this.drawerAnimationState === 'in' && !(this.rucInputData.disableClose ?? false)) {
317
- this.toggleDrawer(this.currentDrawerPosition);
318
- }
319
- }
320
- /**
321
- * Clears any dynamically loaded component.
322
- * @private
323
- */
324
- clearDynamicContent() {
325
- if (this.drawerComponentHost) {
326
- this.drawerComponentHost.clear();
327
- }
328
- if (this.dynamicComponentRef) {
329
- this.dynamicComponentRef.destroy();
330
- this.dynamicComponentRef = null;
331
- }
332
- }
333
- /**
334
- * Angular lifecycle hook that is called clear dynamic component content.
335
- */
336
- ngOnDestroy() {
337
- this.clearDynamicContent();
338
- }
339
- }
340
- RuclibDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
341
- RuclibDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: RuclibDrawerComponent, selector: "uxp-ruclib-drawer", inputs: { rucInputData: "rucInputData", customTheme: "customTheme" }, outputs: { rucEvent: "rucEvent" }, host: { listeners: { "document:keydown.escape": "onKeydownHandler($event)" } }, viewQueries: [{ propertyName: "drawerComponentHost", first: true, predicate: ["drawerComponentHost"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- \r\n Custom Backdrop element.\r\n Visible only when:\r\n - rucInputData.mode is 'over'\r\n - rucInputData.hasBackdrop is true (or undefined, defaulting to true)\r\n - drawerAnimationState is 'in' (drawer is open or opening)\r\n Animates using 'backdropFade' trigger.\r\n Clicking the backdrop will toggle the drawer for the current position.\r\n Background color can be customized via rucInputData.backdropBackgroundColor.\r\n-->\r\n<div class=\"custom-backdrop\"\r\n *ngIf=\"rucInputData.mode === 'over' && (rucInputData.hasBackdrop ?? true) && drawerAnimationState === 'in'\"\r\n [@backdropFade]=\"backdropAnimationParams\"\r\n (click)=\"handleBackdropClick()\"\r\n [style.background-color]=\"rucInputData.hasBackdrop ? rucInputData.backdropBackgroundColor : ''\">\r\n</div>\r\n\r\n<!-- \r\n Custom Dynamic Drawer element.\r\n This is the main panel that slides in and out.\r\n - Applies CSS classes based on currentDrawerPosition and customTheme.\r\n - Dynamically sets width and height based on drawer orientation and input data.\r\n - Uses one of four animation triggers (slideInOutLeft, slideInOutRight, slideInOutTop, slideInOutBottom)\r\n based on currentDrawerPosition. Only the active trigger runs its animation; others are set to an\r\n instant 'out' state to prevent interference.\r\n - Animation completion events are handled by onAnimationDone().\r\n-->\r\n<div class=\"dynamic-drawer\"\r\n [ngClass]=\"'drawer-' + currentDrawerPosition + ' ' + (customTheme || '')\"\r\n [style.width]=\"!isVerticalLayout ? effectiveDrawerDimension : '100%'\"\r\n [style.height]=\"isVerticalLayout ? effectiveDrawerDimension : '100%'\"\r\n\r\n [@slideInOutLeft]=\"currentDrawerPosition === 'left' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutLeft.done)=\"currentDrawerPosition === 'left' && onAnimationDone($event)\"\r\n\r\n [@slideInOutRight]=\"currentDrawerPosition === 'right' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutRight.done)=\"currentDrawerPosition === 'right' && onAnimationDone($event)\"\r\n\r\n [@slideInOutTop]=\"currentDrawerPosition === 'top' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutTop.done)=\"currentDrawerPosition === 'top' && onAnimationDone($event)\"\r\n\r\n [@slideInOutBottom]=\"currentDrawerPosition === 'bottom' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutBottom.done)=\"currentDrawerPosition === 'bottom' && onAnimationDone($event)\">\r\n\r\n <!-- Wrapper for the content inside the drawer, handles padding and layout. -->\r\n <div class=\"drawer-content-wrapper\">\r\n <!-- Optional title for the drawer. -->\r\n <h2 *ngIf=\"rucInputData.content?.drawerTitle\" class=\"ruclib-drawer-title\">\r\n {{ rucInputData.content?.drawerTitle }}\r\n </h2>\r\n <!-- \r\n Optional close button inside the drawer.\r\n Toggles the drawer for the current position when clicked.\r\n ARIA label provides accessibility.\r\n Dimensions can be customized via rucInputData.closeButtonDimensions.\r\n -->\r\n <button *ngIf=\"rucInputData.showCloseIcon\"\r\n mat-icon-button class=\"ruclib-drawer-close-button\"\r\n (click)=\"toggleDrawer(currentDrawerPosition)\"\r\n [attr.aria-label]=\"'Close ' + currentDrawerPosition + ' drawer'\"\r\n [style.width]=\"rucInputData.closeButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.closeButtonDimensions?.height\">\r\n <!-- Material icon for the close button. Size can be customized. -->\r\n <mat-icon [style.font-size]=\"rucInputData.closeButtonDimensions?.iconSize\">close</mat-icon>\r\n </button>\r\n <!-- Main body content of the drawer. -->\r\n <div class=\"ruclib-drawer-body\">\r\n <!-- Host for dynamically injected component -->\r\n <ng-template #drawerComponentHost></ng-template>\r\n <!-- Fallback to HTML content if no component is provided -->\r\n <div *ngIf=\"!rucInputData.content?.drawerContentComponent\" [innerHTML]=\"rucInputData.content?.drawerBody || '' | safeHtml\"></div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Material Drawer Container.\r\n Acts as the main container for the drawer system, especially if 'side' or 'push' modes\r\n were to be implemented with MatDrawer's native behavior. With custom fixed-position animations,\r\n its primary role here is to host the mat-drawer-content.\r\n - Applies 'vertical-layout' class if the drawer is top/bottom.\r\n - MatDrawer's own backdrop is disabled as a custom one is used.\r\n-->\r\n<mat-drawer-container\r\n class=\"ruclib-drawer-container\"\r\n [class.vertical-layout]=\"isVerticalLayout\"\r\n [hasBackdrop]=\"false\"> <!-- MatDrawer's backdrop is not used with custom animation -->\r\n <mat-drawer-content class=\"ruclib-main-content\">\r\n <button [disabled]=\"rucInputData.disableToggleButtonInMainContent\"\r\n mat-raised-button\r\n color=\"primary\"\r\n title=\"Toggle Drawer\"\r\n class=\"drawer-toggle-button\"\r\n [style.width]=\"rucInputData.toggleButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.toggleButtonDimensions?.height\"\r\n [style.padding]=\"rucInputData.toggleButtonDimensions?.padding\"\r\n [style.font-size]=\"rucInputData.toggleButtonDimensions?.fontSize\"\r\n (click)=\"toggleDrawer(currentDrawerPosition)\"\r\n [attr.aria-label]=\"getToggleButtonAriaLabel()\"\r\n [attr.aria-expanded]=\"drawerAnimationState === 'in'\">\r\n <!-- Optional Material icon for the toggle button. Show only if no image URL is provided. -->\r\n <mat-icon *ngIf=\"rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl\" [style.font-size]=\"rucInputData.toggleButtonDimensions?.iconSize\">{{ rucInputData.toggleButtonIcon }}</mat-icon>\r\n <!-- Optional image for the toggle button. If present, it should fill the button. -->\r\n <img *ngIf=\"rucInputData.toggleButtonImageUrl\"\r\n [src]=\"rucInputData.toggleButtonImageUrl\"\r\n [alt]=\"rucInputData.toggleButtonImageAlt || 'Toggle Drawer'\"\r\n class=\"ruclib-drawer-toggle-image\"\r\n [style.width]=\"rucInputData.toggleButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.toggleButtonDimensions?.height\"\r\n [style.padding]=\"rucInputData.toggleButtonDimensions?.padding\">\r\n <!-- Text for the toggle button. Show only if NO icon AND NO image URL is provided. -->\r\n <span *ngIf=\"!rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl && (rucInputData.toggleButtonText?.open || rucInputData.toggleButtonText?.close)\">\r\n {{ drawerAnimationState === 'in' ? (rucInputData.toggleButtonText?.close || 'Close') : (rucInputData.toggleButtonText?.open || 'Open') }}\r\n </span>\r\n <!-- Text for the toggle button when an icon (but NO image) IS also present. -->\r\n <span *ngIf=\"rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl && (rucInputData.toggleButtonText?.open || rucInputData.toggleButtonText?.close)\" class=\"toggle-button-text-with-icon\">\r\n {{ drawerAnimationState === 'in' ? (rucInputData.toggleButtonText?.close || 'Close') : (rucInputData.toggleButtonText?.open || 'Open') }}\r\n </span>\r\n </button>\r\n <!-- Main application content area, rendered from HTML string via safeHtml pipe. -->\r\n <div [innerHTML]=\"rucInputData.content?.mainBody || '' | safeHtml\"></div>\r\n </mat-drawer-content>\r\n</mat-drawer-container>", styles: [".custom-backdrop{position:absolute;inset:0;background-color:#000;z-index:999;visibility:hidden}.ruclib-drawer-container{width:100%;height:400px;border:1px solid #ccc;position:relative;overflow:hidden}.drawer-content-wrapper{padding:16px;position:relative;box-sizing:border-box;height:100%;display:flex;flex-direction:column}.ruclib-drawer-title{margin-top:0;margin-bottom:16px;font-size:1.5em;flex-shrink:0}.ruclib-drawer-close-button{position:absolute;top:8px;right:8px;padding:5px 0 0!important;flex-shrink:0}.ruclib-drawer-body{flex-grow:1;overflow-y:auto;word-break:break-word}.dynamic-drawer{background-color:var(--mat-sidenav-content-background-color, white);position:absolute;box-sizing:border-box;box-shadow:0 2px 10px #0003;z-index:1000;overflow:hidden}.dynamic-drawer.drawer-left{top:0;bottom:0;left:0}.dynamic-drawer.drawer-right{top:0;bottom:0;right:0}.dynamic-drawer.drawer-top{top:0;left:0;right:0}.dynamic-drawer.drawer-bottom{bottom:0;left:0;right:0}.dynamic-drawer.light-theme{background-color:#fff;color:#000000de}.dynamic-drawer.light-theme .ruclib-drawer-title{color:#000000de}.dynamic-drawer.light-theme .ruclib-drawer-close-button .mat-icon{color:#0000008a}.dynamic-drawer.dark-theme{background-color:#424242;color:#fff}.dynamic-drawer.dark-theme .ruclib-drawer-title,.dynamic-drawer.dark-theme .ruclib-drawer-close-button .mat-icon{color:#fff}.dynamic-drawer.custom-theme-one{background-color:#fff;color:#000000de}.dynamic-drawer.custom-theme-one .ruclib-drawer-title{color:#000000de}.dynamic-drawer.custom-theme-one .ruclib-drawer-close-button .mat-icon{color:#0000008a}.dynamic-drawer.custom-theme-two{background-color:#424242;color:#fff}.dynamic-drawer.custom-theme-two .ruclib-drawer-title,.dynamic-drawer.custom-theme-two .ruclib-drawer-close-button .mat-icon{color:#fff}.ruclib-drawer-toggle-image{object-fit:contain;display:block}.drawer-toggle-button{margin-bottom:15px;display:inline-flex;align-items:center;justify-content:center;gap:8px}.ruclib-main-content{padding:16px;display:flex;flex-direction:column;align-items:flex-start}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i4.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "pipe", type: i5.SafeHtmlPipe, name: "safeHtml" }], animations: [
342
- trigger('backdropFade', [
343
- state('out', style({ opacity: 0, visibility: 'hidden' })),
344
- state('in', style({ opacity: 0.6, visibility: 'visible' })),
345
- transition('out => in', animate('{{duration}} ease-in')),
346
- transition('in => out', animate('{{duration}} ease-out')),
347
- ]),
348
- trigger('slideInOutLeft', [
349
- state('out', style({ transform: 'translateX(-100%)', visibility: 'hidden' })),
350
- state('in', style({ transform: 'translateX(0)', visibility: 'visible' })),
351
- transition('out <=> in', animate('{{duration}} ease-in-out')),
352
- ]),
353
- trigger('slideInOutRight', [
354
- state('out', style({ transform: 'translateX(100%)', visibility: 'hidden' })),
355
- state('in', style({ transform: 'translateX(0)', visibility: 'visible' })),
356
- transition('out <=> in', animate('{{duration}} ease-in-out')),
357
- ]),
358
- trigger('slideInOutTop', [
359
- state('out', style({ transform: 'translateY(-100%)', visibility: 'hidden' })),
360
- state('in', style({ transform: 'translateY(0%)', visibility: 'visible' })),
361
- transition('out <=> in', animate('{{duration}} ease-in-out')),
362
- ]),
363
- trigger('slideInOutBottom', [
364
- state('out', style({ transform: 'translateY(100%)', visibility: 'hidden' })),
365
- state('in', style({ transform: 'translateY(0%)', visibility: 'visible' })),
366
- transition('out <=> in', animate('{{duration}} ease-in-out')),
367
- ])
368
- ] });
369
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerComponent, decorators: [{
370
- type: Component,
371
- args: [{ selector: 'uxp-ruclib-drawer', animations: [
372
- trigger('backdropFade', [
373
- state('out', style({ opacity: 0, visibility: 'hidden' })),
374
- state('in', style({ opacity: 0.6, visibility: 'visible' })),
375
- transition('out => in', animate('{{duration}} ease-in')),
376
- transition('in => out', animate('{{duration}} ease-out')),
377
- ]),
378
- trigger('slideInOutLeft', [
379
- state('out', style({ transform: 'translateX(-100%)', visibility: 'hidden' })),
380
- state('in', style({ transform: 'translateX(0)', visibility: 'visible' })),
381
- transition('out <=> in', animate('{{duration}} ease-in-out')),
382
- ]),
383
- trigger('slideInOutRight', [
384
- state('out', style({ transform: 'translateX(100%)', visibility: 'hidden' })),
385
- state('in', style({ transform: 'translateX(0)', visibility: 'visible' })),
386
- transition('out <=> in', animate('{{duration}} ease-in-out')),
387
- ]),
388
- trigger('slideInOutTop', [
389
- state('out', style({ transform: 'translateY(-100%)', visibility: 'hidden' })),
390
- state('in', style({ transform: 'translateY(0%)', visibility: 'visible' })),
391
- transition('out <=> in', animate('{{duration}} ease-in-out')),
392
- ]),
393
- trigger('slideInOutBottom', [
394
- state('out', style({ transform: 'translateY(100%)', visibility: 'hidden' })),
395
- state('in', style({ transform: 'translateY(0%)', visibility: 'visible' })),
396
- transition('out <=> in', animate('{{duration}} ease-in-out')),
397
- ])
398
- ], template: "<!-- \r\n Custom Backdrop element.\r\n Visible only when:\r\n - rucInputData.mode is 'over'\r\n - rucInputData.hasBackdrop is true (or undefined, defaulting to true)\r\n - drawerAnimationState is 'in' (drawer is open or opening)\r\n Animates using 'backdropFade' trigger.\r\n Clicking the backdrop will toggle the drawer for the current position.\r\n Background color can be customized via rucInputData.backdropBackgroundColor.\r\n-->\r\n<div class=\"custom-backdrop\"\r\n *ngIf=\"rucInputData.mode === 'over' && (rucInputData.hasBackdrop ?? true) && drawerAnimationState === 'in'\"\r\n [@backdropFade]=\"backdropAnimationParams\"\r\n (click)=\"handleBackdropClick()\"\r\n [style.background-color]=\"rucInputData.hasBackdrop ? rucInputData.backdropBackgroundColor : ''\">\r\n</div>\r\n\r\n<!-- \r\n Custom Dynamic Drawer element.\r\n This is the main panel that slides in and out.\r\n - Applies CSS classes based on currentDrawerPosition and customTheme.\r\n - Dynamically sets width and height based on drawer orientation and input data.\r\n - Uses one of four animation triggers (slideInOutLeft, slideInOutRight, slideInOutTop, slideInOutBottom)\r\n based on currentDrawerPosition. Only the active trigger runs its animation; others are set to an\r\n instant 'out' state to prevent interference.\r\n - Animation completion events are handled by onAnimationDone().\r\n-->\r\n<div class=\"dynamic-drawer\"\r\n [ngClass]=\"'drawer-' + currentDrawerPosition + ' ' + (customTheme || '')\"\r\n [style.width]=\"!isVerticalLayout ? effectiveDrawerDimension : '100%'\"\r\n [style.height]=\"isVerticalLayout ? effectiveDrawerDimension : '100%'\"\r\n\r\n [@slideInOutLeft]=\"currentDrawerPosition === 'left' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutLeft.done)=\"currentDrawerPosition === 'left' && onAnimationDone($event)\"\r\n\r\n [@slideInOutRight]=\"currentDrawerPosition === 'right' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutRight.done)=\"currentDrawerPosition === 'right' && onAnimationDone($event)\"\r\n\r\n [@slideInOutTop]=\"currentDrawerPosition === 'top' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutTop.done)=\"currentDrawerPosition === 'top' && onAnimationDone($event)\"\r\n\r\n [@slideInOutBottom]=\"currentDrawerPosition === 'bottom' ? animationParams : {value: 'out', params: {duration: '0ms'}}\"\r\n (@slideInOutBottom.done)=\"currentDrawerPosition === 'bottom' && onAnimationDone($event)\">\r\n\r\n <!-- Wrapper for the content inside the drawer, handles padding and layout. -->\r\n <div class=\"drawer-content-wrapper\">\r\n <!-- Optional title for the drawer. -->\r\n <h2 *ngIf=\"rucInputData.content?.drawerTitle\" class=\"ruclib-drawer-title\">\r\n {{ rucInputData.content?.drawerTitle }}\r\n </h2>\r\n <!-- \r\n Optional close button inside the drawer.\r\n Toggles the drawer for the current position when clicked.\r\n ARIA label provides accessibility.\r\n Dimensions can be customized via rucInputData.closeButtonDimensions.\r\n -->\r\n <button *ngIf=\"rucInputData.showCloseIcon\"\r\n mat-icon-button class=\"ruclib-drawer-close-button\"\r\n (click)=\"toggleDrawer(currentDrawerPosition)\"\r\n [attr.aria-label]=\"'Close ' + currentDrawerPosition + ' drawer'\"\r\n [style.width]=\"rucInputData.closeButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.closeButtonDimensions?.height\">\r\n <!-- Material icon for the close button. Size can be customized. -->\r\n <mat-icon [style.font-size]=\"rucInputData.closeButtonDimensions?.iconSize\">close</mat-icon>\r\n </button>\r\n <!-- Main body content of the drawer. -->\r\n <div class=\"ruclib-drawer-body\">\r\n <!-- Host for dynamically injected component -->\r\n <ng-template #drawerComponentHost></ng-template>\r\n <!-- Fallback to HTML content if no component is provided -->\r\n <div *ngIf=\"!rucInputData.content?.drawerContentComponent\" [innerHTML]=\"rucInputData.content?.drawerBody || '' | safeHtml\"></div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n Angular Material Drawer Container.\r\n Acts as the main container for the drawer system, especially if 'side' or 'push' modes\r\n were to be implemented with MatDrawer's native behavior. With custom fixed-position animations,\r\n its primary role here is to host the mat-drawer-content.\r\n - Applies 'vertical-layout' class if the drawer is top/bottom.\r\n - MatDrawer's own backdrop is disabled as a custom one is used.\r\n-->\r\n<mat-drawer-container\r\n class=\"ruclib-drawer-container\"\r\n [class.vertical-layout]=\"isVerticalLayout\"\r\n [hasBackdrop]=\"false\"> <!-- MatDrawer's backdrop is not used with custom animation -->\r\n <mat-drawer-content class=\"ruclib-main-content\">\r\n <button [disabled]=\"rucInputData.disableToggleButtonInMainContent\"\r\n mat-raised-button\r\n color=\"primary\"\r\n title=\"Toggle Drawer\"\r\n class=\"drawer-toggle-button\"\r\n [style.width]=\"rucInputData.toggleButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.toggleButtonDimensions?.height\"\r\n [style.padding]=\"rucInputData.toggleButtonDimensions?.padding\"\r\n [style.font-size]=\"rucInputData.toggleButtonDimensions?.fontSize\"\r\n (click)=\"toggleDrawer(currentDrawerPosition)\"\r\n [attr.aria-label]=\"getToggleButtonAriaLabel()\"\r\n [attr.aria-expanded]=\"drawerAnimationState === 'in'\">\r\n <!-- Optional Material icon for the toggle button. Show only if no image URL is provided. -->\r\n <mat-icon *ngIf=\"rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl\" [style.font-size]=\"rucInputData.toggleButtonDimensions?.iconSize\">{{ rucInputData.toggleButtonIcon }}</mat-icon>\r\n <!-- Optional image for the toggle button. If present, it should fill the button. -->\r\n <img *ngIf=\"rucInputData.toggleButtonImageUrl\"\r\n [src]=\"rucInputData.toggleButtonImageUrl\"\r\n [alt]=\"rucInputData.toggleButtonImageAlt || 'Toggle Drawer'\"\r\n class=\"ruclib-drawer-toggle-image\"\r\n [style.width]=\"rucInputData.toggleButtonDimensions?.width\"\r\n [style.height]=\"rucInputData.toggleButtonDimensions?.height\"\r\n [style.padding]=\"rucInputData.toggleButtonDimensions?.padding\">\r\n <!-- Text for the toggle button. Show only if NO icon AND NO image URL is provided. -->\r\n <span *ngIf=\"!rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl && (rucInputData.toggleButtonText?.open || rucInputData.toggleButtonText?.close)\">\r\n {{ drawerAnimationState === 'in' ? (rucInputData.toggleButtonText?.close || 'Close') : (rucInputData.toggleButtonText?.open || 'Open') }}\r\n </span>\r\n <!-- Text for the toggle button when an icon (but NO image) IS also present. -->\r\n <span *ngIf=\"rucInputData.toggleButtonIcon && !rucInputData.toggleButtonImageUrl && (rucInputData.toggleButtonText?.open || rucInputData.toggleButtonText?.close)\" class=\"toggle-button-text-with-icon\">\r\n {{ drawerAnimationState === 'in' ? (rucInputData.toggleButtonText?.close || 'Close') : (rucInputData.toggleButtonText?.open || 'Open') }}\r\n </span>\r\n </button>\r\n <!-- Main application content area, rendered from HTML string via safeHtml pipe. -->\r\n <div [innerHTML]=\"rucInputData.content?.mainBody || '' | safeHtml\"></div>\r\n </mat-drawer-content>\r\n</mat-drawer-container>", styles: [".custom-backdrop{position:absolute;inset:0;background-color:#000;z-index:999;visibility:hidden}.ruclib-drawer-container{width:100%;height:400px;border:1px solid #ccc;position:relative;overflow:hidden}.drawer-content-wrapper{padding:16px;position:relative;box-sizing:border-box;height:100%;display:flex;flex-direction:column}.ruclib-drawer-title{margin-top:0;margin-bottom:16px;font-size:1.5em;flex-shrink:0}.ruclib-drawer-close-button{position:absolute;top:8px;right:8px;padding:5px 0 0!important;flex-shrink:0}.ruclib-drawer-body{flex-grow:1;overflow-y:auto;word-break:break-word}.dynamic-drawer{background-color:var(--mat-sidenav-content-background-color, white);position:absolute;box-sizing:border-box;box-shadow:0 2px 10px #0003;z-index:1000;overflow:hidden}.dynamic-drawer.drawer-left{top:0;bottom:0;left:0}.dynamic-drawer.drawer-right{top:0;bottom:0;right:0}.dynamic-drawer.drawer-top{top:0;left:0;right:0}.dynamic-drawer.drawer-bottom{bottom:0;left:0;right:0}.dynamic-drawer.light-theme{background-color:#fff;color:#000000de}.dynamic-drawer.light-theme .ruclib-drawer-title{color:#000000de}.dynamic-drawer.light-theme .ruclib-drawer-close-button .mat-icon{color:#0000008a}.dynamic-drawer.dark-theme{background-color:#424242;color:#fff}.dynamic-drawer.dark-theme .ruclib-drawer-title,.dynamic-drawer.dark-theme .ruclib-drawer-close-button .mat-icon{color:#fff}.dynamic-drawer.custom-theme-one{background-color:#fff;color:#000000de}.dynamic-drawer.custom-theme-one .ruclib-drawer-title{color:#000000de}.dynamic-drawer.custom-theme-one .ruclib-drawer-close-button .mat-icon{color:#0000008a}.dynamic-drawer.custom-theme-two{background-color:#424242;color:#fff}.dynamic-drawer.custom-theme-two .ruclib-drawer-title,.dynamic-drawer.custom-theme-two .ruclib-drawer-close-button .mat-icon{color:#fff}.ruclib-drawer-toggle-image{object-fit:contain;display:block}.drawer-toggle-button{margin-bottom:15px;display:inline-flex;align-items:center;justify-content:center;gap:8px}.ruclib-main-content{padding:16px;display:flex;flex-direction:column;align-items:flex-start}\n"] }]
399
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { rucInputData: [{
400
- type: Input
401
- }], customTheme: [{
402
- type: Input
403
- }], rucEvent: [{
404
- type: Output
405
- }], drawerComponentHost: [{
406
- type: ViewChild,
407
- args: ['drawerComponentHost', { read: ViewContainerRef, static: true }]
408
- }], onKeydownHandler: [{
409
- type: HostListener,
410
- args: ['document:keydown.escape', ['$event']]
411
- }] } });
412
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjbGliLWRyYXdlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3J1Y2xpYi1kcmF3ZXIvcnVjbGliLWRyYXdlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9zcmMvbGliL3J1Y2xpYi1kcmF3ZXIvcnVjbGliLWRyYXdlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBb0MsTUFBTSxFQUFFLFlBQVksRUFBaUIsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBMkIsTUFBTSxlQUFlLENBQUM7QUFDL00sT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQWtCLE1BQU0scUJBQXFCLENBQUM7Ozs7Ozs7QUFJakc7Ozs7R0FJRztBQWtDSCxNQUFNLE9BQU8scUJBQXFCO0lBK0VoQyxZQUNVLEdBQXNCO1FBQXRCLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBL0VoQzs7O1dBR0c7UUFDTSxpQkFBWSxHQUFzQixFQUFFLENBQUM7UUFNOUM7Ozs7V0FJRztRQUNPLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBSzdDLHNEQUFzRDtRQUM5Qyx3QkFBbUIsR0FBNkIsSUFBSSxDQUFDO1FBRTdEOzs7V0FHRztRQUNJLHlCQUFvQixHQUFpQixLQUFLLENBQUM7UUFDbEQ7Ozs7V0FJRztRQUNJLDBCQUFxQixHQUF3QyxNQUFNLENBQUMsQ0FBQyxVQUFVO1FBQ3RGOzs7O1dBSUc7UUFDSywwQkFBcUIsR0FBK0MsSUFBSSxDQUFDO1FBQ2pGOzs7V0FHRztRQUNJLGdCQUFXLEdBQVksS0FBSyxDQUFDO1FBQ3BDOzs7O1dBSUc7UUFDSSwrQkFBMEIsR0FBVyxPQUFPLENBQUM7UUFFcEQ7Ozs7V0FJRztRQUNJLGtCQUFhLEdBQWtCLE1BQU0s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QUUsbUJBQW1CLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7NEJBQzdFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDOzRCQUMxRSxVQUFVLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO3lCQUM5RCxDQUFDO3dCQUNGLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRTs0QkFDMUIsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxTQUFTLEVBQUUsa0JBQWtCLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7NEJBQzVFLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDOzRCQUMxRSxVQUFVLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO3lCQUM5RCxDQUFDO3FCQUNIO3dHQU9RLFlBQVk7c0JBQXBCLEtBQUs7Z0JBS0csV0FBVztzQkFBbkIsS0FBSztnQkFNSSxRQUFRO3NCQUFqQixNQUFNO2dCQUdxRSxtQkFBbUI7c0JBQTlGLFNBQVM7dUJBQUMscUJBQXFCLEVBQUUsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkF1VDFFLGdCQUFnQjtzQkFEZixZQUFZO3VCQUFDLHlCQUF5QixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0LCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBBZnRlclZpZXdJbml0LCBDaGFuZ2VEZXRlY3RvclJlZiwgSG9zdExpc3RlbmVyLCBWaWV3Q2hpbGQsIFZpZXdDb250YWluZXJSZWYsIENvbXBvbmVudFJlZiwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgdHJhbnNpdGlvbiwgYW5pbWF0ZSwgQW5pbWF0aW9uRXZlbnQgfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcclxuaW1wb3J0IHsgTWF0RHJhd2VyTW9kZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NpZGVuYXYnO1xyXG5pbXBvcnQgeyBSdWNsaWJEcmF3ZXJJbnB1dCB9IGZyb20gJy4uLy4uL2ludGVyZmFjZS9kcmF3ZXInO1xyXG5cclxuLyoqXHJcbiAqIEBDb21wb25lbnQgUnVjbGliRHJhd2VyQ29tcG9uZW50XHJcbiAqIEBkZXNjcmlwdGlvbiBBIGhpZ2hseSBjb25maWd1cmFibGUgZHJhd2VyIGNvbXBvbmVudCB0aGF0IGNhbiBzbGlkZSBpbiBmcm9tIGFueSBvZiB0aGUgZm91ciBkaXJlY3Rpb25zIChsZWZ0LCByaWdodCwgdG9wLCBib3R0b20pLlxyXG4gKiBJdCB1c2VzIGN1c3RvbSBBbmd1bGFyIGFuaW1hdGlvbnMgZm9yIHNtb290aCB0cmFuc2l0aW9ucyBhbmQgc3VwcG9ydHMgdGhlbWluZy5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAndXhwLXJ1Y2xpYi1kcmF3ZXInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9ydWNsaWItZHJhd2VyLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9ydWNsaWItZHJhd2VyLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgYW5pbWF0aW9uczogW1xyXG4gICAgdHJpZ2dlcignYmFja2Ryb3BGYWRlJywgW1xyXG4gICAgICBzdGF0ZSgnb3V0Jywgc3R5bGUoeyBvcGFjaXR5OiAwLCB2aXNpYmlsaXR5OiAnaGlkZGVuJyB9KSksXHJcbiAgICAgIHN0YXRlKCdpbicsIHN0eWxlKHsgb3BhY2l0eTogMC42LCB2aXNpYmlsaXR5OiAndmlzaWJsZScgfSkpLFxyXG4gICAgICB0cmFuc2l0aW9uKCdvdXQgPT4gaW4nLCBhbmltYXRlKCd7e2R1cmF0aW9ufX0gZWFzZS1pbicpKSxcclxuICAgICAgdHJhbnNpdGlvbignaW4gPT4gb3V0JywgYW5pbWF0ZSgne3tkdXJhdGlvbn19IGVhc2Utb3V0JykpLFxyXG4gICAgXSksXHJcbiAgICB0cmlnZ2VyKCdzbGlkZUluT3V0TGVmdCcsIFtcclxuICAgICAgc3RhdGUoJ291dCcsIHN0eWxlKHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgtMTAwJSknLCB2aXNpYmlsaXR5OiAnaGlkZGVuJyB9KSksXHJcbiAgICAgIHN0YXRlKCdpbicsIHN0eWxlKHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKScsIHZpc2liaWxpdHk6ICd2aXNpYmxlJyB9KSksXHJcbiAgICAgIHRyYW5zaXRpb24oJ291dCA8PT4gaW4nLCBhbmltYXRlKCd7e2R1cmF0aW9ufX0gZWFzZS1pbi1vdXQnKSksXHJcbiAgICBdKSxcclxuICAgIHRyaWdnZXIoJ3NsaWRlSW5PdXRSaWdodCcsIFtcclxuICAgICAgc3RhdGUoJ291dCcsIHN0eWxlKHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgxMDAlKScsIHZpc2liaWxpdHk6ICdoaWRkZW4nIH0pKSxcclxuICAgICAgc3RhdGUoJ2luJywgc3R5bGUoeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDApJywgdmlzaWJpbGl0eTogJ3Zpc2libGUnIH0pKSxcclxuICAgICAgdHJhbnNpdGlvbignb3V0IDw9PiBpbicsIGFuaW1hdGUoJ3t7ZHVyYXRpb259fSBlYXNlLWluLW91dCcpKSxcclxuICAgIF0pLFxyXG4gICAgdHJpZ2dlcignc2xpZGVJbk91dFRvcCcsIFtcclxuICAgICAgc3RhdGUoJ291dCcsIHN0eWxlKHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWSgtMTAwJSknLCB2aXNpYmlsaXR5OiAnaGlkZGVuJyB9KSksXHJcbiAgICAgIHN0YXRlKCdpbicsIHN0eWxlKHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlWSgwJSknLCB2aXNpYmlsaXR5OiAndmlzaWJsZScgfSkpLFxyXG4gICAgICB0cmFuc2l0aW9uKCdvdXQgPD0+IGluJywgYW5pbWF0ZSgne3tkdXJhdGlvbn19IGVhc2UtaW4tb3V0JykpLFxyXG4gICAgXSksXHJcbiAgICB0cmlnZ2VyKCdzbGlkZUluT3V0Qm90dG9tJywgW1xyXG4gICAgICBzdGF0ZSgnb3V0Jywgc3R5bGUoeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKDEwMCUpJywgdmlzaWJpbGl0eTogJ2hpZGRlbicgfSkpLFxyXG4gICAgICBzdGF0ZSgnaW4nLCBzdHlsZSh7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVkoMCUpJywgdmlzaWJpbGl0eTogJ3Zpc2libGUnIH0pKSxcclxuICAgICAgdHJhbnNpdGlvbignb3V0IDw9PiBpbicsIGFuaW1hdGUoJ3t7ZHVyYXRpb259fSBlYXNlLWluLW91dCcpKSxcclxuICAgIF0pXHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUnVjbGliRHJhd2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XHJcbiAgLyoqXHJcbiAgICogSW5wdXQgZGF0YSBmb3IgY29uZmlndXJpbmcgdGhlIGRyYXdlcidzIGFwcGVhcmFuY2UgYW5kIGJlaGF2aW9yLlxyXG4gICAqIEBzZWUgUnVjbGliRHJhd2VySW5wdXQgaW50ZXJmYWNlIGZvciBkZXRhaWxlZCBwcm9wZXJ0aWVzLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHJ1Y0lucHV0RGF0YTogUnVjbGliRHJhd2VySW5wdXQgPSB7fTtcclxuICAvKipcclxuICAgKiBPcHRpb25hbCBjdXN0b20gdGhlbWUgY2xhc3MgdG8gYmUgYXBwbGllZCB0byB0aGUgZHJhd2VyIHBhbmVsLlxyXG4gICAqIEBleGFtcGxlICdkYXJrLXRoZW1lJywgJ2N1c3RvbS10aGVtZS1vbmUnXHJcbiAgICovXHJcbiAgQElucHV0KCkgY3VzdG9tVGhlbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcclxuICAvKipcclxuICAgKiBFdmVudEVtaXR0ZXIgZm9yIHZhcmlvdXMgZHJhd2VyIGV2ZW50cy5cclxuICAgKiBFbWl0cyBvYmplY3RzIHdpdGggYHR5cGVgIChlLmcuLCAnb3BlbmVkU3RhcnQnLCAnY2xvc2VkU3RhcnQnLCAnb3BlbmVkQ2hhbmdlJywgJ2RyYXdlclRvZ2dsZScpXHJcbiAgICogYW5kIGBvcGVuZWRgIChib29sZWFuKSBhbmQgYHBvc2l0aW9uYCAoc3RyaW5nKSBwcm9wZXJ0aWVzLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBydWNFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICAvKiogVmlld0NvbnRhaW5lclJlZiB0byBob3N0IHRoZSBkeW5hbWljYWxseSBsb2FkZWQgY29tcG9uZW50LiAqL1xyXG4gIEBWaWV3Q2hpbGQoJ2RyYXdlckNvbXBvbmVudEhvc3QnLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYsIHN0YXRpYzogdHJ1ZSB9KSBkcmF3ZXJDb21wb25lbnRIb3N0ITogVmlld0NvbnRhaW5lclJlZjtcclxuXHJcbiAgLyoqIFJlZmVyZW5jZSB0byB0aGUgZHluYW1pY2FsbHkgY3JlYXRlZCBjb21wb25lbnQuICovXHJcbiAgcHJpdmF0ZSBkeW5hbWljQ29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8YW55PiB8IG51bGwgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBDdXJyZW50IGFuaW1hdGlvbiBzdGF0ZSBvZiB0aGUgZHJhd2VyICgnaW4nIG9yICdvdXQnKS5cclxuICAgKiBAcHVibGljXHJcbiAgICovXHJcbiAgcHVibGljIGRyYXdlckFuaW1hdGlvblN0YXRlOiAnaW4nIHwgJ291dCcgPSAnb3V0JztcclxuICAvKipcclxuICAgKiBDdXJyZW50IGFjdGl2ZSBwb3NpdGlvbiBvZiB0aGUgZHJhd2VyLlxyXG4gICAqIEBwdWJsaWNcclxuICAgKiBAZGVmYXVsdCAnbGVmdCdcclxuICAgKi9cclxuICBwdWJsaWMgY3VycmVudERyYXdlclBvc2l0aW9uOiAnbGVmdCcgfCAncmlnaHQnIHwgJ3RvcCcgfCAnYm90dG9tJyA9ICdsZWZ0JzsgLy8gRGVmYXVsdFxyXG4gIC8qKlxyXG4gICAqIFN0b3JlcyB0aGUgbmV4dCBwb3NpdGlvbiBpZiB0aGUgZHJhd2VyIGlzIGN1cnJlbnRseSBvcGVuIGFuZCBhIG5ldyBwb3NpdGlvbiBpcyByZXF1ZXN0ZWQuXHJcbiAgICogVXNlZCB0byBzZXF1ZW5jZSBjbG9zZSBhbmQgb3BlbiBhbmltYXRpb25zLlxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwZW5kaW5nRHJhd2VyUG9zaXRpb246ICdsZWZ0JyB8ICdyaWdodCcgfCAndG9wJyB8ICdib3R0b20nIHwgbnVsbCA9IG51bGw7XHJcbiAgLyoqXHJcbiAgICogRmxhZyB0byBpbmRpY2F0ZSBpZiBhbiBhbmltYXRpb24gaXMgY3VycmVudGx5IGluIHByb2dyZXNzIHRvIHByZXZlbnQgcmFwaWQgdG9nZ2xpbmcuXHJcbiAgICogQHB1YmxpY1xyXG4gICAqL1xyXG4gIHB1YmxpYyBpc0FuaW1hdGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKlxyXG4gICAqIEVmZmVjdGl2ZSBhbmltYXRpb24gZHVyYXRpb24gZm9yIHRoZSBkcmF3ZXIsIGRlcml2ZWQgZnJvbSBpbnB1dCBvciBkZWZhdWx0LlxyXG4gICAqIEBwdWJsaWNcclxuICAgKiBAZGVmYXVsdCAnMzAwbXMnXHJcbiAgICovXHJcbiAgcHVibGljIGVmZmVjdGl2ZUFuaW1hdGlvbkR1cmF0aW9uOiBzdHJpbmcgPSAnMzAwbXMnO1xyXG5cclxuICAvKipcclxuICAgKiBNb2RlIG9mIHRoZSBkcmF3ZXIsIHByaW1hcmlseSBmb3IgZGV0ZXJtaW5pbmcgYmFja2Ryb3AgYmVoYXZpb3Igd2l0aCBjdXN0b20gYW5pbWF0aW9ucy5cclxuICAgKiBAcHVibGljXHJcbiAgICogQGRlZmF1bHQgJ3NpZGUnXHJcbiAgICovXHJcbiAgcHVibGljIG1hdERyYXdlck1vZGU6IE1hdERyYXdlck1vZGUgPSAnc2lkZSc7XHJcbiAgLyoqXHJcbiAgICogQWN0dWFsIHBvc2l0aW9uICgnc3RhcnQnIG9yICdlbmQnKSB1c2VkIGJ5IEFuZ3VsYXIgTWF0ZXJpYWwncyBNYXREcmF3ZXIgaWYgaXQgd2VyZSBkaXJlY3RseSB1c2VkLlxyXG4gICAqIFJldGFpbmVkIGZvciBsb2dpY2FsIGNvbnNpc3RlbmN5IGluIGRldGVybWluaW5nIGxheW91dC5cclxuICAgKiBAcHVibGljXHJcbiAgICogQGRlZmF1bHQgJ3N0YXJ0J1xyXG4gICAqL1xyXG4gIHB1YmxpYyBtYXRBY3R1YWxQb3NpdGlvbjogJ3N0YXJ0JyB8ICdlbmQnID0gJ3N0YXJ0JztcclxuICAvKipcclxuICAgKiBGbGFnIGluZGljYXRpbmcgaWYgdGhlIGRyYXdlciBpcyBpbiBhIHZlcnRpY2FsIGxheW91dCAodG9wL2JvdHRvbSkuXHJcbiAgICogSGVscHMgZGV0ZXJtaW5lIGlmIHdpZHRoIG9yIGhlaWdodCBzaG91bGQgYmUgMTAwJS5cclxuICAgKiBAcHVibGljXHJcbiAgICovXHJcbiAgcHVibGljIGlzVmVydGljYWxMYXlvdXQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAvKipcclxuICAgKiBFZmZlY3RpdmUgZGltZW5zaW9uICh3aWR0aCBvciBoZWlnaHQpIG9mIHRoZSBkcmF3ZXIgcGFuZWwuXHJcbiAgICogQHB1YmxpY1xyXG4gICAqIEBkZWZhdWx0ICcyNTBweCdcclxuICAgKi9cclxuICBwdWJsaWMgZWZmZWN0aXZlRHJhd2VyRGltZW5zaW9uOiBzdHJpbmcgPSAnMjUwcHgnO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZlxyXG4gICkgeyB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2sgdGhhdCBpcyBjYWxsZWQgYWZ0ZXIgZGF0YS1ib3VuZCBwcm9wZXJ0aWVzIG9mIGEgZGlyZWN0aXZlIGFyZSBpbml0aWFsaXplZC5cclxuICAgKi9cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuYXBwbHlJbnB1dHMoKTtcclxuICAgIHRoaXMuZHJhd2VyQW5pbWF0aW9uU3RhdGUgPSAnb3V0JztcclxuICAgIHRoaXMubG9hZER5bmFtaWNDb250ZW50KCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBbmd1bGFyIGxpZmVjeWNsZSBob29rIHRoYXQgaXMgY2FsbGVkIGFmdGVyIEFuZ3VsYXIgaGFzIGZ1bGx5IGluaXRpYWxpemVkIGEgY29tcG9uZW50J3Mgdmlldy5cclxuICAgKi9cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5ydWNJbnB1dERhdGEuaW5pdGlhbE9wZW5lZFN0YXRlICYmIHRoaXMuZHJhd2VyQW5pbWF0aW9uU3RhdGUgPT09ICdvdXQnKSB7XHJcbiAgICAgIC8vIERlZmVyIHN0YXRlIHVwZGF0ZSB0byB0aGUgbmV4dCBtaWNyb3Rhc2sgcXVldWUuXHJcbiAgICAgIC8vIFRoaXMgaGVscHMgYXZvaWQgRXhwcmVzc2lvbkNoYW5nZWRBZnRlckl0SGFzQmVlbkNoZWNrZWRFcnJvciB3aGVuIGluaXRpYWxpemluZyB0aGUgZHJhd2VyJ3Mgb3BlbiBzdGF0ZS5cclxuICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB0aGlzLnNldERyYXdlck9wZW5TdGF0ZSh0cnVlKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBbmd1bGFyIGxpZmVjeWNsZSBob29rIHRoYXQgaXMgY2FsbGVkIHdoZW4gYW55IGRhdGEtYm91bmQgcHJvcGVydHkgb2YgYSBkaXJlY3RpdmUgY2hhbmdlcy5cclxuICAgKiBAcGFyYW0gY2hhbmdlcyAtIE9iamVjdCBjb250YWluaW5nIHRoZSBjaGFuZ2VkIHByb3BlcnRpZXMuXHJcbiAgICovXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKGNoYW5nZXNbJ3J1Y0lucHV0RGF0YSddKSB7XHJcbiAgICAgIGNvbnN0IHByZXZpb3VzUnVjSW5wdXREYXRhID0gY2hhbmdlc1sncnVjSW5wdXREYXRhJ10ucHJldmlvdXNWYWx1ZSBhcyBSdWNsaWJEcmF3ZXJJbnB1dCB8fCB7fTtcclxuICAgICAgY29uc3QgY3VycmVudFJ1Y0lucHV0RGF0YSA9IGNoYW5nZXNbJ3J1Y0lucHV0RGF0YSddLmN1cnJlbnRWYWx1ZSBhcyBSdWNsaWJEcmF3ZXJJbnB1dCB8fCB7fTtcclxuXHJcbiAgICAgIGNvbnN0IG9sZFBvc2l0aW9uID0gcHJldmlvdXNSdWNJbnB1dERhdGEuZHJhd2VyUG9zaXRpb24gPz8gdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb247XHJcbiAgICAgIGNvbnN0IHdhc09wZW4gPSB0aGlzLmRyYXdlckFuaW1hdGlvblN0YXRlID09PSAnaW4nO1xyXG5cclxuICAgICAgdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24gPSBjdXJyZW50UnVjSW5wdXREYXRhLmRyYXdlclBvc2l0aW9uID8/ICdsZWZ0JztcclxuICAgICAgdGhpcy5hcHBseUlucHV0cygpO1xyXG5cclxuICAgICAgY29uc3QgbmV3UG9zaXRpb24gPSB0aGlzLmN1cnJlbnREcmF3ZXJQb3NpdGlvbjtcclxuICAgICAgY29uc3Qgc2hvdWxkQmVPcGVuID0gdGhpcy5ydWNJbnB1dERhdGEuaW5pdGlhbE9wZW5lZFN0YXRlID8/IGZhbHNlO1xyXG5cclxuICAgICAgaWYgKHdhc09wZW4gJiYgb2xkUG9zaXRpb24gIT09IG5ld1Bvc2l0aW9uKSB7XHJcbiAgICAgICAgdGhpcy5wZW5kaW5nRHJhd2VyUG9zaXRpb24gPSBuZXdQb3NpdGlvbjtcclxuICAgICAgICB0aGlzLnNldERyYXdlck9wZW5TdGF0ZShmYWxzZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAod2FzT3BlbiAhPT0gc2hvdWxkQmVPcGVuKSB7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnNldERyYXdlck9wZW5TdGF0ZShzaG91bGRCZU9wZW4pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMubG9hZER5bmFtaWNDb250ZW50KCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXBwbGllcyBpbnB1dCBkYXRhIHRvIGNvbXBvbmVudCBwcm9wZXJ0aWVzLCBjYWxjdWxhdGluZyBkaW1lbnNpb25zIGFuZCBwb3NpdGlvbnMuXHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIGFwcGx5SW5wdXRzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5tYXREcmF3ZXJNb2RlID0gdGhpcy5ydWNJbnB1dERhdGEubW9kZSA/PyAnc2lkZSc7XHJcbiAgICB0aGlzLmVmZmVjdGl2ZUFuaW1hdGlvbkR1cmF0aW9uID0gdGhpcy5ydWNJbnB1dERhdGEuYW5pbWF0aW9uRHVyYXRpb24gfHwgJzMwMG1zJztcclxuXHJcbiAgICBjb25zdCBnZXREaW1lbnNpb24gPSAoaW5wdXREaW1lbnNpb246IHN0cmluZyB8IHVuZGVmaW5lZCwgZGVmYXVsdERpbWVuc2lvbjogc3RyaW5nKTogc3RyaW5nID0+IHtcclxuICAgICAgcmV0dXJuIChpbnB1dERpbWVuc2lvbiAmJiBpbnB1dERpbWVuc2lvbi50cmltKCkgIT09ICcnKSA/IGlucHV0RGltZW5zaW9uIDogZGVmYXVsdERpbWVuc2lvbjtcclxuICAgIH07XHJcblxyXG4gICAgc3dpdGNoICh0aGlzLmN1cnJlbnREcmF3ZXJQb3NpdGlvbikge1xyXG4gICAgICBjYXNlICdyaWdodCc6XHJcbiAgICAgICAgdGhpcy5tYXRBY3R1YWxQb3NpdGlvbiA9ICdlbmQnO1xyXG4gICAgICAgIHRoaXMuaXNWZXJ0aWNhbExheW91dCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuZWZmZWN0aXZlRHJhd2VyRGltZW5zaW9uID0gZ2V0RGltZW5zaW9uKHRoaXMucnVjSW5wdXREYXRhLmRyYXdlcldpZHRoLCAnMjUwcHgnKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSAndG9wJzpcclxuICAgICAgICB0aGlzLm1hdEFjdHVhbFBvc2l0aW9uID0gJ3N0YXJ0JztcclxuICAgICAgICB0aGlzLmlzVmVydGljYWxMYXlvdXQgPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuZWZmZWN0aXZlRHJhd2VyRGltZW5zaW9uID0gZ2V0RGltZW5zaW9uKHRoaXMucnVjSW5wdXREYXRhLmRyYXdlckhlaWdodCwgJzIwMHB4Jyk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ2JvdHRvbSc6XHJcbiAgICAgICAgdGhpcy5tYXRBY3R1YWxQb3NpdGlvbiA9ICdlbmQnO1xyXG4gICAgICAgIHRoaXMuaXNWZXJ0aWNhbExheW91dCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5lZmZlY3RpdmVEcmF3ZXJEaW1lbnNpb24gPSBnZXREaW1lbnNpb24odGhpcy5ydWNJbnB1dERhdGEuZHJhd2VySGVpZ2h0LCAnMjAwcHgnKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSAnbGVmdCc6XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgdGhpcy5tYXRBY3R1YWxQb3NpdGlvbiA9ICdzdGFydCc7XHJcbiAgICAgICAgdGhpcy5pc1ZlcnRpY2FsTGF5b3V0ID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5lZmZlY3RpdmVEcmF3ZXJEaW1lbnNpb24gPSBnZXREaW1lbnNpb24odGhpcy5ydWNJbnB1dERhdGEuZHJhd2VyV2lkdGgsICcyNTBweCcpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVG9nZ2xlcyB0aGUgZHJhd2VyJ3Mgb3Blbi9jbG9zZSBzdGF0ZSBvciBzd2l0Y2hlcyB0byBhIG5ldyBwb3NpdGlvbi5cclxuICAgKiBAcGFyYW0gcmVxdWVzdGVkUG9zaXRpb24gLSBUaGUgZGVzaXJlZCBwb3NpdGlvbiB0byBvcGVuIHRoZSBkcmF3ZXIgZnJvbS4gSWYgbm90IHByb3ZpZGVkLCB1c2VzIGBjdXJyZW50RHJhd2VyUG9zaXRpb25gLlxyXG4gICAqL1xyXG4gIHRvZ2dsZURyYXdlcihyZXF1ZXN0ZWRQb3NpdGlvbj86ICdsZWZ0JyB8ICdyaWdodCcgfCAndG9wJyB8ICdib3R0b20nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5pc0FuaW1hdGluZyAmJiAhdGhpcy5wZW5kaW5nRHJhd2VyUG9zaXRpb24pIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICBjb25zdCBwb3NpdGlvblRvVG9nZ2xlID0gcmVxdWVzdGVkUG9zaXRpb24gfHwgdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb247XHJcbiAgICBjb25zdCBpc0RyYXdlck9wZW4gPSB0aGlzLmRyYXdlckFuaW1hdGlvblN0YXRlID09PSAnaW4nO1xyXG4gICAgY29uc3QgaXNTYW1lUG9zaXRpb24gPSB0aGlzLmN1cnJlbnREcmF3ZXJQb3NpdGlvbiA9PT0gcG9zaXRpb25Ub1RvZ2dsZTtcclxuXHJcbiAgICBpZiAoaXNEcmF3ZXJPcGVuKSB7XHJcbiAgICAgIGlmIChpc1NhbWVQb3NpdGlvbikge1xyXG4gICAgICAgIHRoaXMuc2V0RHJhd2VyT3BlblN0YXRlKGZhbHNlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnBlbmRpbmdEcmF3ZXJQb3NpdGlvbiA9IHBvc2l0aW9uVG9Ub2dnbGU7XHJcbiAgICAgICAgdGhpcy5zZXREcmF3ZXJPcGVuU3RhdGUoZmFsc2UpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAoIWlzU2FtZVBvc2l0aW9uKSB7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24gPSBwb3NpdGlvblRvVG9nZ2xlO1xyXG4gICAgICAgIHRoaXMuYXBwbHlJbnB1dHMoKTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNldERyYXdlck9wZW5TdGF0ZSh0cnVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgdGhlIGRyYXdlcidzIG9wZW4gc3RhdGUgYW5kIHRyaWdnZXJzIHRoZSBhbmltYXRpb24uXHJcbiAgICogQHBhcmFtIG9wZW4gLSBCb29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0byBvcGVuICh0cnVlKSBvciBjbG9zZSAoZmFsc2UpIHRoZSBkcmF3ZXIuXHJcbiAgICogQHByaXZhdGVcclxuICAgKi9cclxuICBwcml2YXRlIHNldERyYXdlck9wZW5TdGF0ZShvcGVuOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5pc0FuaW1hdGluZyAmJiAhdGhpcy5wZW5kaW5nRHJhd2VyUG9zaXRpb24gJiYgb3BlbiA9PT0gKHRoaXMuZHJhd2VyQW5pbWF0aW9uU3RhdGUgPT09ICdpbicpKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuaXNBbmltYXRpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy5kcmF3ZXJBbmltYXRpb25TdGF0ZSA9IG9wZW4gPyAnaW4nIDogJ291dCc7XHJcbiAgICB0aGlzLnJ1Y0V2ZW50LmVtaXQoe1xyXG4gICAgICB0eXBlOiBvcGVuID8gJ29wZW5lZFN0YXJ0JyA6ICdjbG9zZWRTdGFydCcsXHJcbiAgICAgIG9wZW5lZDogb3BlbixcclxuICAgICAgcG9zaXRpb246IHRoaXMuY3VycmVudERyYXdlclBvc2l0aW9uXHJcbiAgICB9KTtcclxuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbGxiYWNrIGZvciB3aGVuIGEgZHJhd2VyIGFuaW1hdGlvbiBmaW5pc2hlcy5cclxuICAgKiBNYW5hZ2VzIHN0YXRlIHRyYW5zaXRpb25zLCBlc3BlY2lhbGx5IHdoZW4gc3dpdGNoaW5nIGJldHdlZW4gb3BlbiBkcmF3ZXJzLlxyXG4gICAqIEBwYXJhbSBldmVudCAtIFRoZSBBbmd1bGFyIEFuaW1hdGlvbkV2ZW50LlxyXG4gICAqL1xyXG4gIG9uQW5pbWF0aW9uRG9uZShldmVudDogQW5pbWF0aW9uRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmIChldmVudC5lbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnZHluYW1pYy1kcmF3ZXInKSkge1xyXG4gICAgICBpZiAoZXZlbnQudG9TdGF0ZSA9PT0gJ291dCcpIHtcclxuICAgICAgICB0aGlzLnJ1Y0V2ZW50LmVtaXQoeyB0eXBlOiAnb3BlbmVkQ2hhbmdlJywgb3BlbmVkOiBmYWxzZSwgcG9zaXRpb246IHRoaXMuY3VycmVudERyYXdlclBvc2l0aW9uIH0pO1xyXG4gICAgICAgIHRoaXMucnVjRXZlbnQuZW1pdCh7IHR5cGU6ICdkcmF3ZXJUb2dnbGUnLCBvcGVuZWQ6IGZhbHNlLCBwb3NpdGlvbjogdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24gfSk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnBlbmRpbmdEcmF3ZXJQb3NpdGlvbikge1xyXG4gICAgICAgICAgdGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24gPSB0aGlzLnBlbmRpbmdEcmF3ZXJQb3NpdGlvbjtcclxuICAgICAgICAgIHRoaXMucGVuZGluZ0RyYXdlclBvc2l0aW9uID0gbnVsbDtcclxuICAgICAgICAgIHRoaXMuYXBwbHlJbnB1dHMoKTtcclxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnNldERyYXdlck9wZW5TdGF0ZSh0cnVlKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIGlmIChldmVudC50b1N0YXRlID09PSAnaW4nKSB7XHJcbiAgICAgICAgdGhpcy5ydWNFdmVudC5lbWl0KHsgdHlwZTogJ29wZW5lZENoYW5nZScsIG9wZW5lZDogdHJ1ZSwgcG9zaXRpb246IHRoaXMuY3VycmVudERyYXdlclBvc2l0aW9uIH0pO1xyXG4gICAgICAgIHRoaXMucnVjRXZlbnQuZW1pdCh7IHR5cGU6ICdkcmF3ZXJUb2dnbGUnLCBvcGVuZWQ6IHRydWUsIHBvc2l0aW9uOiB0aGlzLmN1cnJlbnREcmF3ZXJQb3NpdGlvbiB9KTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvYWRzIHRoZSBkeW5hbWljIGNvbXBvbmVudCBpbnRvIHRoZSBkcmF3ZXIgaWYgc3BlY2lmaWVkIGluIHJ1Y0lucHV0RGF0YS5cclxuICAgKiBDbGVhcnMgZXhpc3RpbmcgZHluYW1pYyBjb21wb25lbnQgaWYgYW55LlxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBsb2FkRHluYW1pY0NvbnRlbnQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNsZWFyRHluYW1pY0NvbnRlbnQoKTtcclxuXHJcbiAgICBjb25zdCBjb21wb25lbnRUeXBlID0gdGhpcy5ydWNJbnB1dERhdGEuY29udGVudD8uZHJhd2VyQ29udGVudENvbXBvbmVudDtcclxuICAgIGlmIChjb21wb25lbnRUeXBlICYmIHRoaXMuZHJhd2VyQ29tcG9uZW50SG9zdCkge1xyXG4gICAgICB0aGlzLmR5bmFtaWNDb21wb25lbnRSZWYgPSB0aGlzLmRyYXdlckNvbXBvbmVudEhvc3QuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudFR5cGUpO1xyXG4gICAgICBpZiAodGhpcy5keW5hbWljQ29tcG9uZW50UmVmLmluc3RhbmNlKSB7XHJcbiAgICAgICAgdGhpcy5keW5hbWljQ29tcG9uZW50UmVmLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMucnVjSW5wdXREYXRhLmRyYXdlckNvbnRlbnRDb21wb25lbnREYXRhICYmIHRoaXMuZHluYW1pY0NvbXBvbmVudFJlZi5pbnN0YW5jZSkge1xyXG4gICAgICAgIE9iamVjdC5rZXlzKHRoaXMucnVjSW5wdXREYXRhLmRyYXdlckNvbnRlbnRDb21wb25lbnREYXRhKS5mb3JFYWNoKGtleSA9PiB7XHJcbiAgICAgICAgICBpZiAoa2V5IGluIHRoaXMuZHluYW1pY0NvbXBvbmVudFJlZiEuaW5zdGFuY2UpIHtcclxuICAgICAgICAgICAgdGhpcy5keW5hbWljQ29tcG9uZW50UmVmIS5pbnN0YW5jZVtrZXldID0gdGhpcy5ydWNJbnB1dERhdGEuZHJhd2VyQ29udGVudENvbXBvbmVudERhdGFba2V5XTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLmR5bmFtaWNDb21wb25lbnRSZWYuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBmb3IgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHBhcmFtZXRlcnMgdG8gYmUgcGFzc2VkIHRvIHRoZSBhbmltYXRpb24gdHJpZ2dlcnMgaW4gdGhlIHRlbXBsYXRlLlxyXG4gICAqIEluY2x1ZGVzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBzdGF0ZSAoJ2luJyBvciAnb3V0JykgYW5kIHRoZSBlZmZlY3RpdmUgZHVyYXRpb24uXHJcbiAgICovXHJcbiAgZ2V0IGFuaW1hdGlvblBhcmFtcygpIHtcclxuICAgIHJldHVybiB7IHZhbHVlOiB0aGlzLmRyYXdlckFuaW1hdGlvblN0YXRlLCBwYXJhbXM6IHsgZHVyYXRpb246IHRoaXMuZWZmZWN0aXZlQW5pbWF0aW9uRHVyYXRpb24gfSB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0dGVyIGZvciB0aGUgYmFja2Ryb3AgYW5pbWF0aW9uIHBhcmFtZXRlcnMuXHJcbiAgICogVHlwaWNhbGx5IHVzZXMgYSBmYXN0ZXIgZHVyYXRpb24gdGhhbiB0aGUgbWFpbiBkcmF3ZXIgYW5pbWF0aW9uLlxyXG4gICAqL1xyXG4gIGdldCBiYWNrZHJvcEFuaW1hdGlvblBhcmFtcygpIHtcclxuICAgIGxldCBkdXJhdGlvbk1zID0gMDtcclxuICAgIGlmICh0aGlzLmVmZmVjdGl2ZUFuaW1hdGlvbkR1cmF0aW9uLmVuZHNXaXRoKCdtcycpKSB7XHJcbiAgICAgIGR1cmF0aW9uTXMgPSBwYXJzZUludCh0aGlzLmVmZmVjdGl2ZUFuaW1hdGlvbkR1cmF0aW9uLCAxMCk7XHJcbiAgICB9IGVsc2UgaWYgKHRoaXMuZWZmZWN0aXZlQW5pbWF0aW9uRHVyYXRpb24uZW5kc1dpdGgoJ3MnKSkge1xyXG4gICAgICBkdXJhdGlvbk1zID0gcGFyc2VGbG9hdCh0aGlzLmVmZmVjdGl2ZUFuaW1hdGlvbkR1cmF0aW9uKSAqIDEwMDA7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBkdXJhdGlvbk1zID0gcGFyc2VJbnQodGhpcy5lZmZlY3RpdmVBbmltYXRpb25EdXJhdGlvbiwgMTApIHx8IDMwMDsgLy8gRmFsbGJhY2sgaWYgZm9ybWF0IGlzIHVuZXhwZWN0ZWRcclxuICAgIH1cclxuICAgIGNvbnN0IGJhY2tkcm9wRHVyYXRpb25WYWx1ZSA9IE1hdGguZmxvb3IoZHVyYXRpb25NcyAvIDIpOyAvLyBFbnN1cmUgaW50ZWdlciBmb3IgbXNcclxuICAgIGNvbnN0IGJhY2tkcm9wRHVyYXRpb24gPSBiYWNrZHJvcER1cmF0aW9uVmFsdWUgPiAwID8gYCR7YmFja2Ryb3BEdXJhdGlvblZhbHVlfW1zYCA6ICcxNTBtcyc7IC8vIEZhbGxiYWNrIGlmIGNhbGN1bGF0ZWQgZHVyYXRpb24gaXMgMCBvciBsZXNzXHJcbiAgICByZXR1cm4geyB2YWx1ZTogdGhpcy5kcmF3ZXJBbmltYXRpb25TdGF0ZSwgcGFyYW1zOiB7IGR1cmF0aW9uOiBiYWNrZHJvcER1cmF0aW9uIH0gfTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGVzIGFuIGFjY2Vzc2libGUgbGFiZWwgZm9yIHRoZSB0b2dnbGUgYnV0dG9uIGJhc2VkIG9uIHRoZSBkcmF3ZXIncyBzdGF0ZSBhbmQgcG9zaXRpb24uXHJcbiAgICogQHJldHVybnMgVGhlIEFSSUEgbGFiZWwgc3RyaW5nIGZvciB0aGUgdG9nZ2xlIGJ1dHRvbi5cclxuICAgKi9cclxuICBnZXRUb2dnbGVCdXR0b25BcmlhTGFiZWwoKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGRlZmF1bHRPcGVuID0gYE9wZW4gJHt0aGlzLmN1cnJlbnREcmF3ZXJQb3NpdGlvbn0gRHJhd2VyYDtcclxuICAgIGNvbnN0IGRlZmF1bHRDbG9zZSA9IGBDbG9zZSAke3RoaXMuY3VycmVudERyYXdlclBvc2l0aW9ufSBEcmF3ZXJgO1xyXG4gICAgY29uc3Qgb3BlblRleHQgPSB0aGlzLnJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25UZXh0Py5vcGVuIHx8IGRlZmF1bHRPcGVuO1xyXG4gICAgY29uc3QgY2xvc2VUZXh0ID0gdGhpcy5ydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uVGV4dD8uY2xvc2UgfHwgZGVmYXVsdENsb3NlO1xyXG4gICAgcmV0dXJuIHRoaXMuZHJhd2VyQW5pbWF0aW9uU3RhdGUgPT09ICdpbicgPyBjbG9zZVRleHQgOiBvcGVuVGV4dDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZXMgY2xpY2tzIG9uIHRoZSBiYWNrZHJvcC5cclxuICAgKiBDbG9zZXMgdGhlIGRyYXdlciBvbmx5IGlmIGBkaXNhYmxlQ2xvc2VgIGlzIG5vdCB0cnVlLlxyXG4gICAqIEBwdWJsaWNcclxuICAgKi9cclxuICBwdWJsaWMgaGFuZGxlQmFja2Ryb3BDbGljaygpOiB2b2lkIHtcclxuICAgIGlmICghKHRoaXMucnVjSW5wdXREYXRhLmRpc2FibGVDbG9zZSA/PyBmYWxzZSkpIHtcclxuICAgICAgdGhpcy50b2dnbGVEcmF3ZXIodGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTGlzdGVucyBmb3IgRXNjYXBlIGtleSBwcmVzc2VzIG9uIHRoZSBkb2N1bWVudC5cclxuICAgKiBDbG9zZXMgdGhlIGRyYXdlciBpZiBpdCdzIG9wZW4gYW5kIGBkaXNhYmxlQ2xvc2VgIGlzIG5vdCB0cnVlLlxyXG4gICAqIEBwYXJhbSBldmVudCAtIFRoZSBLZXlib2FyZEV2ZW50LlxyXG4gICAqL1xyXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24uZXNjYXBlJywgWyckZXZlbnQnXSlcclxuICBvbktleWRvd25IYW5kbGVyKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcbiAgICBpZiAodGhpcy5kcmF3ZXJBbmltYXRpb25TdGF0ZSA9PT0gJ2luJyAmJiAhKHRoaXMucnVjSW5wdXREYXRhLmRpc2FibGVDbG9zZSA/PyBmYWxzZSkpIHtcclxuICAgICAgdGhpcy50b2dnbGVEcmF3ZXIodGhpcy5jdXJyZW50RHJhd2VyUG9zaXRpb24pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xlYXJzIGFueSBkeW5hbWljYWxseSBsb2FkZWQgY29tcG9uZW50LlxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjbGVhckR5bmFtaWNDb250ZW50KCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZHJhd2VyQ29tcG9uZW50SG9zdCkge1xyXG4gICAgICB0aGlzLmRyYXdlckNvbXBvbmVudEhvc3QuY2xlYXIoKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmR5bmFtaWNDb21wb25lbnRSZWYpIHtcclxuICAgICAgdGhpcy5keW5hbWljQ29tcG9uZW50UmVmLmRlc3Ryb3koKTtcclxuICAgICAgdGhpcy5keW5hbWljQ29tcG9uZW50UmVmID0gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2sgdGhhdCBpcyBjYWxsZWQgY2xlYXIgZHluYW1pYyBjb21wb25lbnQgY29udGVudC5cclxuICAgKi9cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xlYXJEeW5hbWljQ29udGVudCgpO1xyXG4gIH1cclxufSIsIjwhLS0gXHJcbiAgQ3VzdG9tIEJhY2tkcm9wIGVsZW1lbnQuXHJcbiAgVmlzaWJsZSBvbmx5IHdoZW46XHJcbiAgLSBydWNJbnB1dERhdGEubW9kZSBpcyAnb3ZlcidcclxuICAtIHJ1Y0lucHV0RGF0YS5oYXNCYWNrZHJvcCBpcyB0cnVlIChvciB1bmRlZmluZWQsIGRlZmF1bHRpbmcgdG8gdHJ1ZSlcclxuICAtIGRyYXdlckFuaW1hdGlvblN0YXRlIGlzICdpbicgKGRyYXdlciBpcyBvcGVuIG9yIG9wZW5pbmcpXHJcbiAgQW5pbWF0ZXMgdXNpbmcgJ2JhY2tkcm9wRmFkZScgdHJpZ2dlci5cclxuICBDbGlja2luZyB0aGUgYmFja2Ryb3Agd2lsbCB0b2dnbGUgdGhlIGRyYXdlciBmb3IgdGhlIGN1cnJlbnQgcG9zaXRpb24uXHJcbiAgQmFja2dyb3VuZCBjb2xvciBjYW4gYmUgY3VzdG9taXplZCB2aWEgcnVjSW5wdXREYXRhLmJhY2tkcm9wQmFja2dyb3VuZENvbG9yLlxyXG4tLT5cclxuPGRpdiBjbGFzcz1cImN1c3RvbS1iYWNrZHJvcFwiXHJcbiAgICAgKm5nSWY9XCJydWNJbnB1dERhdGEubW9kZSA9PT0gJ292ZXInICYmIChydWNJbnB1dERhdGEuaGFzQmFja2Ryb3AgPz8gdHJ1ZSkgJiYgZHJhd2VyQW5pbWF0aW9uU3RhdGUgPT09ICdpbidcIlxyXG4gICAgIFtAYmFja2Ryb3BGYWRlXT1cImJhY2tkcm9wQW5pbWF0aW9uUGFyYW1zXCJcclxuICAgICAoY2xpY2spPVwiaGFuZGxlQmFja2Ryb3BDbGljaygpXCJcclxuICAgICBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCJydWNJbnB1dERhdGEuaGFzQmFja2Ryb3AgPyBydWNJbnB1dERhdGEuYmFja2Ryb3BCYWNrZ3JvdW5kQ29sb3IgOiAnJ1wiPlxyXG48L2Rpdj5cclxuXHJcbjwhLS0gXHJcbiAgQ3VzdG9tIER5bmFtaWMgRHJhd2VyIGVsZW1lbnQuXHJcbiAgVGhpcyBpcyB0aGUgbWFpbiBwYW5lbCB0aGF0IHNsaWRlcyBpbiBhbmQgb3V0LlxyXG4gIC0gQXBwbGllcyBDU1MgY2xhc3NlcyBiYXNlZCBvbiBjdXJyZW50RHJhd2VyUG9zaXRpb24gYW5kIGN1c3RvbVRoZW1lLlxyXG4gIC0gRHluYW1pY2FsbHkgc2V0cyB3aWR0aCBhbmQgaGVpZ2h0IGJhc2VkIG9uIGRyYXdlciBvcmllbnRhdGlvbiBhbmQgaW5wdXQgZGF0YS5cclxuICAtIFVzZXMgb25lIG9mIGZvdXIgYW5pbWF0aW9uIHRyaWdnZXJzIChzbGlkZUluT3V0TGVmdCwgc2xpZGVJbk91dFJpZ2h0LCBzbGlkZUluT3V0VG9wLCBzbGlkZUluT3V0Qm90dG9tKVxyXG4gICAgYmFzZWQgb24gY3VycmVudERyYXdlclBvc2l0aW9uLiBPbmx5IHRoZSBhY3RpdmUgdHJpZ2dlciBydW5zIGl0cyBhbmltYXRpb247IG90aGVycyBhcmUgc2V0IHRvIGFuXHJcbiAgICBpbnN0YW50ICdvdXQnIHN0YXRlIHRvIHByZXZlbnQgaW50ZXJmZXJlbmNlLlxyXG4gIC0gQW5pbWF0aW9uIGNvbXBsZXRpb24gZXZlbnRzIGFyZSBoYW5kbGVkIGJ5IG9uQW5pbWF0aW9uRG9uZSgpLlxyXG4tLT5cclxuPGRpdiBjbGFzcz1cImR5bmFtaWMtZHJhd2VyXCJcclxuICAgICBbbmdDbGFzc109XCInZHJhd2VyLScgKyBjdXJyZW50RHJhd2VyUG9zaXRpb24gKyAnICcgKyAoY3VzdG9tVGhlbWUgfHwgJycpXCJcclxuICAgICBbc3R5bGUud2lkdGhdPVwiIWlzVmVydGljYWxMYXlvdXQgPyBlZmZlY3RpdmVEcmF3ZXJEaW1lbnNpb24gOiAnMTAwJSdcIlxyXG4gICAgIFtzdHlsZS5oZWlnaHRdPVwiaXNWZXJ0aWNhbExheW91dCA/IGVmZmVjdGl2ZURyYXdlckRpbWVuc2lvbiA6ICcxMDAlJ1wiXHJcblxyXG4gICAgIFtAc2xpZGVJbk91dExlZnRdPVwiY3VycmVudERyYXdlclBvc2l0aW9uID09PSAnbGVmdCcgPyBhbmltYXRpb25QYXJhbXMgOiB7dmFsdWU6ICdvdXQnLCBwYXJhbXM6IHtkdXJhdGlvbjogJzBtcyd9fVwiXHJcbiAgICAgKEBzbGlkZUluT3V0TGVmdC5kb25lKT1cImN1cnJlbnREcmF3ZXJQb3NpdGlvbiA9PT0gJ2xlZnQnICYmIG9uQW5pbWF0aW9uRG9uZSgkZXZlbnQpXCJcclxuXHJcbiAgICAgW0BzbGlkZUluT3V0UmlnaHRdPVwiY3VycmVudERyYXdlclBvc2l0aW9uID09PSAncmlnaHQnID8gYW5pbWF0aW9uUGFyYW1zIDoge3ZhbHVlOiAnb3V0JywgcGFyYW1zOiB7ZHVyYXRpb246ICcwbXMnfX1cIlxyXG4gICAgIChAc2xpZGVJbk91dFJpZ2h0LmRvbmUpPVwiY3VycmVudERyYXdlclBvc2l0aW9uID09PSAncmlnaHQnICYmIG9uQW5pbWF0aW9uRG9uZSgkZXZlbnQpXCJcclxuXHJcbiAgICAgW0BzbGlkZUluT3V0VG9wXT1cImN1cnJlbnREcmF3ZXJQb3NpdGlvbiA9PT0gJ3RvcCcgPyBhbmltYXRpb25QYXJhbXMgOiB7dmFsdWU6ICdvdXQnLCBwYXJhbXM6IHtkdXJhdGlvbjogJzBtcyd9fVwiXHJcbiAgICAgKEBzbGlkZUluT3V0VG9wLmRvbmUpPVwiY3VycmVudERyYXdlclBvc2l0aW9uID09PSAndG9wJyAmJiBvbkFuaW1hdGlvbkRvbmUoJGV2ZW50KVwiXHJcblxyXG4gICAgIFtAc2xpZGVJbk91dEJvdHRvbV09XCJjdXJyZW50RHJhd2VyUG9zaXRpb24gPT09ICdib3R0b20nID8gYW5pbWF0aW9uUGFyYW1zIDoge3ZhbHVlOiAnb3V0JywgcGFyYW1zOiB7ZHVyYXRpb246ICcwbXMnfX1cIlxyXG4gICAgIChAc2xpZGVJbk91dEJvdHRvbS5kb25lKT1cImN1cnJlbnREcmF3ZXJQb3NpdGlvbiA9PT0gJ2JvdHRvbScgJiYgb25BbmltYXRpb25Eb25lKCRldmVudClcIj5cclxuXHJcbiAgPCEtLSBXcmFwcGVyIGZvciB0aGUgY29udGVudCBpbnNpZGUgdGhlIGRyYXdlciwgaGFuZGxlcyBwYWRkaW5nIGFuZCBsYXlvdXQuIC0tPlxyXG4gIDxkaXYgY2xhc3M9XCJkcmF3ZXItY29udGVudC13cmFwcGVyXCI+XHJcbiAgICA8IS0tIE9wdGlvbmFsIHRpdGxlIGZvciB0aGUgZHJhd2VyLiAtLT5cclxuICAgIDxoMiAqbmdJZj1cInJ1Y0lucHV0RGF0YS5jb250ZW50Py5kcmF3ZXJUaXRsZVwiIGNsYXNzPVwicnVjbGliLWRyYXdlci10aXRsZVwiPlxyXG4gICAgICB7eyBydWNJbnB1dERhdGEuY29udGVudD8uZHJhd2VyVGl0bGUgfX1cclxuICAgIDwvaDI+XHJcbiAgICA8IS0tIFxyXG4gICAgICBPcHRpb25hbCBjbG9zZSBidXR0b24gaW5zaWRlIHRoZSBkcmF3ZXIuXHJcbiAgICAgIFRvZ2dsZXMgdGhlIGRyYXdlciBmb3IgdGhlIGN1cnJlbnQgcG9zaXRpb24gd2hlbiBjbGlja2VkLlxyXG4gICAgICBBUklBIGxhYmVsIHByb3ZpZGVzIGFjY2Vzc2liaWxpdHkuXHJcbiAgICAgIERpbWVuc2lvbnMgY2FuIGJlIGN1c3RvbWl6ZWQgdmlhIHJ1Y0lucHV0RGF0YS5jbG9zZUJ1dHRvbkRpbWVuc2lvbnMuXHJcbiAgICAtLT5cclxuICAgIDxidXR0b24gKm5nSWY9XCJydWNJbnB1dERhdGEuc2hvd0Nsb3NlSWNvblwiXHJcbiAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvbiBjbGFzcz1cInJ1Y2xpYi1kcmF3ZXItY2xvc2UtYnV0dG9uXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZURyYXdlcihjdXJyZW50RHJhd2VyUG9zaXRpb24pXCJcclxuICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInQ2xvc2UgJyArIGN1cnJlbnREcmF3ZXJQb3NpdGlvbiArICcgZHJhd2VyJ1wiXHJcbiAgICAgICAgICAgIFtzdHlsZS53aWR0aF09XCJydWNJbnB1dERhdGEuY2xvc2VCdXR0b25EaW1lbnNpb25zPy53aWR0aFwiXHJcbiAgICAgICAgICAgIFtzdHlsZS5oZWlnaHRdPVwicnVjSW5wdXREYXRhLmNsb3NlQnV0dG9uRGltZW5zaW9ucz8uaGVpZ2h0XCI+XHJcbiAgICAgIDwhLS0gTWF0ZXJpYWwgaWNvbiBmb3IgdGhlIGNsb3NlIGJ1dHRvbi4gU2l6ZSBjYW4gYmUgY3VzdG9taXplZC4gLS0+XHJcbiAgICAgIDxtYXQtaWNvbiBbc3R5bGUuZm9udC1zaXplXT1cInJ1Y0lucHV0RGF0YS5jbG9zZUJ1dHRvbkRpbWVuc2lvbnM/Lmljb25TaXplXCI+Y2xvc2U8L21hdC1pY29uPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICA8IS0tIE1haW4gYm9keSBjb250ZW50IG9mIHRoZSBkcmF3ZXIuIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cInJ1Y2xpYi1kcmF3ZXItYm9keVwiPlxyXG4gICAgICA8IS0tIEhvc3QgZm9yIGR5bmFtaWNhbGx5IGluamVjdGVkIGNvbXBvbmVudCAtLT5cclxuICAgICAgPG5nLXRlbXBsYXRlICNkcmF3ZXJDb21wb25lbnRIb3N0PjwvbmctdGVtcGxhdGU+XHJcbiAgICAgIDwhLS0gRmFsbGJhY2sgdG8gSFRNTCBjb250ZW50IGlmIG5vIGNvbXBvbmVudCBpcyBwcm92aWRlZCAtLT5cclxuICAgICAgPGRpdiAqbmdJZj1cIiFydWNJbnB1dERhdGEuY29udGVudD8uZHJhd2VyQ29udGVudENvbXBvbmVudFwiIFtpbm5lckhUTUxdPVwicnVjSW5wdXREYXRhLmNvbnRlbnQ/LmRyYXdlckJvZHkgfHwgJycgfCBzYWZlSHRtbFwiPjwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPCEtLSBcclxuICBBbmd1bGFyIE1hdGVyaWFsIERyYXdlciBDb250YWluZXIuXHJcbiAgQWN0cyBhcyB0aGUgbWFpbiBjb250YWluZXIgZm9yIHRoZSBkcmF3ZXIgc3lzdGVtLCBlc3BlY2lhbGx5IGlmICdzaWRlJyBvciAncHVzaCcgbW9kZXNcclxuICB3ZXJlIHRvIGJlIGltcGxlbWVudGVkIHdpdGggTWF0RHJhd2VyJ3MgbmF0aXZlIGJlaGF2aW9yLiBXaXRoIGN1c3RvbSBmaXhlZC1wb3NpdGlvbiBhbmltYXRpb25zLFxyXG4gIGl0cyBwcmltYXJ5IHJvbGUgaGVyZSBpcyB0byBob3N0IHRoZSBtYXQtZHJhd2VyLWNvbnRlbnQuXHJcbiAgLSBBcHBsaWVzICd2ZXJ0aWNhbC1sYXlvdXQnIGNsYXNzIGlmIHRoZSBkcmF3ZXIgaXMgdG9wL2JvdHRvbS5cclxuICAtIE1hdERyYXdlcidzIG93biBiYWNrZHJvcCBpcyBkaXNhYmxlZCBhcyBhIGN1c3RvbSBvbmUgaXMgdXNlZC5cclxuLS0+XHJcbjxtYXQtZHJhd2VyLWNvbnRhaW5lclxyXG4gIGNsYXNzPVwicnVjbGliLWRyYXdlci1jb250YWluZXJcIlxyXG4gIFtjbGFzcy52ZXJ0aWNhbC1sYXlvdXRdPVwiaXNWZXJ0aWNhbExheW91dFwiXHJcbiAgW2hhc0JhY2tkcm9wXT1cImZhbHNlXCI+IDwhLS0gTWF0RHJhd2VyJ3MgYmFja2Ryb3AgaXMgbm90IHVzZWQgd2l0aCBjdXN0b20gYW5pbWF0aW9uIC0tPlxyXG4gIDxtYXQtZHJhd2VyLWNvbnRlbnQgY2xhc3M9XCJydWNsaWItbWFpbi1jb250ZW50XCI+XHJcbiAgICA8YnV0dG9uIFtkaXNhYmxlZF09XCJydWNJbnB1dERhdGEuZGlzYWJsZVRvZ2dsZUJ1dHRvbkluTWFpbkNvbnRlbnRcIlxyXG4gICAgICAgICAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICB0aXRsZT1cIlRvZ2dsZSBEcmF3ZXJcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImRyYXdlci10b2dnbGUtYnV0dG9uXCJcclxuICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cInJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25EaW1lbnNpb25zPy53aWR0aFwiXHJcbiAgICAgICAgICAgIFtzdHlsZS5oZWlnaHRdPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkRpbWVuc2lvbnM/LmhlaWdodFwiXHJcbiAgICAgICAgICAgIFtzdHlsZS5wYWRkaW5nXT1cInJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25EaW1lbnNpb25zPy5wYWRkaW5nXCJcclxuICAgICAgICAgICAgW3N0eWxlLmZvbnQtc2l6ZV09XCJydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uRGltZW5zaW9ucz8uZm9udFNpemVcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRHJhd2VyKGN1cnJlbnREcmF3ZXJQb3NpdGlvbilcIlxyXG4gICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImdldFRvZ2dsZUJ1dHRvbkFyaWFMYWJlbCgpXCJcclxuICAgICAgICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJkcmF3ZXJBbmltYXRpb25TdGF0ZSA9PT0gJ2luJ1wiPlxyXG4gICAgICA8IS0tIE9wdGlvbmFsIE1hdGVyaWFsIGljb24gZm9yIHRoZSB0b2dnbGUgYnV0dG9uLiBTaG93IG9ubHkgaWYgbm8gaW1hZ2UgVVJMIGlzIHByb3ZpZGVkLiAtLT5cclxuICAgICAgPG1hdC1pY29uICpuZ0lmPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkljb24gJiYgIXJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25JbWFnZVVybFwiIFtzdHlsZS5mb250LXNpemVdPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkRpbWVuc2lvbnM/Lmljb25TaXplXCI+e3sgcnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkljb24gfX08L21hdC1pY29uPlxyXG4gICAgICA8IS0tIE9wdGlvbmFsIGltYWdlIGZvciB0aGUgdG9nZ2xlIGJ1dHRvbi4gSWYgcHJlc2VudCwgaXQgc2hvdWxkIGZpbGwgdGhlIGJ1dHRvbi4gLS0+XHJcbiAgICAgIDxpbWcgKm5nSWY9XCJydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uSW1hZ2VVcmxcIlxyXG4gICAgICAgICAgIFtzcmNdPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkltYWdlVXJsXCJcclxuICAgICAgICAgICBbYWx0XT1cInJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25JbWFnZUFsdCB8fCAnVG9nZ2xlIERyYXdlcidcIlxyXG4gICAgICAgICAgIGNsYXNzPVwicnVjbGliLWRyYXdlci10b2dnbGUtaW1hZ2VcIlxyXG4gICAgICAgICAgIFtzdHlsZS53aWR0aF09XCJydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uRGltZW5zaW9ucz8ud2lkdGhcIlxyXG4gICAgICAgICAgIFtzdHlsZS5oZWlnaHRdPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkRpbWVuc2lvbnM/LmhlaWdodFwiXHJcbiAgICAgICAgICAgW3N0eWxlLnBhZGRpbmddPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkRpbWVuc2lvbnM/LnBhZGRpbmdcIj5cclxuICAgICAgPCEtLSBUZXh0IGZvciB0aGUgdG9nZ2xlIGJ1dHRvbi4gU2hvdyBvbmx5IGlmIE5PIGljb24gQU5EIE5PIGltYWdlIFVSTCBpcyBwcm92aWRlZC4gLS0+XHJcbiAgICAgIDxzcGFuICpuZ0lmPVwiIXJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25JY29uICYmICFydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uSW1hZ2VVcmwgJiYgKHJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25UZXh0Py5vcGVuIHx8IHJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25UZXh0Py5jbG9zZSlcIj5cclxuICAgICAgICB7eyBkcmF3ZXJBbmltYXRpb25TdGF0ZSA9PT0gJ2luJyA/IChydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uVGV4dD8uY2xvc2UgfHwgJ0Nsb3NlJykgOiAocnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvblRleHQ/Lm9wZW4gfHwgJ09wZW4nKSB9fVxyXG4gICAgICA8L3NwYW4+XHJcbiAgICAgIDwhLS0gVGV4dCBmb3IgdGhlIHRvZ2dsZSBidXR0b24gd2hlbiBhbiBpY29uIChidXQgTk8gaW1hZ2UpIElTIGFsc28gcHJlc2VudC4gLS0+XHJcbiAgICAgIDxzcGFuICpuZ0lmPVwicnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvbkljb24gJiYgIXJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25JbWFnZVVybCAmJiAocnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvblRleHQ/Lm9wZW4gfHwgcnVjSW5wdXREYXRhLnRvZ2dsZUJ1dHRvblRleHQ/LmNsb3NlKVwiIGNsYXNzPVwidG9nZ2xlLWJ1dHRvbi10ZXh0LXdpdGgtaWNvblwiPlxyXG4gICAgICAgIHt7IGRyYXdlckFuaW1hdGlvblN0YXRlID09PSAnaW4nID8gKHJ1Y0lucHV0RGF0YS50b2dnbGVCdXR0b25UZXh0Py5jbG9zZSB8fCAnQ2xvc2UnKSA6IChydWNJbnB1dERhdGEudG9nZ2xlQnV0dG9uVGV4dD8ub3BlbiB8fCAnT3BlbicpIH19XHJcbiAgICAgIDwvc3Bhbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPCEtLSBNYWluIGFwcGxpY2F0aW9uIGNvbnRlbnQgYXJlYSwgcmVuZGVyZWQgZnJvbSBIVE1MIHN0cmluZyB2aWEgc2FmZUh0bWwgcGlwZS4gLS0+XHJcbiAgICA8ZGl2IFtpbm5lckhUTUxdPVwicnVjSW5wdXREYXRhLmNvbnRlbnQ/Lm1haW5Cb2R5IHx8ICcnIHwgc2FmZUh0bWxcIj48L2Rpdj5cclxuICA8L21hdC1kcmF3ZXItY29udGVudD5cclxuPC9tYXQtZHJhd2VyLWNvbnRhaW5lcj4iXX0=
@@ -1,41 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { RuclibDrawerComponent } from './ruclib-drawer/ruclib-drawer.component';
4
- import { MatSidenavModule } from '@angular/material/sidenav';
5
- import { MatButtonModule } from '@angular/material/button';
6
- import { MatToolbarModule } from '@angular/material/toolbar';
7
- import { MatIconModule } from '@angular/material/icon';
8
- import { SafeHtmlPipe } from '../pipes/pipes/safe-html.pipe';
9
- import * as i0 from "@angular/core";
10
- export class RuclibDrawerModule {
11
- }
12
- RuclibDrawerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
13
- RuclibDrawerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerModule, declarations: [RuclibDrawerComponent,
14
- SafeHtmlPipe], imports: [CommonModule,
15
- MatButtonModule,
16
- MatIconModule,
17
- MatSidenavModule,
18
- MatToolbarModule], exports: [RuclibDrawerComponent] });
19
- RuclibDrawerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerModule, imports: [CommonModule,
20
- MatButtonModule,
21
- MatIconModule,
22
- MatSidenavModule,
23
- MatToolbarModule] });
24
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: RuclibDrawerModule, decorators: [{
25
- type: NgModule,
26
- args: [{
27
- imports: [
28
- CommonModule,
29
- MatButtonModule,
30
- MatIconModule,
31
- MatSidenavModule,
32
- MatToolbarModule,
33
- ],
34
- declarations: [
35
- RuclibDrawerComponent,
36
- SafeHtmlPipe
37
- ],
38
- exports: [RuclibDrawerComponent],
39
- }]
40
- }] });
41
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjbGliLWRyYXdlci5tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3J1Y2xpYi1kcmF3ZXIubW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDOztBQWdCN0QsTUFBTSxPQUFPLGtCQUFrQjs7Z0hBQWxCLGtCQUFrQjtpSEFBbEIsa0JBQWtCLGlCQUwzQixxQkFBcUI7UUFDckIsWUFBWSxhQVJaLFlBQVk7UUFDWixlQUFlO1FBQ2YsYUFBYTtRQUNiLGdCQUFnQjtRQUNoQixnQkFBZ0IsYUFNUixxQkFBcUI7aUhBRXBCLGtCQUFrQixZQVozQixZQUFZO1FBQ1osZUFBZTtRQUNmLGFBQWE7UUFDYixnQkFBZ0I7UUFDaEIsZ0JBQWdCOzRGQVFQLGtCQUFrQjtrQkFkOUIsUUFBUTttQkFBQztvQkFDUixPQUFPLEVBQUU7d0JBQ1AsWUFBWTt3QkFDWixlQUFlO3dCQUNmLGFBQWE7d0JBQ2IsZ0JBQWdCO3dCQUNoQixnQkFBZ0I7cUJBQ2pCO29CQUNELFlBQVksRUFBRTt3QkFDWixxQkFBcUI7d0JBQ3JCLFlBQVk7cUJBQ2I7b0JBQ0QsT0FBTyxFQUFFLENBQUMscUJBQXFCLENBQUM7aUJBQ2pDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgUnVjbGliRHJhd2VyQ29tcG9uZW50IH0gZnJvbSAnLi9ydWNsaWItZHJhd2VyL3J1Y2xpYi1kcmF3ZXIuY29tcG9uZW50JztcclxuaW1wb3J0IHsgTWF0U2lkZW5hdk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NpZGVuYXYnO1xyXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xyXG5pbXBvcnQgeyBNYXRUb29sYmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbGJhcic7XHJcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcclxuaW1wb3J0IHsgU2FmZUh0bWxQaXBlIH0gZnJvbSAnLi4vcGlwZXMvcGlwZXMvc2FmZS1odG1sLnBpcGUnO1xyXG5cclxuQE5nTW9kdWxlKHtcclxuICBpbXBvcnRzOiBbXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Nb2R1bGUsXHJcbiAgICBNYXRJY29uTW9kdWxlLFxyXG4gICAgTWF0U2lkZW5hdk1vZHVsZSxcclxuICAgIE1hdFRvb2xiYXJNb2R1bGUsXHJcbiAgXSxcclxuICBkZWNsYXJhdGlvbnM6IFtcclxuICAgIFJ1Y2xpYkRyYXdlckNvbXBvbmVudCxcclxuICAgIFNhZmVIdG1sUGlwZVxyXG4gIF0sXHJcbiAgZXhwb3J0czogW1J1Y2xpYkRyYXdlckNvbXBvbmVudF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBSdWNsaWJEcmF3ZXJNb2R1bGUge31cclxuIl19