@glowhop/angular-tour 1.0.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.
@@ -0,0 +1,624 @@
1
+ import { NgTemplateOutlet } from "@angular/common";
2
+ import { booleanAttribute, Component, computed, DestroyRef, Directive, ElementRef, effect, Injectable, InjectionToken, Injector, Input, inject, signal, TemplateRef, ViewChild, } from "@angular/core";
3
+ import { connectGlowTourRoot, OVERLAY_IDLE_ATTRIBUTES, OVERLAY_IDLE_STYLE, OVERLAY_PATH_IDLE_ATTRIBUTES, POINTER_IDLE_ATTRIBUTES, POINTER_IDLE_STYLE, POPOVER_IDLE_ATTRIBUTES, POPOVER_IDLE_STYLE, styleRecordToCssText, } from "@glowhop/core-tour/adapter";
4
+ import * as i0 from "@angular/core";
5
+ const OVERLAY_IDLE_STYLE_TEXT = styleRecordToCssText(OVERLAY_IDLE_STYLE);
6
+ const POINTER_IDLE_STYLE_TEXT = styleRecordToCssText(POINTER_IDLE_STYLE);
7
+ const POPOVER_IDLE_STYLE_TEXT = styleRecordToCssText(POPOVER_IDLE_STYLE);
8
+ const DEFAULT_POINTER_DIRECTION_CONTENT = {
9
+ bottom: "👇",
10
+ left: "👈",
11
+ right: "👉",
12
+ top: "👆",
13
+ };
14
+ const POINTER_DIRECTIONS = ["top", "bottom", "left", "right"];
15
+ class GlowTourScope {
16
+ binding = signal(null);
17
+ tour = signal(null);
18
+ snapshot = signal(null);
19
+ state = this.snapshot.asReadonly();
20
+ constructor() {
21
+ effect((onCleanup) => {
22
+ const tour = this.tour();
23
+ if (!tour) {
24
+ this.snapshot.set(null);
25
+ return;
26
+ }
27
+ this.snapshot.set(tour.state.get());
28
+ onCleanup(tour.state.subscribe((state) => this.snapshot.set(state)));
29
+ }, { allowSignalWrites: true });
30
+ }
31
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
32
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope });
33
+ }
34
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope, decorators: [{
35
+ type: Injectable
36
+ }], ctorParameters: () => [] });
37
+ const GLOW_TOUR_SCOPE = new InjectionToken("GlowTourScope");
38
+ function useTourScope() {
39
+ const scope = inject(GLOW_TOUR_SCOPE, { optional: true });
40
+ if (!scope) {
41
+ throw new Error('GlowTour components must be rendered inside <glow-tour-root [tour]="...">.');
42
+ }
43
+ return scope;
44
+ }
45
+ /**
46
+ * Injects the tour state signal into a component.
47
+ * Must be called within a GlowTourRoot component context.
48
+ * @returns A signal containing the current tour state or null.
49
+ */
50
+ export function injectGlowTour() {
51
+ return useTourScope().state;
52
+ }
53
+ class GlowTourReactiveComponent {
54
+ scope = useTourScope();
55
+ snapshot = this.scope.state;
56
+ step = computed(() => this.snapshot()?.currentStep?.currentProps ?? null);
57
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourReactiveComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
58
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourReactiveComponent, ngImport: i0 });
59
+ }
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourReactiveComponent, decorators: [{
61
+ type: Directive
62
+ }] });
63
+ /** Root container component for GlowTour.js. Provides tour context and manages the root binding. */
64
+ export class GlowTourRoot {
65
+ /** The tour controller instance to display. */
66
+ tour;
67
+ /** Optional prefix for generated HTML IDs. */
68
+ idPrefix;
69
+ element = inject((ElementRef));
70
+ scope = inject(GlowTourScope);
71
+ active = null;
72
+ initialized = false;
73
+ ngOnChanges() {
74
+ if (this.initialized)
75
+ this.reconcile();
76
+ }
77
+ ngOnInit() {
78
+ if (!this.tour) {
79
+ throw new Error("GlowTourRoot requires a tour input.");
80
+ }
81
+ this.initialized = true;
82
+ this.reconcile();
83
+ }
84
+ ngOnDestroy() {
85
+ this.release();
86
+ }
87
+ reconcile() {
88
+ const root = this.element.nativeElement;
89
+ const tour = this.tour;
90
+ const idPrefix = this.idPrefix;
91
+ this.scope.tour.set(tour);
92
+ const current = this.active;
93
+ if (current !== null &&
94
+ current.root === root &&
95
+ current.tour === tour &&
96
+ current.idPrefix === idPrefix) {
97
+ return;
98
+ }
99
+ this.release();
100
+ const binding = connectGlowTourRoot(tour, {
101
+ idPrefix,
102
+ root,
103
+ });
104
+ const active = { binding, idPrefix, root, tour };
105
+ this.active = active;
106
+ this.scope.binding.set(binding);
107
+ }
108
+ release() {
109
+ const active = this.active;
110
+ if (!active)
111
+ return;
112
+ this.active = null;
113
+ active.binding.release();
114
+ if (this.scope.binding() === active.binding)
115
+ this.scope.binding.set(null);
116
+ }
117
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourRoot, deps: [], target: i0.ɵɵFactoryTarget.Component });
118
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourRoot, isStandalone: true, selector: "glow-tour-root", inputs: { tour: "tour", idPrefix: "idPrefix" }, host: { attributes: { "data-glow-tour-root": "" } }, providers: [GlowTourScope, { provide: GLOW_TOUR_SCOPE, useExisting: GlowTourScope }], usesOnChanges: true, ngImport: i0, template: "<ng-content />", isInline: true });
119
+ }
120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourRoot, decorators: [{
121
+ type: Component,
122
+ args: [{
123
+ selector: "glow-tour-root",
124
+ standalone: true,
125
+ host: { "data-glow-tour-root": "" },
126
+ providers: [GlowTourScope, { provide: GLOW_TOUR_SCOPE, useExisting: GlowTourScope }],
127
+ template: "<ng-content />",
128
+ }]
129
+ }], propDecorators: { tour: [{
130
+ type: Input,
131
+ args: [{ required: true }]
132
+ }], idPrefix: [{
133
+ type: Input
134
+ }] } });
135
+ /** Header component displaying the current step's title. */
136
+ export class GlowTourHeader extends GlowTourReactiveComponent {
137
+ titleTemplate = computed(() => {
138
+ const title = this.step()?.title;
139
+ return title instanceof TemplateRef ? title : null;
140
+ });
141
+ titleText = computed(() => {
142
+ const title = this.step()?.title;
143
+ return typeof title === "string" ? title : "";
144
+ });
145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourHeader, deps: null, target: i0.ɵɵFactoryTarget.Component });
146
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourHeader, isStandalone: true, selector: "glow-tour-header", usesInheritance: true, ngImport: i0, template: `
147
+ <header data-glow-tour-header [id]="scope.binding()?.ids?.title">
148
+ @if (titleTemplate()) {
149
+ <ng-container [ngTemplateOutlet]="titleTemplate()" />
150
+ } @else {
151
+ {{ titleText() }}
152
+ }
153
+ </header>
154
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
155
+ }
156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourHeader, decorators: [{
157
+ type: Component,
158
+ args: [{
159
+ selector: "glow-tour-header",
160
+ standalone: true,
161
+ imports: [NgTemplateOutlet],
162
+ template: `
163
+ <header data-glow-tour-header [id]="scope.binding()?.ids?.title">
164
+ @if (titleTemplate()) {
165
+ <ng-container [ngTemplateOutlet]="titleTemplate()" />
166
+ } @else {
167
+ {{ titleText() }}
168
+ }
169
+ </header>
170
+ `,
171
+ }]
172
+ }] });
173
+ /** Content component displaying the current step's content with live region. */
174
+ export class GlowTourContent extends GlowTourReactiveComponent {
175
+ contentTemplate = computed(() => {
176
+ const content = this.step()?.content;
177
+ return content instanceof TemplateRef ? content : null;
178
+ });
179
+ contentText = computed(() => {
180
+ const content = this.step()?.content;
181
+ return typeof content === "string" ? content : "";
182
+ });
183
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourContent, deps: null, target: i0.ɵɵFactoryTarget.Component });
184
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourContent, isStandalone: true, selector: "glow-tour-content", usesInheritance: true, ngImport: i0, template: `
185
+ <div aria-live="polite" data-glow-tour-content [id]="scope.binding()?.ids?.description">
186
+ @if (contentTemplate()) {
187
+ <ng-container [ngTemplateOutlet]="contentTemplate()" />
188
+ } @else {
189
+ {{ contentText() }}
190
+ }
191
+ </div>
192
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
193
+ }
194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourContent, decorators: [{
195
+ type: Component,
196
+ args: [{
197
+ selector: "glow-tour-content",
198
+ standalone: true,
199
+ imports: [NgTemplateOutlet],
200
+ template: `
201
+ <div aria-live="polite" data-glow-tour-content [id]="scope.binding()?.ids?.description">
202
+ @if (contentTemplate()) {
203
+ <ng-container [ngTemplateOutlet]="contentTemplate()" />
204
+ } @else {
205
+ {{ contentText() }}
206
+ }
207
+ </div>
208
+ `,
209
+ }]
210
+ }] });
211
+ /** Footer component containing action buttons. Conditionally rendered based on tour step configuration. */
212
+ export class GlowTourFooter extends GlowTourReactiveComponent {
213
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourFooter, deps: null, target: i0.ɵɵFactoryTarget.Component });
214
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourFooter, isStandalone: true, selector: "glow-tour-footer", usesInheritance: true, ngImport: i0, template: `@if (!step()?.popover?.hideFooter) { <footer data-glow-tour-footer><ng-content /></footer> }`, isInline: true });
215
+ }
216
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourFooter, decorators: [{
217
+ type: Component,
218
+ args: [{
219
+ selector: "glow-tour-footer",
220
+ standalone: true,
221
+ template: `@if (!step()?.popover?.hideFooter) { <footer data-glow-tour-footer><ng-content /></footer> }`,
222
+ }]
223
+ }] });
224
+ class GlowTourBoundElement {
225
+ scope = useTourScope();
226
+ destroyRef = inject(DestroyRef);
227
+ injector = inject(Injector);
228
+ bind(element, bindElement) {
229
+ const cleanup = effect((onCleanup) => {
230
+ const binding = this.scope.binding();
231
+ if (binding)
232
+ onCleanup(bindElement(binding, element));
233
+ }, { injector: this.injector });
234
+ this.destroyRef.onDestroy(() => cleanup.destroy());
235
+ }
236
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBoundElement, deps: [], target: i0.ɵɵFactoryTarget.Directive });
237
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourBoundElement, ngImport: i0 });
238
+ }
239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBoundElement, decorators: [{
240
+ type: Directive
241
+ }] });
242
+ /** Popover component containing the tour content with accessibility attributes. */
243
+ export class GlowTourPopover extends GlowTourBoundElement {
244
+ element;
245
+ idleAriaHidden = POPOVER_IDLE_ATTRIBUTES["aria-hidden"];
246
+ idleInert = POPOVER_IDLE_ATTRIBUTES.inert;
247
+ idleStyle = POPOVER_IDLE_STYLE_TEXT;
248
+ ngOnInit() {
249
+ this.bind(this.element.nativeElement, (binding, element) => binding.bindPopover(element));
250
+ }
251
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPopover, deps: null, target: i0.ɵɵFactoryTarget.Component });
252
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourPopover, isStandalone: true, selector: "glow-tour-popover", viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
253
+ <section #tourElement
254
+ [attr.aria-hidden]="idleAriaHidden"
255
+ data-glow-tour-popover
256
+ [attr.aria-describedby]="scope.binding()?.ids?.description"
257
+ [attr.aria-labelledby]="scope.binding()?.ids?.title"
258
+ [id]="scope.binding()?.ids?.popover"
259
+ [attr.inert]="idleInert"
260
+ role="dialog"
261
+ [style]="idleStyle"
262
+ tabindex="-1"
263
+ ><ng-content /></section>
264
+ `, isInline: true });
265
+ }
266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPopover, decorators: [{
267
+ type: Component,
268
+ args: [{
269
+ selector: "glow-tour-popover",
270
+ standalone: true,
271
+ // The idle attributes/style come from imported `@glowhop/core-tour/adapter`
272
+ // constants, so ngc's AOT template analyzer (NG1010) cannot inline them as
273
+ // string-interpolated literals in the template. Bound via component fields
274
+ // instead; the values are still static, so server and client render
275
+ // byte-identical output.
276
+ template: `
277
+ <section #tourElement
278
+ [attr.aria-hidden]="idleAriaHidden"
279
+ data-glow-tour-popover
280
+ [attr.aria-describedby]="scope.binding()?.ids?.description"
281
+ [attr.aria-labelledby]="scope.binding()?.ids?.title"
282
+ [id]="scope.binding()?.ids?.popover"
283
+ [attr.inert]="idleInert"
284
+ role="dialog"
285
+ [style]="idleStyle"
286
+ tabindex="-1"
287
+ ><ng-content /></section>
288
+ `,
289
+ }]
290
+ }], propDecorators: { element: [{
291
+ type: ViewChild,
292
+ args: ["tourElement", { static: true }]
293
+ }] } });
294
+ /** Pointer component displaying directional indicators pointing to the target element. */
295
+ export class GlowTourPointer extends GlowTourBoundElement {
296
+ element;
297
+ directionContentValue = signal(undefined);
298
+ idleAriaHidden = POINTER_IDLE_ATTRIBUTES["aria-hidden"];
299
+ idleStyle = POINTER_IDLE_STYLE_TEXT;
300
+ directions = POINTER_DIRECTIONS;
301
+ content = computed(() => ({
302
+ ...DEFAULT_POINTER_DIRECTION_CONTENT,
303
+ ...this.directionContentValue(),
304
+ }));
305
+ /** Optional custom content for each pointer direction. */
306
+ set directionContent(value) {
307
+ this.directionContentValue.set(value);
308
+ }
309
+ asTemplate(value) {
310
+ return value instanceof TemplateRef ? value : null;
311
+ }
312
+ ngOnInit() {
313
+ this.bind(this.element.nativeElement, (binding, element) => binding.bindPointer(element));
314
+ }
315
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPointer, deps: null, target: i0.ɵɵFactoryTarget.Component });
316
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourPointer, isStandalone: true, selector: "glow-tour-pointer", inputs: { directionContent: "directionContent" }, viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
317
+ <div #tourElement data-glow-tour-pointer [attr.aria-hidden]="idleAriaHidden" [style]="idleStyle">
318
+ @for (direction of directions; track direction) {
319
+ <div [attr.data-glow-tour-pointer-direction]="direction">
320
+ @if (asTemplate(content()[direction]); as template) {
321
+ <ng-container [ngTemplateOutlet]="template" />
322
+ } @else {
323
+ {{ content()[direction] }}
324
+ }
325
+ </div>
326
+ }
327
+ </div>
328
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
329
+ }
330
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPointer, decorators: [{
331
+ type: Component,
332
+ args: [{
333
+ selector: "glow-tour-pointer",
334
+ standalone: true,
335
+ imports: [NgTemplateOutlet],
336
+ template: `
337
+ <div #tourElement data-glow-tour-pointer [attr.aria-hidden]="idleAriaHidden" [style]="idleStyle">
338
+ @for (direction of directions; track direction) {
339
+ <div [attr.data-glow-tour-pointer-direction]="direction">
340
+ @if (asTemplate(content()[direction]); as template) {
341
+ <ng-container [ngTemplateOutlet]="template" />
342
+ } @else {
343
+ {{ content()[direction] }}
344
+ }
345
+ </div>
346
+ }
347
+ </div>
348
+ `,
349
+ }]
350
+ }], propDecorators: { element: [{
351
+ type: ViewChild,
352
+ args: ["tourElement", { static: true }]
353
+ }], directionContent: [{
354
+ type: Input
355
+ }] } });
356
+ /** Overlay component rendering a clipped SVG mask highlighting the target element. */
357
+ export class GlowTourOverlay extends GlowTourBoundElement {
358
+ element;
359
+ idleAriaHidden = OVERLAY_IDLE_ATTRIBUTES["aria-hidden"];
360
+ idleAllowInteraction = OVERLAY_IDLE_ATTRIBUTES["data-glow-tour-allow-interaction"];
361
+ idleInert = OVERLAY_IDLE_ATTRIBUTES.inert;
362
+ idleStyle = OVERLAY_IDLE_STYLE_TEXT;
363
+ idlePathCursor = OVERLAY_PATH_IDLE_ATTRIBUTES.cursor;
364
+ idlePathOpacity = OVERLAY_PATH_IDLE_ATTRIBUTES.opacity;
365
+ idlePathPointerEvents = OVERLAY_PATH_IDLE_ATTRIBUTES["pointer-events"];
366
+ ngOnInit() {
367
+ this.bind(this.element.nativeElement, (binding, element) => binding.bindOverlay(element));
368
+ }
369
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourOverlay, deps: null, target: i0.ɵɵFactoryTarget.Component });
370
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourOverlay, isStandalone: true, selector: "glow-tour-overlay", viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
371
+ <svg #tourElement
372
+ [attr.aria-hidden]="idleAriaHidden"
373
+ [attr.data-glow-tour-allow-interaction]="idleAllowInteraction"
374
+ data-glow-tour-overlay
375
+ focusable="false"
376
+ [attr.inert]="idleInert"
377
+ role="presentation"
378
+ [style]="idleStyle"
379
+ viewBox="0 0 0 0"
380
+ >
381
+ <path
382
+ [attr.cursor]="idlePathCursor"
383
+ data-glow-tour-overlay-path
384
+ fill-rule="evenodd"
385
+ [attr.opacity]="idlePathOpacity"
386
+ [attr.pointer-events]="idlePathPointerEvents"
387
+ /><ng-content />
388
+ </svg>
389
+ `, isInline: true });
390
+ }
391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourOverlay, decorators: [{
392
+ type: Component,
393
+ args: [{
394
+ selector: "glow-tour-overlay",
395
+ standalone: true,
396
+ template: `
397
+ <svg #tourElement
398
+ [attr.aria-hidden]="idleAriaHidden"
399
+ [attr.data-glow-tour-allow-interaction]="idleAllowInteraction"
400
+ data-glow-tour-overlay
401
+ focusable="false"
402
+ [attr.inert]="idleInert"
403
+ role="presentation"
404
+ [style]="idleStyle"
405
+ viewBox="0 0 0 0"
406
+ >
407
+ <path
408
+ [attr.cursor]="idlePathCursor"
409
+ data-glow-tour-overlay-path
410
+ fill-rule="evenodd"
411
+ [attr.opacity]="idlePathOpacity"
412
+ [attr.pointer-events]="idlePathPointerEvents"
413
+ /><ng-content />
414
+ </svg>
415
+ `,
416
+ }]
417
+ }], propDecorators: { element: [{
418
+ type: ViewChild,
419
+ args: ["tourElement", { static: true }]
420
+ }] } });
421
+ class GlowTourTrigger extends GlowTourReactiveComponent {
422
+ ariaLabelValue = signal(undefined);
423
+ disabledValue = signal(false);
424
+ ariaLabelText = computed(() => this.ariaLabelValue());
425
+ consumerDisabled = computed(() => this.disabledValue());
426
+ ariaControls = computed(() => this.scope.binding()?.ids.popover);
427
+ setAriaLabel(value) {
428
+ this.ariaLabelValue.set(value);
429
+ }
430
+ setDisabled(value) {
431
+ this.disabledValue.set(value);
432
+ }
433
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourTrigger, deps: null, target: i0.ɵɵFactoryTarget.Directive });
434
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourTrigger, usesInheritance: true, ngImport: i0 });
435
+ }
436
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourTrigger, decorators: [{
437
+ type: Directive
438
+ }] });
439
+ /** Button component for navigating to the previous step in the tour. */
440
+ export class GlowTourBackTrigger extends GlowTourTrigger {
441
+ backLabelValue = signal(undefined);
442
+ /** Optional aria-label for the back button. */
443
+ set ariaLabel(value) {
444
+ this.setAriaLabel(value);
445
+ }
446
+ /** Optional label text for the back button. */
447
+ set backLabel(value) {
448
+ this.backLabelValue.set(value);
449
+ }
450
+ /** Whether the button is disabled. */
451
+ set disabled(value) {
452
+ this.setDisabled(value);
453
+ }
454
+ isDisabled = computed(() => this.consumerDisabled() ||
455
+ !this.snapshot()?.canPrevious ||
456
+ this.step()?.popover?.disablePreviousButton === true);
457
+ label = computed(() => this.backLabelValue() ?? "Back step");
458
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBackTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
459
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourBackTrigger, isStandalone: true, selector: "glow-tour-back-trigger", inputs: { ariaLabel: "ariaLabel", backLabel: "backLabel", disabled: ["disabled", "disabled", booleanAttribute] }, usesInheritance: true, ngImport: i0, template: `
460
+ @if (!step()?.popover?.hidePreviousButton) {
461
+ <button
462
+ data-glow-tour-previous-trigger
463
+ [attr.aria-controls]="ariaControls()"
464
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
465
+ [attr.aria-label]="ariaLabelText() ?? label()"
466
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
467
+ [disabled]="isDisabled()"
468
+ type="button"
469
+ ><ng-content>{{ label() }}</ng-content></button>
470
+ }
471
+ `, isInline: true });
472
+ }
473
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBackTrigger, decorators: [{
474
+ type: Component,
475
+ args: [{
476
+ selector: "glow-tour-back-trigger",
477
+ standalone: true,
478
+ template: `
479
+ @if (!step()?.popover?.hidePreviousButton) {
480
+ <button
481
+ data-glow-tour-previous-trigger
482
+ [attr.aria-controls]="ariaControls()"
483
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
484
+ [attr.aria-label]="ariaLabelText() ?? label()"
485
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
486
+ [disabled]="isDisabled()"
487
+ type="button"
488
+ ><ng-content>{{ label() }}</ng-content></button>
489
+ }
490
+ `,
491
+ }]
492
+ }], propDecorators: { ariaLabel: [{
493
+ type: Input
494
+ }], backLabel: [{
495
+ type: Input
496
+ }], disabled: [{
497
+ type: Input,
498
+ args: [{ transform: booleanAttribute }]
499
+ }] } });
500
+ /** Button component for advancing to the next step or finishing the tour. */
501
+ export class GlowTourAdvanceTrigger extends GlowTourTrigger {
502
+ finishLabelValue = signal(undefined);
503
+ advanceLabelValue = signal(undefined);
504
+ /** Optional aria-label for the advance button. */
505
+ set ariaLabel(value) {
506
+ this.setAriaLabel(value);
507
+ }
508
+ /** Whether the button is disabled. */
509
+ set disabled(value) {
510
+ this.setDisabled(value);
511
+ }
512
+ /** Optional label text for the finish step. */
513
+ set finishLabel(value) {
514
+ this.finishLabelValue.set(value);
515
+ }
516
+ /** Optional label text for advancing to the next step. */
517
+ set advanceLabel(value) {
518
+ this.advanceLabelValue.set(value);
519
+ }
520
+ isDisabled = computed(() => this.consumerDisabled() ||
521
+ !this.snapshot()?.canAdvance ||
522
+ this.step()?.popover?.disableAdvanceButton === true);
523
+ label = computed(() => {
524
+ return this.snapshot()?.isLastStep
525
+ ? (this.finishLabelValue() ?? "Finish tour")
526
+ : (this.advanceLabelValue() ?? "Advance step");
527
+ });
528
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourAdvanceTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
529
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourAdvanceTrigger, isStandalone: true, selector: "glow-tour-advance-trigger", inputs: { ariaLabel: "ariaLabel", disabled: ["disabled", "disabled", booleanAttribute], finishLabel: "finishLabel", advanceLabel: "advanceLabel" }, usesInheritance: true, ngImport: i0, template: `
530
+ @if (!step()?.popover?.hideAdvanceButton) {
531
+ <button
532
+ data-glow-tour-advance-trigger
533
+ [attr.aria-controls]="ariaControls()"
534
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
535
+ [attr.aria-label]="ariaLabelText() ?? label()"
536
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
537
+ [disabled]="isDisabled()"
538
+ type="button"
539
+ ><ng-content>{{ label() }}</ng-content></button>
540
+ }
541
+ `, isInline: true });
542
+ }
543
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourAdvanceTrigger, decorators: [{
544
+ type: Component,
545
+ args: [{
546
+ selector: "glow-tour-advance-trigger",
547
+ standalone: true,
548
+ template: `
549
+ @if (!step()?.popover?.hideAdvanceButton) {
550
+ <button
551
+ data-glow-tour-advance-trigger
552
+ [attr.aria-controls]="ariaControls()"
553
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
554
+ [attr.aria-label]="ariaLabelText() ?? label()"
555
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
556
+ [disabled]="isDisabled()"
557
+ type="button"
558
+ ><ng-content>{{ label() }}</ng-content></button>
559
+ }
560
+ `,
561
+ }]
562
+ }], propDecorators: { ariaLabel: [{
563
+ type: Input
564
+ }], disabled: [{
565
+ type: Input,
566
+ args: [{ transform: booleanAttribute }]
567
+ }], finishLabel: [{
568
+ type: Input
569
+ }], advanceLabel: [{
570
+ type: Input
571
+ }] } });
572
+ /** Button component for canceling/skipping the tour. */
573
+ export class GlowTourCancelTrigger extends GlowTourTrigger {
574
+ /** Optional aria-label for the cancel button. */
575
+ set ariaLabel(value) {
576
+ this.setAriaLabel(value);
577
+ }
578
+ /** Whether the button is disabled. */
579
+ set disabled(value) {
580
+ this.setDisabled(value);
581
+ }
582
+ isDisabled = computed(() => this.consumerDisabled() || !this.snapshot()?.canCancel);
583
+ label = computed(() => "Skip");
584
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourCancelTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
585
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourCancelTrigger, isStandalone: true, selector: "glow-tour-cancel-trigger", inputs: { ariaLabel: "ariaLabel", disabled: ["disabled", "disabled", booleanAttribute] }, usesInheritance: true, ngImport: i0, template: `
586
+ @if (snapshot()?.canCancel) {
587
+ <button
588
+ data-glow-tour-cancel-trigger
589
+ [attr.aria-controls]="ariaControls()"
590
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
591
+ [attr.aria-label]="ariaLabelText() ?? label()"
592
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
593
+ [disabled]="isDisabled()"
594
+ type="button"
595
+ ><ng-content>{{ label() }}</ng-content></button>
596
+ }
597
+ `, isInline: true });
598
+ }
599
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourCancelTrigger, decorators: [{
600
+ type: Component,
601
+ args: [{
602
+ selector: "glow-tour-cancel-trigger",
603
+ standalone: true,
604
+ template: `
605
+ @if (snapshot()?.canCancel) {
606
+ <button
607
+ data-glow-tour-cancel-trigger
608
+ [attr.aria-controls]="ariaControls()"
609
+ [attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
610
+ [attr.aria-label]="ariaLabelText() ?? label()"
611
+ [attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
612
+ [disabled]="isDisabled()"
613
+ type="button"
614
+ ><ng-content>{{ label() }}</ng-content></button>
615
+ }
616
+ `,
617
+ }]
618
+ }], propDecorators: { ariaLabel: [{
619
+ type: Input
620
+ }], disabled: [{
621
+ type: Input,
622
+ args: [{ transform: booleanAttribute }]
623
+ }] } });
624
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91ci1jb21wb25lbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3RvdXItY29tcG9uZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFNBQVMsRUFDVCxVQUFVLEVBQ1YsTUFBTSxFQUNOLFVBQVUsRUFDVixjQUFjLEVBQ2QsUUFBUSxFQUNSLEtBQUssRUFDTCxNQUFNLEVBS04sTUFBTSxFQUNOLFdBQVcsRUFDWCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUVMLG1CQUFtQixFQUNuQix1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLDRCQUE0QixFQUM1Qix1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLHVCQUF1QixFQUN2QixrQkFBa0IsRUFDbEIsb0JBQW9CLEdBQ3JCLE1BQU0sNEJBQTRCLENBQUM7O0FBR3BDLE1BQU0sdUJBQXVCLEdBQUcsb0JBQW9CLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUN6RSxNQUFNLHVCQUF1QixHQUFHLG9CQUFvQixDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDekUsTUFBTSx1QkFBdUIsR0FBRyxvQkFBb0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBZXpFLE1BQU0saUNBQWlDLEdBQXNDO0lBQzNFLE1BQU0sRUFBRSxJQUFJO0lBQ1osSUFBSSxFQUFFLElBQUk7SUFDVixLQUFLLEVBQUUsSUFBSTtJQUNYLEdBQUcsRUFBRSxJQUFJO0NBQ1YsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQVUsQ0FBQztBQVN2RSxNQUNNLGFBQWE7SUFDUixPQUFPLEdBQUcsTUFB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QixLQUFLO2dCQUlzQyxRQUFRO3NCQUFuRCxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdUZW1wbGF0ZU91dGxldCB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7XG4gIGJvb2xlYW5BdHRyaWJ1dGUsXG4gIENvbXBvbmVudCxcbiAgY29tcHV0ZWQsXG4gIERlc3Ryb3lSZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgZWZmZWN0LFxuICBJbmplY3RhYmxlLFxuICBJbmplY3Rpb25Ub2tlbixcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBpbmplY3QsXG4gIHR5cGUgT25DaGFuZ2VzLFxuICB0eXBlIE9uRGVzdHJveSxcbiAgdHlwZSBPbkluaXQsXG4gIHR5cGUgU2lnbmFsLFxuICBzaWduYWwsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IEdsb3dUb3VyIGFzIENvcmVHbG93VG91ciwgVG91clN0YXRlIH0gZnJvbSBcIkBnbG93aG9wL2NvcmUtdG91clwiO1xuaW1wb3J0IHtcbiAgdHlwZSBBZGFwdGVyUm9vdEJpbmRpbmcsXG4gIGNvbm5lY3RHbG93VG91clJvb3QsXG4gIE9WRVJMQVlfSURMRV9BVFRSSUJVVEVTLFxuICBPVkVSTEFZX0lETEVfU1RZTEUsXG4gIE9WRVJMQVlfUEFUSF9JRExFX0FUVFJJQlVURVMsXG4gIFBPSU5URVJfSURMRV9BVFRSSUJVVEVTLFxuICBQT0lOVEVSX0lETEVfU1RZTEUsXG4gIFBPUE9WRVJfSURMRV9BVFRSSUJVVEVTLFxuICBQT1BPVkVSX0lETEVfU1RZTEUsXG4gIHN0eWxlUmVjb3JkVG9Dc3NUZXh0LFxufSBmcm9tIFwiQGdsb3dob3AvY29yZS10b3VyL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgQW5ndWxhclRvdXJDb250ZW50IH0gZnJvbSBcIi4uL2dsb3ctdG91clwiO1xuXG5jb25zdCBPVkVSTEFZX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KE9WRVJMQVlfSURMRV9TVFlMRSk7XG5jb25zdCBQT0lOVEVSX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KFBPSU5URVJfSURMRV9TVFlMRSk7XG5jb25zdCBQT1BPVkVSX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KFBPUE9WRVJfSURMRV9TVFlMRSk7XG5cbnR5cGUgVG91ciA9IENvcmVHbG93VG91cjxBbmd1bGFyVG91ckNvbnRlbnQ+O1xuXG4vKiogUG9pbnRlciBkaXJlY3Rpb24gY29udGVudCB2YWx1ZSB0eXBlOiBzdHJpbmcgb3IgVGVtcGxhdGVSZWYuICovXG5leHBvcnQgdHlwZSBQb2ludGVyRGlyZWN0aW9uVmFsdWUgPSBzdHJpbmcgfCBUZW1wbGF0ZVJlZjx1bmtub3duPjtcblxuLyoqIFBvaW50ZXIgZGlyZWN0aW9uIGNvbnRlbnQgY29uZmlndXJhdGlvbiBmb3IgY3VzdG9tIHBvaW50ZXIgY29udGVudC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9pbnRlckRpcmVjdGlvbkNvbnRlbnQge1xuICByZWFkb25seSB0b3A/OiBQb2ludGVyRGlyZWN0aW9uVmFsdWU7XG4gIHJlYWRvbmx5IGJvdHRvbT86IFBvaW50ZXJEaXJlY3Rpb25WYWx1ZTtcbiAgcmVhZG9ubHkgbGVmdD86IFBvaW50ZXJEaXJlY3Rpb25WYWx1ZTtcbiAgcmVhZG9ubHkgcmlnaHQ/OiBQb2ludGVyRGlyZWN0aW9uVmFsdWU7XG59XG5cbmNvbnN0IERFRkFVTFRfUE9JTlRFUl9ESVJFQ1RJT05fQ09OVEVOVDogUmVxdWlyZWQ8UG9pbnRlckRpcmVjdGlvbkNvbnRlbnQ+ID0ge1xuICBib3R0b206IFwi8J+Rh1wiLFxuICBsZWZ0OiBcIvCfkYhcIixcbiAgcmlnaHQ6IFwi8J+RiVwiLFxuICB0b3A6IFwi8J+RhlwiLFxufTtcblxuY29uc3QgUE9JTlRFUl9ESVJFQ1RJT05TID0gW1widG9wXCIsIFwiYm90dG9tXCIsIFwibGVmdFwiLCBcInJpZ2h0XCJdIGFzIGNvbnN0O1xuXG5pbnRlcmZhY2UgQWN0aXZlUm9vdEJpbmRpbmcge1xuICByZWFkb25seSBiaW5kaW5nOiBBZGFwdGVyUm9vdEJpbmRpbmc7XG4gIHJlYWRvbmx5IGlkUHJlZml4OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHJvb3Q6IEhUTUxFbGVtZW50O1xuICByZWFkb25seSB0b3VyOiBUb3VyO1xufVxuXG5ASW5qZWN0YWJsZSgpXG5jbGFzcyBHbG93VG91clNjb3BlIHtcbiAgcmVhZG9ubHkgYmluZGluZyA9IHNpZ25hbDxBZGFwdGVyUm9vdEJpbmRpbmcgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgdG91ciA9IHNpZ25hbDxUb3VyIHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc25hcHNob3QgPSBzaWduYWw8VG91clN0YXRlPEFuZ3VsYXJUb3VyQ29udGVudD4gfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgc3RhdGUgPSB0aGlzLnNuYXBzaG90LmFzUmVhZG9ubHkoKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoXG4gICAgICAob25DbGVhbnVwKSA9PiB7XG4gICAgICAgIGNvbnN0IHRvdXIgPSB0aGlzLnRvdXIoKTtcbiAgICAgICAgaWYgKCF0b3VyKSB7XG4gICAgICAgICAgdGhpcy5zbmFwc2hvdC5zZXQobnVsbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc25hcHNob3Quc2V0KHRvdXIuc3RhdGUuZ2V0KCkpO1xuICAgICAgICBvbkNsZWFudXAodG91ci5zdGF0ZS5zdWJzY3JpYmUoKHN0YXRlKSA9PiB0aGlzLnNuYXBzaG90LnNldChzdGF0ZSkpKTtcbiAgICAgIH0sXG4gICAgICB7IGFsbG93U2lnbmFsV3JpdGVzOiB0cnVlIH0sXG4gICAgKTtcbiAgfVxufVxuXG5jb25zdCBHTE9XX1RPVVJfU0NPUEUgPSBuZXcgSW5qZWN0aW9uVG9rZW48R2xvd1RvdXJTY29wZT4oXCJHbG93VG91clNjb3BlXCIpO1xuXG5mdW5jdGlvbiB1c2VUb3VyU2NvcGUoKSB7XG4gIGNvbnN0IHNjb3BlID0gaW5qZWN0KEdMT1dfVE9VUl9TQ09QRSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgaWYgKCFzY29wZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignR2xvd1RvdXIgY29tcG9uZW50cyBtdXN0IGJlIHJlbmRlcmVkIGluc2lkZSA8Z2xvdy10b3VyLXJvb3QgW3RvdXJdPVwiLi4uXCI+LicpO1xuICB9XG4gIHJldHVybiBzY29wZTtcbn1cblxuLyoqXG4gKiBJbmplY3RzIHRoZSB0b3VyIHN0YXRlIHNpZ25hbCBpbnRvIGEgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgd2l0aGluIGEgR2xvd1RvdXJSb290IGNvbXBvbmVudCBjb250ZXh0LlxuICogQHJldHVybnMgQSBzaWduYWwgY29udGFpbmluZyB0aGUgY3VycmVudCB0b3VyIHN0YXRlIG9yIG51bGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RHbG93VG91cigpOiBTaWduYWw8VG91clN0YXRlPEFuZ3VsYXJUb3VyQ29udGVudD4gfCBudWxsPiB7XG4gIHJldHVybiB1c2VUb3VyU2NvcGUoKS5zdGF0ZTtcbn1cblxuQERpcmVjdGl2ZSgpXG5hYnN0cmFjdCBjbGFzcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNjb3BlID0gdXNlVG91clNjb3BlKCk7XG4gIHByb3RlY3RlZCByZWFkb25seSBzbmFwc2hvdCA9IHRoaXMuc2NvcGUuc3RhdGU7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdGVwID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5zbmFwc2hvdCgpPy5jdXJyZW50U3RlcD8uY3VycmVudFByb3BzID8/IG51bGwpO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiZ2xvdy10b3VyLXJvb3RcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaG9zdDogeyBcImRhdGEtZ2xvdy10b3VyLXJvb3RcIjogXCJcIiB9LFxuICBwcm92aWRlcnM6IFtHbG93VG91clNjb3BlLCB7IHByb3ZpZGU6IEdMT1dfVE9VUl9TQ09QRSwgdXNlRXhpc3Rpbmc6IEdsb3dUb3VyU2NvcGUgfV0sXG4gIHRlbXBsYXRlOiBcIjxuZy1jb250ZW50IC8+XCIsXG59KVxuLyoqIFJvb3QgY29udGFpbmVyIGNvbXBvbmVudCBmb3IgR2xvd1RvdXIuanMuIFByb3ZpZGVzIHRvdXIgY29udGV4dCBhbmQgbWFuYWdlcyB0aGUgcm9vdCBiaW5kaW5nLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyUm9vdCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPbkluaXQge1xuICAvKiogVGhlIHRvdXIgY29udHJvbGxlciBpbnN0YW5jZSB0byBkaXNwbGF5LiAqL1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSB0b3VyITogVG91cjtcbiAgLyoqIE9wdGlvbmFsIHByZWZpeCBmb3IgZ2VuZXJhdGVkIEhUTUwgSURzLiAqL1xuICBASW5wdXQoKSBpZFByZWZpeD86IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnQgPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pO1xuICBwcml2YXRlIHJlYWRvbmx5IHNjb3BlID0gaW5qZWN0KEdsb3dUb3VyU2NvcGUpO1xuICBwcml2YXRlIGFjdGl2ZTogQWN0aXZlUm9vdEJpbmRpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBpbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gIG5nT25DaGFuZ2VzKCkge1xuICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB0aGlzLnJlY29uY2lsZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKCF0aGlzLnRvdXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkdsb3dUb3VyUm9vdCByZXF1aXJlcyBhIHRvdXIgaW5wdXQuXCIpO1xuICAgIH1cblxuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIHRoaXMucmVjb25jaWxlKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnJlbGVhc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVjb25jaWxlKCkge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCB0b3VyID0gdGhpcy50b3VyO1xuICAgIGNvbnN0IGlkUHJlZml4ID0gdGhpcy5pZFByZWZpeDtcbiAgICB0aGlzLnNjb3BlLnRvdXIuc2V0KHRvdXIpO1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmFjdGl2ZTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50ICE9PSBudWxsICYmXG4gICAgICBjdXJyZW50LnJvb3QgPT09IHJvb3QgJiZcbiAgICAgIGN1cnJlbnQudG91ciA9PT0gdG91ciAmJlxuICAgICAgY3VycmVudC5pZFByZWZpeCA9PT0gaWRQcmVmaXhcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yZWxlYXNlKCk7XG4gICAgY29uc3QgYmluZGluZyA9IGNvbm5lY3RHbG93VG91clJvb3QodG91ciwge1xuICAgICAgaWRQcmVmaXgsXG4gICAgICByb290LFxuICAgIH0pO1xuICAgIGNvbnN0IGFjdGl2ZSA9IHsgYmluZGluZywgaWRQcmVmaXgsIHJvb3QsIHRvdXIgfTtcbiAgICB0aGlzLmFjdGl2ZSA9IGFjdGl2ZTtcbiAgICB0aGlzLnNjb3BlLmJpbmRpbmcuc2V0KGJpbmRpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWxlYXNlKCkge1xuICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuYWN0aXZlO1xuICAgIGlmICghYWN0aXZlKSByZXR1cm47XG4gICAgdGhpcy5hY3RpdmUgPSBudWxsO1xuICAgIGFjdGl2ZS5iaW5kaW5nLnJlbGVhc2UoKTtcbiAgICBpZiAodGhpcy5zY29wZS5iaW5kaW5nKCkgPT09IGFjdGl2ZS5iaW5kaW5nKSB0aGlzLnNjb3BlLmJpbmRpbmcuc2V0KG51bGwpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItaGVhZGVyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtOZ1RlbXBsYXRlT3V0bGV0XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8aGVhZGVyIGRhdGEtZ2xvdy10b3VyLWhlYWRlciBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LnRpdGxlXCI+XG4gICAgICBAaWYgKHRpdGxlVGVtcGxhdGUoKSkge1xuICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRpdGxlVGVtcGxhdGUoKVwiIC8+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAge3sgdGl0bGVUZXh0KCkgfX1cbiAgICAgIH1cbiAgICA8L2hlYWRlcj5cbiAgYCxcbn0pXG4vKiogSGVhZGVyIGNvbXBvbmVudCBkaXNwbGF5aW5nIHRoZSBjdXJyZW50IHN0ZXAncyB0aXRsZS4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91ckhlYWRlciBleHRlbmRzIEdsb3dUb3VyUmVhY3RpdmVDb21wb25lbnQge1xuICByZWFkb25seSB0aXRsZVRlbXBsYXRlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHRpdGxlID0gdGhpcy5zdGVwKCk/LnRpdGxlO1xuICAgIHJldHVybiB0aXRsZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmID8gdGl0bGUgOiBudWxsO1xuICB9KTtcbiAgcmVhZG9ubHkgdGl0bGVUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHRpdGxlID0gdGhpcy5zdGVwKCk/LnRpdGxlO1xuICAgIHJldHVybiB0eXBlb2YgdGl0bGUgPT09IFwic3RyaW5nXCIgPyB0aXRsZSA6IFwiXCI7XG4gIH0pO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiZ2xvdy10b3VyLWNvbnRlbnRcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW05nVGVtcGxhdGVPdXRsZXRdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgYXJpYS1saXZlPVwicG9saXRlXCIgZGF0YS1nbG93LXRvdXItY29udGVudCBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LmRlc2NyaXB0aW9uXCI+XG4gICAgICBAaWYgKGNvbnRlbnRUZW1wbGF0ZSgpKSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29udGVudFRlbXBsYXRlKClcIiAvPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIHt7IGNvbnRlbnRUZXh0KCkgfX1cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG4vKiogQ29udGVudCBjb21wb25lbnQgZGlzcGxheWluZyB0aGUgY3VycmVudCBzdGVwJ3MgY29udGVudCB3aXRoIGxpdmUgcmVnaW9uLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyQ29udGVudCBleHRlbmRzIEdsb3dUb3VyUmVhY3RpdmVDb21wb25lbnQge1xuICByZWFkb25seSBjb250ZW50VGVtcGxhdGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY29udGVudCA9IHRoaXMuc3RlcCgpPy5jb250ZW50O1xuICAgIHJldHVybiBjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYgPyBjb250ZW50IDogbnVsbDtcbiAgfSk7XG4gIHJlYWRvbmx5IGNvbnRlbnRUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLnN0ZXAoKT8uY29udGVudDtcbiAgICByZXR1cm4gdHlwZW9mIGNvbnRlbnQgPT09IFwic3RyaW5nXCIgPyBjb250ZW50IDogXCJcIjtcbiAgfSk7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItZm9vdGVyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgQGlmICghc3RlcCgpPy5wb3BvdmVyPy5oaWRlRm9vdGVyKSB7IDxmb290ZXIgZGF0YS1nbG93LXRvdXItZm9vdGVyPjxuZy1jb250ZW50IC8+PC9mb290ZXI+IH1gLFxufSlcbi8qKiBGb290ZXIgY29tcG9uZW50IGNvbnRhaW5pbmcgYWN0aW9uIGJ1dHRvbnMuIENvbmRpdGlvbmFsbHkgcmVuZGVyZWQgYmFzZWQgb24gdG91ciBzdGVwIGNvbmZpZ3VyYXRpb24uICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJGb290ZXIgZXh0ZW5kcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHt9XG5cbkBEaXJlY3RpdmUoKVxuYWJzdHJhY3QgY2xhc3MgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8VCBleHRlbmRzIEVsZW1lbnQ+IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNjb3BlID0gdXNlVG91clNjb3BlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmplY3RvciA9IGluamVjdChJbmplY3Rvcik7XG5cbiAgcHJvdGVjdGVkIGJpbmQoZWxlbWVudDogVCwgYmluZEVsZW1lbnQ6IChiaW5kaW5nOiBBZGFwdGVyUm9vdEJpbmRpbmcsIGVsZW1lbnQ6IFQpID0+ICgpID0+IHZvaWQpIHtcbiAgICBjb25zdCBjbGVhbnVwID0gZWZmZWN0KFxuICAgICAgKG9uQ2xlYW51cCkgPT4ge1xuICAgICAgICBjb25zdCBiaW5kaW5nID0gdGhpcy5zY29wZS5iaW5kaW5nKCk7XG4gICAgICAgIGlmIChiaW5kaW5nKSBvbkNsZWFudXAoYmluZEVsZW1lbnQoYmluZGluZywgZWxlbWVudCkpO1xuICAgICAgfSxcbiAgICAgIHsgaW5qZWN0b3I6IHRoaXMuaW5qZWN0b3IgfSxcbiAgICApO1xuICAgIHRoaXMuZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4gY2xlYW51cC5kZXN0cm95KCkpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItcG9wb3ZlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICAvLyBUaGUgaWRsZSBhdHRyaWJ1dGVzL3N0eWxlIGNvbWUgZnJvbSBpbXBvcnRlZCBgQGdsb3dob3AvY29yZS10b3VyL2FkYXB0ZXJgXG4gIC8vIGNvbnN0YW50cywgc28gbmdjJ3MgQU9UIHRlbXBsYXRlIGFuYWx5emVyIChORzEwMTApIGNhbm5vdCBpbmxpbmUgdGhlbSBhc1xuICAvLyBzdHJpbmctaW50ZXJwb2xhdGVkIGxpdGVyYWxzIGluIHRoZSB0ZW1wbGF0ZS4gQm91bmQgdmlhIGNvbXBvbmVudCBmaWVsZHNcbiAgLy8gaW5zdGVhZDsgdGhlIHZhbHVlcyBhcmUgc3RpbGwgc3RhdGljLCBzbyBzZXJ2ZXIgYW5kIGNsaWVudCByZW5kZXJcbiAgLy8gYnl0ZS1pZGVudGljYWwgb3V0cHV0LlxuICB0ZW1wbGF0ZTogYFxuICAgIDxzZWN0aW9uICN0b3VyRWxlbWVudFxuICAgICAgW2F0dHIuYXJpYS1oaWRkZW5dPVwiaWRsZUFyaWFIaWRkZW5cIlxuICAgICAgZGF0YS1nbG93LXRvdXItcG9wb3ZlclxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJzY29wZS5iaW5kaW5nKCk/Lmlkcz8uZGVzY3JpcHRpb25cIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cInNjb3BlLmJpbmRpbmcoKT8uaWRzPy50aXRsZVwiXG4gICAgICBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LnBvcG92ZXJcIlxuICAgICAgW2F0dHIuaW5lcnRdPVwiaWRsZUluZXJ0XCJcbiAgICAgIHJvbGU9XCJkaWFsb2dcIlxuICAgICAgW3N0eWxlXT1cImlkbGVTdHlsZVwiXG4gICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICA+PG5nLWNvbnRlbnQgLz48L3NlY3Rpb24+XG4gIGAsXG59KVxuLyoqIFBvcG92ZXIgY29tcG9uZW50IGNvbnRhaW5pbmcgdGhlIHRvdXIgY29udGVudCB3aXRoIGFjY2Vzc2liaWxpdHkgYXR0cmlidXRlcy4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91clBvcG92ZXIgZXh0ZW5kcyBHbG93VG91ckJvdW5kRWxlbWVudDxIVE1MRWxlbWVudD4gaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKFwidG91ckVsZW1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50ITogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlQXJpYUhpZGRlbiA9IFBPUE9WRVJfSURMRV9BVFRSSUJVVEVTW1wiYXJpYS1oaWRkZW5cIl07XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlSW5lcnQgPSBQT1BPVkVSX0lETEVfQVRUUklCVVRFUy5pbmVydDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVTdHlsZSA9IFBPUE9WRVJfSURMRV9TVFlMRV9URVhUO1xuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYmluZCh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCwgKGJpbmRpbmcsIGVsZW1lbnQpID0+IGJpbmRpbmcuYmluZFBvcG92ZXIoZWxlbWVudCkpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItcG9pbnRlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTmdUZW1wbGF0ZU91dGxldF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiAjdG91ckVsZW1lbnQgZGF0YS1nbG93LXRvdXItcG9pbnRlciBbYXR0ci5hcmlhLWhpZGRlbl09XCJpZGxlQXJpYUhpZGRlblwiIFtzdHlsZV09XCJpZGxlU3R5bGVcIj5cbiAgICAgIEBmb3IgKGRpcmVjdGlvbiBvZiBkaXJlY3Rpb25zOyB0cmFjayBkaXJlY3Rpb24pIHtcbiAgICAgICAgPGRpdiBbYXR0ci5kYXRhLWdsb3ctdG91ci1wb2ludGVyLWRpcmVjdGlvbl09XCJkaXJlY3Rpb25cIj5cbiAgICAgICAgICBAaWYgKGFzVGVtcGxhdGUoY29udGVudCgpW2RpcmVjdGlvbl0pOyBhcyB0ZW1wbGF0ZSkge1xuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJ0ZW1wbGF0ZVwiIC8+XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyBjb250ZW50KClbZGlyZWN0aW9uXSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuLyoqIFBvaW50ZXIgY29tcG9uZW50IGRpc3BsYXlpbmcgZGlyZWN0aW9uYWwgaW5kaWNhdG9ycyBwb2ludGluZyB0byB0aGUgdGFyZ2V0IGVsZW1lbnQuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJQb2ludGVyIGV4dGVuZHMgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8SFRNTEVsZW1lbnQ+IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQFZpZXdDaGlsZChcInRvdXJFbGVtZW50XCIsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgcmVhZG9ubHkgZWxlbWVudCE6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGRpcmVjdGlvbkNvbnRlbnRWYWx1ZSA9IHNpZ25hbDxQb2ludGVyRGlyZWN0aW9uQ29udGVudCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBcmlhSGlkZGVuID0gUE9JTlRFUl9JRExFX0FUVFJJQlVURVNbXCJhcmlhLWhpZGRlblwiXTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVTdHlsZSA9IFBPSU5URVJfSURMRV9TVFlMRV9URVhUO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBkaXJlY3Rpb25zID0gUE9JTlRFUl9ESVJFQ1RJT05TO1xuICByZWFkb25seSBjb250ZW50ID0gY29tcHV0ZWQoKCkgPT4gKHtcbiAgICAuLi5ERUZBVUxUX1BPSU5URVJfRElSRUNUSU9OX0NPTlRFTlQsXG4gICAgLi4udGhpcy5kaXJlY3Rpb25Db250ZW50VmFsdWUoKSxcbiAgfSkpO1xuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gY29udGVudCBmb3IgZWFjaCBwb2ludGVyIGRpcmVjdGlvbi4gKi9cbiAgQElucHV0KCkgc2V0IGRpcmVjdGlvbkNvbnRlbnQodmFsdWU6IFBvaW50ZXJEaXJlY3Rpb25Db250ZW50IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5kaXJlY3Rpb25Db250ZW50VmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc1RlbXBsYXRlKHZhbHVlOiBQb2ludGVyRGlyZWN0aW9uVmFsdWUpOiBUZW1wbGF0ZVJlZjx1bmtub3duPiB8IG51bGwge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmID8gdmFsdWUgOiBudWxsO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5iaW5kKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAoYmluZGluZywgZWxlbWVudCkgPT4gYmluZGluZy5iaW5kUG9pbnRlcihlbGVtZW50KSk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1vdmVybGF5XCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgXG4gICAgPHN2ZyAjdG91ckVsZW1lbnRcbiAgICAgIFthdHRyLmFyaWEtaGlkZGVuXT1cImlkbGVBcmlhSGlkZGVuXCJcbiAgICAgIFthdHRyLmRhdGEtZ2xvdy10b3VyLWFsbG93LWludGVyYWN0aW9uXT1cImlkbGVBbGxvd0ludGVyYWN0aW9uXCJcbiAgICAgIGRhdGEtZ2xvdy10b3VyLW92ZXJsYXlcbiAgICAgIGZvY3VzYWJsZT1cImZhbHNlXCJcbiAgICAgIFthdHRyLmluZXJ0XT1cImlkbGVJbmVydFwiXG4gICAgICByb2xlPVwicHJlc2VudGF0aW9uXCJcbiAgICAgIFtzdHlsZV09XCJpZGxlU3R5bGVcIlxuICAgICAgdmlld0JveD1cIjAgMCAwIDBcIlxuICAgID5cbiAgICAgIDxwYXRoXG4gICAgICAgIFthdHRyLmN1cnNvcl09XCJpZGxlUGF0aEN1cnNvclwiXG4gICAgICAgIGRhdGEtZ2xvdy10b3VyLW92ZXJsYXktcGF0aFxuICAgICAgICBmaWxsLXJ1bGU9XCJldmVub2RkXCJcbiAgICAgICAgW2F0dHIub3BhY2l0eV09XCJpZGxlUGF0aE9wYWNpdHlcIlxuICAgICAgICBbYXR0ci5wb2ludGVyLWV2ZW50c109XCJpZGxlUGF0aFBvaW50ZXJFdmVudHNcIlxuICAgICAgLz48bmctY29udGVudCAvPlxuICAgIDwvc3ZnPlxuICBgLFxufSlcbi8qKiBPdmVybGF5IGNvbXBvbmVudCByZW5kZXJpbmcgYSBjbGlwcGVkIFNWRyBtYXNrIGhpZ2hsaWdodGluZyB0aGUgdGFyZ2V0IGVsZW1lbnQuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJPdmVybGF5IGV4dGVuZHMgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8U1ZHU1ZHRWxlbWVudD4gaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKFwidG91ckVsZW1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50ITogRWxlbWVudFJlZjxTVkdTVkdFbGVtZW50PjtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBcmlhSGlkZGVuID0gT1ZFUkxBWV9JRExFX0FUVFJJQlVURVNbXCJhcmlhLWhpZGRlblwiXTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBbGxvd0ludGVyYWN0aW9uID1cbiAgICBPVkVSTEFZX0lETEVfQVRUUklCVVRFU1tcImRhdGEtZ2xvdy10b3VyLWFsbG93LWludGVyYWN0aW9uXCJdO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaWRsZUluZXJ0ID0gT1ZFUkxBWV9JRExFX0FUVFJJQlVURVMuaW5lcnQ7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlU3R5bGUgPSBPVkVSTEFZX0lETEVfU1RZTEVfVEVYVDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVQYXRoQ3Vyc29yID0gT1ZFUkxBWV9QQVRIX0lETEVfQVRUUklCVVRFUy5jdXJzb3I7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlUGF0aE9wYWNpdHkgPSBPVkVSTEFZX1BBVEhfSURMRV9BVFRSSUJVVEVTLm9wYWNpdHk7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlUGF0aFBvaW50ZXJFdmVudHMgPSBPVkVSTEFZX1BBVEhfSURMRV9BVFRSSUJVVEVTW1wicG9pbnRlci1ldmVudHNcIl07XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5iaW5kKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAoYmluZGluZywgZWxlbWVudCkgPT4gYmluZGluZy5iaW5kT3ZlcmxheShlbGVtZW50KSk7XG4gIH1cbn1cblxuQERpcmVjdGl2ZSgpXG5hYnN0cmFjdCBjbGFzcyBHbG93VG91clRyaWdnZXIgZXh0ZW5kcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhcmlhTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGlzYWJsZWRWYWx1ZSA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGFyaWFMYWJlbFRleHQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmFyaWFMYWJlbFZhbHVlKCkpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29uc3VtZXJEaXNhYmxlZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZGlzYWJsZWRWYWx1ZSgpKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGFyaWFDb250cm9scyA9IGNvbXB1dGVkKCgpID0+IHRoaXMuc2NvcGUuYmluZGluZygpPy5pZHMucG9wb3Zlcik7XG5cbiAgcHJvdGVjdGVkIHNldEFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5hcmlhTGFiZWxWYWx1ZS5zZXQodmFsdWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldERpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5kaXNhYmxlZFZhbHVlLnNldCh2YWx1ZSk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1iYWNrLXRyaWdnZXJcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKCFzdGVwKCk/LnBvcG92ZXI/LmhpZGVQcmV2aW91c0J1dHRvbikge1xuICAgICAgPGJ1dHRvblxuICAgICAgICBkYXRhLWdsb3ctdG91ci1wcmV2aW91cy10cmlnZ2VyXG4gICAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzRGlzYWJsZWQoKSA/ICd0cnVlJyA6ICdmYWxzZSdcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFRleHQoKSA/PyBsYWJlbCgpXCJcbiAgICAgICAgW2F0dHIuZGF0YS1nbG93LXRvdXItY29uc3VtZXItZGlzYWJsZWRdPVwiY29uc3VtZXJEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgID48bmctY29udGVudD57eyBsYWJlbCgpIH19PC9uZy1jb250ZW50PjwvYnV0dG9uPlxuICAgIH1cbiAgYCxcbn0pXG4vKiogQnV0dG9uIGNvbXBvbmVudCBmb3IgbmF2aWdhdGluZyB0byB0aGUgcHJldmlvdXMgc3RlcCBpbiB0aGUgdG91ci4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91ckJhY2tUcmlnZ2VyIGV4dGVuZHMgR2xvd1RvdXJUcmlnZ2VyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYWNrTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbiAgLyoqIE9wdGlvbmFsIGFyaWEtbGFiZWwgZm9yIHRoZSBiYWNrIGJ1dHRvbi4gKi9cbiAgQElucHV0KCkgc2V0IGFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5zZXRBcmlhTGFiZWwodmFsdWUpO1xuICB9XG4gIC8qKiBPcHRpb25hbCBsYWJlbCB0ZXh0IGZvciB0aGUgYmFjayBidXR0b24uICovXG4gIEBJbnB1dCgpIHNldCBiYWNrTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuYmFja0xhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuICAvKiogV2hldGhlciB0aGUgYnV0dG9uIGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXREaXNhYmxlZCh2YWx1ZSk7XG4gIH1cblxuICByZWFkb25seSBpc0Rpc2FibGVkID0gY29tcHV0ZWQoXG4gICAgKCkgPT5cbiAgICAgIHRoaXMuY29uc3VtZXJEaXNhYmxlZCgpIHx8XG4gICAgICAhdGhpcy5zbmFwc2hvdCgpPy5jYW5QcmV2aW91cyB8fFxuICAgICAgdGhpcy5zdGVwKCk/LnBvcG92ZXI/LmRpc2FibGVQcmV2aW91c0J1dHRvbiA9PT0gdHJ1ZSxcbiAgKTtcbiAgcmVhZG9ubHkgbGFiZWwgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmJhY2tMYWJlbFZhbHVlKCkgPz8gXCJCYWNrIHN0ZXBcIik7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItYWR2YW5jZS10cmlnZ2VyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgXG4gICAgQGlmICghc3RlcCgpPy5wb3BvdmVyPy5oaWRlQWR2YW5jZUJ1dHRvbikge1xuICAgICAgPGJ1dHRvblxuICAgICAgICBkYXRhLWdsb3ctdG91ci1hZHZhbmNlLXRyaWdnZXJcbiAgICAgICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJhcmlhQ29udHJvbHMoKVwiXG4gICAgICAgIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiaXNEaXNhYmxlZCgpID8gJ3RydWUnIDogJ2ZhbHNlJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsVGV4dCgpID8/IGxhYmVsKClcIlxuICAgICAgICBbYXR0ci5kYXRhLWdsb3ctdG91ci1jb25zdW1lci1kaXNhYmxlZF09XCJjb25zdW1lckRpc2FibGVkKCkgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWQoKVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgPjxuZy1jb250ZW50Pnt7IGxhYmVsKCkgfX08L25nLWNvbnRlbnQ+PC9idXR0b24+XG4gICAgfVxuICBgLFxufSlcbi8qKiBCdXR0b24gY29tcG9uZW50IGZvciBhZHZhbmNpbmcgdG8gdGhlIG5leHQgc3RlcCBvciBmaW5pc2hpbmcgdGhlIHRvdXIuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJBZHZhbmNlVHJpZ2dlciBleHRlbmRzIEdsb3dUb3VyVHJpZ2dlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZmluaXNoTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWR2YW5jZUxhYmVsVmFsdWUgPSBzaWduYWw8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIC8qKiBPcHRpb25hbCBhcmlhLWxhYmVsIGZvciB0aGUgYWR2YW5jZSBidXR0b24uICovXG4gIEBJbnB1dCgpIHNldCBhcmlhTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuc2V0QXJpYUxhYmVsKHZhbHVlKTtcbiAgfVxuICAvKiogV2hldGhlciB0aGUgYnV0dG9uIGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXREaXNhYmxlZCh2YWx1ZSk7XG4gIH1cbiAgLyoqIE9wdGlvbmFsIGxhYmVsIHRleHQgZm9yIHRoZSBmaW5pc2ggc3RlcC4gKi9cbiAgQElucHV0KCkgc2V0IGZpbmlzaExhYmVsKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmZpbmlzaExhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuICAvKiogT3B0aW9uYWwgbGFiZWwgdGV4dCBmb3IgYWR2YW5jaW5nIHRvIHRoZSBuZXh0IHN0ZXAuICovXG4gIEBJbnB1dCgpIHNldCBhZHZhbmNlTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuYWR2YW5jZUxhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuXG4gIHJlYWRvbmx5IGlzRGlzYWJsZWQgPSBjb21wdXRlZChcbiAgICAoKSA9PlxuICAgICAgdGhpcy5jb25zdW1lckRpc2FibGVkKCkgfHxcbiAgICAgICF0aGlzLnNuYXBzaG90KCk/LmNhbkFkdmFuY2UgfHxcbiAgICAgIHRoaXMuc3RlcCgpPy5wb3BvdmVyPy5kaXNhYmxlQWR2YW5jZUJ1dHRvbiA9PT0gdHJ1ZSxcbiAgKTtcbiAgcmVhZG9ubHkgbGFiZWwgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc25hcHNob3QoKT8uaXNMYXN0U3RlcFxuICAgICAgPyAodGhpcy5maW5pc2hMYWJlbFZhbHVlKCkgPz8gXCJGaW5pc2ggdG91clwiKVxuICAgICAgOiAodGhpcy5hZHZhbmNlTGFiZWxWYWx1ZSgpID8/IFwiQWR2YW5jZSBzdGVwXCIpO1xuICB9KTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1jYW5jZWwtdHJpZ2dlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoc25hcHNob3QoKT8uY2FuQ2FuY2VsKSB7XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGRhdGEtZ2xvdy10b3VyLWNhbmNlbC10cmlnZ2VyXG4gICAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzRGlzYWJsZWQoKSA/ICd0cnVlJyA6ICdmYWxzZSdcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFRleHQoKSA/PyBsYWJlbCgpXCJcbiAgICAgICAgW2F0dHIuZGF0YS1nbG93LXRvdXItY29uc3VtZXItZGlzYWJsZWRdPVwiY29uc3VtZXJEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgID48bmctY29udGVudD57eyBsYWJlbCgpIH19PC9uZy1jb250ZW50PjwvYnV0dG9uPlxuICAgIH1cbiAgYCxcbn0pXG4vKiogQnV0dG9uIGNvbXBvbmVudCBmb3IgY2FuY2VsaW5nL3NraXBwaW5nIHRoZSB0b3VyLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyQ2FuY2VsVHJpZ2dlciBleHRlbmRzIEdsb3dUb3VyVHJpZ2dlciB7XG4gIC8qKiBPcHRpb25hbCBhcmlhLWxhYmVsIGZvciB0aGUgY2FuY2VsIGJ1dHRvbi4gKi9cbiAgQElucHV0KCkgc2V0IGFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5zZXRBcmlhTGFiZWwodmFsdWUpO1xuICB9XG4gIC8qKiBXaGV0aGVyIHRoZSBidXR0b24gaXMgZGlzYWJsZWQuICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzZXQgZGlzYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldERpc2FibGVkKHZhbHVlKTtcbiAgfVxuXG4gIHJlYWRvbmx5IGlzRGlzYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNvbnN1bWVyRGlzYWJsZWQoKSB8fCAhdGhpcy5zbmFwc2hvdCgpPy5jYW5DYW5jZWwpO1xuICByZWFkb25seSBsYWJlbCA9IGNvbXB1dGVkKCgpID0+IFwiU2tpcFwiKTtcbn1cbiJdfQ==