@sd-angular/core 19.0.0-beta.87 → 19.0.0-beta.89
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/components/document-builder/src/plugins/variable/variable.plugin.d.ts +6 -0
- package/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.d.ts +5 -6
- package/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.d.ts +3 -2
- package/components/table/src/models/table-option-selector.model.d.ts +48 -0
- package/components/table/src/models/table-option.model.d.ts +102 -0
- package/fesm2022/sd-angular-core-components-document-builder.mjs +84 -18
- package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tab-router.mjs +40 -36
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +9 -9
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input.mjs +9 -2
- package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +4 -1
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs +9 -2
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-interceptors.mjs +24 -1
- package/fesm2022/sd-angular-core-interceptors.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-api.mjs +18 -34
- package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
- package/forms/input/src/input.component.d.ts +2 -0
- package/forms/textarea/src/textarea.component.d.ts +2 -0
- package/interceptors/index.d.ts +1 -0
- package/interceptors/unauthorized/unauthorized.interceptor.d.ts +12 -0
- package/package.json +71 -71
- package/sd-angular-core-19.0.0-beta.89.tgz +0 -0
- package/services/api/src/api.service.d.ts +3 -7
- package/services/api/src/interceptors/api.interceptor.d.ts +2 -4
- package/sd-angular-core-19.0.0-beta.87.tgz +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Pipe, Input, ChangeDetectionStrategy, Component, HostListener,
|
|
2
|
+
import { Injectable, Pipe, Input, ChangeDetectionStrategy, Component, viewChild, input, inject, ChangeDetectorRef, ElementRef, HostListener, booleanAttribute, signal, Injector, NgModuleFactory, createNgModule } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/router';
|
|
4
|
-
import { Router, ActivatedRoute, RouterEvent, RoutesRecognized, NavigationEnd } from '@angular/router';
|
|
5
|
-
import * as i1 from '@angular/common';
|
|
4
|
+
import { Router, ActivatedRoute, RouterEvent, RoutesRecognized, NavigationEnd, RouterOutlet } from '@angular/router';
|
|
5
|
+
import * as i1$1 from '@angular/common';
|
|
6
6
|
import { CommonModule } from '@angular/common';
|
|
7
7
|
import * as i3 from '@angular/material/icon';
|
|
8
8
|
import { MatIconModule } from '@angular/material/icon';
|
|
@@ -11,7 +11,7 @@ import { BehaviorSubject, Subscription, isObservable, lastValueFrom, Subject } f
|
|
|
11
11
|
import { debounceTime, startWith, map, filter, take } from 'rxjs/operators';
|
|
12
12
|
import { SdNotifyService } from '@sd-angular/core/services/notify';
|
|
13
13
|
import { SdUtilities } from '@sd-angular/core/utilities';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i1 from '@angular/cdk/drag-drop';
|
|
15
15
|
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
16
16
|
import { SdBadge } from '@sd-angular/core/components/badge';
|
|
17
17
|
|
|
@@ -248,23 +248,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
248
248
|
}] } });
|
|
249
249
|
|
|
250
250
|
class SdTabRouterNavComponent {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
tabRouterNav;
|
|
254
|
-
tabs = [];
|
|
251
|
+
tabRouterNav = viewChild('tabRouterNav');
|
|
252
|
+
tabs = input([]);
|
|
255
253
|
mode = 'default';
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
elementRef) {
|
|
259
|
-
this.cdRef = cdRef;
|
|
260
|
-
this.elementRef = elementRef;
|
|
261
|
-
}
|
|
254
|
+
cdRef = inject(ChangeDetectorRef);
|
|
255
|
+
elementRef = inject(ElementRef);
|
|
262
256
|
onResize() {
|
|
263
257
|
this.checkUI();
|
|
264
258
|
}
|
|
265
259
|
checkUI = () => {
|
|
266
|
-
const width = this.tabRouterNav?.nativeElement.clientWidth;
|
|
267
|
-
const
|
|
260
|
+
const width = this.tabRouterNav()?.nativeElement.clientWidth ?? 0;
|
|
261
|
+
const tabs = this.tabs();
|
|
262
|
+
if (tabs.length === 0) {
|
|
263
|
+
this.mode = 'default';
|
|
264
|
+
this.cdRef.markForCheck();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const nameWidth = (width - tabs.length * 68) / tabs.length;
|
|
268
268
|
if (nameWidth <= 20) {
|
|
269
269
|
this.mode = 'compact';
|
|
270
270
|
}
|
|
@@ -274,27 +274,24 @@ class SdTabRouterNavComponent {
|
|
|
274
274
|
this.cdRef.markForCheck();
|
|
275
275
|
};
|
|
276
276
|
onDrop = (event) => {
|
|
277
|
-
moveItemInArray(this.tabs, event.previousIndex, event.currentIndex);
|
|
277
|
+
moveItemInArray(this.tabs(), event.previousIndex, event.currentIndex);
|
|
278
278
|
};
|
|
279
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterNavComponent, deps: [
|
|
280
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
279
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
280
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdTabRouterNavComponent, isStandalone: true, selector: "sd-tab-router-nav", inputs: { tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "tabRouterNav", first: true, predicate: ["tabRouterNav"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs().length > 1\">\n @for (tab of tabs(); track tab.key) {\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\n }\n</div>\n", styles: [".tab-router__nav{background:#f9f9f9;overflow:hidden}.tab-router__nav--compact::ng-deep .tab-router__name{display:none}.tab-router__nav--compact::ng-deep .tab-router__icon{margin:0!important}.tab-router__nav--compact::ng-deep .tab-router__item--active{min-width:240px}.tab-router__nav--compact::ng-deep .tab-router__item--active .tab-router__icon{margin-right:8px!important}.tab-router__nav--compact::ng-deep .tab-router__item--active .tab-router__name{display:-webkit-box}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: SdTabRouterItemComponent, selector: "sd-tab-router-item", inputs: ["tab"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
281
281
|
}
|
|
282
282
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterNavComponent, decorators: [{
|
|
283
283
|
type: Component,
|
|
284
|
-
args: [{ selector: 'sd-tab-router-nav', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DragDropModule, SdTabRouterItemComponent], template: "<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs.length > 1\">\n
|
|
285
|
-
}],
|
|
286
|
-
type: ViewChild,
|
|
287
|
-
args: ['tabRouterNav']
|
|
288
|
-
}], tabs: [{
|
|
289
|
-
type: Input
|
|
290
|
-
}], onResize: [{
|
|
284
|
+
args: [{ selector: 'sd-tab-router-nav', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DragDropModule, SdTabRouterItemComponent], template: "<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs().length > 1\">\n @for (tab of tabs(); track tab.key) {\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\n }\n</div>\n", styles: [".tab-router__nav{background:#f9f9f9;overflow:hidden}.tab-router__nav--compact::ng-deep .tab-router__name{display:none}.tab-router__nav--compact::ng-deep .tab-router__icon{margin:0!important}.tab-router__nav--compact::ng-deep .tab-router__item--active{min-width:240px}.tab-router__nav--compact::ng-deep .tab-router__item--active .tab-router__icon{margin-right:8px!important}.tab-router__nav--compact::ng-deep .tab-router__item--active .tab-router__name{display:-webkit-box}\n"] }]
|
|
285
|
+
}], propDecorators: { onResize: [{
|
|
291
286
|
type: HostListener,
|
|
292
|
-
args: ['window:resize'
|
|
287
|
+
args: ['window:resize']
|
|
293
288
|
}] } });
|
|
294
289
|
|
|
295
290
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
291
|
+
// eslint-disable-next-line @angular-eslint/no-unused-standalone-imports
|
|
296
292
|
class SdTabRouterOutletComponent {
|
|
297
|
-
|
|
293
|
+
disabled = input(false, { transform: booleanAttribute });
|
|
294
|
+
tabRouterNav = viewChild('tabRouterNav');
|
|
298
295
|
tabs = signal([]);
|
|
299
296
|
#router = inject(Router);
|
|
300
297
|
#activatedRoute = inject(ActivatedRoute);
|
|
@@ -320,6 +317,10 @@ class SdTabRouterOutletComponent {
|
|
|
320
317
|
// - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)
|
|
321
318
|
filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd))
|
|
322
319
|
.subscribe(async (event) => {
|
|
320
|
+
if (this.disabled()) {
|
|
321
|
+
this.#pendingNavigationState = {};
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
323
324
|
if (event instanceof RoutesRecognized) {
|
|
324
325
|
// Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn
|
|
325
326
|
// getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.
|
|
@@ -334,6 +335,8 @@ class SdTabRouterOutletComponent {
|
|
|
334
335
|
this.#pendingNavigationState = {};
|
|
335
336
|
}));
|
|
336
337
|
this.#subscription.add(this.#tabRouterService.actions.subscribe((event) => {
|
|
338
|
+
if (this.disabled())
|
|
339
|
+
return;
|
|
337
340
|
if (event?.type === 'close') {
|
|
338
341
|
this.#closeTab(event.tab);
|
|
339
342
|
}
|
|
@@ -344,6 +347,8 @@ class SdTabRouterOutletComponent {
|
|
|
344
347
|
}
|
|
345
348
|
tabTrackBy = (index, tab) => tab.key;
|
|
346
349
|
#closeTab = (tab) => {
|
|
350
|
+
if (this.disabled())
|
|
351
|
+
return;
|
|
347
352
|
const currentTabs = this.tabs();
|
|
348
353
|
const { isActive, key: activeKey } = tab;
|
|
349
354
|
if (isActive) {
|
|
@@ -362,10 +367,12 @@ class SdTabRouterOutletComponent {
|
|
|
362
367
|
}
|
|
363
368
|
else {
|
|
364
369
|
this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));
|
|
365
|
-
this.tabRouterNav?.checkUI();
|
|
370
|
+
this.tabRouterNav()?.checkUI();
|
|
366
371
|
}
|
|
367
372
|
};
|
|
368
373
|
#activeRoute = async (fullUrl, route, state = {}) => {
|
|
374
|
+
if (this.disabled())
|
|
375
|
+
return;
|
|
369
376
|
if (!route?.component)
|
|
370
377
|
return;
|
|
371
378
|
const component = route.component;
|
|
@@ -485,7 +492,7 @@ class SdTabRouterOutletComponent {
|
|
|
485
492
|
this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');
|
|
486
493
|
}
|
|
487
494
|
}
|
|
488
|
-
this.tabRouterNav?.checkUI();
|
|
495
|
+
this.tabRouterNav()?.checkUI();
|
|
489
496
|
};
|
|
490
497
|
// Lần xuống deepest firstChild để lấy snapshot của route lá (route thực sự render component).
|
|
491
498
|
#getActivatedRouteSnapshot = (snapshot) => {
|
|
@@ -507,15 +514,12 @@ class SdTabRouterOutletComponent {
|
|
|
507
514
|
return null;
|
|
508
515
|
};
|
|
509
516
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
510
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdTabRouterOutletComponent, isStandalone: true, selector: "sd-tab-router-outlet", viewQueries: [{ propertyName: "tabRouterNav", first: true, predicate: ["tabRouterNav"], descendants: true }], ngImport: i0, template: "<sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n
|
|
517
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdTabRouterOutletComponent, isStandalone: true, selector: "sd-tab-router-outlet", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "tabRouterNav", first: true, predicate: ["tabRouterNav"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (disabled()) {\n <div class=\"tab-router__disabled-outlet\">\n <router-outlet></router-outlet>\n </div>\n} @else {\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n <div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n </div>\n}", styles: [":host{display:flex;flex-direction:column;width:100%;min-height:0;height:100vh}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1;min-height:0}.tab-router__disabled-outlet{flex:1;width:100%;min-height:0;overflow:auto}.tab-router__pane{display:none;position:relative;height:100%;width:100%}.tab-router__pane.active{display:block}.tab-router__content{position:absolute;inset:0;overflow:auto;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: SdTabRouterNavComponent, selector: "sd-tab-router-nav", inputs: ["tabs"] }] });
|
|
511
518
|
}
|
|
512
519
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterOutletComponent, decorators: [{
|
|
513
520
|
type: Component,
|
|
514
|
-
args: [{ selector: 'sd-tab-router-outlet', standalone: true, imports: [CommonModule, MatIconModule, MatTooltipModule, SdTabRouterNavComponent], template: "<sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n
|
|
515
|
-
}], ctorParameters: () => []
|
|
516
|
-
type: ViewChild,
|
|
517
|
-
args: ['tabRouterNav']
|
|
518
|
-
}] } });
|
|
521
|
+
args: [{ selector: 'sd-tab-router-outlet', standalone: true, imports: [CommonModule, MatIconModule, MatTooltipModule, RouterOutlet, SdTabRouterNavComponent], template: "@if (disabled()) {\n <div class=\"tab-router__disabled-outlet\">\n <router-outlet></router-outlet>\n </div>\n} @else {\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n <div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n </div>\n}", styles: [":host{display:flex;flex-direction:column;width:100%;min-height:0;height:100vh}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1;min-height:0}.tab-router__disabled-outlet{flex:1;width:100%;min-height:0;overflow:auto}.tab-router__pane{display:none;position:relative;height:100%;width:100%}.tab-router__pane.active{display:block}.tab-router__content{position:absolute;inset:0;overflow:auto;height:100%;width:100%}\n"] }]
|
|
522
|
+
}], ctorParameters: () => [] });
|
|
519
523
|
// Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ
|
|
520
524
|
// (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute
|
|
521
525
|
// của route đang active → component cũ trong tab inactive nhận data sai khi user navigate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-tab-router.mjs","sources":["../../../projects/sd-angular/components/tab-router/src/events/tab-router.event.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-router.service.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-decorator.service.ts","../../../projects/sd-angular/components/tab-router/src/pipes/tab-info.pipe.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.html","../../../projects/sd-angular/components/tab-router/src/decorators/tab.decorator.ts","../../../projects/sd-angular/components/tab-router/sd-angular-core-components-tab-router.ts"],"sourcesContent":["import { SdTab } from '../models/tab-router.model';\n\nexport class SdTabBase {\n #tab: SdTab | undefined;\n\n constructor(tab: SdTab | undefined) {\n this.#tab = tab;\n }\n\n get tab(): SdTab | undefined {\n return this.#tab;\n }\n}\n\nexport class SdTabActivated extends SdTabBase {}\n\nexport class SdTabDeactivated extends SdTabBase {}\n\nexport declare type SdTabEvent = SdTabActivated | SdTabDeactivated;\n","import { Injectable, Type } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { SdTabAction } from '../actions/tab-router.action';\r\nimport { SdTabComponentBuilder } from '../decorators/tab.decorator';\r\nimport { SdTabBase, SdTabEvent } from '../events/tab-router.event';\r\nimport { SdTab } from '../models/tab-router.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdTabRouterService {\r\n events = new BehaviorSubject<SdTabEvent>(new SdTabBase(undefined));\r\n actions = new BehaviorSubject<SdTabAction | undefined>(undefined);\r\n builders = new BehaviorSubject<SdTabComponentBuilder[]>([]);\r\n currentTabChanges = new BehaviorSubject<SdTab | undefined>(undefined);\r\n newTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n updateTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n #currentTab: SdTab | undefined = undefined;\r\n #componentBuilders: SdTabComponentBuilder[] = [];\r\n constructor() {}\r\n\r\n addBuilder = (builder: SdTabComponentBuilder) => {\r\n if (!this.#componentBuilders.some(e => e.component === builder.component)) {\r\n this.#componentBuilders.push(builder);\r\n this.builders.next(this.#componentBuilders);\r\n }\r\n };\r\n\r\n get currentTab() {\r\n return this.#currentTab;\r\n }\r\n\r\n get currentKey() {\r\n return this.#currentTab?.key || null;\r\n }\r\n\r\n // select = (tabOrKey: string | SdTab): void => {\r\n // const tab = this.#tabs.find(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key === tabOrKey;\r\n // }\r\n // return e.key === tabOrKey?.key;\r\n // });\r\n // if (tab) {\r\n // this.#currentTab = tab;\r\n // }\r\n // }\r\n\r\n // add = (tab: SdTab): void => {\r\n // if (!tab.key) {\r\n // this.notifyService.notify.warning('Tab key is required');\r\n // }\r\n // if (!tab.component) {\r\n // this.notifyService.notify.warning('Tab component is required');\r\n // }\r\n // const existedTab = this.#tabs.find(e => e.key === tab.key);\r\n // if (!existedTab) {\r\n // this.#tabs.push(tab);\r\n // this.select(tab);\r\n // } else {\r\n // this.select(existedTab);\r\n // }\r\n // }\r\n\r\n // remove = (tabOrKey: string | SdTab): void => {\r\n // this.#tabs = this.#tabs.filter(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key !== tabOrKey;\r\n // }\r\n // return e.key !== tabOrKey?.key;\r\n // });\r\n // }\r\n\r\n setCurrentTab = (tab: SdTab): void => {\r\n this.#currentTab = tab;\r\n this.currentTabChanges.next(tab);\r\n };\r\n\r\n pushEvent = (tab: SdTab, Event: Type<SdTabEvent>) => {\r\n this.events.next(new Event(tab));\r\n };\r\n\r\n setOptions = () => {};\r\n\r\n close = (tab?: SdTab) => {\r\n tab = tab || this.#currentTab;\r\n if (tab) {\r\n this.actions.next({\r\n type: 'close',\r\n tab,\r\n });\r\n }\r\n };\r\n\r\n // Gọi hàm này để thực hiện update tab\r\n updateTab = (tab: SdTab) => {};\r\n}\r\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SdTabRouterService } from './tab-router.service';\n@Injectable({\n providedIn: 'root',\n})\nexport class SdTabDecoratorService {\n static tabRouterService = new BehaviorSubject<SdTabRouterService | undefined>(undefined);\n constructor(tabRouterService: SdTabRouterService) {\n SdTabDecoratorService.tabRouterService.next(tabRouterService);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { SdTab, SdTabInfo } from '../models/tab-router.model';\nimport { SdTabRouterService } from '../services/tab-router.service';\n@Pipe({\n name: 'sdTabInfo',\n standalone: true,\n})\nexport class SdTabInfoPipe implements PipeTransform {\n constructor(private tabRouterService: SdTabRouterService) {}\n transform(tabInfo: SdTabInfo | undefined | null, tab: SdTab): SdTabInfo {\n if (tabInfo) {\n return tabInfo;\n }\n const builders = this.tabRouterService.builders.getValue();\n const builder = builders.find(e => e.component === tab.component);\n if (builder) {\n const { url, params, queryParams, data } = tab;\n return {\n name: typeof builder.name === 'function' ? builder.name({ url, params, queryParams, data }) : builder.name,\n icon: typeof builder.icon === 'function' ? builder.icon({ url, params, queryParams }) : builder.icon,\n tooltip: typeof builder.tooltip === 'function' ? builder.tooltip({ url, params, queryParams }) : builder.tooltip,\n color: typeof builder.color === 'function' ? builder.color({ url, params, queryParams }) : builder.color,\n };\n }\n return {\n name: tab.url,\n icon: undefined,\n };\n }\n}\n","import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\nimport { debounceTime, startWith } from 'rxjs/operators';\r\n\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdBadge } from '@sd-angular/core/components/badge';\r\nimport { SdTab, SdTabInfo } from '../../models';\r\nimport { SdTabRouterService } from '../../services/tab-router.service';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { SdTabInfoPipe } from '../../pipes/tab-info.pipe';\r\n\r\n@Component({\r\n selector: 'sd-tab-router-item',\r\n templateUrl: './tab-router-item.component.html',\r\n styleUrls: ['./tab-router-item.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, MatIconModule, SdBadge, SdTabInfoPipe],\r\n})\r\nexport class SdTabRouterItemComponent implements OnInit, OnDestroy {\r\n @Input({ required: true }) tab!: SdTab;\r\n\r\n #subsctiption: Subscription = new Subscription();\r\n tabInfo?: SdTabInfo;\r\n constructor(\r\n private cdRef: ChangeDetectorRef,\r\n private tabRouterService: SdTabRouterService,\r\n private router: Router\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n this.#subsctiption.add(\r\n this.tabRouterService.events.pipe(debounceTime(100)).subscribe(() => {\r\n this.cdRef.markForCheck();\r\n })\r\n );\r\n\r\n this.#subsctiption.add(\r\n this.tab.tabInfoChanges.pipe(startWith(null)).subscribe(tabInfo => {\r\n if (tabInfo) {\r\n this.tabInfo = tabInfo;\r\n this.cdRef.markForCheck();\r\n }\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.#subsctiption.unsubscribe();\r\n }\r\n\r\n onTabClick = (event: Event) => {\r\n event.preventDefault();\r\n this.router.navigate([this.tab.url], {\r\n queryParams: this.tab.queryParams,\r\n state: { switchTab: true },\r\n });\r\n };\r\n\r\n close = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n };\r\n\r\n onMousedown = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n onMouseup = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n }\r\n };\r\n\r\n #closeTab = async () => {\r\n if (this.tab?.beforeClose) {\r\n //\r\n if (this.tab?.beforeClose()) {\r\n const result = this.tab?.beforeClose();\r\n if (typeof result === 'boolean') {\r\n if (result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n } else {\r\n if (await result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n }\r\n }\r\n } else {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n };\r\n}\r\n","<a\r\n [href]=\"[tab.url]\"\r\n class=\"tab-router__item d-flex align-items-center gap-8\"\r\n [class.tab-router__item--active]=\"tab.isActive\"\r\n (click)=\"onTabClick($event)\"\r\n (mousedown)=\"onMousedown($event)\"\r\n (mouseup)=\"onMouseup($event)\">\r\n @let info = tabInfo | sdTabInfo: tab;\r\n @if (info) {\r\n <sd-badge\r\n style=\"overflow: hidden;white-space: nowrap;\"\r\n [icon]=\"info.icon\"\r\n [title]=\"info.icon\"\r\n [tooltip]=\"info.tooltip || info.name\"\r\n [title]=\"info.name\"\r\n [color]=\"info.color\"\r\n (click)=\"onTabClick($event)\"></sd-badge>\r\n <button\r\n aria-hidden=\"true\"\r\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\r\n (click)=\"close($event)\"\r\n (mousedown)=\"$event.stopPropagation()\">\r\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\r\n </button>\r\n }\r\n</a>\r\n","import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostListener, Input, ViewChild } from '@angular/core';\n\nimport { SdTab } from '../../models/tab-router.model';\nimport { SdTabRouterItemComponent } from '../tab-router-item/tab-router-item.component';\nimport { CommonModule } from '@angular/common';\n\n@Component({\n selector: 'sd-tab-router-nav',\n templateUrl: './tab-router-nav.component.html',\n styleUrls: ['./tab-router-nav.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, DragDropModule, SdTabRouterItemComponent],\n})\nexport class SdTabRouterNavComponent {\n @ViewChild('tabRouterNav') tabRouterNav?: ElementRef;\n\n @Input() tabs: SdTab[] = [];\n mode: 'default' | 'compact' = 'default';\n\n constructor(\n private cdRef: ChangeDetectorRef,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public elementRef: ElementRef<any>\n ) {}\n\n @HostListener('window:resize', ['$event'])\n onResize(): void {\n this.checkUI();\n }\n\n checkUI = () => {\n const width = this.tabRouterNav?.nativeElement.clientWidth;\n const nameWidth = (width - this.tabs!.length * 68) / this.tabs!.length;\n if (nameWidth <= 20) {\n this.mode = 'compact';\n } else {\n this.mode = 'default';\n }\n this.cdRef.markForCheck();\n };\n\n onDrop = (event: CdkDragDrop<SdTab[]>) => {\n moveItemInArray(this.tabs!, event.previousIndex, event.currentIndex);\n };\n}\n","<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs.length > 1\">\n <ng-container *ngFor=\"let tab of tabs\">\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef?.nativeElement\"></sd-tab-router-item>\n </ng-container>\n</div>\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n Component,\n Injector,\n OnDestroy,\n Type,\n ViewChild,\n inject,\n signal,\n createNgModule,\n NgModuleFactory,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ActivatedRouteSnapshot,\n NavigationEnd,\n Router,\n RouterEvent,\n RoutesRecognized,\n} from '@angular/router';\nimport { CommonModule } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subject, Subscription, isObservable, lastValueFrom } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdTabActivated, SdTabDeactivated } from '../../events/tab-router.event';\nimport { SdTabAction } from '../../actions/tab-router.action';\nimport { SdTab } from '../../models';\nimport { SdTabDecoratorService } from '../../services/tab-decorator.service';\nimport { SdTabRouterService } from '../../services/tab-router.service';\nimport { SdTabRouterNavComponent } from '../tab-router-nav/tab-router-nav.component';\n\n@Component({\n selector: 'sd-tab-router-outlet',\n templateUrl: './tab-router-outlet.component.html',\n styleUrls: ['./tab-router-outlet.component.scss'],\n standalone: true,\n imports: [CommonModule, MatIconModule, MatTooltipModule, SdTabRouterNavComponent],\n})\nexport class SdTabRouterOutletComponent implements OnDestroy {\n @ViewChild('tabRouterNav') tabRouterNav?: SdTabRouterNavComponent;\n\n tabs = signal<SdTab[]>([]);\n\n #router = inject(Router);\n #activatedRoute = inject(ActivatedRoute);\n #injector = inject(Injector);\n #tabRouterService = inject(SdTabRouterService);\n #sdNotifyService = inject(SdNotifyService);\n // Inject để đảm bảo SdTabDecoratorService được khởi tạo (nó register BehaviorSubject\n // tĩnh để @SdTab decorator có thể truy cập SdTabRouterService). Không dùng trực tiếp ở đây.\n #tabDecoratorService = inject(SdTabDecoratorService);\n\n #rootRoute?: ActivatedRoute;\n #subscription = new Subscription();\n\n // State của navigation hiện tại (replaceTab, switchTab, ...) được capture ở RoutesRecognized\n // và dùng lại ở NavigationEnd. Lý do: tại NavigationEnd, getCurrentNavigation() đã trả về null,\n // còn lastSuccessfulNavigation và window.history.state không đáng tin cậy với mọi case.\n #pendingNavigationState: Record<string, any> = {};\n\n constructor() {\n this.#subscription.add(\n this.#router.events\n .pipe(\n // Một số event của Angular bọc trong wrapper có .routerEvent → unwrap về RouterEvent gốc.\n map((event: any) => (event instanceof RouterEvent ? event : event.routerEvent)),\n // Hybrid: cần CẢ HAI event vì mỗi event chứa data khác nhau ở thời điểm khác nhau.\n // - RoutesRecognized: navigation đang in-flight → getCurrentNavigation().extras.state đọc được\n // - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)\n filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd)\n )\n .subscribe(async (event: any) => {\n if (event instanceof RoutesRecognized) {\n // Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn\n // getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.\n this.#pendingNavigationState = this.#router.getCurrentNavigation()?.extras?.state ?? {};\n return;\n }\n // NavigationEnd: dùng activatedRoute.snapshot và routerState.root MỚI nhất\n // (chứa route component đã được activate, cả lazy lẫn standalone routes).\n const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);\n this.#rootRoute = this.#router.routerState.root;\n await this.#activeRoute(event.urlAfterRedirects || event.url, route, this.#pendingNavigationState);\n this.#pendingNavigationState = {};\n })\n );\n\n this.#subscription.add(\n this.#tabRouterService.actions.subscribe((event: SdTabAction | undefined) => {\n if (event?.type === 'close') {\n this.#closeTab(event.tab);\n }\n })\n );\n }\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n\n tabTrackBy = (index: number, tab: SdTab) => tab.key;\n\n #closeTab = (tab: SdTab) => {\n const currentTabs = this.tabs();\n const { isActive, key: activeKey } = tab;\n\n if (isActive) {\n const activeIndex = currentTabs.findIndex(({ key }) => key === activeKey);\n const nextTab = currentTabs[activeIndex + 1] || currentTabs[activeIndex - 1];\n\n this.tabs.set(currentTabs.filter(({ key }) => key !== activeKey));\n\n if (nextTab) {\n this.#router.navigate([nextTab.url], {\n queryParams: { ...(nextTab.queryParams || {}) },\n state: { switchTab: true },\n });\n } else {\n this.#router.navigateByUrl('/', { state: { switchTab: true } });\n }\n } else {\n this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));\n this.tabRouterNav?.checkUI();\n }\n };\n\n #activeRoute = async (\n fullUrl: string,\n route: ActivatedRouteSnapshot | null,\n state: Record<string, any> = {}\n ) => {\n if (!route?.component) return;\n\n const component = route.component as Type<any>;\n const queryParams = { ...(route.queryParams || {}) };\n const params = { ...(route.params || {}) };\n const data = { ...(route.data || {}) };\n const [url] = fullUrl.split('?');\n // Tab identity = hash(url + queryParams). Cùng key = cùng tab, không tạo lại.\n const key = SdUtilities.hash({ url, queryParams });\n\n let existedIndex = -1;\n let activatedIndex = -1;\n\n const currentTabs = this.tabs();\n\n // QUAN TRỌNG: scan READ-ONLY, KHÔNG mutate tab.isActive trong loop này.\n //\n // Lý do: NavigationEnd có thể fire nhiều lần cho 1 user-action (do nested outlets,\n // redirect, hoặc Angular internal). Vì #activeRoute là async (await getBestInjector),\n // 2 invocations có thể chạy concurrent và interleave với nhau.\n //\n // Nếu mutate tab.isActive = false ở đây, call thứ 2 sẽ thấy isActive đã bị call 1\n // set false rồi → không tìm thấy active tab → activatedIndex stay -1 → splice bỏ qua\n // → tab cũ không bị remove → xuất hiện duplicate tabs.\n //\n // Cách fix: chỉ ĐỌC isActive, sau đó dùng .map() ở dưới để tạo tab objects mới qua spread.\n for (let i = 0; i < currentTabs.length; i++) {\n const tab = currentTabs[i];\n if (tab.key === key) {\n existedIndex = i;\n } else if (tab.isActive) {\n activatedIndex = i;\n this.#tabRouterService.pushEvent(tab, SdTabDeactivated);\n }\n }\n\n const replaceTab = state['replaceTab'];\n\n // Resolve injector phù hợp với route. Cần xử lý 3 trường hợp:\n // - Standalone route (Angular đã set _injector trên routeConfig sau khi activate)\n // - NgModule lazy load (cần createNgModule từ class)\n // - Fallback: root injector\n const getBestInjector = async (snapshot: ActivatedRouteSnapshot): Promise<Injector> => {\n // Standalone route: Angular tự lưu environment injector trên routeConfig._injector\n const routeInjector = (snapshot as any)._resolvedGui || (snapshot as any).routeConfig?._injector;\n if (routeInjector) return routeInjector;\n\n // NgModule lazy: phải gọi lại loadChildren() để lấy module class rồi createNgModule\n const loadChildren = snapshot.parent?.routeConfig?.loadChildren;\n if (typeof loadChildren === 'function') {\n let loaded: any = await loadChildren();\n\n if (isObservable(loaded)) {\n loaded = await lastValueFrom(loaded);\n }\n\n // ES module có thể export default\n if (loaded && typeof loaded === 'object' && 'default' in loaded) {\n loaded = loaded.default;\n }\n\n // Angular cũ: NgModuleFactory\n if (loaded instanceof NgModuleFactory) {\n return loaded.create(this.#injector).injector;\n }\n\n // Angular mới: NgModule class. Bọc try/catch vì createNgModule throw nếu không phải NgModule.\n if (typeof loaded === 'function' && !Array.isArray(loaded)) {\n try {\n return createNgModule(loaded, this.#injector).injector;\n } catch {\n return this.#injector;\n }\n }\n }\n return this.#injector;\n };\n\n const finalInjector = await getBestInjector(route);\n const activatedRoute = this.#getActivatedRoute(this.#rootRoute!, component);\n\n const newTab: SdTab = {\n key,\n component,\n injector: new SdOutletInjector(activatedRoute, finalInjector),\n isActive: true,\n url,\n params,\n queryParams,\n data,\n tabInfoChanges: new Subject(),\n };\n\n // Tạo updatedTabs qua spread thay vì mutate (xem lý do ở for loop phía trên).\n // Với tab có isActive không đổi: giữ nguyên reference (tránh trigger ngComponentOutlet\n // re-evaluate không cần thiết). Với tab cần đổi isActive: tạo object mới qua spread,\n // các nested fields (component, injector) vẫn giữ same reference nên component không bị recreate.\n let updatedTabs = currentTabs.map(tab => {\n if (tab.key === key) return tab.isActive ? tab : { ...tab, isActive: true };\n return tab.isActive ? { ...tab, isActive: false } : tab;\n });\n\n // replaceTab: thay vì mở tab mới song song, xoá tab đang active rồi mở tab mới ở cuối.\n // Use case: từ tab \"chi tiết\" bấm \"chỉnh sửa\" với replaceTab → tab chi tiết bị xoá,\n // tab chỉnh sửa thay thế (giữ số tab không tăng).\n if (replaceTab && activatedIndex >= 0) {\n updatedTabs = updatedTabs.filter((_, i) => i !== activatedIndex);\n }\n\n if (existedIndex >= 0) {\n // Tab đã tồn tại (cùng url + queryParams) → CHỈ activate, KHÔNG thay tab object.\n // Lý do: thay tab object = đổi reference của tab.injector → ngComponentOutlet recreate\n // component → tab bị \"reload\" mỗi khi click lại hoặc navigate cùng URL.\n //\n // splice phía trên có thể đã shift index nếu activatedIndex < existedIndex.\n const idx = replaceTab && activatedIndex >= 0 && activatedIndex < existedIndex\n ? existedIndex - 1\n : existedIndex;\n this.#tabRouterService.setCurrentTab(updatedTabs[idx]);\n this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);\n this.tabs.set(updatedTabs);\n } else {\n // Tab chưa tồn tại → thêm mới ở cuối.\n this.#tabRouterService.setCurrentTab(newTab);\n this.tabs.set([...updatedTabs, newTab]);\n\n if (this.tabs().length > 30) {\n this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');\n }\n }\n\n this.tabRouterNav?.checkUI();\n };\n\n // Lần xuống deepest firstChild để lấy snapshot của route lá (route thực sự render component).\n #getActivatedRouteSnapshot = (snapshot: ActivatedRouteSnapshot): ActivatedRouteSnapshot | null => {\n let node = snapshot;\n while (node.firstChild) node = node.firstChild;\n return node;\n };\n\n // DFS tìm ActivatedRoute (không phải snapshot) trong tree theo component class.\n // Cần ActivatedRoute thật vì SdOutletInjector sẽ inject nó vào component qua DI.\n #getActivatedRoute = (activatedRoute: ActivatedRoute, component: any): ActivatedRoute | null => {\n if (activatedRoute.component === component) return activatedRoute;\n for (const child of activatedRoute.children) {\n const result = this.#getActivatedRoute(child, component);\n if (result) return result;\n }\n return null;\n };\n}\n\n// Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ\n// (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute\n// của route đang active → component cũ trong tab inactive nhận data sai khi user navigate.\nclass SdOutletInjector implements Injector {\n constructor(\n private route: ActivatedRoute | null,\n private parentInjector: Injector\n ) {}\n\n get(token: any, notFoundValue?: any): any {\n if (token === ActivatedRoute) {\n return this.route || notFoundValue;\n }\n return this.parentInjector.get(token, notFoundValue);\n }\n}\n","<sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n\n<div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n</div>","import { Type } from '@angular/core';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { SdTabDecoratorService } from '../services/tab-decorator.service';\r\n\r\nexport interface SdTabComponentArgs {\r\n url?: string;\r\n params?: any;\r\n queryParams?: any;\r\n data?: Record<string, any>;\r\n}\r\n\r\nexport declare interface SdTabComponentBuilder {\r\n component: Type<any>;\r\n name: string | ((args: SdTabComponentArgs) => string);\r\n icon?: string | ((args: SdTabComponentArgs) => string);\r\n tooltip?: string | ((args: SdTabComponentArgs) => string);\r\n color?: SdColor | ((args: SdTabComponentArgs) => SdColor);\r\n}\r\n\r\nexport function SdTabComponent<T>(builder: SdTabComponentBuilder) {\r\n return (constructor: T) => {\r\n SdTabDecoratorService.tabRouterService\r\n .pipe(\r\n filter(service => service !== undefined && service !== null),\r\n take(1)\r\n )\r\n .subscribe(service => {\r\n service.addBuilder(builder);\r\n });\r\n };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.SdTabRouterService"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-tab-router.mjs","sources":["../../../projects/sd-angular/components/tab-router/src/events/tab-router.event.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-router.service.ts","../../../projects/sd-angular/components/tab-router/src/services/tab-decorator.service.ts","../../../projects/sd-angular/components/tab-router/src/pipes/tab-info.pipe.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-item/tab-router-item.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.html","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.ts","../../../projects/sd-angular/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.html","../../../projects/sd-angular/components/tab-router/src/decorators/tab.decorator.ts","../../../projects/sd-angular/components/tab-router/sd-angular-core-components-tab-router.ts"],"sourcesContent":["import { SdTab } from '../models/tab-router.model';\n\nexport class SdTabBase {\n #tab: SdTab | undefined;\n\n constructor(tab: SdTab | undefined) {\n this.#tab = tab;\n }\n\n get tab(): SdTab | undefined {\n return this.#tab;\n }\n}\n\nexport class SdTabActivated extends SdTabBase {}\n\nexport class SdTabDeactivated extends SdTabBase {}\n\nexport declare type SdTabEvent = SdTabActivated | SdTabDeactivated;\n","import { Injectable, Type } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\nimport { SdTabAction } from '../actions/tab-router.action';\r\nimport { SdTabComponentBuilder } from '../decorators/tab.decorator';\r\nimport { SdTabBase, SdTabEvent } from '../events/tab-router.event';\r\nimport { SdTab } from '../models/tab-router.model';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdTabRouterService {\r\n events = new BehaviorSubject<SdTabEvent>(new SdTabBase(undefined));\r\n actions = new BehaviorSubject<SdTabAction | undefined>(undefined);\r\n builders = new BehaviorSubject<SdTabComponentBuilder[]>([]);\r\n currentTabChanges = new BehaviorSubject<SdTab | undefined>(undefined);\r\n newTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n updateTabs = new BehaviorSubject<SdTab | undefined>(undefined);\r\n #currentTab: SdTab | undefined = undefined;\r\n #componentBuilders: SdTabComponentBuilder[] = [];\r\n constructor() {}\r\n\r\n addBuilder = (builder: SdTabComponentBuilder) => {\r\n if (!this.#componentBuilders.some(e => e.component === builder.component)) {\r\n this.#componentBuilders.push(builder);\r\n this.builders.next(this.#componentBuilders);\r\n }\r\n };\r\n\r\n get currentTab() {\r\n return this.#currentTab;\r\n }\r\n\r\n get currentKey() {\r\n return this.#currentTab?.key || null;\r\n }\r\n\r\n // select = (tabOrKey: string | SdTab): void => {\r\n // const tab = this.#tabs.find(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key === tabOrKey;\r\n // }\r\n // return e.key === tabOrKey?.key;\r\n // });\r\n // if (tab) {\r\n // this.#currentTab = tab;\r\n // }\r\n // }\r\n\r\n // add = (tab: SdTab): void => {\r\n // if (!tab.key) {\r\n // this.notifyService.notify.warning('Tab key is required');\r\n // }\r\n // if (!tab.component) {\r\n // this.notifyService.notify.warning('Tab component is required');\r\n // }\r\n // const existedTab = this.#tabs.find(e => e.key === tab.key);\r\n // if (!existedTab) {\r\n // this.#tabs.push(tab);\r\n // this.select(tab);\r\n // } else {\r\n // this.select(existedTab);\r\n // }\r\n // }\r\n\r\n // remove = (tabOrKey: string | SdTab): void => {\r\n // this.#tabs = this.#tabs.filter(e => {\r\n // if (typeof (tabOrKey) === 'string') {\r\n // return e.key !== tabOrKey;\r\n // }\r\n // return e.key !== tabOrKey?.key;\r\n // });\r\n // }\r\n\r\n setCurrentTab = (tab: SdTab): void => {\r\n this.#currentTab = tab;\r\n this.currentTabChanges.next(tab);\r\n };\r\n\r\n pushEvent = (tab: SdTab, Event: Type<SdTabEvent>) => {\r\n this.events.next(new Event(tab));\r\n };\r\n\r\n setOptions = () => {};\r\n\r\n close = (tab?: SdTab) => {\r\n tab = tab || this.#currentTab;\r\n if (tab) {\r\n this.actions.next({\r\n type: 'close',\r\n tab,\r\n });\r\n }\r\n };\r\n\r\n // Gọi hàm này để thực hiện update tab\r\n updateTab = (tab: SdTab) => {};\r\n}\r\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SdTabRouterService } from './tab-router.service';\n@Injectable({\n providedIn: 'root',\n})\nexport class SdTabDecoratorService {\n static tabRouterService = new BehaviorSubject<SdTabRouterService | undefined>(undefined);\n constructor(tabRouterService: SdTabRouterService) {\n SdTabDecoratorService.tabRouterService.next(tabRouterService);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { SdTab, SdTabInfo } from '../models/tab-router.model';\nimport { SdTabRouterService } from '../services/tab-router.service';\n@Pipe({\n name: 'sdTabInfo',\n standalone: true,\n})\nexport class SdTabInfoPipe implements PipeTransform {\n constructor(private tabRouterService: SdTabRouterService) {}\n transform(tabInfo: SdTabInfo | undefined | null, tab: SdTab): SdTabInfo {\n if (tabInfo) {\n return tabInfo;\n }\n const builders = this.tabRouterService.builders.getValue();\n const builder = builders.find(e => e.component === tab.component);\n if (builder) {\n const { url, params, queryParams, data } = tab;\n return {\n name: typeof builder.name === 'function' ? builder.name({ url, params, queryParams, data }) : builder.name,\n icon: typeof builder.icon === 'function' ? builder.icon({ url, params, queryParams }) : builder.icon,\n tooltip: typeof builder.tooltip === 'function' ? builder.tooltip({ url, params, queryParams }) : builder.tooltip,\n color: typeof builder.color === 'function' ? builder.color({ url, params, queryParams }) : builder.color,\n };\n }\n return {\n name: tab.url,\n icon: undefined,\n };\n }\n}\n","import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\nimport { debounceTime, startWith } from 'rxjs/operators';\r\n\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdBadge } from '@sd-angular/core/components/badge';\r\nimport { SdTab, SdTabInfo } from '../../models';\r\nimport { SdTabRouterService } from '../../services/tab-router.service';\r\nimport { Router } from '@angular/router';\r\nimport { CommonModule } from '@angular/common';\r\nimport { SdTabInfoPipe } from '../../pipes/tab-info.pipe';\r\n\r\n@Component({\r\n selector: 'sd-tab-router-item',\r\n templateUrl: './tab-router-item.component.html',\r\n styleUrls: ['./tab-router-item.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, MatIconModule, SdBadge, SdTabInfoPipe],\r\n})\r\nexport class SdTabRouterItemComponent implements OnInit, OnDestroy {\r\n @Input({ required: true }) tab!: SdTab;\r\n\r\n #subsctiption: Subscription = new Subscription();\r\n tabInfo?: SdTabInfo;\r\n constructor(\r\n private cdRef: ChangeDetectorRef,\r\n private tabRouterService: SdTabRouterService,\r\n private router: Router\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n this.#subsctiption.add(\r\n this.tabRouterService.events.pipe(debounceTime(100)).subscribe(() => {\r\n this.cdRef.markForCheck();\r\n })\r\n );\r\n\r\n this.#subsctiption.add(\r\n this.tab.tabInfoChanges.pipe(startWith(null)).subscribe(tabInfo => {\r\n if (tabInfo) {\r\n this.tabInfo = tabInfo;\r\n this.cdRef.markForCheck();\r\n }\r\n })\r\n );\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.#subsctiption.unsubscribe();\r\n }\r\n\r\n onTabClick = (event: Event) => {\r\n event.preventDefault();\r\n this.router.navigate([this.tab.url], {\r\n queryParams: this.tab.queryParams,\r\n state: { switchTab: true },\r\n });\r\n };\r\n\r\n close = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n };\r\n\r\n onMousedown = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n onMouseup = (event: MouseEvent) => {\r\n if (event.button === 1) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.#closeTab();\r\n }\r\n };\r\n\r\n #closeTab = async () => {\r\n if (this.tab?.beforeClose) {\r\n //\r\n if (this.tab?.beforeClose()) {\r\n const result = this.tab?.beforeClose();\r\n if (typeof result === 'boolean') {\r\n if (result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n } else {\r\n if (await result) {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n }\r\n }\r\n } else {\r\n this.tabRouterService.close(this.tab);\r\n }\r\n };\r\n}\r\n","<a\r\n [href]=\"[tab.url]\"\r\n class=\"tab-router__item d-flex align-items-center gap-8\"\r\n [class.tab-router__item--active]=\"tab.isActive\"\r\n (click)=\"onTabClick($event)\"\r\n (mousedown)=\"onMousedown($event)\"\r\n (mouseup)=\"onMouseup($event)\">\r\n @let info = tabInfo | sdTabInfo: tab;\r\n @if (info) {\r\n <sd-badge\r\n style=\"overflow: hidden;white-space: nowrap;\"\r\n [icon]=\"info.icon\"\r\n [title]=\"info.icon\"\r\n [tooltip]=\"info.tooltip || info.name\"\r\n [title]=\"info.name\"\r\n [color]=\"info.color\"\r\n (click)=\"onTabClick($event)\"></sd-badge>\r\n <button\r\n aria-hidden=\"true\"\r\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\r\n (click)=\"close($event)\"\r\n (mousedown)=\"$event.stopPropagation()\">\r\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\r\n </button>\r\n }\r\n</a>\r\n","import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n inject,\n input,\n viewChild,\n} from '@angular/core';\n\nimport { SdTab } from '../../models/tab-router.model';\nimport { SdTabRouterItemComponent } from '../tab-router-item/tab-router-item.component';\nimport { CommonModule } from '@angular/common';\n\n@Component({\n selector: 'sd-tab-router-nav',\n templateUrl: './tab-router-nav.component.html',\n styleUrls: ['./tab-router-nav.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, DragDropModule, SdTabRouterItemComponent],\n})\nexport class SdTabRouterNavComponent {\n tabRouterNav = viewChild<ElementRef>('tabRouterNav');\n\n tabs = input<SdTab[]>([]);\n mode: 'default' | 'compact' = 'default';\n cdRef = inject(ChangeDetectorRef);\n elementRef = inject<ElementRef<any>>(ElementRef);\n\n @HostListener('window:resize')\n onResize(): void {\n this.checkUI();\n }\n\n checkUI = () => {\n const width = this.tabRouterNav()?.nativeElement.clientWidth ?? 0;\n const tabs = this.tabs();\n if (tabs.length === 0) {\n this.mode = 'default';\n this.cdRef.markForCheck();\n return;\n }\n\n const nameWidth = (width - tabs.length * 68) / tabs.length;\n if (nameWidth <= 20) {\n this.mode = 'compact';\n } else {\n this.mode = 'default';\n }\n this.cdRef.markForCheck();\n };\n\n onDrop = (event: CdkDragDrop<SdTab[]>) => {\n moveItemInArray(this.tabs(), event.previousIndex, event.currentIndex);\n };\n}\n","<div\n #tabRouterNav\n cdkDropList\n cdkDropListLockAxis=\"x\"\n cdkDropListOrientation=\"horizontal\"\n (cdkDropListDropped)=\"onDrop($event)\"\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\n [class.d-none]=\"tabs().length > 1\">\n @for (tab of tabs(); track tab.key) {\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\n }\n</div>\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n booleanAttribute,\n Component,\n Injector,\n OnDestroy,\n Type,\n inject,\n input,\n signal,\n viewChild,\n createNgModule,\n NgModuleFactory,\n} from '@angular/core';\nimport {\n ActivatedRoute,\n ActivatedRouteSnapshot,\n NavigationEnd,\n Router,\n RouterOutlet,\n RouterEvent,\n RoutesRecognized,\n} from '@angular/router';\nimport { CommonModule } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subject, Subscription, isObservable, lastValueFrom } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdTabActivated, SdTabDeactivated } from '../../events/tab-router.event';\nimport { SdTabAction } from '../../actions/tab-router.action';\nimport { SdTab } from '../../models';\nimport { SdTabDecoratorService } from '../../services/tab-decorator.service';\nimport { SdTabRouterService } from '../../services/tab-router.service';\nimport { SdTabRouterNavComponent } from '../tab-router-nav/tab-router-nav.component';\n\n// eslint-disable-next-line @angular-eslint/no-unused-standalone-imports\n@Component({\n selector: 'sd-tab-router-outlet',\n templateUrl: './tab-router-outlet.component.html',\n styleUrls: ['./tab-router-outlet.component.scss'],\n standalone: true,\n imports: [CommonModule, MatIconModule, MatTooltipModule, RouterOutlet, SdTabRouterNavComponent],\n})\nexport class SdTabRouterOutletComponent implements OnDestroy {\n disabled = input(false, { transform: booleanAttribute });\n\n tabRouterNav = viewChild<SdTabRouterNavComponent>('tabRouterNav');\n\n tabs = signal<SdTab[]>([]);\n\n #router = inject(Router);\n #activatedRoute = inject(ActivatedRoute);\n #injector = inject(Injector);\n #tabRouterService = inject(SdTabRouterService);\n #sdNotifyService = inject(SdNotifyService);\n // Inject để đảm bảo SdTabDecoratorService được khởi tạo (nó register BehaviorSubject\n // tĩnh để @SdTab decorator có thể truy cập SdTabRouterService). Không dùng trực tiếp ở đây.\n #tabDecoratorService = inject(SdTabDecoratorService);\n\n #rootRoute?: ActivatedRoute;\n #subscription = new Subscription();\n\n // State của navigation hiện tại (replaceTab, switchTab, ...) được capture ở RoutesRecognized\n // và dùng lại ở NavigationEnd. Lý do: tại NavigationEnd, getCurrentNavigation() đã trả về null,\n // còn lastSuccessfulNavigation và window.history.state không đáng tin cậy với mọi case.\n #pendingNavigationState: Record<string, any> = {};\n\n constructor() {\n this.#subscription.add(\n this.#router.events\n .pipe(\n // Một số event của Angular bọc trong wrapper có .routerEvent → unwrap về RouterEvent gốc.\n map((event: any) => (event instanceof RouterEvent ? event : event.routerEvent)),\n // Hybrid: cần CẢ HAI event vì mỗi event chứa data khác nhau ở thời điểm khác nhau.\n // - RoutesRecognized: navigation đang in-flight → getCurrentNavigation().extras.state đọc được\n // - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)\n filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd)\n )\n .subscribe(async (event: any) => {\n if (this.disabled()) {\n this.#pendingNavigationState = {};\n return;\n }\n\n if (event instanceof RoutesRecognized) {\n // Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn\n // getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.\n this.#pendingNavigationState = this.#router.getCurrentNavigation()?.extras?.state ?? {};\n return;\n }\n // NavigationEnd: dùng activatedRoute.snapshot và routerState.root MỚI nhất\n // (chứa route component đã được activate, cả lazy lẫn standalone routes).\n const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);\n this.#rootRoute = this.#router.routerState.root;\n await this.#activeRoute(event.urlAfterRedirects || event.url, route, this.#pendingNavigationState);\n this.#pendingNavigationState = {};\n })\n );\n\n this.#subscription.add(\n this.#tabRouterService.actions.subscribe((event: SdTabAction | undefined) => {\n if (this.disabled()) return;\n\n if (event?.type === 'close') {\n this.#closeTab(event.tab);\n }\n })\n );\n }\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n\n tabTrackBy = (index: number, tab: SdTab) => tab.key;\n\n #closeTab = (tab: SdTab) => {\n if (this.disabled()) return;\n\n const currentTabs = this.tabs();\n const { isActive, key: activeKey } = tab;\n\n if (isActive) {\n const activeIndex = currentTabs.findIndex(({ key }) => key === activeKey);\n const nextTab = currentTabs[activeIndex + 1] || currentTabs[activeIndex - 1];\n\n this.tabs.set(currentTabs.filter(({ key }) => key !== activeKey));\n\n if (nextTab) {\n this.#router.navigate([nextTab.url], {\n queryParams: { ...(nextTab.queryParams || {}) },\n state: { switchTab: true },\n });\n } else {\n this.#router.navigateByUrl('/', { state: { switchTab: true } });\n }\n } else {\n this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));\n this.tabRouterNav()?.checkUI();\n }\n };\n\n #activeRoute = async (\n fullUrl: string,\n route: ActivatedRouteSnapshot | null,\n state: Record<string, any> = {}\n ) => {\n if (this.disabled()) return;\n if (!route?.component) return;\n\n const component = route.component as Type<any>;\n const queryParams = { ...(route.queryParams || {}) };\n const params = { ...(route.params || {}) };\n const data = { ...(route.data || {}) };\n const [url] = fullUrl.split('?');\n // Tab identity = hash(url + queryParams). Cùng key = cùng tab, không tạo lại.\n const key = SdUtilities.hash({ url, queryParams });\n\n let existedIndex = -1;\n let activatedIndex = -1;\n\n const currentTabs = this.tabs();\n\n // QUAN TRỌNG: scan READ-ONLY, KHÔNG mutate tab.isActive trong loop này.\n //\n // Lý do: NavigationEnd có thể fire nhiều lần cho 1 user-action (do nested outlets,\n // redirect, hoặc Angular internal). Vì #activeRoute là async (await getBestInjector),\n // 2 invocations có thể chạy concurrent và interleave với nhau.\n //\n // Nếu mutate tab.isActive = false ở đây, call thứ 2 sẽ thấy isActive đã bị call 1\n // set false rồi → không tìm thấy active tab → activatedIndex stay -1 → splice bỏ qua\n // → tab cũ không bị remove → xuất hiện duplicate tabs.\n //\n // Cách fix: chỉ ĐỌC isActive, sau đó dùng .map() ở dưới để tạo tab objects mới qua spread.\n for (let i = 0; i < currentTabs.length; i++) {\n const tab = currentTabs[i];\n if (tab.key === key) {\n existedIndex = i;\n } else if (tab.isActive) {\n activatedIndex = i;\n this.#tabRouterService.pushEvent(tab, SdTabDeactivated);\n }\n }\n\n const replaceTab = state['replaceTab'];\n\n // Resolve injector phù hợp với route. Cần xử lý 3 trường hợp:\n // - Standalone route (Angular đã set _injector trên routeConfig sau khi activate)\n // - NgModule lazy load (cần createNgModule từ class)\n // - Fallback: root injector\n const getBestInjector = async (snapshot: ActivatedRouteSnapshot): Promise<Injector> => {\n // Standalone route: Angular tự lưu environment injector trên routeConfig._injector\n const routeInjector = (snapshot as any)._resolvedGui || (snapshot as any).routeConfig?._injector;\n if (routeInjector) return routeInjector;\n\n // NgModule lazy: phải gọi lại loadChildren() để lấy module class rồi createNgModule\n const loadChildren = snapshot.parent?.routeConfig?.loadChildren;\n if (typeof loadChildren === 'function') {\n let loaded: any = await loadChildren();\n\n if (isObservable(loaded)) {\n loaded = await lastValueFrom(loaded);\n }\n\n // ES module có thể export default\n if (loaded && typeof loaded === 'object' && 'default' in loaded) {\n loaded = loaded.default;\n }\n\n // Angular cũ: NgModuleFactory\n if (loaded instanceof NgModuleFactory) {\n return loaded.create(this.#injector).injector;\n }\n\n // Angular mới: NgModule class. Bọc try/catch vì createNgModule throw nếu không phải NgModule.\n if (typeof loaded === 'function' && !Array.isArray(loaded)) {\n try {\n return createNgModule(loaded, this.#injector).injector;\n } catch {\n return this.#injector;\n }\n }\n }\n return this.#injector;\n };\n\n const finalInjector = await getBestInjector(route);\n const activatedRoute = this.#getActivatedRoute(this.#rootRoute!, component);\n\n const newTab: SdTab = {\n key,\n component,\n injector: new SdOutletInjector(activatedRoute, finalInjector),\n isActive: true,\n url,\n params,\n queryParams,\n data,\n tabInfoChanges: new Subject(),\n };\n\n // Tạo updatedTabs qua spread thay vì mutate (xem lý do ở for loop phía trên).\n // Với tab có isActive không đổi: giữ nguyên reference (tránh trigger ngComponentOutlet\n // re-evaluate không cần thiết). Với tab cần đổi isActive: tạo object mới qua spread,\n // các nested fields (component, injector) vẫn giữ same reference nên component không bị recreate.\n let updatedTabs = currentTabs.map(tab => {\n if (tab.key === key) return tab.isActive ? tab : { ...tab, isActive: true };\n return tab.isActive ? { ...tab, isActive: false } : tab;\n });\n\n // replaceTab: thay vì mở tab mới song song, xoá tab đang active rồi mở tab mới ở cuối.\n // Use case: từ tab \"chi tiết\" bấm \"chỉnh sửa\" với replaceTab → tab chi tiết bị xoá,\n // tab chỉnh sửa thay thế (giữ số tab không tăng).\n if (replaceTab && activatedIndex >= 0) {\n updatedTabs = updatedTabs.filter((_, i) => i !== activatedIndex);\n }\n\n if (existedIndex >= 0) {\n // Tab đã tồn tại (cùng url + queryParams) → CHỈ activate, KHÔNG thay tab object.\n // Lý do: thay tab object = đổi reference của tab.injector → ngComponentOutlet recreate\n // component → tab bị \"reload\" mỗi khi click lại hoặc navigate cùng URL.\n //\n // splice phía trên có thể đã shift index nếu activatedIndex < existedIndex.\n const idx = replaceTab && activatedIndex >= 0 && activatedIndex < existedIndex\n ? existedIndex - 1\n : existedIndex;\n this.#tabRouterService.setCurrentTab(updatedTabs[idx]);\n this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);\n this.tabs.set(updatedTabs);\n } else {\n // Tab chưa tồn tại → thêm mới ở cuối.\n this.#tabRouterService.setCurrentTab(newTab);\n this.tabs.set([...updatedTabs, newTab]);\n\n if (this.tabs().length > 30) {\n this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');\n }\n }\n\n this.tabRouterNav()?.checkUI();\n };\n\n // Lần xuống deepest firstChild để lấy snapshot của route lá (route thực sự render component).\n #getActivatedRouteSnapshot = (snapshot: ActivatedRouteSnapshot): ActivatedRouteSnapshot | null => {\n let node = snapshot;\n while (node.firstChild) node = node.firstChild;\n return node;\n };\n\n // DFS tìm ActivatedRoute (không phải snapshot) trong tree theo component class.\n // Cần ActivatedRoute thật vì SdOutletInjector sẽ inject nó vào component qua DI.\n #getActivatedRoute = (activatedRoute: ActivatedRoute, component: any): ActivatedRoute | null => {\n if (activatedRoute.component === component) return activatedRoute;\n for (const child of activatedRoute.children) {\n const result = this.#getActivatedRoute(child, component);\n if (result) return result;\n }\n return null;\n };\n}\n\n// Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ\n// (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute\n// của route đang active → component cũ trong tab inactive nhận data sai khi user navigate.\nclass SdOutletInjector implements Injector {\n constructor(\n private route: ActivatedRoute | null,\n private parentInjector: Injector\n ) {}\n\n get(token: any, notFoundValue?: any): any {\n if (token === ActivatedRoute) {\n return this.route || notFoundValue;\n }\n return this.parentInjector.get(token, notFoundValue);\n }\n}\n","@if (disabled()) {\n <div class=\"tab-router__disabled-outlet\">\n <router-outlet></router-outlet>\n </div>\n} @else {\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\n <div class=\"tab-router__list\">\n @for (tab of tabs(); track tab.key) {\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\n <div class=\"tab-router__content\">\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\n </div>\n </div>\n } @empty {\n <div class=\"tab-router__empty\">\n </div>\n }\n </div>\n}","import { Type } from '@angular/core';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport { filter, take } from 'rxjs/operators';\r\nimport { SdTabDecoratorService } from '../services/tab-decorator.service';\r\n\r\nexport interface SdTabComponentArgs {\r\n url?: string;\r\n params?: any;\r\n queryParams?: any;\r\n data?: Record<string, any>;\r\n}\r\n\r\nexport declare interface SdTabComponentBuilder {\r\n component: Type<any>;\r\n name: string | ((args: SdTabComponentArgs) => string);\r\n icon?: string | ((args: SdTabComponentArgs) => string);\r\n tooltip?: string | ((args: SdTabComponentArgs) => string);\r\n color?: SdColor | ((args: SdTabComponentArgs) => SdColor);\r\n}\r\n\r\nexport function SdTabComponent<T>(builder: SdTabComponentBuilder) {\r\n return (constructor: T) => {\r\n SdTabDecoratorService.tabRouterService\r\n .pipe(\r\n filter(service => service !== undefined && service !== null),\r\n take(1)\r\n )\r\n .subscribe(service => {\r\n service.addBuilder(builder);\r\n });\r\n };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.SdTabRouterService","i1"],"mappings":"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"}
|
|
@@ -288,7 +288,7 @@ class SdUploadFile {
|
|
|
288
288
|
// ─── Model Signal (two-way binding support: [(model)]) ────────────────
|
|
289
289
|
model = model([]);
|
|
290
290
|
constructor() {
|
|
291
|
-
this.#
|
|
291
|
+
this.#validateDuplicateConfigurationKeys();
|
|
292
292
|
// Sync form group & register form control
|
|
293
293
|
afterNextRender(() => {
|
|
294
294
|
this.#formGroup = this.form();
|
|
@@ -375,14 +375,14 @@ class SdUploadFile {
|
|
|
375
375
|
}
|
|
376
376
|
return Array.isArray(config) ? config : [config];
|
|
377
377
|
};
|
|
378
|
-
#
|
|
378
|
+
#validateDuplicateConfigurationKeys = () => {
|
|
379
379
|
const configurations = this.#getConfigurations();
|
|
380
380
|
if (!configurations.length) {
|
|
381
381
|
return;
|
|
382
382
|
}
|
|
383
383
|
const seen = new Set();
|
|
384
|
-
for (const
|
|
385
|
-
const key =
|
|
384
|
+
for (const configuration of configurations) {
|
|
385
|
+
const key = configuration.key;
|
|
386
386
|
const normalizedKey = key === undefined ? '__undefined__' : key;
|
|
387
387
|
if (seen.has(normalizedKey)) {
|
|
388
388
|
const label = key === undefined ? 'undefined' : key;
|
|
@@ -391,22 +391,22 @@ class SdUploadFile {
|
|
|
391
391
|
seen.add(normalizedKey);
|
|
392
392
|
}
|
|
393
393
|
};
|
|
394
|
-
#
|
|
394
|
+
#getSelectedConfiguration = () => {
|
|
395
395
|
const configurations = this.#getConfigurations();
|
|
396
396
|
if (!configurations.length) {
|
|
397
397
|
return undefined;
|
|
398
398
|
}
|
|
399
399
|
const key = this.key();
|
|
400
|
-
return configurations.find(
|
|
400
|
+
return configurations.find(configuration => configuration.key === key);
|
|
401
401
|
};
|
|
402
402
|
#getUploadHandler = () => {
|
|
403
|
-
return this.uploadInput() || this.#
|
|
403
|
+
return this.uploadInput() || this.#getSelectedConfiguration()?.upload;
|
|
404
404
|
};
|
|
405
405
|
#getDetailsHandler = () => {
|
|
406
|
-
return this.details() || this.#
|
|
406
|
+
return this.details() || this.#getSelectedConfiguration()?.details;
|
|
407
407
|
};
|
|
408
408
|
#getDownloadHandler = () => {
|
|
409
|
-
return this.downloadInput() || this.#
|
|
409
|
+
return this.downloadInput() || this.#getSelectedConfiguration()?.download;
|
|
410
410
|
};
|
|
411
411
|
// #updateValidator = () => {
|
|
412
412
|
// this.formControl.clearValidators();
|