@libs-ui/services-grid-layout 0.2.357-19 → 0.2.357-20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # @libs-ui/services-grid-layout
2
2
 
3
- Mặt phẳng kéo–thả. Thư viện lo toàn bộ việc **vẽ lưới, kéo thả, đổi kích thước, lồng container**;
4
- nơi dùng chỉ đưa **component nội dung** **cây dữ liệu**, thư viện tự gắn component lên từng khối.
3
+ Mặt phẳng kéo–thả. Thư viện lo **toàn bộ** việc vẽ lưới, kéo thả, đổi kích thước, lồng container,
4
+ tay cầm kéo, bộ nút trên khối, viền chế độ sửa, dọn dẹp khi component chết.
5
5
 
6
- Cùng hình với `@libs-ui/services-diagram-draw`: truyền `nodeComponentType`, thư viện `createComponent`.
6
+ Nơi dùng chỉ đưa **cây dữ liệu** **cách phân giải component nội dung**. Component nội dung của bạn
7
+ chỉ vẽ phần nội dung — không phải tự lo kích thước, không phải tự vẽ viền chế độ sửa.
7
8
 
8
9
  ## Cài
9
10
 
@@ -18,70 +19,162 @@ Lib dùng `angular-gridster2` qua **alias npm** để chạy song song nhiều b
18
19
  Nơi dùng đang có `angular-gridster2` bản khác thì **không bị đụng** — hai bản nằm ở hai thư mục
19
20
  `node_modules` riêng.
20
21
 
22
+ Chạy Jest thì phải map **cả hai** tên, vì package tự khai `name: angular-gridster2`:
23
+
24
+ ```ts
25
+ // jest.config.ts của nơi dùng
26
+ moduleNameMapper: {
27
+ '^gridster18$': '<rootDir>/../../node_modules/gridster18/fesm2022/angular-gridster2.mjs',
28
+ '^angular-gridster2$': '<rootDir>/../../node_modules/gridster18/fesm2022/angular-gridster2.mjs',
29
+ }
30
+ ```
31
+
21
32
  ## Dùng
22
33
 
23
34
  ```ts
24
35
  @Component({
25
36
  imports: [LibsUiGridLayoutCanvasComponent],
26
37
  // 🔴 Khai trong providers của CHÍNH component — service theo từng mặt phẳng, không phải root.
27
- providers: [LibsUiGridLayoutService, LibsUiGridLayoutTreeService],
28
- template: `<libs_ui-services-grid_layout-canvas [node]="root()" (outChange)="save($event)" />`,
38
+ providers: [LibsUiGridLayoutService],
39
+ template: `<libs_ui-services-grid_layout-canvas
40
+ (outChange)="handlerChange($event)"
41
+ (outRemoveNode)="handlerRemoveNode($event)"
42
+ (outAddBlockInside)="handlerAddInside($event)"
43
+ (outToggleType)="handlerToggleType($event)" />`,
29
44
  })
30
- export class MyPageComponent implements OnDestroy {
45
+ export class MyPageComponent {
31
46
  private readonly gridLayout = inject(LibsUiGridLayoutService);
32
47
 
33
- protected readonly root = signal<T_gridLayout_node>(initialLayout());
34
-
35
48
  constructor() {
36
49
  this.gridLayout.init({
37
- nodeComponentType: MyCardComponent, // component nội dung của BẠN
38
- data: this.root(),
50
+ data: layoutFromServer(), // cây khối, thường lấy từ backend
51
+ getComponentOutlet: resolveNodeComponent,
39
52
  mode: E_gridLayout_mode_string.grid,
40
53
  isEditMode: true,
41
- allowOverlap: false,
42
54
  });
43
55
  }
56
+ // KHÔNG cần ngOnDestroy — thư viện tự dọn qua DestroyRef.
57
+ }
58
+ ```
59
+
60
+ **Không truyền `[node]`** — `init()` đã giữ cây. Input `node`/`depth` của canvas chỉ dành cho lưới
61
+ lồng bên trong thư viện.
44
62
 
