@libs-ui/components-scroll-measure-items-direction-vertical 0.2.356-25 → 0.2.356-27

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.
@@ -2,11 +2,20 @@ import { AfterViewInit } from '@angular/core';
2
2
  import { IScrollMeasureItemDirectionVerticalFunctionsControl } from './interfaces/direction-vertical.interface';
3
3
  import * as i0 from "@angular/core";
4
4
  export declare class LibsUiScrollMeasureItemDirectionVerticalDirective implements AfterViewInit {
5
+ /** Số item buffer render thêm sau viewport để tránh trắng vùng khi scroll. */
6
+ private readonly bufferAhead;
5
7
  private viewPortItems;
6
8
  private start;
7
9
  private end;
8
10
  private storeItems;
9
11
  private divVirtual;
12
+ private resizeObserver?;
13
+ /** Tham chiếu setTimeout của ngAfterViewInit để clear khi destroy — chặn ResizeObserver mồ côi. */
14
+ private timerAfterViewInit?;
15
+ /** Token nhận dạng lần effect chạy hiện tại. Async đo height xong sẽ bỏ kết quả nếu token đổi. */
16
+ private executionToken;
17
+ /** Style + DOM hook của divVirtual chỉ cần khởi tạo một lần cho cả vòng đời directive. */
18
+ private divVirtualInitialized;
10
19
  readonly elementScroll: import("@angular/core").InputSignal<HTMLElement>;
11
20
  readonly functionGetHeightItem: import("@angular/core").InputSignal<(item: any) => Promise<number>>;
12
21
  readonly items: import("@angular/core").InputSignal<any[]>;
@@ -2,16 +2,24 @@
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
3
  import { DestroyRef, Directive, ElementRef, effect, inject, input, output, signal, untracked } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
- import { get } from '@libs-ui/utils';
6
5
  import { fromEvent } from 'rxjs';
7
6
  import * as i0 from "@angular/core";
8
7
  export class LibsUiScrollMeasureItemDirectionVerticalDirective {
9
8
  // #region PROPERTY
9
+ /** Số item buffer render thêm sau viewport để tránh trắng vùng khi scroll. */
10
+ bufferAhead = 3;
10
11
  viewPortItems = signal([]);
11
12
  start = signal(0);
12
13
  end = signal(0);
13
14
  storeItems = signal([]);
14
15
  divVirtual = document.createElement('div');
16
+ resizeObserver;
17
+ /** Tham chiếu setTimeout của ngAfterViewInit để clear khi destroy — chặn ResizeObserver mồ côi. */
18
+ timerAfterViewInit;
19
+ /** Token nhận dạng lần effect chạy hiện tại. Async đo height xong sẽ bỏ kết quả nếu token đổi. */
20
+ executionToken = 0;
21
+ /** Style + DOM hook của divVirtual chỉ cần khởi tạo một lần cho cả vòng đời directive. */
22
+ divVirtualInitialized = false;
15
23
  // #region INPUT
16
24
  elementScroll = input.required();
17
25
  functionGetHeightItem = input.required();
@@ -26,59 +34,79 @@ export class LibsUiScrollMeasureItemDirectionVerticalDirective {
26
34
  destroyRef = inject(DestroyRef);
27
35
  constructor() {
28
36
  effect(() => {
29
- const scrollEl = untracked(() => this.ScrollContainer);
30
- if (!scrollEl || !untracked(() => this.functionGetHeightItem())) {
31
- return;
32
- }
33
37
  const items = this.items();
38
+ const myToken = ++this.executionToken;
34
39
  untracked(async () => {
40
+ const scrollEl = this.ScrollContainer;
41
+ const functionGetHeightItem = this.functionGetHeightItem();
42
+ if (!scrollEl || !functionGetHeightItem) {
43
+ return;
44
+ }
45
+ // Đo height tất cả item song song — rút ngắn thời gian cho list lớn.
46
+ const heights = await Promise.all(items.map((it) => functionGetHeightItem(it)));
47
+ // Bị huỷ vì có lượt items() mới chạy sau — bỏ kết quả cũ tránh đè state.
48
+ if (myToken !== this.executionToken) {
49
+ return;
50
+ }
35
51
  this.start.set(0);
36
52
  const scrollTop = scrollEl.scrollTop;
37
53
  const containerHeight = scrollEl.getBoundingClientRect().height;
38
54
  let height = 0;
55
+ let endLocal = 0;
39
56
  const newItems = [];
40
57
  for (let i = 0; i < items.length; i++) {
41
- const item = items[i];
42
- const newItem = { ref: item, itemHeight: 0, start: 0, end: 0 };
43
- const itemHeight = await this.functionGetHeightItem()(item);
44
- newItem.itemHeight = itemHeight;
45
- newItem.start = height;
58
+ const itemHeight = heights[i];
59
+ const newItem = { ref: items[i], itemHeight, start: height, end: 0 };
46
60
  height += itemHeight;
47
61
  newItem.end = height;
48
62
  if (newItem.end <= containerHeight + scrollTop) {
49
- this.end.set(i);
63
+ endLocal = i;
50
64
  }
51
65
  newItems.push(newItem);
52
66
  }
67
+ // Set end một lần thay vì ghi mỗi vòng lặp — tránh notify consumer N lần.
68
+ this.end.set(endLocal);
53
69
  this.storeItems.set(newItems);
54
- this.viewPortItems.set(this.storeItems()
55
- .slice(this.start(), this.end() + 3)
56
- .map((item) => item.ref));
57
- this.outViewPortItem.emit(this.viewPortItems());
58
- this.outPaddingTop.emit(get(this.storeItems(), `[${this.start()}].start`, 0));
59
- this.divVirtual.style.position = 'absolute';
60
- this.divVirtual.style.top = '0px';
61
- this.divVirtual.style.left = '0px';
70
+ // Khởi tạo style + DOM hook của divVirtual đúng một lần.
71
+ if (!this.divVirtualInitialized) {
72
+ this.divVirtual.style.position = 'absolute';
73
+ this.divVirtual.style.top = '0px';
74
+ this.divVirtual.style.left = '0px';
75
+ this.divVirtual.style.width = '1px';
76
+ this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị
77
+ this.elementRef.nativeElement.classList.add('relative');
78
+ this.elementRef.nativeElement.classList.remove('h-full');
79
+ this.elementRef.nativeElement.style.paddingTop = '0px';
80
+ scrollEl.append(this.divVirtual);
81
+ this.divVirtualInitialized = true;
82
+ this.outDivVirtual.emit(this.divVirtual);
83
+ }
84
+ // Height tổng thể đổi theo dataset → cần update mỗi lượt.
62
85
  this.divVirtual.style.height = `${height}px`;
63
- this.divVirtual.style.width = '1px';
64
- this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị
65
- this.elementRef.nativeElement.classList.add('relative');
66
- this.elementRef.nativeElement.classList.remove('h-full');
67
- this.elementRef.nativeElement.style.paddingTop = '0px';
68
- scrollEl.append(this.divVirtual);
69
- this.outDivVirtual.emit(this.divVirtual);
86
+ // containerHeight lúc đầu có thể = 0 (DOM chưa layout), khiến end giữ
87
+ // nguyên 0 chỉ render bufferAhead item đầu. Re-đo bằng handlerScroll sau khi vòng
88
+ // lặp await xong (layout thường đã hoàn tất) để end ra đúng giá trị.
89
+ this.handlerScroll();
70
90
  });
71
91
  });
72
92
  this.destroyRef.onDestroy(() => {
93
+ clearTimeout(this.timerAfterViewInit);
73
94
  this.divVirtual.remove();
95
+ this.resizeObserver?.disconnect();
74
96
  });
75
97
  }
76
98
  ngAfterViewInit() {
77
- setTimeout(() => {
99
+ this.timerAfterViewInit = setTimeout(() => {
78
100
  fromEvent(this.ScrollContainer, 'scroll')
79
101
  .pipe(takeUntilDestroyed(this.destroyRef))
80
102
  .subscribe(() => this.handlerScroll());
81
103
  this.outFunctionControl.emit(this.FunctionsControl);
104
+ // Re-tính viewport sau khi container có kích thước thật.
105
+ // Lần đầu render, getBoundingClientRect().height có thể = 0 nên end giữ giá trị 0,
106
+ // chỉ hiển thị bufferAhead item đầu. ResizeObserver fire ngay khi observe và mỗi lần
107
+ // container đổi size sẽ kéo end về đúng giá trị.
108
+ this.resizeObserver = new ResizeObserver(() => this.handlerScroll());
109
+ this.resizeObserver.observe(this.ScrollContainer);
82
110
  });
83
111
  }
84
112
  // #region PUBLIC API
@@ -138,18 +166,17 @@ export class LibsUiScrollMeasureItemDirectionVerticalDirective {
138
166
  // Utilize Binary Search for optimal O(log N) discovery
139
167
  const start = this.findStartIndex(store, scrollTop);
140
168
  const end = this.findEndIndex(store, scrollTop + containerHeight);
141
- this.end.set(end);
169
+ if (end !== this.end()) {
170
+ this.end.set(end);
171
+ }
142
172
  if (start !== this.start()) {
143
173
  this.start.set(start);
144
- // Use logical OR for fallback when start is invalid. But binary search guarantees valid index.
145
- const paddingTop = store[start]?.start || 0;
174
+ // Binary search guarantees `start` index hợp lệ trong store.
175
+ const paddingTop = store[start].start;
146
176
  this.elementRef.nativeElement.style.paddingTop = `${paddingTop}px`;
147
177
  this.outPaddingTop.emit(paddingTop);
148
178
  }
149
- if (this.start() < 0) {
150
- this.start.set(0);
151
- }
152
- this.viewPortItems.set(store.slice(this.start(), this.end() + 3).map((item) => item.ref));
179
+ this.viewPortItems.set(store.slice(this.start(), this.end() + this.bufferAhead).map((item) => item.ref));
153
180
  this.outViewPortItem.emit(this.viewPortItems());
154
181
  }
155
182
  async scrollInto(itemScroll) {
@@ -170,10 +197,14 @@ export class LibsUiScrollMeasureItemDirectionVerticalDirective {
170
197
  this.ScrollContainer.scrollTop = itemOfIndex.start;
171
198
  }
172
199
  async reCalculatorViewPort() {
173
- let height = 0;
174
200
  const items = this.storeItems();
175
- for (const item of items) {
176
- const itemHeight = await this.functionGetHeightItem()(item.ref);
201
+ const fn = this.functionGetHeightItem();
202
+ // Đo song song để rút ngắn thời gian thay vì await tuần tự.
203
+ const heights = await Promise.all(items.map((it) => fn(it.ref)));
204
+ let height = 0;
205
+ for (let i = 0; i < items.length; i++) {
206
+ const item = items[i];
207
+ const itemHeight = heights[i];
177
208
  item.itemHeight = itemHeight;
178
209
  item.start = height;
179
210
  height += itemHeight;
@@ -194,4 +225,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
194
225
  standalone: true,
195
226
  }]
196
227
  }], ctorParameters: () => [] });
197
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlyZWN0aW9uLXZlcnRpY2FsLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMtdWkvY29tcG9uZW50cy9zY3JvbGwtbWVhc3VyZS1pdGVtcy9kaXJlY3Rpb24tdmVydGljYWwvc3JjL2RpcmVjdGlvbi12ZXJ0aWNhbC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseUZBQXlGO0FBQ3pGLHVEQUF1RDtBQUN2RCxPQUFPLEVBQWlCLFVBQVUsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25JLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDOztBQVFqQyxNQUFNLE9BQU8saURBQWlEO0lBQzVELG1CQUFtQjtJQUNYLGFBQWEsR0FBRyxNQUFNLENBQWEsRUFBRSxDQUFDLENBQUM7SUFDdkMsS0FBSyxHQUFHLE1BQU0sQ0FBUyxDQUFDLENBQUMsQ0FBQztJQUMxQixHQUFHLEdBQUcsTUFBTSxDQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLFVBQVUsR0FBRyxNQUFNLENBQWdELEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLFVBQVUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRW5ELGdCQUFnQjtJQUNQLGFBQWEsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFlLENBQUM7SUFDOUMscUJBQXFCLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBa0MsQ0FBQztJQUN6RSxLQUFLLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBYyxDQUFDO0lBRTlDLGlCQUFpQjtJ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LElBQUksS0FBSyxFQUFFLENBQUM7WUFDekIsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEUsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7WUFDN0IsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUM7WUFDcEIsTUFBTSxJQUFJLFVBQVUsQ0FBQztZQUNyQixJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQztRQUNwQixDQUFDO1FBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUM7UUFDN0MsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7d0dBek1VLGlEQUFpRDs0RkFBakQsaURBQWlEOzs0RkFBakQsaURBQWlEO2tCQUw3RCxTQUFTO21CQUFDO29CQUNULDhEQUE4RDtvQkFDOUQsUUFBUSxFQUFFLHFEQUFxRDtvQkFDL0QsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ09OVkVOVElPTi1FWENFUFQ6IGFueSDigJQgR2VuZXJpYyBkaXJlY3RpdmUgd29ya3Mgd2l0aCB1bmtub3duIGl0ZW0gdHlwZXMgZnJvbSBjb25zdW1lclxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgRGVzdHJveVJlZiwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBlZmZlY3QsIGluamVjdCwgaW5wdXQsIG91dHB1dCwgc2lnbmFsLCB1bnRyYWNrZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IGdldCB9IGZyb20gJ0BsaWJzLXVpL3V0aWxzJztcbmltcG9ydCB7IGZyb21FdmVudCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgSVNjcm9sbE1lYXN1cmVJdGVtRGlyZWN0aW9uVmVydGljYWxGdW5jdGlvbnNDb250cm9sLCBJU2Nyb2xsTWVhc3VyZVN0b3JlSXRlbVZlcnRpY2FsQ29udmVydCB9IGZyb20gJy4vaW50ZXJmYWNlcy9kaXJlY3Rpb24tdmVydGljYWwuaW50ZXJmYWNlJztcblxuQERpcmVjdGl2ZSh7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvZGlyZWN0aXZlLXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnW0xpYnNVaVNjcm9sbE1lYXN1cmVJdGVtRGlyZWN0aW9uVmVydGljYWxEaXJlY3RpdmVdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgTGlic1VpU2Nyb2xsTWVhc3VyZUl0ZW1EaXJlY3Rpb25WZXJ0aWNhbERpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuICAvLyAjcmVnaW9uIFBST1BFUlRZXG4gIHByaXZhdGUgdmlld1BvcnRJdGVtcyA9IHNpZ25hbDxBcnJheTxhbnk+PihbXSk7XG4gIHByaXZhdGUgc3RhcnQgPSBzaWduYWw8bnVtYmVyPigwKTtcbiAgcHJpdmF0ZSBlbmQgPSBzaWduYWw8bnVtYmVyPigwKTtcbiAgcHJpdmF0ZSBzdG9yZUl0ZW1zID0gc2lnbmFsPEFycmF5PElTY3JvbGxNZWFzdXJlU3RvcmVJdGVtVmVydGljYWxDb252ZXJ0Pj4oW10pO1xuICBwcml2YXRlIGRpdlZpcnR1YWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAvLyAjcmVnaW9uIElOUFVUXG4gIHJlYWRvbmx5IGVsZW1lbnRTY3JvbGwgPSBpbnB1dC5yZXF1aXJlZDxIVE1MRWxlbWVudD4oKTtcbiAgcmVhZG9ubHkgZnVuY3Rpb25HZXRIZWlnaHRJdGVtID0gaW5wdXQucmVxdWlyZWQ8KGl0ZW06IGFueSkgPT4gUHJvbWlzZTxudW1iZXI+PigpO1xuICByZWFkb25seSBpdGVtcyA9IGlucHV0LnJlcXVpcmVkPEFycmF5PGFueT4+KCk7XG5cbiAgLy8gI3JlZ2lvbiBPVVRQVVRcbiAgcmVhZG9ubHkgb3V0Vmlld1BvcnRJdGVtID0gb3V0cHV0PEFycmF5PGFueT4+KCk7XG4gIHJlYWRvbmx5IG91dEZ1bmN0aW9uQ29udHJvbCA9IG91dHB1dDxJU2Nyb2xsTWVhc3VyZUl0ZW1EaXJlY3Rpb25WZXJ0aWNhbEZ1bmN0aW9uc0NvbnRyb2w+KCk7XG4gIHJlYWRvbmx5IG91dERpdlZpcnR1YWwgPSBvdXRwdXQ8SFRNTERpdkVsZW1lbnQ+KCk7XG4gIHJlYWRvbmx5IG91dFBhZGRpbmdUb3AgPSBvdXRwdXQ8bnVtYmVyPigpO1xuXG4gIC8vICNyZWdpb24gSU5KRUNUXG4gIHByaXZhdGUgcmVhZG9ubHkgZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBzY3JvbGxFbCA9IHVudHJhY2tlZCgoKSA9PiB0aGlzLlNjcm9sbENvbnRhaW5lcik7XG4gICAgICBpZiAoIXNjcm9sbEVsIHx8ICF1bnRyYWNrZWQoKCkgPT4gdGhpcy5mdW5jdGlvbkdldEhlaWdodEl0ZW0oKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zKCk7XG4gICAgICB1bnRyYWNrZWQoYXN5bmMgKCkgPT4ge1xuICAgICAgICB0aGlzLnN0YXJ0LnNldCgwKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVG9wID0gc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICBjb25zdCBjb250YWluZXJIZWlnaHQgPSBzY3JvbGxFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICAgIGxldCBoZWlnaHQgPSAwO1xuICAgICAgICBjb25zdCBuZXdJdGVtczogQXJyYXk8SVNjcm9sbE1lYXN1cmVTdG9yZUl0ZW1WZXJ0aWNhbENvbnZlcnQ+ID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGl0ZW0gPSBpdGVtc1tpXTtcbiAgICAgICAgICBjb25zdCBuZXdJdGVtOiBJU2Nyb2xsTWVhc3VyZVN0b3JlSXRlbVZlcnRpY2FsQ29udmVydCA9IHsgcmVmOiBpdGVtLCBpdGVtSGVpZ2h0OiAwLCBzdGFydDogMCwgZW5kOiAwIH07XG4gICAgICAgICAgY29uc3QgaXRlbUhlaWdodCA9IGF3YWl0IHRoaXMuZnVuY3Rpb25HZXRIZWlnaHRJdGVtKCkoaXRlbSk7XG4gICAgICAgICAgbmV3SXRlbS5pdGVtSGVpZ2h0ID0gaXRlbUhlaWdodDtcbiAgICAgICAgICBuZXdJdGVtLnN0YXJ0ID0gaGVpZ2h0O1xuICAgICAgICAgIGhlaWdodCArPSBpdGVtSGVpZ2h0O1xuICAgICAgICAgIG5ld0l0ZW0uZW5kID0gaGVpZ2h0O1xuICAgICAgICAgIGlmIChuZXdJdGVtLmVuZCA8PSBjb250YWluZXJIZWlnaHQgKyBzY3JvbGxUb3ApIHtcbiAgICAgICAgICAgIHRoaXMuZW5kLnNldChpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbmV3SXRlbXMucHVzaChuZXdJdGVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RvcmVJdGVtcy5zZXQobmV3SXRlbXMpO1xuICAgICAgICB0aGlzLnZpZXdQb3J0SXRlbXMuc2V0KFxuICAgICAgICAgIHRoaXMuc3RvcmVJdGVtcygpXG4gICAgICAgICAgICAuc2xpY2UodGhpcy5zdGFydCgpLCB0aGlzLmVuZCgpICsgMylcbiAgICAgICAgICAgIC5tYXAoKGl0ZW0pID0+IGl0ZW0ucmVmKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm91dFZpZXdQb3J0SXRlbS5lbWl0KHRoaXMudmlld1BvcnRJdGVtcygpKTtcbiAgICAgICAgdGhpcy5vdXRQYWRkaW5nVG9wLmVtaXQoZ2V0KHRoaXMuc3RvcmVJdGVtcygpLCBgWyR7dGhpcy5zdGFydCgpfV0uc3RhcnRgLCAwKSk7XG5cbiAgICAgICAgdGhpcy5kaXZWaXJ0dWFsLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgdGhpcy5kaXZWaXJ0dWFsLnN0eWxlLnRvcCA9ICcwcHgnO1xuICAgICAgICB0aGlzLmRpdlZpcnR1YWwuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgICAgICB0aGlzLmRpdlZpcnR1YWwuc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcbiAgICAgICAgdGhpcy5kaXZWaXJ0dWFsLnN0eWxlLndpZHRoID0gJzFweCc7XG4gICAgICAgIHRoaXMuZGl2VmlydHVhbC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7IC8vIMSQ4bqjbSBi4bqjbyBhbiB0b8OgbiBraMO0bmcgaGnhu4NuIHRo4buLXG4gICAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ3JlbGF0aXZlJyk7XG4gICAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2gtZnVsbCcpO1xuICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5zdHlsZS5wYWRkaW5nVG9wID0gJzBweCc7XG4gICAgICAgIHNjcm9sbEVsLmFwcGVuZCh0aGlzLmRpdlZpcnR1YWwpO1xuICAgICAgICB0aGlzLm91dERpdlZpcnR1YWwuZW1pdCh0aGlzLmRpdlZpcnR1YWwpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmRlc3Ryb3lSZWYub25EZXN0cm95KCgpID0+IHtcbiAgICAgIHRoaXMuZGl2VmlydHVhbC5yZW1vdmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGZyb21FdmVudDxFdmVudD4odGhpcy5TY3JvbGxDb250YWluZXIsICdzY3JvbGwnKVxuICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmhhbmRsZXJTY3JvbGwoKSk7XG4gICAgICB0aGlzLm91dEZ1bmN0aW9uQ29udHJvbC5lbWl0KHRoaXMuRnVuY3Rpb25zQ29udHJvbCk7XG4gICAgfSk7XG4gIH1cblxuICAvLyAjcmVnaW9uIFBVQkxJQyBBUElcbiAgcHVibGljIGdldCBGdW5jdGlvbnNDb250cm9sKCk6IElTY3JvbGxNZWFzdXJlSXRlbURpcmVjdGlvblZlcnRpY2FsRnVuY3Rpb25zQ29udHJvbCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjcm9sbEludG86IHRoaXMuc2Nyb2xsSW50by5iaW5kKHRoaXMpLFxuICAgICAgc2Nyb2xsVG9Qb3NpdGlvbjogdGhpcy5zY3JvbGxUb1Bvc2l0aW9uLmJpbmQodGhpcyksXG4gICAgICBzY3JvbGxUb0luZGV4OiB0aGlzLnNjcm9sbFRvSW5kZXguYmluZCh0aGlzKSxcbiAgICAgIHJlQ2FsY3VsYXRvclZpZXdQb3J0OiB0aGlzLnJlQ2FsY3VsYXRvclZpZXdQb3J0LmJpbmQodGhpcyksXG4gICAgICBnZXRWaWV3UG9ydEl0ZW1zOiAoKSA9PiB0aGlzLnZpZXdQb3J0SXRlbXMoKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gI3JlZ2lvbiBQUklWQVRFIE1FVEhPRFNcbiAgcHJpdmF0ZSBnZXQgU2Nyb2xsQ29udGFpbmVyKCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50U2Nyb2xsKCkgfHwgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIGZpbmRTdGFydEluZGV4KHN0b3JlOiBBcnJheTxJU2Nyb2xsTWVhc3VyZVN0b3JlSXRlbVZlcnRpY2FsQ29udmVydD4sIHNjcm9sbFRvcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgbG93ID0gMDtcbiAgICBsZXQgaGlnaCA9IHN0b3JlLmxlbmd0aCAtIDE7XG4gICAgbGV0IGFucyA9IHN0b3JlLmxlbmd0aCAtIDE7IC8vIERlZmF1bHQgdG8gbGFzdCBpdGVtIGlmIHNjcm9sbGVkIHBhc3QgYm90dG9tIChydWJiZXIgYmFuZCBlZmZlY3QpXG4gICAgd2hpbGUgKGxvdyA8PSBoaWdoKSB7XG4gICAgICBjb25zdCBtaWQgPSBNYXRoLmZsb29yKChsb3cgKyBoaWdoKSAvIDIpO1xuICAgICAgaWYgKHN0b3JlW21pZF0uZW5kID49IHNjcm9sbFRvcCkge1xuICAgICAgICBhbnMgPSBtaWQ7XG4gICAgICAgIGhpZ2ggPSBtaWQgLSAxOyAvLyBUcnkgdG8gZmluZCBlYXJsaWVyXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb3cgPSBtaWQgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYW5zO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kRW5kSW5kZXgoc3RvcmU6IEFycmF5PElTY3JvbGxNZWFzdXJlU3RvcmVJdGVtVmVydGljYWxDb252ZXJ0Piwgc2Nyb2xsQm90dG9tOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBsb3cgPSAwO1xuICAgIGxldCBoaWdoID0gc3RvcmUubGVuZ3RoIC0gMTtcbiAgICBsZXQgYW5zID0gMDsgLy8gRGVmYXVsdCB0byBmaXJzdCBpdGVtIGlmIHJ1YmJlci1iYW5kZWQgYWJvdmUgdGhlIHRvcFxuICAgIHdoaWxlIChsb3cgPD0gaGlnaCkge1xuICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgIGlmIChzdG9yZVttaWRdLnN0YXJ0IDw9IHNjcm9sbEJvdHRvbSkge1xuICAgICAgICBhbnMgPSBtaWQ7XG4gICAgICAgIGxvdyA9IG1pZCArIDE7IC8vIFRyeSB0byBmaW5kIGxhdGVyXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBoaWdoID0gbWlkIC0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFucztcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlclNjcm9sbCgpIHtcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuc3RvcmVJdGVtcygpO1xuICAgIGlmICghc3RvcmU/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzY3JvbGxFbCA9IHRoaXMuU2Nyb2xsQ29udGFpbmVyO1xuICAgIGNvbnN0IHNjcm9sbFRvcCA9IHNjcm9sbEVsLnNjcm9sbFRvcDtcbiAgICBjb25zdCBjb250YWluZXJIZWlnaHQgPSBzY3JvbGxFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgXG4gICAgLy8gVXRpbGl6ZSBCaW5hcnkgU2VhcmNoIGZvciBvcHRpbWFsIE8obG9nIE4pIGRpc2NvdmVyeVxuICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5maW5kU3RhcnRJbmRleChzdG9yZSwgc2Nyb2xsVG9wKTtcbiAgICBjb25zdCBlbmQgPSB0aGlzLmZpbmRFbmRJbmRleChzdG9yZSwgc2Nyb2xsVG9wICsgY29udGFpbmVySGVpZ2h0KTtcblxuICAgIHRoaXMuZW5kLnNldChlbmQpO1xuXG4gICAgaWYgKHN0YXJ0ICE9PSB0aGlzLnN0YXJ0KCkpIHtcbiAgICAgIHRoaXMuc3RhcnQuc2V0KHN0YXJ0KTtcbiAgICAgIC8vIFVzZSBsb2dpY2FsIE9SIGZvciBmYWxsYmFjayB3aGVuIHN0YXJ0IGlzIGludmFsaWQuIEJ1dCBiaW5hcnkgc2VhcmNoIGd1YXJhbnRlZXMgdmFsaWQgaW5kZXguXG4gICAgICBjb25zdCBwYWRkaW5nVG9wID0gc3RvcmVbc3RhcnRdPy5zdGFydCB8fCAwO1xuICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuc3R5bGUucGFkZGluZ1RvcCA9IGAke3BhZGRpbmdUb3B9cHhgO1xuICAgICAgdGhpcy5vdXRQYWRkaW5nVG9wLmVtaXQocGFkZGluZ1RvcCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RhcnQoKSA8IDApIHtcbiAgICAgIHRoaXMuc3RhcnQuc2V0KDApO1xuICAgIH1cbiAgICB0aGlzLnZpZXdQb3J0SXRlbXMuc2V0KHN0b3JlLnNsaWNlKHRoaXMuc3RhcnQoKSwgdGhpcy5lbmQoKSArIDMpLm1hcCgoaXRlbSkgPT4gaXRlbS5yZWYpKTtcbiAgICB0aGlzLm91dFZpZXdQb3J0SXRlbS5lbWl0KHRoaXMudmlld1BvcnRJdGVtcygpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2Nyb2xsSW50byhpdGVtU2Nyb2xsOiBhbnkpIHtcbiAgICBjb25zdCBpdGVtRm91bmQgPSB0aGlzLnN0b3JlSXRlbXMoKS5maW5kKChpdGVtKSA9PiBpdGVtLnJlZiA9PT0gaXRlbVNjcm9sbCk7XG4gICAgaWYgKCFpdGVtRm91bmQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5TY3JvbGxDb250YWluZXIuc2Nyb2xsVG9wID0gaXRlbUZvdW5kLnN0YXJ0O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzY3JvbGxUb1Bvc2l0aW9uKHBvc2l0aW9uOiBudW1iZXIpIHtcbiAgICB0aGlzLlNjcm9sbENvbnRhaW5lci5zY3JvbGxUb3AgPSBwb3NpdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2Nyb2xsVG9JbmRleChpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgaXRlbU9mSW5kZXggPSB0aGlzLnN0b3JlSXRlbXMoKVtpbmRleF07XG4gICAgaWYgKCFpdGVtT2ZJbmRleCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLlNjcm9sbENvbnRhaW5lci5zY3JvbGxUb3AgPSBpdGVtT2ZJbmRleC5zdGFydDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVDYWxjdWxhdG9yVmlld1BvcnQoKSB7XG4gICAgbGV0IGhlaWdodCA9IDA7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLnN0b3JlSXRlbXMoKTtcblxuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgY29uc3QgaXRlbUhlaWdodCA9IGF3YWl0IHRoaXMuZnVuY3Rpb25HZXRIZWlnaHRJdGVtKCkoaXRlbS5yZWYpO1xuICAgICAgaXRlbS5pdGVtSGVpZ2h0ID0gaXRlbUhlaWdodDtcbiAgICAgIGl0ZW0uc3RhcnQgPSBoZWlnaHQ7XG4gICAgICBoZWlnaHQgKz0gaXRlbUhlaWdodDtcbiAgICAgIGl0ZW0uZW5kID0gaGVpZ2h0O1xuICAgIH1cblxuICAgIHRoaXMuc3RvcmVJdGVtcy5zZXQoWy4uLml0ZW1zXSk7XG4gICAgdGhpcy5kaXZWaXJ0dWFsLnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG4gICAgdGhpcy5oYW5kbGVyU2Nyb2xsKCk7XG4gIH1cbn1cbiJdfQ==
228
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlyZWN0aW9uLXZlcnRpY2FsLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMtdWkvY29tcG9uZW50cy9zY3JvbGwtbWVhc3VyZS1pdGVtcy9kaXJlY3Rpb24tdmVydGljYWwvc3JjL2RpcmVjdGlvbi12ZXJ0aWNhbC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseUZBQXlGO0FBQ3pGLHVEQUF1RDtBQUN2RCxPQUFPLEVBQWlCLFVBQVUsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25JLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7O0FBUWpDLE1BQU0sT0FBTyxpREFBaUQ7SUFDNUQsbUJBQW1CO0lBQ25CLDhFQUE4RTtJQUM3RCxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBRXpCLGFBQWEsR0FBRyxNQUFNLENBQWEsRUFBRSxDQUFDLENBQUM7SUFDdkMsS0FBSyxHQUFHLE1BQU0sQ0FBUyxDQUFDLENBQUMsQ0FBQztJQUMxQixHQUFHLEdBQUcsTUFBTSxDQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLFVBQVUsR0FBRyxNQUFNLENBQWdELEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLFVBQVUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNDLGNBQWMsQ0FBa0I7SUFDeEMsbUdBQW1HO0lBQzNGLGtCQUFrQixDQUFVO0lBQ3BDLGtHQUFrRztJQUMxRixjQUFjLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLDBGQUEwRjtJQUNsRixxQkFBcUIsR0FBRyxLQUFLLENBQUM7SUFFdEMsZ0JBQWdCO0lBQ1AsYUFBYSxHQUFH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LEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQztRQUM3QyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQzt3R0ExT1UsaURBQWlEOzRGQUFqRCxpREFBaUQ7OzRGQUFqRCxpREFBaUQ7a0JBTDdELFNBQVM7bUJBQUM7b0JBQ1QsOERBQThEO29CQUM5RCxRQUFRLEVBQUUscURBQXFEO29CQUMvRCxVQUFVLEVBQUUsSUFBSTtpQkFDakIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDT05WRU5USU9OLUVYQ0VQVDogYW55IOKAlCBHZW5lcmljIGRpcmVjdGl2ZSB3b3JrcyB3aXRoIHVua25vd24gaXRlbSB0eXBlcyBmcm9tIGNvbnN1bWVyXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5pbXBvcnQgeyBBZnRlclZpZXdJbml0LCBEZXN0cm95UmVmLCBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIGVmZmVjdCwgaW5qZWN0LCBpbnB1dCwgb3V0cHV0LCBzaWduYWwsIHVudHJhY2tlZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgZnJvbUV2ZW50IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBJU2Nyb2xsTWVhc3VyZUl0ZW1EaXJlY3Rpb25WZXJ0aWNhbEZ1bmN0aW9uc0NvbnRyb2wsIElTY3JvbGxNZWFzdXJlU3RvcmVJdGVtVmVydGljYWxDb252ZXJ0IH0gZnJvbSAnLi9pbnRlcmZhY2VzL2RpcmVjdGlvbi12ZXJ0aWNhbC5pbnRlcmZhY2UnO1xuXG5ARGlyZWN0aXZlKHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9kaXJlY3RpdmUtc2VsZWN0b3JcbiAgc2VsZWN0b3I6ICdbTGlic1VpU2Nyb2xsTWVhc3VyZUl0ZW1EaXJlY3Rpb25WZXJ0aWNhbERpcmVjdGl2ZV0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlTY3JvbGxNZWFzdXJlSXRlbURpcmVjdGlvblZlcnRpY2FsRGlyZWN0aXZlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCB7XG4gIC8vICNyZWdpb24gUFJPUEVSVFlcbiAgLyoqIFPhu5EgaXRlbSBidWZmZXIgcmVuZGVyIHRow6ptIHNhdSB2aWV3cG9ydCDEkeG7gyB0csOhbmggdHLhuq9uZyB2w7luZyBraGkgc2Nyb2xsLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGJ1ZmZlckFoZWFkID0gMztcblxuICBwcml2YXRlIHZpZXdQb3J0SXRlbXMgPSBzaWduYWw8QXJyYXk8YW55Pj4oW10pO1xuICBwcml2YXRlIHN0YXJ0ID0gc2lnbmFsPG51bWJlcj4oMCk7XG4gIHByaXZhdGUgZW5kID0gc2lnbmFsPG51bWJlcj4oMCk7XG4gIHByaXZhdGUgc3RvcmVJdGVtcyA9IHNpZ25hbDxBcnJheTxJU2Nyb2xsTWVhc3VyZVN0b3JlSXRlbVZlcnRpY2FsQ29udmVydD4+KFtdKTtcbiAgcHJpdmF0ZSBkaXZWaXJ0dWFsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIHByaXZhdGUgcmVzaXplT2JzZXJ2ZXI/OiBSZXNpemVPYnNlcnZlcjtcbiAgLyoqIFRoYW0gY2hp4bq/dSBzZXRUaW1lb3V0IGPhu6dhIG5nQWZ0ZXJWaWV3SW5pdCDEkeG7gyBjbGVhciBraGkgZGVzdHJveSDigJQgY2jhurduIFJlc2l6ZU9ic2VydmVyIG3hu5MgY8O0aS4gKi9cbiAgcHJpdmF0ZSB0aW1lckFmdGVyVmlld0luaXQ/OiBudW1iZXI7XG4gIC8qKiBUb2tlbiBuaOG6rW4gZOG6oW5nIGzhuqduIGVmZmVjdCBjaOG6oXkgaGnhu4duIHThuqFpLiBBc3luYyDEkW8gaGVpZ2h0IHhvbmcgc+G6vSBi4buPIGvhur90IHF14bqjIG7hur91IHRva2VuIMSR4buVaS4gKi9cbiAgcHJpdmF0ZSBleGVjdXRpb25Ub2tlbiA9IDA7XG4gIC8qKiBTdHlsZSArIERPTSBob29rIGPhu6dhIGRpdlZpcnR1YWwgY2jhu4kgY+G6p24ga2jhu59pIHThuqFvIG3hu5l0IGzhuqduIGNobyBj4bqjIHbDsm5nIMSR4budaSBkaXJlY3RpdmUuICovXG4gIHByaXZhdGUgZGl2VmlydHVhbEluaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgLy8gI3JlZ2lvbiBJTlBVVFxuICByZWFkb25seSBlbGVtZW50U2Nyb2xsID0gaW5wdXQucmVxdWlyZWQ8SFRNTEVsZW1lbnQ+KCk7XG4gIHJlYWRvbmx5IGZ1bmN0aW9uR2V0SGVpZ2h0SXRlbSA9IGlucHV0LnJlcXVpcmVkPChpdGVtOiBhbnkpID0+IFByb21pc2U8bnVtYmVyPj4oKTtcbiAgcmVhZG9ubHkgaXRlbXMgPSBpbnB1dC5yZXF1aXJlZDxBcnJheTxhbnk+PigpO1xuXG4gIC8vICNyZWdpb24gT1VUUFVUXG4gIHJlYWRvbmx5IG91dFZpZXdQb3J0SXRlbSA9IG91dHB1dDxBcnJheTxhbnk+PigpO1xuICByZWFkb25seSBvdXRGdW5jdGlvbkNvbnRyb2wgPSBvdXRwdXQ8SVNjcm9sbE1lYXN1cmVJdGVtRGlyZWN0aW9uVmVydGljYWxGdW5jdGlvbnNDb250cm9sPigpO1xuICByZWFkb25seSBvdXREaXZWaXJ0dWFsID0gb3V0cHV0PEhUTUxEaXZFbGVtZW50PigpO1xuICByZWFkb25seSBvdXRQYWRkaW5nVG9wID0gb3V0cHV0PG51bWJlcj4oKTtcblxuICAvLyAjcmVnaW9uIElOSkVDVFxuICBwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnRSZWYgPSBpbmplY3QoRWxlbWVudFJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zKCk7XG4gICAgICBjb25zdCBteVRva2VuID0gKyt0aGlzLmV4ZWN1dGlvblRva2VuO1xuICAgICAgdW50cmFja2VkKGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3Qgc2Nyb2xsRWwgPSB0aGlzLlNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25HZXRIZWlnaHRJdGVtID0gdGhpcy5mdW5jdGlvbkdldEhlaWdodEl0ZW0oKTtcbiAgICAgICAgaWYgKCFzY3JvbGxFbCB8fCAhZnVuY3Rpb25HZXRIZWlnaHRJdGVtKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gxJBvIGhlaWdodCB04bqldCBj4bqjIGl0ZW0gc29uZyBzb25nIOKAlCByw7p0IG5n4bqvbiB0aOG7nWkgZ2lhbiBjaG8gbGlzdCBs4bubbi5cbiAgICAgICAgY29uc3QgaGVpZ2h0cyA9IGF3YWl0IFByb21pc2UuYWxsKGl0ZW1zLm1hcCgoaXQpID0+IGZ1bmN0aW9uR2V0SGVpZ2h0SXRlbShpdCkpKTtcbiAgICAgICAgLy8gQuG7iyBodeG7tyB2w6wgY8OzIGzGsOG7o3QgaXRlbXMoKSBt4bubaSBjaOG6oXkgc2F1IOKAlCBi4buPIGvhur90IHF14bqjIGPFqSB0csOhbmggxJHDqCBzdGF0ZS5cbiAgICAgICAgaWYgKG15VG9rZW4gIT09IHRoaXMuZXhlY3V0aW9uVG9rZW4pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnN0YXJ0LnNldCgwKTtcbiAgICAgICAgY29uc3Qgc2Nyb2xsVG9wID0gc2Nyb2xsRWwuc2Nyb2xsVG9wO1xuICAgICAgICBjb25zdCBjb250YWluZXJIZWlnaHQgPSBzY3JvbGxFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgICAgIGxldCBoZWlnaHQgPSAwO1xuICAgICAgICBsZXQgZW5kTG9jYWwgPSAwO1xuICAgICAgICBjb25zdCBuZXdJdGVtczogQXJyYXk8SVNjcm9sbE1lYXN1cmVTdG9yZUl0ZW1WZXJ0aWNhbENvbnZlcnQ+ID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGl0ZW1IZWlnaHQgPSBoZWlnaHRzW2ldO1xuICAgICAgICAgIGNvbnN0IG5ld0l0ZW06IElTY3JvbGxNZWFzdXJlU3RvcmVJdGVtVmVydGljYWxDb252ZXJ0ID0geyByZWY6IGl0ZW1zW2ldLCBpdGVtSGVpZ2h0LCBzdGFydDogaGVpZ2h0LCBlbmQ6IDAgfTtcbiAgICAgICAgICBoZWlnaHQgKz0gaXRlbUhlaWdodDtcbiAgICAgICAgICBuZXdJdGVtLmVuZCA9IGhlaWdodDtcbiAgICAgICAgICBpZiAobmV3SXRlbS5lbmQgPD0gY29udGFpbmVySGVpZ2h0ICsgc2Nyb2xsVG9wKSB7XG4gICAgICAgICAgICBlbmRMb2NhbCA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG5ld0l0ZW1zLnB1c2gobmV3SXRlbSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gU2V0IGVuZCBt4buZdCBs4bqnbiB0aGF5IHbDrCBnaGkgbeG7l2kgdsOybmcgbOG6t3Ag4oCUIHRyw6FuaCBub3RpZnkgY29uc3VtZXIgTiBs4bqnbi5cbiAgICAgICAgdGhpcy5lbmQuc2V0KGVuZExvY2FsKTtcbiAgICAgICAgdGhpcy5zdG9yZUl0ZW1zLnNldChuZXdJdGVtcyk7XG5cbiAgICAgICAgLy8gS2jhu59pIHThuqFvIHN0eWxlICsgRE9NIGhvb2sgY+G7p2EgZGl2VmlydHVhbCDEkcO6bmcgbeG7mXQgbOG6p24uXG4gICAgICAgIGlmICghdGhpcy5kaXZWaXJ0dWFsSW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgICB0aGlzLmRpdlZpcnR1YWwuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICAgIHRoaXMuZGl2VmlydHVhbC5zdHlsZS50b3AgPSAnMHB4JztcbiAgICAgICAgICB0aGlzLmRpdlZpcnR1YWwuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgICAgICAgIHRoaXMuZGl2VmlydHVhbC5zdHlsZS53aWR0aCA9ICcxcHgnO1xuICAgICAgICAgIHRoaXMuZGl2VmlydHVhbC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7IC8vIMSQ4bqjbSBi4bqjbyBhbiB0b8OgbiBraMO0bmcgaGnhu4NuIHRo4buLXG4gICAgICAgICAgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmFkZCgncmVsYXRpdmUnKTtcbiAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdoLWZ1bGwnKTtcbiAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5zdHlsZS5wYWRkaW5nVG9wID0gJzBweCc7XG4gICAgICAgICAgc2Nyb2xsRWwuYXBwZW5kKHRoaXMuZGl2VmlydHVhbCk7XG4gICAgICAgICAgdGhpcy5kaXZWaXJ0dWFsSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgIHRoaXMub3V0RGl2VmlydHVhbC5lbWl0KHRoaXMuZGl2VmlydHVhbCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSGVpZ2h0IHThu5VuZyB0aOG7gyDEkeG7lWkgdGhlbyBkYXRhc2V0IOKGkiBj4bqnbiB1cGRhdGUgbeG7l2kgbMaw4bujdC5cbiAgICAgICAgdGhpcy5kaXZWaXJ0dWFsLnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG5cbiAgICAgICAgLy8gY29udGFpbmVySGVpZ2h0IGzDumMgxJHhuqd1IGPDsyB0aOG7gyA9IDAgKERPTSBjaMawYSBsYXlvdXQpLCBraGnhur9uIGVuZCBnaeG7r1xuICAgICAgICAvLyBuZ3V5w6puIDAgdsOgIGNo4buJIHJlbmRlciBidWZmZXJBaGVhZCBpdGVtIMSR4bqndS4gUmUtxJFvIGLhurFuZyBoYW5kbGVyU2Nyb2xsIHNhdSBraGkgdsOybmdcbiAgICAgICAgLy8gbOG6t3AgYXdhaXQgeG9uZyAobGF5b3V0IHRoxrDhu51uZyDEkcOjIGhvw6BuIHThuqV0KSDEkeG7gyBlbmQgcmEgxJHDum5nIGdpw6EgdHLhu4suXG4gICAgICAgIHRoaXMuaGFuZGxlclNjcm9sbCgpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmRlc3Ryb3lSZWYub25EZXN0cm95KCgpID0+IHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVyQWZ0ZXJWaWV3SW5pdCk7XG4gICAgICB0aGlzLmRpdlZpcnR1YWwucmVtb3ZlKCk7XG4gICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyPy5kaXNjb25uZWN0KCk7XG4gICAgfSk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy50aW1lckFmdGVyVmlld0luaXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGZyb21FdmVudDxFdmVudD4odGhpcy5TY3JvbGxDb250YWluZXIsICdzY3JvbGwnKVxuICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmhhbmRsZXJTY3JvbGwoKSk7XG4gICAgICB0aGlzLm91dEZ1bmN0aW9uQ29udHJvbC5lbWl0KHRoaXMuRnVuY3Rpb25zQ29udHJvbCk7XG5cbiAgICAgIC8vIFJlLXTDrW5oIHZpZXdwb3J0IHNhdSBraGkgY29udGFpbmVyIGPDsyBrw61jaCB0aMaw4bubYyB0aOG6rXQuXG4gICAgICAvLyBM4bqnbiDEkeG6p3UgcmVuZGVyLCBnZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQgY8OzIHRo4buDID0gMCBuw6puIGVuZCBnaeG7ryBnacOhIHRy4buLIDAsXG4gICAgICAvLyBjaOG7iSBoaeG7g24gdGjhu4sgYnVmZmVyQWhlYWQgaXRlbSDEkeG6p3UuIFJlc2l6ZU9ic2VydmVyIGZpcmUgbmdheSBraGkgb2JzZXJ2ZSB2w6AgbeG7l2kgbOG6p25cbiAgICAgIC8vIGNvbnRhaW5lciDEkeG7lWkgc2l6ZSBz4bq9IGvDqW8gZW5kIHbhu4EgxJHDum5nIGdpw6EgdHLhu4suXG4gICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKCgpID0+IHRoaXMuaGFuZGxlclNjcm9sbCgpKTtcbiAgICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLlNjcm9sbENvbnRhaW5lcik7XG4gICAgfSk7XG4gIH1cblxuICAvLyAjcmVnaW9uIFBVQkxJQyBBUElcbiAgcHVibGljIGdldCBGdW5jdGlvbnNDb250cm9sKCk6IElTY3JvbGxNZWFzdXJlSXRlbURpcmVjdGlvblZlcnRpY2FsRnVuY3Rpb25zQ29udHJvbCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjcm9sbEludG86IHRoaXMuc2Nyb2xsSW50by5iaW5kKHRoaXMpLFxuICAgICAgc2Nyb2xsVG9Qb3NpdGlvbjogdGhpcy5zY3JvbGxUb1Bvc2l0aW9uLmJpbmQodGhpcyksXG4gICAgICBzY3JvbGxUb0luZGV4OiB0aGlzLnNjcm9sbFRvSW5kZXguYmluZCh0aGlzKSxcbiAgICAgIHJlQ2FsY3VsYXRvclZpZXdQb3J0OiB0aGlzLnJlQ2FsY3VsYXRvclZpZXdQb3J0LmJpbmQodGhpcyksXG4gICAgICBnZXRWaWV3UG9ydEl0ZW1zOiAoKSA9PiB0aGlzLnZpZXdQb3J0SXRlbXMoKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gI3JlZ2lvbiBQUklWQVRFIE1FVEhPRFNcbiAgcHJpdmF0ZSBnZXQgU2Nyb2xsQ29udGFpbmVyKCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5lbGVtZW50U2Nyb2xsKCkgfHwgdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIGZpbmRTdGFydEluZGV4KHN0b3JlOiBBcnJheTxJU2Nyb2xsTWVhc3VyZVN0b3JlSXRlbVZlcnRpY2FsQ29udmVydD4sIHNjcm9sbFRvcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgbG93ID0gMDtcbiAgICBsZXQgaGlnaCA9IHN0b3JlLmxlbmd0aCAtIDE7XG4gICAgbGV0IGFucyA9IHN0b3JlLmxlbmd0aCAtIDE7IC8vIERlZmF1bHQgdG8gbGFzdCBpdGVtIGlmIHNjcm9sbGVkIHBhc3QgYm90dG9tIChydWJiZXIgYmFuZCBlZmZlY3QpXG4gICAgd2hpbGUgKGxvdyA8PSBoaWdoKSB7XG4gICAgICBjb25zdCBtaWQgPSBNYXRoLmZsb29yKChsb3cgKyBoaWdoKSAvIDIpO1xuICAgICAgaWYgKHN0b3JlW21pZF0uZW5kID49IHNjcm9sbFRvcCkge1xuICAgICAgICBhbnMgPSBtaWQ7XG4gICAgICAgIGhpZ2ggPSBtaWQgLSAxOyAvLyBUcnkgdG8gZmluZCBlYXJsaWVyXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb3cgPSBtaWQgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYW5zO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kRW5kSW5kZXgoc3RvcmU6IEFycmF5PElTY3JvbGxNZWFzdXJlU3RvcmVJdGVtVmVydGljYWxDb252ZXJ0Piwgc2Nyb2xsQm90dG9tOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCBsb3cgPSAwO1xuICAgIGxldCBoaWdoID0gc3RvcmUubGVuZ3RoIC0gMTtcbiAgICBsZXQgYW5zID0gMDsgLy8gRGVmYXVsdCB0byBmaXJzdCBpdGVtIGlmIHJ1YmJlci1iYW5kZWQgYWJvdmUgdGhlIHRvcFxuICAgIHdoaWxlIChsb3cgPD0gaGlnaCkge1xuICAgICAgY29uc3QgbWlkID0gTWF0aC5mbG9vcigobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgIGlmIChzdG9yZVttaWRdLnN0YXJ0IDw9IHNjcm9sbEJvdHRvbSkge1xuICAgICAgICBhbnMgPSBtaWQ7XG4gICAgICAgIGxvdyA9IG1pZCArIDE7IC8vIFRyeSB0byBmaW5kIGxhdGVyXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBoaWdoID0gbWlkIC0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFucztcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlclNjcm9sbCgpIHtcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuc3RvcmVJdGVtcygpO1xuICAgIGlmICghc3RvcmU/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzY3JvbGxFbCA9IHRoaXMuU2Nyb2xsQ29udGFpbmVyO1xuICAgIGNvbnN0IHNjcm9sbFRvcCA9IHNjcm9sbEVsLnNjcm9sbFRvcDtcbiAgICBjb25zdCBjb250YWluZXJIZWlnaHQgPSBzY3JvbGxFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG5cbiAgICAvLyBVdGlsaXplIEJpbmFyeSBTZWFyY2ggZm9yIG9wdGltYWwgTyhsb2cgTikgZGlzY292ZXJ5XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmZpbmRTdGFydEluZGV4KHN0b3JlLCBzY3JvbGxUb3ApO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuZmluZEVuZEluZGV4KHN0b3JlLCBzY3JvbGxUb3AgKyBjb250YWluZXJIZWlnaHQpO1xuXG4gICAgaWYgKGVuZCAhPT0gdGhpcy5lbmQoKSkge1xuICAgICAgdGhpcy5lbmQuc2V0KGVuZCk7XG4gICAgfVxuXG4gICAgaWYgKHN0YXJ0ICE9PSB0aGlzLnN0YXJ0KCkpIHtcbiAgICAgIHRoaXMuc3RhcnQuc2V0KHN0YXJ0KTtcbiAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZ3VhcmFudGVlcyBgc3RhcnRgIGzDoCBpbmRleCBo4bujcCBs4buHIHRyb25nIHN0b3JlLlxuICAgICAgY29uc3QgcGFkZGluZ1RvcCA9IHN0b3JlW3N0YXJ0XS5zdGFydDtcbiAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnN0eWxlLnBhZGRpbmdUb3AgPSBgJHtwYWRkaW5nVG9wfXB4YDtcbiAgICAgIHRoaXMub3V0UGFkZGluZ1RvcC5lbWl0KHBhZGRpbmdUb3ApO1xuICAgIH1cbiAgICB0aGlzLnZpZXdQb3J0SXRlbXMuc2V0KHN0b3JlLnNsaWNlKHRoaXMuc3RhcnQoKSwgdGhpcy5lbmQoKSArIHRoaXMuYnVmZmVyQWhlYWQpLm1hcCgoaXRlbSkgPT4gaXRlbS5yZWYpKTtcbiAgICB0aGlzLm91dFZpZXdQb3J0SXRlbS5lbWl0KHRoaXMudmlld1BvcnRJdGVtcygpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2Nyb2xsSW50byhpdGVtU2Nyb2xsOiBhbnkpIHtcbiAgICBjb25zdCBpdGVtRm91bmQgPSB0aGlzLnN0b3JlSXRlbXMoKS5maW5kKChpdGVtKSA9PiBpdGVtLnJlZiA9PT0gaXRlbVNjcm9sbCk7XG4gICAgaWYgKCFpdGVtRm91bmQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5TY3JvbGxDb250YWluZXIuc2Nyb2xsVG9wID0gaXRlbUZvdW5kLnN0YXJ0O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzY3JvbGxUb1Bvc2l0aW9uKHBvc2l0aW9uOiBudW1iZXIpIHtcbiAgICB0aGlzLlNjcm9sbENvbnRhaW5lci5zY3JvbGxUb3AgPSBwb3NpdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2Nyb2xsVG9JbmRleChpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgaXRlbU9mSW5kZXggPSB0aGlzLnN0b3JlSXRlbXMoKVtpbmRleF07XG4gICAgaWYgKCFpdGVtT2ZJbmRleCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLlNjcm9sbENvbnRhaW5lci5zY3JvbGxUb3AgPSBpdGVtT2ZJbmRleC5zdGFydDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVDYWxjdWxhdG9yVmlld1BvcnQoKSB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLnN0b3JlSXRlbXMoKTtcbiAgICBjb25zdCBmbiA9IHRoaXMuZnVuY3Rpb25HZXRIZWlnaHRJdGVtKCk7XG4gICAgLy8gxJBvIHNvbmcgc29uZyDEkeG7gyByw7p0IG5n4bqvbiB0aOG7nWkgZ2lhbiB0aGF5IHbDrCBhd2FpdCB0deG6p24gdOG7sS5cbiAgICBjb25zdCBoZWlnaHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoaXRlbXMubWFwKChpdCkgPT4gZm4oaXQucmVmKSkpO1xuXG4gICAgbGV0IGhlaWdodCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgY29uc3QgaXRlbUhlaWdodCA9IGhlaWdodHNbaV07XG4gICAgICBpdGVtLml0ZW1IZWlnaHQgPSBpdGVtSGVpZ2h0O1xuICAgICAgaXRlbS5zdGFydCA9IGhlaWdodDtcbiAgICAgIGhlaWdodCArPSBpdGVtSGVpZ2h0O1xuICAgICAgaXRlbS5lbmQgPSBoZWlnaHQ7XG4gICAgfVxuXG4gICAgdGhpcy5zdG9yZUl0ZW1zLnNldChbLi4uaXRlbXNdKTtcbiAgICB0aGlzLmRpdlZpcnR1YWwuc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcbiAgICB0aGlzLmhhbmRsZXJTY3JvbGwoKTtcbiAgfVxufVxuIl19
@@ -1,18 +1,26 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { signal, input, output, inject, ElementRef, DestroyRef, effect, untracked, Directive } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { get } from '@libs-ui/utils';
5
4
  import { fromEvent } from 'rxjs';
6
5
 
7
6
  // CONVENTION-EXCEPT: any — Generic directive works with unknown item types from consumer
8
7
  /* eslint-disable @typescript-eslint/no-explicit-any */
9
8
  class LibsUiScrollMeasureItemDirectionVerticalDirective {
10
9
  // #region PROPERTY
10
+ /** Số item buffer render thêm sau viewport để tránh trắng vùng khi scroll. */
11
+ bufferAhead = 3;
11
12
  viewPortItems = signal([]);
12
13
  start = signal(0);
13
14
  end = signal(0);
14
15
  storeItems = signal([]);
15
16
  divVirtual = document.createElement('div');
17
+ resizeObserver;
18
+ /** Tham chiếu setTimeout của ngAfterViewInit để clear khi destroy — chặn ResizeObserver mồ côi. */
19
+ timerAfterViewInit;
20
+ /** Token nhận dạng lần effect chạy hiện tại. Async đo height xong sẽ bỏ kết quả nếu token đổi. */
21
+ executionToken = 0;
22
+ /** Style + DOM hook của divVirtual chỉ cần khởi tạo một lần cho cả vòng đời directive. */
23
+ divVirtualInitialized = false;
16
24
  // #region INPUT
17
25
  elementScroll = input.required();
18
26
  functionGetHeightItem = input.required();
@@ -27,59 +35,79 @@ class LibsUiScrollMeasureItemDirectionVerticalDirective {
27
35
  destroyRef = inject(DestroyRef);
28
36
  constructor() {
29
37
  effect(() => {
30
- const scrollEl = untracked(() => this.ScrollContainer);
31
- if (!scrollEl || !untracked(() => this.functionGetHeightItem())) {
32
- return;
33
- }
34
38
  const items = this.items();
39
+ const myToken = ++this.executionToken;
35
40
  untracked(async () => {
41
+ const scrollEl = this.ScrollContainer;
42
+ const functionGetHeightItem = this.functionGetHeightItem();
43
+ if (!scrollEl || !functionGetHeightItem) {
44
+ return;
45
+ }
46
+ // Đo height tất cả item song song — rút ngắn thời gian cho list lớn.
47
+ const heights = await Promise.all(items.map((it) => functionGetHeightItem(it)));
48
+ // Bị huỷ vì có lượt items() mới chạy sau — bỏ kết quả cũ tránh đè state.
49
+ if (myToken !== this.executionToken) {
50
+ return;
51
+ }
36
52
  this.start.set(0);
37
53
  const scrollTop = scrollEl.scrollTop;
38
54
  const containerHeight = scrollEl.getBoundingClientRect().height;
39
55
  let height = 0;
56
+ let endLocal = 0;
40
57
  const newItems = [];
41
58
  for (let i = 0; i < items.length; i++) {
42
- const item = items[i];
43
- const newItem = { ref: item, itemHeight: 0, start: 0, end: 0 };
44
- const itemHeight = await this.functionGetHeightItem()(item);
45
- newItem.itemHeight = itemHeight;
46
- newItem.start = height;
59
+ const itemHeight = heights[i];
60
+ const newItem = { ref: items[i], itemHeight, start: height, end: 0 };
47
61
  height += itemHeight;
48
62
  newItem.end = height;
49
63
  if (newItem.end <= containerHeight + scrollTop) {
50
- this.end.set(i);
64
+ endLocal = i;
51
65
  }
52
66
  newItems.push(newItem);
53
67
  }
68
+ // Set end một lần thay vì ghi mỗi vòng lặp — tránh notify consumer N lần.
69
+ this.end.set(endLocal);
54
70
  this.storeItems.set(newItems);
55
- this.viewPortItems.set(this.storeItems()
56
- .slice(this.start(), this.end() + 3)
57
- .map((item) => item.ref));
58
- this.outViewPortItem.emit(this.viewPortItems());
59
- this.outPaddingTop.emit(get(this.storeItems(), `[${this.start()}].start`, 0));
60
- this.divVirtual.style.position = 'absolute';
61
- this.divVirtual.style.top = '0px';
62
- this.divVirtual.style.left = '0px';
71
+ // Khởi tạo style + DOM hook của divVirtual đúng một lần.
72
+ if (!this.divVirtualInitialized) {
73
+ this.divVirtual.style.position = 'absolute';
74
+ this.divVirtual.style.top = '0px';
75
+ this.divVirtual.style.left = '0px';
76
+ this.divVirtual.style.width = '1px';
77
+ this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị
78
+ this.elementRef.nativeElement.classList.add('relative');
79
+ this.elementRef.nativeElement.classList.remove('h-full');
80
+ this.elementRef.nativeElement.style.paddingTop = '0px';
81
+ scrollEl.append(this.divVirtual);
82
+ this.divVirtualInitialized = true;
83
+ this.outDivVirtual.emit(this.divVirtual);
84
+ }
85
+ // Height tổng thể đổi theo dataset → cần update mỗi lượt.
63
86
  this.divVirtual.style.height = `${height}px`;
64
- this.divVirtual.style.width = '1px';
65
- this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị
66
- this.elementRef.nativeElement.classList.add('relative');
67
- this.elementRef.nativeElement.classList.remove('h-full');
68
- this.elementRef.nativeElement.style.paddingTop = '0px';
69
- scrollEl.append(this.divVirtual);
70
- this.outDivVirtual.emit(this.divVirtual);
87
+ // containerHeight lúc đầu có thể = 0 (DOM chưa layout), khiến end giữ
88
+ // nguyên 0 chỉ render bufferAhead item đầu. Re-đo bằng handlerScroll sau khi vòng
89
+ // lặp await xong (layout thường đã hoàn tất) để end ra đúng giá trị.
90
+ this.handlerScroll();
71
91
  });
72
92
  });
73
93
  this.destroyRef.onDestroy(() => {
94
+ clearTimeout(this.timerAfterViewInit);
74
95
  this.divVirtual.remove();
96
+ this.resizeObserver?.disconnect();
75
97
  });
76
98
  }
77
99
  ngAfterViewInit() {
78
- setTimeout(() => {
100
+ this.timerAfterViewInit = setTimeout(() => {
79
101
  fromEvent(this.ScrollContainer, 'scroll')
80
102
  .pipe(takeUntilDestroyed(this.destroyRef))
81
103
  .subscribe(() => this.handlerScroll());
82
104
  this.outFunctionControl.emit(this.FunctionsControl);
105
+ // Re-tính viewport sau khi container có kích thước thật.
106
+ // Lần đầu render, getBoundingClientRect().height có thể = 0 nên end giữ giá trị 0,
107
+ // chỉ hiển thị bufferAhead item đầu. ResizeObserver fire ngay khi observe và mỗi lần
108
+ // container đổi size sẽ kéo end về đúng giá trị.
109
+ this.resizeObserver = new ResizeObserver(() => this.handlerScroll());
110
+ this.resizeObserver.observe(this.ScrollContainer);
83
111
  });
84
112
  }
85
113
  // #region PUBLIC API
@@ -139,18 +167,17 @@ class LibsUiScrollMeasureItemDirectionVerticalDirective {
139
167
  // Utilize Binary Search for optimal O(log N) discovery
140
168
  const start = this.findStartIndex(store, scrollTop);
141
169
  const end = this.findEndIndex(store, scrollTop + containerHeight);
142
- this.end.set(end);
170
+ if (end !== this.end()) {
171
+ this.end.set(end);
172
+ }
143
173
  if (start !== this.start()) {
144
174
  this.start.set(start);
145
- // Use logical OR for fallback when start is invalid. But binary search guarantees valid index.
146
- const paddingTop = store[start]?.start || 0;
175
+ // Binary search guarantees `start` index hợp lệ trong store.
176
+ const paddingTop = store[start].start;
147
177
  this.elementRef.nativeElement.style.paddingTop = `${paddingTop}px`;
148
178
  this.outPaddingTop.emit(paddingTop);
149
179
  }
150
- if (this.start() < 0) {
151
- this.start.set(0);
152
- }
153
- this.viewPortItems.set(store.slice(this.start(), this.end() + 3).map((item) => item.ref));
180
+ this.viewPortItems.set(store.slice(this.start(), this.end() + this.bufferAhead).map((item) => item.ref));
154
181
  this.outViewPortItem.emit(this.viewPortItems());
155
182
  }
156
183
  async scrollInto(itemScroll) {
@@ -171,10 +198,14 @@ class LibsUiScrollMeasureItemDirectionVerticalDirective {
171
198
  this.ScrollContainer.scrollTop = itemOfIndex.start;
172
199
  }
173
200
  async reCalculatorViewPort() {
174
- let height = 0;
175
201
  const items = this.storeItems();
176
- for (const item of items) {
177
- const itemHeight = await this.functionGetHeightItem()(item.ref);
202
+ const fn = this.functionGetHeightItem();
203
+ // Đo song song để rút ngắn thời gian thay vì await tuần tự.
204
+ const heights = await Promise.all(items.map((it) => fn(it.ref)));
205
+ let height = 0;
206
+ for (let i = 0; i < items.length; i++) {
207
+ const item = items[i];
208
+ const itemHeight = heights[i];
178
209
  item.itemHeight = itemHeight;
179
210
  item.start = height;
180
211
  height += itemHeight;
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-components-scroll-measure-items-direction-vertical.mjs","sources":["../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/direction-vertical.directive.ts","../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/interfaces/direction-vertical.interface.ts","../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/libs-ui-components-scroll-measure-items-direction-vertical.ts"],"sourcesContent":["// CONVENTION-EXCEPT: any — Generic directive works with unknown item types from consumer\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { AfterViewInit, DestroyRef, Directive, ElementRef, effect, inject, input, output, signal, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { get } from '@libs-ui/utils';\nimport { fromEvent } from 'rxjs';\nimport { IScrollMeasureItemDirectionVerticalFunctionsControl, IScrollMeasureStoreItemVerticalConvert } from './interfaces/direction-vertical.interface';\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[LibsUiScrollMeasureItemDirectionVerticalDirective]',\n standalone: true,\n})\nexport class LibsUiScrollMeasureItemDirectionVerticalDirective implements AfterViewInit {\n // #region PROPERTY\n private viewPortItems = signal<Array<any>>([]);\n private start = signal<number>(0);\n private end = signal<number>(0);\n private storeItems = signal<Array<IScrollMeasureStoreItemVerticalConvert>>([]);\n private divVirtual = document.createElement('div');\n\n // #region INPUT\n readonly elementScroll = input.required<HTMLElement>();\n readonly functionGetHeightItem = input.required<(item: any) => Promise<number>>();\n readonly items = input.required<Array<any>>();\n\n // #region OUTPUT\n readonly outViewPortItem = output<Array<any>>();\n readonly outFunctionControl = output<IScrollMeasureItemDirectionVerticalFunctionsControl>();\n readonly outDivVirtual = output<HTMLDivElement>();\n readonly outPaddingTop = output<number>();\n\n // #region INJECT\n private readonly elementRef = inject(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n\n constructor() {\n effect(() => {\n const scrollEl = untracked(() => this.ScrollContainer);\n if (!scrollEl || !untracked(() => this.functionGetHeightItem())) {\n return;\n }\n const items = this.items();\n untracked(async () => {\n this.start.set(0);\n const scrollTop = scrollEl.scrollTop;\n const containerHeight = scrollEl.getBoundingClientRect().height;\n let height = 0;\n const newItems: Array<IScrollMeasureStoreItemVerticalConvert> = [];\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const newItem: IScrollMeasureStoreItemVerticalConvert = { ref: item, itemHeight: 0, start: 0, end: 0 };\n const itemHeight = await this.functionGetHeightItem()(item);\n newItem.itemHeight = itemHeight;\n newItem.start = height;\n height += itemHeight;\n newItem.end = height;\n if (newItem.end <= containerHeight + scrollTop) {\n this.end.set(i);\n }\n newItems.push(newItem);\n }\n\n this.storeItems.set(newItems);\n this.viewPortItems.set(\n this.storeItems()\n .slice(this.start(), this.end() + 3)\n .map((item) => item.ref)\n );\n this.outViewPortItem.emit(this.viewPortItems());\n this.outPaddingTop.emit(get(this.storeItems(), `[${this.start()}].start`, 0));\n\n this.divVirtual.style.position = 'absolute';\n this.divVirtual.style.top = '0px';\n this.divVirtual.style.left = '0px';\n this.divVirtual.style.height = `${height}px`;\n this.divVirtual.style.width = '1px';\n this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị\n this.elementRef.nativeElement.classList.add('relative');\n this.elementRef.nativeElement.classList.remove('h-full');\n this.elementRef.nativeElement.style.paddingTop = '0px';\n scrollEl.append(this.divVirtual);\n this.outDivVirtual.emit(this.divVirtual);\n });\n });\n\n this.destroyRef.onDestroy(() => {\n this.divVirtual.remove();\n });\n }\n\n ngAfterViewInit() {\n setTimeout(() => {\n fromEvent<Event>(this.ScrollContainer, 'scroll')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.handlerScroll());\n this.outFunctionControl.emit(this.FunctionsControl);\n });\n }\n\n // #region PUBLIC API\n public get FunctionsControl(): IScrollMeasureItemDirectionVerticalFunctionsControl {\n return {\n scrollInto: this.scrollInto.bind(this),\n scrollToPosition: this.scrollToPosition.bind(this),\n scrollToIndex: this.scrollToIndex.bind(this),\n reCalculatorViewPort: this.reCalculatorViewPort.bind(this),\n getViewPortItems: () => this.viewPortItems(),\n };\n }\n\n // #region PRIVATE METHODS\n private get ScrollContainer(): HTMLElement {\n return this.elementScroll() || this.elementRef.nativeElement;\n }\n\n private findStartIndex(store: Array<IScrollMeasureStoreItemVerticalConvert>, scrollTop: number): number {\n let low = 0;\n let high = store.length - 1;\n let ans = store.length - 1; // Default to last item if scrolled past bottom (rubber band effect)\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n if (store[mid].end >= scrollTop) {\n ans = mid;\n high = mid - 1; // Try to find earlier\n } else {\n low = mid + 1;\n }\n }\n return ans;\n }\n\n private findEndIndex(store: Array<IScrollMeasureStoreItemVerticalConvert>, scrollBottom: number): number {\n let low = 0;\n let high = store.length - 1;\n let ans = 0; // Default to first item if rubber-banded above the top\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n if (store[mid].start <= scrollBottom) {\n ans = mid;\n low = mid + 1; // Try to find later\n } else {\n high = mid - 1;\n }\n }\n return ans;\n }\n\n private handlerScroll() {\n const store = this.storeItems();\n if (!store?.length) {\n return;\n }\n const scrollEl = this.ScrollContainer;\n const scrollTop = scrollEl.scrollTop;\n const containerHeight = scrollEl.getBoundingClientRect().height;\n \n // Utilize Binary Search for optimal O(log N) discovery\n const start = this.findStartIndex(store, scrollTop);\n const end = this.findEndIndex(store, scrollTop + containerHeight);\n\n this.end.set(end);\n\n if (start !== this.start()) {\n this.start.set(start);\n // Use logical OR for fallback when start is invalid. But binary search guarantees valid index.\n const paddingTop = store[start]?.start || 0;\n this.elementRef.nativeElement.style.paddingTop = `${paddingTop}px`;\n this.outPaddingTop.emit(paddingTop);\n }\n\n if (this.start() < 0) {\n this.start.set(0);\n }\n this.viewPortItems.set(store.slice(this.start(), this.end() + 3).map((item) => item.ref));\n this.outViewPortItem.emit(this.viewPortItems());\n }\n\n private async scrollInto(itemScroll: any) {\n const itemFound = this.storeItems().find((item) => item.ref === itemScroll);\n if (!itemFound) {\n return;\n }\n this.ScrollContainer.scrollTop = itemFound.start;\n }\n\n private async scrollToPosition(position: number) {\n this.ScrollContainer.scrollTop = position;\n }\n\n private async scrollToIndex(index: number) {\n const itemOfIndex = this.storeItems()[index];\n if (!itemOfIndex) {\n return;\n }\n this.ScrollContainer.scrollTop = itemOfIndex.start;\n }\n\n private async reCalculatorViewPort() {\n let height = 0;\n const items = this.storeItems();\n\n for (const item of items) {\n const itemHeight = await this.functionGetHeightItem()(item.ref);\n item.itemHeight = itemHeight;\n item.start = height;\n height += itemHeight;\n item.end = height;\n }\n\n this.storeItems.set([...items]);\n this.divVirtual.style.height = `${height}px`;\n this.handlerScroll();\n }\n}\n","// CONVENTION-EXCEPT: any — Generic data structures from consumers\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface IScrollMeasureStoreItemVerticalConvert {\n ref: any;\n itemHeight: number;\n start: number; // Tọa độ Y (px) bắt đầu của item\n end: number; // Tọa độ Y (px) kết thúc của item\n}\n\nexport interface IScrollMeasureItemDirectionVerticalFunctionsControl {\n scrollInto: (item: any) => Promise<void>;\n scrollToPosition: (position: number) => Promise<void>;\n scrollToIndex: (index: number) => Promise<void>;\n reCalculatorViewPort: () => Promise<void>;\n getViewPortItems: () => Array<any>;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"libs-ui-components-scroll-measure-items-direction-vertical.mjs","sources":["../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/direction-vertical.directive.ts","../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/interfaces/direction-vertical.interface.ts","../../../../../../libs-ui/components/scroll-measure-items/direction-vertical/src/libs-ui-components-scroll-measure-items-direction-vertical.ts"],"sourcesContent":["// CONVENTION-EXCEPT: any — Generic directive works with unknown item types from consumer\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { AfterViewInit, DestroyRef, Directive, ElementRef, effect, inject, input, output, signal, untracked } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { fromEvent } from 'rxjs';\nimport { IScrollMeasureItemDirectionVerticalFunctionsControl, IScrollMeasureStoreItemVerticalConvert } from './interfaces/direction-vertical.interface';\n\n@Directive({\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[LibsUiScrollMeasureItemDirectionVerticalDirective]',\n standalone: true,\n})\nexport class LibsUiScrollMeasureItemDirectionVerticalDirective implements AfterViewInit {\n // #region PROPERTY\n /** Số item buffer render thêm sau viewport để tránh trắng vùng khi scroll. */\n private readonly bufferAhead = 3;\n\n private viewPortItems = signal<Array<any>>([]);\n private start = signal<number>(0);\n private end = signal<number>(0);\n private storeItems = signal<Array<IScrollMeasureStoreItemVerticalConvert>>([]);\n private divVirtual = document.createElement('div');\n private resizeObserver?: ResizeObserver;\n /** Tham chiếu setTimeout của ngAfterViewInit để clear khi destroy — chặn ResizeObserver mồ côi. */\n private timerAfterViewInit?: number;\n /** Token nhận dạng lần effect chạy hiện tại. Async đo height xong sẽ bỏ kết quả nếu token đổi. */\n private executionToken = 0;\n /** Style + DOM hook của divVirtual chỉ cần khởi tạo một lần cho cả vòng đời directive. */\n private divVirtualInitialized = false;\n\n // #region INPUT\n readonly elementScroll = input.required<HTMLElement>();\n readonly functionGetHeightItem = input.required<(item: any) => Promise<number>>();\n readonly items = input.required<Array<any>>();\n\n // #region OUTPUT\n readonly outViewPortItem = output<Array<any>>();\n readonly outFunctionControl = output<IScrollMeasureItemDirectionVerticalFunctionsControl>();\n readonly outDivVirtual = output<HTMLDivElement>();\n readonly outPaddingTop = output<number>();\n\n // #region INJECT\n private readonly elementRef = inject(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n\n constructor() {\n effect(() => {\n const items = this.items();\n const myToken = ++this.executionToken;\n untracked(async () => {\n const scrollEl = this.ScrollContainer;\n const functionGetHeightItem = this.functionGetHeightItem();\n if (!scrollEl || !functionGetHeightItem) {\n return;\n }\n\n // Đo height tất cả item song song — rút ngắn thời gian cho list lớn.\n const heights = await Promise.all(items.map((it) => functionGetHeightItem(it)));\n // Bị huỷ vì có lượt items() mới chạy sau — bỏ kết quả cũ tránh đè state.\n if (myToken !== this.executionToken) {\n return;\n }\n\n this.start.set(0);\n const scrollTop = scrollEl.scrollTop;\n const containerHeight = scrollEl.getBoundingClientRect().height;\n let height = 0;\n let endLocal = 0;\n const newItems: Array<IScrollMeasureStoreItemVerticalConvert> = [];\n\n for (let i = 0; i < items.length; i++) {\n const itemHeight = heights[i];\n const newItem: IScrollMeasureStoreItemVerticalConvert = { ref: items[i], itemHeight, start: height, end: 0 };\n height += itemHeight;\n newItem.end = height;\n if (newItem.end <= containerHeight + scrollTop) {\n endLocal = i;\n }\n newItems.push(newItem);\n }\n // Set end một lần thay vì ghi mỗi vòng lặp — tránh notify consumer N lần.\n this.end.set(endLocal);\n this.storeItems.set(newItems);\n\n // Khởi tạo style + DOM hook của divVirtual đúng một lần.\n if (!this.divVirtualInitialized) {\n this.divVirtual.style.position = 'absolute';\n this.divVirtual.style.top = '0px';\n this.divVirtual.style.left = '0px';\n this.divVirtual.style.width = '1px';\n this.divVirtual.style.visibility = 'hidden'; // Đảm bảo an toàn không hiển thị\n this.elementRef.nativeElement.classList.add('relative');\n this.elementRef.nativeElement.classList.remove('h-full');\n this.elementRef.nativeElement.style.paddingTop = '0px';\n scrollEl.append(this.divVirtual);\n this.divVirtualInitialized = true;\n this.outDivVirtual.emit(this.divVirtual);\n }\n // Height tổng thể đổi theo dataset → cần update mỗi lượt.\n this.divVirtual.style.height = `${height}px`;\n\n // containerHeight lúc đầu có thể = 0 (DOM chưa layout), khiến end giữ\n // nguyên 0 và chỉ render bufferAhead item đầu. Re-đo bằng handlerScroll sau khi vòng\n // lặp await xong (layout thường đã hoàn tất) để end ra đúng giá trị.\n this.handlerScroll();\n });\n });\n\n this.destroyRef.onDestroy(() => {\n clearTimeout(this.timerAfterViewInit);\n this.divVirtual.remove();\n this.resizeObserver?.disconnect();\n });\n }\n\n ngAfterViewInit() {\n this.timerAfterViewInit = setTimeout(() => {\n fromEvent<Event>(this.ScrollContainer, 'scroll')\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.handlerScroll());\n this.outFunctionControl.emit(this.FunctionsControl);\n\n // Re-tính viewport sau khi container có kích thước thật.\n // Lần đầu render, getBoundingClientRect().height có thể = 0 nên end giữ giá trị 0,\n // chỉ hiển thị bufferAhead item đầu. ResizeObserver fire ngay khi observe và mỗi lần\n // container đổi size sẽ kéo end về đúng giá trị.\n this.resizeObserver = new ResizeObserver(() => this.handlerScroll());\n this.resizeObserver.observe(this.ScrollContainer);\n });\n }\n\n // #region PUBLIC API\n public get FunctionsControl(): IScrollMeasureItemDirectionVerticalFunctionsControl {\n return {\n scrollInto: this.scrollInto.bind(this),\n scrollToPosition: this.scrollToPosition.bind(this),\n scrollToIndex: this.scrollToIndex.bind(this),\n reCalculatorViewPort: this.reCalculatorViewPort.bind(this),\n getViewPortItems: () => this.viewPortItems(),\n };\n }\n\n // #region PRIVATE METHODS\n private get ScrollContainer(): HTMLElement {\n return this.elementScroll() || this.elementRef.nativeElement;\n }\n\n private findStartIndex(store: Array<IScrollMeasureStoreItemVerticalConvert>, scrollTop: number): number {\n let low = 0;\n let high = store.length - 1;\n let ans = store.length - 1; // Default to last item if scrolled past bottom (rubber band effect)\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n if (store[mid].end >= scrollTop) {\n ans = mid;\n high = mid - 1; // Try to find earlier\n } else {\n low = mid + 1;\n }\n }\n return ans;\n }\n\n private findEndIndex(store: Array<IScrollMeasureStoreItemVerticalConvert>, scrollBottom: number): number {\n let low = 0;\n let high = store.length - 1;\n let ans = 0; // Default to first item if rubber-banded above the top\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n if (store[mid].start <= scrollBottom) {\n ans = mid;\n low = mid + 1; // Try to find later\n } else {\n high = mid - 1;\n }\n }\n return ans;\n }\n\n private handlerScroll() {\n const store = this.storeItems();\n if (!store?.length) {\n return;\n }\n const scrollEl = this.ScrollContainer;\n const scrollTop = scrollEl.scrollTop;\n const containerHeight = scrollEl.getBoundingClientRect().height;\n\n // Utilize Binary Search for optimal O(log N) discovery\n const start = this.findStartIndex(store, scrollTop);\n const end = this.findEndIndex(store, scrollTop + containerHeight);\n\n if (end !== this.end()) {\n this.end.set(end);\n }\n\n if (start !== this.start()) {\n this.start.set(start);\n // Binary search guarantees `start` là index hợp lệ trong store.\n const paddingTop = store[start].start;\n this.elementRef.nativeElement.style.paddingTop = `${paddingTop}px`;\n this.outPaddingTop.emit(paddingTop);\n }\n this.viewPortItems.set(store.slice(this.start(), this.end() + this.bufferAhead).map((item) => item.ref));\n this.outViewPortItem.emit(this.viewPortItems());\n }\n\n private async scrollInto(itemScroll: any) {\n const itemFound = this.storeItems().find((item) => item.ref === itemScroll);\n if (!itemFound) {\n return;\n }\n this.ScrollContainer.scrollTop = itemFound.start;\n }\n\n private async scrollToPosition(position: number) {\n this.ScrollContainer.scrollTop = position;\n }\n\n private async scrollToIndex(index: number) {\n const itemOfIndex = this.storeItems()[index];\n if (!itemOfIndex) {\n return;\n }\n this.ScrollContainer.scrollTop = itemOfIndex.start;\n }\n\n private async reCalculatorViewPort() {\n const items = this.storeItems();\n const fn = this.functionGetHeightItem();\n // Đo song song để rút ngắn thời gian thay vì await tuần tự.\n const heights = await Promise.all(items.map((it) => fn(it.ref)));\n\n let height = 0;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const itemHeight = heights[i];\n item.itemHeight = itemHeight;\n item.start = height;\n height += itemHeight;\n item.end = height;\n }\n\n this.storeItems.set([...items]);\n this.divVirtual.style.height = `${height}px`;\n this.handlerScroll();\n }\n}\n","// CONVENTION-EXCEPT: any — Generic data structures from consumers\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface IScrollMeasureStoreItemVerticalConvert {\n ref: any;\n itemHeight: number;\n start: number; // Tọa độ Y (px) bắt đầu của item\n end: number; // Tọa độ Y (px) kết thúc của item\n}\n\nexport interface IScrollMeasureItemDirectionVerticalFunctionsControl {\n scrollInto: (item: any) => Promise<void>;\n scrollToPosition: (position: number) => Promise<void>;\n scrollToIndex: (index: number) => Promise<void>;\n reCalculatorViewPort: () => Promise<void>;\n getViewPortItems: () => Array<any>;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "@libs-ui/components-scroll-measure-items-direction-vertical",
3
- "version": "0.2.356-25",
3
+ "version": "0.2.356-27",
4
4
  "peerDependencies": {
5
5
  "@angular/core": "^18.2.0",
6
- "@libs-ui/utils": "0.2.356-25",
7
6
  "rxjs": "~7.8.0"
8
7
  },
9
8
  "sideEffects": false,