@covalent/guided-tour 3.1.2 → 4.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,4 @@
1
1
  @import './guided-tour.scss';
2
- @import '~@angular/material/button/button-base';
3
2
 
4
3
  @mixin covalent-guided-tour-theme($theme, $config: null) {
5
4
  @include td-guided-tour-typography($config);
@@ -14,9 +13,11 @@
14
13
  .shepherd-title {
15
14
  @include mat-typography-level-to-styles($config, subheading-2);
16
15
  }
16
+
17
17
  .shepherd-text {
18
18
  @include mat-typography-level-to-styles($config, body-1);
19
19
  }
20
+
20
21
  .shepherd-progress {
21
22
  @include mat-typography-level-to-styles($config, body-1);
22
23
  }
@@ -41,6 +42,7 @@
41
42
  .shepherd-cancel-icon span::after {
42
43
  color: mat-color($accent, darker-contrast);
43
44
  }
45
+
44
46
  .shepherd-button:not(:disabled),
45
47
  .shepherd-button.shepherd-button-secondary:not(:disabled),
46
48
  .shepherd-cancel-icon {
@@ -61,8 +63,6 @@
61
63
  // Bringing in mat-icon button styles
62
64
  // Class can't be passed so we must include mat button styles here
63
65
  .shepherd-cancel-icon {
64
- @include mat-button-base;
65
-
66
66
  min-width: 0;
67
67
  margin: 0;
68
68
  padding: 0;
@@ -72,6 +72,7 @@
72
72
  line-height: $mat-icon-button-size;
73
73
  border-radius: $mat-icon-button-border-radius;
74
74
  }
75
+
75
76
  .shepherd-void-button {
76
77
  display: none;
77
78
  }
package/_guided-tour.scss CHANGED
@@ -5,12 +5,14 @@ $mat-icon-font: 'Material Icons', sans-serif;
5
5
  @include mat-elevation-transition;
6
6
  @include mat-elevation(4);
7
7
  }
8
+
8
9
  .shepherd-element:hover {
9
10
  .shepherd-content,
10
11
  .shepherd-arrow::before {
11
12
  @include mat-elevation(8);
12
13
  }
13
14
  }
15
+
14
16
  .shepherd-arrow::after {
15
17
  content: '';
16
18
  position: absolute;
@@ -39,6 +41,7 @@ $mat-icon-font: 'Material Icons', sans-serif;
39
41
  .shepherd-element[data-popper-placement^='top'] > .shepherd-arrow::after {
40
42
  bottom: 8px;
41
43
  }
44
+
42
45
  .shepherd-element[data-popper-placement^='bottom'] > .shepherd-arrow::after {
43
46
  top: 8px;
44
47
  }
@@ -49,9 +52,11 @@ $mat-icon-font: 'Material Icons', sans-serif;
49
52
  height: 48px;
50
53
  bottom: -16px;
51
54
  }
55
+
52
56
  .shepherd-element[data-popper-placement^='left'] > .shepherd-arrow::after {
53
57
  right: 8px;
54
58
  }
59
+
55
60
  .shepherd-element[data-popper-placement^='right'] > .shepherd-arrow::after {
56
61
  left: 8px;
57
62
  }
@@ -62,6 +67,7 @@ $mat-icon-font: 'Material Icons', sans-serif;
62
67
  cursor: pointer;
63
68
  margin-right: 0.5rem;
64
69
  padding: 0.5rem 1.5rem;
70
+
65
71
  &.material-icons {
66
72
  font-family: $mat-icon-font;
67
73
  font-size: 24px;
@@ -114,11 +120,14 @@ $mat-icon-font: 'Material Icons', sans-serif;
114
120
  background: none;
115
121
  font-size: 1.6em;
116
122
  font-family: $mat-icon-font;
123
+ position: relative;
124
+ border-width: 0;
117
125
  // Work around for having material icon as close button
118
126
  // Shepherd uses a span with 'x' string as content and aria-label hidden,
119
127
  // hence, doing this won't affect accessibility.
120
128
  span {
121
129
  color: transparent;
130
+
122
131
  &::after {
123
132
  content: 'close';
124
133
  font-size: 20px;
@@ -157,7 +166,7 @@ $mat-icon-font: 'Material Icons', sans-serif;
157
166
 
158
167
  .shepherd-element {
159
168
  border-radius: 5px;
160
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
169
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 20%);
161
170
  max-width: 400px;
162
171
  min-width: 400px;
163
172
  min-height: 100px;
@@ -198,21 +207,26 @@ $mat-icon-font: 'Material Icons', sans-serif;
198
207
  .shepherd-element[data-popper-placement^='top'] > .shepherd-arrow {
199
208
  bottom: -8px;
200
209
  }
210
+
201
211
  .shepherd-element[data-popper-placement^='bottom'] > .shepherd-arrow {
202
212
  top: -8px;
203
213
  }
214
+
204
215
  .shepherd-element[data-popper-placement^='left'] > .shepherd-arrow {
205
216
  right: -8px;
206
217
  }
218
+
207
219
  .shepherd-element[data-popper-placement^='right'] > .shepherd-arrow {
208
220
  left: -8px;
209
221
  }
222
+
210
223
  .shepherd-target-click-disabled.shepherd-enabled.shepherd-target,
211
224
  .shepherd-target-click-disabled.shepherd-enabled.shepherd-target * {
212
225
  pointer-events: none;
213
226
  }
227
+
214
228
  .shepherd-modal-overlay-container {
215
- -ms-filter: progid:dximagetransform.microsoft.gradient.alpha(Opacity=50);
229
+ filter: progid:dximagetransform.microsoft.gradient.alpha(Opacity=50);
216
230
  filter: alpha(opacity=50);
217
231
  height: 0;
218
232
  left: 0;
@@ -231,6 +245,7 @@ $mat-icon-font: 'Material Icons', sans-serif;
231
245
  opacity: 0.5;
232
246
  transition: all 0.3s ease-out, height 0s 0s, opacity 0.3s 0s;
233
247
  }
248
+
234
249
  .shepherd-modal-overlay-container.shepherd-modal-is-visible path {
235
250
  pointer-events: all;
236
251
  }
@@ -1,4 +1,5 @@
1
1
  /**
2
2
  * Generated bundle index. Do not edit.
3
3
  */
4
+ /// <amd-module name="@covalent/guided-tour" />
4
5
  export * from './index';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './index';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY292YWxlbnQtZ3VpZGVkLXRvdXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcGxhdGZvcm0vZ3VpZGVkLXRvdXIvY292YWxlbnQtZ3VpZGVkLXRvdXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0=
@@ -0,0 +1,20 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CovalentGuidedTourService } from './guided-tour.service';
4
+ import * as i0 from "@angular/core";
5
+ export class CovalentGuidedTourModule {
6
+ }
7
+ /** @nocollapse */ /** @nocollapse */ CovalentGuidedTourModule.ɵfac = function CovalentGuidedTourModule_Factory(t) { return new (t || CovalentGuidedTourModule)(); };
8
+ /** @nocollapse */ /** @nocollapse */ CovalentGuidedTourModule.ɵmod = /** @pureOrBreakMyCode */ i0.ɵɵdefineNgModule({ type: CovalentGuidedTourModule });
9
+ /** @nocollapse */ /** @nocollapse */ CovalentGuidedTourModule.ɵinj = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjector({ providers: [CovalentGuidedTourService], imports: [[CommonModule]] });
10
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CovalentGuidedTourModule, [{
11
+ type: NgModule,
12
+ args: [{
13
+ imports: [CommonModule],
14
+ providers: [CovalentGuidedTourService],
15
+ declarations: [],
16
+ exports: [],
17
+ }]
18
+ }], null, null); })();
19
+ (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(CovalentGuidedTourModule, { imports: [CommonModule] }); })();
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VpZGVkLXRvdXIubW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3BsYXRmb3JtL2d1aWRlZC10b3VyL2d1aWRlZC10b3VyLm1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7QUFRbEUsTUFBTSxPQUFPLHdCQUF3Qjs7c0lBQXhCLHdCQUF3Qjs0SEFBeEIsd0JBQXdCO2lJQUp4QixDQUFDLHlCQUF5QixDQUFDLFlBRDdCLENBQUMsWUFBWSxDQUFDO3VGQUtaLHdCQUF3QjtjQU5wQyxRQUFRO2VBQUM7Z0JBQ1IsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDO2dCQUN2QixTQUFTLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQztnQkFDdEMsWUFBWSxFQUFFLEVBQUU7Z0JBQ2hCLE9BQU8sRUFBRSxFQUFFO2FBQ1o7O3dGQUNZLHdCQUF3QixjQUx6QixZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb3ZhbGVudEd1aWRlZFRvdXJTZXJ2aWNlIH0gZnJvbSAnLi9ndWlkZWQtdG91ci5zZXJ2aWNlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHByb3ZpZGVyczogW0NvdmFsZW50R3VpZGVkVG91clNlcnZpY2VdLFxuICBkZWNsYXJhdGlvbnM6IFtdLFxuICBleHBvcnRzOiBbXSxcbn0pXG5leHBvcnQgY2xhc3MgQ292YWxlbnRHdWlkZWRUb3VyTW9kdWxlIHt9XG4iXX0=
@@ -0,0 +1,155 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Router, ActivatedRoute, NavigationStart, } from '@angular/router';
4
+ import { tap, map, filter } from 'rxjs/operators';
5
+ import { fromEvent } from 'rxjs';
6
+ import { debounceTime } from 'rxjs/operators';
7
+ import { CovalentGuidedTour } from './guided.tour';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/router";
10
+ import * as i2 from "@angular/common/http";
11
+ /**
12
+ * Router enabled Shepherd tour
13
+ */
14
+ export var TourEvents;
15
+ (function (TourEvents) {
16
+ TourEvents["complete"] = "complete";
17
+ TourEvents["cancel"] = "cancel";
18
+ TourEvents["hide"] = "hide";
19
+ TourEvents["show"] = "show";
20
+ TourEvents["start"] = "start";
21
+ TourEvents["active"] = "active";
22
+ TourEvents["inactive"] = "inactive";
23
+ })(TourEvents || (TourEvents = {}));
24
+ export class CovalentGuidedTourService extends CovalentGuidedTour {
25
+ constructor(_router, _route, _httpClient) {
26
+ super();
27
+ this._router = _router;
28
+ this._route = _route;
29
+ this._httpClient = _httpClient;
30
+ this._toursMap = new Map();
31
+ this._tourStepURLs = new Map();
32
+ _router.events
33
+ .pipe(filter((event) => event instanceof NavigationStart && event.navigationTrigger === 'popstate'))
34
+ .subscribe((event) => {
35
+ if (this.shepherdTour.isActive) {
36
+ this.shepherdTour.cancel();
37
+ }
38
+ });
39
+ }
40
+ tourEvent$(str) {
41
+ return fromEvent(this.shepherdTour, str);
42
+ }
43
+ async registerTour(tourName, tour) {
44
+ const guidedTour = typeof tour === 'string' ? await this._loadTour(tour) : tour;
45
+ this._toursMap.set(tourName, guidedTour);
46
+ }
47
+ startTour(tourName) {
48
+ const guidedTour = this._getTour(tourName);
49
+ this.finish();
50
+ if (guidedTour && guidedTour.steps && guidedTour.steps.length) {
51
+ // remove steps from tour since we need to preprocess them first
52
+ this.newTour(Object.assign({}, guidedTour, { steps: undefined }));
53
+ const tourInstance = this.shepherdTour.addSteps(this._configureRoutesForSteps(this._prepareTour(guidedTour.steps, guidedTour.finishButtonText)));
54
+ // init route transition if step URL is different then the current location.
55
+ this.tourEvent$(TourEvents.show).subscribe((tourEvent) => {
56
+ const currentURL = this._router.url.split(/[?#]/)[0];
57
+ const { step: { id, options }, } = tourEvent;
58
+ if (this._tourStepURLs.has(id)) {
59
+ const stepRoute = this._tourStepURLs.get(id);
60
+ if (stepRoute !== currentURL) {
61
+ this._router.navigate([stepRoute]);
62
+ }
63
+ }
64
+ else {
65
+ if (options && options.routing) {
66
+ this._tourStepURLs.set(id, options.routing.route);
67
+ }
68
+ else {
69
+ this._tourStepURLs.set(id, currentURL);
70
+ }
71
+ }
72
+ });
73
+ this.start();
74
+ return tourInstance;
75
+ }
76
+ else {
77
+ // tslint:disable-next-line:no-console
78
+ console.warn(`Tour ${tourName} does not exist. Please try another tour.`);
79
+ }
80
+ }
81
+ // Finds the right registered tour by using queryParams
82
+ // finishes any other tour and starts the new one.
83
+ initializeOnQueryParams(queryParam = 'tour') {
84
+ return this._route.queryParamMap.pipe(debounceTime(100), tap((params) => {
85
+ const tourParam = params.get(queryParam);
86
+ if (tourParam) {
87
+ this.startTour(tourParam);
88
+ // get current search parameters
89
+ const searchParams = new URLSearchParams(window.location.search);
90
+ // delete tour queryParam
91
+ searchParams.delete(queryParam);
92
+ // build new URL string without it
93
+ let url = window.location.protocol + '//' + window.location.host + window.location.pathname;
94
+ if (searchParams.toString()) {
95
+ url += '?' + searchParams.toString();
96
+ }
97
+ // replace state in history without triggering a navigation
98
+ window.history.replaceState({ path: url }, '', url);
99
+ }
100
+ }));
101
+ }
102
+ setNextBtnDisability(stepId, isDisabled) {
103
+ if (this.shepherdTour.getById(stepId)) {
104
+ const stepOptions = this.shepherdTour.getById(stepId).options;
105
+ stepOptions.buttons.forEach((button) => {
106
+ if (button.text === 'chevron_right') {
107
+ button.disabled = isDisabled;
108
+ }
109
+ });
110
+ this.shepherdTour.getById(stepId).updateStepOptions(stepOptions);
111
+ }
112
+ }
113
+ async _loadTour(tourUrl) {
114
+ const request = this._httpClient.get(tourUrl);
115
+ try {
116
+ return await request
117
+ .pipe(map((resultSet) => {
118
+ return JSON.parse(JSON.stringify(resultSet));
119
+ }))
120
+ .toPromise();
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ }
126
+ _getTour(key) {
127
+ return this._toursMap.get(key);
128
+ }
129
+ _configureRoutesForSteps(routedSteps) {
130
+ routedSteps.forEach((step) => {
131
+ if (step.routing) {
132
+ const route = step.routing.route;
133
+ // if there is a beforeShowPromise, then we save it and call it after the navigation
134
+ if (step.beforeShowPromise) {
135
+ const beforeShowPromise = step.beforeShowPromise;
136
+ step.beforeShowPromise = () => {
137
+ return this._router.navigate([route], step.routing.extras).then(() => {
138
+ return beforeShowPromise();
139
+ });
140
+ };
141
+ }
142
+ else {
143
+ step.beforeShowPromise = () => this._router.navigate([route]);
144
+ }
145
+ }
146
+ });
147
+ return routedSteps;
148
+ }
149
+ }
150
+ /** @nocollapse */ /** @nocollapse */ CovalentGuidedTourService.ɵfac = function CovalentGuidedTourService_Factory(t) { return new (t || CovalentGuidedTourService)(i0.ɵɵinject(i1.Router), i0.ɵɵinject(i1.ActivatedRoute), i0.ɵɵinject(i2.HttpClient)); };
151
+ /** @nocollapse */ /** @nocollapse */ CovalentGuidedTourService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: CovalentGuidedTourService, factory: CovalentGuidedTourService.ɵfac });
152
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CovalentGuidedTourService, [{
153
+ type: Injectable
154
+ }], function () { return [{ type: i1.Router }, { type: i1.ActivatedRoute }, { type: i2.HttpClient }]; }, null); })();
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VpZGVkLXRvdXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9wbGF0Zm9ybS9ndWlkZWQtdG91ci9ndWlkZWQtdG91ci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFDTCxNQUFNLEVBQ04sY0FBYyxFQUdkLGVBQWUsR0FFaEIsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRCxPQUFPLEVBQWMsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQTJDLE1BQU0sZUFBZSxDQUFDOzs7O0FBYzVGOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksVUFRWDtBQVJELFdBQVksVUFBVTtJQUNwQixtQ0FBcUIsQ0FBQTtJQUNyQiwrQkFBaUIsQ0FBQTtJQUNqQiwyQkFBYSxDQUFBO0lBQ2IsMkJBQWEsQ0FBQTtJQUNiLDZCQUFlLENBQUE7SUFDZiwrQkFBaUIsQ0FBQTtJQUNqQixtQ0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBUlcsVUFBVSxLQUFWLFVBQVUsUUFRckI7QUFTRCxNQUFNLE9BQU8seUJBQTBCLFNBQVEsa0JBQWtCO0lBRy9ELFlBQW9CLE9BQWUsRUFBVSxNQUFzQixFQUFVLFdBQXVCO1FBQ2xHLEtBQUssRUFBRSxDQUFDO1FBRFUsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUFVLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQVUsZ0JBQVcsR0FBWCxXQUFXLENBQVk7UUFGNUYsY0FBUyxHQUE2QixJQUFJ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QyxHQUFHLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRU8sd0JBQXdCLENBQUMsV0FBOEI7UUFDN0QsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQXFCLEVBQUUsRUFBRTtZQUM1QyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ2hCLE1BQU0sS0FBSyxHQUFXLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO2dCQUN6QyxvRkFBb0Y7Z0JBQ3BGLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO29CQUMxQixNQUFNLGlCQUFpQixHQUF3QixJQUFJLENBQUMsaUJBQWlCLENBQUM7b0JBQ3RFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxHQUFHLEVBQUU7d0JBQzVCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7NEJBQ25FLE9BQU8saUJBQWlCLEVBQUUsQ0FBQzt3QkFDN0IsQ0FBQyxDQUFDLENBQUM7b0JBQ0wsQ0FBQyxDQUFDO2lCQUNIO3FCQUFNO29CQUNMLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQy9EO2FBQ0Y7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7O3dJQXhJVSx5QkFBeUI7aUlBQXpCLHlCQUF5QixXQUF6Qix5QkFBeUI7dUZBQXpCLHlCQUF5QjtjQURyQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7XG4gIFJvdXRlcixcbiAgQWN0aXZhdGVkUm91dGUsXG4gIFBhcmFtTWFwLFxuICBOYXZpZ2F0aW9uRXh0cmFzLFxuICBOYXZpZ2F0aW9uU3RhcnQsXG4gIEV2ZW50IGFzIE5hdmlnYXRpb25FdmVudCxcbn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCBTaGVwaGVyZCBmcm9tICdzaGVwaGVyZC5qcyc7XG5pbXBvcnQgeyB0YXAsIG1hcCwgZmlsdGVyIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZnJvbUV2ZW50IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBDb3ZhbGVudEd1aWRlZFRvdXIsIElUb3VyU3RlcCwgSVRvdXJPcHRpb25zLCBUb3VyU3RlcEJ1dHRvbiB9IGZyb20gJy4vZ3VpZGVkLnRvdXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIElHdWlkZWRUb3VyIGV4dGVuZHMgSVRvdXJPcHRpb25zIHtcbiAgc3RlcHM6IElHdWlkZWRUb3VyU3RlcFtdO1xuICBmaW5pc2hCdXR0b25UZXh0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElHdWlkZWRUb3VyU3RlcCBleHRlbmRzIElUb3VyU3RlcCB7XG4gIHJvdXRpbmc/OiB7XG4gICAgcm91dGU6IHN0cmluZztcbiAgICBleHRyYXM/OiBOYXZpZ2F0aW9uRXh0cmFzO1xuICB9O1xufVxuXG4vKipcbiAqICBSb3V0ZXIgZW5hYmxlZCBTaGVwaGVyZCB0b3VyXG4gKi9cbmV4cG9ydCBlbnVtIFRvdXJFdmVudHMge1xuICBjb21wbGV0ZSA9ICdjb21wbGV0ZScsXG4gIGNhbmNlbCA9ICdjYW5jZWwnLFxuICBoaWRlID0gJ2hpZGUnLFxuICBzaG93ID0gJ3Nob3cnLFxuICBzdGFydCA9ICdzdGFydCcsXG4gIGFjdGl2ZSA9ICdhY3RpdmUnLFxuICBpbmFjdGl2ZSA9ICdpbmFjdGl2ZScsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUd1aWRlZFRvdXJFdmVudCB7XG4gIHN0ZXA6IGFueTtcbiAgcHJldmlvdXM6IGFueTtcbiAgdG91cjogYW55O1xufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQ292YWxlbnRHdWlkZWRUb3VyU2VydmljZSBleHRlbmRzIENvdmFsZW50R3VpZGVkVG91ciB7XG4gIHByaXZhdGUgX3RvdXJzTWFwOiBNYXA8c3RyaW5nLCBJR3VpZGVkVG91cj4gPSBuZXcgTWFwPHN0cmluZywgSUd1aWRlZFRvdXI+KCk7XG4gIHByaXZhdGUgX3RvdXJTdGVwVVJMczogTWFwPHN0cmluZywgc3RyaW5nPiA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX3JvdXRlcjogUm91dGVyLCBwcml2YXRlIF9yb3V0ZTogQWN0aXZhdGVkUm91dGUsIHByaXZhdGUgX2h0dHBDbGllbnQ6IEh0dHBDbGllbnQpIHtcbiAgICBzdXBlcigpO1xuICAgIF9yb3V0ZXIuZXZlbnRzXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKChldmVudDogTmF2aWdhdGlvbkV2ZW50KSA9PiBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25TdGFydCAmJiBldmVudC5uYXZpZ2F0aW9uVHJpZ2dlciA9PT0gJ3BvcHN0YXRlJyksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChldmVudDogTmF2aWdhdGlvbkV2ZW50KSA9PiB7XG4gICAgICAgIGlmICh0aGlzLnNoZXBoZXJkVG91ci5pc0FjdGl2ZSkge1xuICAgICAgICAgIHRoaXMuc2hlcGhlcmRUb3VyLmNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHRvdXJFdmVudCQoc3RyOiBUb3VyRXZlbnRzKTogT2JzZXJ2YWJsZTxJR3VpZGVkVG91ckV2ZW50PiB7XG4gICAgcmV0dXJuIGZyb21FdmVudCh0aGlzLnNoZXBoZXJkVG91ciwgc3RyKTtcbiAgfVxuXG4gIGFzeW5jIHJlZ2lzdGVyVG91cih0b3VyTmFtZTogc3RyaW5nLCB0b3VyOiBJR3VpZGVkVG91ciB8IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGd1aWRlZFRvdXI6IElHdWlkZWRUb3VyID0gdHlwZW9mIHRvdXIgPT09ICdzdHJpbmcnID8gYXdhaXQgdGhpcy5fbG9hZFRvdXIodG91cikgOiB0b3VyO1xuICAgIHRoaXMuX3RvdXJzTWFwLnNldCh0b3VyTmFtZSwgZ3VpZGVkVG91cik7XG4gIH1cblxuICBzdGFydFRvdXIodG91ck5hbWU6IHN0cmluZyk6IFNoZXBoZXJkLlRvdXIge1xuICAgIGNvbnN0IGd1aWRlZFRvdXI6IElHdWlkZWRUb3VyID0gdGhpcy5fZ2V0VG91cih0b3VyTmFtZSk7XG4gICAgdGhpcy5maW5pc2goKTtcbiAgICBpZiAoZ3VpZGVkVG91ciAmJiBndWlkZWRUb3VyLnN0ZXBzICYmIGd1aWRlZFRvdXIuc3RlcHMubGVuZ3RoKSB7XG4gICAgICAvLyByZW1vdmUgc3RlcHMgZnJvbSB0b3VyIHNpbmNlIHdlIG5lZWQgdG8gcHJlcHJvY2VzcyB0aGVtIGZpcnN0XG4gICAgICB0aGlzLm5ld1RvdXIoT2JqZWN0LmFzc2lnbih7fSwgZ3VpZGVkVG91ciwgeyBzdGVwczogdW5kZWZpbmVkIH0pKTtcbiAgICAgIGNvbnN0IHRvdXJJbnN0YW5jZTogU2hlcGhlcmQuVG91ciA9IHRoaXMuc2hlcGhlcmRUb3VyLmFkZFN0ZXBzKFxuICAgICAgICB0aGlzLl9jb25maWd1cmVSb3V0ZXNGb3JTdGVwcyh0aGlzLl9wcmVwYXJlVG91cihndWlkZWRUb3VyLnN0ZXBzLCBndWlkZWRUb3VyLmZpbmlzaEJ1dHRvblRleHQpKSxcbiAgICAgICk7XG4gICAgICAvLyBpbml0IHJvdXRlIHRyYW5zaXRpb24gaWYgc3RlcCBVUkwgaXMgZGlmZmVyZW50IHRoZW4gdGhlIGN1cnJlbnQgbG9jYXRpb24uXG4gICAgICB0aGlzLnRvdXJFdmVudCQoVG91ckV2ZW50cy5zaG93KS5zdWJzY3JpYmUoKHRvdXJFdmVudDogSUd1aWRlZFRvdXJFdmVudCkgPT4ge1xuICAgICAgICBjb25zdCBjdXJyZW50VVJMOiBzdHJpbmcgPSB0aGlzLl9yb3V0ZXIudXJsLnNwbGl0KC9bPyNdLylbMF07XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBzdGVwOiB7IGlkLCBvcHRpb25zIH0sXG4gICAgICAgIH0gPSB0b3VyRXZlbnQ7XG4gICAgICAgIGlmICh0aGlzLl90b3VyU3RlcFVSTHMuaGFzKGlkKSkge1xuICAgICAgICAgIGNvbnN0IHN0ZXBSb3V0ZTogc3RyaW5nID0gdGhpcy5fdG91clN0ZXBVUkxzLmdldChpZCk7XG4gICAgICAgICAgaWYgKHN0ZXBSb3V0ZSAhPT0gY3VycmVudFVSTCkge1xuICAgICAgICAgICAgdGhpcy5fcm91dGVyLm5hdmlnYXRlKFtzdGVwUm91dGVdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5yb3V0aW5nKSB7XG4gICAgICAgICAgICB0aGlzLl90b3VyU3RlcFVSTHMuc2V0KGlkLCBvcHRpb25zLnJvdXRpbmcucm91dGUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl90b3VyU3RlcFVSTHMuc2V0KGlkLCBjdXJyZW50VVJMKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5zdGFydCgpO1xuICAgICAgcmV0dXJuIHRvdXJJbnN0YW5jZTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUud2FybihgVG91ciAke3RvdXJOYW1lfSBkb2VzIG5vdCBleGlzdC4gUGxlYXNlIHRyeSBhbm90aGVyIHRvdXIuYCk7XG4gICAgfVxuICB9XG5cbiAgLy8gRmluZHMgdGhlIHJpZ2h0IHJlZ2lzdGVyZWQgdG91ciBieSB1c2luZyBxdWVyeVBhcmFtc1xuICAvLyBmaW5pc2hlcyBhbnkgb3RoZXIgdG91ciBhbmQgc3RhcnRzIHRoZSBuZXcgb25lLlxuICBpbml0aWFsaXplT25RdWVyeVBhcmFtcyhxdWVyeVBhcmFtOiBzdHJpbmcgPSAndG91cicpOiBPYnNlcnZhYmxlPFBhcmFtTWFwPiB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlLnF1ZXJ5UGFyYW1NYXAucGlwZShcbiAgICAgIGRlYm91bmNlVGltZSgxMDApLFxuICAgICAgdGFwKChwYXJhbXM6IFBhcmFtTWFwKSA9PiB7XG4gICAgICAgIGNvbnN0IHRvdXJQYXJhbTogc3RyaW5nID0gcGFyYW1zLmdldChxdWVyeVBhcmFtKTtcbiAgICAgICAgaWYgKHRvdXJQYXJhbSkge1xuICAgICAgICAgIHRoaXMuc3RhcnRUb3VyKHRvdXJQYXJhbSk7XG4gICAgICAgICAgLy8gZ2V0IGN1cnJlbnQgc2VhcmNoIHBhcmFtZXRlcnNcbiAgICAgICAgICBjb25zdCBzZWFyY2hQYXJhbXM6IFVSTFNlYXJjaFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgICAgICAgLy8gZGVsZXRlIHRvdXIgcXVlcnlQYXJhbVxuICAgICAgICAgIHNlYXJjaFBhcmFtcy5kZWxldGUocXVlcnlQYXJhbSk7XG4gICAgICAgICAgLy8gYnVpbGQgbmV3IFVSTCBzdHJpbmcgd2l0aG91dCBpdFxuICAgICAgICAgIGxldCB1cmw6IHN0cmluZyA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyB3aW5kb3cubG9jYXRpb24uaG9zdCArIHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZTtcbiAgICAgICAgICBpZiAoc2VhcmNoUGFyYW1zLnRvU3RyaW5nKCkpIHtcbiAgICAgICAgICAgIHVybCArPSAnPycgKyBzZWFyY2hQYXJhbXMudG9TdHJpbmcoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gcmVwbGFjZSBzdGF0ZSBpbiBoaXN0b3J5IHdpdGhvdXQgdHJpZ2dlcmluZyBhIG5hdmlnYXRpb25cbiAgICAgICAgICB3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoeyBwYXRoOiB1cmwgfSwgJycsIHVybCk7XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBzZXROZXh0QnRuRGlzYWJpbGl0eShzdGVwSWQ6IHN0cmluZywgaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICh0aGlzLnNoZXBoZXJkVG91ci5nZXRCeUlkKHN0ZXBJZCkpIHtcbiAgICAgIGNvbnN0IHN0ZXBPcHRpb25zOiBJVG91clN0ZXAgPSAodGhpcy5zaGVwaGVyZFRvdXIuZ2V0QnlJZChzdGVwSWQpIGFzIGFueSkub3B0aW9ucztcbiAgICAgIHN0ZXBPcHRpb25zLmJ1dHRvbnMuZm9yRWFjaCgoYnV0dG9uOiBUb3VyU3RlcEJ1dHRvbikgPT4ge1xuICAgICAgICBpZiAoYnV0dG9uLnRleHQgPT09ICdjaGV2cm9uX3JpZ2h0Jykge1xuICAgICAgICAgIGJ1dHRvbi5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5zaGVwaGVyZFRvdXIuZ2V0QnlJZChzdGVwSWQpLnVwZGF0ZVN0ZXBPcHRpb25zKHN0ZXBPcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9sb2FkVG91cih0b3VyVXJsOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHJlcXVlc3Q6IE9ic2VydmFibGU8b2JqZWN0PiA9IHRoaXMuX2h0dHBDbGllbnQuZ2V0KHRvdXJVcmwpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVxdWVzdFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBtYXAoKHJlc3VsdFNldDogYW55KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShyZXN1bHRTZXQpKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgICAudG9Qcm9taXNlKCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldFRvdXIoa2V5OiBzdHJpbmcpOiBJR3VpZGVkVG91ciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdXJzTWFwLmdldChrZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uZmlndXJlUm91dGVzRm9yU3RlcHMocm91dGVkU3RlcHM6IElHdWlkZWRUb3VyU3RlcFtdKTogSUd1aWRlZFRvdXJTdGVwW10ge1xuICAgIHJvdXRlZFN0ZXBzLmZvckVhY2goKHN0ZXA6IElHdWlkZWRUb3VyU3RlcCkgPT4ge1xuICAgICAgaWYgKHN0ZXAucm91dGluZykge1xuICAgICAgICBjb25zdCByb3V0ZTogc3RyaW5nID0gc3RlcC5yb3V0aW5nLnJvdXRlO1xuICAgICAgICAvLyBpZiB0aGVyZSBpcyBhIGJlZm9yZVNob3dQcm9taXNlLCB0aGVuIHdlIHNhdmUgaXQgYW5kIGNhbGwgaXQgYWZ0ZXIgdGhlIG5hdmlnYXRpb25cbiAgICAgICAgaWYgKHN0ZXAuYmVmb3JlU2hvd1Byb21pc2UpIHtcbiAgICAgICAgICBjb25zdCBiZWZvcmVTaG93UHJvbWlzZTogKCkgPT4gUHJvbWlzZTx2b2lkPiA9IHN0ZXAuYmVmb3JlU2hvd1Byb21pc2U7XG4gICAgICAgICAgc3RlcC5iZWZvcmVTaG93UHJvbWlzZSA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yb3V0ZXIubmF2aWdhdGUoW3JvdXRlXSwgc3RlcC5yb3V0aW5nLmV4dHJhcykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBiZWZvcmVTaG93UHJvbWlzZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdGVwLmJlZm9yZVNob3dQcm9taXNlID0gKCkgPT4gdGhpcy5fcm91dGVyLm5hdmlnYXRlKFtyb3V0ZV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcm91dGVkU3RlcHM7XG4gIH1cbn1cbiJdfQ==