45
- ngOnDestroy(): void {
46
- this.gridLayout.destroy(); // 🔴 BẮT BUỘC, nếu không là rò rỉ bộ nhớ
63
+ ### Phân giải component theo từng khối
64
+
65
+ Mỗi khối tự quyết định component của nó, đọc từ `node.data` (dữ liệu hình dạng server). Trả
66
+ `Observable` nên `import()` động dùng được ngay — mỗi loại khối là một chunk riêng:
67
+
68
+ ```ts
69
+ export const resolveNodeComponent = (node: T_gridLayout_node): Observable<Type<unknown>> => {
70
+ switch ((node.data as T_serverElement | undefined)?.type) {
71
+ case E_serverElement_type_string.chart:
72
+ return from(import('./chart-card.component').then((c) => c.ChartCardComponent));
73
+ case E_serverElement_type_string.table:
74
+ return from(import('./table-card.component').then((c) => c.TableCardComponent));
75
+ default:
76
+ return from(import('./sample-card.component').then((c) => c.SampleCardComponent));
47
77
  }
48
- }
78
+ };
49
79
  ```
50
80
 
51
- Component nội dung **bắt buộc** khai đủ ba input — thư viện `setInput` đúng ba tên này:
81
+ Khai `config.getComponentOutlet` cho cả mặt phẳng, hoặc `node.getComponentOutlet` cho riêng một
82
+ khối (khối tự khai thì thắng).
83
+
84
+ ### Component nội dung
85
+
86
+ Khai đủ **bốn** input — thư viện `setInput` đúng bốn tên này, thiếu một cái là lỗi lúc chạy mà build
87
+ không bắt được:
52
88
 
53
89
  ```ts
54
90
  @Component({ changeDetection: ChangeDetectionStrategy.OnPush, /* … */ })
55
91
  export class MyCardComponent {
92
+ readonly data = input.required<T_myData>(); // = node.data — thường chỉ cần cái này
56
93
  readonly node = input.required<T_gridLayout_node>();
57
94
  readonly isEditMode = input<boolean>(false);
58
95
  readonly depth = input<number>(0);
59
96
  }
60
97
  ```
61
98
 
99
+ Type sẵn có: `T_gridLayout_nodeInputs<TData>`.
100
+
101
+ ## Nút sẵn có bắn event kèm callback
102
+
103
+ Xoá · gộp · tách · thêm-khối-bên-trong là nút của thư viện. Bấm vào, thư viện **chưa làm gì** — nó
104
+ bắn event mang theo `confirm()`. Nghiệp vụ cần hỏi xác nhận thì mở modal rồi mới gọi; không cần thì
105
+ gọi luôn; không cho phép thì đừng gọi:
106
+
107
+ ```ts
108
+ protected handlerRemoveNode(event: T_gridLayout_actionEvent): void {
109
+ if (!event.node.children?.length) {
110
+ event.confirm(); // khối đơn — xoá luôn
111
+ return;
112
+ }
113
+ this.pendingRemove.set(event); // khối ghép — hỏi trước, confirm() gọi sau
114
+ }
115
+
116
+ protected handlerAddInside(event: T_gridLayout_addEvent): void {
117
+ // confirm nhận khối mới, trả về khối đã tạo kèm id thư viện sinh
118
+ const added = event.confirm({ cols: 3, rows: 2, data: { type: 'metric' } });
119
+ }
120
+ ```
121
+
122
+ | Output | Khi nào bắn | `confirm()` |
123
+ |---|---|---|
124
+ | `outChange` | người dùng kéo / đổi kích thước — **chỉ** thao tác thật của người dùng | — |
125
+ | `outRemoveNode` | bấm nút xoá | `() => boolean` |
126
+ | `outToggleType` | bấm gộp (khối đơn → container) hoặc tách | `() => boolean` |
127
+ | `outAddBlockInside` | bấm + trên container | `(item) => node \| undefined` |
128
+
129
+ `outChange` **không** bắn khi chính bạn gọi `addBlock`/`removeBlock`/`compact` — bạn đã biết mình vừa
130
+ làm gì, khỏi phải chống dội.
131
+
62
132
  ## Hai chế độ
63
133
 
64
134
  | Chế độ | Khối bám lưới | Chồng lên nhau | Dùng khi |
65
135
  |---|---|---|---|
66
- | `luoi` | có | chỉ khi `allowOverlap` bật **và** hai khối khác `layerIndex` | dashboard, bố cục dạng bảng |
67
- | `tuDo` | không, toạ độ px | tự do | dựng bố cục kiểu canvas |
136
+ | `grid` | có | chỉ khi `allowOverlap` bật **và** hai khối khác `layerIndex` | dashboard, bố cục dạng bảng |
137
+ | `free` | không, toạ độ px | tự do | bố cục kiểu canvas — *engine chưa dựng, hiện vẫn chạy trên lưới* |
68
138
 
69
139
  ## API
70
140
 
71
- **`LibsUiGridLayoutService`** (một thực thể cho mỗi mặt phẳng)
141
+ **`LibsUiGridLayoutService`** một thực thể cho mỗi mặt phẳng.
72
142
 
73
143
  | Thành viên | Việc |
74
144
  |---|---|
75
- | `init(config)` | dựng mặt phẳng; gọi lại sẽ dọn sạch rồi dựng lại |
76
- | `setEditMode(bat)` | bật/tắt chế độ sửa |
77
- | `refresh(event?)` | báo cây vừa đổi từ bên ngoài |
78
- | `destroy()` | dọn mọi component đã dựnggọi trong `ngOnDestroy` |
145
+ | `init(config)` | dựng mặt phẳng; gọi lại sẽ dọn sạch rồi dựng lại. Tự san phẳng container lồng quá trần |
146
+ | `setEditMode(value)` | bật/tắt chế độ sửa |
147
+ | `setAllowOverlap(value)` | cho phép xếp chồng; tự gán `layerIndex`. KHÔNG dựng lại component nào |
148
+ | `refresh(event?)` | báo cây vừa đổi từ bên ngoài hiếm khi cần |
149
+ | `addBlock(item, parentId?)` | thêm khối; bỏ `parentId` là thêm ở gốc. Trả khối vừa tạo (kèm `id`) |
150
+ | `removeBlock(id)` | bỏ khối; xoá container là xoá cả ruột |
151
+ | `toContainer(id)` · `toSingle(id)` | gộp thành container / tách về khối đơn — không mất dữ liệu |
152
+ | `compact()` | dồn khối lên, bỏ khoảng trống. Đệ quy vào container |
153
+ | `findBlock(id)` · `findParentBlock(id)` | tra cây |
154
+ | `exportLayout()` | cây hiện tại đã bỏ hàm, `cloneDeep` — gửi thẳng lên backend được |
79
155
  | `Root` · `IsEditMode` · `Version` | signal chỉ đọc |
80
156
 
81
- **`LibsUiGridLayoutTreeService`**thao tác trên cây
157
+ Mọi hàm sửa cây **tự vẽ lại** không phải gọi `refresh()` theo sau.
158
+
159
+ **Thư viện tự dọn** qua `DestroyRef` — `destroy()` là `private`, **CẤM** gọi trong `ngOnDestroy`.
160
+
161
+ **KHÔNG tự đặt `id`** cho khối: `addBlock` sinh bằng `uuid()` và trả về khối vừa tạo. Tự đặt là mời
162
+ trùng id, mà trùng thì `findBlock` trả nhầm khối và cây hỏng im lặng.
163
+
164
+ `LibsUiGridLayoutTreeService` **cố ý không xuất**: mọi thao tác trên cây đã có trên service với chữ ký
165
+ gọn hơn (không phải truyền `root` — thư viện đang giữ nó). Cấu hình gridster cũng không xuất, xem lý
166
+ do ở mục dưới.
167
+
168
+ ### Lưu và mở lại bố cục
169
+
170
+ ```ts
171
+ UtilsCache.Set(KEY, this.gridLayout.exportLayout(), UtilsCache.CACHE_EXPIRE_NONE);
172
+ // mở lại
173
+ this.gridLayout.init({ data: UtilsCache.Get(KEY) ?? defaultLayout(), getComponentOutlet });
174
+ ```
82
175
 
83
- `findById` · `findParent` · `addChild` · `removeById` · `canBecomeContainer` ·
84
- `flattenOverDepthContainers` · `compact`
176
+ `exportLayout()` đã lược `getComponentOutlet` (hàm không tuần tự hoá được) nên `JSON.stringify` được
177
+ ngay. Mở lại chỉ cần đưa `getComponentOutlet` vào `init` — cây không mang hàm.
85
178
 
86
179
  ## Vì sao cấu hình gridster lại như vậy
87
180
 
@@ -99,6 +192,7 @@ export class MyCardComponent {
99
192
  | tay cầm resize ở `0`, không âm | `overflow: hidden` cắt mất nửa tay cầm → kéo mép không ăn |
100
193
  | `setGridSize: false` ở lưới lồng | vòng lặp đo–ghi, lưới con co dần về 64×64px |
101
194
  | `disableScroll*` ở lưới lồng | khối con bị đẩy ra ngoài container rồi kẹt |
195
+ | `layerIndex` gán vào cây ĐANG VẼ | gán vào `config.data` thì z-index đứng ở 1 — cây đang vẽ là bản clone |
102
196
 
103
197
  ## Kiểm
104
198
 
@@ -59,6 +59,11 @@ export class LibsUiGridLayoutService {
59
59
  init(config) {
60
60
  this.destroy();
61
61
  this.config = config;
62
+ // 🔴 Bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện: bản lưu cũ (sinh trước khi có trần,
63
+ // hoặc do thao tác lỗi) vẫn mang container lồng container. Trần `maxContainerDepth` chỉ ẩn NÚT
64
+ // trên canvas — nó không sửa dữ liệu, nên thiếu dòng này là vẽ ra đúng cây quá sâu đó.
65
+ // Nơi dùng KHÔNG tự gọi được: `LibsUiGridLayoutTreeService` cố ý không xuất.
66
+ this.treeService.flattenOverDepthContainers(config.data, this.maxContainerDepth());
62
67
  this.assignOverlapLayers(config.data);
63
68
  // 🔴 Nhân bản như `refresh()`: `init()` lại (đổi chế độ, bật/tắt chồng khối) trên CÙNG object cây
64
69
  // thì `@for` không dựng lại `gridster-item`, nên `layerIndex` vừa gán không tới `$item` và khối
@@ -430,4 +435,4 @@ export class LibsUiGridLayoutService {
430
435
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiGridLayoutService, decorators: [{
431
436
  type: Injectable
432
437
  }], ctorParameters: () => [] });
433
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC1sYXlvdXQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMtdWkvc2VydmljZXMvZ3JpZC1sYXlvdXQvc3JjL2dyaWQtbGF5b3V0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFnQixVQUFVLEVBQUUsVUFBVSxFQUFvQixNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQWdCLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNoRyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7QUFTN0Q7Ozs7Ozs7Ozs7R0FVRztBQUVILE1BQU0sT0FBTyx1QkFBdUI7SUFDbEMsNkZBQTZGO0lBQzdGLHdGQUF3RjtJQUN4RixtRkFBbUY7SUFDbEUsV0FBVyxHQUFHLElBQUksMkJBQTJCLEVBQUUsQ0FBQztJQUNqRSxvRkFBb0Y7SUFDbkUsWUFBWSxHQUFHLElBQUksR0FBRyxFQUF3QixDQUFDO0lBRWhFO1FBQ0UsK0ZBQStGO1FBQy9GLHlGQUF5RjtRQUN6RiwrRkFBK0Y7UUFDL0YsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRU8sTUFBTSxDQUF1QjtJQUNwQixhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQWlDLENBQUM7SUFFekQsUUFBUSxHQUFHLE1BQU0sQ0FBZ0MsU0FBUyxDQUFDLENBQUM7SUFDNUQsUUFBUSxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNuRCxxRUFBcUU7SUFDcEQsT0FBTyxH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QixFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtZQUMvQyxlQUFlLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBZSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUN6RixVQUFVLEVBQUUsQ0FBQyxJQUF1QixFQUFFLEtBQWEsRUFBRSxJQUFzQixFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDO1lBQ2xILFVBQVUsRUFBRSxDQUFDLE1BQWMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7U0FDeEQsQ0FBQztJQUNKLENBQUM7SUFFTyxXQUFXLENBQUMsR0FBMEIsRUFBRSxJQUF1QixFQUFFLEtBQWE7UUFDcEYsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hDLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzNCLEdBQUcsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7d0dBbmZVLHVCQUF1Qjs0R0FBdkIsdUJBQXVCOzs0RkFBdkIsdUJBQXVCO2tCQURuQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50UmVmLCBEZXN0cm95UmVmLCBJbmplY3RhYmxlLCBWaWV3Q29udGFpbmVyUmVmLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgR3JpZHN0ZXJDb25maWcsIEdyaWRzdGVySXRlbSB9IGZyb20gJ2dyaWRzdGVyMTgnO1xuaW1wb3J0IHsgY2xvbmVEZWVwIH0gZnJvbSAnQGxpYnMtdWkvdXRpbHMnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCB0YWtlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBncmlkTGF5b3V0TmVzdGVkQ29uZmlnLCBncmlkTGF5b3V0Um9vdENvbmZpZyB9IGZyb20gJy4vZGVmaW5lcy9ncmlkc3Rlci1jb25maWcuZGVmaW5lJztcbmltcG9ydCB7IExpYnNVaUdyaWRMYXlvdXRUcmVlU2VydmljZSB9IGZyb20gJy4vdHJlZS5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIEVfZ3JpZExheW91dF9tb2RlX3N0cmluZyxcbiAgVF9ncmlkTGF5b3V0X2NoYW5nZUV2ZW50LFxuICBUX2dyaWRMYXlvdXRfbmV3Tm9kZSxcbiAgVF9ncmlkTGF5b3V0X2NvbmZpZyxcbiAgVF9ncmlkTGF5b3V0X25vZGUsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9ncmlkLWxheW91dC5pbnRlcmZhY2UnO1xuXG4vKipcbiAqIEThu7FuZyBt4buZdCBt4bq3dCBwaOG6s25nIGvDqW8gdGjhuqMgdsOgIHThu7EgZ+G6r24gY29tcG9uZW50IGPhu6dhIG7GoWkgZMO5bmcgbMOqbiB04burbmcga2jhu5FpLlxuICpcbiAqIE7GoWkgZMO5bmcgY2jhu4kgY+G6p24gxJHGsGEgdsOgbzogbG/huqFpIGNvbXBvbmVudCBtdeG7kW4gZOG7sW5nXG4gKiAoYG5vZGVDb21wb25lbnRUeXBlYCkgdsOgIGPDonkgZOG7ryBsaeG7h3UgKGBkYXRhYCkuIFRvw6BuIGLhu5kgdmnhu4djIHbhur0gbMaw4bubaSwga8OpbyB0aOG6oywgxJHhu5VpIGvDrWNoIHRoxrDhu5tjLFxuICogbOG7k25nIGNvbnRhaW5lciB2w6AgZOG7jW4gZOG6uXAgZG8gdGjGsCB2aeG7h24gbG8uXG4gKlxuICog8J+UtCDEkMOieSBsw6Agc2VydmljZSB0aGVvIFThu6pORyBt4bq3dCBwaOG6s25nLCBLSMOUTkcgYHByb3ZpZGVkSW46ICdyb290J2AuIEtoYWkgdHJvbmcgYHByb3ZpZGVyc2AgY+G7p2FcbiAqIGNvbXBvbmVudCBkw7luZyBuw7M7IGhhaSBt4bq3dCBwaOG6s25nIHRyw6puIGPDuW5nIG3hu5l0IG3DoG4gcGjhuqNpIGzDoCBoYWkgdGjhu7FjIHRo4buDIHJpw6puZywgZMO5bmcgY2h1bmcgdGjDrFxuICogYGNvbXBvbmVudFJlZnNgIGPhu6dhIG3hurd0IHBo4bqzbmcgbsOgeSBi4buLIG3hurd0IHBo4bqzbmcga2lhIGThu41uIG3huqV0LlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTGlic1VpR3JpZExheW91dFNlcnZpY2Uge1xuICAvLyDwn5S0IFThu7AgVOG6oE8sIGtow7RuZyBgaW5qZWN0YC4gTsahaSBkw7luZyBjaOG7iSBwaOG6o2kgdmnhur90IGBwcm92aWRlcnM6IFtMaWJzVWlHcmlkTGF5b3V0U2VydmljZV1gIOKAlFxuICAvLyBraMO0bmcgcGjhuqNpIGJp4bq/dCBiw6puIHRyb25nIHRoxrAgdmnhu4duIGPDsm4gc2VydmljZSBuw6BvIGtow6FjIChuZ8aw4budaSBkw7luZyBjaOG7kXQgMjgvMDgvMjAyNikuXG4gIC8vIGBUcmVlU2VydmljZWAga2jDtG5nIGdp4buvIHRy4bqhbmcgdGjDoWkgZMO5bmcgY2h1bmcgbsOqbiBt4buXaSBt4bq3dCBwaOG6s25nIG3hu5l0IGLhuqNuIGzDoCDEkcO6bmcuXG4gIHByaXZhdGUgcmVhZG9ubHkgdHJlZVNlcnZpY2UgPSBuZXcgTGlic1VpR3JpZExheW91dFRyZWVTZXJ2aWNlKCk7XG4gIC8qKiBMxrDhu6N0IHThuqNpIGNvbXBvbmVudCDEkWFuZyBjaOG7nSwgdGhlbyBpZCBraOG7kWkg4oCUIMSR4buDIGh14bu3IGtoaSBraOG7kWkgYuG7iyBn4buhIGdp4buvYSBjaOG7q25nLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdMb2FkcyA9IG5ldyBNYXA8c3RyaW5nLCBTdWJzY3JpcHRpb24+KCk7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLy8g8J+UtCBTZXJ2aWNlIGtoYWkgdHJvbmcgYHByb3ZpZGVyc2AgY+G7p2EgY29tcG9uZW50IG7Dqm4gQW5ndWxhciBodeG7tyBuw7MgY8O5bmcgY29tcG9uZW50IOKAlCB0aMawIHZp4buHblxuICAgIC8vIHThu7EgZOG7jW4g4bufIMSRw6J5LCBuxqFpIGTDuW5nIEtIw5RORyBwaOG6o2kgZ+G7jWkgYGRlc3Ryb3koKWAgdHJvbmcgYG5nT25EZXN0cm95YCAobmfGsOG7nWkgZMO5bmcgY2jhu5F0XG4gICAgLy8gMjgvMDgvMjAyNikuIELhuq90IG5o4bubIG3hu5l0IGLGsOG7m2MgZOG7jW4gZOG6uXAgbMOgIGtp4buDdSBBUEkgZOG7hSBxdcOqbiwgdsOgIHF1w6puIHRow6wgcsOyIHLhu4kgYuG7mSBuaOG7myBpbSBs4bq3bmcuXG4gICAgaW5qZWN0KERlc3Ryb3lSZWYpLm9uRGVzdHJveSgoKSA9PiB0aGlzLmRlc3Ryb3koKSk7XG4gIH1cblxuICBwcml2YXRlIGNvbmZpZz86IFRfZ3JpZExheW91dF9jb25maWc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29tcG9uZW50UmVmcyA9IG5ldyBNYXA8c3RyaW5nLCBDb21wb25lbnRSZWY8dW5rbm93bj4+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSByb290Tm9kZSA9IHNpZ25hbDxUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgcHJpdmF0ZSByZWFkb25seSBlZGl0TW9kZSA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIC8qKiB0xINuZyBt4buXaSBs4bqnbiBjw6J5IMSR4buVaSDigJQgY29tcG9uZW50IGNvbiDEkeG7jWMgxJHhu4MgYmnhur90IHBo4bqjaSB0w61uaCBs4bqhaSAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHZlcnNpb24gPSBzaWduYWw8bnVtYmVyPigwKTtcblxuICAvKipcbiAgICogU2lnbmFsIGNo4buJIMSR4buNYyDEkeG7gyBuxqFpIGTDuW5nIHRoZW8gZMO1aS5cbiAgICpcbiAgICog8J+UtCBMw6AgVEhV4buYQyBUw41OSCwga2jDtG5nIHBo4bqjaSBnZXR0ZXIuIEdldHRlciB0cuG6oyBzaWduYWwgdGjDrCBjaOG7lyDEkeG7jWMgcGjhuqNpIHZp4bq/dCBgVmVyc2lvbigpKClgIOKAlFxuICAgKiBxdcOqbiBj4bq3cCBuZ2/hurdjIHRo4bupIGhhaSBsw6AgY29tcHV0ZWQgS0jDlE5HIHBo4bulIHRodeG7mWMgdsOgbyBuw7MsIGPDonkgxJHhu5VpIG3DoCBsxrDhu5tpIMSR4bupbmcgaW0sIHbDoFxuICAgKiBUeXBlU2NyaXB0IGtow7RuZyBo4buBIGLDoW8gbOG7l2kgKMSRbyAyOC8wOC8yMDI2OiB0aMOqbSBraOG7kWkga2jDtG5nIGhp4buHbiwgc+G6r3AgZ+G7jW4ga2jDtG5nIG5ow7pjIG5ow61jaCkuXG4gICAqL1xuICByZWFkb25seSBSb290ID0gdGhpcy5yb290Tm9kZS5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IElzRWRpdE1vZGUgPSB0aGlzLmVkaXRNb2RlLmFzUmVhZG9ubHkoKTtcbiAgLyoqIHTEg25nIG3hu5dpIGzhuqduIGPDonkgaG/hurdjIGPhuqV1IGjDrG5oIMSR4buVaSAqL1xuICByZWFkb25seSBWZXJzaW9uID0gdGhpcy52ZXJzaW9uLmFzUmVhZG9ubHkoKTtcblxuICAvKipcbiAgICogdHLhuqduIHPhu5EgY+G6pXAgY29udGFpbmVyIGzhu5NuZyBuaGF1IOKAlCBjYW52YXMgxJHhu41jIMSR4buDIGJp4bq/dCBjw7MgY2hvIGNodXnhu4NuIHRow6BuaCBjb250YWluZXIga2jDtG5nICovXG4gIHByaXZhdGUgbWF4Q29udGFpbmVyRGVwdGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc/Lm1heENvbnRhaW5lckRlcHRoID8/IDE7XG4gIH1cblxuICAvKipcbiAgICogbOG7gSB0cm9uZyBj4bunYSBjb250YWluZXIsIHB4IOKAlCBjYW52YXMgxJHhu41jIMSR4buDIMSR4bq3dCBwYWRkaW5nIGzDqm4gduG7jyBjb250YWluZXIgKi9cbiAgcHJpdmF0ZSBjb250YWluZXJQYWRkaW5nKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnPy5jb250YWluZXJQYWRkaW5nID8/IDEyO1xuICB9XG5cbiAgLyoqIEto4bufaSB04bqhbyBt4bq3dCBwaOG6s25nLiBH4buNaSBs4bqhaSBz4bq9IGThu41uIHPhuqFjaCBjb21wb25lbnQgY8WpIHLhu5NpIGThu7FuZyBs4bqhaSB04burIMSR4bqndS4gKi9cbiAgaW5pdChjb25maWc6IFRfZ3JpZExheW91dF9jb25maWcpOiB2b2lkIHtcbiAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB0aGlzLmFzc2lnbk92ZXJsYXBMYXllcnMoY29uZmlnLmRhdGEpO1xuICAgIC8vIPCflLQgTmjDom4gYuG6o24gbmjGsCBgcmVmcmVzaCgpYDogYGluaXQoKWAgbOG6oWkgKMSR4buVaSBjaOG6vyDEkeG7mSwgYuG6rXQvdOG6r3QgY2jhu5NuZyBraOG7kWkpIHRyw6puIEPDmU5HIG9iamVjdCBjw6J5XG4gICAgLy8gdGjDrCBgQGZvcmAga2jDtG5nIGThu7FuZyBs4bqhaSBgZ3JpZHN0ZXItaXRlbWAsIG7Dqm4gYGxheWVySW5kZXhgIHbhu6thIGfDoW4ga2jDtG5nIHThu5tpIGAkaXRlbWAgdsOgIGto4buRaVxuICAgIC8vIHbhuqtuIGtow7RuZyDEkcOoIG5oYXUgxJHGsOG7o2MgKMSRbyAyOC8wOC8yMDI2OiBgaXRlbS5sYXllckluZGV4YCA9IDF8MnwzfDR8NyBtw6AgYCRpdGVtLmxheWVySW5kZXhgXG4gICAgLy8gdG/DoG4gYHVuZGVmaW5lZGApLlxuICAgIHRoaXMucm9vdE5vZGUuc2V0KHRoaXMuc2hhbGxvd0Nsb25lVHJlZShjb25maWcuZGF0YSkpO1xuICAgIHRoaXMuZWRpdE1vZGUuc2V0KGNvbmZpZy5pc0VkaXRNb2RlID8/IGZhbHNlKTtcbiAgICB0aGlzLnZlcnNpb24udXBkYXRlKCh2KSA9PiB2ICsgMSk7XG4gIH1cblxuICBzZXRFZGl0TW9kZSh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuZWRpdE1vZGUuc2V0KHZhbHVlKTtcbiAgICAvLyDwn5S0IFBI4bqiSSBixqFtIGB2ZXJzaW9uYDogYGdyaWRzdGVyT3B0aW9ucygpYCDEkeG7jWMgYGVkaXRNb2RlYCDEkeG7gyBi4bqtdC904bqvdCBrw6lv4oCTdGjhuqMsIG3DoCBjb21wdXRlZFxuICAgIC8vIGBncmlkT3B0aW9uc2AgYsOqbiBjYW52YXMgY2jhu4kgY2jhuqF5IGzhuqFpIGtoaSBgVmVyc2lvbmAgxJHhu5VpLiBUaGnhur91IGTDsm5nIG7DoHkgdGjDrCDEkeG7lWkgY2jhur8gxJHhu5kgeG9uZ1xuICAgIC8vIGdyaWRzdGVyIHbhuqtuIGdp4buvIG9wdGlvbnMgY8WpIOKAlCBjaHV54buDbiBzYW5nIFhFTSBtw6Aga2jhu5FpIHbhuqtuIGvDqW8gxJHGsOG7o2MuXG4gICAgdGhpcy52ZXJzaW9uLnVwZGF0ZSgodikgPT4gdiArIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIELhuq10L3Thuq90IGNobyBraOG7kWkgY2jhu5NuZyBsw6puIG5oYXUg4oCUIEtIw5RORyBk4buxbmcgbOG6oWkgbeG6t3QgcGjhurNuZy5cbiAgICpcbiAgICogVHLGsOG7m2MgxJHDonkgbsahaSBkw7luZyBwaOG6o2kgZ+G7jWkgYGluaXQoKWAgbOG6oWkgxJHhu4MgxJHhu5VpIGPhu50gbsOgeSwgbcOgIGBpbml0KClgIGh14bu3IHPhuqFjaCBy4buTaSBk4buxbmcgbOG6oWkgbeG7jWlcbiAgICogY29tcG9uZW50IG7hu5lpIGR1bmcg4oCUIGzDo25nIHBow60sIHbDoCBuZ8aw4budaSBkw7luZyB0aOG6pXkgbcOgbiBjaOG7m3AgKG5nxrDhu51pIGTDuW5nIGNo4buRdCAyOC8wOC8yMDI2KS5cbiAgICovXG4gIHNldEFsbG93T3ZlcmxhcCh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmNvbmZpZyA9IHsgLi4udGhpcy5jb25maWcsIGFsbG93T3ZlcmxhcDogdmFsdWUgfTtcblxuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG5cbiAgICBpZiAoIXJvb3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyDwn5S0IEfDoW4gbOG7m3AgdsOgbyBDw4JZIMSQQU5HIFbhurwgKGByb290Tm9kZWApLCBLSMOUTkcgcGjhuqNpIGBjb25maWcuZGF0YWAuXG4gICAgLy8gYGluaXQoKWAgxJHDoyBjbG9uZSBgY29uZmlnLmRhdGFgIHNhbmcgYHJvb3ROb2RlYCBuw6puIGhhaSBvYmplY3QgS0jDgUMgbmhhdTsgZ8OhbiB2w6BvIGBjb25maWcuZGF0YWBcbiAgICAvLyB0aMOsIGByZWZyZXNoKClgIGNsb25lIGzhuqFpIHThu6sgYHJvb3ROb2RlYCDigJQgbOG7m3AgduG7q2EgZ8OhbiBraMO0bmcgdOG7m2kgYGdyaWRzdGVyLWl0ZW1gIG7DoG8sIGB6LWluZGV4YFxuICAgIC8vIGPhu6dhIG3hu41pIGto4buRaSDEkeG7qW5nIOG7nyBgMWAgdsOgIGto4buRaSBuw6BvIHbhur0gc2F1IHRow6wgbuG6sW0gdHLDqm46IGNo4buTbmcga2jhu5FpIFwibMO6YyDEkcaw4bujYyBsw7pjIGtow7RuZ1wiXG4gICAgLy8gKMSRbyAwNC8wOS8yMDI2OiBgaXRlbS5sYXllckluZGV4YCB1bmRlZmluZWQsIGBnZXRMYXllckluZGV4KClgID0gMCBjaG8gY+G6oyA4IGto4buRaSkuXG4gICAgdGhpcy5hc3NpZ25PdmVybGFwTGF5ZXJzKHJvb3QpO1xuICAgIC8vIFRoYXkgdGhhbSBjaGnhur91IGPDonkgxJHhu4MgYGxheWVySW5kZXhgIHbhu6thIGfDoW4gdOG7m2kgxJHGsOG7o2MgYCRpdGVtYCBj4bunYSBncmlkc3RlcjsgY29tcG9uZW50IG7hu5lpIGR1bmdcbiAgICAvLyBLSMOUTkcgYuG7iyBk4buxbmcgbOG6oWkgdsOsIGBhdHRhY2hOb2RlYCBuaOG6rW4gcmEgaWQgY8WpIHbDoCBjaOG7iSBgc2V0SW5wdXRgLlxuICAgIHRoaXMucmVmcmVzaCgpO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEPhuqV1IGjDrG5oIGdyaWRzdGVyIGNobyBt4buZdCBj4bqlcCBsxrDhu5tpLlxuICAgKlxuICAgKiBAcGFyYW0gZGVwdGggMCA9IGzGsOG7m2kgY+G6pXAgdHJhbmcsIOKJpSAxID0gbMaw4bubaSBs4buTbmcgdHJvbmcgY29udGFpbmVyXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkR3JpZHN0ZXJPcHRpb25zKGRlcHRoOiBudW1iZXIsIGl0ZW1DaGFuZ2VDYWxsYmFjaz86ICgpID0+IHZvaWQpOiBHcmlkc3RlckNvbmZpZyB7XG4gICAgY29uc3QgYmFzZSA9IGRlcHRoID09PSAwID8gZ3JpZExheW91dFJvb3RDb25maWcoKSA6IGdyaWRMYXlvdXROZXN0ZWRDb25maWcoKTtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZztcblxuICAgIGlmICghY29uZmlnKSB7XG4gICAgICByZXR1cm4gYmFzZTtcbiAgICB9XG5cbiAgICBjb25zdCBpc0ZyZWVNb2RlID0gY29uZmlnLm1vZGUgPT09IEVfZ3JpZExheW91dF9tb2RlX3N0cmluZy5mcmVlO1xuICAgIGNvbnN0IGNhbkVkaXQgPSB0aGlzLmVkaXRNb2RlKCk7XG4gICAgY29uc3QgY2FuT3ZlcmxhcCA9IGlzRnJlZU1vZGUgfHwgKGNvbmZpZy5hbGxvd092ZXJsYXAgPz8gZmFsc2UpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2UsXG4gICAgICAuLi4oY29uZmlnLmNvbHMgPyB7IG1pbkNvbHM6IGNvbmZpZy5jb2xzLCBtYXhDb2xzOiBjb25maWcuY29scywgbWF4SXRlbUNvbHM6IGNvbmZpZy5jb2xzIH0gOiB7fSksXG4gICAgICAuLi4oY29uZmlnLnJvd0hlaWdodCAmJiBkZXB0aCA9PT0gMCA/IHsgZml4ZWRSb3dIZWlnaHQ6IGNvbmZpZy5yb3dIZWlnaHQgfSA6IHt9KSxcbiAgICAgIC8vIEtoZSB2w6AgY2hp4buBdSBjYW8gaMOgbmcga2jDoWMgbmhhdSB0aGVvIGPhuqVwOiBsxrDhu5tpIHRyYW5nIHRob8OhbmcsIGzGsOG7m2kgbOG7k25nIGtow610LlxuICAgICAgLi4uKGRlcHRoID09PSAwICYmIGNvbmZpZy5tYXJnaW4gIT09IHVuZGVmaW5lZCA/IHsgbWFyZ2luOiBjb25maWcubWFyZ2luIH0gOiB7fSksXG4gICAgICAuLi4oZGVwdGggPiAwICYmIGNvbmZpZy5uZXN0ZWRNYXJnaW4gIT09IHVuZGVmaW5lZCA/IHsgbWFyZ2luOiBjb25maWcubmVzdGVkTWFyZ2luIH0gOiB7fSksXG4gICAgICAuLi4oZGVwdGggPiAwICYmIGNvbmZpZy5uZXN0ZWRSb3dIZWlnaHQgIT09IHVuZGVmaW5lZCA/IHsgZml4ZWRSb3dIZWlnaHQ6IGNvbmZpZy5uZXN0ZWRSb3dIZWlnaHQgfSA6IHt9KSxcbiAgICAgIC4uLihkZXB0aCA9PT0gMCAmJiBjb25maWcub3V0ZXJNYXJnaW4gIT09IHVuZGVmaW5lZCA/IHsgb3V0ZXJNYXJnaW46IGNvbmZpZy5vdXRlck1hcmdpbiB9IDoge30pLFxuICAgICAgLi4uKGRlcHRoID09PSAwICYmIGNvbmZpZy5vdXRlck1hcmdpbkJvdHRvbSAhPT0gdW5kZWZpbmVkID8geyBvdXRlck1hcmdpbkJvdHRvbTogY29uZmlnLm91dGVyTWFyZ2luQm90dG9tIH0gOiB7fSksXG4gICAgICAuLi4oY29uZmlnLm1pbkl0ZW1Sb3dzICE9PSB1bmRlZmluZWQgPyB7IG1pbkl0ZW1Sb3dzOiBjb25maWcubWluSXRlbVJvd3MgfSA6IHt9KSxcbiAgICAgIC4uLihjb25maWcuZGVmYXVsdEl0ZW1Db2xzICE9PSB1bmRlZmluZWQgPyB7IGRlZmF1bHRJdGVtQ29sczogY29uZmlnLmRlZmF1bHRJdGVtQ29scyB9IDoge30pLFxuICAgICAgLi4uKGNvbmZpZy5kZWZhdWx0SXRlbVJvd3MgIT09IHVuZGVmaW5lZCA/IHsgZGVmYXVsdEl0ZW1Sb3dzOiBjb25maWcuZGVmYXVsdEl0ZW1Sb3dzIH0gOiB7fSksXG5cbiAgICAgIC8vIPCflLQgQ2jhur8gxJHhu5kgWEVNIHBo4bqjaSBU4bquVCBo4bqzbiBrw6lvIHbDoCDEkeG7lWkga8OtY2ggdGjGsOG7m2MuXG4gICAgICAvLyBgYmFzZWAgbHXDtG4gxJHhu4MgYGVuYWJsZWQ6IHRydWVgOyBraMO0bmcgZ2hpIMSRw6ggdGhlbyBgZWRpdE1vZGVgIHRow6wgbmfGsOG7nWkgeGVtIHbhuqtuIGvDqW8gxJHGsOG7o2Mga2jhu5FpXG4gICAgICAvLyB2w6AgxJHhu5VpIGLhu5EgY+G7pWMgY+G7p2EgbmfGsOG7nWkga2jDoWMgKG5nxrDhu51pIGTDuW5nIGLDoW8gMjgvMDgvMjAyNjogXCLEkWFuZyB4ZW0gbcOgIHbhuqtuIGvDqW8gdGjhuqMgdGhheSDEkeG7lWlcbiAgICAgIC8vIHbhu4sgdHLDrSB2w6AgdGjDqm0ga2jhu5FpIMSRxrDhu6NjXCIpLlxuICAgICAgZHJhZ2dhYmxlOiB7IC4uLmJhc2UuZHJhZ2dhYmxlLCBlbmFibGVkOiBjYW5FZGl0IH0sXG4gICAgICByZXNpemFibGU6IHsgLi4uYmFzZS5yZXNpemFibGUsIGVuYWJsZWQ6IGNhbkVkaXQgfSxcblxuICAgICAgLy8gQ2jhur8gxJHhu5kgdOG7sSBkbyBMVcOUTiBjaG8gY2jhu5NuZzsgY2jhur8gxJHhu5kgbMaw4bubaSB0aMOsIHRoZW8gY+G7nSBj4bunYSBuxqFpIGTDuW5nLlxuICAgICAgYWxsb3dNdWx0aUxheWVyOiBjYW5PdmVybGFwLFxuICAgICAgLy8g8J+UtCBC4bqtdCBgYWxsb3dNdWx0aUxheWVyYCBN4buYVCBNw4xOSCBraMO0bmcgxJHhu6cuIE3DoyBsaWIgc28gYGxheWVySW5kZXhgIGPhu6dhIGhhaSBraOG7kWk6IEtIw4FDIG5oYXVcbiAgICAgIC8vIHRow6wgY2hvIMSRw6gsIEdJ4buQTkcgbmhhdSB24bqrbiBiw6FvIHZhIGNo4bqhbS4gS2jhu5FpIGtow7RuZyBraGFpIGBsYXllckluZGV4YCDEkeG7gXUgcsahaSB24buBXG4gICAgICAvLyBgZGVmYXVsdExheWVySW5kZXhgIOKAlCB04bupYyBjw7luZyBs4bubcCwgdsOgIHbhuqtuIGLhu4sgxJHhuql5IG5oYXUgbmjGsCBsxrDhu5tpIHRoxrDhu51uZyAobmfGsOG7nWkgZMO5bmcgYsOhb1xuICAgICAgLy8gMjgvMDgvMjAyNjogXCJi4bqtdCBjaOG7k25nIGto4buRaSBuaMawbmcga2hpIGvDqW8gdGjDrCBjw6FjIGto4buRaSB24bqrbiBkaSBjaHV54buDbiB0aGVvXCIpLlxuICAgICAgLy8gQ2hvIGNo4buTbmcgdGjDrCBwaOG6o2kgVOG6rlQgxJHhuql5IGto4buRaSwgbuG6v3Uga2jDtG5nIGto4buRaSBi4buLIGThuqF0IMSRaSB0csaw4bubYyBraGkga+G7i3AgxJHDqCBsw6puIG5oYXUuXG4gICAgICAuLi4oY2FuT3ZlcmxhcCA/IHsgcHVzaEl0ZW1zOiBmYWxzZSwgcHVzaFJlc2l6ZUl0ZW1zOiBmYWxzZSwgc3dhcDogZmFsc2UsIHN3YXBXaGlsZURyYWdnaW5nOiBmYWxzZSB9IDoge30pLFxuXG4gICAgICBpdGVtQ2hhbmdlQ2FsbGJhY2s6IChpdGVtOiBHcmlkc3Rlckl0ZW0pID0+IHtcbiAgICAgICAgLy8g8J+UtCBLaOG7kWkgduG7q2EgdGhhbyB0w6FjIHBo4bqjaSBsw6puIEzhu5pQIFRSw4pOIEPDmU5HLlxuICAgICAgICAvLyBgbGF5ZXJJbmRleGAgZ8OhbiBt4buZdCBs4bqnbiB0aGVvIHRo4bupIHThu7EgY8OieSBsw7pjIGto4bufaSB04bqhbywgbsOqbiBraOG7kWkga8OpbyBsw6puIGNo4buJIG7hu5VpIFRST05HIEzDmkNcbiAgICAgICAgLy8ga8OpbyAobmjhu50gYHotaW5kZXg6IDMwYCBj4bunYSBs4bubcCBgZ3JpZHN0ZXItaXRlbS1tb3ZpbmdgKTsgdGjhuqMgdGF5IHJhIGzDoCB24buBIGzhu5twIGPFqSB2w6AgYuG7iyBraOG7kWlcbiAgICAgICAgLy8gxJHhu6luZyBzYXUgdHJvbmcgY8OieSDEkcOoIG5nxrDhu6NjIGzDqm4gKG5nxrDhu51pIGTDuW5nIGLDoW8gMjgvMDgvMjAyNiwgxJFvIMSRxrDhu6NjOiBrw6lvIHo9MzAsIHRo4bqjIHbhu4FcbiAgICAgICAgLy8gej0xMCB0cm9uZyBraGkgaGFpIGto4buRaSBr4bq/IGLDqm4gxJFhbmcgej0xMSB2w6Agej0xMikuXG4gICAgICAgIGlmIChjYW5PdmVybGFwKSB7XG4gICAgICAgICAgdGhpcy5yYWlzZVRvVG9wTGF5ZXIoaXRlbSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZlcnNpb24udXBkYXRlKCh2KSA9PiB2ICsgMSk7XG4gICAgICAgIGl0ZW1DaGFuZ2VDYWxsYmFjaz8uKCk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogR+G6r24gY29tcG9uZW50IGPhu6dhIG7GoWkgZMO5bmcgbMOqbiBt4buZdCBraOG7kWkuXG4gICAqXG4gICAqIEBwYXJhbSBob3N0IGNo4buXIGfhuq9uIFJJw4pORyBj4bunYSDDtCDEkcOzIOKAlCBt4buXaSBraOG7kWkgbeG7mXQgYFZpZXdDb250YWluZXJSZWZgLCBkw7luZyBjaHVuZyBt4buZdCBjw6FpIHRow6xcbiAgICogICBt4buNaSBjb21wb25lbnQgYuG7iyBk4buTbiBo4bq/dCB2w6BvIG3hu5l0IMO0LlxuICAgKi9cbiAgcHJpdmF0ZSBhdHRhY2hOb2RlKG5vZGU6IFRfZ3JpZExheW91dF9ub2RlLCBkZXB0aDogbnVtYmVyLCBob3N0OiBWaWV3Q29udGFpbmVyUmVmKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWc7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5jb21wb25lbnRSZWZzLmdldChub2RlLmlkKTtcblxuICAgIGlmIChleGlzdGluZykge1xuICAgICAgdGhpcy5hcHBseUlucHV0cyhleGlzdGluZywgbm9kZSwgZGVwdGgpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gS2jhu5FpIHThu7Ega2hhaSB0aMOsIGjhu49pIG7Dszsga2jDtG5nIHRow6wgaOG7j2kgaMOgbSBwaMOibiBnaeG6o2kgY2h1bmcuIEPhuqMgaGFpIMSR4buBdSBuaOG6rW4gYG5vZGVgIMSR4buDIMSR4buNY1xuICAgIC8vIMSRxrDhu6NjIGBkYXRhLnR5cGVgIG3DoCBxdXnhur90IMSR4buLbmggdHLhuqMgY29tcG9uZW50IG7DoG8uXG4gICAgY29uc3Qgc3RyZWFtID0gKG5vZGUuZ2V0Q29tcG9uZW50T3V0bGV0ID8/IGNvbmZpZy5nZXRDb21wb25lbnRPdXRsZXQpPy4obm9kZSk7XG5cbiAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIPCflLQgSHXhu7cgbMaw4bujdCB04bqjaSBDxaggY+G7p2EgxJHDum5nIGto4buRaSBuw6B5IHRyxrDhu5tjIGtoaSBt4bufIGzGsOG7o3QgbeG7m2kuXG4gICAgLy8gS2jhu5FpIGLhu4sgZ+G7oSBy4buTaSBn4bqvbiBs4bqhaSAoxJHhu5VpIGLhu5EgY+G7pWMsIHPhuq9wIGfhu41uKSB0cm9uZyBsw7pjIGBpbXBvcnQoKWAgY2jGsGEgeG9uZyB0aMOsIGzGsOG7o3QgY8WpIHbhuqtuXG4gICAgLy8gY2jhuqF5IHRp4bq/cCB2w6AgZOG7sW5nIGNvbXBvbmVudCB2w6BvIG3hu5l0IGBWaWV3Q29udGFpbmVyUmVmYCDEkcOjIGNo4bq/dC5cbiAgICB0aGlzLnBlbmRpbmdMb2Fkcy5nZXQobm9kZS5pZCk/LnVuc3Vic2NyaWJlKCk7XG5cbiAgICBjb25zdCBzdWIgPSBzdHJlYW0ucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKGNvbXBvbmVudFR5cGUpID0+IHtcbiAgICAgIHRoaXMucGVuZGluZ0xvYWRzLmRlbGV0ZShub2RlLmlkKTtcblxuICAgICAgLy8gS2jhu5FpIGPDsyB0aOG7gyDEkcOjIGLhu4sgeG/DoSB0cm9uZyBsw7pjIGNo4budIHThuqNpIOKAlCBk4buxbmcgdsOgbyDEkcOieSBsw6AgcsOyIHLhu4kuXG4gICAgICBpZiAoIXRoaXMudHJlZVNlcnZpY2UuZmluZEJ5SWQodGhpcy5yb290Tm9kZSgpID8/IG5vZGUsIG5vZGUuaWQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVmID0gaG9zdC5jcmVhdGVDb21wb25lbnQoY29tcG9uZW50VHlwZSk7XG5cbiAgICAgIHRoaXMuYXBwbHlJbnB1dHMocmVmLCBub2RlLCBkZXB0aCk7XG4gICAgICB0aGlzLmNvbXBvbmVudFJlZnMuc2V0KG5vZGUuaWQsIHJlZik7XG4gICAgfSk7XG5cbiAgICB0aGlzLnBlbmRpbmdMb2Fkcy5zZXQobm9kZS5pZCwgc3ViKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBH4buhIGNvbXBvbmVudCBj4bunYSBt4buZdCBraOG7kWkgdsOgIGh14bu3IG7Dsy4gKi9cbiAgcHJpdmF0ZSBkZXRhY2hOb2RlKG5vZGVJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgLy8gS2jhu5FpIGLhu4sgZ+G7oSBraGkgY29tcG9uZW50IGPhu6dhIG7DsyBjw7JuIMSRYW5nIHThuqNpIOKAlCBwaOG6o2kgaHXhu7cgbMaw4bujdCB04bqjaSwga2jDtG5nIHRow6wgbsOzIGThu7FuZyB2w6BvIG3hu5l0XG4gICAgLy8gYFZpZXdDb250YWluZXJSZWZgIMSRw6MgY2jhur90LlxuICAgIHRoaXMucGVuZGluZ0xvYWRzLmdldChub2RlSWQpPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMucGVuZGluZ0xvYWRzLmRlbGV0ZShub2RlSWQpO1xuXG4gICAgY29uc3QgcmVmID0gdGhpcy5jb21wb25lbnRSZWZzLmdldChub2RlSWQpO1xuXG4gICAgaWYgKCFyZWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICByZWYuZGVzdHJveSgpO1xuICAgIHRoaXMuY29tcG9uZW50UmVmcy5kZWxldGUobm9kZUlkKTtcbiAgfVxuXG4gIHByaXZhdGUgZGVzdHJveSgpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IHN1YiBvZiB0aGlzLnBlbmRpbmdMb2Fkcy52YWx1ZXMoKSkge1xuICAgICAgc3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCByZWYgb2YgdGhpcy5jb21wb25lbnRSZWZzLnZhbHVlcygpKSB7XG4gICAgICByZWYuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMucGVuZGluZ0xvYWRzLmNsZWFyKCk7XG4gICAgdGhpcy5jb21wb25lbnRSZWZzLmNsZWFyKCk7XG4gICAgdGhpcy5jb25maWcgPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgLy8gTmjDs20gaMOgbSBjaG8gbsahaSBkw7luZyBDSOG7piDEkOG7mE5HIGfhu41pIOKAlCBraMO0bmcgcGjhuqNpIGNo4budIG5nxrDhu51pIGTDuW5nIGLhuqVtIG7DunQgdHLDqm4ga2jhu5FpLlxuICAvLyBT4butYSBjw6J5IHRow6wgZMO5bmcgdGjhurNuZyBgVHJlZVNlcnZpY2VgIHLhu5NpIGfhu41pIGByZWZyZXNoKClgIOKAlCB4ZW0gZGVtbyB0cm9uZyBjb3JlLXVpLlxuICAvLyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogQsOhbyBjaG8gc2VydmljZSBiaeG6v3QgY8OieSB24burYSDEkeG7lWkgdOG7qyBiw6puIG5nb8OgaSAodGjDqm0veG/DoSBraOG7kWksIHPhuq9wIGfhu41uLCBu4bqhcCBi4buRIGPhu6VjIGtow6FjKS5cbiAgICpcbiAgICog8J+UtCBQSOG6okkgdGhheSBUSEFNIENISeG6vlUgY+G7p2Egbm9kZSBn4buRYywga2jDtG5nIGNo4buJIGLGoW0gYHZlcnNpb25gLlxuICAgKiBgQGZvciDigKYgdHJhY2sgaXRlbS5pZGAgZ2nhu68gbmd1ecOqbiBvYmplY3Qga2hpIGlkIGtow7RuZyDEkeG7lWksIG7Dqm4gYDxncmlkc3Rlci1pdGVtIFtpdGVtXT1cIuKAplwiPmAgduG6q25cbiAgICogbmjhuq1uIMSRw7puZyBvYmplY3QgY8WpIHbDoCBncmlkc3RlciBraMO0bmcgaOG7gSBiaeG6v3QgYHgveS9jb2xzL3Jvd3MvbGF5ZXJJbmRleGAgduG7q2EgYuG7iyBz4butYS4gQsahbSBt4buXaVxuICAgKiBgdmVyc2lvbmAgdGjDrCBjb21wdXRlZCBjaOG6oXkgbOG6oWkgbmjGsG5nIHRy4bqjIHbhu4EgQ8OZTkcgbeG6o25nIGPFqSDigJQgbMaw4bubaSDEkeG7qW5nIGltICjEkW8gMjgvMDgvMjAyNjogYuG6pW1cbiAgICogXCJT4bqvcCBn4buNblwiIGPDonkgxJHDoyBk4buTbiBraMOtdCBtw6AgbcOgbiBow6xuaCBraMO0bmcgbmjDumMgbmjDrWNoOyBi4bqtdCBjaOG7k25nIGto4buRaSBtw6AgYCRpdGVtLmxheWVySW5kZXhgXG4gICAqIHbhuqtuIHRy4buRbmcpLlxuICAgKlxuICAgKiBOaMOibiBi4bqjbiBOw5RORyBj4bqjIG5vZGUgZ+G7kWMgdsOgIGRhbmggc8OhY2ggY29uIGzDoCDEkeG7pzogbeG6o25nIG3hu5tpIOKGkiBgQGZvcmAgZOG7sW5nIGzhuqFpIGl0ZW0sIG9iamVjdCBjb25cbiAgICogbeG7m2kg4oaSIGdyaWRzdGVyIMSR4buNYyBs4bqhaSB0b8OgbiBi4buZIHRv4bqhIMSR4buZLlxuICAgKi9cbiAgcmVmcmVzaChldmVudD86IFRfZ3JpZExheW91dF9jaGFuZ2VFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHJvb3QgPSBldmVudD8ucm9vdCA/PyB0aGlzLnJvb3ROb2RlKCk7XG5cbiAgICBpZiAoIXJvb3QpIHtcbiAgICAgIHRoaXMudmVyc2lvbi51cGRhdGUoKHYpID0+IHYgKyAxKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZykge1xuICAgICAgdGhpcy5jb25maWcgPSB7IC4uLnRoaXMuY29uZmlnLCBkYXRhOiByb290IH07XG4gICAgfVxuXG4gICAgdGhpcy5yb290Tm9kZS5zZXQodGhpcy5zaGFsbG93Q2xvbmVUcmVlKHJvb3QpKTtcbiAgICB0aGlzLnZlcnNpb24udXBkYXRlKCh2KSA9PiB2ICsgMSk7XG4gIH1cblxuICAvKiogTmjDom4gYuG6o24gbsO0bmcgdGhlbyBj4bqjIGNoaeG7gXUgc8OidTogbeG7l2kgbm9kZSB2w6AgbeG6o25nIGBjaGlsZHJlbmAgdGjDoG5oIHRoYW0gY2hp4bq/dSBt4bubaS4gKi9cbiAgLyoqXG4gICAqIE5ow6JuIGLhuqNuIFPDglUgY+G6oyBjw6J5IOKAlCBkw7luZyBjaG8gYGV4cG9ydExheW91dCgpYC5cbiAgICpcbiAgICog8J+UtCBC4buOIGBnZXRDb21wb25lbnRPdXRsZXRgIGto4buPaSBi4bqjbiBzYW86IG7DsyBsw6AgbeG7mXQgSMOATSwga2jDtG5nIHR14bqnbiB04buxIGhvw6EgxJHGsOG7o2MgbsOqbiBn4butaSB4deG7kW5nXG4gICAqIGJhY2tlbmQgbMOgIGjhu49uZyAoYEpTT04uc3RyaW5naWZ5YCBudeG7kXQgbeG6pXQsIGBzdHJ1Y3R1cmVkQ2xvbmVgIG7DqW0gbOG7l2kpLiBO4bqhcCBs4bqhaSB0aMOsIGjDoG0gcGjDom5cbiAgICogZ2nhuqNpIGNodW5nIGPhu6dhIGPhuqV1IGjDrG5oIGxvIOKAlCBjb21wb25lbnQgc3V5IHJhIHThu6sgYGRhdGEudHlwZWAsIGtow7RuZyBj4bqnbiBsxrB1LlxuICAgKi9cbiAgcHJpdmF0ZSBkZWVwQ2xvbmVUcmVlKG5vZGU6IFRfZ3JpZExheW91dF9ub2RlKTogVF9ncmlkTGF5b3V0X25vZGUge1xuICAgIGNvbnN0IGNvcHk6IFRfZ3JpZExheW91dF9ub2RlID0geyAuLi5ub2RlIH07XG5cbiAgICAvLyBD4bqvdCBow6BtIHBow6JuIGdp4bqjaSDigJQgeGVtIGNow7ogdGjDrWNoIHRyw6puLlxuICAgIGRlbGV0ZSBjb3B5LmdldENvbXBvbmVudE91dGxldDtcblxuICAgIGNvbnN0IHsgY2hpbGRyZW4sIGRhdGEsIC4uLnJlc3QgfSA9IGNvcHk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ucmVzdCxcbiAgICAgIC4uLihkYXRhID09PSB1bmRlZmluZWQgPyB7fSA6IHsgZGF0YTogY2xvbmVEZWVwKGRhdGEpIH0pLFxuICAgICAgLi4uKGNoaWxkcmVuID8geyBjaGlsZHJlbjogY2hpbGRyZW4ubWFwKChjaGlsZCkgPT4gdGhpcy5kZWVwQ2xvbmVUcmVlKGNoaWxkKSkgfSA6IHt9KSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzaGFsbG93Q2xvbmVUcmVlKG5vZGU6IFRfZ3JpZExheW91dF9ub2RlKTogVF9ncmlkTGF5b3V0X25vZGUge1xuICAgIGlmICghbm9kZS5jaGlsZHJlbj8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4geyAuLi5ub2RlIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgLi4ubm9kZSwgY2hpbGRyZW46IG5vZGUuY2hpbGRyZW4ubWFwKChjaGlsZCkgPT4gdGhpcy5zaGFsbG93Q2xvbmVUcmVlKGNoaWxkKSkgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHw6FuIGBsYXllckluZGV4YCBraMOhYyBuaGF1IGNobyB04burbmcga2jhu5FpIGtoaSBi4bqtdCBjaOG7k25nIGto4buRaS5cbiAgICpcbiAgICog8J+UtCBgYWxsb3dNdWx0aUxheWVyOiB0cnVlYCBN4buYVCBNw4xOSCBraMO0bmcgY2hvIGto4buRaSDEkcOoIG5oYXUuIE3DoyBsaWIgc28gYGxheWVySW5kZXhgIGPhu6dhIGhhaSBraOG7kWk6XG4gICAqIEtIw4FDIG5oYXUgdGjDrCBjaG8gxJHDqCwgR0nhu5BORyBuaGF1IHbhuqtuIGLDoW8gdmEgY2jhuqFtLiBLaOG7kWkga2jDtG5nIGtoYWkgYGxheWVySW5kZXhgIMSR4buBdSByxqFpIHbhu4FcbiAgICogYGRlZmF1bHRMYXllckluZGV4YCDigJQgdOG7qWMgQ8OZTkcgbOG7m3AsIG7Dqm4ga8OpbyB2w6BvIG5oYXUgbMOgIGLhu4sgY2jhurduIHkgbmjGsCBsxrDhu5tpIHRoxrDhu51uZyAobmfGsOG7nWkgZMO5bmdcbiAgICogYsOhbyAyOC8wOC8yMDI2OiBcImLhuq10IGNo4buTbmcga2jhu5FpIG5oxrBuZyBraGkga8OpbyB0aMOsIGPDoWMga2jhu5FpIHbhuqtuIGRpIGNodXnhu4NuIHRoZW9cIikuXG4gICAqXG4gICAqIE7GoWkgZMO5bmcgdOG7sSBraGFpIGBsYXllckluZGV4YCB0aMOsIGdp4buvIG5ndXnDqm47IGFpIGtow7RuZyBraGFpIHRow6wgdGjGsCB2aeG7h24geOG6v3AgbeG7l2kga2jhu5FpIG3hu5l0IGzhu5twXG4gICAqIHRoZW8gdGjhu6kgdOG7sSwgxJHhu6cgxJHhu4MgbeG7jWkgY+G6t3AgxJHhu4F1IGtow6FjIGzhu5twLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3NpZ25PdmVybGFwTGF5ZXJzKHJvb3Q6IFRfZ3JpZExheW91dF9ub2RlKTogdm9pZCB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWc7XG4gICAgY29uc3QgY2FuT3ZlcmxhcCA9IGNvbmZpZz8ubW9kZSA9PT0gRV9ncmlkTGF5b3V0X21vZGVfc3RyaW5nLmZyZWUgfHwgKGNvbmZpZz8uYWxsb3dPdmVybGFwID8/IGZhbHNlKTtcblxuICAgIGlmICghY2FuT3ZlcmxhcCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBsYXllciA9IDA7XG4gICAgY29uc3Qgd2FsayA9IChub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSk6IHZvaWQgPT4ge1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNoaWxkcmVuID8/IFtdKSB7XG4gICAgICAgIGlmIChjaGlsZC5sYXllckluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBsYXllciArPSAxO1xuICAgICAgICAgIGNoaWxkLmxheWVySW5kZXggPSBsYXllcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdhbGsoY2hpbGQpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB3YWxrKHJvb3QpO1xuXG4gIH1cblxuICAvKiogxJDGsGEgbeG7mXQga2jhu5FpIGzDqm4gdHLDqm4gdOG6pXQgY+G6ozogbOG7m3AgY+G7p2EgbsOzID0gbOG7m3AgbOG7m24gbmjhuqV0IMSRYW5nIGPDsyArIDEuICovXG4gIHByaXZhdGUgcmFpc2VUb1RvcExheWVyKGl0ZW06IEdyaWRzdGVySXRlbSk6IHZvaWQge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG5cbiAgICBpZiAoIXJvb3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgdG9wTGF5ZXIgPSAwO1xuICAgIGNvbnN0IHdhbGsgPSAobm9kZTogVF9ncmlkTGF5b3V0X25vZGUpOiB2b2lkID0+IHtcbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbiA/PyBbXSkge1xuICAgICAgICB0b3BMYXllciA9IE1hdGgubWF4KHRvcExheWVyLCBjaGlsZC5sYXllckluZGV4ID8/IDApO1xuICAgICAgICB3YWxrKGNoaWxkKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgd2Fsayhyb290KTtcblxuICAgIC8vIGBpdGVtYCBncmlkc3RlciB0cuG6oyB24buBIENIw41OSCBsw6Agb2JqZWN0IG5vZGUgY+G7p2EgY8OieSAodHJ1eeG7gW4gdGjhurNuZyBxdWEgYFtpdGVtXWApLCBuw6puIGfDoW4gdsOgb1xuICAgIC8vIMSRw6J5IGzDoCBjw6J5IGPFqW5nIMSR4buVaSB0aGVvLlxuICAgIGNvbnN0IG5vZGUgPSBpdGVtIGFzIHVua25vd24gYXMgVF9ncmlkTGF5b3V0X25vZGU7XG5cbiAgICBpZiAobm9kZS5sYXllckluZGV4ID09PSB0b3BMYXllcikge1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbm9kZS5sYXllckluZGV4ID0gdG9wTGF5ZXIgKyAxO1xuICB9XG5cbiAgLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8vIFPhu6xBIEPDglkg4oCUIHRoxrAgdmnhu4duIMSRw6MgZ2nhu68gY8OieSBuw6puIGLhuqFuIEtIw5RORyBwaOG6o2kgdHJ1eeG7gW4gbsOzIHbDoG8uXG4gIC8vIE3hu41pIGjDoG0gZMaw4bubaSDEkcOieSB04buxIHbhur0gbOG6oWk7IGtow7RuZyBj4bqnbiBn4buNaSBgcmVmcmVzaCgpYC5cbiAgLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqXG4gICAqIFRow6ptIG3hu5l0IGto4buRaS5cbiAgICpcbiAgICogQHBhcmFtIGl0ZW0ga2jhu5FpIG3hu5tpIOKAlCBLSMOUTkcgY+G6p24gYGlkYCAodGjGsCB2aeG7h24gc2luaCkgdsOgIGB4YC9geWAgKHThu7EgxJHhurd0IHh14buRbmcgaMOgbmcgdHLhu5FuZykuXG4gICAqIEBwYXJhbSBwYXJlbnRJZCBjb250YWluZXIgbXXhu5FuIHRow6ptIHbDoG87IGLhu48gdHLhu5FuZyB0aMOsIHRow6ptIHbDoG8gbeG6t3QgcGjhurNuZyBn4buRYy5cbiAgICogQHJldHVybnMga2jhu5FpIHbhu6thIHThuqFvIChrw6htIGBpZGAgduG7q2Egc2luaCksIGhv4bq3YyBgdW5kZWZpbmVkYCBraGkga2jDtG5nIHTDrG0gdGjhuqV5IGNvbnRhaW5lci5cbiAgICovXG4gIGFkZEJsb2NrKGl0ZW06IFRfZ3JpZExheW91dF9uZXdOb2RlLCBwYXJlbnRJZD86IHN0cmluZyk6IFRfZ3JpZExheW91dF9ub2RlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuICAgIGNvbnN0IGFkZGVkID0gcm9vdCA/IHRoaXMudHJlZVNlcnZpY2UuYWRkQ2hpbGQocm9vdCwgcGFyZW50SWQgPz8gcm9vdC5pZCwgaXRlbSkgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoYWRkZWQpIHtcbiAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH1cblxuICAgIHJldHVybiBhZGRlZDtcbiAgfVxuXG4gIC8qKiBYb8OhIG3hu5l0IGto4buRaS4gWG/DoSBjb250YWluZXIgbMOgIHhvw6EgY+G6oyBydeG7mXQuIFRy4bqjIGBmYWxzZWAga2hpIGtow7RuZyB4b8OhIMSRxrDhu6NjICh2ZCBraOG7kWkgZ+G7kWMpLiAqL1xuICByZW1vdmVCbG9jayhpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcbiAgICBjb25zdCBkb25lID0gcm9vdCA/IHRoaXMudHJlZVNlcnZpY2UucmVtb3ZlQnlJZChyb290LCBpZCkgOiBmYWxzZTtcblxuICAgIGlmIChkb25lKSB7XG4gICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZG9uZTtcbiAgfVxuXG4gIC8qKiBCaeG6v24ga2jhu5FpIMSRxqFuIHRow6BuaCBDT05UQUlORVIg4oCUIG7hu5lpIGR1bmcgY8WpIHRow6BuaCBraOG7kWkgY29uIMSR4bqndSB0acOqbiwga2jDtG5nIG3huqV0IGThu68gbGnhu4d1LiAqL1xuICB0b0NvbnRhaW5lcihpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcbiAgICBjb25zdCBkb25lID0gcm9vdCA/IHRoaXMudHJlZVNlcnZpY2UudG9Db250YWluZXIocm9vdCwgaWQsIHRoaXMuY29uZmlnPy5jb2xzID8/IDEyKSA6IGZhbHNlO1xuXG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH1cblxuICAgIHJldHVybiBkb25lO1xuICB9XG5cbiAgLyoqIMSQxrBhIENPTlRBSU5FUiB24buBIGto4buRaSDEkcahbiDigJQga2jhu5FpIGNvbiDEkcaw4bujYyBuw6JuZyBsw6puIGPhuqVwIHRyw6puLCBraMO0bmcgYuG7iyB4b8OhLiAqL1xuICB0b1NpbmdsZShpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcbiAgICBjb25zdCBkb25lID0gcm9vdCA/IHRoaXMudHJlZVNlcnZpY2UudG9TaW5nbGUocm9vdCwgaWQpIDogZmFsc2U7XG5cbiAgICBpZiAoZG9uZSkge1xuICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRvbmU7XG4gIH1cblxuICAvKiogROG7k24ga2jhu5FpIGtow610IGzDqm4gdHLDqm4sIGzhuqVwIGjhur90IGNo4buXIHRy4buRbmcuIMSQ4buHIHF1eSB2w6BvIGNvbnRhaW5lci4gKi9cbiAgY29tcGFjdCgpOiB2b2lkIHtcbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgaWYgKCFyb290KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy50cmVlU2VydmljZS5jb21wYWN0KHJvb3QsIHRoaXMuY29uZmlnPy5jb2xzID8/IDEyKTtcbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBC4buRIGPhu6VjIEhJ4buGTiBU4bqgSSwgxJHDoyBj4bqvdCBt4buNaSB0aGFtIGNoaeG6v3Ug4oCUIGfhu61pIHRo4bqzbmcgeHXhu5FuZyBiYWNrZW5kIMSRxrDhu6NjLlxuICAgKlxuICAgKiBEw7luZyBraGkgYuG6pW0gbsO6dCBMxrB1LiBLaMOhYyBgUm9vdCgpYCDhu58gY2jhu5cgxJHDonkgbMOgIGLhuqNuIFNBTzogbsahaSBkw7luZyBjw7Mgc+G7rWEgZ8OsIHRyw6puIGvhur90IHF14bqjIGPFqW5nXG4gICAqIGtow7RuZyDEkeG7pW5nIHThu5tpIGPDonkgbcOgIHRoxrAgdmnhu4duIMSRYW5nIHbhur0uXG4gICAqXG4gICAqIEByZXR1cm5zIGB1bmRlZmluZWRgIGtoaSBt4bq3dCBwaOG6s25nIGNoxrBhIGBpbml0KClgLlxuICAgKi9cbiAgZXhwb3J0TGF5b3V0KCk6IFRfZ3JpZExheW91dF9ub2RlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgcmV0dXJuIHJvb3QgPyB0aGlzLmRlZXBDbG9uZVRyZWUocm9vdCkgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKiogVMOsbSBt4buZdCBraOG7kWkgdGhlbyBpZC4gKi9cbiAgZmluZEJsb2NrKGlkOiBzdHJpbmcpOiBUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcblxuICAgIHJldHVybiByb290ID8gdGhpcy50cmVlU2VydmljZS5maW5kQnlJZChyb290LCBpZCkgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKiogVMOsbSBraOG7kWkgY2hhIHRy4buxYyB0aeG6v3AgY+G7p2EgbeG7mXQga2jhu5FpLiAqL1xuICBmaW5kUGFyZW50QmxvY2soaWQ6IHN0cmluZyk6IFRfZ3JpZExheW91dF9ub2RlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgcmV0dXJuIHJvb3QgPyB0aGlzLnRyZWVTZXJ2aWNlLmZpbmRQYXJlbnQocm9vdCwgaWQpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEPhu5VuZyBEVVkgTkjhuqRUIGNobyBjYW52YXMgY+G7p2EgdGjGsCB2aeG7h24uIE7GoWkgZMO5bmcgS0jDlE5HIGfhu41pIHThu5tpIMSRw6J5LlxuICAgKlxuICAgKiBN4buNaSB0aOG7qSBjYW52YXMgY+G6p24gxJHhu4F1IGzDoCBgcHJpdmF0ZWAgxJHhu4Mga2jDtG5nIGzhu410IHJhIEFQSSBjw7RuZyBraGFpOyBnb20gdsOgbyBt4buZdCBnZXR0ZXIgdGhlbyDEkcO6bmdcbiAgICoga2h1w7RuIGBGdW5jdGlvbnNDb250cm9sYCBj4bunYSBi4buZIHF1eSDGsOG7m2MsIHRoYXkgdsOsIMSR4buDIHLhuqNpIHLDoWMgaMOgbSBwdWJsaWMgbcOgIG5nxrDhu51pIG5nb8OgaSB0xrDhu59uZ1xuICAgKiBtw6xuaCBwaOG6o2kgZ+G7jWkgKG5nxrDhu51pIGTDuW5nIGNo4buRdCAyOC8wOC8yMDI2KS5cbiAgICovXG4gIGdldCBGdW5jdGlvbnNDb250cm9sKCkge1xuICAgIHJldHVybiB7XG4gICAgICBtYXhDb250YWluZXJEZXB0aDogKCkgPT4gdGhpcy5tYXhDb250YWluZXJEZXB0aCgpLFxuICAgICAgY29udGFpbmVyUGFkZGluZzogKCkgPT4gdGhpcy5jb250YWluZXJQYWRkaW5nKCksXG4gICAgICBncmlkc3Rlck9wdGlvbnM6IChkZXB0aDogbnVtYmVyLCBjYj86ICgpID0+IHZvaWQpID0+IHRoaXMuYnVpbGRHcmlkc3Rlck9wdGlvbnMoZGVwdGgsIGNiKSxcbiAgICAgIGF0dGFjaE5vZGU6IChub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSwgZGVwdGg6IG51bWJlciwgaG9zdDogVmlld0NvbnRhaW5lclJlZikgPT4gdGhpcy5hdHRhY2hOb2RlKG5vZGUsIGRlcHRoLCBob3N0KSxcbiAgICAgIGRldGFjaE5vZGU6IChub2RlSWQ6IHN0cmluZykgPT4gdGhpcy5kZXRhY2hOb2RlKG5vZGVJZCksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwbHlJbnB1dHMocmVmOiBDb21wb25lbnRSZWY8dW5rbm93bj4sIG5vZGU6IFRfZ3JpZExheW91dF9ub2RlLCBkZXB0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgcmVmLnNldElucHV0KCdkYXRhJywgbm9kZS5kYXRhKTtcbiAgICByZWYuc2V0SW5wdXQoJ25vZGUnLCBub2RlKTtcbiAgICByZWYuc2V0SW5wdXQoJ2lzRWRpdE1vZGUnLCB0aGlzLmVkaXRNb2RlKCkpO1xuICAgIHJlZi5zZXRJbnB1dCgnZGVwdGgnLCBkZXB0aCk7XG4gIH1cbn1cbiJdfQ==
438
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC1sYXlvdXQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMtdWkvc2VydmljZXMvZ3JpZC1sYXlvdXQvc3JjL2dyaWQtbGF5b3V0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFnQixVQUFVLEVBQUUsVUFBVSxFQUFvQixNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQWdCLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNoRyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7QUFTN0Q7Ozs7Ozs7Ozs7R0FVRztBQUVILE1BQU0sT0FBTyx1QkFBdUI7SUFDbEMsNkZBQTZGO0lBQzdGLHdGQUF3RjtJQUN4RixtRkFBbUY7SUFDbEUsV0FBVyxHQUFHLElBQUksMkJBQTJCLEVBQUUsQ0FBQztJQUNqRSxvRkFBb0Y7SUFDbkUsWUFBWSxHQUFHLElBQUksR0FBRyxFQUF3QixDQUFDO0lBRWhFO1FBQ0UsK0ZBQStGO1FBQy9GLHlGQUF5RjtRQUN6RiwrRkFBK0Y7UUFDL0YsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRU8sTUFBTSxDQUF1QjtJQUNwQixhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQWlDLENBQUM7SUFFekQsUUFBUSxHQUFHLE1BQU0sQ0FBZ0MsU0FBUyxDQUFDLENBQUM7SUFDNUQsUUFBUSxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNuRCxxRUFBcUU7SUFDcEQsT0FBTyxH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QUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNsRSxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFBSSxnQkFBZ0I7UUFDbEIsT0FBTztZQUNMLGlCQUFpQixFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUNqRCxnQkFBZ0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDL0MsZUFBZSxFQUFFLENBQUMsS0FBYSxFQUFFLEVBQWUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDekYsVUFBVSxFQUFFLENBQUMsSUFBdUIsRUFBRSxLQUFhLEVBQUUsSUFBc0IsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQztZQUNsSCxVQUFVLEVBQUUsQ0FBQyxNQUFjLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1NBQ3hELENBQUM7SUFDSixDQUFDO0lBRU8sV0FBVyxDQUFDLEdBQTBCLEVBQUUsSUFBdUIsRUFBRSxLQUFhO1FBQ3BGLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoQyxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMzQixHQUFHLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM1QyxHQUFHLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO3dHQXhmVSx1QkFBdUI7NEdBQXZCLHVCQUF1Qjs7NEZBQXZCLHVCQUF1QjtrQkFEbkMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudFJlZiwgRGVzdHJveVJlZiwgSW5qZWN0YWJsZSwgVmlld0NvbnRhaW5lclJlZiwgaW5qZWN0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEdyaWRzdGVyQ29uZmlnLCBHcmlkc3Rlckl0ZW0gfSBmcm9tICdncmlkc3RlcjE4JztcbmltcG9ydCB7IGNsb25lRGVlcCB9IGZyb20gJ0BsaWJzLXVpL3V0aWxzJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiwgdGFrZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZ3JpZExheW91dE5lc3RlZENvbmZpZywgZ3JpZExheW91dFJvb3RDb25maWcgfSBmcm9tICcuL2RlZmluZXMvZ3JpZHN0ZXItY29uZmlnLmRlZmluZSc7XG5pbXBvcnQgeyBMaWJzVWlHcmlkTGF5b3V0VHJlZVNlcnZpY2UgfSBmcm9tICcuL3RyZWUuc2VydmljZSc7XG5pbXBvcnQge1xuICBFX2dyaWRMYXlvdXRfbW9kZV9zdHJpbmcsXG4gIFRfZ3JpZExheW91dF9jaGFuZ2VFdmVudCxcbiAgVF9ncmlkTGF5b3V0X25ld05vZGUsXG4gIFRfZ3JpZExheW91dF9jb25maWcsXG4gIFRfZ3JpZExheW91dF9ub2RlLFxufSBmcm9tICcuL2ludGVyZmFjZXMvZ3JpZC1sYXlvdXQuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBE4buxbmcgbeG7mXQgbeG6t3QgcGjhurNuZyBrw6lvIHRo4bqjIHbDoCB04buxIGfhuq9uIGNvbXBvbmVudCBj4bunYSBuxqFpIGTDuW5nIGzDqm4gdOG7q25nIGto4buRaS5cbiAqXG4gKiBOxqFpIGTDuW5nIGNo4buJIGPhuqduIMSRxrBhIHbDoG86IGxv4bqhaSBjb21wb25lbnQgbXXhu5FuIGThu7FuZ1xuICogKGBub2RlQ29tcG9uZW50VHlwZWApIHbDoCBjw6J5IGThu68gbGnhu4d1IChgZGF0YWApLiBUb8OgbiBi4buZIHZp4buHYyB24bq9IGzGsOG7m2ksIGvDqW8gdGjhuqMsIMSR4buVaSBrw61jaCB0aMaw4bubYyxcbiAqIGzhu5NuZyBjb250YWluZXIgdsOgIGThu41uIGThurlwIGRvIHRoxrAgdmnhu4duIGxvLlxuICpcbiAqIPCflLQgxJDDonkgbMOgIHNlcnZpY2UgdGhlbyBU4buqTkcgbeG6t3QgcGjhurNuZywgS0jDlE5HIGBwcm92aWRlZEluOiAncm9vdCdgLiBLaGFpIHRyb25nIGBwcm92aWRlcnNgIGPhu6dhXG4gKiBjb21wb25lbnQgZMO5bmcgbsOzOyBoYWkgbeG6t3QgcGjhurNuZyB0csOqbiBjw7luZyBt4buZdCBtw6BuIHBo4bqjaSBsw6AgaGFpIHRo4buxYyB0aOG7gyByacOqbmcsIGTDuW5nIGNodW5nIHRow6xcbiAqIGBjb21wb25lbnRSZWZzYCBj4bunYSBt4bq3dCBwaOG6s25nIG7DoHkgYuG7iyBt4bq3dCBwaOG6s25nIGtpYSBk4buNbiBt4bqldC5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIExpYnNVaUdyaWRMYXlvdXRTZXJ2aWNlIHtcbiAgLy8g8J+UtCBU4buwIFThuqBPLCBraMO0bmcgYGluamVjdGAuIE7GoWkgZMO5bmcgY2jhu4kgcGjhuqNpIHZp4bq/dCBgcHJvdmlkZXJzOiBbTGlic1VpR3JpZExheW91dFNlcnZpY2VdYCDigJRcbiAgLy8ga2jDtG5nIHBo4bqjaSBiaeG6v3QgYsOqbiB0cm9uZyB0aMawIHZp4buHbiBjw7JuIHNlcnZpY2UgbsOgbyBraMOhYyAobmfGsOG7nWkgZMO5bmcgY2jhu5F0IDI4LzA4LzIwMjYpLlxuICAvLyBgVHJlZVNlcnZpY2VgIGtow7RuZyBnaeG7ryB0cuG6oW5nIHRow6FpIGTDuW5nIGNodW5nIG7Dqm4gbeG7l2kgbeG6t3QgcGjhurNuZyBt4buZdCBi4bqjbiBsw6AgxJHDum5nLlxuICBwcml2YXRlIHJlYWRvbmx5IHRyZWVTZXJ2aWNlID0gbmV3IExpYnNVaUdyaWRMYXlvdXRUcmVlU2VydmljZSgpO1xuICAvKiogTMaw4bujdCB04bqjaSBjb21wb25lbnQgxJFhbmcgY2jhu50sIHRoZW8gaWQga2jhu5FpIOKAlCDEkeG7gyBodeG7tyBraGkga2jhu5FpIGLhu4sgZ+G7oSBnaeG7r2EgY2jhu6tuZy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBwZW5kaW5nTG9hZHMgPSBuZXcgTWFwPHN0cmluZywgU3Vic2NyaXB0aW9uPigpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIPCflLQgU2VydmljZSBraGFpIHRyb25nIGBwcm92aWRlcnNgIGPhu6dhIGNvbXBvbmVudCBuw6puIEFuZ3VsYXIgaHXhu7cgbsOzIGPDuW5nIGNvbXBvbmVudCDigJQgdGjGsCB2aeG7h25cbiAgICAvLyB04buxIGThu41uIOG7nyDEkcOieSwgbsahaSBkw7luZyBLSMOUTkcgcGjhuqNpIGfhu41pIGBkZXN0cm95KClgIHRyb25nIGBuZ09uRGVzdHJveWAgKG5nxrDhu51pIGTDuW5nIGNo4buRdFxuICAgIC8vIDI4LzA4LzIwMjYpLiBC4bqvdCBuaOG7myBt4buZdCBixrDhu5tjIGThu41uIGThurlwIGzDoCBraeG7g3UgQVBJIGThu4UgcXXDqm4sIHbDoCBxdcOqbiB0aMOsIHLDsiBy4buJIGLhu5kgbmjhu5sgaW0gbOG6t25nLlxuICAgIGluamVjdChEZXN0cm95UmVmKS5vbkRlc3Ryb3koKCkgPT4gdGhpcy5kZXN0cm95KCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25maWc/OiBUX2dyaWRMYXlvdXRfY29uZmlnO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbXBvbmVudFJlZnMgPSBuZXcgTWFwPHN0cmluZywgQ29tcG9uZW50UmVmPHVua25vd24+PigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vdE5vZGUgPSBzaWduYWw8VF9ncmlkTGF5b3V0X25vZGUgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZWRpdE1vZGUgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICAvKiogdMSDbmcgbeG7l2kgbOG6p24gY8OieSDEkeG7lWkg4oCUIGNvbXBvbmVudCBjb24gxJHhu41jIMSR4buDIGJp4bq/dCBwaOG6o2kgdMOtbmggbOG6oWkgKi9cbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJzaW9uID0gc2lnbmFsPG51bWJlcj4oMCk7XG5cbiAgLyoqXG4gICAqIFNpZ25hbCBjaOG7iSDEkeG7jWMgxJHhu4MgbsahaSBkw7luZyB0aGVvIGTDtWkuXG4gICAqXG4gICAqIPCflLQgTMOgIFRIVeG7mEMgVMONTkgsIGtow7RuZyBwaOG6o2kgZ2V0dGVyLiBHZXR0ZXIgdHLhuqMgc2lnbmFsIHRow6wgY2jhu5cgxJHhu41jIHBo4bqjaSB2aeG6v3QgYFZlcnNpb24oKSgpYCDigJRcbiAgICogcXXDqm4gY+G6t3Agbmdv4bq3YyB0aOG7qSBoYWkgbMOgIGNvbXB1dGVkIEtIw5RORyBwaOG7pSB0aHXhu5ljIHbDoG8gbsOzLCBjw6J5IMSR4buVaSBtw6AgbMaw4bubaSDEkeG7qW5nIGltLCB2w6BcbiAgICogVHlwZVNjcmlwdCBraMO0bmcgaOG7gSBiw6FvIGzhu5dpICjEkW8gMjgvMDgvMjAyNjogdGjDqm0ga2jhu5FpIGtow7RuZyBoaeG7h24sIHPhuq9wIGfhu41uIGtow7RuZyBuaMO6YyBuaMOtY2gpLlxuICAgKi9cbiAgcmVhZG9ubHkgUm9vdCA9IHRoaXMucm9vdE5vZGUuYXNSZWFkb25seSgpO1xuICByZWFkb25seSBJc0VkaXRNb2RlID0gdGhpcy5lZGl0TW9kZS5hc1JlYWRvbmx5KCk7XG4gIC8qKiB0xINuZyBt4buXaSBs4bqnbiBjw6J5IGhv4bq3YyBj4bqldSBow6xuaCDEkeG7lWkgKi9cbiAgcmVhZG9ubHkgVmVyc2lvbiA9IHRoaXMudmVyc2lvbi5hc1JlYWRvbmx5KCk7XG5cbiAgLyoqXG4gICAqIHRy4bqnbiBz4buRIGPhuqVwIGNvbnRhaW5lciBs4buTbmcgbmhhdSDigJQgY2FudmFzIMSR4buNYyDEkeG7gyBiaeG6v3QgY8OzIGNobyBjaHV54buDbiB0aMOgbmggY29udGFpbmVyIGtow7RuZyAqL1xuICBwcml2YXRlIG1heENvbnRhaW5lckRlcHRoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnPy5tYXhDb250YWluZXJEZXB0aCA/PyAxO1xuICB9XG5cbiAgLyoqXG4gICAqIGzhu4EgdHJvbmcgY+G7p2EgY29udGFpbmVyLCBweCDigJQgY2FudmFzIMSR4buNYyDEkeG7gyDEkeG6t3QgcGFkZGluZyBsw6puIHbhu48gY29udGFpbmVyICovXG4gIHByaXZhdGUgY29udGFpbmVyUGFkZGluZygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZz8uY29udGFpbmVyUGFkZGluZyA/PyAxMjtcbiAgfVxuXG4gIC8qKiBLaOG7n2kgdOG6oW8gbeG6t3QgcGjhurNuZy4gR+G7jWkgbOG6oWkgc+G6vSBk4buNbiBz4bqhY2ggY29tcG9uZW50IGPFqSBy4buTaSBk4buxbmcgbOG6oWkgdOG7qyDEkeG6p3UuICovXG4gIGluaXQoY29uZmlnOiBUX2dyaWRMYXlvdXRfY29uZmlnKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95KCk7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgLy8g8J+UtCBC4buRIGPhu6VjIMSQw4MgTMavVSBraMO0bmcgxJFpIHF1YSBsdeG6rXQgY2jhurduIG7DoG8gY+G7p2EgZ2lhbyBkaeG7h246IGLhuqNuIGzGsHUgY8WpIChzaW5oIHRyxrDhu5tjIGtoaSBjw7MgdHLhuqduLFxuICAgIC8vIGhv4bq3YyBkbyB0aGFvIHTDoWMgbOG7l2kpIHbhuqtuIG1hbmcgY29udGFpbmVyIGzhu5NuZyBjb250YWluZXIuIFRy4bqnbiBgbWF4Q29udGFpbmVyRGVwdGhgIGNo4buJIOG6qW4gTsOaVFxuICAgIC8vIHRyw6puIGNhbnZhcyDigJQgbsOzIGtow7RuZyBz4butYSBk4buvIGxp4buHdSwgbsOqbiB0aGnhur91IGTDsm5nIG7DoHkgbMOgIHbhur0gcmEgxJHDum5nIGPDonkgcXXDoSBzw6J1IMSRw7MuXG4gICAgLy8gTsahaSBkw7luZyBLSMOUTkcgdOG7sSBn4buNaSDEkcaw4bujYzogYExpYnNVaUdyaWRMYXlvdXRUcmVlU2VydmljZWAgY+G7kSDDvSBraMO0bmcgeHXhuqV0LlxuICAgIHRoaXMudHJlZVNlcnZpY2UuZmxhdHRlbk92ZXJEZXB0aENvbnRhaW5lcnMoY29uZmlnLmRhdGEsIHRoaXMubWF4Q29udGFpbmVyRGVwdGgoKSk7XG4gICAgdGhpcy5hc3NpZ25PdmVybGFwTGF5ZXJzKGNvbmZpZy5kYXRhKTtcbiAgICAvLyDwn5S0IE5ow6JuIGLhuqNuIG5oxrAgYHJlZnJlc2goKWA6IGBpbml0KClgIGzhuqFpICjEkeG7lWkgY2jhur8gxJHhu5ksIGLhuq10L3Thuq90IGNo4buTbmcga2jhu5FpKSB0csOqbiBDw5lORyBvYmplY3QgY8OieVxuICAgIC8vIHRow6wgYEBmb3JgIGtow7RuZyBk4buxbmcgbOG6oWkgYGdyaWRzdGVyLWl0ZW1gLCBuw6puIGBsYXllckluZGV4YCB24burYSBnw6FuIGtow7RuZyB04bubaSBgJGl0ZW1gIHbDoCBraOG7kWlcbiAgICAvLyB24bqrbiBraMO0bmcgxJHDqCBuaGF1IMSRxrDhu6NjICjEkW8gMjgvMDgvMjAyNjogYGl0ZW0ubGF5ZXJJbmRleGAgPSAxfDJ8M3w0fDcgbcOgIGAkaXRlbS5sYXllckluZGV4YFxuICAgIC8vIHRvw6BuIGB1bmRlZmluZWRgKS5cbiAgICB0aGlzLnJvb3ROb2RlLnNldCh0aGlzLnNoYWxsb3dDbG9uZVRyZWUoY29uZmlnLmRhdGEpKTtcbiAgICB0aGlzLmVkaXRNb2RlLnNldChjb25maWcuaXNFZGl0TW9kZSA/PyBmYWxzZSk7XG4gICAgdGhpcy52ZXJzaW9uLnVwZGF0ZSgodikgPT4gdiArIDEpO1xuICB9XG5cbiAgc2V0RWRpdE1vZGUodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmVkaXRNb2RlLnNldCh2YWx1ZSk7XG4gICAgLy8g8J+UtCBQSOG6okkgYsahbSBgdmVyc2lvbmA6IGBncmlkc3Rlck9wdGlvbnMoKWAgxJHhu41jIGBlZGl0TW9kZWAgxJHhu4MgYuG6rXQvdOG6r3Qga8Opb+KAk3Ro4bqjLCBtw6AgY29tcHV0ZWRcbiAgICAvLyBgZ3JpZE9wdGlvbnNgIGLDqm4gY2FudmFzIGNo4buJIGNo4bqheSBs4bqhaSBraGkgYFZlcnNpb25gIMSR4buVaS4gVGhp4bq/dSBkw7JuZyBuw6B5IHRow6wgxJHhu5VpIGNo4bq/IMSR4buZIHhvbmdcbiAgICAvLyBncmlkc3RlciB24bqrbiBnaeG7ryBvcHRpb25zIGPFqSDigJQgY2h1eeG7g24gc2FuZyBYRU0gbcOgIGto4buRaSB24bqrbiBrw6lvIMSRxrDhu6NjLlxuICAgIHRoaXMudmVyc2lvbi51cGRhdGUoKHYpID0+IHYgKyAxKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBC4bqtdC904bqvdCBjaG8ga2jhu5FpIGNo4buTbmcgbMOqbiBuaGF1IOKAlCBLSMOUTkcgZOG7sW5nIGzhuqFpIG3hurd0IHBo4bqzbmcuXG4gICAqXG4gICAqIFRyxrDhu5tjIMSRw6J5IG7GoWkgZMO5bmcgcGjhuqNpIGfhu41pIGBpbml0KClgIGzhuqFpIMSR4buDIMSR4buVaSBj4budIG7DoHksIG3DoCBgaW5pdCgpYCBodeG7tyBz4bqhY2ggcuG7k2kgZOG7sW5nIGzhuqFpIG3hu41pXG4gICAqIGNvbXBvbmVudCBu4buZaSBkdW5nIOKAlCBsw6NuZyBwaMOtLCB2w6AgbmfGsOG7nWkgZMO5bmcgdGjhuqV5IG3DoG4gY2jhu5twIChuZ8aw4budaSBkw7luZyBjaOG7kXQgMjgvMDgvMjAyNikuXG4gICAqL1xuICBzZXRBbGxvd092ZXJsYXAodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5jb25maWcgPSB7IC4uLnRoaXMuY29uZmlnLCBhbGxvd092ZXJsYXA6IHZhbHVlIH07XG5cbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgaWYgKCFyb290KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g8J+UtCBHw6FuIGzhu5twIHbDoG8gQ8OCWSDEkEFORyBW4bq8IChgcm9vdE5vZGVgKSwgS0jDlE5HIHBo4bqjaSBgY29uZmlnLmRhdGFgLlxuICAgIC8vIGBpbml0KClgIMSRw6MgY2xvbmUgYGNvbmZpZy5kYXRhYCBzYW5nIGByb290Tm9kZWAgbsOqbiBoYWkgb2JqZWN0IEtIw4FDIG5oYXU7IGfDoW4gdsOgbyBgY29uZmlnLmRhdGFgXG4gICAgLy8gdGjDrCBgcmVmcmVzaCgpYCBjbG9uZSBs4bqhaSB04burIGByb290Tm9kZWAg4oCUIGzhu5twIHbhu6thIGfDoW4ga2jDtG5nIHThu5tpIGBncmlkc3Rlci1pdGVtYCBuw6BvLCBgei1pbmRleGBcbiAgICAvLyBj4bunYSBt4buNaSBraOG7kWkgxJHhu6luZyDhu58gYDFgIHbDoCBraOG7kWkgbsOgbyB24bq9IHNhdSB0aMOsIG7hurFtIHRyw6puOiBjaOG7k25nIGto4buRaSBcImzDumMgxJHGsOG7o2MgbMO6YyBraMO0bmdcIlxuICAgIC8vICjEkW8gMDQvMDkvMjAyNjogYGl0ZW0ubGF5ZXJJbmRleGAgdW5kZWZpbmVkLCBgZ2V0TGF5ZXJJbmRleCgpYCA9IDAgY2hvIGPhuqMgOCBraOG7kWkpLlxuICAgIHRoaXMuYXNzaWduT3ZlcmxhcExheWVycyhyb290KTtcbiAgICAvLyBUaGF5IHRoYW0gY2hp4bq/dSBjw6J5IMSR4buDIGBsYXllckluZGV4YCB24burYSBnw6FuIHThu5tpIMSRxrDhu6NjIGAkaXRlbWAgY+G7p2EgZ3JpZHN0ZXI7IGNvbXBvbmVudCBu4buZaSBkdW5nXG4gICAgLy8gS0jDlE5HIGLhu4sgZOG7sW5nIGzhuqFpIHbDrCBgYXR0YWNoTm9kZWAgbmjhuq1uIHJhIGlkIGPFqSB2w6AgY2jhu4kgYHNldElucHV0YC5cbiAgICB0aGlzLnJlZnJlc2goKTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBD4bqldSBow6xuaCBncmlkc3RlciBjaG8gbeG7mXQgY+G6pXAgbMaw4bubaS5cbiAgICpcbiAgICogQHBhcmFtIGRlcHRoIDAgPSBsxrDhu5tpIGPhuqVwIHRyYW5nLCDiiaUgMSA9IGzGsOG7m2kgbOG7k25nIHRyb25nIGNvbnRhaW5lclxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEdyaWRzdGVyT3B0aW9ucyhkZXB0aDogbnVtYmVyLCBpdGVtQ2hhbmdlQ2FsbGJhY2s/OiAoKSA9PiB2b2lkKTogR3JpZHN0ZXJDb25maWcge1xuICAgIGNvbnN0IGJhc2UgPSBkZXB0aCA9PT0gMCA/IGdyaWRMYXlvdXRSb290Q29uZmlnKCkgOiBncmlkTGF5b3V0TmVzdGVkQ29uZmlnKCk7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5jb25maWc7XG5cbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmV0dXJuIGJhc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaXNGcmVlTW9kZSA9IGNvbmZpZy5tb2RlID09PSBFX2dyaWRMYXlvdXRfbW9kZV9zdHJpbmcuZnJlZTtcbiAgICBjb25zdCBjYW5FZGl0ID0gdGhpcy5lZGl0TW9kZSgpO1xuICAgIGNvbnN0IGNhbk92ZXJsYXAgPSBpc0ZyZWVNb2RlIHx8IChjb25maWcuYWxsb3dPdmVybGFwID8/IGZhbHNlKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5iYXNlLFxuICAgICAgLi4uKGNvbmZpZy5jb2xzID8geyBtaW5Db2xzOiBjb25maWcuY29scywgbWF4Q29sczogY29uZmlnLmNvbHMsIG1heEl0ZW1Db2xzOiBjb25maWcuY29scyB9IDoge30pLFxuICAgICAgLi4uKGNvbmZpZy5yb3dIZWlnaHQgJiYgZGVwdGggPT09IDAgPyB7IGZpeGVkUm93SGVpZ2h0OiBjb25maWcucm93SGVpZ2h0IH0gOiB7fSksXG4gICAgICAvLyBLaGUgdsOgIGNoaeG7gXUgY2FvIGjDoG5nIGtow6FjIG5oYXUgdGhlbyBj4bqlcDogbMaw4bubaSB0cmFuZyB0aG/DoW5nLCBsxrDhu5tpIGzhu5NuZyBraMOtdC5cbiAgICAgIC4uLihkZXB0aCA9PT0gMCAmJiBjb25maWcubWFyZ2luICE9PSB1bmRlZmluZWQgPyB7IG1hcmdpbjogY29uZmlnLm1hcmdpbiB9IDoge30pLFxuICAgICAgLi4uKGRlcHRoID4gMCAmJiBjb25maWcubmVzdGVkTWFyZ2luICE9PSB1bmRlZmluZWQgPyB7IG1hcmdpbjogY29uZmlnLm5lc3RlZE1hcmdpbiB9IDoge30pLFxuICAgICAgLi4uKGRlcHRoID4gMCAmJiBjb25maWcubmVzdGVkUm93SGVpZ2h0ICE9PSB1bmRlZmluZWQgPyB7IGZpeGVkUm93SGVpZ2h0OiBjb25maWcubmVzdGVkUm93SGVpZ2h0IH0gOiB7fSksXG4gICAgICAuLi4oZGVwdGggPT09IDAgJiYgY29uZmlnLm91dGVyTWFyZ2luICE9PSB1bmRlZmluZWQgPyB7IG91dGVyTWFyZ2luOiBjb25maWcub3V0ZXJNYXJnaW4gfSA6IHt9KSxcbiAgICAgIC4uLihkZXB0aCA9PT0gMCAmJiBjb25maWcub3V0ZXJNYXJnaW5Cb3R0b20gIT09IHVuZGVmaW5lZCA/IHsgb3V0ZXJNYXJnaW5Cb3R0b206IGNvbmZpZy5vdXRlck1hcmdpbkJvdHRvbSB9IDoge30pLFxuICAgICAgLi4uKGNvbmZpZy5taW5JdGVtUm93cyAhPT0gdW5kZWZpbmVkID8geyBtaW5JdGVtUm93czogY29uZmlnLm1pbkl0ZW1Sb3dzIH0gOiB7fSksXG4gICAgICAuLi4oY29uZmlnLmRlZmF1bHRJdGVtQ29scyAhPT0gdW5kZWZpbmVkID8geyBkZWZhdWx0SXRlbUNvbHM6IGNvbmZpZy5kZWZhdWx0SXRlbUNvbHMgfSA6IHt9KSxcbiAgICAgIC4uLihjb25maWcuZGVmYXVsdEl0ZW1Sb3dzICE9PSB1bmRlZmluZWQgPyB7IGRlZmF1bHRJdGVtUm93czogY29uZmlnLmRlZmF1bHRJdGVtUm93cyB9IDoge30pLFxuXG4gICAgICAvLyDwn5S0IENo4bq/IMSR4buZIFhFTSBwaOG6o2kgVOG6rlQgaOG6s24ga8OpbyB2w6AgxJHhu5VpIGvDrWNoIHRoxrDhu5tjLlxuICAgICAgLy8gYGJhc2VgIGx1w7RuIMSR4buDIGBlbmFibGVkOiB0cnVlYDsga2jDtG5nIGdoaSDEkcOoIHRoZW8gYGVkaXRNb2RlYCB0aMOsIG5nxrDhu51pIHhlbSB24bqrbiBrw6lvIMSRxrDhu6NjIGto4buRaVxuICAgICAgLy8gdsOgIMSR4buVaSBi4buRIGPhu6VjIGPhu6dhIG5nxrDhu51pIGtow6FjIChuZ8aw4budaSBkw7luZyBiw6FvIDI4LzA4LzIwMjY6IFwixJFhbmcgeGVtIG3DoCB24bqrbiBrw6lvIHRo4bqjIHRoYXkgxJHhu5VpXG4gICAgICAvLyB24buLIHRyw60gdsOgIHRow6ptIGto4buRaSDEkcaw4bujY1wiKS5cbiAgICAgIGRyYWdnYWJsZTogeyAuLi5iYXNlLmRyYWdnYWJsZSwgZW5hYmxlZDogY2FuRWRpdCB9LFxuICAgICAgcmVzaXphYmxlOiB7IC4uLmJhc2UucmVzaXphYmxlLCBlbmFibGVkOiBjYW5FZGl0IH0sXG5cbiAgICAgIC8vIENo4bq/IMSR4buZIHThu7EgZG8gTFXDlE4gY2hvIGNo4buTbmc7IGNo4bq/IMSR4buZIGzGsOG7m2kgdGjDrCB0aGVvIGPhu50gY+G7p2EgbsahaSBkw7luZy5cbiAgICAgIGFsbG93TXVsdGlMYXllcjogY2FuT3ZlcmxhcCxcbiAgICAgIC8vIPCflLQgQuG6rXQgYGFsbG93TXVsdGlMYXllcmAgTeG7mFQgTcOMTkgga2jDtG5nIMSR4bunLiBNw6MgbGliIHNvIGBsYXllckluZGV4YCBj4bunYSBoYWkga2jhu5FpOiBLSMOBQyBuaGF1XG4gICAgICAvLyB0aMOsIGNobyDEkcOoLCBHSeG7kE5HIG5oYXUgduG6q24gYsOhbyB2YSBjaOG6oW0uIEto4buRaSBraMO0bmcga2hhaSBgbGF5ZXJJbmRleGAgxJHhu4F1IHLGoWkgduG7gVxuICAgICAgLy8gYGRlZmF1bHRMYXllckluZGV4YCDigJQgdOG7qWMgY8O5bmcgbOG7m3AsIHbDoCB24bqrbiBi4buLIMSR4bqpeSBuaGF1IG5oxrAgbMaw4bubaSB0aMaw4budbmcgKG5nxrDhu51pIGTDuW5nIGLDoW9cbiAgICAgIC8vIDI4LzA4LzIwMjY6IFwiYuG6rXQgY2jhu5NuZyBraOG7kWkgbmjGsG5nIGtoaSBrw6lvIHRow6wgY8OhYyBraOG7kWkgduG6q24gZGkgY2h1eeG7g24gdGhlb1wiKS5cbiAgICAgIC8vIENobyBjaOG7k25nIHRow6wgcGjhuqNpIFThuq5UIMSR4bqpeSBraOG7kWksIG7hur91IGtow7RuZyBraOG7kWkgYuG7iyBk4bqhdCDEkWkgdHLGsOG7m2Mga2hpIGvhu4twIMSRw6ggbMOqbiBuaGF1LlxuICAgICAgLi4uKGNhbk92ZXJsYXAgPyB7IHB1c2hJdGVtczogZmFsc2UsIHB1c2hSZXNpemVJdGVtczogZmFsc2UsIHN3YXA6IGZhbHNlLCBzd2FwV2hpbGVEcmFnZ2luZzogZmFsc2UgfSA6IHt9KSxcblxuICAgICAgaXRlbUNoYW5nZUNhbGxiYWNrOiAoaXRlbTogR3JpZHN0ZXJJdGVtKSA9PiB7XG4gICAgICAgIC8vIPCflLQgS2jhu5FpIHbhu6thIHRoYW8gdMOhYyBwaOG6o2kgbMOqbiBM4buaUCBUUsOKTiBDw5lORy5cbiAgICAgICAgLy8gYGxheWVySW5kZXhgIGfDoW4gbeG7mXQgbOG6p24gdGhlbyB0aOG7qSB04buxIGPDonkgbMO6YyBraOG7n2kgdOG6oW8sIG7Dqm4ga2jhu5FpIGvDqW8gbMOqbiBjaOG7iSBu4buVaSBUUk9ORyBMw5pDXG4gICAgICAgIC8vIGvDqW8gKG5o4budIGB6LWluZGV4OiAzMGAgY+G7p2EgbOG7m3AgYGdyaWRzdGVyLWl0ZW0tbW92aW5nYCk7IHRo4bqjIHRheSByYSBsw6AgduG7gSBs4bubcCBjxakgdsOgIGLhu4sga2jhu5FpXG4gICAgICAgIC8vIMSR4bupbmcgc2F1IHRyb25nIGPDonkgxJHDqCBuZ8aw4bujYyBsw6puIChuZ8aw4budaSBkw7luZyBiw6FvIDI4LzA4LzIwMjYsIMSRbyDEkcaw4bujYzoga8OpbyB6PTMwLCB0aOG6oyB24buBXG4gICAgICAgIC8vIHo9MTAgdHJvbmcga2hpIGhhaSBraOG7kWkga+G6vyBiw6puIMSRYW5nIHo9MTEgdsOgIHo9MTIpLlxuICAgICAgICBpZiAoY2FuT3ZlcmxhcCkge1xuICAgICAgICAgIHRoaXMucmFpc2VUb1RvcExheWVyKGl0ZW0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52ZXJzaW9uLnVwZGF0ZSgodikgPT4gdiArIDEpO1xuICAgICAgICBpdGVtQ2hhbmdlQ2FsbGJhY2s/LigpO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEfhuq9uIGNvbXBvbmVudCBj4bunYSBuxqFpIGTDuW5nIGzDqm4gbeG7mXQga2jhu5FpLlxuICAgKlxuICAgKiBAcGFyYW0gaG9zdCBjaOG7lyBn4bqvbiBSScOKTkcgY+G7p2Egw7QgxJHDsyDigJQgbeG7l2kga2jhu5FpIG3hu5l0IGBWaWV3Q29udGFpbmVyUmVmYCwgZMO5bmcgY2h1bmcgbeG7mXQgY8OhaSB0aMOsXG4gICAqICAgbeG7jWkgY29tcG9uZW50IGLhu4sgZOG7k24gaOG6v3QgdsOgbyBt4buZdCDDtC5cbiAgICovXG4gIHByaXZhdGUgYXR0YWNoTm9kZShub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSwgZGVwdGg6IG51bWJlciwgaG9zdDogVmlld0NvbnRhaW5lclJlZik6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY29uZmlnO1xuXG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMuY29tcG9uZW50UmVmcy5nZXQobm9kZS5pZCk7XG5cbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHRoaXMuYXBwbHlJbnB1dHMoZXhpc3RpbmcsIG5vZGUsIGRlcHRoKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEto4buRaSB04buxIGtoYWkgdGjDrCBo4buPaSBuw7M7IGtow7RuZyB0aMOsIGjhu49pIGjDoG0gcGjDom4gZ2nhuqNpIGNodW5nLiBD4bqjIGhhaSDEkeG7gXUgbmjhuq1uIGBub2RlYCDEkeG7gyDEkeG7jWNcbiAgICAvLyDEkcaw4bujYyBgZGF0YS50eXBlYCBtw6AgcXV54bq/dCDEkeG7i25oIHRy4bqjIGNvbXBvbmVudCBuw6BvLlxuICAgIGNvbnN0IHN0cmVhbSA9IChub2RlLmdldENvbXBvbmVudE91dGxldCA/PyBjb25maWcuZ2V0Q29tcG9uZW50T3V0bGV0KT8uKG5vZGUpO1xuXG4gICAgaWYgKCFzdHJlYW0pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyDwn5S0IEh14bu3IGzGsOG7o3QgdOG6o2kgQ8WoIGPhu6dhIMSRw7puZyBraOG7kWkgbsOgeSB0csaw4bubYyBraGkgbeG7nyBsxrDhu6N0IG3hu5tpLlxuICAgIC8vIEto4buRaSBi4buLIGfhu6EgcuG7k2kgZ+G6r24gbOG6oWkgKMSR4buVaSBi4buRIGPhu6VjLCBz4bqvcCBn4buNbikgdHJvbmcgbMO6YyBgaW1wb3J0KClgIGNoxrBhIHhvbmcgdGjDrCBsxrDhu6N0IGPFqSB24bqrblxuICAgIC8vIGNo4bqheSB0aeG6v3AgdsOgIGThu7FuZyBjb21wb25lbnQgdsOgbyBt4buZdCBgVmlld0NvbnRhaW5lclJlZmAgxJHDoyBjaOG6v3QuXG4gICAgdGhpcy5wZW5kaW5nTG9hZHMuZ2V0KG5vZGUuaWQpPy51bnN1YnNjcmliZSgpO1xuXG4gICAgY29uc3Qgc3ViID0gc3RyZWFtLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKChjb21wb25lbnRUeXBlKSA9PiB7XG4gICAgICB0aGlzLnBlbmRpbmdMb2Fkcy5kZWxldGUobm9kZS5pZCk7XG5cbiAgICAgIC8vIEto4buRaSBjw7MgdGjhu4MgxJHDoyBi4buLIHhvw6EgdHJvbmcgbMO6YyBjaOG7nSB04bqjaSDigJQgZOG7sW5nIHbDoG8gxJHDonkgbMOgIHLDsiBy4buJLlxuICAgICAgaWYgKCF0aGlzLnRyZWVTZXJ2aWNlLmZpbmRCeUlkKHRoaXMucm9vdE5vZGUoKSA/PyBub2RlLCBub2RlLmlkKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlZiA9IGhvc3QuY3JlYXRlQ29tcG9uZW50KGNvbXBvbmVudFR5cGUpO1xuXG4gICAgICB0aGlzLmFwcGx5SW5wdXRzKHJlZiwgbm9kZSwgZGVwdGgpO1xuICAgICAgdGhpcy5jb21wb25lbnRSZWZzLnNldChub2RlLmlkLCByZWYpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5wZW5kaW5nTG9hZHMuc2V0KG5vZGUuaWQsIHN1Yik7XG4gIH1cblxuICAvKipcbiAgICogR+G7oSBjb21wb25lbnQgY+G7p2EgbeG7mXQga2jhu5FpIHbDoCBodeG7tyBuw7MuICovXG4gIHByaXZhdGUgZGV0YWNoTm9kZShub2RlSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIC8vIEto4buRaSBi4buLIGfhu6Ega2hpIGNvbXBvbmVudCBj4bunYSBuw7MgY8OybiDEkWFuZyB04bqjaSDigJQgcGjhuqNpIGh14bu3IGzGsOG7o3QgdOG6o2ksIGtow7RuZyB0aMOsIG7DsyBk4buxbmcgdsOgbyBt4buZdFxuICAgIC8vIGBWaWV3Q29udGFpbmVyUmVmYCDEkcOjIGNo4bq/dC5cbiAgICB0aGlzLnBlbmRpbmdMb2Fkcy5nZXQobm9kZUlkKT8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnBlbmRpbmdMb2Fkcy5kZWxldGUobm9kZUlkKTtcblxuICAgIGNvbnN0IHJlZiA9IHRoaXMuY29tcG9uZW50UmVmcy5nZXQobm9kZUlkKTtcblxuICAgIGlmICghcmVmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmVmLmRlc3Ryb3koKTtcbiAgICB0aGlzLmNvbXBvbmVudFJlZnMuZGVsZXRlKG5vZGVJZCk7XG4gIH1cblxuICBwcml2YXRlIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBzdWIgb2YgdGhpcy5wZW5kaW5nTG9hZHMudmFsdWVzKCkpIHtcbiAgICAgIHN1Yi51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcmVmIG9mIHRoaXMuY29tcG9uZW50UmVmcy52YWx1ZXMoKSkge1xuICAgICAgcmVmLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLnBlbmRpbmdMb2Fkcy5jbGVhcigpO1xuICAgIHRoaXMuY29tcG9uZW50UmVmcy5jbGVhcigpO1xuICAgIHRoaXMuY29uZmlnID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIC8vIE5ow7NtIGjDoG0gY2hvIG7GoWkgZMO5bmcgQ0jhu6YgxJDhu5hORyBn4buNaSDigJQga2jDtG5nIHBo4bqjaSBjaOG7nSBuZ8aw4budaSBkw7luZyBi4bqlbSBuw7p0IHRyw6puIGto4buRaS5cbiAgLy8gU+G7rWEgY8OieSB0aMOsIGTDuW5nIHRo4bqzbmcgYFRyZWVTZXJ2aWNlYCBy4buTaSBn4buNaSBgcmVmcmVzaCgpYCDigJQgeGVtIGRlbW8gdHJvbmcgY29yZS11aS5cbiAgLy8g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqXG4gICAqIELDoW8gY2hvIHNlcnZpY2UgYmnhur90IGPDonkgduG7q2EgxJHhu5VpIHThu6sgYsOqbiBuZ2/DoGkgKHRow6ptL3hvw6Ega2jhu5FpLCBz4bqvcCBn4buNbiwgbuG6oXAgYuG7kSBj4bulYyBraMOhYykuXG4gICAqXG4gICAqIPCflLQgUEjhuqJJIHRoYXkgVEhBTSBDSEnhur5VIGPhu6dhIG5vZGUgZ+G7kWMsIGtow7RuZyBjaOG7iSBixqFtIGB2ZXJzaW9uYC5cbiAgICogYEBmb3Ig4oCmIHRyYWNrIGl0ZW0uaWRgIGdp4buvIG5ndXnDqm4gb2JqZWN0IGtoaSBpZCBraMO0bmcgxJHhu5VpLCBuw6puIGA8Z3JpZHN0ZXItaXRlbSBbaXRlbV09XCLigKZcIj5gIHbhuqtuXG4gICAqIG5o4bqtbiDEkcO6bmcgb2JqZWN0IGPFqSB2w6AgZ3JpZHN0ZXIga2jDtG5nIGjhu4EgYmnhur90IGB4L3kvY29scy9yb3dzL2xheWVySW5kZXhgIHbhu6thIGLhu4sgc+G7rWEuIELGoW0gbeG7l2lcbiAgICogYHZlcnNpb25gIHRow6wgY29tcHV0ZWQgY2jhuqF5IGzhuqFpIG5oxrBuZyB0cuG6oyB24buBIEPDmU5HIG3huqNuZyBjxakg4oCUIGzGsOG7m2kgxJHhu6luZyBpbSAoxJFvIDI4LzA4LzIwMjY6IGLhuqVtXG4gICAqIFwiU+G6r3AgZ+G7jW5cIiBjw6J5IMSRw6MgZOG7k24ga2jDrXQgbcOgIG3DoG4gaMOsbmgga2jDtG5nIG5ow7pjIG5ow61jaDsgYuG6rXQgY2jhu5NuZyBraOG7kWkgbcOgIGAkaXRlbS5sYXllckluZGV4YFxuICAgKiB24bqrbiB0cuG7kW5nKS5cbiAgICpcbiAgICogTmjDom4gYuG6o24gTsOUTkcgY+G6oyBub2RlIGfhu5FjIHbDoCBkYW5oIHPDoWNoIGNvbiBsw6AgxJHhu6c6IG3huqNuZyBt4bubaSDihpIgYEBmb3JgIGThu7FuZyBs4bqhaSBpdGVtLCBvYmplY3QgY29uXG4gICAqIG3hu5tpIOKGkiBncmlkc3RlciDEkeG7jWMgbOG6oWkgdG/DoG4gYuG7mSB0b+G6oSDEkeG7mS5cbiAgICovXG4gIHJlZnJlc2goZXZlbnQ/OiBUX2dyaWRMYXlvdXRfY2hhbmdlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCByb290ID0gZXZlbnQ/LnJvb3QgPz8gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgaWYgKCFyb290KSB7XG4gICAgICB0aGlzLnZlcnNpb24udXBkYXRlKCh2KSA9PiB2ICsgMSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIHRoaXMuY29uZmlnID0geyAuLi50aGlzLmNvbmZpZywgZGF0YTogcm9vdCB9O1xuICAgIH1cblxuICAgIHRoaXMucm9vdE5vZGUuc2V0KHRoaXMuc2hhbGxvd0Nsb25lVHJlZShyb290KSk7XG4gICAgdGhpcy52ZXJzaW9uLnVwZGF0ZSgodikgPT4gdiArIDEpO1xuICB9XG5cbiAgLyoqIE5ow6JuIGLhuqNuIG7DtG5nIHRoZW8gY+G6oyBjaGnhu4F1IHPDonU6IG3hu5dpIG5vZGUgdsOgIG3huqNuZyBgY2hpbGRyZW5gIHRow6BuaCB0aGFtIGNoaeG6v3UgbeG7m2kuICovXG4gIC8qKlxuICAgKiBOaMOibiBi4bqjbiBTw4JVIGPhuqMgY8OieSDigJQgZMO5bmcgY2hvIGBleHBvcnRMYXlvdXQoKWAuXG4gICAqXG4gICAqIPCflLQgQuG7jiBgZ2V0Q29tcG9uZW50T3V0bGV0YCBraOG7j2kgYuG6o24gc2FvOiBuw7MgbMOgIG3hu5l0IEjDgE0sIGtow7RuZyB0deG6p24gdOG7sSBob8OhIMSRxrDhu6NjIG7Dqm4gZ+G7rWkgeHXhu5FuZ1xuICAgKiBiYWNrZW5kIGzDoCBo4buPbmcgKGBKU09OLnN0cmluZ2lmeWAgbnXhu5F0IG3huqV0LCBgc3RydWN0dXJlZENsb25lYCBuw6ltIGzhu5dpKS4gTuG6oXAgbOG6oWkgdGjDrCBow6BtIHBow6JuXG4gICAqIGdp4bqjaSBjaHVuZyBj4bunYSBj4bqldSBow6xuaCBsbyDigJQgY29tcG9uZW50IHN1eSByYSB04burIGBkYXRhLnR5cGVgLCBraMO0bmcgY+G6p24gbMawdS5cbiAgICovXG4gIHByaXZhdGUgZGVlcENsb25lVHJlZShub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSk6IFRfZ3JpZExheW91dF9ub2RlIHtcbiAgICBjb25zdCBjb3B5OiBUX2dyaWRMYXlvdXRfbm9kZSA9IHsgLi4ubm9kZSB9O1xuXG4gICAgLy8gQ+G6r3QgaMOgbSBwaMOibiBnaeG6o2kg4oCUIHhlbSBjaMO6IHRow61jaCB0csOqbi5cbiAgICBkZWxldGUgY29weS5nZXRDb21wb25lbnRPdXRsZXQ7XG5cbiAgICBjb25zdCB7IGNoaWxkcmVuLCBkYXRhLCAuLi5yZXN0IH0gPSBjb3B5O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnJlc3QsXG4gICAgICAuLi4oZGF0YSA9PT0gdW5kZWZpbmVkID8ge30gOiB7IGRhdGE6IGNsb25lRGVlcChkYXRhKSB9KSxcbiAgICAgIC4uLihjaGlsZHJlbiA/IHsgY2hpbGRyZW46IGNoaWxkcmVuLm1hcCgoY2hpbGQpID0+IHRoaXMuZGVlcENsb25lVHJlZShjaGlsZCkpIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc2hhbGxvd0Nsb25lVHJlZShub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSk6IFRfZ3JpZExheW91dF9ub2RlIHtcbiAgICBpZiAoIW5vZGUuY2hpbGRyZW4/Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHsgLi4ubm9kZSB9O1xuICAgIH1cblxuICAgIHJldHVybiB7IC4uLm5vZGUsIGNoaWxkcmVuOiBub2RlLmNoaWxkcmVuLm1hcCgoY2hpbGQpID0+IHRoaXMuc2hhbGxvd0Nsb25lVHJlZShjaGlsZCkpIH07XG4gIH1cblxuICAvKipcbiAgICogR8OhbiBgbGF5ZXJJbmRleGAga2jDoWMgbmhhdSBjaG8gdOG7q25nIGto4buRaSBraGkgYuG6rXQgY2jhu5NuZyBraOG7kWkuXG4gICAqXG4gICAqIPCflLQgYGFsbG93TXVsdGlMYXllcjogdHJ1ZWAgTeG7mFQgTcOMTkgga2jDtG5nIGNobyBraOG7kWkgxJHDqCBuaGF1LiBNw6MgbGliIHNvIGBsYXllckluZGV4YCBj4bunYSBoYWkga2jhu5FpOlxuICAgKiBLSMOBQyBuaGF1IHRow6wgY2hvIMSRw6gsIEdJ4buQTkcgbmhhdSB24bqrbiBiw6FvIHZhIGNo4bqhbS4gS2jhu5FpIGtow7RuZyBraGFpIGBsYXllckluZGV4YCDEkeG7gXUgcsahaSB24buBXG4gICAqIGBkZWZhdWx0TGF5ZXJJbmRleGAg4oCUIHThu6ljIEPDmU5HIGzhu5twLCBuw6puIGvDqW8gdsOgbyBuaGF1IGzDoCBi4buLIGNo4bq3biB5IG5oxrAgbMaw4bubaSB0aMaw4budbmcgKG5nxrDhu51pIGTDuW5nXG4gICAqIGLDoW8gMjgvMDgvMjAyNjogXCJi4bqtdCBjaOG7k25nIGto4buRaSBuaMawbmcga2hpIGvDqW8gdGjDrCBjw6FjIGto4buRaSB24bqrbiBkaSBjaHV54buDbiB0aGVvXCIpLlxuICAgKlxuICAgKiBOxqFpIGTDuW5nIHThu7Ega2hhaSBgbGF5ZXJJbmRleGAgdGjDrCBnaeG7ryBuZ3V5w6puOyBhaSBraMO0bmcga2hhaSB0aMOsIHRoxrAgdmnhu4duIHjhur9wIG3hu5dpIGto4buRaSBt4buZdCBs4bubcFxuICAgKiB0aGVvIHRo4bupIHThu7EsIMSR4bunIMSR4buDIG3hu41pIGPhurdwIMSR4buBdSBraMOhYyBs4bubcC5cbiAgICovXG4gIHByaXZhdGUgYXNzaWduT3ZlcmxhcExheWVycyhyb290OiBUX2dyaWRMYXlvdXRfbm9kZSk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuY29uZmlnO1xuICAgIGNvbnN0IGNhbk92ZXJsYXAgPSBjb25maWc/Lm1vZGUgPT09IEVfZ3JpZExheW91dF9tb2RlX3N0cmluZy5mcmVlIHx8IChjb25maWc/LmFsbG93T3ZlcmxhcCA/PyBmYWxzZSk7XG5cbiAgICBpZiAoIWNhbk92ZXJsYXApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgbGF5ZXIgPSAwO1xuICAgIGNvbnN0IHdhbGsgPSAobm9kZTogVF9ncmlkTGF5b3V0X25vZGUpOiB2b2lkID0+IHtcbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbiA/PyBbXSkge1xuICAgICAgICBpZiAoY2hpbGQubGF5ZXJJbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbGF5ZXIgKz0gMTtcbiAgICAgICAgICBjaGlsZC5sYXllckluZGV4ID0gbGF5ZXI7XG4gICAgICAgIH1cblxuICAgICAgICB3YWxrKGNoaWxkKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgd2Fsayhyb290KTtcblxuICB9XG5cbiAgLyoqIMSQxrBhIG3hu5l0IGto4buRaSBsw6puIHRyw6puIHThuqV0IGPhuqM6IGzhu5twIGPhu6dhIG7DsyA9IGzhu5twIGzhu5tuIG5o4bqldCDEkWFuZyBjw7MgKyAxLiAqL1xuICBwcml2YXRlIHJhaXNlVG9Ub3BMYXllcihpdGVtOiBHcmlkc3Rlckl0ZW0pOiB2b2lkIHtcbiAgICBjb25zdCByb290ID0gdGhpcy5yb290Tm9kZSgpO1xuXG4gICAgaWYgKCFyb290KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHRvcExheWVyID0gMDtcbiAgICBjb25zdCB3YWxrID0gKG5vZGU6IFRfZ3JpZExheW91dF9ub2RlKTogdm9pZCA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4gPz8gW10pIHtcbiAgICAgICAgdG9wTGF5ZXIgPSBNYXRoLm1heCh0b3BMYXllciwgY2hpbGQubGF5ZXJJbmRleCA/PyAwKTtcbiAgICAgICAgd2FsayhjaGlsZCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHdhbGsocm9vdCk7XG5cbiAgICAvLyBgaXRlbWAgZ3JpZHN0ZXIgdHLhuqMgduG7gSBDSMONTkggbMOgIG9iamVjdCBub2RlIGPhu6dhIGPDonkgKHRydXnhu4FuIHRo4bqzbmcgcXVhIGBbaXRlbV1gKSwgbsOqbiBnw6FuIHbDoG9cbiAgICAvLyDEkcOieSBsw6AgY8OieSBjxaluZyDEkeG7lWkgdGhlby5cbiAgICBjb25zdCBub2RlID0gaXRlbSBhcyB1bmtub3duIGFzIFRfZ3JpZExheW91dF9ub2RlO1xuXG4gICAgaWYgKG5vZGUubGF5ZXJJbmRleCA9PT0gdG9wTGF5ZXIpIHtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIG5vZGUubGF5ZXJJbmRleCA9IHRvcExheWVyICsgMTtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICAvLyBT4busQSBDw4JZIOKAlCB0aMawIHZp4buHbiDEkcOjIGdp4buvIGPDonkgbsOqbiBi4bqhbiBLSMOUTkcgcGjhuqNpIHRydXnhu4FuIG7DsyB2w6BvLlxuICAvLyBN4buNaSBow6BtIGTGsOG7m2kgxJHDonkgdOG7sSB24bq9IGzhuqFpOyBraMO0bmcgY+G6p24gZ+G7jWkgYHJlZnJlc2goKWAuXG4gIC8vIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKlxuICAgKiBUaMOqbSBt4buZdCBraOG7kWkuXG4gICAqXG4gICAqIEBwYXJhbSBpdGVtIGto4buRaSBt4bubaSDigJQgS0jDlE5HIGPhuqduIGBpZGAgKHRoxrAgdmnhu4duIHNpbmgpIHbDoCBgeGAvYHlgICh04buxIMSR4bq3dCB4deG7kW5nIGjDoG5nIHRy4buRbmcpLlxuICAgKiBAcGFyYW0gcGFyZW50SWQgY29udGFpbmVyIG114buRbiB0aMOqbSB2w6BvOyBi4buPIHRy4buRbmcgdGjDrCB0aMOqbSB2w6BvIG3hurd0IHBo4bqzbmcgZ+G7kWMuXG4gICAqIEByZXR1cm5zIGto4buRaSB24burYSB04bqhbyAoa8OobSBgaWRgIHbhu6thIHNpbmgpLCBob+G6t2MgYHVuZGVmaW5lZGAga2hpIGtow7RuZyB0w6xtIHRo4bqleSBjb250YWluZXIuXG4gICAqL1xuICBhZGRCbG9jayhpdGVtOiBUX2dyaWRMYXlvdXRfbmV3Tm9kZSwgcGFyZW50SWQ/OiBzdHJpbmcpOiBUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcbiAgICBjb25zdCBhZGRlZCA9IHJvb3QgPyB0aGlzLnRyZWVTZXJ2aWNlLmFkZENoaWxkKHJvb3QsIHBhcmVudElkID8/IHJvb3QuaWQsIGl0ZW0pIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKGFkZGVkKSB7XG4gICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYWRkZWQ7XG4gIH1cblxuICAvKiogWG/DoSBt4buZdCBraOG7kWkuIFhvw6EgY29udGFpbmVyIGzDoCB4b8OhIGPhuqMgcnXhu5l0LiBUcuG6oyBgZmFsc2VgIGtoaSBraMO0bmcgeG/DoSDEkcaw4bujYyAodmQga2jhu5FpIGfhu5FjKS4gKi9cbiAgcmVtb3ZlQmxvY2soaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG4gICAgY29uc3QgZG9uZSA9IHJvb3QgPyB0aGlzLnRyZWVTZXJ2aWNlLnJlbW92ZUJ5SWQocm9vdCwgaWQpIDogZmFsc2U7XG5cbiAgICBpZiAoZG9uZSkge1xuICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRvbmU7XG4gIH1cblxuICAvKiogQmnhur9uIGto4buRaSDEkcahbiB0aMOgbmggQ09OVEFJTkVSIOKAlCBu4buZaSBkdW5nIGPFqSB0aMOgbmgga2jhu5FpIGNvbiDEkeG6p3UgdGnDqm4sIGtow7RuZyBt4bqldCBk4buvIGxp4buHdS4gKi9cbiAgdG9Db250YWluZXIoaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG4gICAgY29uc3QgZG9uZSA9IHJvb3QgPyB0aGlzLnRyZWVTZXJ2aWNlLnRvQ29udGFpbmVyKHJvb3QsIGlkLCB0aGlzLmNvbmZpZz8uY29scyA/PyAxMikgOiBmYWxzZTtcblxuICAgIGlmIChkb25lKSB7XG4gICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZG9uZTtcbiAgfVxuXG4gIC8qKiDEkMawYSBDT05UQUlORVIgduG7gSBraOG7kWkgxJHGoW4g4oCUIGto4buRaSBjb24gxJHGsOG7o2MgbsOibmcgbMOqbiBj4bqlcCB0csOqbiwga2jDtG5nIGLhu4sgeG/DoS4gKi9cbiAgdG9TaW5nbGUoaWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG4gICAgY29uc3QgZG9uZSA9IHJvb3QgPyB0aGlzLnRyZWVTZXJ2aWNlLnRvU2luZ2xlKHJvb3QsIGlkKSA6IGZhbHNlO1xuXG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH1cblxuICAgIHJldHVybiBkb25lO1xuICB9XG5cbiAgLyoqIEThu5NuIGto4buRaSBraMOtdCBsw6puIHRyw6puLCBs4bqlcCBo4bq/dCBjaOG7lyB0cuG7kW5nLiDEkOG7hyBxdXkgdsOgbyBjb250YWluZXIuICovXG4gIGNvbXBhY3QoKTogdm9pZCB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcblxuICAgIGlmICghcm9vdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMudHJlZVNlcnZpY2UuY29tcGFjdChyb290LCB0aGlzLmNvbmZpZz8uY29scyA/PyAxMik7XG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gIH1cblxuICAvKipcbiAgICogQuG7kSBj4bulYyBISeG7hk4gVOG6oEksIMSRw6MgY+G6r3QgbeG7jWkgdGhhbSBjaGnhur91IOKAlCBn4butaSB0aOG6s25nIHh14buRbmcgYmFja2VuZCDEkcaw4bujYy5cbiAgICpcbiAgICogRMO5bmcga2hpIGLhuqVtIG7DunQgTMawdS4gS2jDoWMgYFJvb3QoKWAg4bufIGNo4buXIMSRw6J5IGzDoCBi4bqjbiBTQU86IG7GoWkgZMO5bmcgY8OzIHPhu61hIGfDrCB0csOqbiBr4bq/dCBxdeG6oyBjxaluZ1xuICAgKiBraMO0bmcgxJHhu6VuZyB04bubaSBjw6J5IG3DoCB0aMawIHZp4buHbiDEkWFuZyB24bq9LlxuICAgKlxuICAgKiBAcmV0dXJucyBgdW5kZWZpbmVkYCBraGkgbeG6t3QgcGjhurNuZyBjaMawYSBgaW5pdCgpYC5cbiAgICovXG4gIGV4cG9ydExheW91dCgpOiBUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcblxuICAgIHJldHVybiByb290ID8gdGhpcy5kZWVwQ2xvbmVUcmVlKHJvb3QpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIFTDrG0gbeG7mXQga2jhu5FpIHRoZW8gaWQuICovXG4gIGZpbmRCbG9jayhpZDogc3RyaW5nKTogVF9ncmlkTGF5b3V0X25vZGUgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLnJvb3ROb2RlKCk7XG5cbiAgICByZXR1cm4gcm9vdCA/IHRoaXMudHJlZVNlcnZpY2UuZmluZEJ5SWQocm9vdCwgaWQpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIFTDrG0ga2jhu5FpIGNoYSB0cuG7sWMgdGnhur9wIGPhu6dhIG3hu5l0IGto4buRaS4gKi9cbiAgZmluZFBhcmVudEJsb2NrKGlkOiBzdHJpbmcpOiBUX2dyaWRMYXlvdXRfbm9kZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgcm9vdCA9IHRoaXMucm9vdE5vZGUoKTtcblxuICAgIHJldHVybiByb290ID8gdGhpcy50cmVlU2VydmljZS5maW5kUGFyZW50KHJvb3QsIGlkKSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBD4buVbmcgRFVZIE5I4bqkVCBjaG8gY2FudmFzIGPhu6dhIHRoxrAgdmnhu4duLiBOxqFpIGTDuW5nIEtIw5RORyBn4buNaSB04bubaSDEkcOieS5cbiAgICpcbiAgICogTeG7jWkgdGjhu6kgY2FudmFzIGPhuqduIMSR4buBdSBsw6AgYHByaXZhdGVgIMSR4buDIGtow7RuZyBs4buNdCByYSBBUEkgY8O0bmcga2hhaTsgZ29tIHbDoG8gbeG7mXQgZ2V0dGVyIHRoZW8gxJHDum5nXG4gICAqIGtodcO0biBgRnVuY3Rpb25zQ29udHJvbGAgY+G7p2EgYuG7mSBxdXkgxrDhu5tjLCB0aGF5IHbDrCDEkeG7gyBy4bqjaSByw6FjIGjDoG0gcHVibGljIG3DoCBuZ8aw4budaSBuZ2/DoGkgdMaw4bufbmdcbiAgICogbcOsbmggcGjhuqNpIGfhu41pIChuZ8aw4budaSBkw7luZyBjaOG7kXQgMjgvMDgvMjAyNikuXG4gICAqL1xuICBnZXQgRnVuY3Rpb25zQ29udHJvbCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbWF4Q29udGFpbmVyRGVwdGg6ICgpID0+IHRoaXMubWF4Q29udGFpbmVyRGVwdGgoKSxcbiAgICAgIGNvbnRhaW5lclBhZGRpbmc6ICgpID0+IHRoaXMuY29udGFpbmVyUGFkZGluZygpLFxuICAgICAgZ3JpZHN0ZXJPcHRpb25zOiAoZGVwdGg6IG51bWJlciwgY2I/OiAoKSA9PiB2b2lkKSA9PiB0aGlzLmJ1aWxkR3JpZHN0ZXJPcHRpb25zKGRlcHRoLCBjYiksXG4gICAgICBhdHRhY2hOb2RlOiAobm9kZTogVF9ncmlkTGF5b3V0X25vZGUsIGRlcHRoOiBudW1iZXIsIGhvc3Q6IFZpZXdDb250YWluZXJSZWYpID0+IHRoaXMuYXR0YWNoTm9kZShub2RlLCBkZXB0aCwgaG9zdCksXG4gICAgICBkZXRhY2hOb2RlOiAobm9kZUlkOiBzdHJpbmcpID0+IHRoaXMuZGV0YWNoTm9kZShub2RlSWQpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFwcGx5SW5wdXRzKHJlZjogQ29tcG9uZW50UmVmPHVua25vd24+LCBub2RlOiBUX2dyaWRMYXlvdXRfbm9kZSwgZGVwdGg6IG51bWJlcik6IHZvaWQge1xuICAgIHJlZi5zZXRJbnB1dCgnZGF0YScsIG5vZGUuZGF0YSk7XG4gICAgcmVmLnNldElucHV0KCdub2RlJywgbm9kZSk7XG4gICAgcmVmLnNldElucHV0KCdpc0VkaXRNb2RlJywgdGhpcy5lZGl0TW9kZSgpKTtcbiAgICByZWYuc2V0SW5wdXQoJ2RlcHRoJywgZGVwdGgpO1xuICB9XG59XG4iXX0=
@@ -360,6 +360,11 @@ class LibsUiGridLayoutService {
360
360
  init(config) {
361
361
  this.destroy();
362
362
  this.config = config;
363
+ // 🔴 Bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện: bản lưu cũ (sinh trước khi có trần,
364
+ // hoặc do thao tác lỗi) vẫn mang container lồng container. Trần `maxContainerDepth` chỉ ẩn NÚT
365
+ // trên canvas — nó không sửa dữ liệu, nên thiếu dòng này là vẽ ra đúng cây quá sâu đó.
366
+ // Nơi dùng KHÔNG tự gọi được: `LibsUiGridLayoutTreeService` cố ý không xuất.
367
+ this.treeService.flattenOverDepthContainers(config.data, this.maxContainerDepth());
363
368
  this.assignOverlapLayers(config.data);
364
369
  // 🔴 Nhân bản như `refresh()`: `init()` lại (đổi chế độ, bật/tắt chồng khối) trên CÙNG object cây
365
370
  // thì `@for` không dựng lại `gridster-item`, nên `layerIndex` vừa gán không tới `$item` và khối
@@ -1 +1 @@
1
- {"version":3,"file":"libs-ui-services-grid-layout.mjs","sources":["../../../../../libs-ui/services/grid-layout/src/defines/gridster-config.define.ts","../../../../../libs-ui/services/grid-layout/src/tree.service.ts","../../../../../libs-ui/services/grid-layout/src/grid-layout.service.ts","../../../../../libs-ui/services/grid-layout/src/canvas/grid-layout-canvas.component.ts","../../../../../libs-ui/services/grid-layout/src/canvas/grid-layout-canvas.component.html","../../../../../libs-ui/services/grid-layout/src/index.ts","../../../../../libs-ui/services/grid-layout/src/libs-ui-services-grid-layout.ts"],"sourcesContent":["import { CompactType, DisplayGrid, GridsterConfig, GridType } from 'gridster18';\nimport { T_gridLayout_node } from '../interfaces/grid-layout.interface';\n\n/**\n * Cấu hình gridster cho lưới CẤP TRANG.\n *\n * Mọi giá trị dưới đây đều đến từ một lỗi đã đo được trên sản phẩm thật, không phải chọn theo cảm\n * tính. Đổi bất kỳ dòng nào có dấu 🔴 sẽ làm sống lại đúng lỗi ghi trong comment.\n */\nexport const gridLayoutRootConfig = (): GridsterConfig => ({\n // 🔴 VerticalFixed — CẤM đổi sang Fit hay ScrollVertical.\n // `Fit` chia đều chiều cao khung cho số hàng đang dùng, nên card khai `rows: 2` phình từ 124px lên\n // 247px. `ScrollVertical` KHÔNG đọc `fixedRowHeight` (mã lib: chỉ `Fixed` và `VerticalFixed` đọc).\n gridType: GridType.VerticalFixed,\n\n // 🔴 None — CẤM quay lại CompactUp.\n // `CompactUp` hút mọi khối lên sát nhau NGAY sau mỗi thao tác, nên:\n // · kéo mép dưới cho khối cao thêm → chỗ khối dưới vừa nhường bị hút lấp lại tức thì, cú kéo bị\n // `checkGridCollision` báo va chạm rồi HOÀN NGUYÊN (khối đứng im dù kéo);\n // · kéo thả đổi vị trí → khối vừa nhường chỗ bị hút về ngay, khối đang kéo không có chỗ đặt và\n // treo lơ lửng giữa hai khối.\n // Muốn dồn khít thì gọi `sapGon()` của service.\n compactType: CompactType.None,\n displayGrid: DisplayGrid.OnDragAndResize,\n\n // 🔴 pushItems: true — CẤM để false.\n // `swap` của lib CHỈ hoán vị được HAI KHỐI CÙNG KÍCH THƯỚC (mã lib `checkSwap`: tính diffX/diffY\n // rồi hoán vị, lệch kích thước thì `checkCollision` báo va chạm và hoàn nguyên). Khối 3x2 gặp\n // container 7x5 nên không swap được, mà `pushItems: false` cũng không cho container nhường đường\n // → BẾ TẮC: khối đang kéo không đặt được ở đâu.\n pushItems: true,\n // chỉ đẩy XUỐNG: đẩy ngang làm xô lệch bố cục cột người dùng vừa đặt\n pushDirections: { north: false, east: false, south: true, west: false },\n pushResizeItems: true,\n swap: true,\n swapWhileDragging: true,\n\n draggable: {\n enabled: true,\n // 🔴 KHÔNG được bỏ. Không có nó thì gridster vào chế độ kéo ngay từ `mousedown`, nên chỉ bấm\n // CHỌN một khối là nó đã nhích theo dù chuột đứng yên. Lib tự huỷ kéo khi nhả chuột trước mốc\n // này nên cú bấm chọn vẫn ăn nguyên vẹn.\n delayStart: 160,\n // 🔴 `checkDragHandleClass` duyệt DOM từ chỗ bấm NGƯỢC LÊN CHA, và trên MỖI node nó kiểm\n // `dragHandleClass` TRƯỚC `ignoreContentClass`. Vì vậy một phần tử KHÔNG được mang cả hai class\n // cùng lúc — mang cả hai thì lib gặp tay cầm trước, trả `true`, class chặn không tới lượt.\n ignoreContentClass: 'libs-ui-grid-layout-block-parent-drag',\n ignoreContent: true,\n dragHandleClass: 'libs-ui-grid-layout-drag-handle',\n },\n\n resizable: {\n enabled: true,\n // đủ 8 hướng như cửa sổ thường; chỉ có góc dưới-phải thì quá khó trúng\n handles: { s: true, e: true, n: true, w: true, se: true, ne: true, sw: true, nw: true },\n },\n\n margin: 12,\n outerMargin: true,\n outerMarginBottom: 40,\n minCols: 12,\n maxCols: 12,\n minRows: 2,\n\n // 🔴 KHÔNG giới hạn chiều cao khối. Lib có BA trần mặc định phải vô hiệu hoá CÙNG LÚC, thiếu một\n // cái là vẫn bị chặn: `maxItemRows: 50` · `maxItemCols: 50` · `maxItemArea: 2500` (trần DIỆN TÍCH\n // cols × rows — khó thấy nhất: khối 12 cột chỉ cần 209 hàng là đụng trần dù hai trần kia còn dư).\n // `maxRows` là trần của CẢ LƯỚI, cũng phải nới theo.\n maxRows: 5000,\n maxItemRows: 5000,\n maxItemCols: 12,\n maxItemArea: 60000,\n\n // 🔴 Trần LỚP CHỒNG. Mặc định của lib là 2 — quá thấp: khi bật chồng khối, thư viện gán mỗi khối\n // một lớp riêng để chúng khác nhau, nên chỉ 3 khối là đã đụng trần và các khối sau lại rơi về\n // cùng lớp, tức chồng nhau bị chặn trở lại.\n maxLayerIndex: 5000,\n\n setGridSize: true,\n fixedRowHeight: 56,\n defaultItemCols: 3,\n defaultItemRows: 2,\n minItemRows: 1,\n mobileBreakpoint: -1,\n});\n\n/**\n * Cấu hình cho lưới LỒNG (ruột một container).\n *\n * Kế thừa lưới trang rồi ghi đè phần khác biệt. Ba điểm quan trọng nhất: `setGridSize` phải TẮT,\n * tay cầm phải mang TÊN RIÊNG, và tự-cuộn-khi-kéo phải TẮT.\n */\nexport const gridLayoutNestedConfig = (): GridsterConfig => ({\n ...gridLayoutRootConfig(),\n\n // 🔴 PHẢI tắt cho lưới lồng. `setGridSize` làm gridster tự ghi style width/height lên CHÍNH nó,\n // sinh vòng lặp đo-rồi-ghi với ResizeObserver của khung ngoài (khung đổi → onResize xoá style →\n // setGridSize ghi lại) → lưới con co dần về 64x64px trong khung 868px.\n setGridSize: false,\n\n // khe 2px: khối con là các dòng thông tin của CÙNG một card, khe rộng làm chúng trông như card rời\n margin: 2,\n // Lưới lồng KHÔNG tự chừa lề — lề là của VỎ container (`containerPadding`), không phải của lưới.\n // Đặt ở vỏ thì ruột co lại đúng bằng phần còn lại, tay cầm resize của khối con luôn nằm trong tầm\n // chuột (người dùng chốt 28/08/2026: \"lưới cha có padding chứ ko phải con\").\n outerMargin: false,\n outerMarginBottom: 0,\n\n // hàng 16px cho bước kéo mịn, và sàn 1 hàng = 16px nên khối co được nhỏ hơn nhiều\n fixedRowHeight: 16,\n minRows: 1,\n minItemRows: 1,\n defaultItemCols: 2,\n defaultItemRows: 2,\n\n // 🔴 Tay cầm RIÊNG — CẤM dùng chung tên với lưới trang.\n // `checkDragHandleClass` trả `true` ở node ĐẦU TIÊN có `dragHandleClass`. Dùng chung một tên thì\n // lưới CHA cũng nhận ra tay cầm của khối con và nhấc luôn container.\n draggable: {\n ...gridLayoutRootConfig().draggable,\n dragHandleClass: 'libs-ui-grid-layout-drag-handle-child',\n },\n\n // 🔴 KÉO MÉP thì khối dưới ĐỨNG YÊN, chỉ khoảng trống giữa hai khối co giãn. Bật (kế thừa từ lưới\n // trang) thì mỗi cú kéo đẩy dồn cả cột xuống — người dùng chỉ muốn một khối to hơn một chút mà cả\n // card dài ra. `pushItems` vẫn giữ: nó lo việc KÉO THẢ đổi chỗ, khác việc đổi kích thước.\n pushResizeItems: false,\n\n // 🔴 Tắt tự cuộn khi kéo tới sát mép. Lib thấy chuột gần biên là cuộn lưới theo\n // (`scrollSensitivity`), nhưng lưới con nằm trong card có `overflow: hidden` — cuộn ở đây đẩy khối\n // con ra NGOÀI khung container rồi kẹt luôn ở đó.\n disableScrollHorizontal: true,\n disableScrollVertical: true,\n});\n\n/**\n * Cây rỗng dùng khi chưa có dữ liệu — mặt phẳng vẽ ra một lưới trống thay vì vỡ.\n * Xảy ra trong nhịp giữa lúc component dựng và lúc `init()` chạy.\n */\nexport const emptyRootNode = (): T_gridLayout_node => ({ id: 'root', x: 0, y: 0, cols: 12, rows: 0, children: [] });\n","import { Injectable } from '@angular/core';\nimport { uuid } from '@libs-ui/utils';\nimport { T_gridLayout_newNode, T_gridLayout_node } from './interfaces/grid-layout.interface';\n\n/**\n * Thao tác trên cây khối: tìm, thêm, xoá, dồn khít, chặn lồng cấp quá sâu.\n *\n * 🔴 NỘI BỘ thư viện — không xuất ra ngoài. Nơi dùng đi qua `LibsUiGridLayoutService`, ở đó mỗi\n * thao tác sửa bố cục vừa vẽ lại vừa bắn `outChange` đúng MỘT lần. Các hàm ở đây cố tình KHÔNG tự\n * vẽ lại: để chúng tự gọi thì mỗi thao tác vẽ hai lượt và bắn hai sự kiện (người dùng chốt\n * 28/08/2026: \"đặt đúng các điểm mà làm cho layout có thể thay đổi thôi\").\n */\n@Injectable()\nexport class LibsUiGridLayoutTreeService {\n findById(node: T_gridLayout_node, id: string): T_gridLayout_node | undefined {\n if (node.id === id) {\n return node;\n }\n\n for (const child of node.children ?? []) {\n const found = this.findById(child, id);\n\n if (found) {\n return found;\n }\n }\n\n return undefined;\n }\n\n findParent(node: T_gridLayout_node, id: string): T_gridLayout_node | undefined {\n for (const child of node.children ?? []) {\n if (child.id === id) {\n return node;\n }\n\n const found = this.findParent(child, id);\n\n if (found) {\n return found;\n }\n }\n\n return undefined;\n }\n\n /**\n * Thêm khối vào cuối một container. Thư viện tự sinh `id` và tự đặt `x` · `y` xuống hàng trống.\n *\n * @returns khối vừa tạo (kèm `id` vừa sinh), hoặc `undefined` khi không tìm thấy container.\n */\n addChild(root: T_gridLayout_node, parentId: string, item: T_gridLayout_newNode): T_gridLayout_node | undefined {\n const parent = this.findById(root, parentId);\n\n if (!parent) {\n return undefined;\n }\n\n parent.children = parent.children ?? [];\n // 🔴 Thư viện tự sinh `id`. Đây là mã máy dùng để tra cứu, không phải thứ người dùng nghĩ ra —\n // bắt họ tự đặt là mời họ tạo trùng, mà trùng id thì `findById` trả nhầm khối và cả cây hỏng\n // im lặng (người dùng chốt 28/08/2026).\n const node: T_gridLayout_node = { ...item, id: item.id ?? uuid(), x: 0, y: this.nextFreeRow(parent.children) };\n\n parent.children.push(node);\n\n // Trả về khối vừa tạo để nơi dùng biết `id` thư viện vừa sinh.\n return node;\n }\n\n /** Xoá một khối khỏi cây. Không cho xoá gốc. */\n removeById(root: T_gridLayout_node, id: string): boolean {\n if (root.id === id) {\n return false;\n }\n\n const parent = this.findParent(root, id);\n\n if (!parent?.children) {\n return false;\n }\n\n parent.children = parent.children.filter((item) => item.id !== id);\n\n return true;\n }\n\n /**\n * Chuyển một khối đơn thành CONTAINER: nội dung cũ trở thành khối con đầu tiên.\n *\n * Không mất dữ liệu — `data` của khối được mang theo xuống khối con.\n *\n * @returns `false` khi không tìm thấy khối, hoặc khối đã là container rồi.\n */\n toContainer(root: T_gridLayout_node, id: string, colCount: number): boolean {\n const node = this.findById(root, id);\n\n if (!node || (node.children?.length ?? 0) > 0) {\n return false;\n }\n\n node.children = [{ ...node, id: uuid(), x: 0, y: 0, cols: colCount, rows: 4, children: [] }];\n\n return true;\n }\n\n /**\n * Chuyển một CONTAINER về khối đơn: các khối con được NÂNG lên cấp trên, không bị xoá.\n *\n * @returns `false` khi không tìm thấy khối, hoặc khối vốn không phải container.\n */\n toSingle(root: T_gridLayout_node, id: string): boolean {\n const node = this.findById(root, id);\n\n if (!node || (node.children?.length ?? 0) === 0) {\n return false;\n }\n\n const parent = this.findParent(root, id);\n\n for (const child of node.children ?? []) {\n parent?.children?.push({ ...child, cols: node.cols, rows: 2 });\n }\n\n node.children = [];\n\n return true;\n }\n\n /**\n * Làm phẳng mọi container lồng vượt trần.\n *\n * 🔴 Cần thiết vì bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện. Một bản lưu cũ — sinh\n * trước khi có trần, hoặc do thao tác lỗi — vẫn nạp thẳng vào và hiện container lồng container.\n * Container vượt trần bị hạ thành khối thường, con của nó nâng lên cấp trên: KHÔNG mất dữ liệu.\n *\n * @returns số container đã làm phẳng\n */\n flattenOverDepthContainers(node: T_gridLayout_node, maxDepth: number): number {\n return this.walkFlatten(node, 0, maxDepth);\n }\n\n /**\n * Dồn khối khít lên trên theo thứ tự đọc, lấp hết chỗ trống.\n *\n * 🔴 KHÔNG sửa `node.rows` của container. Chiều cao container tính theo đơn vị hàng của lưới CHA,\n * còn `currentRow` đếm theo đơn vị hàng của lưới CON — trộn hai thang đo là container phình lên\n * gấp mấy lần.\n */\n compact(node: T_gridLayout_node, colCount: number): void {\n this.walkCompact(node, colCount);\n }\n\n private walkCompact(node: T_gridLayout_node, colCount: number): void {\n const children = node.children;\n\n if (!children?.length) {\n return;\n }\n\n const inReadingOrder = [...children].sort((a, b) => a.y - b.y || a.x - b.x);\n let currentRow = 0;\n let usedCols = 0;\n let tallestInRow = 0;\n\n for (const item of inReadingOrder) {\n const width = Math.min(item.cols, colCount);\n\n if (usedCols > 0 && usedCols + width > colCount) {\n currentRow += tallestInRow;\n usedCols = 0;\n tallestInRow = 0;\n }\n\n item.x = usedCols;\n item.y = currentRow;\n item.cols = width;\n usedCols += width;\n tallestInRow = Math.max(tallestInRow, item.rows);\n\n if ((item.children?.length ?? 0) > 0) {\n this.walkCompact(item, colCount);\n }\n }\n }\n\n private walkFlatten(node: T_gridLayout_node, containerDepth: number, maxDepth: number): number {\n const children = node.children;\n\n if (!children?.length) {\n return 0;\n }\n\n let fixedCount = 0;\n const result: Array<T_gridLayout_node> = [];\n\n for (const child of children) {\n const isContainer = (child.children?.length ?? 0) > 0;\n\n if (isContainer && containerDepth >= maxDepth) {\n fixedCount += 1;\n\n for (const item of child.children ?? []) {\n fixedCount += this.walkFlatten(item, containerDepth, maxDepth);\n result.push(item);\n }\n\n continue;\n }\n\n fixedCount += this.walkFlatten(child, isContainer ? containerDepth + 1 : containerDepth, maxDepth);\n result.push(child);\n }\n\n node.children = result;\n\n return fixedCount;\n }\n\n private nextFreeRow(children: Array<T_gridLayout_node>): number {\n return children.reduce((max, child) => Math.max(max, child.y + child.rows), 0);\n }\n}\n","import { ComponentRef, DestroyRef, Injectable, ViewContainerRef, inject, signal } from '@angular/core';\nimport { GridsterConfig, GridsterItem } from 'gridster18';\nimport { cloneDeep } from '@libs-ui/utils';\nimport { Subscription, take } from 'rxjs';\nimport { gridLayoutNestedConfig, gridLayoutRootConfig } from './defines/gridster-config.define';\nimport { LibsUiGridLayoutTreeService } from './tree.service';\nimport {\n E_gridLayout_mode_string,\n T_gridLayout_changeEvent,\n T_gridLayout_newNode,\n T_gridLayout_config,\n T_gridLayout_node,\n} from './interfaces/grid-layout.interface';\n\n/**\n * Dựng một mặt phẳng kéo thả và tự gắn component của nơi dùng lên từng khối.\n *\n * Nơi dùng chỉ cần đưa vào: loại component muốn dựng\n * (`nodeComponentType`) và cây dữ liệu (`data`). Toàn bộ việc vẽ lưới, kéo thả, đổi kích thước,\n * lồng container và dọn dẹp do thư viện lo.\n *\n * 🔴 Đây là service theo TỪNG mặt phẳng, KHÔNG `providedIn: 'root'`. Khai trong `providers` của\n * component dùng nó; hai mặt phẳng trên cùng một màn phải là hai thực thể riêng, dùng chung thì\n * `componentRefs` của mặt phẳng này bị mặt phẳng kia dọn mất.\n */\n@Injectable()\nexport class LibsUiGridLayoutService {\n // 🔴 TỰ TẠO, không `inject`. Nơi dùng chỉ phải viết `providers: [LibsUiGridLayoutService]` —\n // không phải biết bên trong thư viện còn service nào khác (người dùng chốt 28/08/2026).\n // `TreeService` không giữ trạng thái dùng chung nên mỗi mặt phẳng một bản là đúng.\n private readonly treeService = new LibsUiGridLayoutTreeService();\n /** Lượt tải component đang chờ, theo id khối — để huỷ khi khối bị gỡ giữa chừng. */\n private readonly pendingLoads = new Map<string, Subscription>();\n\n constructor() {\n // 🔴 Service khai trong `providers` của component nên Angular huỷ nó cùng component — thư viện\n // tự dọn ở đây, nơi dùng KHÔNG phải gọi `destroy()` trong `ngOnDestroy` (người dùng chốt\n // 28/08/2026). Bắt nhớ một bước dọn dẹp là kiểu API dễ quên, và quên thì rò rỉ bộ nhớ im lặng.\n inject(DestroyRef).onDestroy(() => this.destroy());\n }\n\n private config?: T_gridLayout_config;\n private readonly componentRefs = new Map<string, ComponentRef<unknown>>();\n\n private readonly rootNode = signal<T_gridLayout_node | undefined>(undefined);\n private readonly editMode = signal<boolean>(false);\n /** tăng mỗi lần cây đổi — component con đọc để biết phải tính lại */\n private readonly version = signal<number>(0);\n\n /**\n * Signal chỉ đọc để nơi dùng theo dõi.\n *\n * 🔴 Là THUỘC TÍNH, không phải getter. Getter trả signal thì chỗ đọc phải viết `Version()()` —\n * quên cặp ngoặc thứ hai là computed KHÔNG phụ thuộc vào nó, cây đổi mà lưới đứng im, và\n * TypeScript không hề báo lỗi (đo 28/08/2026: thêm khối không hiện, sắp gọn không nhúc nhích).\n */\n readonly Root = this.rootNode.asReadonly();\n readonly IsEditMode = this.editMode.asReadonly();\n /** tăng mỗi lần cây hoặc cấu hình đổi */\n readonly Version = this.version.asReadonly();\n\n /**\n * trần số cấp container lồng nhau — canvas đọc để biết có cho chuyển thành container không */\n private maxContainerDepth(): number {\n return this.config?.maxContainerDepth ?? 1;\n }\n\n /**\n * lề trong của container, px — canvas đọc để đặt padding lên vỏ container */\n private containerPadding(): number {\n return this.config?.containerPadding ?? 12;\n }\n\n /** Khởi tạo mặt phẳng. Gọi lại sẽ dọn sạch component cũ rồi dựng lại từ đầu. */\n init(config: T_gridLayout_config): void {\n this.destroy();\n this.config = config;\n this.assignOverlapLayers(config.data);\n // 🔴 Nhân bản như `refresh()`: `init()` lại (đổi chế độ, bật/tắt chồng khối) trên CÙNG object cây\n // thì `@for` không dựng lại `gridster-item`, nên `layerIndex` vừa gán không tới `$item` và khối\n // vẫn không đè nhau được (đo 28/08/2026: `item.layerIndex` = 1|2|3|4|7 mà `$item.layerIndex`\n // toàn `undefined`).\n this.rootNode.set(this.shallowCloneTree(config.data));\n this.editMode.set(config.isEditMode ?? false);\n this.version.update((v) => v + 1);\n }\n\n setEditMode(value: boolean): void {\n this.editMode.set(value);\n // 🔴 PHẢI bơm `version`: `gridsterOptions()` đọc `editMode` để bật/tắt kéo–thả, mà computed\n // `gridOptions` bên canvas chỉ chạy lại khi `Version` đổi. Thiếu dòng này thì đổi chế độ xong\n // gridster vẫn giữ options cũ — chuyển sang XEM mà khối vẫn kéo được.\n this.version.update((v) => v + 1);\n }\n\n /**\n * Bật/tắt cho khối chồng lên nhau — KHÔNG dựng lại mặt phẳng.\n *\n * Trước đây nơi dùng phải gọi `init()` lại để đổi cờ này, mà `init()` huỷ sạch rồi dựng lại mọi\n * component nội dung — lãng phí, và người dùng thấy màn chớp (người dùng chốt 28/08/2026).\n */\n setAllowOverlap(value: boolean): void {\n if (!this.config) {\n return;\n }\n\n this.config = { ...this.config, allowOverlap: value };\n\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n // 🔴 Gán lớp vào CÂY ĐANG VẼ (`rootNode`), KHÔNG phải `config.data`.\n // `init()` đã clone `config.data` sang `rootNode` nên hai object KHÁC nhau; gán vào `config.data`\n // thì `refresh()` clone lại từ `rootNode` — lớp vừa gán không tới `gridster-item` nào, `z-index`\n // của mọi khối đứng ở `1` và khối nào vẽ sau thì nằm trên: chồng khối \"lúc được lúc không\"\n // (đo 04/09/2026: `item.layerIndex` undefined, `getLayerIndex()` = 0 cho cả 8 khối).\n this.assignOverlapLayers(root);\n // Thay tham chiếu cây để `layerIndex` vừa gán tới được `$item` của gridster; component nội dung\n // KHÔNG bị dựng lại vì `attachNode` nhận ra id cũ và chỉ `setInput`.\n this.refresh();\n }\n\n /**\n *\n * Cấu hình gridster cho một cấp lưới.\n *\n * @param depth 0 = lưới cấp trang, ≥ 1 = lưới lồng trong container\n */\n private buildGridsterOptions(depth: number, itemChangeCallback?: () => void): GridsterConfig {\n const base = depth === 0 ? gridLayoutRootConfig() : gridLayoutNestedConfig();\n const config = this.config;\n\n if (!config) {\n return base;\n }\n\n const isFreeMode = config.mode === E_gridLayout_mode_string.free;\n const canEdit = this.editMode();\n const canOverlap = isFreeMode || (config.allowOverlap ?? false);\n\n return {\n ...base,\n ...(config.cols ? { minCols: config.cols, maxCols: config.cols, maxItemCols: config.cols } : {}),\n ...(config.rowHeight && depth === 0 ? { fixedRowHeight: config.rowHeight } : {}),\n // Khe và chiều cao hàng khác nhau theo cấp: lưới trang thoáng, lưới lồng khít.\n ...(depth === 0 && config.margin !== undefined ? { margin: config.margin } : {}),\n ...(depth > 0 && config.nestedMargin !== undefined ? { margin: config.nestedMargin } : {}),\n ...(depth > 0 && config.nestedRowHeight !== undefined ? { fixedRowHeight: config.nestedRowHeight } : {}),\n ...(depth === 0 && config.outerMargin !== undefined ? { outerMargin: config.outerMargin } : {}),\n ...(depth === 0 && config.outerMarginBottom !== undefined ? { outerMarginBottom: config.outerMarginBottom } : {}),\n ...(config.minItemRows !== undefined ? { minItemRows: config.minItemRows } : {}),\n ...(config.defaultItemCols !== undefined ? { defaultItemCols: config.defaultItemCols } : {}),\n ...(config.defaultItemRows !== undefined ? { defaultItemRows: config.defaultItemRows } : {}),\n\n // 🔴 Chế độ XEM phải TẮT hẳn kéo và đổi kích thước.\n // `base` luôn để `enabled: true`; không ghi đè theo `editMode` thì người xem vẫn kéo được khối\n // và đổi bố cục của người khác (người dùng báo 28/08/2026: \"đang xem mà vẫn kéo thả thay đổi\n // vị trí và thêm khối được\").\n draggable: { ...base.draggable, enabled: canEdit },\n resizable: { ...base.resizable, enabled: canEdit },\n\n // Chế độ tự do LUÔN cho chồng; chế độ lưới thì theo cờ của nơi dùng.\n allowMultiLayer: canOverlap,\n // 🔴 Bật `allowMultiLayer` MỘT MÌNH không đủ. Mã lib so `layerIndex` của hai khối: KHÁC nhau\n // thì cho đè, GIỐNG nhau vẫn báo va chạm. Khối không khai `layerIndex` đều rơi về\n // `defaultLayerIndex` — tức cùng lớp, và vẫn bị đẩy nhau như lưới thường (người dùng báo\n // 28/08/2026: \"bật chồng khối nhưng khi kéo thì các khối vẫn di chuyển theo\").\n // Cho chồng thì phải TẮT đẩy khối, nếu không khối bị dạt đi trước khi kịp đè lên nhau.\n ...(canOverlap ? { pushItems: false, pushResizeItems: false, swap: false, swapWhileDragging: false } : {}),\n\n itemChangeCallback: (item: GridsterItem) => {\n // 🔴 Khối vừa thao tác phải lên LỚP TRÊN CÙNG.\n // `layerIndex` gán một lần theo thứ tự cây lúc khởi tạo, nên khối kéo lên chỉ nổi TRONG LÚC\n // kéo (nhờ `z-index: 30` của lớp `gridster-item-moving`); thả tay ra là về lớp cũ và bị khối\n // đứng sau trong cây đè ngược lên (người dùng báo 28/08/2026, đo được: kéo z=30, thả về\n // z=10 trong khi hai khối kế bên đang z=11 và z=12).\n if (canOverlap) {\n this.raiseToTopLayer(item);\n }\n\n this.version.update((v) => v + 1);\n itemChangeCallback?.();\n },\n };\n }\n\n /**\n *\n * Gắn component của nơi dùng lên một khối.\n *\n * @param host chỗ gắn RIÊNG của ô đó — mỗi khối một `ViewContainerRef`, dùng chung một cái thì\n * mọi component bị dồn hết vào một ô.\n */\n private attachNode(node: T_gridLayout_node, depth: number, host: ViewContainerRef): void {\n const config = this.config;\n\n if (!config) {\n return;\n }\n\n const existing = this.componentRefs.get(node.id);\n\n if (existing) {\n this.applyInputs(existing, node, depth);\n\n return;\n }\n\n // Khối tự khai thì hỏi nó; không thì hỏi hàm phân giải chung. Cả hai đều nhận `node` để đọc\n // được `data.type` mà quyết định trả component nào.\n const stream = (node.getComponentOutlet ?? config.getComponentOutlet)?.(node);\n\n if (!stream) {\n return;\n }\n\n // 🔴 Huỷ lượt tải CŨ của đúng khối này trước khi mở lượt mới.\n // Khối bị gỡ rồi gắn lại (đổi bố cục, sắp gọn) trong lúc `import()` chưa xong thì lượt cũ vẫn\n // chạy tiếp và dựng component vào một `ViewContainerRef` đã chết.\n this.pendingLoads.get(node.id)?.unsubscribe();\n\n const sub = stream.pipe(take(1)).subscribe((componentType) => {\n this.pendingLoads.delete(node.id);\n\n // Khối có thể đã bị xoá trong lúc chờ tải — dựng vào đây là rò rỉ.\n if (!this.treeService.findById(this.rootNode() ?? node, node.id)) {\n return;\n }\n\n const ref = host.createComponent(componentType);\n\n this.applyInputs(ref, node, depth);\n this.componentRefs.set(node.id, ref);\n });\n\n this.pendingLoads.set(node.id, sub);\n }\n\n /**\n * Gỡ component của một khối và huỷ nó. */\n private detachNode(nodeId: string): void {\n // Khối bị gỡ khi component của nó còn đang tải — phải huỷ lượt tải, không thì nó dựng vào một\n // `ViewContainerRef` đã chết.\n this.pendingLoads.get(nodeId)?.unsubscribe();\n this.pendingLoads.delete(nodeId);\n\n const ref = this.componentRefs.get(nodeId);\n\n if (!ref) {\n return;\n }\n\n ref.destroy();\n this.componentRefs.delete(nodeId);\n }\n\n private destroy(): void {\n for (const sub of this.pendingLoads.values()) {\n sub.unsubscribe();\n }\n\n for (const ref of this.componentRefs.values()) {\n ref.destroy();\n }\n\n this.pendingLoads.clear();\n this.componentRefs.clear();\n this.config = undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────────────────\n // Nhóm hàm cho nơi dùng CHỦ ĐỘNG gọi — không phải chờ người dùng bấm nút trên khối.\n // Sửa cây thì dùng thẳng `TreeService` rồi gọi `refresh()` — xem demo trong core-ui.\n // ─────────────────────────────────────────────────────────────────────────────────────────\n\n /**\n * Báo cho service biết cây vừa đổi từ bên ngoài (thêm/xoá khối, sắp gọn, nạp bố cục khác).\n *\n * 🔴 PHẢI thay THAM CHIẾU của node gốc, không chỉ bơm `version`.\n * `@for … track item.id` giữ nguyên object khi id không đổi, nên `<gridster-item [item]=\"…\">` vẫn\n * nhận đúng object cũ và gridster không hề biết `x/y/cols/rows/layerIndex` vừa bị sửa. Bơm mỗi\n * `version` thì computed chạy lại nhưng trả về CÙNG mảng cũ — lưới đứng im (đo 28/08/2026: bấm\n * \"Sắp gọn\" cây đã dồn khít mà màn hình không nhúc nhích; bật chồng khối mà `$item.layerIndex`\n * vẫn trống).\n *\n * Nhân bản NÔNG cả node gốc và danh sách con là đủ: mảng mới → `@for` dựng lại item, object con\n * mới → gridster đọc lại toàn bộ toạ độ.\n */\n refresh(event?: T_gridLayout_changeEvent): void {\n const root = event?.root ?? this.rootNode();\n\n if (!root) {\n this.version.update((v) => v + 1);\n\n return;\n }\n\n if (this.config) {\n this.config = { ...this.config, data: root };\n }\n\n this.rootNode.set(this.shallowCloneTree(root));\n this.version.update((v) => v + 1);\n }\n\n /** Nhân bản nông theo cả chiều sâu: mỗi node và mảng `children` thành tham chiếu mới. */\n /**\n * Nhân bản SÂU cả cây — dùng cho `exportLayout()`.\n *\n * 🔴 BỎ `getComponentOutlet` khỏi bản sao: nó là một HÀM, không tuần tự hoá được nên gửi xuống\n * backend là hỏng (`JSON.stringify` nuốt mất, `structuredClone` ném lỗi). Nạp lại thì hàm phân\n * giải chung của cấu hình lo — component suy ra từ `data.type`, không cần lưu.\n */\n private deepCloneTree(node: T_gridLayout_node): T_gridLayout_node {\n const copy: T_gridLayout_node = { ...node };\n\n // Cắt hàm phân giải — xem chú thích trên.\n delete copy.getComponentOutlet;\n\n const { children, data, ...rest } = copy;\n\n return {\n ...rest,\n ...(data === undefined ? {} : { data: cloneDeep(data) }),\n ...(children ? { children: children.map((child) => this.deepCloneTree(child)) } : {}),\n };\n }\n\n private shallowCloneTree(node: T_gridLayout_node): T_gridLayout_node {\n if (!node.children?.length) {\n return { ...node };\n }\n\n return { ...node, children: node.children.map((child) => this.shallowCloneTree(child)) };\n }\n\n /**\n * Gán `layerIndex` khác nhau cho từng khối khi bật chồng khối.\n *\n * 🔴 `allowMultiLayer: true` MỘT MÌNH không cho khối đè nhau. Mã lib so `layerIndex` của hai khối:\n * KHÁC nhau thì cho đè, GIỐNG nhau vẫn báo va chạm. Khối không khai `layerIndex` đều rơi về\n * `defaultLayerIndex` — tức CÙNG lớp, nên kéo vào nhau là bị chặn y như lưới thường (người dùng\n * báo 28/08/2026: \"bật chồng khối nhưng khi kéo thì các khối vẫn di chuyển theo\").\n *\n * Nơi dùng tự khai `layerIndex` thì giữ nguyên; ai không khai thì thư viện xếp mỗi khối một lớp\n * theo thứ tự, đủ để mọi cặp đều khác lớp.\n */\n private assignOverlapLayers(root: T_gridLayout_node): void {\n const config = this.config;\n const canOverlap = config?.mode === E_gridLayout_mode_string.free || (config?.allowOverlap ?? false);\n\n if (!canOverlap) {\n return;\n }\n\n let layer = 0;\n const walk = (node: T_gridLayout_node): void => {\n for (const child of node.children ?? []) {\n if (child.layerIndex === undefined) {\n layer += 1;\n child.layerIndex = layer;\n }\n\n walk(child);\n }\n };\n\n walk(root);\n\n }\n\n /** Đưa một khối lên trên tất cả: lớp của nó = lớp lớn nhất đang có + 1. */\n private raiseToTopLayer(item: GridsterItem): void {\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n let topLayer = 0;\n const walk = (node: T_gridLayout_node): void => {\n for (const child of node.children ?? []) {\n topLayer = Math.max(topLayer, child.layerIndex ?? 0);\n walk(child);\n }\n };\n\n walk(root);\n\n // `item` gridster trả về CHÍNH là object node của cây (truyền thẳng qua `[item]`), nên gán vào\n // đây là cây cũng đổi theo.\n const node = item as unknown as T_gridLayout_node;\n\n if (node.layerIndex === topLayer) {\n\n return;\n }\n\n node.layerIndex = topLayer + 1;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────────────────\n // SỬA CÂY — thư viện đã giữ cây nên bạn KHÔNG phải truyền nó vào.\n // Mọi hàm dưới đây tự vẽ lại; không cần gọi `refresh()`.\n // ─────────────────────────────────────────────────────────────────────────────────────────\n\n /**\n * Thêm một khối.\n *\n * @param item khối mới — KHÔNG cần `id` (thư viện sinh) và `x`/`y` (tự đặt xuống hàng trống).\n * @param parentId container muốn thêm vào; bỏ trống thì thêm vào mặt phẳng gốc.\n * @returns khối vừa tạo (kèm `id` vừa sinh), hoặc `undefined` khi không tìm thấy container.\n */\n addBlock(item: T_gridLayout_newNode, parentId?: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n const added = root ? this.treeService.addChild(root, parentId ?? root.id, item) : undefined;\n\n if (added) {\n this.refresh();\n }\n\n return added;\n }\n\n /** Xoá một khối. Xoá container là xoá cả ruột. Trả `false` khi không xoá được (vd khối gốc). */\n removeBlock(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.removeById(root, id) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Biến khối đơn thành CONTAINER — nội dung cũ thành khối con đầu tiên, không mất dữ liệu. */\n toContainer(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.toContainer(root, id, this.config?.cols ?? 12) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Đưa CONTAINER về khối đơn — khối con được nâng lên cấp trên, không bị xoá. */\n toSingle(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.toSingle(root, id) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Dồn khối khít lên trên, lấp hết chỗ trống. Đệ quy vào container. */\n compact(): void {\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n this.treeService.compact(root, this.config?.cols ?? 12);\n this.refresh();\n }\n\n /**\n * Bố cục HIỆN TẠI, đã cắt mọi tham chiếu — gửi thẳng xuống backend được.\n *\n * Dùng khi bấm nút Lưu. Khác `Root()` ở chỗ đây là bản SAO: nơi dùng có sửa gì trên kết quả cũng\n * không đụng tới cây mà thư viện đang vẽ.\n *\n * @returns `undefined` khi mặt phẳng chưa `init()`.\n */\n exportLayout(): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.deepCloneTree(root) : undefined;\n }\n\n /** Tìm một khối theo id. */\n findBlock(id: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.treeService.findById(root, id) : undefined;\n }\n\n /** Tìm khối cha trực tiếp của một khối. */\n findParentBlock(id: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.treeService.findParent(root, id) : undefined;\n }\n\n /**\n * Cổng DUY NHẤT cho canvas của thư viện. Nơi dùng KHÔNG gọi tới đây.\n *\n * Mọi thứ canvas cần đều là `private` để không lọt ra API công khai; gom vào một getter theo đúng\n * khuôn `FunctionsControl` của bộ quy ước, thay vì để rải rác hàm public mà người ngoài tưởng\n * mình phải gọi (người dùng chốt 28/08/2026).\n */\n get FunctionsControl() {\n return {\n maxContainerDepth: () => this.maxContainerDepth(),\n containerPadding: () => this.containerPadding(),\n gridsterOptions: (depth: number, cb?: () => void) => this.buildGridsterOptions(depth, cb),\n attachNode: (node: T_gridLayout_node, depth: number, host: ViewContainerRef) => this.attachNode(node, depth, host),\n detachNode: (nodeId: string) => this.detachNode(nodeId),\n };\n }\n\n private applyInputs(ref: ComponentRef<unknown>, node: T_gridLayout_node, depth: number): void {\n ref.setInput('data', node.data);\n ref.setInput('node', node);\n ref.setInput('isEditMode', this.editMode());\n ref.setInput('depth', depth);\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n OnDestroy,\n ViewContainerRef,\n computed,\n inject,\n input,\n output,\n effect,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { GridsterComponent, GridsterModule } from 'gridster18';\nimport { emptyRootNode } from '../defines/gridster-config.define';\nimport { LibsUiGridLayoutService } from '../grid-layout.service';\nimport {\n T_gridLayout_actionEvent,\n T_gridLayout_addEvent,\n T_gridLayout_changeEvent,\n T_gridLayout_newNode,\n T_gridLayout_node,\n} from '../interfaces/grid-layout.interface';\n\n/**\n * Mặt phẳng kéo thả. Đệ quy: khối có `children` thì ruột nó lại là một mặt phẳng nữa.\n *\n * Nơi dùng KHÔNG dựng component này trực tiếp cho từng khối — chỉ đặt MỘT thẻ ở gốc và truyền\n * `nodeComponentType` qua `LibsUiGridLayoutService.init()`. Thư viện tự gắn component cho mọi khối.\n */\n@Component({\n selector: 'libs_ui-services-grid_layout-canvas',\n standalone: true,\n imports: [GridsterModule, LibsUiComponentsButtonsButtonComponent],\n templateUrl: './grid-layout-canvas.component.html',\n styleUrl: './grid-layout-canvas.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LibsUiGridLayoutCanvasComponent implements OnDestroy {\n /**\n * @internal Chỉ mặt phẳng LỒNG dùng — thư viện tự truyền khi vẽ ruột container.\n *\n * Nơi dùng KHÔNG truyền: mặt phẳng gốc đọc cây từ service (đã đưa vào qua `init()`), truyền thêm\n * ở đây là khai hai lần cùng một thứ (người dùng chốt 28/08/2026).\n */\n readonly node = input<T_gridLayout_node>();\n /** @internal Chỉ mặt phẳng LỒNG dùng — thư viện tự truyền. */\n readonly depth = input<number>(0);\n\n /**\n * Bố cục vừa đổi do NGƯỜI DÙNG kéo hoặc đổi kích thước khối.\n *\n * Nơi dùng tự gọi `addBlock` · `removeBlock` · `compact` thì KHÔNG bắn — họ vừa gọi thì đã biết,\n * bắn ngược lại là thừa (người dùng chốt 28/08/2026).\n */\n readonly outChange = output<T_gridLayout_changeEvent>();\n /**\n * Người dùng bấm nút XOÁ trên một khối. Thư viện CHƯA xoá — gọi `event.confirm()` để xoá thật.\n * Cần hỏi trước thì hỏi xong mới gọi; không cho phép thì đừng gọi.\n */\n readonly outRemoveNode = output<T_gridLayout_actionEvent>();\n /**\n * Người dùng bấm nút THÊM trên một container. Thư viện KHÔNG tự thêm — nó không biết bạn có\n * những loại khối nào. Mở menu chọn loại rồi gọi `event.confirm(item)` với khối bạn muốn thêm.\n */\n readonly outAddBlockInside = output<T_gridLayout_addEvent>();\n /** Người dùng bấm nút GỘP/TÁCH. Thư viện chưa làm gì — gọi `event.confirm()` để thực hiện. */\n readonly outToggleType = output<T_gridLayout_actionEvent>();\n\n\n private readonly gridsterRef = viewChild(GridsterComponent);\n /** mỗi ô một chỗ gắn riêng — cùng thứ tự với `children()` */\n private readonly itemHosts = viewChildren('itemHost', { read: ViewContainerRef });\n\n /** Sáu chấm của tay cầm kéo — chỉ để `@for` dựng đủ 6 thẻ, giá trị không dùng tới. */\n protected readonly dragBarDots = [0, 1, 2, 3, 4, 5];\n\n private readonly service = inject(LibsUiGridLayoutService);\n\n /**\n * Node THẬT của mặt phẳng này.\n *\n * 🔴 Mặt phẳng GỐC (depth 0) đọc cây từ SERVICE, không dùng input.\n * Nơi dùng thường sửa cây TẠI CHỖ (`treeService.compact(tree)`) rồi gọi `refresh()`, nên signal\n * `root()` của họ giữ nguyên tham chiếu và input `node` không hề đổi — `@for` không dựng lại\n * `gridster-item`, lưới đứng im dù dữ liệu đã khác (đo 28/08/2026: bấm \"Sắp gọn\" không tác dụng).\n * `refresh()` của service thay tham chiếu cây, nên đọc từ đó mới thấy thay đổi.\n *\n * Mặt phẳng LỒNG vẫn dùng input: nó nhận node con từ mặt phẳng cha, vốn đã là object mới.\n */\n protected readonly currentNode = computed(() => {\n this.service.Version();\n\n if (this.depth() > 0) {\n return this.node() ?? emptyRootNode();\n }\n\n return this.service.Root() ?? emptyRootNode();\n });\n\n protected readonly children = computed(() => this.currentNode().children ?? []);\n\n protected readonly isNestedCanvas = computed(() => this.depth() > 0);\n\n /** trần lồng container — khối đã chạm trần thì không cho chuyển thành container */\n protected readonly maxContainerDepth = computed(() => this.service.FunctionsControl.maxContainerDepth());\n\n /**\n * Lề trong của container, px.\n *\n * 🔴 Đặt trên VỎ container, không đặt vào lưới con. Lưới con giữ nguyên `margin: 2` như cũ; lề\n * này chỉ co ruột lại khỏi biên vỏ, nhờ đó tay cầm đổi kích thước của khối con luôn nằm trong tầm\n * chuột (người dùng chốt 28/08/2026).\n */\n protected readonly containerPadding = computed(() => `${this.service.FunctionsControl.containerPadding()}px`);\n\n /** Dải kéo chỉ hiện ở chế độ sửa — chế độ xem không kéo được nên hiện dải là gây nhầm. */\n protected readonly isEditMode = computed(() => this.service.IsEditMode());\n\n protected readonly gridOptions = computed(() => {\n // Đọc `Version` để `init()` lại (đổi chế độ, bật/tắt chồng khối) sinh ra options MỚI —\n // gridster chỉ áp dụng cấu hình khi tham chiếu `options` đổi.\n this.service.Version();\n\n return this.service.FunctionsControl.gridsterOptions(this.depth(), () => this.outChange.emit({ root: this.currentNode() }));\n });\n\n constructor() {\n // Gắn component của nơi dùng vào từng ô, và gắn LẠI mỗi khi cây đổi.\n // Dùng effect vì `itemHosts()` chỉ có giá trị sau khi Angular dựng xong @for.\n effect(() => {\n const hosts = this.itemHosts();\n const items = this.children();\n\n items.forEach((item, i) => {\n const host = hosts[i];\n\n if (!host) {\n return;\n }\n\n // Khối có con là CONTAINER: ruột nó do mặt phẳng lồng vẽ, không gắn component nội dung.\n if ((item.children?.length ?? 0) > 0) {\n return;\n }\n\n this.service.FunctionsControl.attachNode(item, this.depth() + 1, host);\n });\n });\n }\n\n ngOnDestroy(): void {\n for (const item of this.children()) {\n this.service.FunctionsControl.detachNode(item.id);\n }\n }\n\n /** Vẽ lại lưới — gọi khi khung ngoài đổi kích thước hoặc cây vừa đổi diện rộng. */\n get FunctionControl() {\n return {\n veLaiLuoi: () => this.gridsterRef()?.optionsChanged(),\n };\n }\n\n protected handlerTrackNode(_index: number, item: T_gridLayout_node): string {\n return item.id;\n }\n\n /**\n * 🔴 Chặn `mousedown` nổi lên lưới CHA khi thao tác trong lưới con.\n * Không chặn thì cả hai lưới cùng nhận một cú bấm: kéo khối con là nhấc luôn container.\n */\n /**\n * Chặn `mousedown` của khối trong lưới LỒNG nổi lên lưới cha.\n *\n * Chỉ chặn ở lưới lồng: lưới cấp trang không có cha nào để chặn, và chặn ở đó sẽ nuốt luôn thao\n * tác của chính nó.\n */\n /**\n * 🔴 Ba handler dưới đây PHẢI `stopPropagation`.\n * Nút nằm trong vùng mang `dragHandleClass`, không chặn thì cú bấm bị gridster hiểu là bắt đầu kéo\n * và `delayStart: 160` nuốt luôn `click` — người dùng thấy như nút chết.\n */\n protected handlerRemove(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outRemoveNode.emit({ nodeId: node.id, node, confirm: () => this.service.removeBlock(node.id) });\n }\n\n protected handlerAddInside(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outAddBlockInside.emit({\n nodeId: node.id,\n node,\n confirm: (item: T_gridLayout_newNode) => this.service.addBlock(item, node.id),\n });\n }\n\n protected handlerToggleType(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outToggleType.emit({\n nodeId: node.id,\n node,\n // Gộp hay tách suy ra từ chính khối: đang là container thì tách, không thì gộp.\n confirm: () => (this.isContainer(node) ? this.service.toSingle(node.id) : this.service.toContainer(node.id)),\n });\n }\n\n /** khối này có phải container không (có khối con) */\n protected isContainer(item: T_gridLayout_node): boolean {\n return (item.children?.length ?? 0) > 0;\n }\n\n /** container đã chạm trần lồng thì không cho thêm khối vào trong nữa */\n protected canAddInside(item: T_gridLayout_node): boolean {\n return this.isContainer(item) && this.depth() < this.maxContainerDepth();\n }\n\n /** khối đơn ở cấp chưa chạm trần mới được chuyển thành container */\n protected canToggleType(item: T_gridLayout_node): boolean {\n if (this.isContainer(item)) {\n return true;\n }\n\n return this.depth() < this.maxContainerDepth();\n }\n\n protected handlerBlockParentDrag(event: Event): void {\n if (!this.isNestedCanvas()) {\n return;\n }\n\n event.stopPropagation();\n }\n\n protected handlerMouseDownTrongLuoi(event: Event): void {\n if (this.depth() === 0) {\n return;\n }\n\n event.stopPropagation();\n }\n}\n","<!-- 🔴 `relative` là BẮT BUỘC, CẤM bỏ.\n gridster đổi vị trí chuột thành ô lưới bằng `e.clientY + (el.scrollTop - el.offsetTop)` — công\n thức đó chỉ đúng khi `offsetParent` của <gridster> CHÍNH LÀ khối cuộn này. Thiếu `relative` thì\n `offsetParent` nhảy lên khối bao ngoài: `offsetTop` trả 16 trong khi lệch thật là 65 → gridster\n tính ô sai 49px, ô chờ đặt hiện lệch khỏi con trỏ nên kéo thả không đổi được vị trí, và kéo mép\n cũng tính sai điểm dừng. -->\n<div\n class=\"libs-ui-grid-layout-scroll-area relative h-full min-h-0 w-full min-w-0\"\n [class.overflow-y-auto]=\"!isNestedCanvas()\"\n (mousedown)=\"handlerMouseDownTrongLuoi($event)\">\n <gridster class=\"h-full w-full\" [options]=\"gridOptions()\">\n @for (item of children(); track item.id) {\n <!-- 🔴 Chặn `mousedown` tại ĐÂY cho lưới lồng — CẤM bỏ và CẤM chuyển sang chỗ khác.\n `ignoreContentClass` một mình KHÔNG đủ: `delayStart: 160` làm MỖI lưới lên lịch\n `dragStart` bằng `setTimeout` ngay tại `mousedown`, còn `stopPropagation` mà lib gọi bên\n trong `dragStart` chạy sau 160ms nên quá muộn — lưới CHA đã kịp nhận (đo 28/08/2026: kéo\n dải khối con, chuỗi class duyệt lên ĐÚNG mà container vẫn nhảy 0,0 → 0,1).\n Gắn ở `gridster-item` là đúng biên: lưới con nghe trên chính phần tử này nên đã nhận xong,\n lưới cha ở ngoài bị chặn. -->\n <gridster-item\n [item]=\"item\"\n (mousedown)=\"handlerBlockParentDrag($event)\">\n <!-- 🔴 Vỏ này mang `dragHandleClass` — CẤM bỏ.\n `ignoreContent: true` bắt gridster CHỈ cho kéo khi chỗ bấm nằm dưới một phần tử có\n `dragHandleClass`. Không có vỏ này thì component của nơi dùng (thư viện không kiểm soát\n được class của nó) sẽ không có tay cầm nào, và KHÔNG khối nào kéo được — đo 28/08/2026:\n kéo 320px, toạ độ khối giữ nguyên x=3,y=0.\n Tên class theo cấp: lưới trang và lưới lồng dùng hai tên KHÁC nhau, nếu không lưới cha\n cũng nhận ra tay cầm của khối con và nhấc luôn container. -->\n <!-- 🔴 Vỏ KHÔNG mang `dragHandleClass` — CẤM thêm lại.\n Kéo chỉ được phép bắt đầu từ DẢI XANH (người dùng chốt 28/08/2026: \"phải hover vào vùng\n màu xanh thì mới kéo thả được cho đồng nhất\"). Cho cả vỏ làm tay cầm thì bấm đâu cũng\n kéo, và khối con nằm trong container sẽ nhấc luôn container vì lưới cha duyệt lên gặp\n tay cầm của vỏ container trước.\n Vỏ khối con vẫn giữ class CHẶN để lưới cha dừng đúng ở biên. -->\n <div\n class=\"libs-ui-grid-layout-block-shell group relative h-full w-full min-w-0\"\n [class.libs-ui-grid-layout-block-parent-drag]=\"isNestedCanvas()\">\n <!-- Dải kéo: hiện khi rê chuột vào khối, ba chấm là dấu hiệu kéo quen thuộc.\n Người dùng cần một chỗ bám RÕ RÀNG thay vì đoán xem bấm đâu thì kéo được\n (chốt 28/08/2026, theo đúng dải đang dùng ở màn Customer 360 của mobio-web). -->\n @if (isEditMode()) {\n <!-- 🔴 Dải PHẢI mang tay cầm ĐÚNG CẤP của nó. Dải nhận chuột (`pointer-events: auto`),\n nên nếu không mang tay cầm thì `checkDragHandleClass` duyệt lên gặp tay cầm của\n container và nhấc container thay vì khối con (đo 28/08/2026: kéo dải khối con,\n container nhảy 0,0 → 0,1 còn khối con đứng im).\n 🔴 Dải CHỈ mang tay cầm, CẤM mang thêm class chặn: `checkDragHandleClass` xét hai\n class đó trên CÙNG một node nên để chung là kéo hỏng (đo 28/08/2026: bấm dải khối\n con kéo 140px, khối đứng im). Việc chặn lưới cha do VỎ KHỐI lo. -->\n <div\n class=\"libs-ui-grid-layout-drag-bar\"\n [class.libs-ui-grid-layout-drag-bar-child]=\"isNestedCanvas()\"\n [class.libs-ui-grid-layout-drag-handle]=\"!isNestedCanvas()\"\n [class.libs-ui-grid-layout-drag-handle-child]=\"isNestedCanvas()\">\n <span class=\"libs-ui-grid-layout-drag-bar-dots\">\n @for (dot of dragBarDots; track dot) {\n <span class=\"libs-ui-grid-layout-drag-bar-dot\"></span>\n }\n </span>\n </div>\n }\n\n <!-- Khung chứa component của nơi dùng.\n 🔴 PHẢI có khung thật (không phải `ng-container` trống): nó lo hộ nơi dùng phần lấp đầy\n ô và viền báo chế độ sửa. Không có khung thì mỗi component nội dung lại phải tự viết\n `:host { width/height: 100% }` + viền đứt — đó là việc của thư viện, không phải của\n người dùng (người dùng chốt 28/08/2026).\n Mỗi khối một ViewContainerRef riêng nên component nằm đúng ô của nó. -->\n <div\n class=\"libs-ui-grid-layout-content-frame\"\n [class.libs-ui-grid-layout-content-frame-edit]=\"isEditMode() && !isContainer(item)\"\n [class.libs-ui-grid-layout-content-frame-empty]=\"isContainer(item)\">\n <ng-container #itemHost />\n </div>\n\n <!-- Dấu hiệu CONTAINER: nhãn góc trên-phải + viền đứt bao ruột. Không có dấu hiệu thì\n người dùng không biết khối nào chứa được khối khác (chốt 28/08/2026, theo đúng cách\n màn Customer 360 của mobio-web đang làm). -->\n @if (isEditMode() && isContainer(item)) {\n <div class=\"libs-ui-grid-layout-container-label\">Khối ghép</div>\n <div class=\"libs-ui-grid-layout-container-border\"></div>\n }\n\n <!-- Thanh công cụ: hiện khi rê chuột vào khối.\n 🔴 Dùng `libs_ui-components-buttons-button` — CẤM tự dựng thẻ `<button>`.\n Component này đã có sẵn kiểu nút, cỡ nút và bong bóng chú thích theo đúng bộ giao diện\n của sản phẩm; tự dựng là mỗi nơi một kiểu và mất luôn tooltip. -->\n @if (isEditMode()) {\n <div\n class=\"libs-ui-grid-layout-toolbar\"\n [class.libs-ui-grid-layout-toolbar-child]=\"isNestedCanvas()\">\n @if (canAddInside(item)) {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"'libs-ui-icon-add'\"\n [popover]=\"{ config: { content: 'Thêm khối vào trong', zIndex: 1300 } }\"\n (outClick)=\"handlerAddInside($event, item)\" />\n }\n @if (canToggleType(item)) {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"isContainer(item) ? 'libs-ui-icon-split-cell' : 'libs-ui-icon-merge-cell'\"\n [popover]=\"{ config: { content: isContainer(item) ? 'Đưa về khối đơn' : 'Chuyển thành khối ghép', zIndex: 1300 } }\"\n (outClick)=\"handlerToggleType($event, item)\" />\n }\n <libs_ui-components-buttons-button\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"'libs-ui-icon-remove'\"\n [popover]=\"{ config: { content: isContainer(item) ? 'Xoá cả khối ghép' : 'Xoá khối', zIndex: 1300 } }\"\n (outClick)=\"handlerRemove($event, item)\" />\n </div>\n }\n\n @if (item.children && item.children.length > 0) {\n <!-- Khối có con → ruột nó lại là một mặt phẳng nữa. Đệ quy ở đây, nơi dùng không phải lo.\n Lề đặt ở ĐÂY (vỏ container), không đặt vào lưới con — lưới con giữ nguyên khe 2px. -->\n <libs_ui-services-grid_layout-canvas\n class=\"block h-full w-full\"\n [style.padding]=\"containerPadding()\"\n [node]=\"item\"\n [depth]=\"depth() + 1\"\n (outChange)=\"outChange.emit($event)\"\n (outRemoveNode)=\"outRemoveNode.emit($event)\"\n (outAddBlockInside)=\"outAddBlockInside.emit($event)\"\n (outToggleType)=\"outToggleType.emit($event)\" />\n }\n </div>\n </gridster-item>\n }\n </gridster>\n</div>\n","// Bề mặt CÔNG KHAI — chỉ những gì nơi dùng thật sự cần.\n//\n// `LibsUiGridLayoutTreeService` CỐ Ý không xuất: mọi thao tác trên cây đã có mặt trên\n// `LibsUiGridLayoutService` với chữ ký gọn hơn (không phải truyền `root` — thư viện đang giữ nó).\n// Cấu hình gridster cũng không xuất: nó đã được vá theo hàng chục lỗi đo trên sản phẩm thật, để nơi\n// dùng sửa lại là mở đường cho chính những lỗi đó quay về.\nexport * from './grid-layout.service';\nexport * from './canvas/grid-layout-canvas.component';\nexport * from './interfaces/grid-layout.interface';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;AAGA;;;;;AAKG;AACI,MAAM,oBAAoB,GAAG,OAAuB;;;;IAIzD,QAAQ,EAAE,QAAQ,CAAC,aAAa;;;;;;;;IAShC,WAAW,EAAE,WAAW,CAAC,IAAI;IAC7B,WAAW,EAAE,WAAW,CAAC,eAAe;;;;;;AAOxC,IAAA,SAAS,EAAE,IAAI;;AAEf,IAAA,cAAc,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;AACvE,IAAA,eAAe,EAAE,IAAI;AACrB,IAAA,IAAI,EAAE,IAAI;AACV,IAAA,iBAAiB,EAAE,IAAI;AAEvB,IAAA,SAAS,EAAE;AACT,QAAA,OAAO,EAAE,IAAI;;;;AAIb,QAAA,UAAU,EAAE,GAAG;;;;AAIf,QAAA,kBAAkB,EAAE,uCAAuC;AAC3D,QAAA,aAAa,EAAE,IAAI;AACnB,QAAA,eAAe,EAAE,iCAAiC;AACnD,KAAA;AAED,IAAA,SAAS,EAAE;AACT,QAAA,OAAO,EAAE,IAAI;;AAEb,QAAA,OAAO,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE;AACxF,KAAA;AAED,IAAA,MAAM,EAAE,EAAE;AACV,IAAA,WAAW,EAAE,IAAI;AACjB,IAAA,iBAAiB,EAAE,EAAE;AACrB,IAAA,OAAO,EAAE,EAAE;AACX,IAAA,OAAO,EAAE,EAAE;AACX,IAAA,OAAO,EAAE,CAAC;;;;;AAMV,IAAA,OAAO,EAAE,IAAI;AACb,IAAA,WAAW,EAAE,IAAI;AACjB,IAAA,WAAW,EAAE,EAAE;AACf,IAAA,WAAW,EAAE,KAAK;;;;AAKlB,IAAA,aAAa,EAAE,IAAI;AAEnB,IAAA,WAAW,EAAE,IAAI;AACjB,IAAA,cAAc,EAAE,EAAE;AAClB,IAAA,eAAe,EAAE,CAAC;AAClB,IAAA,eAAe,EAAE,CAAC;AAClB,IAAA,WAAW,EAAE,CAAC;IACd,gBAAgB,EAAE,CAAC,CAAC;AACrB,CAAA,CAAC,CAAC;AAEH;;;;;AAKG;AACI,MAAM,sBAAsB,GAAG,OAAuB;AAC3D,IAAA,GAAG,oBAAoB,EAAE;;;;AAKzB,IAAA,WAAW,EAAE,KAAK;;AAGlB,IAAA,MAAM,EAAE,CAAC;;;;AAIT,IAAA,WAAW,EAAE,KAAK;AAClB,IAAA,iBAAiB,EAAE,CAAC;;AAGpB,IAAA,cAAc,EAAE,EAAE;AAClB,IAAA,OAAO,EAAE,CAAC;AACV,IAAA,WAAW,EAAE,CAAC;AACd,IAAA,eAAe,EAAE,CAAC;AAClB,IAAA,eAAe,EAAE,CAAC;;;;AAKlB,IAAA,SAAS,EAAE;QACT,GAAG,oBAAoB,EAAE,CAAC,SAAS;AACnC,QAAA,eAAe,EAAE,uCAAuC;AACzD,KAAA;;;;AAKD,IAAA,eAAe,EAAE,KAAK;;;;AAKtB,IAAA,uBAAuB,EAAE,IAAI;AAC7B,IAAA,qBAAqB,EAAE,IAAI;AAC5B,CAAA,CAAC,CAAC;AAEH;;;AAGG;AACI,MAAM,aAAa,GAAG,OAA0B,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;;ACvInH;;;;;;;AAOG;MAEU,2BAA2B,CAAA;IACtC,QAAQ,CAAC,IAAuB,EAAE,EAAU,EAAA;AAC1C,QAAA,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;AAClB,YAAA,OAAO,IAAI,CAAC;SACb;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAEvC,IAAI,KAAK,EAAE;AACT,gBAAA,OAAO,KAAK,CAAC;aACd;SACF;AAED,QAAA,OAAO,SAAS,CAAC;KAClB;IAED,UAAU,CAAC,IAAuB,EAAE,EAAU,EAAA;QAC5C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;AACvC,YAAA,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE;AACnB,gBAAA,OAAO,IAAI,CAAC;aACb;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAEzC,IAAI,KAAK,EAAE;AACT,gBAAA,OAAO,KAAK,CAAC;aACd;SACF;AAED,QAAA,OAAO,SAAS,CAAC;KAClB;AAED;;;;AAIG;AACH,IAAA,QAAQ,CAAC,IAAuB,EAAE,QAAgB,EAAE,IAA0B,EAAA;QAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAE7C,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,SAAS,CAAC;SAClB;QAED,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;;;;AAIxC,QAAA,MAAM,IAAI,GAAsB,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;AAE/G,QAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;AAG3B,QAAA,OAAO,IAAI,CAAC;KACb;;IAGD,UAAU,CAAC,IAAuB,EAAE,EAAU,EAAA;AAC5C,QAAA,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;AAClB,YAAA,OAAO,KAAK,CAAC;SACd;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAEzC,QAAA,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE;AACrB,YAAA,OAAO,KAAK,CAAC;SACd;QAED,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAEnE,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;;;;AAMG;AACH,IAAA,WAAW,CAAC,IAAuB,EAAE,EAAU,EAAE,QAAgB,EAAA;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAErC,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;AAC7C,YAAA,OAAO,KAAK,CAAC;SACd;AAED,QAAA,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AAE7F,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;;AAIG;IACH,QAAQ,CAAC,IAAuB,EAAE,EAAU,EAAA;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAErC,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE;AAC/C,YAAA,OAAO,KAAK,CAAC;SACd;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAEzC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;YACvC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;SAChE;AAED,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;AAEnB,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;;;;;;AAQG;IACH,0BAA0B,CAAC,IAAuB,EAAE,QAAgB,EAAA;QAClE,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;KAC5C;AAED;;;;;;AAMG;IACH,OAAO,CAAC,IAAuB,EAAE,QAAgB,EAAA;AAC/C,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KAClC;IAEO,WAAW,CAAC,IAAuB,EAAE,QAAgB,EAAA;AAC3D,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;AAE/B,QAAA,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE;YACrB,OAAO;SACR;AAED,QAAA,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,YAAY,GAAG,CAAC,CAAC;AAErB,QAAA,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE;AACjC,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAE5C,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,KAAK,GAAG,QAAQ,EAAE;gBAC/C,UAAU,IAAI,YAAY,CAAC;gBAC3B,QAAQ,GAAG,CAAC,CAAC;gBACb,YAAY,GAAG,CAAC,CAAC;aAClB;AAED,YAAA,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;AAClB,YAAA,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC;AACpB,YAAA,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;YAClB,QAAQ,IAAI,KAAK,CAAC;YAClB,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAEjD,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;AACpC,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;aAClC;SACF;KACF;AAEO,IAAA,WAAW,CAAC,IAAuB,EAAE,cAAsB,EAAE,QAAgB,EAAA;AACnF,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;AAE/B,QAAA,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE;AACrB,YAAA,OAAO,CAAC,CAAC;SACV;QAED,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,MAAM,GAA6B,EAAE,CAAC;AAE5C,QAAA,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;AAC5B,YAAA,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;AAEtD,YAAA,IAAI,WAAW,IAAI,cAAc,IAAI,QAAQ,EAAE;gBAC7C,UAAU,IAAI,CAAC,CAAC;gBAEhB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE;oBACvC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AAC/D,oBAAA,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;iBACnB;gBAED,SAAS;aACV;YAED,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,GAAG,CAAC,GAAG,cAAc,EAAE,QAAQ,CAAC,CAAC;AACnG,YAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACpB;AAED,QAAA,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;AAEvB,QAAA,OAAO,UAAU,CAAC;KACnB;AAEO,IAAA,WAAW,CAAC,QAAkC,EAAA;AACpD,QAAA,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;KAChF;wGAhNU,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;4GAA3B,2BAA2B,EAAA,CAAA,CAAA;;4FAA3B,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBADvC,UAAU;;;ACEX;;;;;;;;;;AAUG;MAEU,uBAAuB,CAAA;;;;AAIjB,IAAA,WAAW,GAAG,IAAI,2BAA2B,EAAE,CAAC;;AAEhD,IAAA,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEhE,IAAA,WAAA,GAAA;;;;AAIE,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;KACpD;AAEO,IAAA,MAAM,CAAuB;AACpB,IAAA,aAAa,GAAG,IAAI,GAAG,EAAiC,CAAC;AAEzD,IAAA,QAAQ,GAAG,MAAM,CAAgC,SAAS,CAAC,CAAC;AAC5D,IAAA,QAAQ,GAAG,MAAM,CAAU,KAAK,CAAC,CAAC;;AAElC,IAAA,OAAO,GAAG,MAAM,CAAS,CAAC,CAAC,CAAC;AAE7C;;;;;;AAMG;AACM,IAAA,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;AAClC,IAAA,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;;AAExC,IAAA,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;AAE7C;AAC8F;IACtF,iBAAiB,GAAA;AACvB,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,iBAAiB,IAAI,CAAC,CAAC;KAC5C;AAED;AAC6E;IACrE,gBAAgB,GAAA;AACtB,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE,gBAAgB,IAAI,EAAE,CAAC;KAC5C;;AAGD,IAAA,IAAI,CAAC,MAA2B,EAAA;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;AACf,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AACrB,QAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;;;;AAKtC,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,KAAK,CAAC,CAAC;AAC9C,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KACnC;AAED,IAAA,WAAW,CAAC,KAAc,EAAA;AACxB,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;;;;AAIzB,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KACnC;AAED;;;;;AAKG;AACH,IAAA,eAAe,CAAC,KAAc,EAAA;AAC5B,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,OAAO;SACR;AAED,QAAA,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAEtD,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;;;;;;AAOD,QAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;;;QAG/B,IAAI,CAAC,OAAO,EAAE,CAAC;KAChB;AAED;;;;;AAKG;IACK,oBAAoB,CAAC,KAAa,EAAE,kBAA+B,EAAA;AACzE,QAAA,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,oBAAoB,EAAE,GAAG,sBAAsB,EAAE,CAAC;AAC7E,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,OAAO,IAAI,CAAC;SACb;AAED,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,gDAAmC;AACjE,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,UAAU,KAAK,MAAM,CAAC,YAAY,IAAI,KAAK,CAAC,CAAC;QAEhE,OAAO;AACL,YAAA,GAAG,IAAI;AACP,YAAA,IAAI,MAAM,CAAC,IAAI,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;YAChG,IAAI,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC;;YAEhF,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;YAChF,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC;YAC1F,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC;YACxG,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC;YAC/F,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,iBAAiB,KAAK,SAAS,GAAG,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC;YACjH,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC;YAChF,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,GAAG,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC;YAC5F,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,GAAG,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC;;;;;YAM5F,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;YAClD,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;;AAGlD,YAAA,eAAe,EAAE,UAAU;;;;;;YAM3B,IAAI,UAAU,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAE1G,YAAA,kBAAkB,EAAE,CAAC,IAAkB,KAAI;;;;;;gBAMzC,IAAI,UAAU,EAAE;AACd,oBAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;iBAC5B;AAED,gBAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,kBAAkB,IAAI,CAAC;aACxB;SACF,CAAC;KACH;AAED;;;;;;AAMG;AACK,IAAA,UAAU,CAAC,IAAuB,EAAE,KAAa,EAAE,IAAsB,EAAA;AAC/E,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,IAAI,CAAC,MAAM,EAAE;YACX,OAAO;SACR;AAED,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEjD,IAAI,QAAQ,EAAE;YACZ,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YAExC,OAAO;SACR;;;AAID,QAAA,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,kBAAkB,IAAI,MAAM,CAAC,kBAAkB,IAAI,IAAI,CAAC,CAAC;QAE9E,IAAI,CAAC,MAAM,EAAE;YACX,OAAO;SACR;;;;AAKD,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;AAE9C,QAAA,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,aAAa,KAAI;YAC3D,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;AAGlC,YAAA,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE;gBAChE,OAAO;aACR;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;YAEhD,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YACnC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AACvC,SAAC,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;KACrC;AAED;AAC0C;AAClC,IAAA,UAAU,CAAC,MAAc,EAAA;;;QAG/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;AAC7C,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEjC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE3C,IAAI,CAAC,GAAG,EAAE;YACR,OAAO;SACR;QAED,GAAG,CAAC,OAAO,EAAE,CAAC;AACd,QAAA,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACnC;IAEO,OAAO,GAAA;QACb,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE;YAC5C,GAAG,CAAC,WAAW,EAAE,CAAC;SACnB;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE;YAC7C,GAAG,CAAC,OAAO,EAAE,CAAC;SACf;AAED,QAAA,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;AAC1B,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AAC3B,QAAA,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;KACzB;;;;;AAOD;;;;;;;;;;;;AAYG;AACH,IAAA,OAAO,CAAC,KAAgC,EAAA;QACtC,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE5C,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAElC,OAAO;SACR;AAED,QAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,YAAA,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAC9C;AAED,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/C,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KACnC;;AAGD;;;;;;AAMG;AACK,IAAA,aAAa,CAAC,IAAuB,EAAA;AAC3C,QAAA,MAAM,IAAI,GAAsB,EAAE,GAAG,IAAI,EAAE,CAAC;;QAG5C,OAAO,IAAI,CAAC,kBAAkB,CAAC;QAE/B,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QAEzC,OAAO;AACL,YAAA,GAAG,IAAI;AACP,YAAA,IAAI,IAAI,KAAK,SAAS,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;AACxD,YAAA,IAAI,QAAQ,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;SACtF,CAAC;KACH;AAEO,IAAA,gBAAgB,CAAC,IAAuB,EAAA;AAC9C,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE;AAC1B,YAAA,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;SACpB;QAED,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;KAC1F;AAED;;;;;;;;;;AAUG;AACK,IAAA,mBAAmB,CAAC,IAAuB,EAAA;AACjD,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;AAC3B,QAAA,MAAM,UAAU,GAAG,MAAM,EAAE,IAAI,KAAkC,MAAA,yCAAK,MAAM,EAAE,YAAY,IAAI,KAAK,CAAC,CAAC;QAErG,IAAI,CAAC,UAAU,EAAE;YACf,OAAO;SACR;QAED,IAAI,KAAK,GAAG,CAAC,CAAC;AACd,QAAA,MAAM,IAAI,GAAG,CAAC,IAAuB,KAAU;YAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;AACvC,gBAAA,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE;oBAClC,KAAK,IAAI,CAAC,CAAC;AACX,oBAAA,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;iBAC1B;gBAED,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;AACH,SAAC,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,CAAC;KAEZ;;AAGO,IAAA,eAAe,CAAC,IAAkB,EAAA;AACxC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;QAED,IAAI,QAAQ,GAAG,CAAC,CAAC;AACjB,QAAA,MAAM,IAAI,GAAG,CAAC,IAAuB,KAAU;YAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE;AACvC,gBAAA,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,CAAC,CAAC;aACb;AACH,SAAC,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,CAAC;;;QAIX,MAAM,IAAI,GAAG,IAAoC,CAAC;AAElD,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE;YAEhC,OAAO;SACR;AAED,QAAA,IAAI,CAAC,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC;KAChC;;;;;AAOD;;;;;;AAMG;IACH,QAAQ,CAAC,IAA0B,EAAE,QAAiB,EAAA;AACpD,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC;QAE5F,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;SAChB;AAED,QAAA,OAAO,KAAK,CAAC;KACd;;AAGD,IAAA,WAAW,CAAC,EAAU,EAAA;AACpB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;QAElE,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,OAAO,EAAE,CAAC;SAChB;AAED,QAAA,OAAO,IAAI,CAAC;KACb;;AAGD,IAAA,WAAW,CAAC,EAAU,EAAA;AACpB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AAC7B,QAAA,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;QAE5F,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,OAAO,EAAE,CAAC;SAChB;AAED,QAAA,OAAO,IAAI,CAAC;KACb;;AAGD,IAAA,QAAQ,CAAC,EAAU,EAAA;AACjB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;QAEhE,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,OAAO,EAAE,CAAC;SAChB;AAED,QAAA,OAAO,IAAI,CAAC;KACb;;IAGD,OAAO,GAAA;AACL,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE;YACT,OAAO;SACR;AAED,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;KAChB;AAED;;;;;;;AAOG;IACH,YAAY,GAAA;AACV,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AAE7B,QAAA,OAAO,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;KACpD;;AAGD,IAAA,SAAS,CAAC,EAAU,EAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AAE7B,QAAA,OAAO,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC;KAC/D;;AAGD,IAAA,eAAe,CAAC,EAAU,EAAA;AACxB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;AAE7B,QAAA,OAAO,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC;KACjE;AAED;;;;;;AAMG;AACH,IAAA,IAAI,gBAAgB,GAAA;QAClB,OAAO;AACL,YAAA,iBAAiB,EAAE,MAAM,IAAI,CAAC,iBAAiB,EAAE;AACjD,YAAA,gBAAgB,EAAE,MAAM,IAAI,CAAC,gBAAgB,EAAE;AAC/C,YAAA,eAAe,EAAE,CAAC,KAAa,EAAE,EAAe,KAAK,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,CAAC;AACzF,YAAA,UAAU,EAAE,CAAC,IAAuB,EAAE,KAAa,EAAE,IAAsB,KAAK,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC;YAClH,UAAU,EAAE,CAAC,MAAc,KAAK,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;SACxD,CAAC;KACH;AAEO,IAAA,WAAW,CAAC,GAA0B,EAAE,IAAuB,EAAE,KAAa,EAAA;QACpF,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,QAAA,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC5C,QAAA,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;KAC9B;wGAnfU,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;4GAAvB,uBAAuB,EAAA,CAAA,CAAA;;4FAAvB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBADnC,UAAU;;;ACAX;;;;;AAKG;MASU,+BAA+B,CAAA;AAC1C;;;;;AAKG;IACM,IAAI,GAAG,KAAK,EAAqB,CAAC;;AAElC,IAAA,KAAK,GAAG,KAAK,CAAS,CAAC,CAAC,CAAC;AAElC;;;;;AAKG;IACM,SAAS,GAAG,MAAM,EAA4B,CAAC;AACxD;;;AAGG;IACM,aAAa,GAAG,MAAM,EAA4B,CAAC;AAC5D;;;AAGG;IACM,iBAAiB,GAAG,MAAM,EAAyB,CAAC;;IAEpD,aAAa,GAAG,MAAM,EAA4B,CAAC;AAG3C,IAAA,WAAW,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;;IAE3C,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;;AAG/D,IAAA,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEnC,IAAA,OAAO,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;AAE3D;;;;;;;;;;AAUG;AACgB,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;AAC7C,QAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AAEvB,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE;AACpB,YAAA,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;SACvC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;AAChD,KAAC,CAAC,CAAC;AAEgB,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAE7D,IAAA,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;;AAGlD,IAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAEzG;;;;;;AAMG;AACgB,IAAA,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAG,EAAA,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,CAAA,EAAA,CAAI,CAAC,CAAC;;AAG3F,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;AAEvD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;;;AAG7C,QAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AAEvB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;AAC9H,KAAC,CAAC,CAAC;AAEH,IAAA,WAAA,GAAA;;;QAGE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;AAC/B,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAE9B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,KAAI;AACxB,gBAAA,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAEtB,IAAI,CAAC,IAAI,EAAE;oBACT,OAAO;iBACR;;AAGD,gBAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;oBACpC,OAAO;iBACR;AAED,gBAAA,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACzE,aAAC,CAAC,CAAC;AACL,SAAC,CAAC,CAAC;KACJ;IAED,WAAW,GAAA;QACT,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;YAClC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACnD;KACF;;AAGD,IAAA,IAAI,eAAe,GAAA;QACjB,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE;SACtD,CAAC;KACH;IAES,gBAAgB,CAAC,MAAc,EAAE,IAAuB,EAAA;QAChE,OAAO,IAAI,CAAC,EAAE,CAAC;KAChB;AAED;;;AAGG;AACH;;;;;AAKG;AACH;;;;AAIG;IACO,aAAa,CAAC,KAAY,EAAE,IAAuB,EAAA;QAC3D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,CAAC,cAAc,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;KACtG;IAES,gBAAgB,CAAC,KAAY,EAAE,IAAuB,EAAA;QAC9D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,CAAC,cAAc,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,IAAI;AACJ,YAAA,OAAO,EAAE,CAAC,IAA0B,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9E,SAAA,CAAC,CAAC;KACJ;IAES,iBAAiB,CAAC,KAAY,EAAE,IAAuB,EAAA;QAC/D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,KAAK,CAAC,cAAc,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACtB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,IAAI;;AAEJ,YAAA,OAAO,EAAE,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC7G,SAAA,CAAC,CAAC;KACJ;;AAGS,IAAA,WAAW,CAAC,IAAuB,EAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;KACzC;;AAGS,IAAA,YAAY,CAAC,IAAuB,EAAA;AAC5C,QAAA,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;KAC1E;;AAGS,IAAA,aAAa,CAAC,IAAuB,EAAA;AAC7C,QAAA,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC1B,YAAA,OAAO,IAAI,CAAC;SACb;QAED,OAAO,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;KAChD;AAES,IAAA,sBAAsB,CAAC,KAAY,EAAA;AAC3C,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE;YAC1B,OAAO;SACR;QAED,KAAK,CAAC,eAAe,EAAE,CAAC;KACzB;AAES,IAAA,yBAAyB,CAAC,KAAY,EAAA;AAC9C,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;YACtB,OAAO;SACR;QAED,KAAK,CAAC,eAAe,EAAE,CAAC;KACzB;wGA7MU,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;4FAA/B,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qCAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,SAAA,EAAA,WAAA,EAAA,aAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,aAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAgCD,iBAAiB,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,WAAA,EAAA,SAAA,EAAA,CAAA,UAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAA,EAEI,gBAAgB,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECzEhF,g3WAyIA,EAAA,MAAA,EAAA,CAAA,g1HAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDlGa,+BAA+B,EAAA,QAAA,EAAA,qCAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,WAAA,EAAA,eAAA,EAAA,mBAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EALhC,cAAc,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,qBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,sCAAsC,EAAA,QAAA,EAAA,mCAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,MAAA,EAAA,cAAA,EAAA,YAAA,EAAA,OAAA,EAAA,SAAA,EAAA,WAAA,EAAA,WAAA,EAAA,cAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,4BAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,yBAAA,EAAA,+BAAA,EAAA,oBAAA,EAAA,UAAA,EAAA,mCAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,iBAAA,EAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAKrD,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBAR3C,SAAS;+BACE,qCAAqC,EAAA,UAAA,EACnC,IAAI,EAAA,OAAA,EACP,CAAC,cAAc,EAAE,sCAAsC,CAAC,EAAA,eAAA,EAGhD,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,g3WAAA,EAAA,MAAA,EAAA,CAAA,g1HAAA,CAAA,EAAA,CAAA;;;AErCjD;AACA;AACA;AACA;AACA;AACA;;ACLA;;AAEG;;;;"}
1
+ {"version":3,"file":"libs-ui-services-grid-layout.mjs","sources":["../../../../../libs-ui/services/grid-layout/src/defines/gridster-config.define.ts","../../../../../libs-ui/services/grid-layout/src/tree.service.ts","../../../../../libs-ui/services/grid-layout/src/grid-layout.service.ts","../../../../../libs-ui/services/grid-layout/src/canvas/grid-layout-canvas.component.ts","../../../../../libs-ui/services/grid-layout/src/canvas/grid-layout-canvas.component.html","../../../../../libs-ui/services/grid-layout/src/index.ts","../../../../../libs-ui/services/grid-layout/src/libs-ui-services-grid-layout.ts"],"sourcesContent":["import { CompactType, DisplayGrid, GridsterConfig, GridType } from 'gridster18';\nimport { T_gridLayout_node } from '../interfaces/grid-layout.interface';\n\n/**\n * Cấu hình gridster cho lưới CẤP TRANG.\n *\n * Mọi giá trị dưới đây đều đến từ một lỗi đã đo được trên sản phẩm thật, không phải chọn theo cảm\n * tính. Đổi bất kỳ dòng nào có dấu 🔴 sẽ làm sống lại đúng lỗi ghi trong comment.\n */\nexport const gridLayoutRootConfig = (): GridsterConfig => ({\n // 🔴 VerticalFixed — CẤM đổi sang Fit hay ScrollVertical.\n // `Fit` chia đều chiều cao khung cho số hàng đang dùng, nên card khai `rows: 2` phình từ 124px lên\n // 247px. `ScrollVertical` KHÔNG đọc `fixedRowHeight` (mã lib: chỉ `Fixed` và `VerticalFixed` đọc).\n gridType: GridType.VerticalFixed,\n\n // 🔴 None — CẤM quay lại CompactUp.\n // `CompactUp` hút mọi khối lên sát nhau NGAY sau mỗi thao tác, nên:\n // · kéo mép dưới cho khối cao thêm → chỗ khối dưới vừa nhường bị hút lấp lại tức thì, cú kéo bị\n // `checkGridCollision` báo va chạm rồi HOÀN NGUYÊN (khối đứng im dù kéo);\n // · kéo thả đổi vị trí → khối vừa nhường chỗ bị hút về ngay, khối đang kéo không có chỗ đặt và\n // treo lơ lửng giữa hai khối.\n // Muốn dồn khít thì gọi `sapGon()` của service.\n compactType: CompactType.None,\n displayGrid: DisplayGrid.OnDragAndResize,\n\n // 🔴 pushItems: true — CẤM để false.\n // `swap` của lib CHỈ hoán vị được HAI KHỐI CÙNG KÍCH THƯỚC (mã lib `checkSwap`: tính diffX/diffY\n // rồi hoán vị, lệch kích thước thì `checkCollision` báo va chạm và hoàn nguyên). Khối 3x2 gặp\n // container 7x5 nên không swap được, mà `pushItems: false` cũng không cho container nhường đường\n // → BẾ TẮC: khối đang kéo không đặt được ở đâu.\n pushItems: true,\n // chỉ đẩy XUỐNG: đẩy ngang làm xô lệch bố cục cột người dùng vừa đặt\n pushDirections: { north: false, east: false, south: true, west: false },\n pushResizeItems: true,\n swap: true,\n swapWhileDragging: true,\n\n draggable: {\n enabled: true,\n // 🔴 KHÔNG được bỏ. Không có nó thì gridster vào chế độ kéo ngay từ `mousedown`, nên chỉ bấm\n // CHỌN một khối là nó đã nhích theo dù chuột đứng yên. Lib tự huỷ kéo khi nhả chuột trước mốc\n // này nên cú bấm chọn vẫn ăn nguyên vẹn.\n delayStart: 160,\n // 🔴 `checkDragHandleClass` duyệt DOM từ chỗ bấm NGƯỢC LÊN CHA, và trên MỖI node nó kiểm\n // `dragHandleClass` TRƯỚC `ignoreContentClass`. Vì vậy một phần tử KHÔNG được mang cả hai class\n // cùng lúc — mang cả hai thì lib gặp tay cầm trước, trả `true`, class chặn không tới lượt.\n ignoreContentClass: 'libs-ui-grid-layout-block-parent-drag',\n ignoreContent: true,\n dragHandleClass: 'libs-ui-grid-layout-drag-handle',\n },\n\n resizable: {\n enabled: true,\n // đủ 8 hướng như cửa sổ thường; chỉ có góc dưới-phải thì quá khó trúng\n handles: { s: true, e: true, n: true, w: true, se: true, ne: true, sw: true, nw: true },\n },\n\n margin: 12,\n outerMargin: true,\n outerMarginBottom: 40,\n minCols: 12,\n maxCols: 12,\n minRows: 2,\n\n // 🔴 KHÔNG giới hạn chiều cao khối. Lib có BA trần mặc định phải vô hiệu hoá CÙNG LÚC, thiếu một\n // cái là vẫn bị chặn: `maxItemRows: 50` · `maxItemCols: 50` · `maxItemArea: 2500` (trần DIỆN TÍCH\n // cols × rows — khó thấy nhất: khối 12 cột chỉ cần 209 hàng là đụng trần dù hai trần kia còn dư).\n // `maxRows` là trần của CẢ LƯỚI, cũng phải nới theo.\n maxRows: 5000,\n maxItemRows: 5000,\n maxItemCols: 12,\n maxItemArea: 60000,\n\n // 🔴 Trần LỚP CHỒNG. Mặc định của lib là 2 — quá thấp: khi bật chồng khối, thư viện gán mỗi khối\n // một lớp riêng để chúng khác nhau, nên chỉ 3 khối là đã đụng trần và các khối sau lại rơi về\n // cùng lớp, tức chồng nhau bị chặn trở lại.\n maxLayerIndex: 5000,\n\n setGridSize: true,\n fixedRowHeight: 56,\n defaultItemCols: 3,\n defaultItemRows: 2,\n minItemRows: 1,\n mobileBreakpoint: -1,\n});\n\n/**\n * Cấu hình cho lưới LỒNG (ruột một container).\n *\n * Kế thừa lưới trang rồi ghi đè phần khác biệt. Ba điểm quan trọng nhất: `setGridSize` phải TẮT,\n * tay cầm phải mang TÊN RIÊNG, và tự-cuộn-khi-kéo phải TẮT.\n */\nexport const gridLayoutNestedConfig = (): GridsterConfig => ({\n ...gridLayoutRootConfig(),\n\n // 🔴 PHẢI tắt cho lưới lồng. `setGridSize` làm gridster tự ghi style width/height lên CHÍNH nó,\n // sinh vòng lặp đo-rồi-ghi với ResizeObserver của khung ngoài (khung đổi → onResize xoá style →\n // setGridSize ghi lại) → lưới con co dần về 64x64px trong khung 868px.\n setGridSize: false,\n\n // khe 2px: khối con là các dòng thông tin của CÙNG một card, khe rộng làm chúng trông như card rời\n margin: 2,\n // Lưới lồng KHÔNG tự chừa lề — lề là của VỎ container (`containerPadding`), không phải của lưới.\n // Đặt ở vỏ thì ruột co lại đúng bằng phần còn lại, tay cầm resize của khối con luôn nằm trong tầm\n // chuột (người dùng chốt 28/08/2026: \"lưới cha có padding chứ ko phải con\").\n outerMargin: false,\n outerMarginBottom: 0,\n\n // hàng 16px cho bước kéo mịn, và sàn 1 hàng = 16px nên khối co được nhỏ hơn nhiều\n fixedRowHeight: 16,\n minRows: 1,\n minItemRows: 1,\n defaultItemCols: 2,\n defaultItemRows: 2,\n\n // 🔴 Tay cầm RIÊNG — CẤM dùng chung tên với lưới trang.\n // `checkDragHandleClass` trả `true` ở node ĐẦU TIÊN có `dragHandleClass`. Dùng chung một tên thì\n // lưới CHA cũng nhận ra tay cầm của khối con và nhấc luôn container.\n draggable: {\n ...gridLayoutRootConfig().draggable,\n dragHandleClass: 'libs-ui-grid-layout-drag-handle-child',\n },\n\n // 🔴 KÉO MÉP thì khối dưới ĐỨNG YÊN, chỉ khoảng trống giữa hai khối co giãn. Bật (kế thừa từ lưới\n // trang) thì mỗi cú kéo đẩy dồn cả cột xuống — người dùng chỉ muốn một khối to hơn một chút mà cả\n // card dài ra. `pushItems` vẫn giữ: nó lo việc KÉO THẢ đổi chỗ, khác việc đổi kích thước.\n pushResizeItems: false,\n\n // 🔴 Tắt tự cuộn khi kéo tới sát mép. Lib thấy chuột gần biên là cuộn lưới theo\n // (`scrollSensitivity`), nhưng lưới con nằm trong card có `overflow: hidden` — cuộn ở đây đẩy khối\n // con ra NGOÀI khung container rồi kẹt luôn ở đó.\n disableScrollHorizontal: true,\n disableScrollVertical: true,\n});\n\n/**\n * Cây rỗng dùng khi chưa có dữ liệu — mặt phẳng vẽ ra một lưới trống thay vì vỡ.\n * Xảy ra trong nhịp giữa lúc component dựng và lúc `init()` chạy.\n */\nexport const emptyRootNode = (): T_gridLayout_node => ({ id: 'root', x: 0, y: 0, cols: 12, rows: 0, children: [] });\n","import { Injectable } from '@angular/core';\nimport { uuid } from '@libs-ui/utils';\nimport { T_gridLayout_newNode, T_gridLayout_node } from './interfaces/grid-layout.interface';\n\n/**\n * Thao tác trên cây khối: tìm, thêm, xoá, dồn khít, chặn lồng cấp quá sâu.\n *\n * 🔴 NỘI BỘ thư viện — không xuất ra ngoài. Nơi dùng đi qua `LibsUiGridLayoutService`, ở đó mỗi\n * thao tác sửa bố cục vừa vẽ lại vừa bắn `outChange` đúng MỘT lần. Các hàm ở đây cố tình KHÔNG tự\n * vẽ lại: để chúng tự gọi thì mỗi thao tác vẽ hai lượt và bắn hai sự kiện (người dùng chốt\n * 28/08/2026: \"đặt đúng các điểm mà làm cho layout có thể thay đổi thôi\").\n */\n@Injectable()\nexport class LibsUiGridLayoutTreeService {\n findById(node: T_gridLayout_node, id: string): T_gridLayout_node | undefined {\n if (node.id === id) {\n return node;\n }\n\n for (const child of node.children ?? []) {\n const found = this.findById(child, id);\n\n if (found) {\n return found;\n }\n }\n\n return undefined;\n }\n\n findParent(node: T_gridLayout_node, id: string): T_gridLayout_node | undefined {\n for (const child of node.children ?? []) {\n if (child.id === id) {\n return node;\n }\n\n const found = this.findParent(child, id);\n\n if (found) {\n return found;\n }\n }\n\n return undefined;\n }\n\n /**\n * Thêm khối vào cuối một container. Thư viện tự sinh `id` và tự đặt `x` · `y` xuống hàng trống.\n *\n * @returns khối vừa tạo (kèm `id` vừa sinh), hoặc `undefined` khi không tìm thấy container.\n */\n addChild(root: T_gridLayout_node, parentId: string, item: T_gridLayout_newNode): T_gridLayout_node | undefined {\n const parent = this.findById(root, parentId);\n\n if (!parent) {\n return undefined;\n }\n\n parent.children = parent.children ?? [];\n // 🔴 Thư viện tự sinh `id`. Đây là mã máy dùng để tra cứu, không phải thứ người dùng nghĩ ra —\n // bắt họ tự đặt là mời họ tạo trùng, mà trùng id thì `findById` trả nhầm khối và cả cây hỏng\n // im lặng (người dùng chốt 28/08/2026).\n const node: T_gridLayout_node = { ...item, id: item.id ?? uuid(), x: 0, y: this.nextFreeRow(parent.children) };\n\n parent.children.push(node);\n\n // Trả về khối vừa tạo để nơi dùng biết `id` thư viện vừa sinh.\n return node;\n }\n\n /** Xoá một khối khỏi cây. Không cho xoá gốc. */\n removeById(root: T_gridLayout_node, id: string): boolean {\n if (root.id === id) {\n return false;\n }\n\n const parent = this.findParent(root, id);\n\n if (!parent?.children) {\n return false;\n }\n\n parent.children = parent.children.filter((item) => item.id !== id);\n\n return true;\n }\n\n /**\n * Chuyển một khối đơn thành CONTAINER: nội dung cũ trở thành khối con đầu tiên.\n *\n * Không mất dữ liệu — `data` của khối được mang theo xuống khối con.\n *\n * @returns `false` khi không tìm thấy khối, hoặc khối đã là container rồi.\n */\n toContainer(root: T_gridLayout_node, id: string, colCount: number): boolean {\n const node = this.findById(root, id);\n\n if (!node || (node.children?.length ?? 0) > 0) {\n return false;\n }\n\n node.children = [{ ...node, id: uuid(), x: 0, y: 0, cols: colCount, rows: 4, children: [] }];\n\n return true;\n }\n\n /**\n * Chuyển một CONTAINER về khối đơn: các khối con được NÂNG lên cấp trên, không bị xoá.\n *\n * @returns `false` khi không tìm thấy khối, hoặc khối vốn không phải container.\n */\n toSingle(root: T_gridLayout_node, id: string): boolean {\n const node = this.findById(root, id);\n\n if (!node || (node.children?.length ?? 0) === 0) {\n return false;\n }\n\n const parent = this.findParent(root, id);\n\n for (const child of node.children ?? []) {\n parent?.children?.push({ ...child, cols: node.cols, rows: 2 });\n }\n\n node.children = [];\n\n return true;\n }\n\n /**\n * Làm phẳng mọi container lồng vượt trần.\n *\n * 🔴 Cần thiết vì bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện. Một bản lưu cũ — sinh\n * trước khi có trần, hoặc do thao tác lỗi — vẫn nạp thẳng vào và hiện container lồng container.\n * Container vượt trần bị hạ thành khối thường, con của nó nâng lên cấp trên: KHÔNG mất dữ liệu.\n *\n * @returns số container đã làm phẳng\n */\n flattenOverDepthContainers(node: T_gridLayout_node, maxDepth: number): number {\n return this.walkFlatten(node, 0, maxDepth);\n }\n\n /**\n * Dồn khối khít lên trên theo thứ tự đọc, lấp hết chỗ trống.\n *\n * 🔴 KHÔNG sửa `node.rows` của container. Chiều cao container tính theo đơn vị hàng của lưới CHA,\n * còn `currentRow` đếm theo đơn vị hàng của lưới CON — trộn hai thang đo là container phình lên\n * gấp mấy lần.\n */\n compact(node: T_gridLayout_node, colCount: number): void {\n this.walkCompact(node, colCount);\n }\n\n private walkCompact(node: T_gridLayout_node, colCount: number): void {\n const children = node.children;\n\n if (!children?.length) {\n return;\n }\n\n const inReadingOrder = [...children].sort((a, b) => a.y - b.y || a.x - b.x);\n let currentRow = 0;\n let usedCols = 0;\n let tallestInRow = 0;\n\n for (const item of inReadingOrder) {\n const width = Math.min(item.cols, colCount);\n\n if (usedCols > 0 && usedCols + width > colCount) {\n currentRow += tallestInRow;\n usedCols = 0;\n tallestInRow = 0;\n }\n\n item.x = usedCols;\n item.y = currentRow;\n item.cols = width;\n usedCols += width;\n tallestInRow = Math.max(tallestInRow, item.rows);\n\n if ((item.children?.length ?? 0) > 0) {\n this.walkCompact(item, colCount);\n }\n }\n }\n\n private walkFlatten(node: T_gridLayout_node, containerDepth: number, maxDepth: number): number {\n const children = node.children;\n\n if (!children?.length) {\n return 0;\n }\n\n let fixedCount = 0;\n const result: Array<T_gridLayout_node> = [];\n\n for (const child of children) {\n const isContainer = (child.children?.length ?? 0) > 0;\n\n if (isContainer && containerDepth >= maxDepth) {\n fixedCount += 1;\n\n for (const item of child.children ?? []) {\n fixedCount += this.walkFlatten(item, containerDepth, maxDepth);\n result.push(item);\n }\n\n continue;\n }\n\n fixedCount += this.walkFlatten(child, isContainer ? containerDepth + 1 : containerDepth, maxDepth);\n result.push(child);\n }\n\n node.children = result;\n\n return fixedCount;\n }\n\n private nextFreeRow(children: Array<T_gridLayout_node>): number {\n return children.reduce((max, child) => Math.max(max, child.y + child.rows), 0);\n }\n}\n","import { ComponentRef, DestroyRef, Injectable, ViewContainerRef, inject, signal } from '@angular/core';\nimport { GridsterConfig, GridsterItem } from 'gridster18';\nimport { cloneDeep } from '@libs-ui/utils';\nimport { Subscription, take } from 'rxjs';\nimport { gridLayoutNestedConfig, gridLayoutRootConfig } from './defines/gridster-config.define';\nimport { LibsUiGridLayoutTreeService } from './tree.service';\nimport {\n E_gridLayout_mode_string,\n T_gridLayout_changeEvent,\n T_gridLayout_newNode,\n T_gridLayout_config,\n T_gridLayout_node,\n} from './interfaces/grid-layout.interface';\n\n/**\n * Dựng một mặt phẳng kéo thả và tự gắn component của nơi dùng lên từng khối.\n *\n * Nơi dùng chỉ cần đưa vào: loại component muốn dựng\n * (`nodeComponentType`) và cây dữ liệu (`data`). Toàn bộ việc vẽ lưới, kéo thả, đổi kích thước,\n * lồng container và dọn dẹp do thư viện lo.\n *\n * 🔴 Đây là service theo TỪNG mặt phẳng, KHÔNG `providedIn: 'root'`. Khai trong `providers` của\n * component dùng nó; hai mặt phẳng trên cùng một màn phải là hai thực thể riêng, dùng chung thì\n * `componentRefs` của mặt phẳng này bị mặt phẳng kia dọn mất.\n */\n@Injectable()\nexport class LibsUiGridLayoutService {\n // 🔴 TỰ TẠO, không `inject`. Nơi dùng chỉ phải viết `providers: [LibsUiGridLayoutService]` —\n // không phải biết bên trong thư viện còn service nào khác (người dùng chốt 28/08/2026).\n // `TreeService` không giữ trạng thái dùng chung nên mỗi mặt phẳng một bản là đúng.\n private readonly treeService = new LibsUiGridLayoutTreeService();\n /** Lượt tải component đang chờ, theo id khối — để huỷ khi khối bị gỡ giữa chừng. */\n private readonly pendingLoads = new Map<string, Subscription>();\n\n constructor() {\n // 🔴 Service khai trong `providers` của component nên Angular huỷ nó cùng component — thư viện\n // tự dọn ở đây, nơi dùng KHÔNG phải gọi `destroy()` trong `ngOnDestroy` (người dùng chốt\n // 28/08/2026). Bắt nhớ một bước dọn dẹp là kiểu API dễ quên, và quên thì rò rỉ bộ nhớ im lặng.\n inject(DestroyRef).onDestroy(() => this.destroy());\n }\n\n private config?: T_gridLayout_config;\n private readonly componentRefs = new Map<string, ComponentRef<unknown>>();\n\n private readonly rootNode = signal<T_gridLayout_node | undefined>(undefined);\n private readonly editMode = signal<boolean>(false);\n /** tăng mỗi lần cây đổi — component con đọc để biết phải tính lại */\n private readonly version = signal<number>(0);\n\n /**\n * Signal chỉ đọc để nơi dùng theo dõi.\n *\n * 🔴 Là THUỘC TÍNH, không phải getter. Getter trả signal thì chỗ đọc phải viết `Version()()` —\n * quên cặp ngoặc thứ hai là computed KHÔNG phụ thuộc vào nó, cây đổi mà lưới đứng im, và\n * TypeScript không hề báo lỗi (đo 28/08/2026: thêm khối không hiện, sắp gọn không nhúc nhích).\n */\n readonly Root = this.rootNode.asReadonly();\n readonly IsEditMode = this.editMode.asReadonly();\n /** tăng mỗi lần cây hoặc cấu hình đổi */\n readonly Version = this.version.asReadonly();\n\n /**\n * trần số cấp container lồng nhau — canvas đọc để biết có cho chuyển thành container không */\n private maxContainerDepth(): number {\n return this.config?.maxContainerDepth ?? 1;\n }\n\n /**\n * lề trong của container, px — canvas đọc để đặt padding lên vỏ container */\n private containerPadding(): number {\n return this.config?.containerPadding ?? 12;\n }\n\n /** Khởi tạo mặt phẳng. Gọi lại sẽ dọn sạch component cũ rồi dựng lại từ đầu. */\n init(config: T_gridLayout_config): void {\n this.destroy();\n this.config = config;\n // 🔴 Bố cục ĐÃ LƯU không đi qua luật chặn nào của giao diện: bản lưu cũ (sinh trước khi có trần,\n // hoặc do thao tác lỗi) vẫn mang container lồng container. Trần `maxContainerDepth` chỉ ẩn NÚT\n // trên canvas — nó không sửa dữ liệu, nên thiếu dòng này là vẽ ra đúng cây quá sâu đó.\n // Nơi dùng KHÔNG tự gọi được: `LibsUiGridLayoutTreeService` cố ý không xuất.\n this.treeService.flattenOverDepthContainers(config.data, this.maxContainerDepth());\n this.assignOverlapLayers(config.data);\n // 🔴 Nhân bản như `refresh()`: `init()` lại (đổi chế độ, bật/tắt chồng khối) trên CÙNG object cây\n // thì `@for` không dựng lại `gridster-item`, nên `layerIndex` vừa gán không tới `$item` và khối\n // vẫn không đè nhau được (đo 28/08/2026: `item.layerIndex` = 1|2|3|4|7 mà `$item.layerIndex`\n // toàn `undefined`).\n this.rootNode.set(this.shallowCloneTree(config.data));\n this.editMode.set(config.isEditMode ?? false);\n this.version.update((v) => v + 1);\n }\n\n setEditMode(value: boolean): void {\n this.editMode.set(value);\n // 🔴 PHẢI bơm `version`: `gridsterOptions()` đọc `editMode` để bật/tắt kéo–thả, mà computed\n // `gridOptions` bên canvas chỉ chạy lại khi `Version` đổi. Thiếu dòng này thì đổi chế độ xong\n // gridster vẫn giữ options cũ — chuyển sang XEM mà khối vẫn kéo được.\n this.version.update((v) => v + 1);\n }\n\n /**\n * Bật/tắt cho khối chồng lên nhau — KHÔNG dựng lại mặt phẳng.\n *\n * Trước đây nơi dùng phải gọi `init()` lại để đổi cờ này, mà `init()` huỷ sạch rồi dựng lại mọi\n * component nội dung — lãng phí, và người dùng thấy màn chớp (người dùng chốt 28/08/2026).\n */\n setAllowOverlap(value: boolean): void {\n if (!this.config) {\n return;\n }\n\n this.config = { ...this.config, allowOverlap: value };\n\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n // 🔴 Gán lớp vào CÂY ĐANG VẼ (`rootNode`), KHÔNG phải `config.data`.\n // `init()` đã clone `config.data` sang `rootNode` nên hai object KHÁC nhau; gán vào `config.data`\n // thì `refresh()` clone lại từ `rootNode` — lớp vừa gán không tới `gridster-item` nào, `z-index`\n // của mọi khối đứng ở `1` và khối nào vẽ sau thì nằm trên: chồng khối \"lúc được lúc không\"\n // (đo 04/09/2026: `item.layerIndex` undefined, `getLayerIndex()` = 0 cho cả 8 khối).\n this.assignOverlapLayers(root);\n // Thay tham chiếu cây để `layerIndex` vừa gán tới được `$item` của gridster; component nội dung\n // KHÔNG bị dựng lại vì `attachNode` nhận ra id cũ và chỉ `setInput`.\n this.refresh();\n }\n\n /**\n *\n * Cấu hình gridster cho một cấp lưới.\n *\n * @param depth 0 = lưới cấp trang, ≥ 1 = lưới lồng trong container\n */\n private buildGridsterOptions(depth: number, itemChangeCallback?: () => void): GridsterConfig {\n const base = depth === 0 ? gridLayoutRootConfig() : gridLayoutNestedConfig();\n const config = this.config;\n\n if (!config) {\n return base;\n }\n\n const isFreeMode = config.mode === E_gridLayout_mode_string.free;\n const canEdit = this.editMode();\n const canOverlap = isFreeMode || (config.allowOverlap ?? false);\n\n return {\n ...base,\n ...(config.cols ? { minCols: config.cols, maxCols: config.cols, maxItemCols: config.cols } : {}),\n ...(config.rowHeight && depth === 0 ? { fixedRowHeight: config.rowHeight } : {}),\n // Khe và chiều cao hàng khác nhau theo cấp: lưới trang thoáng, lưới lồng khít.\n ...(depth === 0 && config.margin !== undefined ? { margin: config.margin } : {}),\n ...(depth > 0 && config.nestedMargin !== undefined ? { margin: config.nestedMargin } : {}),\n ...(depth > 0 && config.nestedRowHeight !== undefined ? { fixedRowHeight: config.nestedRowHeight } : {}),\n ...(depth === 0 && config.outerMargin !== undefined ? { outerMargin: config.outerMargin } : {}),\n ...(depth === 0 && config.outerMarginBottom !== undefined ? { outerMarginBottom: config.outerMarginBottom } : {}),\n ...(config.minItemRows !== undefined ? { minItemRows: config.minItemRows } : {}),\n ...(config.defaultItemCols !== undefined ? { defaultItemCols: config.defaultItemCols } : {}),\n ...(config.defaultItemRows !== undefined ? { defaultItemRows: config.defaultItemRows } : {}),\n\n // 🔴 Chế độ XEM phải TẮT hẳn kéo và đổi kích thước.\n // `base` luôn để `enabled: true`; không ghi đè theo `editMode` thì người xem vẫn kéo được khối\n // và đổi bố cục của người khác (người dùng báo 28/08/2026: \"đang xem mà vẫn kéo thả thay đổi\n // vị trí và thêm khối được\").\n draggable: { ...base.draggable, enabled: canEdit },\n resizable: { ...base.resizable, enabled: canEdit },\n\n // Chế độ tự do LUÔN cho chồng; chế độ lưới thì theo cờ của nơi dùng.\n allowMultiLayer: canOverlap,\n // 🔴 Bật `allowMultiLayer` MỘT MÌNH không đủ. Mã lib so `layerIndex` của hai khối: KHÁC nhau\n // thì cho đè, GIỐNG nhau vẫn báo va chạm. Khối không khai `layerIndex` đều rơi về\n // `defaultLayerIndex` — tức cùng lớp, và vẫn bị đẩy nhau như lưới thường (người dùng báo\n // 28/08/2026: \"bật chồng khối nhưng khi kéo thì các khối vẫn di chuyển theo\").\n // Cho chồng thì phải TẮT đẩy khối, nếu không khối bị dạt đi trước khi kịp đè lên nhau.\n ...(canOverlap ? { pushItems: false, pushResizeItems: false, swap: false, swapWhileDragging: false } : {}),\n\n itemChangeCallback: (item: GridsterItem) => {\n // 🔴 Khối vừa thao tác phải lên LỚP TRÊN CÙNG.\n // `layerIndex` gán một lần theo thứ tự cây lúc khởi tạo, nên khối kéo lên chỉ nổi TRONG LÚC\n // kéo (nhờ `z-index: 30` của lớp `gridster-item-moving`); thả tay ra là về lớp cũ và bị khối\n // đứng sau trong cây đè ngược lên (người dùng báo 28/08/2026, đo được: kéo z=30, thả về\n // z=10 trong khi hai khối kế bên đang z=11 và z=12).\n if (canOverlap) {\n this.raiseToTopLayer(item);\n }\n\n this.version.update((v) => v + 1);\n itemChangeCallback?.();\n },\n };\n }\n\n /**\n *\n * Gắn component của nơi dùng lên một khối.\n *\n * @param host chỗ gắn RIÊNG của ô đó — mỗi khối một `ViewContainerRef`, dùng chung một cái thì\n * mọi component bị dồn hết vào một ô.\n */\n private attachNode(node: T_gridLayout_node, depth: number, host: ViewContainerRef): void {\n const config = this.config;\n\n if (!config) {\n return;\n }\n\n const existing = this.componentRefs.get(node.id);\n\n if (existing) {\n this.applyInputs(existing, node, depth);\n\n return;\n }\n\n // Khối tự khai thì hỏi nó; không thì hỏi hàm phân giải chung. Cả hai đều nhận `node` để đọc\n // được `data.type` mà quyết định trả component nào.\n const stream = (node.getComponentOutlet ?? config.getComponentOutlet)?.(node);\n\n if (!stream) {\n return;\n }\n\n // 🔴 Huỷ lượt tải CŨ của đúng khối này trước khi mở lượt mới.\n // Khối bị gỡ rồi gắn lại (đổi bố cục, sắp gọn) trong lúc `import()` chưa xong thì lượt cũ vẫn\n // chạy tiếp và dựng component vào một `ViewContainerRef` đã chết.\n this.pendingLoads.get(node.id)?.unsubscribe();\n\n const sub = stream.pipe(take(1)).subscribe((componentType) => {\n this.pendingLoads.delete(node.id);\n\n // Khối có thể đã bị xoá trong lúc chờ tải — dựng vào đây là rò rỉ.\n if (!this.treeService.findById(this.rootNode() ?? node, node.id)) {\n return;\n }\n\n const ref = host.createComponent(componentType);\n\n this.applyInputs(ref, node, depth);\n this.componentRefs.set(node.id, ref);\n });\n\n this.pendingLoads.set(node.id, sub);\n }\n\n /**\n * Gỡ component của một khối và huỷ nó. */\n private detachNode(nodeId: string): void {\n // Khối bị gỡ khi component của nó còn đang tải — phải huỷ lượt tải, không thì nó dựng vào một\n // `ViewContainerRef` đã chết.\n this.pendingLoads.get(nodeId)?.unsubscribe();\n this.pendingLoads.delete(nodeId);\n\n const ref = this.componentRefs.get(nodeId);\n\n if (!ref) {\n return;\n }\n\n ref.destroy();\n this.componentRefs.delete(nodeId);\n }\n\n private destroy(): void {\n for (const sub of this.pendingLoads.values()) {\n sub.unsubscribe();\n }\n\n for (const ref of this.componentRefs.values()) {\n ref.destroy();\n }\n\n this.pendingLoads.clear();\n this.componentRefs.clear();\n this.config = undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────────────────\n // Nhóm hàm cho nơi dùng CHỦ ĐỘNG gọi — không phải chờ người dùng bấm nút trên khối.\n // Sửa cây thì dùng thẳng `TreeService` rồi gọi `refresh()` — xem demo trong core-ui.\n // ─────────────────────────────────────────────────────────────────────────────────────────\n\n /**\n * Báo cho service biết cây vừa đổi từ bên ngoài (thêm/xoá khối, sắp gọn, nạp bố cục khác).\n *\n * 🔴 PHẢI thay THAM CHIẾU của node gốc, không chỉ bơm `version`.\n * `@for … track item.id` giữ nguyên object khi id không đổi, nên `<gridster-item [item]=\"…\">` vẫn\n * nhận đúng object cũ và gridster không hề biết `x/y/cols/rows/layerIndex` vừa bị sửa. Bơm mỗi\n * `version` thì computed chạy lại nhưng trả về CÙNG mảng cũ — lưới đứng im (đo 28/08/2026: bấm\n * \"Sắp gọn\" cây đã dồn khít mà màn hình không nhúc nhích; bật chồng khối mà `$item.layerIndex`\n * vẫn trống).\n *\n * Nhân bản NÔNG cả node gốc và danh sách con là đủ: mảng mới → `@for` dựng lại item, object con\n * mới → gridster đọc lại toàn bộ toạ độ.\n */\n refresh(event?: T_gridLayout_changeEvent): void {\n const root = event?.root ?? this.rootNode();\n\n if (!root) {\n this.version.update((v) => v + 1);\n\n return;\n }\n\n if (this.config) {\n this.config = { ...this.config, data: root };\n }\n\n this.rootNode.set(this.shallowCloneTree(root));\n this.version.update((v) => v + 1);\n }\n\n /** Nhân bản nông theo cả chiều sâu: mỗi node và mảng `children` thành tham chiếu mới. */\n /**\n * Nhân bản SÂU cả cây — dùng cho `exportLayout()`.\n *\n * 🔴 BỎ `getComponentOutlet` khỏi bản sao: nó là một HÀM, không tuần tự hoá được nên gửi xuống\n * backend là hỏng (`JSON.stringify` nuốt mất, `structuredClone` ném lỗi). Nạp lại thì hàm phân\n * giải chung của cấu hình lo — component suy ra từ `data.type`, không cần lưu.\n */\n private deepCloneTree(node: T_gridLayout_node): T_gridLayout_node {\n const copy: T_gridLayout_node = { ...node };\n\n // Cắt hàm phân giải — xem chú thích trên.\n delete copy.getComponentOutlet;\n\n const { children, data, ...rest } = copy;\n\n return {\n ...rest,\n ...(data === undefined ? {} : { data: cloneDeep(data) }),\n ...(children ? { children: children.map((child) => this.deepCloneTree(child)) } : {}),\n };\n }\n\n private shallowCloneTree(node: T_gridLayout_node): T_gridLayout_node {\n if (!node.children?.length) {\n return { ...node };\n }\n\n return { ...node, children: node.children.map((child) => this.shallowCloneTree(child)) };\n }\n\n /**\n * Gán `layerIndex` khác nhau cho từng khối khi bật chồng khối.\n *\n * 🔴 `allowMultiLayer: true` MỘT MÌNH không cho khối đè nhau. Mã lib so `layerIndex` của hai khối:\n * KHÁC nhau thì cho đè, GIỐNG nhau vẫn báo va chạm. Khối không khai `layerIndex` đều rơi về\n * `defaultLayerIndex` — tức CÙNG lớp, nên kéo vào nhau là bị chặn y như lưới thường (người dùng\n * báo 28/08/2026: \"bật chồng khối nhưng khi kéo thì các khối vẫn di chuyển theo\").\n *\n * Nơi dùng tự khai `layerIndex` thì giữ nguyên; ai không khai thì thư viện xếp mỗi khối một lớp\n * theo thứ tự, đủ để mọi cặp đều khác lớp.\n */\n private assignOverlapLayers(root: T_gridLayout_node): void {\n const config = this.config;\n const canOverlap = config?.mode === E_gridLayout_mode_string.free || (config?.allowOverlap ?? false);\n\n if (!canOverlap) {\n return;\n }\n\n let layer = 0;\n const walk = (node: T_gridLayout_node): void => {\n for (const child of node.children ?? []) {\n if (child.layerIndex === undefined) {\n layer += 1;\n child.layerIndex = layer;\n }\n\n walk(child);\n }\n };\n\n walk(root);\n\n }\n\n /** Đưa một khối lên trên tất cả: lớp của nó = lớp lớn nhất đang có + 1. */\n private raiseToTopLayer(item: GridsterItem): void {\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n let topLayer = 0;\n const walk = (node: T_gridLayout_node): void => {\n for (const child of node.children ?? []) {\n topLayer = Math.max(topLayer, child.layerIndex ?? 0);\n walk(child);\n }\n };\n\n walk(root);\n\n // `item` gridster trả về CHÍNH là object node của cây (truyền thẳng qua `[item]`), nên gán vào\n // đây là cây cũng đổi theo.\n const node = item as unknown as T_gridLayout_node;\n\n if (node.layerIndex === topLayer) {\n\n return;\n }\n\n node.layerIndex = topLayer + 1;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────────────────\n // SỬA CÂY — thư viện đã giữ cây nên bạn KHÔNG phải truyền nó vào.\n // Mọi hàm dưới đây tự vẽ lại; không cần gọi `refresh()`.\n // ─────────────────────────────────────────────────────────────────────────────────────────\n\n /**\n * Thêm một khối.\n *\n * @param item khối mới — KHÔNG cần `id` (thư viện sinh) và `x`/`y` (tự đặt xuống hàng trống).\n * @param parentId container muốn thêm vào; bỏ trống thì thêm vào mặt phẳng gốc.\n * @returns khối vừa tạo (kèm `id` vừa sinh), hoặc `undefined` khi không tìm thấy container.\n */\n addBlock(item: T_gridLayout_newNode, parentId?: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n const added = root ? this.treeService.addChild(root, parentId ?? root.id, item) : undefined;\n\n if (added) {\n this.refresh();\n }\n\n return added;\n }\n\n /** Xoá một khối. Xoá container là xoá cả ruột. Trả `false` khi không xoá được (vd khối gốc). */\n removeBlock(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.removeById(root, id) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Biến khối đơn thành CONTAINER — nội dung cũ thành khối con đầu tiên, không mất dữ liệu. */\n toContainer(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.toContainer(root, id, this.config?.cols ?? 12) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Đưa CONTAINER về khối đơn — khối con được nâng lên cấp trên, không bị xoá. */\n toSingle(id: string): boolean {\n const root = this.rootNode();\n const done = root ? this.treeService.toSingle(root, id) : false;\n\n if (done) {\n this.refresh();\n }\n\n return done;\n }\n\n /** Dồn khối khít lên trên, lấp hết chỗ trống. Đệ quy vào container. */\n compact(): void {\n const root = this.rootNode();\n\n if (!root) {\n return;\n }\n\n this.treeService.compact(root, this.config?.cols ?? 12);\n this.refresh();\n }\n\n /**\n * Bố cục HIỆN TẠI, đã cắt mọi tham chiếu — gửi thẳng xuống backend được.\n *\n * Dùng khi bấm nút Lưu. Khác `Root()` ở chỗ đây là bản SAO: nơi dùng có sửa gì trên kết quả cũng\n * không đụng tới cây mà thư viện đang vẽ.\n *\n * @returns `undefined` khi mặt phẳng chưa `init()`.\n */\n exportLayout(): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.deepCloneTree(root) : undefined;\n }\n\n /** Tìm một khối theo id. */\n findBlock(id: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.treeService.findById(root, id) : undefined;\n }\n\n /** Tìm khối cha trực tiếp của một khối. */\n findParentBlock(id: string): T_gridLayout_node | undefined {\n const root = this.rootNode();\n\n return root ? this.treeService.findParent(root, id) : undefined;\n }\n\n /**\n * Cổng DUY NHẤT cho canvas của thư viện. Nơi dùng KHÔNG gọi tới đây.\n *\n * Mọi thứ canvas cần đều là `private` để không lọt ra API công khai; gom vào một getter theo đúng\n * khuôn `FunctionsControl` của bộ quy ước, thay vì để rải rác hàm public mà người ngoài tưởng\n * mình phải gọi (người dùng chốt 28/08/2026).\n */\n get FunctionsControl() {\n return {\n maxContainerDepth: () => this.maxContainerDepth(),\n containerPadding: () => this.containerPadding(),\n gridsterOptions: (depth: number, cb?: () => void) => this.buildGridsterOptions(depth, cb),\n attachNode: (node: T_gridLayout_node, depth: number, host: ViewContainerRef) => this.attachNode(node, depth, host),\n detachNode: (nodeId: string) => this.detachNode(nodeId),\n };\n }\n\n private applyInputs(ref: ComponentRef<unknown>, node: T_gridLayout_node, depth: number): void {\n ref.setInput('data', node.data);\n ref.setInput('node', node);\n ref.setInput('isEditMode', this.editMode());\n ref.setInput('depth', depth);\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n OnDestroy,\n ViewContainerRef,\n computed,\n inject,\n input,\n output,\n effect,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';\nimport { GridsterComponent, GridsterModule } from 'gridster18';\nimport { emptyRootNode } from '../defines/gridster-config.define';\nimport { LibsUiGridLayoutService } from '../grid-layout.service';\nimport {\n T_gridLayout_actionEvent,\n T_gridLayout_addEvent,\n T_gridLayout_changeEvent,\n T_gridLayout_newNode,\n T_gridLayout_node,\n} from '../interfaces/grid-layout.interface';\n\n/**\n * Mặt phẳng kéo thả. Đệ quy: khối có `children` thì ruột nó lại là một mặt phẳng nữa.\n *\n * Nơi dùng KHÔNG dựng component này trực tiếp cho từng khối — chỉ đặt MỘT thẻ ở gốc và truyền\n * `nodeComponentType` qua `LibsUiGridLayoutService.init()`. Thư viện tự gắn component cho mọi khối.\n */\n@Component({\n selector: 'libs_ui-services-grid_layout-canvas',\n standalone: true,\n imports: [GridsterModule, LibsUiComponentsButtonsButtonComponent],\n templateUrl: './grid-layout-canvas.component.html',\n styleUrl: './grid-layout-canvas.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LibsUiGridLayoutCanvasComponent implements OnDestroy {\n /**\n * @internal Chỉ mặt phẳng LỒNG dùng — thư viện tự truyền khi vẽ ruột container.\n *\n * Nơi dùng KHÔNG truyền: mặt phẳng gốc đọc cây từ service (đã đưa vào qua `init()`), truyền thêm\n * ở đây là khai hai lần cùng một thứ (người dùng chốt 28/08/2026).\n */\n readonly node = input<T_gridLayout_node>();\n /** @internal Chỉ mặt phẳng LỒNG dùng — thư viện tự truyền. */\n readonly depth = input<number>(0);\n\n /**\n * Bố cục vừa đổi do NGƯỜI DÙNG kéo hoặc đổi kích thước khối.\n *\n * Nơi dùng tự gọi `addBlock` · `removeBlock` · `compact` thì KHÔNG bắn — họ vừa gọi thì đã biết,\n * bắn ngược lại là thừa (người dùng chốt 28/08/2026).\n */\n readonly outChange = output<T_gridLayout_changeEvent>();\n /**\n * Người dùng bấm nút XOÁ trên một khối. Thư viện CHƯA xoá — gọi `event.confirm()` để xoá thật.\n * Cần hỏi trước thì hỏi xong mới gọi; không cho phép thì đừng gọi.\n */\n readonly outRemoveNode = output<T_gridLayout_actionEvent>();\n /**\n * Người dùng bấm nút THÊM trên một container. Thư viện KHÔNG tự thêm — nó không biết bạn có\n * những loại khối nào. Mở menu chọn loại rồi gọi `event.confirm(item)` với khối bạn muốn thêm.\n */\n readonly outAddBlockInside = output<T_gridLayout_addEvent>();\n /** Người dùng bấm nút GỘP/TÁCH. Thư viện chưa làm gì — gọi `event.confirm()` để thực hiện. */\n readonly outToggleType = output<T_gridLayout_actionEvent>();\n\n\n private readonly gridsterRef = viewChild(GridsterComponent);\n /** mỗi ô một chỗ gắn riêng — cùng thứ tự với `children()` */\n private readonly itemHosts = viewChildren('itemHost', { read: ViewContainerRef });\n\n /** Sáu chấm của tay cầm kéo — chỉ để `@for` dựng đủ 6 thẻ, giá trị không dùng tới. */\n protected readonly dragBarDots = [0, 1, 2, 3, 4, 5];\n\n private readonly service = inject(LibsUiGridLayoutService);\n\n /**\n * Node THẬT của mặt phẳng này.\n *\n * 🔴 Mặt phẳng GỐC (depth 0) đọc cây từ SERVICE, không dùng input.\n * Nơi dùng thường sửa cây TẠI CHỖ (`treeService.compact(tree)`) rồi gọi `refresh()`, nên signal\n * `root()` của họ giữ nguyên tham chiếu và input `node` không hề đổi — `@for` không dựng lại\n * `gridster-item`, lưới đứng im dù dữ liệu đã khác (đo 28/08/2026: bấm \"Sắp gọn\" không tác dụng).\n * `refresh()` của service thay tham chiếu cây, nên đọc từ đó mới thấy thay đổi.\n *\n * Mặt phẳng LỒNG vẫn dùng input: nó nhận node con từ mặt phẳng cha, vốn đã là object mới.\n */\n protected readonly currentNode = computed(() => {\n this.service.Version();\n\n if (this.depth() > 0) {\n return this.node() ?? emptyRootNode();\n }\n\n return this.service.Root() ?? emptyRootNode();\n });\n\n protected readonly children = computed(() => this.currentNode().children ?? []);\n\n protected readonly isNestedCanvas = computed(() => this.depth() > 0);\n\n /** trần lồng container — khối đã chạm trần thì không cho chuyển thành container */\n protected readonly maxContainerDepth = computed(() => this.service.FunctionsControl.maxContainerDepth());\n\n /**\n * Lề trong của container, px.\n *\n * 🔴 Đặt trên VỎ container, không đặt vào lưới con. Lưới con giữ nguyên `margin: 2` như cũ; lề\n * này chỉ co ruột lại khỏi biên vỏ, nhờ đó tay cầm đổi kích thước của khối con luôn nằm trong tầm\n * chuột (người dùng chốt 28/08/2026).\n */\n protected readonly containerPadding = computed(() => `${this.service.FunctionsControl.containerPadding()}px`);\n\n /** Dải kéo chỉ hiện ở chế độ sửa — chế độ xem không kéo được nên hiện dải là gây nhầm. */\n protected readonly isEditMode = computed(() => this.service.IsEditMode());\n\n protected readonly gridOptions = computed(() => {\n // Đọc `Version` để `init()` lại (đổi chế độ, bật/tắt chồng khối) sinh ra options MỚI —\n // gridster chỉ áp dụng cấu hình khi tham chiếu `options` đổi.\n this.service.Version();\n\n return this.service.FunctionsControl.gridsterOptions(this.depth(), () => this.outChange.emit({ root: this.currentNode() }));\n });\n\n constructor() {\n // Gắn component của nơi dùng vào từng ô, và gắn LẠI mỗi khi cây đổi.\n // Dùng effect vì `itemHosts()` chỉ có giá trị sau khi Angular dựng xong @for.\n effect(() => {\n const hosts = this.itemHosts();\n const items = this.children();\n\n items.forEach((item, i) => {\n const host = hosts[i];\n\n if (!host) {\n return;\n }\n\n // Khối có con là CONTAINER: ruột nó do mặt phẳng lồng vẽ, không gắn component nội dung.\n if ((item.children?.length ?? 0) > 0) {\n return;\n }\n\n this.service.FunctionsControl.attachNode(item, this.depth() + 1, host);\n });\n });\n }\n\n ngOnDestroy(): void {\n for (const item of this.children()) {\n this.service.FunctionsControl.detachNode(item.id);\n }\n }\n\n /** Vẽ lại lưới — gọi khi khung ngoài đổi kích thước hoặc cây vừa đổi diện rộng. */\n get FunctionControl() {\n return {\n veLaiLuoi: () => this.gridsterRef()?.optionsChanged(),\n };\n }\n\n protected handlerTrackNode(_index: number, item: T_gridLayout_node): string {\n return item.id;\n }\n\n /**\n * 🔴 Chặn `mousedown` nổi lên lưới CHA khi thao tác trong lưới con.\n * Không chặn thì cả hai lưới cùng nhận một cú bấm: kéo khối con là nhấc luôn container.\n */\n /**\n * Chặn `mousedown` của khối trong lưới LỒNG nổi lên lưới cha.\n *\n * Chỉ chặn ở lưới lồng: lưới cấp trang không có cha nào để chặn, và chặn ở đó sẽ nuốt luôn thao\n * tác của chính nó.\n */\n /**\n * 🔴 Ba handler dưới đây PHẢI `stopPropagation`.\n * Nút nằm trong vùng mang `dragHandleClass`, không chặn thì cú bấm bị gridster hiểu là bắt đầu kéo\n * và `delayStart: 160` nuốt luôn `click` — người dùng thấy như nút chết.\n */\n protected handlerRemove(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outRemoveNode.emit({ nodeId: node.id, node, confirm: () => this.service.removeBlock(node.id) });\n }\n\n protected handlerAddInside(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outAddBlockInside.emit({\n nodeId: node.id,\n node,\n confirm: (item: T_gridLayout_newNode) => this.service.addBlock(item, node.id),\n });\n }\n\n protected handlerToggleType(event: Event, node: T_gridLayout_node): void {\n event.stopPropagation();\n event.preventDefault();\n this.outToggleType.emit({\n nodeId: node.id,\n node,\n // Gộp hay tách suy ra từ chính khối: đang là container thì tách, không thì gộp.\n confirm: () => (this.isContainer(node) ? this.service.toSingle(node.id) : this.service.toContainer(node.id)),\n });\n }\n\n /** khối này có phải container không (có khối con) */\n protected isContainer(item: T_gridLayout_node): boolean {\n return (item.children?.length ?? 0) > 0;\n }\n\n /** container đã chạm trần lồng thì không cho thêm khối vào trong nữa */\n protected canAddInside(item: T_gridLayout_node): boolean {\n return this.isContainer(item) && this.depth() < this.maxContainerDepth();\n }\n\n /** khối đơn ở cấp chưa chạm trần mới được chuyển thành container */\n protected canToggleType(item: T_gridLayout_node): boolean {\n if (this.isContainer(item)) {\n return true;\n }\n\n return this.depth() < this.maxContainerDepth();\n }\n\n protected handlerBlockParentDrag(event: Event): void {\n if (!this.isNestedCanvas()) {\n return;\n }\n\n event.stopPropagation();\n }\n\n protected handlerMouseDownTrongLuoi(event: Event): void {\n if (this.depth() === 0) {\n return;\n }\n\n event.stopPropagation();\n }\n}\n","<!-- 🔴 `relative` là BẮT BUỘC, CẤM bỏ.\n gridster đổi vị trí chuột thành ô lưới bằng `e.clientY + (el.scrollTop - el.offsetTop)` — công\n thức đó chỉ đúng khi `offsetParent` của <gridster> CHÍNH LÀ khối cuộn này. Thiếu `relative` thì\n `offsetParent` nhảy lên khối bao ngoài: `offsetTop` trả 16 trong khi lệch thật là 65 → gridster\n tính ô sai 49px, ô chờ đặt hiện lệch khỏi con trỏ nên kéo thả không đổi được vị trí, và kéo mép\n cũng tính sai điểm dừng. -->\n<div\n class=\"libs-ui-grid-layout-scroll-area relative h-full min-h-0 w-full min-w-0\"\n [class.overflow-y-auto]=\"!isNestedCanvas()\"\n (mousedown)=\"handlerMouseDownTrongLuoi($event)\">\n <gridster class=\"h-full w-full\" [options]=\"gridOptions()\">\n @for (item of children(); track item.id) {\n <!-- 🔴 Chặn `mousedown` tại ĐÂY cho lưới lồng — CẤM bỏ và CẤM chuyển sang chỗ khác.\n `ignoreContentClass` một mình KHÔNG đủ: `delayStart: 160` làm MỖI lưới lên lịch\n `dragStart` bằng `setTimeout` ngay tại `mousedown`, còn `stopPropagation` mà lib gọi bên\n trong `dragStart` chạy sau 160ms nên quá muộn — lưới CHA đã kịp nhận (đo 28/08/2026: kéo\n dải khối con, chuỗi class duyệt lên ĐÚNG mà container vẫn nhảy 0,0 → 0,1).\n Gắn ở `gridster-item` là đúng biên: lưới con nghe trên chính phần tử này nên đã nhận xong,\n lưới cha ở ngoài bị chặn. -->\n <gridster-item\n [item]=\"item\"\n (mousedown)=\"handlerBlockParentDrag($event)\">\n <!-- 🔴 Vỏ này mang `dragHandleClass` — CẤM bỏ.\n `ignoreContent: true` bắt gridster CHỈ cho kéo khi chỗ bấm nằm dưới một phần tử có\n `dragHandleClass`. Không có vỏ này thì component của nơi dùng (thư viện không kiểm soát\n được class của nó) sẽ không có tay cầm nào, và KHÔNG khối nào kéo được — đo 28/08/2026:\n kéo 320px, toạ độ khối giữ nguyên x=3,y=0.\n Tên class theo cấp: lưới trang và lưới lồng dùng hai tên KHÁC nhau, nếu không lưới cha\n cũng nhận ra tay cầm của khối con và nhấc luôn container. -->\n <!-- 🔴 Vỏ KHÔNG mang `dragHandleClass` — CẤM thêm lại.\n Kéo chỉ được phép bắt đầu từ DẢI XANH (người dùng chốt 28/08/2026: \"phải hover vào vùng\n màu xanh thì mới kéo thả được cho đồng nhất\"). Cho cả vỏ làm tay cầm thì bấm đâu cũng\n kéo, và khối con nằm trong container sẽ nhấc luôn container vì lưới cha duyệt lên gặp\n tay cầm của vỏ container trước.\n Vỏ khối con vẫn giữ class CHẶN để lưới cha dừng đúng ở biên. -->\n <div\n class=\"libs-ui-grid-layout-block-shell group relative h-full w-full min-w-0\"\n [class.libs-ui-grid-layout-block-parent-drag]=\"isNestedCanvas()\">\n <!-- Dải kéo: hiện khi rê chuột vào khối, ba chấm là dấu hiệu kéo quen thuộc.\n Người dùng cần một chỗ bám RÕ RÀNG thay vì đoán xem bấm đâu thì kéo được\n (chốt 28/08/2026, theo đúng dải đang dùng ở màn Customer 360 của mobio-web). -->\n @if (isEditMode()) {\n <!-- 🔴 Dải PHẢI mang tay cầm ĐÚNG CẤP của nó. Dải nhận chuột (`pointer-events: auto`),\n nên nếu không mang tay cầm thì `checkDragHandleClass` duyệt lên gặp tay cầm của\n container và nhấc container thay vì khối con (đo 28/08/2026: kéo dải khối con,\n container nhảy 0,0 → 0,1 còn khối con đứng im).\n 🔴 Dải CHỈ mang tay cầm, CẤM mang thêm class chặn: `checkDragHandleClass` xét hai\n class đó trên CÙNG một node nên để chung là kéo hỏng (đo 28/08/2026: bấm dải khối\n con kéo 140px, khối đứng im). Việc chặn lưới cha do VỎ KHỐI lo. -->\n <div\n class=\"libs-ui-grid-layout-drag-bar\"\n [class.libs-ui-grid-layout-drag-bar-child]=\"isNestedCanvas()\"\n [class.libs-ui-grid-layout-drag-handle]=\"!isNestedCanvas()\"\n [class.libs-ui-grid-layout-drag-handle-child]=\"isNestedCanvas()\">\n <span class=\"libs-ui-grid-layout-drag-bar-dots\">\n @for (dot of dragBarDots; track dot) {\n <span class=\"libs-ui-grid-layout-drag-bar-dot\"></span>\n }\n </span>\n </div>\n }\n\n <!-- Khung chứa component của nơi dùng.\n 🔴 PHẢI có khung thật (không phải `ng-container` trống): nó lo hộ nơi dùng phần lấp đầy\n ô và viền báo chế độ sửa. Không có khung thì mỗi component nội dung lại phải tự viết\n `:host { width/height: 100% }` + viền đứt — đó là việc của thư viện, không phải của\n người dùng (người dùng chốt 28/08/2026).\n Mỗi khối một ViewContainerRef riêng nên component nằm đúng ô của nó. -->\n <div\n class=\"libs-ui-grid-layout-content-frame\"\n [class.libs-ui-grid-layout-content-frame-edit]=\"isEditMode() && !isContainer(item)\"\n [class.libs-ui-grid-layout-content-frame-empty]=\"isContainer(item)\">\n <ng-container #itemHost />\n </div>\n\n <!-- Dấu hiệu CONTAINER: nhãn góc trên-phải + viền đứt bao ruột. Không có dấu hiệu thì\n người dùng không biết khối nào chứa được khối khác (chốt 28/08/2026, theo đúng cách\n màn Customer 360 của mobio-web đang làm). -->\n @if (isEditMode() && isContainer(item)) {\n <div class=\"libs-ui-grid-layout-container-label\">Khối ghép</div>\n <div class=\"libs-ui-grid-layout-container-border\"></div>\n }\n\n <!-- Thanh công cụ: hiện khi rê chuột vào khối.\n 🔴 Dùng `libs_ui-components-buttons-button` — CẤM tự dựng thẻ `<button>`.\n Component này đã có sẵn kiểu nút, cỡ nút và bong bóng chú thích theo đúng bộ giao diện\n của sản phẩm; tự dựng là mỗi nơi một kiểu và mất luôn tooltip. -->\n @if (isEditMode()) {\n <div\n class=\"libs-ui-grid-layout-toolbar\"\n [class.libs-ui-grid-layout-toolbar-child]=\"isNestedCanvas()\">\n @if (canAddInside(item)) {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"'libs-ui-icon-add'\"\n [popover]=\"{ config: { content: 'Thêm khối vào trong', zIndex: 1300 } }\"\n (outClick)=\"handlerAddInside($event, item)\" />\n }\n @if (canToggleType(item)) {\n <libs_ui-components-buttons-button\n [type]=\"'button-third'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"isContainer(item) ? 'libs-ui-icon-split-cell' : 'libs-ui-icon-merge-cell'\"\n [popover]=\"{ config: { content: isContainer(item) ? 'Đưa về khối đơn' : 'Chuyển thành khối ghép', zIndex: 1300 } }\"\n (outClick)=\"handlerToggleType($event, item)\" />\n }\n <libs_ui-components-buttons-button\n [type]=\"'button-third-hover-danger'\"\n [iconOnlyType]=\"true\"\n [sizeButton]=\"'smaller'\"\n [classIconLeft]=\"'libs-ui-icon-remove'\"\n [popover]=\"{ config: { content: isContainer(item) ? 'Xoá cả khối ghép' : 'Xoá khối', zIndex: 1300 } }\"\n (outClick)=\"handlerRemove($event, item)\" />\n </div>\n }\n\n @if (item.children && item.children.length > 0) {\n <!-- Khối có con → ruột nó lại là một mặt phẳng nữa. Đệ quy ở đây, nơi dùng không phải lo.\n Lề đặt ở ĐÂY (vỏ container), không đặt vào lưới con — lưới con giữ nguyên khe 2px. -->\n <libs_ui-services-grid_layout-canvas\n class=\"block h-full w-full\"\n [style.padding]=\"containerPadding()\"\n [node]=\"item\"\n [depth]=\"depth() + 1\"\n (outChange)=\"outChange.emit($event)\"\n (outRemoveNode)=\"outRemoveNode.emit($event)\"\n (outAddBlockInside)=\"outAddBlockInside.emit($event)\"\n (outToggleType)=\"outToggleType.emit($event)\" />\n }\n </div>\n </gridster-item>\n }\n </gridster>\n</div>\n","// Bề mặt CÔNG KHAI — chỉ những gì nơi dùng thật sự cần.\n//\n// `LibsUiGridLayoutTreeService` CỐ Ý không xuất: mọi thao tác trên cây đã có mặt trên\n// `LibsUiGridLayoutService` với chữ ký gọn hơn (không phải truyền `root` — thư viện đang giữ nó).\n// Cấu hình gridster cũng không xuất: nó đã được vá theo hàng chục lỗi đo trên sản phẩm thật, để nơi\n// dùng sửa lại là mở đường cho chính những lỗi đó quay về.\nexport * from './grid-layout.service';\nexport * from './canvas/grid-layout-canvas.component';\nexport * from './interfaces/grid-layout.interface';\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,13 +1,13 @@
1
1
  {
2
2
  "name": "@libs-ui/services-grid-layout",
3
- "version": "0.2.357-19",
3
+ "version": "0.2.357-20",
4
4
  "peerDependencies": {
5
5
  "@angular/core": "^18.2.0",
6
6
  "@angular/common": "^18.2.0",
7
7
  "gridster18": "npm:angular-gridster2@18.0.1",
8
8
  "rxjs": "~7.8.0",
9
- "@libs-ui/components-buttons-button": "0.2.357-19",
10
- "@libs-ui/utils": "0.2.357-19"
9
+ "@libs-ui/components-buttons-button": "0.2.357-20",
10
+ "@libs-ui/utils": "0.2.357-20"
11
11
  },
12
12
  "sideEffects": false,
13
13
  "module": "fesm2022/libs-ui-services-grid-layout.mjs",