ng-hub-ui-modal 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.
- package/LICENSE +21 -0
- package/README.md +343 -0
- package/esm2022/lib/modal-backdrop.mjs +51 -0
- package/esm2022/lib/modal-config.mjs +31 -0
- package/esm2022/lib/modal-dismiss-reasons.mjs +6 -0
- package/esm2022/lib/modal-ref.mjs +216 -0
- package/esm2022/lib/modal-stack.mjs +294 -0
- package/esm2022/lib/modal-window.mjs +275 -0
- package/esm2022/lib/modal.mjs +59 -0
- package/esm2022/ng-hub-ui-modal.mjs +5 -0
- package/esm2022/public-api.mjs +5 -0
- package/fesm2022/ng-hub-ui-modal.mjs +920 -0
- package/fesm2022/ng-hub-ui-modal.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/modal-backdrop.d.ts +13 -0
- package/lib/modal-config.d.ts +158 -0
- package/lib/modal-dismiss-reasons.d.ts +4 -0
- package/lib/modal-ref.d.ts +115 -0
- package/lib/modal-stack.d.ts +49 -0
- package/lib/modal-window.d.ts +39 -0
- package/lib/modal.d.ts +42 -0
- package/ng-hub-ui-modal-1.0.0.tgz +0 -0
- package/package.json +50 -0
- package/public-api.d.ts +1 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { of, Subject, zip } from 'rxjs';
|
|
2
|
+
import { takeUntil } from 'rxjs/operators';
|
|
3
|
+
import { isDefined, isPromise } from 'ng-hub-ui-utils';
|
|
4
|
+
/**
|
|
5
|
+
* A reference to the currently opened (active) modal.
|
|
6
|
+
*
|
|
7
|
+
* Instances of this class can be injected into your component passed as modal content.
|
|
8
|
+
* So you can `.update()`, `.close()` or `.dismiss()` the modal window from your component.
|
|
9
|
+
*/
|
|
10
|
+
export class HubActiveModal {
|
|
11
|
+
/**
|
|
12
|
+
* Updates options of an opened modal.
|
|
13
|
+
*
|
|
14
|
+
* @since 14.2.0
|
|
15
|
+
*/
|
|
16
|
+
update(options) { }
|
|
17
|
+
/**
|
|
18
|
+
* Closes the modal with an optional `result` value.
|
|
19
|
+
*
|
|
20
|
+
* The `HubModalRef.result` promise will be resolved with the provided value.
|
|
21
|
+
*/
|
|
22
|
+
close(result) { }
|
|
23
|
+
/**
|
|
24
|
+
* Dismisses the modal with an optional `reason` value.
|
|
25
|
+
*
|
|
26
|
+
* The `HubModalRef.result` promise will be rejected with the provided value.
|
|
27
|
+
*/
|
|
28
|
+
dismiss(reason) { }
|
|
29
|
+
}
|
|
30
|
+
const WINDOW_ATTRIBUTES = [
|
|
31
|
+
'animation',
|
|
32
|
+
'ariaLabelledBy',
|
|
33
|
+
'ariaDescribedBy',
|
|
34
|
+
'backdrop',
|
|
35
|
+
'centered',
|
|
36
|
+
'fullscreen',
|
|
37
|
+
'keyboard',
|
|
38
|
+
'scrollable',
|
|
39
|
+
'size',
|
|
40
|
+
'windowClass',
|
|
41
|
+
'modalDialogClass'
|
|
42
|
+
];
|
|
43
|
+
const BACKDROP_ATTRIBUTES = ['animation', 'backdropClass'];
|
|
44
|
+
/**
|
|
45
|
+
* A reference to the newly opened modal returned by the `HubModal.open()` method.
|
|
46
|
+
*/
|
|
47
|
+
export class HubModalRef {
|
|
48
|
+
_applyWindowOptions(windowInstance, options) {
|
|
49
|
+
WINDOW_ATTRIBUTES.forEach((optionName) => {
|
|
50
|
+
if (isDefined(options[optionName])) {
|
|
51
|
+
windowInstance[optionName] = options[optionName];
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
_applyBackdropOptions(backdropInstance, options) {
|
|
56
|
+
BACKDROP_ATTRIBUTES.forEach((optionName) => {
|
|
57
|
+
if (isDefined(options[optionName])) {
|
|
58
|
+
backdropInstance[optionName] = options[optionName];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Updates options of an opened modal.
|
|
64
|
+
*
|
|
65
|
+
* @since 14.2.0
|
|
66
|
+
*/
|
|
67
|
+
update(options) {
|
|
68
|
+
this._applyWindowOptions(this._windowCmptRef.instance, options);
|
|
69
|
+
if (this._backdropCmptRef && this._backdropCmptRef.instance) {
|
|
70
|
+
this._applyBackdropOptions(this._backdropCmptRef.instance, options);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The instance of a component used for the modal content.
|
|
75
|
+
*
|
|
76
|
+
* When a `TemplateRef` is used as the content or when the modal is closed, will return `undefined`.
|
|
77
|
+
*/
|
|
78
|
+
get componentInstance() {
|
|
79
|
+
if (this._contentRef && this._contentRef.componentRef) {
|
|
80
|
+
return this._contentRef.componentRef.instance;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The observable that emits when the modal is closed via the `.close()` method.
|
|
85
|
+
*
|
|
86
|
+
* It will emit the result passed to the `.close()` method.
|
|
87
|
+
*
|
|
88
|
+
* @since 8.0.0
|
|
89
|
+
*/
|
|
90
|
+
get closed() {
|
|
91
|
+
return this._closed.asObservable().pipe(takeUntil(this._hidden));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The observable that emits when the modal is dismissed via the `.dismiss()` method.
|
|
95
|
+
*
|
|
96
|
+
* It will emit the reason passed to the `.dismissed()` method by the user, or one of the internal
|
|
97
|
+
* reasons like backdrop click or ESC key press.
|
|
98
|
+
*
|
|
99
|
+
* @since 8.0.0
|
|
100
|
+
*/
|
|
101
|
+
get dismissed() {
|
|
102
|
+
return this._dismissed.asObservable().pipe(takeUntil(this._hidden));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The observable that emits when both modal window and backdrop are closed and animations were finished.
|
|
106
|
+
* At this point modal and backdrop elements will be removed from the DOM tree.
|
|
107
|
+
*
|
|
108
|
+
* This observable will be completed after emitting.
|
|
109
|
+
*
|
|
110
|
+
* @since 8.0.0
|
|
111
|
+
*/
|
|
112
|
+
get hidden() {
|
|
113
|
+
return this._hidden.asObservable();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The observable that emits when modal is fully visible and animation was finished.
|
|
117
|
+
* Modal DOM element is always available synchronously after calling 'modal.open()' service.
|
|
118
|
+
*
|
|
119
|
+
* This observable will be completed after emitting.
|
|
120
|
+
* It will not emit, if modal is closed before open animation is finished.
|
|
121
|
+
*
|
|
122
|
+
* @since 8.0.0
|
|
123
|
+
*/
|
|
124
|
+
get shown() {
|
|
125
|
+
return this._windowCmptRef.instance.shown.asObservable();
|
|
126
|
+
}
|
|
127
|
+
constructor(_windowCmptRef, _contentRef, _backdropCmptRef, _beforeDismiss) {
|
|
128
|
+
this._windowCmptRef = _windowCmptRef;
|
|
129
|
+
this._contentRef = _contentRef;
|
|
130
|
+
this._backdropCmptRef = _backdropCmptRef;
|
|
131
|
+
this._beforeDismiss = _beforeDismiss;
|
|
132
|
+
this._closed = new Subject();
|
|
133
|
+
this._dismissed = new Subject();
|
|
134
|
+
this._hidden = new Subject();
|
|
135
|
+
_windowCmptRef.instance.dismissEvent.subscribe((reason) => {
|
|
136
|
+
this.dismiss(reason);
|
|
137
|
+
});
|
|
138
|
+
this.result = new Promise((resolve, reject) => {
|
|
139
|
+
this._resolve = resolve;
|
|
140
|
+
this._reject = reject;
|
|
141
|
+
});
|
|
142
|
+
this.result.then(null, () => { });
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Closes the modal with an optional `result` value.
|
|
146
|
+
*
|
|
147
|
+
* The `HubMobalRef.result` promise will be resolved with the provided value.
|
|
148
|
+
*/
|
|
149
|
+
close(result) {
|
|
150
|
+
if (this._windowCmptRef) {
|
|
151
|
+
this._closed.next(result);
|
|
152
|
+
this._resolve(result);
|
|
153
|
+
this._removeModalElements();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
_dismiss(reason) {
|
|
157
|
+
this._dismissed.next(reason);
|
|
158
|
+
this._reject(reason);
|
|
159
|
+
this._removeModalElements();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Dismisses the modal with an optional `reason` value.
|
|
163
|
+
*
|
|
164
|
+
* The `HubModalRef.result` promise will be rejected with the provided value.
|
|
165
|
+
*/
|
|
166
|
+
dismiss(reason) {
|
|
167
|
+
if (this._windowCmptRef) {
|
|
168
|
+
if (!this._beforeDismiss) {
|
|
169
|
+
this._dismiss(reason);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const dismiss = this._beforeDismiss();
|
|
173
|
+
if (isPromise(dismiss)) {
|
|
174
|
+
dismiss.then((result) => {
|
|
175
|
+
if (result !== false) {
|
|
176
|
+
this._dismiss(reason);
|
|
177
|
+
}
|
|
178
|
+
}, () => { });
|
|
179
|
+
}
|
|
180
|
+
else if (dismiss !== false) {
|
|
181
|
+
this._dismiss(reason);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
_removeModalElements() {
|
|
187
|
+
const windowTransition$ = this._windowCmptRef.instance.hide();
|
|
188
|
+
const backdropTransition$ = this._backdropCmptRef
|
|
189
|
+
? this._backdropCmptRef.instance.hide()
|
|
190
|
+
: of(undefined);
|
|
191
|
+
// hiding window
|
|
192
|
+
windowTransition$.subscribe(() => {
|
|
193
|
+
const { nativeElement } = this._windowCmptRef.location;
|
|
194
|
+
nativeElement.parentNode.removeChild(nativeElement);
|
|
195
|
+
this._windowCmptRef.destroy();
|
|
196
|
+
this._contentRef?.viewRef?.destroy();
|
|
197
|
+
this._windowCmptRef = null;
|
|
198
|
+
this._contentRef = null;
|
|
199
|
+
});
|
|
200
|
+
// hiding backdrop
|
|
201
|
+
backdropTransition$.subscribe(() => {
|
|
202
|
+
if (this._backdropCmptRef) {
|
|
203
|
+
const { nativeElement } = this._backdropCmptRef.location;
|
|
204
|
+
nativeElement.parentNode.removeChild(nativeElement);
|
|
205
|
+
this._backdropCmptRef.destroy();
|
|
206
|
+
this._backdropCmptRef = null;
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
// all done
|
|
210
|
+
zip(windowTransition$, backdropTransition$).subscribe(() => {
|
|
211
|
+
this._hidden.next();
|
|
212
|
+
this._hidden.complete();
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtcmVmLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbW9kYWwvc3JjL2xpYi9tb2RhbC1yZWYudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3BELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUkzQyxPQUFPLEVBQWMsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRW5FOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGNBQWM7SUFDMUI7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxPQUFpQyxJQUFTLENBQUM7SUFDbEQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxNQUFZLElBQVMsQ0FBQztJQUU1Qjs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLE1BQVksSUFBUyxDQUFDO0NBQzlCO0FBRUQsTUFBTSxpQkFBaUIsR0FBYTtJQUNuQyxXQUFXO0lBQ1gsZ0JBQWdCO0lBQ2hCLGlCQUFpQjtJQUNqQixVQUFVO0lBQ1YsVUFBVTtJQUNWLFlBQVk7SUFDWixVQUFVO0lBQ1YsWUFBWTtJQUNaLE1BQU07SUFDTixhQUFhO0lBQ2Isa0JBQWtCO0NBQ2xCLENBQUM7QUFDRixNQUFNLG1CQUFtQixHQUFhLENBQUMsV0FBVyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBRXJFOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFPZixtQkFBbUIsQ0FDMUIsY0FBOEIsRUFDOUIsT0FBd0I7UUFFeEIsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsVUFBa0IsRUFBRSxFQUFFO1lBQ2hELElBQUksU0FBUyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFO2dCQUNuQyxjQUFjLENBQUMsVUFBVSxDQUFDLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ2pE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bUIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDMUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztDQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiwgU3ViamVjdCwgemlwIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBIdWJNb2RhbEJhY2tkcm9wIH0gZnJvbSAnLi9tb2RhbC1iYWNrZHJvcCc7XG5pbXBvcnQgeyBIdWJNb2RhbFdpbmRvdyB9IGZyb20gJy4vbW9kYWwtd2luZG93JztcbmltcG9ydCB7IEh1Yk1vZGFsT3B0aW9ucywgSHViTW9kYWxVcGRhdGFibGVPcHRpb25zIH0gZnJvbSAnLi9tb2RhbC1jb25maWcnO1xuaW1wb3J0IHsgQ29udGVudFJlZiwgaXNEZWZpbmVkLCBpc1Byb21pc2UgfSBmcm9tICduZy1odWItdWktdXRpbHMnO1xuXG4vKipcbiAqIEEgcmVmZXJlbmNlIHRvIHRoZSBjdXJyZW50bHkgb3BlbmVkIChhY3RpdmUpIG1vZGFsLlxuICpcbiAqIEluc3RhbmNlcyBvZiB0aGlzIGNsYXNzIGNhbiBiZSBpbmplY3RlZCBpbnRvIHlvdXIgY29tcG9uZW50IHBhc3NlZCBhcyBtb2RhbCBjb250ZW50LlxuICogU28geW91IGNhbiBgLnVwZGF0ZSgpYCwgYC5jbG9zZSgpYCBvciBgLmRpc21pc3MoKWAgdGhlIG1vZGFsIHdpbmRvdyBmcm9tIHlvdXIgY29tcG9uZW50LlxuICovXG5leHBvcnQgY2xhc3MgSHViQWN0aXZlTW9kYWwge1xuXHQvKipcblx0ICogVXBkYXRlcyBvcHRpb25zIG9mIGFuIG9wZW5lZCBtb2RhbC5cblx0ICpcblx0ICogQHNpbmNlIDE0LjIuMFxuXHQgKi9cblx0dXBkYXRlKG9wdGlvbnM6IEh1Yk1vZGFsVXBkYXRhYmxlT3B0aW9ucyk6IHZvaWQge31cblx0LyoqXG5cdCAqIENsb3NlcyB0aGUgbW9kYWwgd2l0aCBhbiBvcHRpb25hbCBgcmVzdWx0YCB2YWx1ZS5cblx0ICpcblx0ICogVGhlIGBIdWJNb2RhbFJlZi5yZXN1bHRgIHByb21pc2Ugd2lsbCBiZSByZXNvbHZlZCB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZS5cblx0ICovXG5cdGNsb3NlKHJlc3VsdD86IGFueSk6IHZvaWQge31cblxuXHQvKipcblx0ICogRGlzbWlzc2VzIHRoZSBtb2RhbCB3aXRoIGFuIG9wdGlvbmFsIGByZWFzb25gIHZhbHVlLlxuXHQgKlxuXHQgKiBUaGUgYEh1Yk1vZGFsUmVmLnJlc3VsdGAgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGggdGhlIHByb3ZpZGVkIHZhbHVlLlxuXHQgKi9cblx0ZGlzbWlzcyhyZWFzb24/OiBhbnkpOiB2b2lkIHt9XG59XG5cbmNvbnN0IFdJTkRPV19BVFRSSUJVVEVTOiBzdHJpbmdbXSA9IFtcblx0J2FuaW1hdGlvbicsXG5cdCdhcmlhTGFiZWxsZWRCeScsXG5cdCdhcmlhRGVzY3JpYmVkQnknLFxuXHQnYmFja2Ryb3AnLFxuXHQnY2VudGVyZWQnLFxuXHQnZnVsbHNjcmVlbicsXG5cdCdrZXlib2FyZCcsXG5cdCdzY3JvbGxhYmxlJyxcblx0J3NpemUnLFxuXHQnd2luZG93Q2xhc3MnLFxuXHQnbW9kYWxEaWFsb2dDbGFzcydcbl07XG5jb25zdCBCQUNLRFJPUF9BVFRSSUJVVEVTOiBzdHJpbmdbXSA9IFsnYW5pbWF0aW9uJywgJ2JhY2tkcm9wQ2xhc3MnXTtcblxuLyoqXG4gKiBBIHJlZmVyZW5jZSB0byB0aGUgbmV3bHkgb3BlbmVkIG1vZGFsIHJldHVybmVkIGJ5IHRoZSBgSHViTW9kYWwub3BlbigpYCBtZXRob2QuXG4gKi9cbmV4cG9ydCBjbGFzcyBIdWJNb2RhbFJlZiB7XG5cdHByaXZhdGUgX2Nsb3NlZCA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblx0cHJpdmF0ZSBfZGlzbWlzc2VkID0gbmV3IFN1YmplY3Q8YW55PigpO1xuXHRwcml2YXRlIF9oaWRkZW4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXHRwcml2YXRlIF9yZXNvbHZlITogKHJlc3VsdD86IGFueSkgPT4gdm9pZDtcblx0cHJpdmF0ZSBfcmVqZWN0ITogKHJlYXNvbj86IGFueSkgPT4gdm9pZDtcblxuXHRwcml2YXRlIF9hcHBseVdpbmRvd09wdGlvbnMoXG5cdFx0d2luZG93SW5zdGFuY2U6IEh1Yk1vZGFsV2luZG93LFxuXHRcdG9wdGlvbnM6IEh1Yk1vZGFsT3B0aW9uc1xuXHQpOiB2b2lkIHtcblx0XHRXSU5ET1dfQVRUUklCVVRFUy5mb3JFYWNoKChvcHRpb25OYW1lOiBzdHJpbmcpID0+IHtcblx0XHRcdGlmIChpc0RlZmluZWQob3B0aW9uc1tvcHRpb25OYW1lXSkpIHtcblx0XHRcdFx0d2luZG93SW5zdGFuY2Vbb3B0aW9uTmFtZV0gPSBvcHRpb25zW29wdGlvbk5hbWVdO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfYXBwbHlCYWNrZHJvcE9wdGlvbnMoXG5cdFx0YmFja2Ryb3BJbnN0YW5jZTogSHViTW9kYWxCYWNrZHJvcCxcblx0XHRvcHRpb25zOiBIdWJNb2RhbE9wdGlvbnNcblx0KTogdm9pZCB7XG5cdFx0QkFDS0RST1BfQVRUUklCVVRFUy5mb3JFYWNoKChvcHRpb25OYW1lOiBzdHJpbmcpID0+IHtcblx0XHRcdGlmIChpc0RlZmluZWQob3B0aW9uc1tvcHRpb25OYW1lXSkpIHtcblx0XHRcdFx0YmFja2Ryb3BJbnN0YW5jZVtvcHRpb25OYW1lXSA9IG9wdGlvbnNbb3B0aW9uTmFtZV07XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlcyBvcHRpb25zIG9mIGFuIG9wZW5lZCBtb2RhbC5cblx0ICpcblx0ICogQHNpbmNlIDE0LjIuMFxuXHQgKi9cblx0dXBkYXRlKG9wdGlvbnM6IEh1Yk1vZGFsVXBkYXRhYmxlT3B0aW9ucyk6IHZvaWQge1xuXHRcdHRoaXMuX2FwcGx5V2luZG93T3B0aW9ucyh0aGlzLl93aW5kb3dDbXB0UmVmLmluc3RhbmNlLCBvcHRpb25zKTtcblx0XHRpZiAodGhpcy5fYmFja2Ryb3BDbXB0UmVmICYmIHRoaXMuX2JhY2tkcm9wQ21wdFJlZi5pbnN0YW5jZSkge1xuXHRcdFx0dGhpcy5fYXBwbHlCYWNrZHJvcE9wdGlvbnModGhpcy5fYmFja2Ryb3BDbXB0UmVmLmluc3RhbmNlLCBvcHRpb25zKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGluc3RhbmNlIG9mIGEgY29tcG9uZW50IHVzZWQgZm9yIHRoZSBtb2RhbCBjb250ZW50LlxuXHQgKlxuXHQgKiBXaGVuIGEgYFRlbXBsYXRlUmVmYCBpcyB1c2VkIGFzIHRoZSBjb250ZW50IG9yIHdoZW4gdGhlIG1vZGFsIGlzIGNsb3NlZCwgd2lsbCByZXR1cm4gYHVuZGVmaW5lZGAuXG5cdCAqL1xuXHRnZXQgY29tcG9uZW50SW5zdGFuY2UoKTogYW55IHtcblx0XHRpZiAodGhpcy5fY29udGVudFJlZiAmJiB0aGlzLl9jb250ZW50UmVmLmNvbXBvbmVudFJlZikge1xuXHRcdFx0cmV0dXJuIHRoaXMuX2NvbnRlbnRSZWYuY29tcG9uZW50UmVmLmluc3RhbmNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgcHJvbWlzZSB0aGF0IGlzIHJlc29sdmVkIHdoZW4gdGhlIG1vZGFsIGlzIGNsb3NlZCBhbmQgcmVqZWN0ZWQgd2hlbiB0aGUgbW9kYWwgaXMgZGlzbWlzc2VkLlxuXHQgKi9cblx0cmVzdWx0OiBQcm9taXNlPGFueT47XG5cblx0LyoqXG5cdCAqIFRoZSBvYnNlcnZhYmxlIHRoYXQgZW1pdHMgd2hlbiB0aGUgbW9kYWwgaXMgY2xvc2VkIHZpYSB0aGUgYC5jbG9zZSgpYCBtZXRob2QuXG5cdCAqXG5cdCAqIEl0IHdpbGwgZW1pdCB0aGUgcmVzdWx0IHBhc3NlZCB0byB0aGUgYC5jbG9zZSgpYCBtZXRob2QuXG5cdCAqXG5cdCAqIEBzaW5jZSA4LjAuMFxuXHQgKi9cblx0Z2V0IGNsb3NlZCgpOiBPYnNlcnZhYmxlPGFueT4ge1xuXHRcdHJldHVybiB0aGlzLl9jbG9zZWQuYXNPYnNlcnZhYmxlKCkucGlwZSh0YWtlVW50aWwodGhpcy5faGlkZGVuKSk7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIG9ic2VydmFibGUgdGhhdCBlbWl0cyB3aGVuIHRoZSBtb2RhbCBpcyBkaXNtaXNzZWQgdmlhIHRoZSBgLmRpc21pc3MoKWAgbWV0aG9kLlxuXHQgKlxuXHQgKiBJdCB3aWxsIGVtaXQgdGhlIHJlYXNvbiBwYXNzZWQgdG8gdGhlIGAuZGlzbWlzc2VkKClgIG1ldGhvZCBieSB0aGUgdXNlciwgb3Igb25lIG9mIHRoZSBpbnRlcm5hbFxuXHQgKiByZWFzb25zIGxpa2UgYmFja2Ryb3AgY2xpY2sgb3IgRVNDIGtleSBwcmVzcy5cblx0ICpcblx0ICogQHNpbmNlIDguMC4wXG5cdCAqL1xuXHRnZXQgZGlzbWlzc2VkKCk6IE9ic2VydmFibGU8YW55PiB7XG5cdFx0cmV0dXJuIHRoaXMuX2Rpc21pc3NlZC5hc09ic2VydmFibGUoKS5waXBlKHRha2VVbnRpbCh0aGlzLl9oaWRkZW4pKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBUaGUgb2JzZXJ2YWJsZSB0aGF0IGVtaXRzIHdoZW4gYm90aCBtb2RhbCB3aW5kb3cgYW5kIGJhY2tkcm9wIGFyZSBjbG9zZWQgYW5kIGFuaW1hdGlvbnMgd2VyZSBmaW5pc2hlZC5cblx0ICogQXQgdGhpcyBwb2ludCBtb2RhbCBhbmQgYmFja2Ryb3AgZWxlbWVudHMgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIERPTSB0cmVlLlxuXHQgKlxuXHQgKiBUaGlzIG9ic2VydmFibGUgd2lsbCBiZSBjb21wbGV0ZWQgYWZ0ZXIgZW1pdHRpbmcuXG5cdCAqXG5cdCAqIEBzaW5jZSA4LjAuMFxuXHQgKi9cblx0Z2V0IGhpZGRlbigpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcblx0XHRyZXR1cm4gdGhpcy5faGlkZGVuLmFzT2JzZXJ2YWJsZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBvYnNlcnZhYmxlIHRoYXQgZW1pdHMgd2hlbiBtb2RhbCBpcyBmdWxseSB2aXNpYmxlIGFuZCBhbmltYXRpb24gd2FzIGZpbmlzaGVkLlxuXHQgKiBNb2RhbCBET00gZWxlbWVudCBpcyBhbHdheXMgYXZhaWxhYmxlIHN5bmNocm9ub3VzbHkgYWZ0ZXIgY2FsbGluZyAnbW9kYWwub3BlbigpJyBzZXJ2aWNlLlxuXHQgKlxuXHQgKiBUaGlzIG9ic2VydmFibGUgd2lsbCBiZSBjb21wbGV0ZWQgYWZ0ZXIgZW1pdHRpbmcuXG5cdCAqIEl0IHdpbGwgbm90IGVtaXQsIGlmIG1vZGFsIGlzIGNsb3NlZCBiZWZvcmUgb3BlbiBhbmltYXRpb24gaXMgZmluaXNoZWQuXG5cdCAqXG5cdCAqIEBzaW5jZSA4LjAuMFxuXHQgKi9cblx0Z2V0IHNob3duKCk6IE9ic2VydmFibGU8dm9pZD4ge1xuXHRcdHJldHVybiB0aGlzLl93aW5kb3dDbXB0UmVmLmluc3RhbmNlLnNob3duLmFzT2JzZXJ2YWJsZSgpO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSBfd2luZG93Q21wdFJlZjogQ29tcG9uZW50UmVmPEh1Yk1vZGFsV2luZG93Pixcblx0XHRwcml2YXRlIF9jb250ZW50UmVmOiBDb250ZW50UmVmLFxuXHRcdHByaXZhdGUgX2JhY2tkcm9wQ21wdFJlZj86IENvbXBvbmVudFJlZjxIdWJNb2RhbEJhY2tkcm9wPixcblx0XHRwcml2YXRlIF9iZWZvcmVEaXNtaXNzPzogKCkgPT4gYm9vbGVhbiB8IFByb21pc2U8Ym9vbGVhbj5cblx0KSB7XG5cdFx0X3dpbmRvd0NtcHRSZWYuaW5zdGFuY2UuZGlzbWlzc0V2ZW50LnN1YnNjcmliZSgocmVhc29uOiBhbnkpID0+IHtcblx0XHRcdHRoaXMuZGlzbWlzcyhyZWFzb24pO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5yZXN1bHQgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHR0aGlzLl9yZXNvbHZlID0gcmVzb2x2ZTtcblx0XHRcdHRoaXMuX3JlamVjdCA9IHJlamVjdDtcblx0XHR9KTtcblx0XHR0aGlzLnJlc3VsdC50aGVuKG51bGwsICgpID0+IHt9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbG9zZXMgdGhlIG1vZGFsIHdpdGggYW4gb3B0aW9uYWwgYHJlc3VsdGAgdmFsdWUuXG5cdCAqXG5cdCAqIFRoZSBgSHViTW9iYWxSZWYucmVzdWx0YCBwcm9taXNlIHdpbGwgYmUgcmVzb2x2ZWQgd2l0aCB0aGUgcHJvdmlkZWQgdmFsdWUuXG5cdCAqL1xuXHRjbG9zZShyZXN1bHQ/OiBhbnkpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5fd2luZG93Q21wdFJlZikge1xuXHRcdFx0dGhpcy5fY2xvc2VkLm5leHQocmVzdWx0KTtcblx0XHRcdHRoaXMuX3Jlc29sdmUocmVzdWx0KTtcblx0XHRcdHRoaXMuX3JlbW92ZU1vZGFsRWxlbWVudHMoKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF9kaXNtaXNzKHJlYXNvbj86IGFueSkge1xuXHRcdHRoaXMuX2Rpc21pc3NlZC5uZXh0KHJlYXNvbik7XG5cdFx0dGhpcy5fcmVqZWN0KHJlYXNvbik7XG5cdFx0dGhpcy5fcmVtb3ZlTW9kYWxFbGVtZW50cygpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpc21pc3NlcyB0aGUgbW9kYWwgd2l0aCBhbiBvcHRpb25hbCBgcmVhc29uYCB2YWx1ZS5cblx0ICpcblx0ICogVGhlIGBIdWJNb2RhbFJlZi5yZXN1bHRgIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZS5cblx0ICovXG5cdGRpc21pc3MocmVhc29uPzogYW55KTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuX3dpbmRvd0NtcHRSZWYpIHtcblx0XHRcdGlmICghdGhpcy5fYmVmb3JlRGlzbWlzcykge1xuXHRcdFx0XHR0aGlzLl9kaXNtaXNzKHJlYXNvbik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb25zdCBkaXNtaXNzID0gdGhpcy5fYmVmb3JlRGlzbWlzcygpO1xuXHRcdFx0XHRpZiAoaXNQcm9taXNlKGRpc21pc3MpKSB7XG5cdFx0XHRcdFx0ZGlzbWlzcy50aGVuKFxuXHRcdFx0XHRcdFx0KHJlc3VsdCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAocmVzdWx0ICE9PSBmYWxzZSkge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX2Rpc21pc3MocmVhc29uKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRcdCgpID0+IHt9XG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSBlbHNlIGlmIChkaXNtaXNzICE9PSBmYWxzZSkge1xuXHRcdFx0XHRcdHRoaXMuX2Rpc21pc3MocmVhc29uKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgX3JlbW92ZU1vZGFsRWxlbWVudHMoKSB7XG5cdFx0Y29uc3Qgd2luZG93VHJhbnNpdGlvbiQgPSB0aGlzLl93aW5kb3dDbXB0UmVmLmluc3RhbmNlLmhpZGUoKTtcblx0XHRjb25zdCBiYWNrZHJvcFRyYW5zaXRpb24kID0gdGhpcy5fYmFja2Ryb3BDbXB0UmVmXG5cdFx0XHQ/IHRoaXMuX2JhY2tkcm9wQ21wdFJlZi5pbnN0YW5jZS5oaWRlKClcblx0XHRcdDogb2YodW5kZWZpbmVkKTtcblxuXHRcdC8vIGhpZGluZyB3aW5kb3dcblx0XHR3aW5kb3dUcmFuc2l0aW9uJC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0Y29uc3QgeyBuYXRpdmVFbGVtZW50IH0gPSB0aGlzLl93aW5kb3dDbXB0UmVmLmxvY2F0aW9uO1xuXHRcdFx0bmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5hdGl2ZUVsZW1lbnQpO1xuXHRcdFx0dGhpcy5fd2luZG93Q21wdFJlZi5kZXN0cm95KCk7XG5cdFx0XHR0aGlzLl9jb250ZW50UmVmPy52aWV3UmVmPy5kZXN0cm95KCk7XG5cblx0XHRcdHRoaXMuX3dpbmRvd0NtcHRSZWYgPSA8YW55Pm51bGw7XG5cdFx0XHR0aGlzLl9jb250ZW50UmVmID0gPGFueT5udWxsO1xuXHRcdH0pO1xuXG5cdFx0Ly8gaGlkaW5nIGJhY2tkcm9wXG5cdFx0YmFja2Ryb3BUcmFuc2l0aW9uJC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuX2JhY2tkcm9wQ21wdFJlZikge1xuXHRcdFx0XHRjb25zdCB7IG5hdGl2ZUVsZW1lbnQgfSA9IHRoaXMuX2JhY2tkcm9wQ21wdFJlZi5sb2NhdGlvbjtcblx0XHRcdFx0bmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5hdGl2ZUVsZW1lbnQpO1xuXHRcdFx0XHR0aGlzLl9iYWNrZHJvcENtcHRSZWYuZGVzdHJveSgpO1xuXHRcdFx0XHR0aGlzLl9iYWNrZHJvcENtcHRSZWYgPSA8YW55Pm51bGw7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHQvLyBhbGwgZG9uZVxuXHRcdHppcCh3aW5kb3dUcmFuc2l0aW9uJCwgYmFja2Ryb3BUcmFuc2l0aW9uJCkuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdHRoaXMuX2hpZGRlbi5uZXh0KCk7XG5cdFx0XHR0aGlzLl9oaWRkZW4uY29tcGxldGUoKTtcblx0XHR9KTtcblx0fVxufVxuIl19
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { DOCUMENT } from '@angular/common';
|
|
2
|
+
import { ApplicationRef, createComponent, EnvironmentInjector, EventEmitter, inject, Injectable, Injector, NgZone, TemplateRef } from '@angular/core';
|
|
3
|
+
import { ContentRef, hubFocusTrap, isDefined, isString, ScrollBar } from 'ng-hub-ui-utils';
|
|
4
|
+
import { Subject } from 'rxjs';
|
|
5
|
+
import { take } from 'rxjs/operators';
|
|
6
|
+
import { HubModalBackdrop } from './modal-backdrop';
|
|
7
|
+
import { HubActiveModal, HubModalRef } from './modal-ref';
|
|
8
|
+
import { HubModalWindow } from './modal-window';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
export class HubModalStack {
|
|
11
|
+
constructor() {
|
|
12
|
+
this._applicationRef = inject(ApplicationRef);
|
|
13
|
+
this._injector = inject(Injector);
|
|
14
|
+
this._environmentInjector = inject(EnvironmentInjector);
|
|
15
|
+
this._document = inject(DOCUMENT);
|
|
16
|
+
this._scrollBar = inject(ScrollBar);
|
|
17
|
+
this._activeWindowCmptHasChanged = new Subject();
|
|
18
|
+
this._ariaHiddenValues = new Map();
|
|
19
|
+
this._scrollBarRestoreFn = null;
|
|
20
|
+
this._modalRefs = [];
|
|
21
|
+
this._windowCmpts = [];
|
|
22
|
+
this._activeInstances = new EventEmitter();
|
|
23
|
+
const ngZone = inject(NgZone);
|
|
24
|
+
// Trap focus on active WindowCmpt
|
|
25
|
+
this._activeWindowCmptHasChanged.subscribe(() => {
|
|
26
|
+
if (this._windowCmpts.length) {
|
|
27
|
+
const activeWindowCmpt = this._windowCmpts[this._windowCmpts.length - 1];
|
|
28
|
+
hubFocusTrap(ngZone, activeWindowCmpt.location.nativeElement, this._activeWindowCmptHasChanged);
|
|
29
|
+
this._revertAriaHidden();
|
|
30
|
+
this._setAriaHidden(activeWindowCmpt.location.nativeElement);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
_restoreScrollBar() {
|
|
35
|
+
const scrollBarRestoreFn = this._scrollBarRestoreFn;
|
|
36
|
+
if (scrollBarRestoreFn) {
|
|
37
|
+
this._scrollBarRestoreFn = null;
|
|
38
|
+
scrollBarRestoreFn();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
_hideScrollBar() {
|
|
42
|
+
if (!this._scrollBarRestoreFn) {
|
|
43
|
+
this._scrollBarRestoreFn = this._scrollBar.hide();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
open(contentInjector, content, options) {
|
|
47
|
+
const containerEl = options.container instanceof HTMLElement
|
|
48
|
+
? options.container
|
|
49
|
+
: isDefined(options.container)
|
|
50
|
+
? this._document.querySelector(options.container)
|
|
51
|
+
: this._document.body;
|
|
52
|
+
if (!containerEl) {
|
|
53
|
+
throw new Error(`The specified modal container "${options.container || 'body'}" was not found in the DOM.`);
|
|
54
|
+
}
|
|
55
|
+
this._hideScrollBar();
|
|
56
|
+
const activeModal = new HubActiveModal();
|
|
57
|
+
contentInjector = options.injector || contentInjector;
|
|
58
|
+
const environmentInjector = contentInjector.get(EnvironmentInjector, null) ||
|
|
59
|
+
this._environmentInjector;
|
|
60
|
+
const contentRef = this._getContentRef(contentInjector, environmentInjector, content, activeModal, options);
|
|
61
|
+
const backdropCmptRef = options.backdrop !== false
|
|
62
|
+
? this._attachBackdrop(containerEl)
|
|
63
|
+
: undefined;
|
|
64
|
+
const windowCmptRef = this._attachWindowComponent(containerEl, contentRef.nodes, options);
|
|
65
|
+
const hubModalRef = new HubModalRef(windowCmptRef, contentRef, backdropCmptRef, options.beforeDismiss);
|
|
66
|
+
this._registerModalRef(hubModalRef);
|
|
67
|
+
this._registerWindowCmpt(windowCmptRef);
|
|
68
|
+
// We have to cleanup DOM after the last modal when BOTH 'hidden' was emitted and 'result' promise was resolved:
|
|
69
|
+
// - with animations OFF, 'hidden' emits synchronously, then 'result' is resolved asynchronously
|
|
70
|
+
// - with animations ON, 'result' is resolved asynchronously, then 'hidden' emits asynchronously
|
|
71
|
+
hubModalRef.hidden.pipe(take(1)).subscribe(() => Promise.resolve(true).then(() => {
|
|
72
|
+
if (!this._modalRefs.length) {
|
|
73
|
+
this._document.body.classList.remove('modal-open');
|
|
74
|
+
this._restoreScrollBar();
|
|
75
|
+
this._revertAriaHidden();
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
activeModal.close = (result) => {
|
|
79
|
+
hubModalRef.close(result);
|
|
80
|
+
};
|
|
81
|
+
activeModal.dismiss = (reason) => {
|
|
82
|
+
hubModalRef.dismiss(reason);
|
|
83
|
+
};
|
|
84
|
+
activeModal.update = (options) => {
|
|
85
|
+
hubModalRef.update(options);
|
|
86
|
+
};
|
|
87
|
+
hubModalRef.update(options);
|
|
88
|
+
if (this._modalRefs.length === 1) {
|
|
89
|
+
this._document.body.classList.add('modal-open');
|
|
90
|
+
}
|
|
91
|
+
if (backdropCmptRef && backdropCmptRef.instance) {
|
|
92
|
+
backdropCmptRef.changeDetectorRef.detectChanges();
|
|
93
|
+
}
|
|
94
|
+
windowCmptRef.changeDetectorRef.detectChanges();
|
|
95
|
+
return hubModalRef;
|
|
96
|
+
}
|
|
97
|
+
get activeInstances() {
|
|
98
|
+
return this._activeInstances;
|
|
99
|
+
}
|
|
100
|
+
dismissAll(reason) {
|
|
101
|
+
this._modalRefs.forEach((hubModalRef) => hubModalRef.dismiss(reason));
|
|
102
|
+
}
|
|
103
|
+
hasOpenModals() {
|
|
104
|
+
return this._modalRefs.length > 0;
|
|
105
|
+
}
|
|
106
|
+
_attachBackdrop(containerEl) {
|
|
107
|
+
let backdropCmptRef = createComponent(HubModalBackdrop, {
|
|
108
|
+
environmentInjector: this._applicationRef.injector,
|
|
109
|
+
elementInjector: this._injector
|
|
110
|
+
});
|
|
111
|
+
this._applicationRef.attachView(backdropCmptRef.hostView);
|
|
112
|
+
containerEl.appendChild(backdropCmptRef.location.nativeElement);
|
|
113
|
+
return backdropCmptRef;
|
|
114
|
+
}
|
|
115
|
+
_attachWindowComponent(containerEl, [headerNodes, bodyNodes, footerNodes], options) {
|
|
116
|
+
const singleContent = !options.headerSelector && !options.footerSelector;
|
|
117
|
+
let windowCmptRef = createComponent(HubModalWindow, {
|
|
118
|
+
environmentInjector: this._applicationRef.injector,
|
|
119
|
+
elementInjector: this._injector,
|
|
120
|
+
projectableNodes: singleContent
|
|
121
|
+
? [bodyNodes]
|
|
122
|
+
: [[], headerNodes, bodyNodes, footerNodes]
|
|
123
|
+
});
|
|
124
|
+
Object.assign(windowCmptRef.instance, { singleContent });
|
|
125
|
+
this._applicationRef.attachView(windowCmptRef.hostView);
|
|
126
|
+
containerEl.appendChild(windowCmptRef.location.nativeElement);
|
|
127
|
+
return windowCmptRef;
|
|
128
|
+
}
|
|
129
|
+
_getContentRef(contentInjector, environmentInjector, content, activeModal, options) {
|
|
130
|
+
if (!content) {
|
|
131
|
+
return new ContentRef([]);
|
|
132
|
+
}
|
|
133
|
+
else if (content instanceof TemplateRef) {
|
|
134
|
+
return this._createFromTemplateRef(content, activeModal, options);
|
|
135
|
+
}
|
|
136
|
+
else if (isString(content)) {
|
|
137
|
+
return this._createFromString(content);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
return this._createFromComponent(contentInjector, environmentInjector, content, activeModal, options);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
_createFromTemplateRef(templateRef, activeModal, options) {
|
|
144
|
+
const context = {
|
|
145
|
+
$implicit: activeModal,
|
|
146
|
+
close(result) {
|
|
147
|
+
activeModal.close(result);
|
|
148
|
+
},
|
|
149
|
+
dismiss(reason) {
|
|
150
|
+
activeModal.dismiss(reason);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const viewRef = templateRef.createEmbeddedView(context);
|
|
154
|
+
this._applicationRef.attachView(viewRef);
|
|
155
|
+
const containerNode = document.createElement('ng-container');
|
|
156
|
+
containerNode.append(...viewRef.rootNodes);
|
|
157
|
+
this._addDismissEventListener(containerNode, context, options);
|
|
158
|
+
return new ContentRef([
|
|
159
|
+
options.headerSelector
|
|
160
|
+
? extractAndRemoveNodesBySelector(containerNode, options.headerSelector)
|
|
161
|
+
: [],
|
|
162
|
+
containerNode.childNodes,
|
|
163
|
+
options.footerSelector
|
|
164
|
+
? extractAndRemoveNodesBySelector(containerNode, options.footerSelector)
|
|
165
|
+
: []
|
|
166
|
+
], viewRef);
|
|
167
|
+
}
|
|
168
|
+
_createFromString(content) {
|
|
169
|
+
const component = this._document.createTextNode(`${content}`);
|
|
170
|
+
return new ContentRef([[component]]);
|
|
171
|
+
}
|
|
172
|
+
_createFromComponent(contentInjector, environmentInjector, componentType, context, options) {
|
|
173
|
+
const elementInjector = Injector.create({
|
|
174
|
+
providers: [{ provide: HubActiveModal, useValue: context }],
|
|
175
|
+
parent: contentInjector
|
|
176
|
+
});
|
|
177
|
+
const componentRef = createComponent(componentType, {
|
|
178
|
+
environmentInjector,
|
|
179
|
+
elementInjector
|
|
180
|
+
});
|
|
181
|
+
const componentNativeEl = componentRef.location.nativeElement;
|
|
182
|
+
if (options.scrollable) {
|
|
183
|
+
componentNativeEl.classList.add('component-host-scrollable');
|
|
184
|
+
}
|
|
185
|
+
this._applicationRef.attachView(componentRef.hostView);
|
|
186
|
+
this._addDismissEventListener(componentNativeEl, context, options);
|
|
187
|
+
// FIXME: we should here get rid of the component nativeElement
|
|
188
|
+
// and use `[Array.from(componentNativeEl.childNodes)]` instead and remove the above CSS class.
|
|
189
|
+
return new ContentRef([
|
|
190
|
+
options.headerSelector
|
|
191
|
+
? extractAndRemoveNodesBySelector(componentNativeEl, options.headerSelector)
|
|
192
|
+
: [],
|
|
193
|
+
componentNativeEl.childNodes,
|
|
194
|
+
options.footerSelector
|
|
195
|
+
? extractAndRemoveNodesBySelector(componentNativeEl, options.footerSelector)
|
|
196
|
+
: []
|
|
197
|
+
], componentRef.hostView, componentRef);
|
|
198
|
+
}
|
|
199
|
+
_setAriaHidden(element) {
|
|
200
|
+
const parent = element.parentElement;
|
|
201
|
+
if (parent && element !== this._document.body) {
|
|
202
|
+
Array.from(parent.children).forEach((sibling) => {
|
|
203
|
+
if (sibling !== element && sibling.nodeName !== 'SCRIPT') {
|
|
204
|
+
this._ariaHiddenValues.set(sibling, sibling.getAttribute('aria-hidden'));
|
|
205
|
+
sibling.setAttribute('aria-hidden', 'true');
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
this._setAriaHidden(parent);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
_revertAriaHidden() {
|
|
212
|
+
this._ariaHiddenValues.forEach((value, element) => {
|
|
213
|
+
if (value) {
|
|
214
|
+
element.setAttribute('aria-hidden', value);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
element.removeAttribute('aria-hidden');
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
this._ariaHiddenValues.clear();
|
|
221
|
+
}
|
|
222
|
+
_registerModalRef(hubModalRef) {
|
|
223
|
+
const unregisterModalRef = () => {
|
|
224
|
+
const index = this._modalRefs.indexOf(hubModalRef);
|
|
225
|
+
if (index > -1) {
|
|
226
|
+
this._modalRefs.splice(index, 1);
|
|
227
|
+
this._activeInstances.emit(this._modalRefs);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
this._modalRefs.push(hubModalRef);
|
|
231
|
+
this._activeInstances.emit(this._modalRefs);
|
|
232
|
+
hubModalRef.result.then(unregisterModalRef, unregisterModalRef);
|
|
233
|
+
}
|
|
234
|
+
_registerWindowCmpt(hubWindowCmpt) {
|
|
235
|
+
this._windowCmpts.push(hubWindowCmpt);
|
|
236
|
+
this._activeWindowCmptHasChanged.next();
|
|
237
|
+
hubWindowCmpt.onDestroy(() => {
|
|
238
|
+
const index = this._windowCmpts.indexOf(hubWindowCmpt);
|
|
239
|
+
if (index > -1) {
|
|
240
|
+
this._windowCmpts.splice(index, 1);
|
|
241
|
+
this._activeWindowCmptHasChanged.next();
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Attaches click event listeners to elements within a container based on a specified dismiss selector to dismiss a modal.
|
|
247
|
+
*
|
|
248
|
+
* @param {HTMLElement} container - The `container` parameter is an HTMLElement that represents the DOM element which contains the
|
|
249
|
+
* modal content.
|
|
250
|
+
* @param {HubActiveModal} context - The `context` parameter in the `_addDismissEventListener` function refers to the active modal
|
|
251
|
+
* instance that is being displayed. It is used to call the `dismiss` method on the modal instance when a dismissible element is
|
|
252
|
+
* clicked.
|
|
253
|
+
* @param {HubModalOptions} options - The `options` parameter is an object that contains configuration options for the modal. It
|
|
254
|
+
* may include properties such as `dismissSelector`, which is used to specify a CSS selector for elements that, when clicked, will
|
|
255
|
+
* dismiss the modal by calling the `dismiss` method on the `context` object.
|
|
256
|
+
*/
|
|
257
|
+
_addDismissEventListener(container, context, options) {
|
|
258
|
+
if (options.dismissSelector) {
|
|
259
|
+
const dismissaable = container.querySelectorAll(options.dismissSelector);
|
|
260
|
+
for (const item of Array.from(dismissaable)) {
|
|
261
|
+
item.addEventListener('click', () => context.dismiss());
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: HubModalStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
266
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: HubModalStack, providedIn: 'root' }); }
|
|
267
|
+
}
|
|
268
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.5", ngImport: i0, type: HubModalStack, decorators: [{
|
|
269
|
+
type: Injectable,
|
|
270
|
+
args: [{ providedIn: 'root' }]
|
|
271
|
+
}], ctorParameters: () => [] });
|
|
272
|
+
/**
|
|
273
|
+
* Extracts child nodes matching a selector from a container element, removes those nodes from the DOM, and returns them as an array.
|
|
274
|
+
*
|
|
275
|
+
* @param {HTMLElement} container - The `container` parameter in the `extractAndRemoveNodesBySelector` function is an HTMLElement
|
|
276
|
+
* that represents the parent element within which we want to search for nodes matching a specific selector and remove them.
|
|
277
|
+
* @param {string} selector - The `selector` parameter in the `extractAndRemoveNodesBySelector` function is a string that
|
|
278
|
+
* represents a CSS selector. This selector is used to query and select specific elements within the `container` HTMLElement.
|
|
279
|
+
*
|
|
280
|
+
* @returns An array of nodes that were extracted from the container element based on the provided selector, and then removes those
|
|
281
|
+
* nodes from the DOM.
|
|
282
|
+
*/
|
|
283
|
+
function extractAndRemoveNodesBySelector(container, selector) {
|
|
284
|
+
let containerNodes = container.querySelectorAll(selector);
|
|
285
|
+
const nodes = Array.from(containerNodes).reduce((acc, c) => {
|
|
286
|
+
return [...acc, ...Array.from(c.childNodes)];
|
|
287
|
+
}, []);
|
|
288
|
+
// Selecciona los nodos dentro del contenedor que coincidan con el selector
|
|
289
|
+
const nodesToRemove = container.querySelectorAll(selector);
|
|
290
|
+
// Convertir NodeList a array y eliminar cada nodo del DOM
|
|
291
|
+
Array.from(nodesToRemove).forEach((node) => node.remove());
|
|
292
|
+
return nodes;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9tb2RhbC9zcmMvbGliL21vZGFsLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQ04sY0FBYyxFQUVkLGVBQWUsRUFDZixtQkFBbUIsRUFDbkIsWUFBWSxFQUNaLE1BQU0sRUFDTixVQUFVLEVBQ1YsUUFBUSxFQUNSLE1BQU0sRUFDTixXQUFXLEVBRVgsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNOLFVBQVUsRUFDVixZQUFZLEVBQ1osU0FBUyxFQUNULFFBQVEsRUFDUixTQUFTLEVBQ1QsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7O0FBR2hELE1BQU0sT0FBTyxhQUFhO0lBY3pCO1FBYlEsb0JBQWUsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3Qix5QkFBb0IsR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNuRCxjQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdCLGVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFL0IsZ0NBQTJCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUNsRCxzQkFBaUIs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QUFhLEdBQUcsU0FBUyxDQUFDLGdCQUFnQixDQUFjLFFBQVEsQ0FBQyxDQUFDO0lBRXhFLDBEQUEwRDtJQUMxRCxLQUFLLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDM0QsT0FBTyxLQUFLLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcblx0QXBwbGljYXRpb25SZWYsXG5cdENvbXBvbmVudFJlZixcblx0Y3JlYXRlQ29tcG9uZW50LFxuXHRFbnZpcm9ubWVudEluamVjdG9yLFxuXHRFdmVudEVtaXR0ZXIsXG5cdGluamVjdCxcblx0SW5qZWN0YWJsZSxcblx0SW5qZWN0b3IsXG5cdE5nWm9uZSxcblx0VGVtcGxhdGVSZWYsXG5cdFR5cGVcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuXHRDb250ZW50UmVmLFxuXHRodWJGb2N1c1RyYXAsXG5cdGlzRGVmaW5lZCxcblx0aXNTdHJpbmcsXG5cdFNjcm9sbEJhclxufSBmcm9tICduZy1odWItdWktdXRpbHMnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEh1Yk1vZGFsQmFja2Ryb3AgfSBmcm9tICcuL21vZGFsLWJhY2tkcm9wJztcbmltcG9ydCB7IEh1Yk1vZGFsT3B0aW9ucywgSHViTW9kYWxVcGRhdGFibGVPcHRpb25zIH0gZnJvbSAnLi9tb2RhbC1jb25maWcnO1xuaW1wb3J0IHsgSHViQWN0aXZlTW9kYWwsIEh1Yk1vZGFsUmVmIH0gZnJvbSAnLi9tb2RhbC1yZWYnO1xuaW1wb3J0IHsgSHViTW9kYWxXaW5kb3cgfSBmcm9tICcuL21vZGFsLXdpbmRvdyc7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgSHViTW9kYWxTdGFjayB7XG5cdHByaXZhdGUgX2FwcGxpY2F0aW9uUmVmID0gaW5qZWN0KEFwcGxpY2F0aW9uUmVmKTtcblx0cHJpdmF0ZSBfaW5qZWN0b3IgPSBpbmplY3QoSW5qZWN0b3IpO1xuXHRwcml2YXRlIF9lbnZpcm9ubWVudEluamVjdG9yID0gaW5qZWN0KEVudmlyb25tZW50SW5qZWN0b3IpO1xuXHRwcml2YXRlIF9kb2N1bWVudCA9IGluamVjdChET0NVTUVOVCk7XG5cdHByaXZhdGUgX3Njcm9sbEJhciA9IGluamVjdChTY3JvbGxCYXIpO1xuXG5cdHByaXZhdGUgX2FjdGl2ZVdpbmRvd0NtcHRIYXNDaGFuZ2VkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblx0cHJpdmF0ZSBfYXJpYUhpZGRlblZhbHVlczogTWFwPEVsZW1lbnQsIHN0cmluZyB8IG51bGw+ID0gbmV3IE1hcCgpO1xuXHRwcml2YXRlIF9zY3JvbGxCYXJSZXN0b3JlRm46IG51bGwgfCAoKCkgPT4gdm9pZCkgPSBudWxsO1xuXHRwcml2YXRlIF9tb2RhbFJlZnM6IEh1Yk1vZGFsUmVmW10gPSBbXTtcblx0cHJpdmF0ZSBfd2luZG93Q21wdHM6IENvbXBvbmVudFJlZjxIdWJNb2RhbFdpbmRvdz5bXSA9IFtdO1xuXHRwcml2YXRlIF9hY3RpdmVJbnN0YW5jZXM6IEV2ZW50RW1pdHRlcjxIdWJNb2RhbFJlZltdPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHRjb25zdHJ1Y3RvcigpIHtcblx0XHRjb25zdCBuZ1pvbmUgPSBpbmplY3QoTmdab25lKTtcblxuXHRcdC8vIFRyYXAgZm9jdXMgb24gYWN0aXZlIFdpbmRvd0NtcHRcblx0XHR0aGlzLl9hY3RpdmVXaW5kb3dDbXB0SGFzQ2hhbmdlZC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuX3dpbmRvd0NtcHRzLmxlbmd0aCkge1xuXHRcdFx0XHRjb25zdCBhY3RpdmVXaW5kb3dDbXB0ID1cblx0XHRcdFx0XHR0aGlzLl93aW5kb3dDbXB0c1t0aGlzLl93aW5kb3dDbXB0cy5sZW5ndGggLSAxXTtcblx0XHRcdFx0aHViRm9jdXNUcmFwKFxuXHRcdFx0XHRcdG5nWm9uZSxcblx0XHRcdFx0XHRhY3RpdmVXaW5kb3dDbXB0LmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHRcdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWRcblx0XHRcdFx0KTtcblx0XHRcdFx0dGhpcy5fcmV2ZXJ0QXJpYUhpZGRlbigpO1xuXHRcdFx0XHR0aGlzLl9zZXRBcmlhSGlkZGVuKGFjdGl2ZVdpbmRvd0NtcHQubG9jYXRpb24ubmF0aXZlRWxlbWVudCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIF9yZXN0b3JlU2Nyb2xsQmFyKCkge1xuXHRcdGNvbnN0IHNjcm9sbEJhclJlc3RvcmVGbiA9IHRoaXMuX3Njcm9sbEJhclJlc3RvcmVGbjtcblx0XHRpZiAoc2Nyb2xsQmFyUmVzdG9yZUZuKSB7XG5cdFx0XHR0aGlzLl9zY3JvbGxCYXJSZXN0b3JlRm4gPSBudWxsO1xuXHRcdFx0c2Nyb2xsQmFyUmVzdG9yZUZuKCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBfaGlkZVNjcm9sbEJhcigpIHtcblx0XHRpZiAoIXRoaXMuX3Njcm9sbEJhclJlc3RvcmVGbikge1xuXHRcdFx0dGhpcy5fc2Nyb2xsQmFyUmVzdG9yZUZuID0gdGhpcy5fc2Nyb2xsQmFyLmhpZGUoKTtcblx0XHR9XG5cdH1cblxuXHRvcGVuKFxuXHRcdGNvbnRlbnRJbmplY3RvcjogSW5qZWN0b3IsXG5cdFx0Y29udGVudDogYW55LFxuXHRcdG9wdGlvbnM6IEh1Yk1vZGFsT3B0aW9uc1xuXHQpOiBIdWJNb2RhbFJlZiB7XG5cdFx0Y29uc3QgY29udGFpbmVyRWwgPVxuXHRcdFx0b3B0aW9ucy5jb250YWluZXIgaW5zdGFuY2VvZiBIVE1MRWxlbWVudFxuXHRcdFx0XHQ/IG9wdGlvbnMuY29udGFpbmVyXG5cdFx0XHRcdDogaXNEZWZpbmVkKG9wdGlvbnMuY29udGFpbmVyKVxuXHRcdFx0XHQ/IHRoaXMuX2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iob3B0aW9ucy5jb250YWluZXIhKVxuXHRcdFx0XHQ6IHRoaXMuX2RvY3VtZW50LmJvZHk7XG5cblx0XHRpZiAoIWNvbnRhaW5lckVsKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBUaGUgc3BlY2lmaWVkIG1vZGFsIGNvbnRhaW5lciBcIiR7XG5cdFx0XHRcdFx0b3B0aW9ucy5jb250YWluZXIgfHwgJ2JvZHknXG5cdFx0XHRcdH1cIiB3YXMgbm90IGZvdW5kIGluIHRoZSBET00uYFxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHR0aGlzLl9oaWRlU2Nyb2xsQmFyKCk7XG5cblx0XHRjb25zdCBhY3RpdmVNb2RhbCA9IG5ldyBIdWJBY3RpdmVNb2RhbCgpO1xuXG5cdFx0Y29udGVudEluamVjdG9yID0gb3B0aW9ucy5pbmplY3RvciB8fCBjb250ZW50SW5qZWN0b3I7XG5cdFx0Y29uc3QgZW52aXJvbm1lbnRJbmplY3RvciA9XG5cdFx0XHRjb250ZW50SW5qZWN0b3IuZ2V0KEVudmlyb25tZW50SW5qZWN0b3IsIG51bGwpIHx8XG5cdFx0XHR0aGlzLl9lbnZpcm9ubWVudEluamVjdG9yO1xuXHRcdGNvbnN0IGNvbnRlbnRSZWYgPSB0aGlzLl9nZXRDb250ZW50UmVmKFxuXHRcdFx0Y29udGVudEluamVjdG9yLFxuXHRcdFx0ZW52aXJvbm1lbnRJbmplY3Rvcixcblx0XHRcdGNvbnRlbnQsXG5cdFx0XHRhY3RpdmVNb2RhbCxcblx0XHRcdG9wdGlvbnNcblx0XHQpO1xuXG5cdFx0Y29uc3QgYmFja2Ryb3BDbXB0UmVmOiBDb21wb25lbnRSZWY8SHViTW9kYWxCYWNrZHJvcD4gfCB1bmRlZmluZWQgPVxuXHRcdFx0b3B0aW9ucy5iYWNrZHJvcCAhPT0gZmFsc2Vcblx0XHRcdFx0PyB0aGlzLl9hdHRhY2hCYWNrZHJvcChjb250YWluZXJFbClcblx0XHRcdFx0OiB1bmRlZmluZWQ7XG5cdFx0Y29uc3Qgd2luZG93Q21wdFJlZjogQ29tcG9uZW50UmVmPEh1Yk1vZGFsV2luZG93PiA9XG5cdFx0XHR0aGlzLl9hdHRhY2hXaW5kb3dDb21wb25lbnQoY29udGFpbmVyRWwsIGNvbnRlbnRSZWYubm9kZXMsIG9wdGlvbnMpO1xuXHRcdGNvbnN0IGh1Yk1vZGFsUmVmOiBIdWJNb2RhbFJlZiA9IG5ldyBIdWJNb2RhbFJlZihcblx0XHRcdHdpbmRvd0NtcHRSZWYsXG5cdFx0XHRjb250ZW50UmVmLFxuXHRcdFx0YmFja2Ryb3BDbXB0UmVmLFxuXHRcdFx0b3B0aW9ucy5iZWZvcmVEaXNtaXNzXG5cdFx0KTtcblxuXHRcdHRoaXMuX3JlZ2lzdGVyTW9kYWxSZWYoaHViTW9kYWxSZWYpO1xuXHRcdHRoaXMuX3JlZ2lzdGVyV2luZG93Q21wdCh3aW5kb3dDbXB0UmVmKTtcblxuXHRcdC8vIFdlIGhhdmUgdG8gY2xlYW51cCBET00gYWZ0ZXIgdGhlIGxhc3QgbW9kYWwgd2hlbiBCT1RIICdoaWRkZW4nIHdhcyBlbWl0dGVkIGFuZCAncmVzdWx0JyBwcm9taXNlIHdhcyByZXNvbHZlZDpcblx0XHQvLyAtIHdpdGggYW5pbWF0aW9ucyBPRkYsICdoaWRkZW4nIGVtaXRzIHN5bmNocm9ub3VzbHksIHRoZW4gJ3Jlc3VsdCcgaXMgcmVzb2x2ZWQgYXN5bmNocm9ub3VzbHlcblx0XHQvLyAtIHdpdGggYW5pbWF0aW9ucyBPTiwgJ3Jlc3VsdCcgaXMgcmVzb2x2ZWQgYXN5bmNocm9ub3VzbHksIHRoZW4gJ2hpZGRlbicgZW1pdHMgYXN5bmNocm9ub3VzbHlcblx0XHRodWJNb2RhbFJlZi5oaWRkZW4ucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKCkgPT5cblx0XHRcdFByb21pc2UucmVzb2x2ZSh0cnVlKS50aGVuKCgpID0+IHtcblx0XHRcdFx0aWYgKCF0aGlzLl9tb2RhbFJlZnMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0dGhpcy5fZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCdtb2RhbC1vcGVuJyk7XG5cdFx0XHRcdFx0dGhpcy5fcmVzdG9yZVNjcm9sbEJhcigpO1xuXHRcdFx0XHRcdHRoaXMuX3JldmVydEFyaWFIaWRkZW4oKTtcblx0XHRcdFx0fVxuXHRcdFx0fSlcblx0XHQpO1xuXG5cdFx0YWN0aXZlTW9kYWwuY2xvc2UgPSAocmVzdWx0OiBhbnkpID0+IHtcblx0XHRcdGh1Yk1vZGFsUmVmLmNsb3NlKHJlc3VsdCk7XG5cdFx0fTtcblx0XHRhY3RpdmVNb2RhbC5kaXNtaXNzID0gKHJlYXNvbjogYW55KSA9PiB7XG5cdFx0XHRodWJNb2RhbFJlZi5kaXNtaXNzKHJlYXNvbik7XG5cdFx0fTtcblxuXHRcdGFjdGl2ZU1vZGFsLnVwZGF0ZSA9IChvcHRpb25zOiBIdWJNb2RhbFVwZGF0YWJsZU9wdGlvbnMpID0+IHtcblx0XHRcdGh1Yk1vZGFsUmVmLnVwZGF0ZShvcHRpb25zKTtcblx0XHR9O1xuXG5cdFx0aHViTW9kYWxSZWYudXBkYXRlKG9wdGlvbnMpO1xuXHRcdGlmICh0aGlzLl9tb2RhbFJlZnMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHR0aGlzLl9kb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ21vZGFsLW9wZW4nKTtcblx0XHR9XG5cblx0XHRpZiAoYmFja2Ryb3BDbXB0UmVmICYmIGJhY2tkcm9wQ21wdFJlZi5pbnN0YW5jZSkge1xuXHRcdFx0YmFja2Ryb3BDbXB0UmVmLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcblx0XHR9XG5cdFx0d2luZG93Q21wdFJlZi5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG5cdFx0cmV0dXJuIGh1Yk1vZGFsUmVmO1xuXHR9XG5cblx0Z2V0IGFjdGl2ZUluc3RhbmNlcygpIHtcblx0XHRyZXR1cm4gdGhpcy5fYWN0aXZlSW5zdGFuY2VzO1xuXHR9XG5cblx0ZGlzbWlzc0FsbChyZWFzb24/OiBhbnkpIHtcblx0XHR0aGlzLl9tb2RhbFJlZnMuZm9yRWFjaCgoaHViTW9kYWxSZWYpID0+IGh1Yk1vZGFsUmVmLmRpc21pc3MocmVhc29uKSk7XG5cdH1cblxuXHRoYXNPcGVuTW9kYWxzKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLl9tb2RhbFJlZnMubGVuZ3RoID4gMDtcblx0fVxuXG5cdHByaXZhdGUgX2F0dGFjaEJhY2tkcm9wKFxuXHRcdGNvbnRhaW5lckVsOiBFbGVtZW50XG5cdCk6IENvbXBvbmVudFJlZjxIdWJNb2RhbEJhY2tkcm9wPiB7XG5cdFx0bGV0IGJhY2tkcm9wQ21wdFJlZiA9IGNyZWF0ZUNvbXBvbmVudChIdWJNb2RhbEJhY2tkcm9wLCB7XG5cdFx0XHRlbnZpcm9ubWVudEluamVjdG9yOiB0aGlzLl9hcHBsaWNhdGlvblJlZi5pbmplY3Rvcixcblx0XHRcdGVsZW1lbnRJbmplY3RvcjogdGhpcy5faW5qZWN0b3Jcblx0XHR9KTtcblx0XHR0aGlzLl9hcHBsaWNhdGlvblJlZi5hdHRhY2hWaWV3KGJhY2tkcm9wQ21wdFJlZi5ob3N0Vmlldyk7XG5cdFx0Y29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoYmFja2Ryb3BDbXB0UmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdHJldHVybiBiYWNrZHJvcENtcHRSZWY7XG5cdH1cblxuXHRwcml2YXRlIF9hdHRhY2hXaW5kb3dDb21wb25lbnQoXG5cdFx0Y29udGFpbmVyRWw6IEVsZW1lbnQsXG5cdFx0W2hlYWRlck5vZGVzLCBib2R5Tm9kZXMsIGZvb3Rlck5vZGVzXTogTm9kZVtdW10sXG5cdFx0b3B0aW9uczogSHViTW9kYWxPcHRpb25zXG5cdCk6IENvbXBvbmVudFJlZjxIdWJNb2RhbFdpbmRvdz4ge1xuXHRcdGNvbnN0IHNpbmdsZUNvbnRlbnQgPVxuXHRcdFx0IW9wdGlvbnMuaGVhZGVyU2VsZWN0b3IgJiYgIW9wdGlvbnMuZm9vdGVyU2VsZWN0b3I7XG5cdFx0bGV0IHdpbmRvd0NtcHRSZWYgPSBjcmVhdGVDb21wb25lbnQoSHViTW9kYWxXaW5kb3csIHtcblx0XHRcdGVudmlyb25tZW50SW5qZWN0b3I6IHRoaXMuX2FwcGxpY2F0aW9uUmVmLmluamVjdG9yLFxuXHRcdFx0ZWxlbWVudEluamVjdG9yOiB0aGlzLl9pbmplY3Rvcixcblx0XHRcdHByb2plY3RhYmxlTm9kZXM6IHNpbmdsZUNvbnRlbnRcblx0XHRcdFx0PyBbYm9keU5vZGVzXVxuXHRcdFx0XHQ6IFtbXSwgaGVhZGVyTm9kZXMsIGJvZHlOb2RlcywgZm9vdGVyTm9kZXNdXG5cdFx0fSk7XG5cblx0XHRPYmplY3QuYXNzaWduKHdpbmRvd0NtcHRSZWYuaW5zdGFuY2UsIHsgc2luZ2xlQ29udGVudCB9KTtcblxuXHRcdHRoaXMuX2FwcGxpY2F0aW9uUmVmLmF0dGFjaFZpZXcod2luZG93Q21wdFJlZi5ob3N0Vmlldyk7XG5cdFx0Y29udGFpbmVyRWwuYXBwZW5kQ2hpbGQod2luZG93Q21wdFJlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcblx0XHRyZXR1cm4gd2luZG93Q21wdFJlZjtcblx0fVxuXG5cdHByaXZhdGUgX2dldENvbnRlbnRSZWYoXG5cdFx0Y29udGVudEluamVjdG9yOiBJbmplY3Rvcixcblx0XHRlbnZpcm9ubWVudEluamVjdG9yOiBFbnZpcm9ubWVudEluamVjdG9yLFxuXHRcdGNvbnRlbnQ6IFR5cGU8YW55PiB8IFRlbXBsYXRlUmVmPGFueT4gfCBzdHJpbmcsXG5cdFx0YWN0aXZlTW9kYWw6IEh1YkFjdGl2ZU1vZGFsLFxuXHRcdG9wdGlvbnM6IEh1Yk1vZGFsT3B0aW9uc1xuXHQpOiBDb250ZW50UmVmIHtcblx0XHRpZiAoIWNvbnRlbnQpIHtcblx0XHRcdHJldHVybiBuZXcgQ29udGVudFJlZihbXSk7XG5cdFx0fSBlbHNlIGlmIChjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYpIHtcblx0XHRcdHJldHVybiB0aGlzLl9jcmVhdGVGcm9tVGVtcGxhdGVSZWYoY29udGVudCwgYWN0aXZlTW9kYWwsIG9wdGlvbnMpO1xuXHRcdH0gZWxzZSBpZiAoaXNTdHJpbmcoY29udGVudCkpIHtcblx0XHRcdHJldHVybiB0aGlzLl9jcmVhdGVGcm9tU3RyaW5nKGNvbnRlbnQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlRnJvbUNvbXBvbmVudChcblx0XHRcdFx0Y29udGVudEluamVjdG9yLFxuXHRcdFx0XHRlbnZpcm9ubWVudEluamVjdG9yLFxuXHRcdFx0XHRjb250ZW50LFxuXHRcdFx0XHRhY3RpdmVNb2RhbCxcblx0XHRcdFx0b3B0aW9uc1xuXHRcdFx0KTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF9jcmVhdGVGcm9tVGVtcGxhdGVSZWYoXG5cdFx0dGVtcGxhdGVSZWY6IFRlbXBsYXRlUmVmPGFueT4sXG5cdFx0YWN0aXZlTW9kYWw6IEh1YkFjdGl2ZU1vZGFsLFxuXHRcdG9wdGlvbnM6IEh1Yk1vZGFsT3B0aW9uc1xuXHQpOiBDb250ZW50UmVmIHtcblx0XHRjb25zdCBjb250ZXh0ID0ge1xuXHRcdFx0JGltcGxpY2l0OiBhY3RpdmVNb2RhbCxcblx0XHRcdGNsb3NlKHJlc3VsdCkge1xuXHRcdFx0XHRhY3RpdmVNb2RhbC5jbG9zZShyZXN1bHQpO1xuXHRcdFx0fSxcblx0XHRcdGRpc21pc3MocmVhc29uKSB7XG5cdFx0XHRcdGFjdGl2ZU1vZGFsLmRpc21pc3MocmVhc29uKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdGNvbnN0IHZpZXdSZWYgPSB0ZW1wbGF0ZVJlZi5jcmVhdGVFbWJlZGRlZFZpZXcoY29udGV4dCk7XG5cdFx0dGhpcy5fYXBwbGljYXRpb25SZWYuYXR0YWNoVmlldyh2aWV3UmVmKTtcblxuXHRcdGNvbnN0IGNvbnRhaW5lck5vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCduZy1jb250YWluZXInKTtcblx0XHRjb250YWluZXJOb2RlLmFwcGVuZCguLi52aWV3UmVmLnJvb3ROb2Rlcyk7XG5cblx0XHR0aGlzLl9hZGREaXNtaXNzRXZlbnRMaXN0ZW5lcihjb250YWluZXJOb2RlLCBjb250ZXh0IGFzIGFueSwgb3B0aW9ucyk7XG5cblx0XHRyZXR1cm4gbmV3IENvbnRlbnRSZWYoXG5cdFx0XHRbXG5cdFx0XHRcdG9wdGlvbnMuaGVhZGVyU2VsZWN0b3Jcblx0XHRcdFx0XHQ/IGV4dHJhY3RBbmRSZW1vdmVOb2Rlc0J5U2VsZWN0b3IoXG5cdFx0XHRcdFx0XHRcdGNvbnRhaW5lck5vZGUsXG5cdFx0XHRcdFx0XHRcdG9wdGlvbnMuaGVhZGVyU2VsZWN0b3Jcblx0XHRcdFx0XHQgIClcblx0XHRcdFx0XHQ6IFtdLFxuXHRcdFx0XHRjb250YWluZXJOb2RlLmNoaWxkTm9kZXMgYXMgYW55LFxuXHRcdFx0XHRvcHRpb25zLmZvb3RlclNlbGVjdG9yXG5cdFx0XHRcdFx0PyBleHRyYWN0QW5kUmVtb3ZlTm9kZXNCeVNlbGVjdG9yKFxuXHRcdFx0XHRcdFx0XHRjb250YWluZXJOb2RlLFxuXHRcdFx0XHRcdFx0XHRvcHRpb25zLmZvb3RlclNlbGVjdG9yXG5cdFx0XHRcdFx0ICApXG5cdFx0XHRcdFx0OiBbXVxuXHRcdFx0XSxcblx0XHRcdHZpZXdSZWZcblx0XHQpO1xuXHR9XG5cblx0cHJpdmF0ZSBfY3JlYXRlRnJvbVN0cmluZyhjb250ZW50OiBzdHJpbmcpOiBDb250ZW50UmVmIHtcblx0XHRjb25zdCBjb21wb25lbnQgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShgJHtjb250ZW50fWApO1xuXHRcdHJldHVybiBuZXcgQ29udGVudFJlZihbW2NvbXBvbmVudF1dKTtcblx0fVxuXG5cdHByaXZhdGUgX2NyZWF0ZUZyb21Db21wb25lbnQoXG5cdFx0Y29udGVudEluamVjdG9yOiBJbmplY3Rvcixcblx0XHRlbnZpcm9ubWVudEluamVjdG9yOiBFbnZpcm9ubWVudEluamVjdG9yLFxuXHRcdGNvbXBvbmVudFR5cGU6IFR5cGU8YW55Pixcblx0XHRjb250ZXh0OiBIdWJBY3RpdmVNb2RhbCxcblx0XHRvcHRpb25zOiBIdWJNb2RhbE9wdGlvbnNcblx0KTogQ29udGVudFJlZiB7XG5cdFx0Y29uc3QgZWxlbWVudEluamVjdG9yID0gSW5qZWN0b3IuY3JlYXRlKHtcblx0XHRcdHByb3ZpZGVyczogW3sgcHJvdmlkZTogSHViQWN0aXZlTW9kYWwsIHVzZVZhbHVlOiBjb250ZXh0IH1dLFxuXHRcdFx0cGFyZW50OiBjb250ZW50SW5qZWN0b3Jcblx0XHR9KTtcblx0XHRjb25zdCBjb21wb25lbnRSZWYgPSBjcmVhdGVDb21wb25lbnQoY29tcG9uZW50VHlwZSwge1xuXHRcdFx0ZW52aXJvbm1lbnRJbmplY3Rvcixcblx0XHRcdGVsZW1lbnRJbmplY3RvclxuXHRcdH0pO1xuXHRcdGNvbnN0IGNvbXBvbmVudE5hdGl2ZUVsOiBIVE1MRWxlbWVudCA9XG5cdFx0XHRjb21wb25lbnRSZWYubG9jYXRpb24ubmF0aXZlRWxlbWVudDtcblx0XHRpZiAob3B0aW9ucy5zY3JvbGxhYmxlKSB7XG5cdFx0XHRjb21wb25lbnROYXRpdmVFbC5jbGFzc0xpc3QuYWRkKCdjb21wb25lbnQtaG9zdC1zY3JvbGxhYmxlJyk7XG5cdFx0fVxuXHRcdHRoaXMuX2FwcGxpY2F0aW9uUmVmLmF0dGFjaFZpZXcoY29tcG9uZW50UmVmLmhvc3RWaWV3KTtcblxuXHRcdHRoaXMuX2FkZERpc21pc3NFdmVudExpc3RlbmVyKGNvbXBvbmVudE5hdGl2ZUVsLCBjb250ZXh0LCBvcHRpb25zKTtcblxuXHRcdC8vIEZJWE1FOiB3ZSBzaG91bGQgaGVyZSBnZXQgcmlkIG9mIHRoZSBjb21wb25lbnQgbmF0aXZlRWxlbWVudFxuXHRcdC8vIGFuZCB1c2UgYFtBcnJheS5mcm9tKGNvbXBvbmVudE5hdGl2ZUVsLmNoaWxkTm9kZXMpXWAgaW5zdGVhZCBhbmQgcmVtb3ZlIHRoZSBhYm92ZSBDU1MgY2xhc3MuXG5cdFx0cmV0dXJuIG5ldyBDb250ZW50UmVmKFxuXHRcdFx0W1xuXHRcdFx0XHRvcHRpb25zLmhlYWRlclNlbGVjdG9yXG5cdFx0XHRcdFx0PyBleHRyYWN0QW5kUmVtb3ZlTm9kZXNCeVNlbGVjdG9yKFxuXHRcdFx0XHRcdFx0XHRjb21wb25lbnROYXRpdmVFbCxcblx0XHRcdFx0XHRcdFx0b3B0aW9ucy5oZWFkZXJTZWxlY3RvclxuXHRcdFx0XHRcdCAgKVxuXHRcdFx0XHRcdDogW10sXG5cdFx0XHRcdGNvbXBvbmVudE5hdGl2ZUVsLmNoaWxkTm9kZXMgYXMgYW55LFxuXHRcdFx0XHRvcHRpb25zLmZvb3RlclNlbGVjdG9yXG5cdFx0XHRcdFx0PyBleHRyYWN0QW5kUmVtb3ZlTm9kZXNCeVNlbGVjdG9yKFxuXHRcdFx0XHRcdFx0XHRjb21wb25lbnROYXRpdmVFbCxcblx0XHRcdFx0XHRcdFx0b3B0aW9ucy5mb290ZXJTZWxlY3RvclxuXHRcdFx0XHRcdCAgKVxuXHRcdFx0XHRcdDogW11cblx0XHRcdF0sXG5cdFx0XHRjb21wb25lbnRSZWYuaG9zdFZpZXcsXG5cdFx0XHRjb21wb25lbnRSZWZcblx0XHQpO1xuXHR9XG5cblx0cHJpdmF0ZSBfc2V0QXJpYUhpZGRlbihlbGVtZW50OiBFbGVtZW50KSB7XG5cdFx0Y29uc3QgcGFyZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50O1xuXHRcdGlmIChwYXJlbnQgJiYgZWxlbWVudCAhPT0gdGhpcy5fZG9jdW1lbnQuYm9keSkge1xuXHRcdFx0QXJyYXkuZnJvbShwYXJlbnQuY2hpbGRyZW4pLmZvckVhY2goKHNpYmxpbmcpID0+IHtcblx0XHRcdFx0aWYgKHNpYmxpbmcgIT09IGVsZW1lbnQgJiYgc2libGluZy5ub2RlTmFtZSAhPT0gJ1NDUklQVCcpIHtcblx0XHRcdFx0XHR0aGlzLl9hcmlhSGlkZGVuVmFsdWVzLnNldChcblx0XHRcdFx0XHRcdHNpYmxpbmcsXG5cdFx0XHRcdFx0XHRzaWJsaW5nLmdldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0c2libGluZy5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgJ3RydWUnKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMuX3NldEFyaWFIaWRkZW4ocGFyZW50KTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIF9yZXZlcnRBcmlhSGlkZGVuKCkge1xuXHRcdHRoaXMuX2FyaWFIaWRkZW5WYWx1ZXMuZm9yRWFjaCgodmFsdWUsIGVsZW1lbnQpID0+IHtcblx0XHRcdGlmICh2YWx1ZSkge1xuXHRcdFx0XHRlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCB2YWx1ZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHR0aGlzLl9hcmlhSGlkZGVuVmFsdWVzLmNsZWFyKCk7XG5cdH1cblxuXHRwcml2YXRlIF9yZWdpc3Rlck1vZGFsUmVmKGh1Yk1vZGFsUmVmOiBIdWJNb2RhbFJlZikge1xuXHRcdGNvbnN0IHVucmVnaXN0ZXJNb2RhbFJlZiA9ICgpID0+IHtcblx0XHRcdGNvbnN0IGluZGV4ID0gdGhpcy5fbW9kYWxSZWZzLmluZGV4T2YoaHViTW9kYWxSZWYpO1xuXHRcdFx0aWYgKGluZGV4ID4gLTEpIHtcblx0XHRcdFx0dGhpcy5fbW9kYWxSZWZzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0XHRcdHRoaXMuX2FjdGl2ZUluc3RhbmNlcy5lbWl0KHRoaXMuX21vZGFsUmVmcyk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHR0aGlzLl9tb2RhbFJlZnMucHVzaChodWJNb2RhbFJlZik7XG5cdFx0dGhpcy5fYWN0aXZlSW5zdGFuY2VzLmVtaXQodGhpcy5fbW9kYWxSZWZzKTtcblx0XHRodWJNb2RhbFJlZi5yZXN1bHQudGhlbih1bnJlZ2lzdGVyTW9kYWxSZWYsIHVucmVnaXN0ZXJNb2RhbFJlZik7XG5cdH1cblxuXHRwcml2YXRlIF9yZWdpc3RlcldpbmRvd0NtcHQoaHViV2luZG93Q21wdDogQ29tcG9uZW50UmVmPEh1Yk1vZGFsV2luZG93Pikge1xuXHRcdHRoaXMuX3dpbmRvd0NtcHRzLnB1c2goaHViV2luZG93Q21wdCk7XG5cdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuXG5cdFx0aHViV2luZG93Q21wdC5vbkRlc3Ryb3koKCkgPT4ge1xuXHRcdFx0Y29uc3QgaW5kZXggPSB0aGlzLl93aW5kb3dDbXB0cy5pbmRleE9mKGh1YldpbmRvd0NtcHQpO1xuXHRcdFx0aWYgKGluZGV4ID4gLTEpIHtcblx0XHRcdFx0dGhpcy5fd2luZG93Q21wdHMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHRcdFx0dGhpcy5fYWN0aXZlV2luZG93Q21wdEhhc0NoYW5nZWQubmV4dCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEF0dGFjaGVzIGNsaWNrIGV2ZW50IGxpc3RlbmVycyB0byBlbGVtZW50cyB3aXRoaW4gYSBjb250YWluZXIgYmFzZWQgb24gYSBzcGVjaWZpZWQgZGlzbWlzcyBzZWxlY3RvciB0byBkaXNtaXNzIGEgbW9kYWwuXG5cdCAqXG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGNvbnRhaW5lciAtIFRoZSBgY29udGFpbmVyYCBwYXJhbWV0ZXIgaXMgYW4gSFRNTEVsZW1lbnQgdGhhdCByZXByZXNlbnRzIHRoZSBET00gZWxlbWVudCB3aGljaCBjb250YWlucyB0aGVcblx0ICogbW9kYWwgY29udGVudC5cblx0ICogQHBhcmFtIHtIdWJBY3RpdmVNb2RhbH0gY29udGV4dCAtIFRoZSBgY29udGV4dGAgcGFyYW1ldGVyIGluIHRoZSBgX2FkZERpc21pc3NFdmVudExpc3RlbmVyYCBmdW5jdGlvbiByZWZlcnMgdG8gdGhlIGFjdGl2ZSBtb2RhbFxuXHQgKiBpbnN0YW5jZSB0aGF0IGlzIGJlaW5nIGRpc3BsYXllZC4gSXQgaXMgdXNlZCB0byBjYWxsIHRoZSBgZGlzbWlzc2AgbWV0aG9kIG9uIHRoZSBtb2RhbCBpbnN0YW5jZSB3aGVuIGEgZGlzbWlzc2libGUgZWxlbWVudCBpc1xuXHQgKiBjbGlja2VkLlxuXHQgKiBAcGFyYW0ge0h1Yk1vZGFsT3B0aW9uc30gb3B0aW9ucyAtIFRoZSBgb3B0aW9uc2AgcGFyYW1ldGVyIGlzIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIG1vZGFsLiBJdFxuXHQgKiBtYXkgaW5jbHVkZSBwcm9wZXJ0aWVzIHN1Y2ggYXMgYGRpc21pc3NTZWxlY3RvcmAsIHdoaWNoIGlzIHVzZWQgdG8gc3BlY2lmeSBhIENTUyBzZWxlY3RvciBmb3IgZWxlbWVudHMgdGhhdCwgd2hlbiBjbGlja2VkLCB3aWxsXG5cdCAqIGRpc21pc3MgdGhlIG1vZGFsIGJ5IGNhbGxpbmcgdGhlIGBkaXNtaXNzYCBtZXRob2Qgb24gdGhlIGBjb250ZXh0YCBvYmplY3QuXG5cdCAqL1xuXHRwcml2YXRlIF9hZGREaXNtaXNzRXZlbnRMaXN0ZW5lcihcblx0XHRjb250YWluZXI6IEhUTUxFbGVtZW50LFxuXHRcdGNvbnRleHQ6IEh1YkFjdGl2ZU1vZGFsLFxuXHRcdG9wdGlvbnM6IEh1Yk1vZGFsT3B0aW9uc1xuXHQpIHtcblx0XHRpZiAob3B0aW9ucy5kaXNtaXNzU2VsZWN0b3IpIHtcblx0XHRcdGNvbnN0IGRpc21pc3NhYWJsZTogTm9kZUxpc3RPZjxFbGVtZW50PiA9XG5cdFx0XHRcdGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKG9wdGlvbnMuZGlzbWlzc1NlbGVjdG9yKTtcblx0XHRcdGZvciAoY29uc3QgaXRlbSBvZiBBcnJheS5mcm9tKGRpc21pc3NhYWJsZSkpIHtcblx0XHRcdFx0aXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IGNvbnRleHQuZGlzbWlzcygpKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBFeHRyYWN0cyBjaGlsZCBub2RlcyBtYXRjaGluZyBhIHNlbGVjdG9yIGZyb20gYSBjb250YWluZXIgZWxlbWVudCwgcmVtb3ZlcyB0aG9zZSBub2RlcyBmcm9tIHRoZSBET00sIGFuZCByZXR1cm5zIHRoZW0gYXMgYW4gYXJyYXkuXG4gKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gY29udGFpbmVyIC0gVGhlIGBjb250YWluZXJgIHBhcmFtZXRlciBpbiB0aGUgYGV4dHJhY3RBbmRSZW1vdmVOb2Rlc0J5U2VsZWN0b3JgIGZ1bmN0aW9uIGlzIGFuIEhUTUxFbGVtZW50XG4gKiB0aGF0IHJlcHJlc2VudHMgdGhlIHBhcmVudCBlbGVtZW50IHdpdGhpbiB3aGljaCB3ZSB3YW50IHRvIHNlYXJjaCBmb3Igbm9kZXMgbWF0Y2hpbmcgYSBzcGVjaWZpYyBzZWxlY3RvciBhbmQgcmVtb3ZlIHRoZW0uXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3IgLSBUaGUgYHNlbGVjdG9yYCBwYXJhbWV0ZXIgaW4gdGhlIGBleHRyYWN0QW5kUmVtb3ZlTm9kZXNCeVNlbGVjdG9yYCBmdW5jdGlvbiBpcyBhIHN0cmluZyB0aGF0XG4gKiByZXByZXNlbnRzIGEgQ1NTIHNlbGVjdG9yLiBUaGlzIHNlbGVjdG9yIGlzIHVzZWQgdG8gcXVlcnkgYW5kIHNlbGVjdCBzcGVjaWZpYyBlbGVtZW50cyB3aXRoaW4gdGhlIGBjb250YWluZXJgIEhUTUxFbGVtZW50LlxuICpcbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIG5vZGVzIHRoYXQgd2VyZSBleHRyYWN0ZWQgZnJvbSB0aGUgY29udGFpbmVyIGVsZW1lbnQgYmFzZWQgb24gdGhlIHByb3ZpZGVkIHNlbGVjdG9yLCBhbmQgdGhlbiByZW1vdmVzIHRob3NlXG4gKiBub2RlcyBmcm9tIHRoZSBET00uXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RBbmRSZW1vdmVOb2Rlc0J5U2VsZWN0b3IoXG5cdGNvbnRhaW5lcjogSFRNTEVsZW1lbnQsXG5cdHNlbGVjdG9yOiBzdHJpbmdcbik6IEFycmF5PE5vZGU+IHtcblx0bGV0IGNvbnRhaW5lck5vZGVzID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuXG5cdGNvbnN0IG5vZGVzID0gQXJyYXkuZnJvbShjb250YWluZXJOb2RlcykucmVkdWNlKChhY2MsIGMpID0+IHtcblx0XHRyZXR1cm4gWy4uLmFjYywgLi4uQXJyYXkuZnJvbShjLmNoaWxkTm9kZXMpXTtcblx0fSwgW10gYXMgQXJyYXk8Tm9kZT4pO1xuXG5cdC8vIFNlbGVjY2lvbmEgbG9zIG5vZG9zIGRlbnRybyBkZWwgY29udGVuZWRvciBxdWUgY29pbmNpZGFuIGNvbiBlbCBzZWxlY3RvclxuXHRjb25zdCBub2Rlc1RvUmVtb3ZlID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGw8SFRNTEVsZW1lbnQ+KHNlbGVjdG9yKTtcblxuXHQvLyBDb252ZXJ0aXIgTm9kZUxpc3QgYSBhcnJheSB5IGVsaW1pbmFyIGNhZGEgbm9kbyBkZWwgRE9NXG5cdEFycmF5LmZyb20obm9kZXNUb1JlbW92ZSkuZm9yRWFjaCgobm9kZSkgPT4gbm9kZS5yZW1vdmUoKSk7XG5cdHJldHVybiBub2Rlcztcbn1cbiJdfQ==
|