@scion/components 15.0.2 → 16.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dimension/dimension.directive.d.ts +2 -2
  2. package/dimension/dimension.module.d.ts +1 -2
  3. package/esm2022/dimension/dimension.directive.mjs +85 -0
  4. package/esm2022/dimension/dimension.module.mjs +35 -0
  5. package/esm2022/sashbox/element-ref.directive.mjs +32 -0
  6. package/esm2022/sashbox/public_api.mjs +18 -0
  7. package/esm2022/sashbox/sash-initializer.directive.mjs +36 -0
  8. package/esm2022/sashbox/sash.directive.mjs +146 -0
  9. package/esm2022/sashbox/sashbox.component.mjs +286 -0
  10. package/esm2022/sashbox/sashbox.module.mjs +56 -0
  11. package/esm2022/splitter/public_api.mjs +17 -0
  12. package/esm2022/splitter/splitter.component.mjs +226 -0
  13. package/esm2022/splitter/splitter.module.mjs +39 -0
  14. package/esm2022/throbber/ellipsis-throbber/ellipsis-throbber.component.mjs +26 -0
  15. package/esm2022/throbber/ripple-throbber/ripple-throbber.component.mjs +26 -0
  16. package/esm2022/throbber/roller-throbber/roller-throbber.component.mjs +26 -0
  17. package/esm2022/throbber/spinner-throbber/spinner-throbber.component.mjs +27 -0
  18. package/esm2022/throbber/throbber.component.mjs +76 -0
  19. package/esm2022/throbber/throbber.module.mjs +33 -0
  20. package/esm2022/viewport/native-scrollbar-track-size-provider.service.mjs +113 -0
  21. package/esm2022/viewport/public_api.mjs +19 -0
  22. package/esm2022/viewport/scrollable.directive.mjs +95 -0
  23. package/esm2022/viewport/scrollbar/scrollbar.component.mjs +323 -0
  24. package/esm2022/viewport/viewport.component.mjs +289 -0
  25. package/esm2022/viewport/viewport.module.mjs +43 -0
  26. package/{fesm2015 → fesm2022}/scion-components-dimension.mjs +13 -11
  27. package/fesm2022/scion-components-dimension.mjs.map +1 -0
  28. package/{fesm2020 → fesm2022}/scion-components-sashbox.mjs +69 -61
  29. package/fesm2022/scion-components-sashbox.mjs.map +1 -0
  30. package/{fesm2020 → fesm2022}/scion-components-splitter.mjs +25 -25
  31. package/fesm2022/scion-components-splitter.mjs.map +1 -0
  32. package/fesm2022/scion-components-throbber.mjs +215 -0
  33. package/fesm2022/scion-components-throbber.mjs.map +1 -0
  34. package/{fesm2020 → fesm2022}/scion-components-viewport.mjs +164 -161
  35. package/fesm2022/scion-components-viewport.mjs.map +1 -0
  36. package/package.json +27 -43
  37. package/sashbox/element-ref.directive.d.ts +1 -1
  38. package/sashbox/public_api.d.ts +3 -3
  39. package/sashbox/sash-initializer.directive.d.ts +1 -1
  40. package/sashbox/sash.directive.d.ts +2 -2
  41. package/sashbox/sashbox.component.d.ts +1 -3
  42. package/sashbox/sashbox.module.d.ts +1 -5
  43. package/splitter/public_api.d.ts +2 -2
  44. package/splitter/splitter.component.d.ts +1 -3
  45. package/splitter/splitter.module.d.ts +1 -2
  46. package/throbber/ellipsis-throbber/ellipsis-throbber.component.d.ts +1 -1
  47. package/throbber/ripple-throbber/ripple-throbber.component.d.ts +1 -1
  48. package/throbber/roller-throbber/roller-throbber.component.d.ts +1 -1
  49. package/throbber/spinner-throbber/spinner-throbber.component.d.ts +1 -1
  50. package/throbber/throbber.component.d.ts +1 -1
  51. package/throbber/throbber.module.d.ts +1 -6
  52. package/viewport/native-scrollbar-track-size-provider.service.d.ts +0 -2
  53. package/viewport/public_api.d.ts +3 -4
  54. package/viewport/scrollable.directive.d.ts +1 -1
  55. package/viewport/scrollbar/scrollbar.component.d.ts +2 -2
  56. package/viewport/viewport.component.d.ts +2 -2
  57. package/viewport/viewport.module.d.ts +1 -3
  58. package/esm2020/dimension/dimension.directive.mjs +0 -83
  59. package/esm2020/dimension/dimension.module.mjs +0 -38
  60. package/esm2020/sashbox/element-ref.directive.mjs +0 -27
  61. package/esm2020/sashbox/public_api.mjs +0 -18
  62. package/esm2020/sashbox/sash-initializer.directive.mjs +0 -32
  63. package/esm2020/sashbox/sash.directive.mjs +0 -144
  64. package/esm2020/sashbox/sashbox.component.mjs +0 -278
  65. package/esm2020/sashbox/sashbox.module.mjs +0 -69
  66. package/esm2020/splitter/public_api.mjs +0 -17
  67. package/esm2020/splitter/splitter.component.mjs +0 -227
  68. package/esm2020/splitter/splitter.module.mjs +0 -42
  69. package/esm2020/throbber/ellipsis-throbber/ellipsis-throbber.component.mjs +0 -25
  70. package/esm2020/throbber/ripple-throbber/ripple-throbber.component.mjs +0 -25
  71. package/esm2020/throbber/roller-throbber/roller-throbber.component.mjs +0 -25
  72. package/esm2020/throbber/spinner-throbber/spinner-throbber.component.mjs +0 -26
  73. package/esm2020/throbber/throbber.component.mjs +0 -67
  74. package/esm2020/throbber/throbber.module.mjs +0 -48
  75. package/esm2020/viewport/native-scrollbar-track-size-provider.service.mjs +0 -114
  76. package/esm2020/viewport/public_api.mjs +0 -20
  77. package/esm2020/viewport/scrollable.directive.mjs +0 -93
  78. package/esm2020/viewport/scrollbar/scrollbar.component.mjs +0 -322
  79. package/esm2020/viewport/viewport.component.mjs +0 -281
  80. package/esm2020/viewport/viewport.module.mjs +0 -50
  81. package/fesm2015/scion-components-dimension.mjs.map +0 -1
  82. package/fesm2015/scion-components-sashbox.mjs +0 -554
  83. package/fesm2015/scion-components-sashbox.mjs.map +0 -1
  84. package/fesm2015/scion-components-splitter.mjs +0 -284
  85. package/fesm2015/scion-components-splitter.mjs.map +0 -1
  86. package/fesm2015/scion-components-throbber.mjs +0 -214
  87. package/fesm2015/scion-components-throbber.mjs.map +0 -1
  88. package/fesm2015/scion-components-viewport.mjs +0 -861
  89. package/fesm2015/scion-components-viewport.mjs.map +0 -1
  90. package/fesm2015/scion-components.mjs +0 -4
  91. package/fesm2015/scion-components.mjs.map +0 -1
  92. package/fesm2020/scion-components-dimension.mjs +0 -135
  93. package/fesm2020/scion-components-dimension.mjs.map +0 -1
  94. package/fesm2020/scion-components-sashbox.mjs.map +0 -1
  95. package/fesm2020/scion-components-splitter.mjs.map +0 -1
  96. package/fesm2020/scion-components-throbber.mjs +0 -214
  97. package/fesm2020/scion-components-throbber.mjs.map +0 -1
  98. package/fesm2020/scion-components-viewport.mjs.map +0 -1
  99. /package/{esm2020 → esm2022}/dimension/public_api.mjs +0 -0
  100. /package/{esm2020 → esm2022}/dimension/scion-components-dimension.mjs +0 -0
  101. /package/{esm2020 → esm2022}/public-api.mjs +0 -0
  102. /package/{esm2020 → esm2022}/sashbox/sashbox-accessor.mjs +0 -0
  103. /package/{esm2020 → esm2022}/sashbox/scion-components-sashbox.mjs +0 -0
  104. /package/{esm2020 → esm2022}/scion-components.mjs +0 -0
  105. /package/{esm2020 → esm2022}/splitter/scion-components-splitter.mjs +0 -0
  106. /package/{esm2020 → esm2022}/throbber/public_api.mjs +0 -0
  107. /package/{esm2020 → esm2022}/throbber/scion-components-throbber.mjs +0 -0
  108. /package/{esm2020 → esm2022}/viewport/scion-components-viewport.mjs +0 -0
  109. /package/{fesm2020 → fesm2022}/scion-components.mjs +0 -0
  110. /package/{fesm2020 → fesm2022}/scion-components.mjs.map +0 -0
@@ -0,0 +1,323 @@
1
+ /*
2
+ * Copyright (c) 2018-2019 Swiss Federal Railways
3
+ *
4
+ * This program and the accompanying materials are made
5
+ * available under the terms of the Eclipse Public License 2.0
6
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
7
+ *
8
+ * SPDX-License-Identifier: EPL-2.0
9
+ */
10
+ import { DOCUMENT } from '@angular/common';
11
+ import { ChangeDetectionStrategy, Component, HostBinding, Inject, Input, NgZone, ViewChild } from '@angular/core';
12
+ import { fromEvent, merge, of, Subject, timer } from 'rxjs';
13
+ import { debounceTime, first, map, startWith, switchMap, takeUntil, takeWhile, withLatestFrom } from 'rxjs/operators';
14
+ import { fromDimension$, fromMutation$ } from '@scion/toolkit/observable';
15
+ import { filterArray, subscribeInside } from '@scion/toolkit/operators';
16
+ import * as i0 from "@angular/core";
17
+ /**
18
+ * Renders a vertical or horizontal scrollbar.
19
+ *
20
+ * The scrollbar features the following functionality:
21
+ * - allows to move the thumb by mouse or touch
22
+ * - enlarges the thumb if the mouse pointer is near the thumb
23
+ * - allows paging on mousedown on the scroll track
24
+ *
25
+ * ### CSS styling:
26
+ *
27
+ * You can override the following CSS variables:
28
+ *
29
+ * - sci-scrollbar-color: Sets the color of the scrollbar (by default, uses `rgb(78, 78, 78)`).
30
+ *
31
+ * Example:
32
+ *
33
+ * ```css
34
+ *
35
+ * sci-scrollbar {
36
+ * --sci-scrollbar-color: blue;
37
+ * }
38
+ * ```
39
+ */
40
+ class SciScrollbarComponent {
41
+ /**
42
+ * Timeout for debouncing viewport resize events that trigger the scroll position computation.
43
+ *
44
+ * Debouncing is particularly important in the context of Angular animations, since they continuously
45
+ * trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
46
+ * expands a panel that contains a viewport.
47
+ *
48
+ * @internal
49
+ */
50
+ static { this.VIEWPORT_RESIZE_DEBOUNCE_TIME = 50; }
51
+ get vertical() {
52
+ return this.direction === 'vscroll';
53
+ }
54
+ get horizontal() {
55
+ return this.direction === 'hscroll';
56
+ }
57
+ get scrolling() {
58
+ return this._lastDragPosition !== null;
59
+ }
60
+ /**
61
+ * The viewport to provide scrollbars for.
62
+ */
63
+ set setViewport(viewport) {
64
+ this._viewport = viewport;
65
+ this._viewportChange$.next();
66
+ }
67
+ constructor(_host, _document, _zone) {
68
+ this._host = _host;
69
+ this._document = _document;
70
+ this._zone = _zone;
71
+ this._destroy$ = new Subject();
72
+ this._viewportChange$ = new Subject();
73
+ this._lastDragPosition = null;
74
+ this._overflow = false;
75
+ this._thumbSizeFr = 0;
76
+ this._thumbPositionFr = 0;
77
+ /**
78
+ * Specifies the direction of the scrollbar.
79
+ *
80
+ * By default, if not specified, renders a vertical scrollbar.
81
+ */
82
+ this.direction = 'vscroll';
83
+ this._viewportChange$
84
+ .pipe(switchMap(() => {
85
+ if (!this._viewport) {
86
+ return of(undefined);
87
+ }
88
+ return merge(this.viewportScrollChange$(), this.viewportDimensionChange$({ debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME }), this.viewportClientDimensionChange$({ debounceTime: SciScrollbarComponent.VIEWPORT_RESIZE_DEBOUNCE_TIME }));
89
+ }), subscribeInside(continueFn => this._zone.runOutsideAngular(continueFn)), takeUntil(this._destroy$))
90
+ .subscribe(() => {
91
+ if (this._viewport) {
92
+ this.renderScrollPosition();
93
+ }
94
+ else {
95
+ this.unsetScrollPosition();
96
+ }
97
+ });
98
+ }
99
+ /**
100
+ * Computes the scroll position and updates CSS variables to render the scroll position in the UI.
101
+ */
102
+ renderScrollPosition() {
103
+ NgZone.assertNotInAngularZone();
104
+ const viewportSize = this.viewportSize;
105
+ const viewportClientSize = this.viewportClientSize;
106
+ const thumbPositionFr = this.scrollPosition / viewportClientSize;
107
+ const thumbSizeFr = viewportSize / viewportClientSize;
108
+ const overflow = viewportClientSize > viewportSize;
109
+ if (thumbPositionFr !== this._thumbPositionFr || thumbSizeFr !== this._thumbSizeFr) {
110
+ this._thumbPositionFr = thumbPositionFr;
111
+ this._thumbSizeFr = thumbSizeFr;
112
+ this.setCssVariable('--ɵsci-scrollbar-thumb-position-fr', thumbPositionFr);
113
+ this.setCssVariable('--ɵsci-scrollbar-thumb-size-fr', thumbSizeFr);
114
+ }
115
+ if (overflow !== this._overflow) {
116
+ this._overflow = overflow;
117
+ overflow ? this._host.nativeElement.classList.add('overflow') : this._host.nativeElement.classList.remove('overflow');
118
+ }
119
+ }
120
+ /**
121
+ * Clears CSS variables used for rendering the scroll position in the UI.
122
+ */
123
+ unsetScrollPosition() {
124
+ NgZone.assertNotInAngularZone();
125
+ this._thumbPositionFr = 0;
126
+ this._thumbSizeFr = 0;
127
+ this._overflow = false;
128
+ this.setCssVariable('--ɵsci-scrollbar-thumb-position-fr', 0);
129
+ this.setCssVariable('--ɵsci-scrollbar-thumb-size-fr', 0);
130
+ this._host.nativeElement.classList.remove('overflow');
131
+ }
132
+ /* @docs-private */
133
+ onTouchStart(event) {
134
+ event.preventDefault();
135
+ this._lastDragPosition = this.vertical ? event.touches[0].screenY : event.touches[0].screenX;
136
+ }
137
+ /* @docs-private */
138
+ onTouchMove(event) {
139
+ event.preventDefault();
140
+ const newDragPositionPx = this.vertical ? event.touches[0].screenY : event.touches[0].screenX;
141
+ const scrollbarPanPx = newDragPositionPx - this._lastDragPosition;
142
+ const viewportPanPx = this.toViewportPanPx(scrollbarPanPx);
143
+ this._lastDragPosition = newDragPositionPx;
144
+ this.moveViewportClient(viewportPanPx);
145
+ }
146
+ /* @docs-private */
147
+ onTouchEnd(event) {
148
+ event.preventDefault();
149
+ this._lastDragPosition = null;
150
+ }
151
+ /* @docs-private */
152
+ onMouseDown(mousedownEvent) {
153
+ if (mousedownEvent.button !== 0) {
154
+ return;
155
+ }
156
+ mousedownEvent.preventDefault();
157
+ this._lastDragPosition = this.vertical ? mousedownEvent.screenY : mousedownEvent.screenX;
158
+ // Listen for 'mousemove' events
159
+ this._zone.runOutsideAngular(() => {
160
+ const mousemoveListener = merge(fromEvent(this._document, 'mousemove'), fromEvent(this._document, 'sci-mousemove'))
161
+ .pipe(takeUntil(this._destroy$))
162
+ .subscribe(mousemoveEvent => {
163
+ mousemoveEvent.preventDefault();
164
+ const newDragPositionPx = this.vertical ? mousemoveEvent.screenY : mousemoveEvent.screenX;
165
+ const scrollbarPanPx = newDragPositionPx - this._lastDragPosition;
166
+ const viewportPanPx = this.toViewportPanPx(scrollbarPanPx);
167
+ this._lastDragPosition = newDragPositionPx;
168
+ this.moveViewportClient(viewportPanPx);
169
+ });
170
+ // Listen for 'mouseup' events; use 'capture phase' and 'stop propagation' to not close overlays
171
+ merge(fromEvent(this._document, 'mouseup', { capture: true }), fromEvent(this._document, 'sci-mouseup'))
172
+ .pipe(first(), takeUntil(this._destroy$))
173
+ .subscribe(mouseupEvent => {
174
+ mouseupEvent.stopPropagation();
175
+ mousemoveListener.unsubscribe();
176
+ this._lastDragPosition = null;
177
+ });
178
+ });
179
+ }
180
+ /* @docs-private */
181
+ onScrollTrackMouseDown(event, direction) {
182
+ const signum = (direction === 'up' ? -1 : +1);
183
+ this.scrollWhileMouseDown(this.toViewportPanPx(signum * this.thumbSize), event);
184
+ }
185
+ /**
186
+ * Projects the given scrollbar scroll pixels into viewport scroll pixels.
187
+ */
188
+ toViewportPanPx(scrollbarPanPx) {
189
+ const scrollRangePx = this.trackSize - this.thumbSize;
190
+ const scrollRatio = scrollbarPanPx / scrollRangePx;
191
+ return scrollRatio * (this.viewportClientSize - this.viewportSize);
192
+ }
193
+ /**
194
+ * Moves the viewport client by the specified numbers of pixels.
195
+ */
196
+ moveViewportClient(viewportPanPx) {
197
+ if (this.vertical) {
198
+ this._viewport.scrollTop += viewportPanPx;
199
+ }
200
+ else {
201
+ this._viewport.scrollLeft += viewportPanPx;
202
+ }
203
+ }
204
+ /**
205
+ * Indicates if the content overflows.
206
+ */
207
+ get overflow() {
208
+ return this._overflow;
209
+ }
210
+ /**
211
+ * Scrolls continuously while holding the mouse pressed, or until the mouse leaves the scrolltrack.
212
+ */
213
+ scrollWhileMouseDown(viewportScrollPx, mousedownEvent) {
214
+ // The `EventTarget` type of `Event.target` is not yet compatible with `FromEventTarget` used in `fromEvent`.
215
+ // This will be fixed in rxjs version 7.0.0. Refer to https://github.com/ReactiveX/rxjs/commit/5f022d784570684632e6fd5ae247fc259ee34c4b
216
+ // for more details.
217
+ const scrollTrackElement = mousedownEvent.target;
218
+ // scroll continuously every 50ms after an initial delay of 250ms
219
+ timer(250, 50)
220
+ .pipe(
221
+ // continue chain with latest mouse event
222
+ withLatestFrom(merge(of(mousedownEvent), fromEvent(scrollTrackElement, 'mousemove')), (tick, event) => event),
223
+ // start immediately
224
+ startWith(mousedownEvent),
225
+ // stop scrolling if the thumb hits the mouse pointer position
226
+ takeWhile((event) => scrollTrackElement === this._document.elementFromPoint(event.clientX, event.clientY)), debounceTime(10),
227
+ // stop scrolling on mouseout or mouseup
228
+ takeUntil(merge(fromEvent(scrollTrackElement, 'mouseout'), fromEvent(scrollTrackElement, 'mouseup'))))
229
+ .subscribe(() => {
230
+ this.moveViewportClient(viewportScrollPx);
231
+ });
232
+ }
233
+ /**
234
+ * Emits whenever the viewport scrolls.
235
+ */
236
+ viewportScrollChange$() {
237
+ return fromEvent(this._viewport, 'scroll', { passive: true }).pipe(map(() => undefined));
238
+ }
239
+ /**
240
+ * Emits on subscription, and then each time the size of the viewport changes.
241
+ */
242
+ viewportDimensionChange$(options) {
243
+ return fromDimension$(this._viewport)
244
+ .pipe(
245
+ // Debouncing is particularly important in the context of Angular animations, since they continuously
246
+ // trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
247
+ // expands a panel that contains a viewport.
248
+ debounceTime(options.debounceTime), map(() => undefined));
249
+ }
250
+ /**
251
+ * Emits on subscription, and then each time the size or style property of the viewport client changes.
252
+ */
253
+ viewportClientDimensionChange$(options) {
254
+ return this.children$(this._viewport)
255
+ .pipe(switchMap(children => merge(...children.map(child => merge(fromDimension$(child),
256
+ // Observe style mutations since some transformations change the scroll position without necessarily triggering a dimension change,
257
+ // e.g., `scale` or `translate` used by some virtual scroll implementations
258
+ fromMutation$(child, { subtree: false, childList: false, attributeFilter: ['style'] }))))),
259
+ // Debouncing is particularly important in the context of Angular animations, since they continuously
260
+ // trigger resize events. Debouncing prevents the scrollbar from flickering, for example, when the user
261
+ // expands a panel that contains a viewport.
262
+ debounceTime(options.debounceTime), map(() => undefined));
263
+ }
264
+ /**
265
+ * Emits the children of the passed element, and then each time child elements are added or removed.
266
+ */
267
+ children$(element) {
268
+ return fromMutation$(element, { subtree: false, childList: true })
269
+ .pipe(startWith(undefined), map(() => Array.from(element.children)), filterArray((child) => child instanceof HTMLElement));
270
+ }
271
+ setCssVariable(key, value) {
272
+ this._host.nativeElement.style.setProperty(key, value);
273
+ }
274
+ get viewportSize() {
275
+ return this._viewport ? (this.vertical ? this._viewport.clientHeight : this._viewport.clientWidth) : 0;
276
+ }
277
+ get viewportClientSize() {
278
+ return this._viewport ? (this.vertical ? this._viewport.scrollHeight : this._viewport.scrollWidth) : 0;
279
+ }
280
+ get scrollPosition() {
281
+ return this._viewport ? (this.vertical ? this._viewport.scrollTop : this._viewport.scrollLeft) : 0;
282
+ }
283
+ get thumbSize() {
284
+ const thumbElement = this.thumbElement.nativeElement;
285
+ return this.vertical ? thumbElement.clientHeight : thumbElement.clientWidth;
286
+ }
287
+ get trackSize() {
288
+ const trackElement = this._host.nativeElement;
289
+ return this.vertical ? trackElement.clientHeight : trackElement.clientWidth;
290
+ }
291
+ /* @docs-private */
292
+ ngOnDestroy() {
293
+ this._destroy$.next();
294
+ }
295
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: SciScrollbarComponent, deps: [{ token: i0.ElementRef }, { token: DOCUMENT }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
296
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: SciScrollbarComponent, isStandalone: true, selector: "sci-scrollbar", inputs: { direction: "direction", setViewport: ["viewport", "setViewport"] }, host: { properties: { "class.vertical": "this.vertical", "class.horizontal": "this.horizontal", "class.scrolling": "this.scrolling" } }, viewQueries: [{ propertyName: "thumbElement", first: true, predicate: ["thumb_handle"], descendants: true, static: true }], ngImport: i0, template: "<!-- scrolltrack to move the viewport client upwards (paging) -->\n<div class=\"scrolltrack-start\" (mousedown)=\"onScrollTrackMouseDown($event, 'up')\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical\"\n [class.horizontal]=\"horizontal\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n (touchcancel)=\"onTouchEnd($event)\">\n <div class=\"thumb\"\n [class.vertical]=\"vertical\"\n [class.horizontal]=\"horizontal\">\n </div>\n</div>\n\n<!-- scrolltrack to move the viewport client downwards (paging) -->\n<div class=\"scrolltrack-end\" (mousedown)=\"onScrollTrackMouseDown($event, 'down')\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;border:2px solid transparent;box-sizing:border-box;--sci-scrollbar-color: rgb(78, 78, 78);--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column}:host.horizontal{flex-direction:row}:host>div.scrolltrack-start{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host>div.thumb-handle{flex-basis:20px;display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column}:host>div.thumb-handle.horizontal{flex-direction:row}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack-end{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}:host-context:not(.overflow){display:none}:host-context:hover>div.thumb-handle>div.thumb,:host-context(.scrolling)>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host-context:hover>div.thumb-handle>div.thumb.vertical,:host-context(.scrolling)>div.thumb-handle>div.thumb.vertical{width:100%}:host-context:hover>div.thumb-handle>div.thumb.horizontal,:host-context(.scrolling)>div.thumb-handle>div.thumb.horizontal{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
297
+ }
298
+ export { SciScrollbarComponent };
299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: SciScrollbarComponent, decorators: [{
300
+ type: Component,
301
+ args: [{ selector: 'sci-scrollbar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<!-- scrolltrack to move the viewport client upwards (paging) -->\n<div class=\"scrolltrack-start\" (mousedown)=\"onScrollTrackMouseDown($event, 'up')\"></div>\n\n<!-- scrollthumb -->\n<div #thumb_handle\n class=\"thumb-handle\"\n [class.vertical]=\"vertical\"\n [class.horizontal]=\"horizontal\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n (touchcancel)=\"onTouchEnd($event)\">\n <div class=\"thumb\"\n [class.vertical]=\"vertical\"\n [class.horizontal]=\"horizontal\">\n </div>\n</div>\n\n<!-- scrolltrack to move the viewport client downwards (paging) -->\n<div class=\"scrolltrack-end\" (mousedown)=\"onScrollTrackMouseDown($event, 'down')\"></div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;border:2px solid transparent;box-sizing:border-box;--sci-scrollbar-color: rgb(78, 78, 78);--\\275sci-scrollbar-thumb-position-fr: 0;--\\275sci-scrollbar-thumb-size-fr: 0}:host.vertical{flex-direction:column}:host.horizontal{flex-direction:row}:host>div.scrolltrack-start{flex-grow:var(--\\275sci-scrollbar-thumb-position-fr)}:host>div.thumb-handle{flex-basis:20px;display:flex;flex-grow:var(--\\275sci-scrollbar-thumb-size-fr);align-items:center}:host>div.thumb-handle.vertical{flex-direction:column}:host>div.thumb-handle.horizontal{flex-direction:row}:host>div.thumb-handle>div.thumb{flex:auto;border-radius:4px;background-color:var(--sci-scrollbar-color);opacity:.4;transition-duration:125ms;transition-property:width,height;transition-timing-function:ease-out}:host>div.thumb-handle>div.thumb.vertical{width:60%}:host>div.thumb-handle>div.thumb.horizontal{height:60%}:host>div.scrolltrack-end{flex-grow:calc(1 - (var(--\\275sci-scrollbar-thumb-position-fr) + var(--\\275sci-scrollbar-thumb-size-fr)))}:host-context:not(.overflow){display:none}:host-context:hover>div.thumb-handle>div.thumb,:host-context(.scrolling)>div.thumb-handle>div.thumb{background-color:var(--sci-scrollbar-color);opacity:.75}:host-context:hover>div.thumb-handle>div.thumb.vertical,:host-context(.scrolling)>div.thumb-handle>div.thumb.vertical{width:100%}:host-context:hover>div.thumb-handle>div.thumb.horizontal,:host-context(.scrolling)>div.thumb-handle>div.thumb.horizontal{height:100%}\n"] }]
302
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: Document, decorators: [{
303
+ type: Inject,
304
+ args: [DOCUMENT]
305
+ }] }, { type: i0.NgZone }]; }, propDecorators: { thumbElement: [{
306
+ type: ViewChild,
307
+ args: ['thumb_handle', { static: true }]
308
+ }], vertical: [{
309
+ type: HostBinding,
310
+ args: ['class.vertical']
311
+ }], horizontal: [{
312
+ type: HostBinding,
313
+ args: ['class.horizontal']
314
+ }], scrolling: [{
315
+ type: HostBinding,
316
+ args: ['class.scrolling']
317
+ }], direction: [{
318
+ type: Input
319
+ }], setViewport: [{
320
+ type: Input,
321
+ args: [{ alias: 'viewport', required: true }]
322
+ }] } });
323
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3NjaW9uL2NvbXBvbmVudHMvdmlld3BvcnQvc3JjL3Njcm9sbGJhci9zY3JvbGxiYXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2Npb24vY29tcG9uZW50cy92aWV3cG9ydC9zcmMvc2Nyb2xsYmFyL3Njcm9sbGJhci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsU0FBUyxFQUFjLFdBQVcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBYSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDdkksT0FBTyxFQUFDLFNBQVMsRUFBRSxLQUFLLEVBQWMsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDdEUsT0FBTyxFQUFDLFlBQVksRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwSCxPQUFPLEVBQUMsY0FBYyxFQUFFLGFBQWEsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQ3hFLE9BQU8sRUFBQyxXQUFXLEVBQUUsZUFBZSxFQUFDLE1BQU0sMEJBQTBCLENBQUM7O0FBRXRFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFPYSxxQkFBcUI7SUFFaEM7Ozs7Ozs7O09BUUc7YUFDb0Isa0NBQTZCLEdBQUcsRUFBRSxBQUFMLENBQU07SUFlMUQsSUFDVyxRQUFRO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLENB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QUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUM7SUFDOUUsQ0FBQztJQUVELG1CQUFtQjtJQUNaLFdBQVc7UUFDaEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN4QixDQUFDOzhHQW5VVSxxQkFBcUIsNENBMkRaLFFBQVE7a0dBM0RqQixxQkFBcUIsNFpDL0NsQyw0eUJBcUJBOztTRDBCYSxxQkFBcUI7MkZBQXJCLHFCQUFxQjtrQkFQakMsU0FBUzsrQkFDRSxlQUFlLG1CQUdSLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSTs7MEJBNkRILE1BQU07MkJBQUMsUUFBUTtpRUFuQ3JCLFlBQVk7c0JBRGxCLFNBQVM7dUJBQUMsY0FBYyxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQztnQkFJOUIsUUFBUTtzQkFEbEIsV0FBVzt1QkFBQyxnQkFBZ0I7Z0JBTWxCLFVBQVU7c0JBRHBCLFdBQVc7dUJBQUMsa0JBQWtCO2dCQU1wQixTQUFTO3NCQURuQixXQUFXO3VCQUFDLGlCQUFpQjtnQkFXdkIsU0FBUztzQkFEZixLQUFLO2dCQU9LLFdBQVc7c0JBRHJCLEtBQUs7dUJBQUMsRUFBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE4LTIwMTkgU3dpc3MgRmVkZXJhbCBSYWlsd2F5c1xuICpcbiAqIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMgYXJlIG1hZGVcbiAqIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgMi4wXG4gKiB3aGljaCBpcyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvZXBsLTIuMC9cbiAqXG4gKiAgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEVQTC0yLjBcbiAqL1xuXG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0QmluZGluZywgSW5qZWN0LCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIFZpZXdDaGlsZH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge2Zyb21FdmVudCwgbWVyZ2UsIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0LCB0aW1lcn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2RlYm91bmNlVGltZSwgZmlyc3QsIG1hcCwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCwgdGFrZVdoaWxlLCB3aXRoTGF0ZXN0RnJvbX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtmcm9tRGltZW5zaW9uJCwgZnJvbU11dGF0aW9uJH0gZnJvbSAnQHNjaW9uL3Rvb2xraXQvb2JzZXJ2YWJsZSc7XG5pbXBvcnQge2ZpbHRlckFycmF5LCBzdWJzY3JpYmVJbnNpZGV9IGZyb20gJ0BzY2lvbi90b29sa2l0L29wZXJhdG9ycyc7XG5cbi8qKlxuICogUmVuZGVycyBhIHZlcnRpY2FsIG9yIGhvcml6b250YWwgc2Nyb2xsYmFyLlxuICpcbiAqIFRoZSBzY3JvbGxiYXIgZmVhdHVyZXMgdGhlIGZvbGxvd2luZyBmdW5jdGlvbmFsaXR5OlxuICogLSBhbGxvd3MgdG8gbW92ZSB0aGUgdGh1bWIgYnkgbW91c2Ugb3IgdG91Y2hcbiAqIC0gZW5sYXJnZXMgdGhlIHRodW1iIGlmIHRoZSBtb3VzZSBwb2ludGVyIGlzIG5lYXIgdGhlIHRodW1iXG4gKiAtIGFsbG93cyBwYWdpbmcgb24gbW91c2Vkb3duIG9uIHRoZSBzY3JvbGwgdHJhY2tcbiAqXG4gKiAjIyMgQ1NTIHN0eWxpbmc6XG4gKlxuICogWW91IGNhbiBvdmVycmlkZSB0aGUgZm9sbG93aW5nIENTUyB2YXJpYWJsZXM6XG4gKlxuICogLSBzY2ktc2Nyb2xsYmFyLWNvbG9yOiAgICBTZXRzIHRoZSBjb2xvciBvZiB0aGUgc2Nyb2xsYmFyIChieSBkZWZhdWx0LCB1c2VzIGByZ2IoNzgsIDc4LCA3OClgKS5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqIGBgYGNzc1xuICpcbiAqIHNjaS1zY3JvbGxiYXIge1xuICogICAtLXNjaS1zY3JvbGxiYXItY29sb3I6IGJsdWU7XG4gKiB9XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc2NpLXNjcm9sbGJhcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9zY3JvbGxiYXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9zY3JvbGxiYXIuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIFNjaVNjcm9sbGJhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG5cbiAgLyoqXG4gICAqIFRpbWVvdXQgZm9yIGRlYm91bmNpbmcgdmlld3BvcnQgcmVzaXplIGV2ZW50cyB0aGF0IHRyaWdnZXIgdGhlIHNjcm9sbCBwb3NpdGlvbiBjb21wdXRhdGlvbi5cbiAgICpcbiAgICogRGVib3VuY2luZyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50IGluIHRoZSBjb250ZXh0IG9mIEFuZ3VsYXIgYW5pbWF0aW9ucywgc2luY2UgdGhleSBjb250aW51b3VzbHlcbiAgICogdHJpZ2dlciByZXNpemUgZXZlbnRzLiBEZWJvdW5jaW5nIHByZXZlbnRzIHRoZSBzY3JvbGxiYXIgZnJvbSBmbGlja2VyaW5nLCBmb3IgZXhhbXBsZSwgd2hlbiB0aGUgdXNlclxuICAgKiBleHBhbmRzIGEgcGFuZWwgdGhhdCBjb250YWlucyBhIHZpZXdwb3J0LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgVklFV1BPUlRfUkVTSVpFX0RFQk9VTkNFX1RJTUUgPSA1MDtcblxuICBwcml2YXRlIF9kZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgX3ZpZXdwb3J0ITogSFRNTEVsZW1lbnQ7XG4gIHByaXZhdGUgX3ZpZXdwb3J0Q2hhbmdlJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgX2xhc3REcmFnUG9zaXRpb246IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgX292ZXJmbG93ID0gZmFsc2U7XG4gIHByaXZhdGUgX3RodW1iU2l6ZUZyID0gMDtcbiAgcHJpdmF0ZSBfdGh1bWJQb3NpdGlvbkZyID0gMDtcblxuICAvKiBAZG9jcy1wcml2YXRlICovXG4gIEBWaWV3Q2hpbGQoJ3RodW1iX2hhbmRsZScsIHtzdGF0aWM6IHRydWV9KVxuICBwdWJsaWMgdGh1bWJFbGVtZW50ITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XG5cbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy52ZXJ0aWNhbCcpXG4gIHB1YmxpYyBnZXQgdmVydGljYWwoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGlyZWN0aW9uID09PSAndnNjcm9sbCc7XG4gIH1cblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmhvcml6b250YWwnKVxuICBwdWJsaWMgZ2V0IGhvcml6b250YWwoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGlyZWN0aW9uID09PSAnaHNjcm9sbCc7XG4gIH1cblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLnNjcm9sbGluZycpXG4gIHB1YmxpYyBnZXQgc2Nyb2xsaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9sYXN0RHJhZ1Bvc2l0aW9uICE9PSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzY3JvbGxiYXIuXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIGlmIG5vdCBzcGVjaWZpZWQsIHJlbmRlcnMgYSB2ZXJ0aWNhbCBzY3JvbGxiYXIuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgZGlyZWN0aW9uOiAndnNjcm9sbCcgfCAnaHNjcm9sbCcgPSAndnNjcm9sbCc7XG5cbiAgLyoqXG4gICAqIFRoZSB2aWV3cG9ydCB0byBwcm92aWRlIHNjcm9sbGJhcnMgZm9yLlxuICAgKi9cbiAgQElucHV0KHthbGlhczogJ3ZpZXdwb3J0JywgcmVxdWlyZWQ6IHRydWV9KSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEBhbmd1bGFyLWVzbGludC9uby1pbnB1dC1yZW5hbWVcbiAgcHVibGljIHNldCBzZXRWaWV3cG9ydCh2aWV3cG9ydDogSFRNTEVsZW1lbnQpIHtcbiAgICB0aGlzLl92aWV3cG9ydCA9IHZpZXdwb3J0O1xuICAgIHRoaXMuX3ZpZXdwb3J0Q2hhbmdlJC5uZXh0KCk7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9ob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICAgICAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBfZG9jdW1lbnQ6IERvY3VtZW50LFxuICAgICAgICAgICAgICBwcml2YXRlIF96b25lOiBOZ1pvbmUpIHtcbiAgICB0aGlzLl92aWV3cG9ydENoYW5nZSRcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4ge1xuICAgICAgICAgIGlmICghdGhpcy5fdmlld3BvcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBvZih1bmRlZmluZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbWVyZ2UoXG4gICAgICAgICAgICB0aGlzLnZpZXdwb3J0U2Nyb2xsQ2hhbmdlJCgpLFxuICAgICAgICAgICAgdGhpcy52aWV3cG9ydERpbWVuc2lvbkNoYW5nZSQoe2RlYm91bmNlVGltZTogU2NpU2Nyb2xsYmFyQ29tcG9uZW50LlZJRVdQT1JUX1JFU0laRV9ERUJPVU5DRV9USU1FfSksXG4gICAgICAgICAgICB0aGlzLnZpZXdwb3J0Q2xpZW50RGltZW5zaW9uQ2hhbmdlJCh7ZGVib3VuY2VUaW1lOiBTY2lTY3JvbGxiYXJDb21wb25lbnQuVklFV1BPUlRfUkVTSVpFX0RFQk9VTkNFX1RJTUV9KSxcbiAgICAgICAgICApO1xuICAgICAgICB9KSxcbiAgICAgICAgc3Vic2NyaWJlSW5zaWRlKGNvbnRpbnVlRm4gPT4gdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcihjb250aW51ZUZuKSksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX3ZpZXdwb3J0KSB7XG4gICAgICAgICAgdGhpcy5yZW5kZXJTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHRoaXMudW5zZXRTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlcyB0aGUgc2Nyb2xsIHBvc2l0aW9uIGFuZCB1cGRhdGVzIENTUyB2YXJpYWJsZXMgdG8gcmVuZGVyIHRoZSBzY3JvbGwgcG9zaXRpb24gaW4gdGhlIFVJLlxuICAgKi9cbiAgcHJpdmF0ZSByZW5kZXJTY3JvbGxQb3NpdGlvbigpOiB2b2lkIHtcbiAgICBOZ1pvbmUuYXNzZXJ0Tm90SW5Bbmd1bGFyWm9uZSgpO1xuICAgIGNvbnN0IHZpZXdwb3J0U2l6ZSA9IHRoaXMudmlld3BvcnRTaXplO1xuICAgIGNvbnN0IHZpZXdwb3J0Q2xpZW50U2l6ZSA9IHRoaXMudmlld3BvcnRDbGllbnRTaXplO1xuICAgIGNvbnN0IHRodW1iUG9zaXRpb25GciA9IHRoaXMuc2Nyb2xsUG9zaXRpb24gLyB2aWV3cG9ydENsaWVudFNpemU7XG4gICAgY29uc3QgdGh1bWJTaXplRnIgPSB2aWV3cG9ydFNpemUgLyB2aWV3cG9ydENsaWVudFNpemU7XG4gICAgY29uc3Qgb3ZlcmZsb3cgPSB2aWV3cG9ydENsaWVudFNpemUgPiB2aWV3cG9ydFNpemU7XG5cbiAgICBpZiAodGh1bWJQb3NpdGlvbkZyICE9PSB0aGlzLl90aHVtYlBvc2l0aW9uRnIgfHwgdGh1bWJTaXplRnIgIT09IHRoaXMuX3RodW1iU2l6ZUZyKSB7XG4gICAgICB0aGlzLl90aHVtYlBvc2l0aW9uRnIgPSB0aHVtYlBvc2l0aW9uRnI7XG4gICAgICB0aGlzLl90aHVtYlNpemVGciA9IHRodW1iU2l6ZUZyO1xuICAgICAgdGhpcy5zZXRDc3NWYXJpYWJsZSgnLS3JtXNjaS1zY3JvbGxiYXItdGh1bWItcG9zaXRpb24tZnInLCB0aHVtYlBvc2l0aW9uRnIpO1xuICAgICAgdGhpcy5zZXRDc3NWYXJpYWJsZSgnLS3JtXNjaS1zY3JvbGxiYXItdGh1bWItc2l6ZS1mcicsIHRodW1iU2l6ZUZyKTtcbiAgICB9XG5cbiAgICBpZiAob3ZlcmZsb3cgIT09IHRoaXMuX292ZXJmbG93KSB7XG4gICAgICB0aGlzLl9vdmVyZmxvdyA9IG92ZXJmbG93O1xuICAgICAgb3ZlcmZsb3cgPyB0aGlzLl9ob3N0Lm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnb3ZlcmZsb3cnKSA6IHRoaXMuX2hvc3QubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdvdmVyZmxvdycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhcnMgQ1NTIHZhcmlhYmxlcyB1c2VkIGZvciByZW5kZXJpbmcgdGhlIHNjcm9sbCBwb3NpdGlvbiBpbiB0aGUgVUkuXG4gICAqL1xuICBwcml2YXRlIHVuc2V0U2Nyb2xsUG9zaXRpb24oKTogdm9pZCB7XG4gICAgTmdab25lLmFzc2VydE5vdEluQW5ndWxhclpvbmUoKTtcbiAgICB0aGlzLl90aHVtYlBvc2l0aW9uRnIgPSAwO1xuICAgIHRoaXMuX3RodW1iU2l6ZUZyID0gMDtcbiAgICB0aGlzLl9vdmVyZmxvdyA9IGZhbHNlO1xuICAgIHRoaXMuc2V0Q3NzVmFyaWFibGUoJy0tybVzY2ktc2Nyb2xsYmFyLXRodW1iLXBvc2l0aW9uLWZyJywgMCk7XG4gICAgdGhpcy5zZXRDc3NWYXJpYWJsZSgnLS3JtXNjaS1zY3JvbGxiYXItdGh1bWItc2l6ZS1mcicsIDApO1xuICAgIHRoaXMuX2hvc3QubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdvdmVyZmxvdycpO1xuICB9XG5cbiAgLyogQGRvY3MtcHJpdmF0ZSAqL1xuICBwdWJsaWMgb25Ub3VjaFN0YXJ0KGV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLl9sYXN0RHJhZ1Bvc2l0aW9uID0gdGhpcy52ZXJ0aWNhbCA/IGV2ZW50LnRvdWNoZXNbMF0uc2NyZWVuWSA6IGV2ZW50LnRvdWNoZXNbMF0uc2NyZWVuWDtcbiAgfVxuXG4gIC8qIEBkb2NzLXByaXZhdGUgKi9cbiAgcHVibGljIG9uVG91Y2hNb3ZlKGV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIGNvbnN0IG5ld0RyYWdQb3NpdGlvblB4ID0gdGhpcy52ZXJ0aWNhbCA/IGV2ZW50LnRvdWNoZXNbMF0uc2NyZWVuWSA6IGV2ZW50LnRvdWNoZXNbMF0uc2NyZWVuWDtcbiAgICBjb25zdCBzY3JvbGxiYXJQYW5QeCA9IG5ld0RyYWdQb3NpdGlvblB4IC0gdGhpcy5fbGFzdERyYWdQb3NpdGlvbiE7XG4gICAgY29uc3Qgdmlld3BvcnRQYW5QeCA9IHRoaXMudG9WaWV3cG9ydFBhblB4KHNjcm9sbGJhclBhblB4KTtcbiAgICB0aGlzLl9sYXN0RHJhZ1Bvc2l0aW9uID0gbmV3RHJhZ1Bvc2l0aW9uUHg7XG4gICAgdGhpcy5tb3ZlVmlld3BvcnRDbGllbnQodmlld3BvcnRQYW5QeCk7XG4gIH1cblxuICAvKiBAZG9jcy1wcml2YXRlICovXG4gIHB1YmxpYyBvblRvdWNoRW5kKGV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLl9sYXN0RHJhZ1Bvc2l0aW9uID0gbnVsbDtcbiAgfVxuXG4gIC8qIEBkb2NzLXByaXZhdGUgKi9cbiAgcHVibGljIG9uTW91c2VEb3duKG1vdXNlZG93bkV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKG1vdXNlZG93bkV2ZW50LmJ1dHRvbiAhPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG1vdXNlZG93bkV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgdGhpcy5fbGFzdERyYWdQb3NpdGlvbiA9IHRoaXMudmVydGljYWwgPyBtb3VzZWRvd25FdmVudC5zY3JlZW5ZIDogbW91c2Vkb3duRXZlbnQuc2NyZWVuWDtcblxuICAgIC8vIExpc3RlbiBmb3IgJ21vdXNlbW92ZScgZXZlbnRzXG4gICAgdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBjb25zdCBtb3VzZW1vdmVMaXN0ZW5lciA9IG1lcmdlKGZyb21FdmVudDxNb3VzZUV2ZW50Pih0aGlzLl9kb2N1bWVudCwgJ21vdXNlbW92ZScpLCBmcm9tRXZlbnQ8TW91c2VFdmVudD4odGhpcy5fZG9jdW1lbnQsICdzY2ktbW91c2Vtb3ZlJykpXG4gICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCkpXG4gICAgICAgIC5zdWJzY3JpYmUobW91c2Vtb3ZlRXZlbnQgPT4ge1xuICAgICAgICAgIG1vdXNlbW92ZUV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICBjb25zdCBuZXdEcmFnUG9zaXRpb25QeCA9IHRoaXMudmVydGljYWwgPyBtb3VzZW1vdmVFdmVudC5zY3JlZW5ZIDogbW91c2Vtb3ZlRXZlbnQuc2NyZWVuWDtcbiAgICAgICAgICBjb25zdCBzY3JvbGxiYXJQYW5QeCA9IG5ld0RyYWdQb3NpdGlvblB4IC0gdGhpcy5fbGFzdERyYWdQb3NpdGlvbiE7XG4gICAgICAgICAgY29uc3Qgdmlld3BvcnRQYW5QeCA9IHRoaXMudG9WaWV3cG9ydFBhblB4KHNjcm9sbGJhclBhblB4KTtcbiAgICAgICAgICB0aGlzLl9sYXN0RHJhZ1Bvc2l0aW9uID0gbmV3RHJhZ1Bvc2l0aW9uUHg7XG4gICAgICAgICAgdGhpcy5tb3ZlVmlld3BvcnRDbGllbnQodmlld3BvcnRQYW5QeCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAvLyBMaXN0ZW4gZm9yICdtb3VzZXVwJyBldmVudHM7IHVzZSAnY2FwdHVyZSBwaGFzZScgYW5kICdzdG9wIHByb3BhZ2F0aW9uJyB0byBub3QgY2xvc2Ugb3ZlcmxheXNcbiAgICAgIG1lcmdlKGZyb21FdmVudDxNb3VzZUV2ZW50Pih0aGlzLl9kb2N1bWVudCwgJ21vdXNldXAnLCB7Y2FwdHVyZTogdHJ1ZX0pLCBmcm9tRXZlbnQ8TW91c2VFdmVudD4odGhpcy5fZG9jdW1lbnQsICdzY2ktbW91c2V1cCcpKVxuICAgICAgICAucGlwZShmaXJzdCgpLCB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpKVxuICAgICAgICAuc3Vic2NyaWJlKG1vdXNldXBFdmVudCA9PiB7XG4gICAgICAgICAgbW91c2V1cEV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgIG1vdXNlbW92ZUxpc3RlbmVyLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgdGhpcy5fbGFzdERyYWdQb3NpdGlvbiA9IG51bGw7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyogQGRvY3MtcHJpdmF0ZSAqL1xuICBwdWJsaWMgb25TY3JvbGxUcmFja01vdXNlRG93bihldmVudDogTW91c2VFdmVudCwgZGlyZWN0aW9uOiAndXAnIHwgJ2Rvd24nKTogdm9pZCB7XG4gICAgY29uc3Qgc2lnbnVtID0gKGRpcmVjdGlvbiA9PT0gJ3VwJyA/IC0xIDogKzEpO1xuICAgIHRoaXMuc2Nyb2xsV2hpbGVNb3VzZURvd24odGhpcy50b1ZpZXdwb3J0UGFuUHgoc2lnbnVtICogdGhpcy50aHVtYlNpemUpLCBldmVudCk7XG4gIH1cblxuICAvKipcbiAgICogUHJvamVjdHMgdGhlIGdpdmVuIHNjcm9sbGJhciBzY3JvbGwgcGl4ZWxzIGludG8gdmlld3BvcnQgc2Nyb2xsIHBpeGVscy5cbiAgICovXG4gIHByaXZhdGUgdG9WaWV3cG9ydFBhblB4KHNjcm9sbGJhclBhblB4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHNjcm9sbFJhbmdlUHggPSB0aGlzLnRyYWNrU2l6ZSAtIHRoaXMudGh1bWJTaXplO1xuICAgIGNvbnN0IHNjcm9sbFJhdGlvID0gc2Nyb2xsYmFyUGFuUHggLyBzY3JvbGxSYW5nZVB4O1xuICAgIHJldHVybiBzY3JvbGxSYXRpbyAqICh0aGlzLnZpZXdwb3J0Q2xpZW50U2l6ZSAtIHRoaXMudmlld3BvcnRTaXplKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlcyB0aGUgdmlld3BvcnQgY2xpZW50IGJ5IHRoZSBzcGVjaWZpZWQgbnVtYmVycyBvZiBwaXhlbHMuXG4gICAqL1xuICBwcml2YXRlIG1vdmVWaWV3cG9ydENsaWVudCh2aWV3cG9ydFBhblB4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy52ZXJ0aWNhbCkge1xuICAgICAgdGhpcy5fdmlld3BvcnQuc2Nyb2xsVG9wICs9IHZpZXdwb3J0UGFuUHg7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy5fdmlld3BvcnQuc2Nyb2xsTGVmdCArPSB2aWV3cG9ydFBhblB4O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhlIGNvbnRlbnQgb3ZlcmZsb3dzLlxuICAgKi9cbiAgcHVibGljIGdldCBvdmVyZmxvdygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fb3ZlcmZsb3c7XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xscyBjb250aW51b3VzbHkgd2hpbGUgaG9sZGluZyB0aGUgbW91c2UgcHJlc3NlZCwgb3IgdW50aWwgdGhlIG1vdXNlIGxlYXZlcyB0aGUgc2Nyb2xsdHJhY2suXG4gICAqL1xuICBwcml2YXRlIHNjcm9sbFdoaWxlTW91c2VEb3duKHZpZXdwb3J0U2Nyb2xsUHg6IG51bWJlciwgbW91c2Vkb3duRXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBUaGUgYEV2ZW50VGFyZ2V0YCB0eXBlIG9mIGBFdmVudC50YXJnZXRgIGlzIG5vdCB5ZXQgY29tcGF0aWJsZSB3aXRoIGBGcm9tRXZlbnRUYXJnZXRgIHVzZWQgaW4gYGZyb21FdmVudGAuXG4gICAgLy8gVGhpcyB3aWxsIGJlIGZpeGVkIGluIHJ4anMgdmVyc2lvbiA3LjAuMC4gUmVmZXIgdG8gaHR0cHM6Ly9naXRodWIuY29tL1JlYWN0aXZlWC9yeGpzL2NvbW1pdC81ZjAyMmQ3ODQ1NzA2ODQ2MzJlNmZkNWFlMjQ3ZmMyNTllZTM0YzRiXG4gICAgLy8gZm9yIG1vcmUgZGV0YWlscy5cbiAgICBjb25zdCBzY3JvbGxUcmFja0VsZW1lbnQgPSBtb3VzZWRvd25FdmVudC50YXJnZXQgYXMgRWxlbWVudDtcblxuICAgIC8vIHNjcm9sbCBjb250aW51b3VzbHkgZXZlcnkgNTBtcyBhZnRlciBhbiBpbml0aWFsIGRlbGF5IG9mIDI1MG1zXG4gICAgdGltZXIoMjUwLCA1MClcbiAgICAgIC5waXBlKFxuICAgICAgICAvLyBjb250aW51ZSBjaGFpbiB3aXRoIGxhdGVzdCBtb3VzZSBldmVudFxuICAgICAgICB3aXRoTGF0ZXN0RnJvbShtZXJnZShvZihtb3VzZWRvd25FdmVudCksIGZyb21FdmVudDxNb3VzZUV2ZW50PihzY3JvbGxUcmFja0VsZW1lbnQsICdtb3VzZW1vdmUnKSksICh0aWNrLCBldmVudCkgPT4gZXZlbnQpLFxuICAgICAgICAvLyBzdGFydCBpbW1lZGlhdGVseVxuICAgICAgICBzdGFydFdpdGgobW91c2Vkb3duRXZlbnQpLFxuICAgICAgICAvLyBzdG9wIHNjcm9sbGluZyBpZiB0aGUgdGh1bWIgaGl0cyB0aGUgbW91c2UgcG9pbnRlciBwb3NpdGlvblxuICAgICAgICB0YWtlV2hpbGUoKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiBzY3JvbGxUcmFja0VsZW1lbnQgPT09IHRoaXMuX2RvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSkpLFxuICAgICAgICBkZWJvdW5jZVRpbWUoMTApLFxuICAgICAgICAvLyBzdG9wIHNjcm9sbGluZyBvbiBtb3VzZW91dCBvciBtb3VzZXVwXG4gICAgICAgIHRha2VVbnRpbChtZXJnZShmcm9tRXZlbnQoc2Nyb2xsVHJhY2tFbGVtZW50LCAnbW91c2VvdXQnKSwgZnJvbUV2ZW50KHNjcm9sbFRyYWNrRWxlbWVudCwgJ21vdXNldXAnKSkpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMubW92ZVZpZXdwb3J0Q2xpZW50KHZpZXdwb3J0U2Nyb2xsUHgpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgd2hlbmV2ZXIgdGhlIHZpZXdwb3J0IHNjcm9sbHMuXG4gICAqL1xuICBwcml2YXRlIHZpZXdwb3J0U2Nyb2xsQ2hhbmdlJCgpOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gZnJvbUV2ZW50KHRoaXMuX3ZpZXdwb3J0LCAnc2Nyb2xsJywge3Bhc3NpdmU6IHRydWV9KS5waXBlKG1hcCgoKSA9PiB1bmRlZmluZWQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0cyBvbiBzdWJzY3JpcHRpb24sIGFuZCB0aGVuIGVhY2ggdGltZSB0aGUgc2l6ZSBvZiB0aGUgdmlld3BvcnQgY2hhbmdlcy5cbiAgICovXG4gIHByaXZhdGUgdmlld3BvcnREaW1lbnNpb25DaGFuZ2UkKG9wdGlvbnM6IHtkZWJvdW5jZVRpbWU6IG51bWJlcn0pOiBPYnNlcnZhYmxlPHZvaWQ+IHtcbiAgICByZXR1cm4gZnJvbURpbWVuc2lvbiQodGhpcy5fdmlld3BvcnQpXG4gICAgICAucGlwZShcbiAgICAgICAgLy8gRGVib3VuY2luZyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50IGluIHRoZSBjb250ZXh0IG9mIEFuZ3VsYXIgYW5pbWF0aW9ucywgc2luY2UgdGhleSBjb250aW51b3VzbHlcbiAgICAgICAgLy8gdHJpZ2dlciByZXNpemUgZXZlbnRzLiBEZWJvdW5jaW5nIHByZXZlbnRzIHRoZSBzY3JvbGxiYXIgZnJvbSBmbGlja2VyaW5nLCBmb3IgZXhhbXBsZSwgd2hlbiB0aGUgdXNlclxuICAgICAgICAvLyBleHBhbmRzIGEgcGFuZWwgdGhhdCBjb250YWlucyBhIHZpZXdwb3J0LlxuICAgICAgICBkZWJvdW5jZVRpbWUob3B0aW9ucy5kZWJvdW5jZVRpbWUpLFxuICAgICAgICBtYXAoKCkgPT4gdW5kZWZpbmVkKSxcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgb24gc3Vic2NyaXB0aW9uLCBhbmQgdGhlbiBlYWNoIHRpbWUgdGhlIHNpemUgb3Igc3R5bGUgcHJvcGVydHkgb2YgdGhlIHZpZXdwb3J0IGNsaWVudCBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSB2aWV3cG9ydENsaWVudERpbWVuc2lvbkNoYW5nZSQob3B0aW9uczoge2RlYm91bmNlVGltZTogbnVtYmVyfSk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmNoaWxkcmVuJCh0aGlzLl92aWV3cG9ydClcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoY2hpbGRyZW4gPT4gbWVyZ2UoLi4uY2hpbGRyZW4ubWFwKGNoaWxkID0+IG1lcmdlKFxuICAgICAgICAgIGZyb21EaW1lbnNpb24kKGNoaWxkKSxcbiAgICAgICAgICAvLyBPYnNlcnZlIHN0eWxlIG11dGF0aW9ucyBzaW5jZSBzb21lIHRyYW5zZm9ybWF0aW9ucyBjaGFuZ2UgdGhlIHNjcm9sbCBwb3NpdGlvbiB3aXRob3V0IG5lY2Vzc2FyaWx5IHRyaWdnZXJpbmcgYSBkaW1lbnNpb24gY2hhbmdlLFxuICAgICAgICAgIC8vIGUuZy4sIGBzY2FsZWAgb3IgYHRyYW5zbGF0ZWAgdXNlZCBieSBzb21lIHZpcnR1YWwgc2Nyb2xsIGltcGxlbWVudGF0aW9uc1xuICAgICAgICAgIGZyb21NdXRhdGlvbiQoY2hpbGQsIHtzdWJ0cmVlOiBmYWxzZSwgY2hpbGRMaXN0OiBmYWxzZSwgYXR0cmlidXRlRmlsdGVyOiBbJ3N0eWxlJ119KSksXG4gICAgICAgICkpKSxcbiAgICAgICAgLy8gRGVib3VuY2luZyBpcyBwYXJ0aWN1bGFybHkgaW1wb3J0YW50IGluIHRoZSBjb250ZXh0IG9mIEFuZ3VsYXIgYW5pbWF0aW9ucywgc2luY2UgdGhleSBjb250aW51b3VzbHlcbiAgICAgICAgLy8gdHJpZ2dlciByZXNpemUgZXZlbnRzLiBEZWJvdW5jaW5nIHByZXZlbnRzIHRoZSBzY3JvbGxiYXIgZnJvbSBmbGlja2VyaW5nLCBmb3IgZXhhbXBsZSwgd2hlbiB0aGUgdXNlclxuICAgICAgICAvLyBleHBhbmRzIGEgcGFuZWwgdGhhdCBjb250YWlucyBhIHZpZXdwb3J0LlxuICAgICAgICBkZWJvdW5jZVRpbWUob3B0aW9ucy5kZWJvdW5jZVRpbWUpLFxuICAgICAgICBtYXAoKCkgPT4gdW5kZWZpbmVkKSxcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgdGhlIGNoaWxkcmVuIG9mIHRoZSBwYXNzZWQgZWxlbWVudCwgYW5kIHRoZW4gZWFjaCB0aW1lIGNoaWxkIGVsZW1lbnRzIGFyZSBhZGRlZCBvciByZW1vdmVkLlxuICAgKi9cbiAgcHJpdmF0ZSBjaGlsZHJlbiQoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBPYnNlcnZhYmxlPEhUTUxFbGVtZW50W10+IHtcbiAgICByZXR1cm4gZnJvbU11dGF0aW9uJChlbGVtZW50LCB7c3VidHJlZTogZmFsc2UsIGNoaWxkTGlzdDogdHJ1ZX0pXG4gICAgICAucGlwZShcbiAgICAgICAgc3RhcnRXaXRoKHVuZGVmaW5lZCBhcyB2b2lkKSxcbiAgICAgICAgbWFwKCgpID0+IEFycmF5LmZyb20oZWxlbWVudC5jaGlsZHJlbikpLFxuICAgICAgICBmaWx0ZXJBcnJheSgoY2hpbGQ6IEVsZW1lbnQpOiBjaGlsZCBpcyBIVE1MRWxlbWVudCA9PiBjaGlsZCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSxcbiAgICAgICk7XG4gIH1cblxuICBwcml2YXRlIHNldENzc1ZhcmlhYmxlKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5faG9zdC5uYXRpdmVFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KGtleSwgdmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdmlld3BvcnRTaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3ZpZXdwb3J0ID8gKHRoaXMudmVydGljYWwgPyB0aGlzLl92aWV3cG9ydC5jbGllbnRIZWlnaHQgOiB0aGlzLl92aWV3cG9ydC5jbGllbnRXaWR0aCkgOiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdmlld3BvcnRDbGllbnRTaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3ZpZXdwb3J0ID8gKHRoaXMudmVydGljYWwgPyB0aGlzLl92aWV3cG9ydC5zY3JvbGxIZWlnaHQgOiB0aGlzLl92aWV3cG9ydC5zY3JvbGxXaWR0aCkgOiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgc2Nyb2xsUG9zaXRpb24oKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fdmlld3BvcnQgPyAodGhpcy52ZXJ0aWNhbCA/IHRoaXMuX3ZpZXdwb3J0LnNjcm9sbFRvcCA6IHRoaXMuX3ZpZXdwb3J0LnNjcm9sbExlZnQpIDogMDtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IHRodW1iU2l6ZSgpOiBudW1iZXIge1xuICAgIGNvbnN0IHRodW1iRWxlbWVudCA9IHRoaXMudGh1bWJFbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgcmV0dXJuIHRoaXMudmVydGljYWwgPyB0aHVtYkVsZW1lbnQuY2xpZW50SGVpZ2h0IDogdGh1bWJFbGVtZW50LmNsaWVudFdpZHRoO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgdHJhY2tTaXplKCk6IG51bWJlciB7XG4gICAgY29uc3QgdHJhY2tFbGVtZW50ID0gdGhpcy5faG9zdC5uYXRpdmVFbGVtZW50O1xuICAgIHJldHVybiB0aGlzLnZlcnRpY2FsID8gdHJhY2tFbGVtZW50LmNsaWVudEhlaWdodCA6IHRyYWNrRWxlbWVudC5jbGllbnRXaWR0aDtcbiAgfVxuXG4gIC8qIEBkb2NzLXByaXZhdGUgKi9cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuX2Rlc3Ryb3kkLm5leHQoKTtcbiAgfVxufVxuIiwiPCEtLSBzY3JvbGx0cmFjayB0byBtb3ZlIHRoZSB2aWV3cG9ydCBjbGllbnQgdXB3YXJkcyAocGFnaW5nKSAtLT5cbjxkaXYgY2xhc3M9XCJzY3JvbGx0cmFjay1zdGFydFwiIChtb3VzZWRvd24pPVwib25TY3JvbGxUcmFja01vdXNlRG93bigkZXZlbnQsICd1cCcpXCI+PC9kaXY+XG5cbjwhLS0gc2Nyb2xsdGh1bWIgLS0+XG48ZGl2ICN0aHVtYl9oYW5kbGVcbiAgICAgY2xhc3M9XCJ0aHVtYi1oYW5kbGVcIlxuICAgICBbY2xhc3MudmVydGljYWxdPVwidmVydGljYWxcIlxuICAgICBbY2xhc3MuaG9yaXpvbnRhbF09XCJob3Jpem9udGFsXCJcbiAgICAgKG1vdXNlZG93bik9XCJvbk1vdXNlRG93bigkZXZlbnQpXCJcbiAgICAgKHRvdWNoc3RhcnQpPVwib25Ub3VjaFN0YXJ0KCRldmVudClcIlxuICAgICAodG91Y2htb3ZlKT1cIm9uVG91Y2hNb3ZlKCRldmVudClcIlxuICAgICAodG91Y2hlbmQpPVwib25Ub3VjaEVuZCgkZXZlbnQpXCJcbiAgICAgKHRvdWNoY2FuY2VsKT1cIm9uVG91Y2hFbmQoJGV2ZW50KVwiPlxuICA8ZGl2IGNsYXNzPVwidGh1bWJcIlxuICAgICAgIFtjbGFzcy52ZXJ0aWNhbF09XCJ2ZXJ0aWNhbFwiXG4gICAgICAgW2NsYXNzLmhvcml6b250YWxdPVwiaG9yaXpvbnRhbFwiPlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48IS0tIHNjcm9sbHRyYWNrIHRvIG1vdmUgdGhlIHZpZXdwb3J0IGNsaWVudCBkb3dud2FyZHMgKHBhZ2luZykgLS0+XG48ZGl2IGNsYXNzPVwic2Nyb2xsdHJhY2stZW5kXCIgKG1vdXNlZG93bik9XCJvblNjcm9sbFRyYWNrTW91c2VEb3duKCRldmVudCwgJ2Rvd24nKVwiPjwvZGl2PlxuIl19