@sd-angular/core 19.0.0-beta.5 → 19.0.0-beta.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +686 -33
  2. package/assets/scss/ckeditor5.scss +60 -2
  3. package/assets/scss/core/bootstrap.scss +17 -0
  4. package/assets/scss/core/grid.scss +40 -0
  5. package/assets/scss/sd-core.scss +1 -0
  6. package/components/avatar/index.d.ts +1 -0
  7. package/components/avatar/src/avatar.component.d.ts +15 -0
  8. package/components/badge/src/badge.component.d.ts +77 -19
  9. package/components/button/src/button.component.d.ts +26 -28
  10. package/components/code-editor/index.d.ts +1 -0
  11. package/components/code-editor/src/code-editor.component.d.ts +25 -0
  12. package/components/document-builder/index.d.ts +1 -0
  13. package/components/document-builder/src/document-builder.component.d.ts +18 -36
  14. package/components/document-builder/src/document-builder.model.d.ts +10 -10
  15. package/components/document-builder/src/plugins/block-space/block-space.plugin.d.ts +9 -0
  16. package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.d.ts +44 -0
  17. package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.model.d.ts +56 -0
  18. package/components/document-builder/src/plugins/heading/heading.plugin.d.ts +1 -0
  19. package/components/document-builder/src/plugins/highlight-range/highlight-range.plugin.d.ts +4 -0
  20. package/components/document-builder/src/plugins/image-custom/image-custom.plugin.d.ts +31 -0
  21. package/components/document-builder/src/plugins/index.d.ts +7 -2
  22. package/components/document-builder/src/plugins/page-orientation/page-orientation.plugin.d.ts +2 -2
  23. package/components/document-builder/src/plugins/paste-handler/filters/bookmark.d.ts +14 -0
  24. package/components/document-builder/src/plugins/paste-handler/filters/br.d.ts +15 -0
  25. package/components/document-builder/src/plugins/paste-handler/filters/image.d.ts +25 -0
  26. package/components/document-builder/src/plugins/paste-handler/filters/list.d.ts +29 -0
  27. package/components/document-builder/src/plugins/paste-handler/filters/parse.d.ts +35 -0
  28. package/components/document-builder/src/plugins/paste-handler/filters/removeboldwrapper.d.ts +15 -0
  29. package/components/document-builder/src/plugins/paste-handler/filters/removegooglesheetstag.d.ts +15 -0
  30. package/components/document-builder/src/plugins/paste-handler/filters/removeinvalidtablewidth.d.ts +15 -0
  31. package/components/document-builder/src/plugins/paste-handler/filters/removemsattributes.d.ts +15 -0
  32. package/components/document-builder/src/plugins/paste-handler/filters/removestyleblock.d.ts +15 -0
  33. package/components/document-builder/src/plugins/paste-handler/filters/removexmlns.d.ts +15 -0
  34. package/components/document-builder/src/plugins/paste-handler/filters/replacemsfootnotes.d.ts +54 -0
  35. package/components/document-builder/src/plugins/paste-handler/filters/replacetabswithinprewithspaces.d.ts +24 -0
  36. package/components/document-builder/src/plugins/paste-handler/filters/space.d.ts +27 -0
  37. package/components/document-builder/src/plugins/paste-handler/filters/table.d.ts +16 -0
  38. package/components/document-builder/src/plugins/paste-handler/filters/utils.d.ts +25 -0
  39. package/components/document-builder/src/plugins/paste-handler/index.d.ts +35 -0
  40. package/components/document-builder/src/plugins/paste-handler/normalizers/googledocsnormalizer.d.ts +31 -0
  41. package/components/document-builder/src/plugins/paste-handler/normalizers/googlesheetsnormalizer.d.ts +31 -0
  42. package/components/document-builder/src/plugins/paste-handler/normalizers/mswordnormalizer.d.ts +29 -0
  43. package/components/document-builder/src/plugins/paste-handler/types.d.ts +30 -0
  44. package/components/document-builder/src/plugins/table-custom/index.d.ts +34 -0
  45. package/components/index.d.ts +4 -0
  46. package/components/mini-editor/index.d.ts +2 -0
  47. package/components/mini-editor/src/mini-editor.component.d.ts +90 -0
  48. package/components/mini-editor/src/mini-editor.model.d.ts +44 -0
  49. package/components/side-drawer/src/side-drawer.component.d.ts +1 -2
  50. package/components/tab-router/src/components/tab-router-item/tab-router-item.component.d.ts +4 -1
  51. package/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.d.ts +3 -15
  52. package/components/table/src/components/column-filter/column-filter.component.d.ts +3 -3
  53. package/components/table/src/components/external-filter/external-filter.component.d.ts +1 -1
  54. package/components/table/src/components/selector-action/action-filter.pipe.d.ts +11 -10
  55. package/components/table/src/directives/index.d.ts +2 -0
  56. package/components/table/src/directives/sd-table-column-filter-def.directive.d.ts +9 -0
  57. package/components/table/src/directives/sticky-shadow.directive.d.ts +17 -0
  58. package/components/table/src/models/table-column.model.d.ts +33 -34
  59. package/components/table/src/models/table-command.model.d.ts +7 -3
  60. package/components/table/src/models/table-item.model.d.ts +5 -4
  61. package/components/table/src/models/table-option-export.model.d.ts +3 -2
  62. package/components/table/src/models/table-option-selector.model.d.ts +11 -10
  63. package/components/table/src/models/table-option.model.d.ts +10 -8
  64. package/components/table/src/services/index.d.ts +3 -0
  65. package/components/table/src/services/table-export/table-export.service.d.ts +26 -0
  66. package/components/table/src/services/table-filter/table-filter.model.d.ts +5 -4
  67. package/components/table/src/services/table-format/table-format.service.d.ts +16 -0
  68. package/components/table/src/table.component.d.ts +39 -53
  69. package/components/view/index.d.ts +1 -0
  70. package/components/view/src/view.component.d.ts +16 -0
  71. package/components/workflow/src/models/index.d.ts +1 -0
  72. package/directives/index.d.ts +1 -0
  73. package/directives/src/sd-href.directive.d.ts +9 -0
  74. package/fesm2022/sd-angular-core-components-avatar.mjs +90 -0
  75. package/fesm2022/sd-angular-core-components-avatar.mjs.map +1 -0
  76. package/fesm2022/sd-angular-core-components-badge.mjs +101 -91
  77. package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
  78. package/fesm2022/sd-angular-core-components-button.mjs +64 -96
  79. package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
  80. package/fesm2022/sd-angular-core-components-code-editor.mjs +129 -0
  81. package/fesm2022/sd-angular-core-components-code-editor.mjs.map +1 -0
  82. package/fesm2022/sd-angular-core-components-document-builder.mjs +3635 -521
  83. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  84. package/fesm2022/sd-angular-core-components-history.mjs +1 -1
  85. package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
  86. package/fesm2022/sd-angular-core-components-import-excel.mjs +1 -1
  87. package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
  88. package/fesm2022/sd-angular-core-components-mini-editor.mjs +326 -0
  89. package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -0
  90. package/fesm2022/sd-angular-core-components-preview.mjs +1 -1
  91. package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
  92. package/fesm2022/sd-angular-core-components-side-drawer.mjs +21 -8
  93. package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
  94. package/fesm2022/sd-angular-core-components-tab-router.mjs +152 -226
  95. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  96. package/fesm2022/sd-angular-core-components-table.mjs +1234 -1076
  97. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  98. package/fesm2022/sd-angular-core-components-upload-file.mjs +1 -1
  99. package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
  100. package/fesm2022/sd-angular-core-components-view.mjs +45 -0
  101. package/fesm2022/sd-angular-core-components-view.mjs.map +1 -0
  102. package/fesm2022/sd-angular-core-components-workflow.mjs +33 -43
  103. package/fesm2022/sd-angular-core-components-workflow.mjs.map +1 -1
  104. package/fesm2022/sd-angular-core-components.mjs +4 -0
  105. package/fesm2022/sd-angular-core-components.mjs.map +1 -1
  106. package/fesm2022/sd-angular-core-directives.mjs +80 -27
  107. package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
  108. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +257 -363
  109. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  110. package/fesm2022/sd-angular-core-forms-date-range.mjs +145 -245
  111. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  112. package/fesm2022/sd-angular-core-forms-date.mjs +137 -273
  113. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  114. package/fesm2022/sd-angular-core-forms-datetime.mjs +136 -288
  115. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  116. package/fesm2022/sd-angular-core-forms-input-number.mjs +174 -337
  117. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  118. package/fesm2022/sd-angular-core-forms-input.mjs +130 -285
  119. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  120. package/fesm2022/sd-angular-core-forms-radio.mjs +3 -2
  121. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  122. package/fesm2022/sd-angular-core-forms-select.mjs +337 -420
  123. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  124. package/fesm2022/sd-angular-core-forms-textarea.mjs +121 -226
  125. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  126. package/fesm2022/sd-angular-core-modules-keycloak.mjs +126 -0
  127. package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -0
  128. package/fesm2022/sd-angular-core-modules-layout.mjs +440 -431
  129. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  130. package/fesm2022/sd-angular-core-modules.mjs +1 -1
  131. package/fesm2022/sd-angular-core-services-api.mjs +5 -10
  132. package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
  133. package/fesm2022/sd-angular-core-services-confirm.mjs +2 -2
  134. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  135. package/fesm2022/sd-angular-core-services-docx.mjs +173 -0
  136. package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -0
  137. package/fesm2022/sd-angular-core-services-notify.mjs +2 -2
  138. package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
  139. package/fesm2022/sd-angular-core-services.mjs +1 -0
  140. package/fesm2022/sd-angular-core-services.mjs.map +1 -1
  141. package/fesm2022/sd-angular-core-utilities-extensions.mjs +21 -45
  142. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  143. package/fesm2022/sd-angular-core-utilities-models.mjs +15 -1
  144. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  145. package/forms/autocomplete/src/autocomplete.component.d.ts +51 -56
  146. package/forms/date/src/date.component.d.ts +41 -45
  147. package/forms/date-range/src/date-range.component.d.ts +28 -33
  148. package/forms/datetime/src/datetime.component.d.ts +41 -48
  149. package/forms/input/src/input.component.d.ts +46 -56
  150. package/forms/input-number/src/input-number.component.d.ts +47 -54
  151. package/forms/select/src/select.component.d.ts +60 -58
  152. package/forms/textarea/src/textarea.component.d.ts +34 -41
  153. package/modules/index.d.ts +1 -1
  154. package/modules/keycloak/index.d.ts +4 -0
  155. package/modules/keycloak/keycloak.configuration.d.ts +11 -0
  156. package/modules/keycloak/keycloak.interceptor.d.ts +2 -0
  157. package/modules/keycloak/keycloak.module.d.ts +18 -0
  158. package/modules/keycloak/keycloak.service.d.ts +14 -0
  159. package/modules/layout/components/layout-main/layout-main.component.d.ts +7 -12
  160. package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +22 -29
  161. package/modules/layout/components/sidebar-v1/components/user/user.component.d.ts +11 -17
  162. package/modules/layout/components/sidebar-v1/main.component.d.ts +14 -14
  163. package/modules/layout/configurations/layout.configuration.d.ts +46 -3
  164. package/modules/layout/modules/forbidden/pages/root/root.component.d.ts +3 -8
  165. package/modules/layout/modules/home/components/home-page/home-page.component.d.ts +2 -5
  166. package/modules/layout/modules/not-found/pages/root/root.component.d.ts +3 -8
  167. package/modules/layout/services/index.d.ts +1 -0
  168. package/modules/layout/services/layout.service.d.ts +10 -0
  169. package/modules/layout/services/menu/menu.model.d.ts +2 -0
  170. package/modules/layout/services/storage/storage.service.d.ts +0 -3
  171. package/package.json +90 -67
  172. package/sd-angular-core-19.0.0-beta.51.tgz +0 -0
  173. package/services/api/src/api.model.d.ts +6 -1
  174. package/services/confirm/src/lib/confirm.service.d.ts +1 -0
  175. package/services/docx/index.d.ts +1 -0
  176. package/services/docx/src/lib/docx.model.d.ts +9 -0
  177. package/services/docx/src/lib/docx.service.d.ts +13 -0
  178. package/services/docx/src/public-api.d.ts +2 -0
  179. package/services/index.d.ts +1 -0
  180. package/utilities/extensions/src/string.extension.d.ts +2 -0
  181. package/utilities/extensions/src/utility.extension.d.ts +1 -0
  182. package/utilities/models/index.d.ts +3 -0
  183. package/utilities/models/src/filter.model.d.ts +14 -2
  184. package/utilities/models/src/icon.model.d.ts +2 -0
  185. package/utilities/models/src/nested-key-of.model.d.ts +5 -0
  186. package/utilities/models/src/pattern.model.d.ts +1 -1
  187. package/utilities/models/src/unwrap-signal.model.d.ts +6 -0
  188. package/components/document-builder/src/plugins/comment/comment.plugin.d.ts +0 -4
  189. package/components/document-builder/src/plugins/table-fit/table-fit.plugin.d.ts +0 -4
  190. package/fesm2022/sd-angular-core-modules-oidc.mjs +0 -127
  191. package/fesm2022/sd-angular-core-modules-oidc.mjs.map +0 -1
  192. package/modules/oidc/dynamic-sts.loader.d.ts +0 -11
  193. package/modules/oidc/index.d.ts +0 -2
  194. package/modules/oidc/oidc.configuration.d.ts +0 -11
  195. package/modules/oidc/oidc.module.d.ts +0 -14
@@ -1,19 +1,19 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Pipe, Input, ChangeDetectionStrategy, Component, HostListener, ViewChild, createNgModule } from '@angular/core';
3
- import * as i1 from '@angular/router';
4
- import { RouterModule, RouterEvent, RoutesRecognized, NavigationEnd, ActivatedRoute } from '@angular/router';
5
- import * as i5 from '@angular/common';
2
+ import { Injectable, Pipe, Input, ChangeDetectionStrategy, Component, HostListener, ViewChild, signal, inject, Injector, NgModuleFactory, createNgModule } from '@angular/core';
3
+ import * as i2 from '@angular/router';
4
+ import { Router, ActivatedRoute, RouterEvent, RoutesRecognized, NavigationEnd } from '@angular/router';
5
+ import * as i1 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';
9
9
  import { MatTooltipModule } from '@angular/material/tooltip';
10
- import { BehaviorSubject, Subscription, Subject } from 'rxjs';
10
+ import { BehaviorSubject, Subscription, isObservable, lastValueFrom, Subject } from 'rxjs';
11
11
  import { debounceTime, startWith, map, filter, take } from 'rxjs/operators';
12
- import * as i2 from '@angular/cdk/drag-drop';
12
+ import { SdNotifyService } from '@sd-angular/core/services/notify';
13
+ import { SdUtilities } from '@sd-angular/core/utilities';
14
+ import * as i2$1 from '@angular/cdk/drag-drop';
13
15
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
14
16
  import { SdBadge } from '@sd-angular/core/components/badge';
15
- import { SdUtilities } from '@sd-angular/core/utilities';
16
- import * as i4 from '@sd-angular/core/services/notify';
17
17
 
18
18
  class SdTabBase {
19
19
  #tab;
@@ -114,6 +114,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
114
114
  }]
115
115
  }], ctorParameters: () => [] });
116
116
 
117
+ class SdTabDecoratorService {
118
+ static tabRouterService = new BehaviorSubject(undefined);
119
+ constructor(tabRouterService) {
120
+ SdTabDecoratorService.tabRouterService.next(tabRouterService);
121
+ }
122
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, deps: [{ token: SdTabRouterService }], target: i0.ɵɵFactoryTarget.Injectable });
123
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, providedIn: 'root' });
124
+ }
125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, decorators: [{
126
+ type: Injectable,
127
+ args: [{
128
+ providedIn: 'root',
129
+ }]
130
+ }], ctorParameters: () => [{ type: SdTabRouterService }] });
131
+
117
132
  class SdTabInfoPipe {
118
133
  tabRouterService;
119
134
  constructor(tabRouterService) {
@@ -153,12 +168,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
153
168
  class SdTabRouterItemComponent {
154
169
  cdRef;
155
170
  tabRouterService;
171
+ router;
156
172
  tab;
157
173
  #subsctiption = new Subscription();
158
174
  tabInfo;
159
- constructor(cdRef, tabRouterService) {
175
+ constructor(cdRef, tabRouterService, router) {
160
176
  this.cdRef = cdRef;
161
177
  this.tabRouterService = tabRouterService;
178
+ this.router = router;
162
179
  }
163
180
  ngOnInit() {
164
181
  this.#subsctiption.add(this.tabRouterService.events.pipe(debounceTime(100)).subscribe(() => {
@@ -174,6 +191,13 @@ class SdTabRouterItemComponent {
174
191
  ngOnDestroy() {
175
192
  this.#subsctiption.unsubscribe();
176
193
  }
194
+ onTabClick = (event) => {
195
+ event.preventDefault();
196
+ this.router.navigate([this.tab.url], {
197
+ queryParams: this.tab.queryParams,
198
+ state: { switchTab: true },
199
+ });
200
+ };
177
201
  close = (event) => {
178
202
  event.preventDefault();
179
203
  event.stopPropagation();
@@ -212,13 +236,13 @@ class SdTabRouterItemComponent {
212
236
  this.tabRouterService.close(this.tab);
213
237
  }
214
238
  };
215
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SdTabRouterService }], target: i0.ɵɵFactoryTarget.Component });
216
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdTabRouterItemComponent, isStandalone: true, selector: "sd-tab-router-item", inputs: { tab: "tab" }, ngImport: i0, template: "<a\n [routerLink]=\"[tab.url]\"\n [queryParams]=\"tab.queryParams\"\n [state]=\"{ switchTab: true }\"\n class=\"tab-router__item d-flex align-items-center\"\n style=\"gap: 8px\"\n [class.tab-router__item--active]=\"tab.isActive\"\n (mousedown)=\"onMousedown($event)\"\n (mouseup)=\"onMouseup($event)\">\n @let info = tabInfo | sdTabInfo: tab;\n @if (info) {\n <sd-badge\n style=\"overflow: hidden;white-space: nowrap;\"\n [icon]=\"info.icon\"\n [title]=\"info.icon\"\n [tooltip]=\"info.tooltip || info.name\"\n [title]=\"info.name\"\n [color]=\"info.color\"></sd-badge>\n <button\n aria-hidden=\"true\"\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\n (click)=\"close($event)\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\n </button>\n }\n</a>\n", styles: [":host{display:block;overflow:hidden;position:relative;flex:1 1 64px;max-width:240px}:host:after{content:\"\";position:absolute;right:0;top:0;bottom:0;height:16px;width:1px;background:#dde0e5;margin:auto}:host:last-child:after{content:none}:host::ng-deep .tab-router__item sd-badge .c-badge-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:184px}.flex-1{flex:1}.tab-router__icon{background-color:#5c6bc0;width:16px;height:16px;line-height:16px;text-align:center;font-size:10px;color:#fff;border-radius:2px;text-transform:uppercase}.tab-router__icon .mat-icon{height:10px;width:10px;font-size:10px}.tab-router__close{color:#757575;outline:none;border:0;background:none;border-radius:50%;height:16px;width:16px}.tab-router__close:hover{background-color:#0000001f}.tab-router__close .mat-icon{font-size:12px;height:12px;width:12px}.tab-router__item{background:#f2f3f4;padding:8px;color:inherit;text-decoration:none;font-size:12px;line-height:16px;overflow:hidden}.tab-router__item:hover{background-color:#fff}.tab-router__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tab-router__item--active{border-radius:8px 8px 0 0;background-color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdBadge, selector: "sd-badge", inputs: ["type", "color", "primary", "secondary", "success", "info", "warning", "error", "fontSet", "title", "description", "tooltip", "icon", "size"], outputs: ["sdClick"] }, { kind: "pipe", type: SdTabInfoPipe, name: "sdTabInfo" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SdTabRouterService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Component });
240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdTabRouterItemComponent, isStandalone: true, selector: "sd-tab-router-item", inputs: { tab: "tab" }, ngImport: i0, template: "<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", styles: [":host{display:block;overflow:hidden;position:relative;flex:1 1 64px;max-width:240px}:host:after{content:\"\";position:absolute;right:0;top:0;bottom:0;height:16px;width:1px;background:#dde0e5;margin:auto}:host:last-child:after{content:none}:host::ng-deep .tab-router__item sd-badge .c-badge-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:184px}.flex-1{flex:1}.tab-router__icon{background-color:#5c6bc0;width:16px;height:16px;line-height:16px;text-align:center;font-size:10px;color:#fff;border-radius:2px;text-transform:uppercase}.tab-router__icon .mat-icon{height:10px;width:10px;font-size:10px}.tab-router__close{color:#757575;outline:none;border:0;background:none;border-radius:50%;height:16px;width:16px}.tab-router__close:hover{background-color:#0000001f}.tab-router__close .mat-icon{font-size:12px;height:12px;width:12px}.tab-router__item{background:#f2f3f4;padding:8px;color:inherit;text-decoration:none;font-size:12px;line-height:16px;overflow:hidden}.tab-router__item:hover{background-color:#fff}.tab-router__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tab-router__item--active{border-radius:8px 8px 0 0;background-color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdBadge, selector: "sd-badge", inputs: ["type", "color", "primary", "secondary", "success", "info", "warning", "error", "fontSet", "title", "description", "tooltip", "icon", "size"], outputs: ["click"] }, { kind: "pipe", type: SdTabInfoPipe, name: "sdTabInfo" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
217
241
  }
218
242
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterItemComponent, decorators: [{
219
243
  type: Component,
220
- args: [{ selector: 'sd-tab-router-item', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, RouterModule, MatIconModule, SdBadge, SdTabInfoPipe], template: "<a\n [routerLink]=\"[tab.url]\"\n [queryParams]=\"tab.queryParams\"\n [state]=\"{ switchTab: true }\"\n class=\"tab-router__item d-flex align-items-center\"\n style=\"gap: 8px\"\n [class.tab-router__item--active]=\"tab.isActive\"\n (mousedown)=\"onMousedown($event)\"\n (mouseup)=\"onMouseup($event)\">\n @let info = tabInfo | sdTabInfo: tab;\n @if (info) {\n <sd-badge\n style=\"overflow: hidden;white-space: nowrap;\"\n [icon]=\"info.icon\"\n [title]=\"info.icon\"\n [tooltip]=\"info.tooltip || info.name\"\n [title]=\"info.name\"\n [color]=\"info.color\"></sd-badge>\n <button\n aria-hidden=\"true\"\n class=\"tab-router__close d-flex align-items-center justify-content-center ml-auto p-0\"\n (click)=\"close($event)\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon aria-hidden=\"true\" fontIcon=\"close\"></mat-icon>\n </button>\n }\n</a>\n", styles: [":host{display:block;overflow:hidden;position:relative;flex:1 1 64px;max-width:240px}:host:after{content:\"\";position:absolute;right:0;top:0;bottom:0;height:16px;width:1px;background:#dde0e5;margin:auto}:host:last-child:after{content:none}:host::ng-deep .tab-router__item sd-badge .c-badge-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:184px}.flex-1{flex:1}.tab-router__icon{background-color:#5c6bc0;width:16px;height:16px;line-height:16px;text-align:center;font-size:10px;color:#fff;border-radius:2px;text-transform:uppercase}.tab-router__icon .mat-icon{height:10px;width:10px;font-size:10px}.tab-router__close{color:#757575;outline:none;border:0;background:none;border-radius:50%;height:16px;width:16px}.tab-router__close:hover{background-color:#0000001f}.tab-router__close .mat-icon{font-size:12px;height:12px;width:12px}.tab-router__item{background:#f2f3f4;padding:8px;color:inherit;text-decoration:none;font-size:12px;line-height:16px;overflow:hidden}.tab-router__item:hover{background-color:#fff}.tab-router__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tab-router__item--active{border-radius:8px 8px 0 0;background-color:#fff}\n"] }]
221
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: SdTabRouterService }], propDecorators: { tab: [{
244
+ args: [{ selector: 'sd-tab-router-item', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, MatIconModule, SdBadge, SdTabInfoPipe], template: "<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", styles: [":host{display:block;overflow:hidden;position:relative;flex:1 1 64px;max-width:240px}:host:after{content:\"\";position:absolute;right:0;top:0;bottom:0;height:16px;width:1px;background:#dde0e5;margin:auto}:host:last-child:after{content:none}:host::ng-deep .tab-router__item sd-badge .c-badge-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:184px}.flex-1{flex:1}.tab-router__icon{background-color:#5c6bc0;width:16px;height:16px;line-height:16px;text-align:center;font-size:10px;color:#fff;border-radius:2px;text-transform:uppercase}.tab-router__icon .mat-icon{height:10px;width:10px;font-size:10px}.tab-router__close{color:#757575;outline:none;border:0;background:none;border-radius:50%;height:16px;width:16px}.tab-router__close:hover{background-color:#0000001f}.tab-router__close .mat-icon{font-size:12px;height:12px;width:12px}.tab-router__item{background:#f2f3f4;padding:8px;color:inherit;text-decoration:none;font-size:12px;line-height:16px;overflow:hidden}.tab-router__item:hover{background-color:#fff}.tab-router__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tab-router__item--active{border-radius:8px 8px 0 0;background-color:#fff}\n"] }]
245
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: SdTabRouterService }, { type: i2.Router }], propDecorators: { tab: [{
222
246
  type: Input,
223
247
  args: [{ required: true }]
224
248
  }] } });
@@ -253,7 +277,7 @@ class SdTabRouterNavComponent {
253
277
  moveItemInArray(this.tabs, event.previousIndex, event.currentIndex);
254
278
  };
255
279
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterNavComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
256
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: SdTabRouterNavComponent, isStandalone: true, selector: "sd-tab-router-nav", inputs: { tabs: "tabs" }, host: { listeners: { "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "tabRouterNav", first: true, predicate: ["tabRouterNav"], descendants: 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 <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", 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: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.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: i2.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 });
280
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: SdTabRouterNavComponent, isStandalone: true, selector: "sd-tab-router-nav", inputs: { tabs: "tabs" }, host: { listeners: { "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "tabRouterNav", first: true, predicate: ["tabRouterNav"], descendants: 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 <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", 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: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2$1.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: i2$1.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 });
257
281
  }
258
282
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterNavComponent, decorators: [{
259
283
  type: Component,
@@ -268,64 +292,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
268
292
  args: ['window:resize', ['$event']]
269
293
  }] } });
270
294
 
271
- class SdTabDecoratorService {
272
- static tabRouterService = new BehaviorSubject(undefined);
273
- constructor(tabRouterService) {
274
- SdTabDecoratorService.tabRouterService.next(tabRouterService);
275
- }
276
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, deps: [{ token: SdTabRouterService }], target: i0.ɵɵFactoryTarget.Injectable });
277
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, providedIn: 'root' });
278
- }
279
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabDecoratorService, decorators: [{
280
- type: Injectable,
281
- args: [{
282
- providedIn: 'root',
283
- }]
284
- }], ctorParameters: () => [{ type: SdTabRouterService }] });
285
-
286
295
  /* eslint-disable @typescript-eslint/no-explicit-any */
287
296
  class SdTabRouterOutletComponent {
288
- router;
289
- activatedRoute;
290
- cd;
291
- injector;
292
- tabDecoratorService;
293
- tabRouterService;
294
- sdNotifyService;
295
297
  tabRouterNav;
296
- tabs = [];
298
+ tabs = signal([]);
299
+ #router = inject(Router);
300
+ #activatedRoute = inject(ActivatedRoute);
301
+ #injector = inject(Injector);
302
+ #tabRouterService = inject(SdTabRouterService);
303
+ #sdNotifyService = inject(SdNotifyService);
304
+ #tabDecoratorService = inject(SdTabDecoratorService);
297
305
  #rootRoute;
298
306
  #subscription = new Subscription();
299
307
  #firstLoad = true;
300
- constructor(router, activatedRoute, cd, injector, tabDecoratorService, // KHÔNG XÓA
301
- tabRouterService, sdNotifyService) {
302
- this.router = router;
303
- this.activatedRoute = activatedRoute;
304
- this.cd = cd;
305
- this.injector = injector;
306
- this.tabDecoratorService = tabDecoratorService;
307
- this.tabRouterService = tabRouterService;
308
- this.sdNotifyService = sdNotifyService;
309
- this.#subscription.add(router.events
310
- .pipe(map((event) => (event instanceof RouterEvent ? event : event.routerEvent)), filter(event => {
311
- return event instanceof RoutesRecognized || event instanceof NavigationEnd;
312
- }))
308
+ constructor() {
309
+ this.#subscription.add(this.#router.events
310
+ .pipe(map((event) => (event instanceof RouterEvent ? event : event.routerEvent)), filter(event => event instanceof RoutesRecognized || event instanceof NavigationEnd))
313
311
  .subscribe(async (event) => {
314
312
  if (this.#firstLoad && event instanceof NavigationEnd) {
315
313
  this.#firstLoad = false;
316
- const route = this.#getActivatedRouteSnapshot(this.activatedRoute.snapshot);
317
- this.#rootRoute = this.router.routerState.root;
314
+ const route = this.#getActivatedRouteSnapshot(this.#activatedRoute.snapshot);
315
+ this.#rootRoute = this.#router.routerState.root;
318
316
  await this.#activeRoute(event.urlAfterRedirects || event.url, route);
319
317
  return;
320
318
  }
321
319
  if (!this.#firstLoad && event instanceof RoutesRecognized) {
322
320
  const route = this.#getActivatedRouteSnapshot(event.state.root);
323
- this.#rootRoute = this.router.routerState.root;
321
+ this.#rootRoute = this.#router.routerState.root;
324
322
  await this.#activeRoute(event.urlAfterRedirects || event.url, route);
325
323
  }
326
324
  }));
327
- this.#subscription.add(tabRouterService.actions.subscribe((event) => {
328
- if (event && event.type === 'close') {
325
+ this.#subscription.add(this.#tabRouterService.actions.subscribe((event) => {
326
+ if (event?.type === 'close') {
329
327
  this.#closeTab(event.tab);
330
328
  }
331
329
  }));
@@ -333,61 +331,42 @@ class SdTabRouterOutletComponent {
333
331
  ngOnDestroy() {
334
332
  this.#subscription.unsubscribe();
335
333
  }
336
- tabTrackBy = (index, tab) => {
337
- return tab.key;
338
- };
334
+ tabTrackBy = (index, tab) => tab.key;
339
335
  #closeTab = (tab) => {
336
+ const currentTabs = this.tabs();
340
337
  const { isActive, key: activeKey } = tab;
341
338
  if (isActive) {
342
- const activeIndex = this.tabs.findIndex(({ key }) => key === activeKey);
343
- const nextTab = this.tabs[activeIndex + 1] || this.tabs[activeIndex - 1];
339
+ const activeIndex = currentTabs.findIndex(({ key }) => key === activeKey);
340
+ const nextTab = currentTabs[activeIndex + 1] || currentTabs[activeIndex - 1];
341
+ this.tabs.set(currentTabs.filter(({ key }) => key !== activeKey));
344
342
  if (nextTab) {
345
- const { url: nextUrl } = nextTab;
346
- const nextQueryParams = {
347
- ...(nextTab.queryParams || {}),
348
- };
349
- this.tabs = this.tabs.filter(({ key }) => key !== activeKey);
350
- this.router.navigate([nextUrl], {
351
- queryParams: nextQueryParams,
352
- state: {
353
- switchTab: true,
354
- },
343
+ this.#router.navigate([nextTab.url], {
344
+ queryParams: { ...(nextTab.queryParams || {}) },
345
+ state: { switchTab: true },
355
346
  });
356
347
  }
357
348
  else {
358
- this.tabs = this.tabs.filter(({ key }) => key !== activeKey);
359
- this.router.navigateByUrl('/', {
360
- state: {
361
- switchTab: true,
362
- },
363
- });
349
+ this.#router.navigateByUrl('/', { state: { switchTab: true } });
364
350
  }
365
351
  }
366
352
  else {
367
- this.tabs = this.tabs.filter(({ key }) => key !== tab.key);
353
+ this.tabs.set(currentTabs.filter(({ key }) => key !== tab.key));
368
354
  this.tabRouterNav?.checkUI();
369
- this.cd.markForCheck();
370
355
  }
371
356
  };
372
357
  #activeRoute = async (fullUrl, route) => {
373
- if (!route?.component) {
358
+ if (!route?.component)
374
359
  return;
375
- }
376
360
  const component = route.component;
377
- const queryParams = {
378
- ...(route.queryParams || {}),
379
- };
380
- const params = {
381
- ...(route.params || {}),
382
- };
383
- const data = {
384
- ...(route.data || {}),
385
- };
361
+ const queryParams = { ...(route.queryParams || {}) };
362
+ const params = { ...(route.params || {}) };
363
+ const data = { ...(route.data || {}) };
386
364
  const [url] = fullUrl.split('?');
387
365
  const key = SdUtilities.hash({ url, queryParams });
388
366
  let existedIndex = -1;
389
367
  let activatedIndex = -1;
390
- this.tabs.forEach((tab, index) => {
368
+ const currentTabs = this.tabs();
369
+ currentTabs.forEach((tab, index) => {
391
370
  if (tab.key === key) {
392
371
  tab.isActive = true;
393
372
  existedIndex = index;
@@ -395,179 +374,126 @@ class SdTabRouterOutletComponent {
395
374
  else {
396
375
  if (tab.isActive) {
397
376
  activatedIndex = index;
398
- this.tabRouterService.pushEvent(tab, SdTabDeactivated);
377
+ this.#tabRouterService.pushEvent(tab, SdTabDeactivated);
399
378
  }
400
379
  tab.isActive = false;
401
380
  }
402
381
  });
403
- const currentNavigation = this.router.getCurrentNavigation();
404
- // Switch tab sẽ ko re-render lại trang
382
+ const currentNavigation = this.#router.getCurrentNavigation();
405
383
  const switchTab = currentNavigation?.extras?.state?.['switchTab'];
406
- // Replace tab sẽ close trang hiện tại
407
384
  const replaceTab = currentNavigation?.extras?.state?.['replaceTab'];
385
+ // --- XỬ LÝ INJECTOR VÀ FIX LỖI TYPE TS(2345) ---
386
+ const getBestInjector = async (snapshot) => {
387
+ // 1. Nếu là Standalone Route, lấy injector từ chính route config (đã được router resolve)
388
+ const routeInjector = snapshot._resolvedGui || snapshot.routeConfig?._injector;
389
+ if (routeInjector)
390
+ return routeInjector;
391
+ // 2. Xử lý NgModule (Lazy load kiểu cũ)
392
+ const loadChildren = snapshot.parent?.routeConfig?.loadChildren;
393
+ if (typeof loadChildren === 'function') {
394
+ let loaded = await loadChildren();
395
+ // Unwrap Observable
396
+ if (isObservable(loaded)) {
397
+ loaded = await lastValueFrom(loaded);
398
+ }
399
+ // Unwrap Default Export (ES Module)
400
+ if (loaded && typeof loaded === 'object' && 'default' in loaded) {
401
+ loaded = loaded.default;
402
+ }
403
+ // Nếu là NgModuleFactory (Angular cũ hơn)
404
+ if (loaded instanceof NgModuleFactory) {
405
+ return loaded.create(this.#injector).injector;
406
+ }
407
+ // Nếu là Type (Class NgModule) - Đây là chỗ fix lỗi TS(2345)
408
+ if (typeof loaded === 'function' && !Array.isArray(loaded)) {
409
+ try {
410
+ return createNgModule(loaded, this.#injector).injector;
411
+ }
412
+ catch {
413
+ return this.#injector;
414
+ }
415
+ }
416
+ }
417
+ return this.#injector;
418
+ };
419
+ const finalInjector = await getBestInjector(route);
420
+ const activatedRoute = this.#getActivatedRoute(this.#rootRoute, component);
421
+ const newTab = {
422
+ key,
423
+ component,
424
+ injector: new SdOutletInjector(activatedRoute, finalInjector),
425
+ isActive: true,
426
+ url,
427
+ params,
428
+ queryParams,
429
+ data,
430
+ tabInfoChanges: new Subject(),
431
+ };
408
432
  if (existedIndex >= 0) {
409
- const existedTab = this.tabs[existedIndex];
433
+ const updatedTabs = [...currentTabs];
410
434
  if (replaceTab && activatedIndex >= 0) {
411
- if (activatedIndex >= 0) {
412
- this.tabs.splice(activatedIndex, 1);
413
- }
435
+ updatedTabs.splice(activatedIndex, 1);
414
436
  }
415
437
  if (switchTab) {
416
- this.tabRouterService.setCurrentTab(existedTab);
417
- this.tabRouterService.pushEvent(existedTab, SdTabActivated);
438
+ this.#tabRouterService.setCurrentTab(updatedTabs[existedIndex]);
439
+ this.#tabRouterService.pushEvent(updatedTabs[existedIndex], SdTabActivated);
418
440
  }
419
441
  else {
420
- if (typeof route?.parent?.routeConfig?.loadChildren === 'function') {
421
- const module = (await route.parent.routeConfig.loadChildren());
422
- const moduleRef = createNgModule(module, this.injector);
423
- const activatedRoute = this.#getActivatedRoute(this.#rootRoute, component);
424
- const tab = {
425
- key,
426
- component,
427
- injector: new SdOutletInjector(activatedRoute, moduleRef),
428
- isActive: true,
429
- url,
430
- params,
431
- queryParams,
432
- data,
433
- tabInfoChanges: new Subject(),
434
- };
435
- this.tabs[this.tabs.indexOf(existedTab)] = tab;
436
- }
442
+ updatedTabs[existedIndex] = newTab;
437
443
  }
444
+ this.tabs.set(updatedTabs);
438
445
  }
439
446
  else {
440
- if (typeof route?.parent?.routeConfig?.loadChildren === 'function') {
441
- const module = (await route.parent.routeConfig.loadChildren());
442
- const moduleRef = createNgModule(module, this.injector);
443
- const activatedRoute = this.#getActivatedRoute(this.#rootRoute, component);
444
- const tab = {
445
- key,
446
- component,
447
- injector: new SdOutletInjector(activatedRoute, moduleRef),
448
- isActive: true,
449
- url,
450
- params,
451
- queryParams,
452
- data,
453
- tabInfoChanges: new Subject(),
454
- };
455
- this.tabRouterService.setCurrentTab(tab);
456
- if (activatedIndex >= 0 && replaceTab) {
457
- this.tabs.splice(activatedIndex, 1);
458
- }
459
- this.tabs.push(tab);
460
- // if (existedIndex >= 0 && !switchTab) {
461
- // this.tabs[existedIndex] = tab;
462
- // } else {
463
- // this.tabs.push(tab);
464
- // }
447
+ const updatedTabs = [...currentTabs];
448
+ this.#tabRouterService.setCurrentTab(newTab);
449
+ if (activatedIndex >= 0 && replaceTab) {
450
+ updatedTabs.splice(activatedIndex, 1);
465
451
  }
466
- this.tabRouterNav?.checkUI();
467
- if (this.tabs.length > 10) {
468
- this.sdNotifyService.warning('Bạn đã mở quá nhiều tab. Vui lòng tắt các tab không dùng để hệ thống hoạt động tốt hơn.');
452
+ this.tabs.set([...updatedTabs, newTab]);
453
+ if (this.tabs().length > 10) {
454
+ this.#sdNotifyService.warning('Bạn đã mở quá nhiều tab.');
469
455
  }
470
- // if (this.tabs.length > 15) {
471
- // this.tabs.splice(0, this.tabs.length - 10);
472
- // }
473
456
  }
474
- // if (existedIndex >= 0 && switchTab) {
475
- // const existedTab = this.tabs[existedIndex];
476
- // this.tabRouterService.setCurrentTab(existedTab);
477
- // this.tabRouterService.pushEvent(existedTab, SdTabActivated);
478
- // } else {
479
- // if (typeof route?.parent?.routeConfig?.loadChildren === 'function') {
480
- // const module = await route.parent.routeConfig.loadChildren();
481
- // const factory = await this.compiler.compileModuleAsync(module);
482
- // const injector = factory.create(this.injector);
483
- // const activatedRoute = this.#getActivatedRoute(
484
- // this.#rootRoute,
485
- // component
486
- // );
487
- // const tab = {
488
- // key,
489
- // component,
490
- // injector: new SdOutletInjector(activatedRoute, injector),
491
- // isActive: true,
492
- // name: url,
493
- // url,
494
- // params,
495
- // queryParams,
496
- // data
497
- // };
498
- // this.tabRouterService.setCurrentTab(tab);
499
- // if (activatedIndex >= 0 && replaceTab) {
500
- // this.tabs.splice(activatedIndex, 1);
501
- // }
502
- // if (existedIndex >= 0 && !switchTab) {
503
- // this.tabs[existedIndex] = tab;
504
- // } else {
505
- // this.tabs.push(tab);
506
- // }
507
- // }
508
- // this.tabRouterNav?.checkUI();
509
- // if (this.tabs.length > 10) {
510
- // this.sdNotifyService.notify.warning(
511
- // 'Bạn đã mở quá nhiều tab. Vui lòng tắt các tab không dùng để hệ thống hoạt động tốt hơn.'
512
- // );
513
- // }
514
- // if (this.tabs.length > 15) {
515
- // this.tabs.splice(0, this.tabs.length - 10);
516
- // }
517
- // }
518
- this.cd.markForCheck();
457
+ this.tabRouterNav?.checkUI();
519
458
  };
520
- #getActivatedRouteSnapshot = (activatedRouteSnapshot) => {
521
- if (!activatedRouteSnapshot) {
522
- return null;
523
- }
524
- while (activatedRouteSnapshot.firstChild) {
525
- activatedRouteSnapshot = activatedRouteSnapshot.firstChild;
526
- }
527
- return activatedRouteSnapshot;
459
+ #getActivatedRouteSnapshot = (snapshot) => {
460
+ let node = snapshot;
461
+ while (node.firstChild)
462
+ node = node.firstChild;
463
+ return node;
528
464
  };
529
465
  #getActivatedRoute = (activatedRoute, component) => {
530
- if (!activatedRoute) {
531
- return null;
532
- }
533
- if (activatedRoute.component && activatedRoute.component === component) {
466
+ if (activatedRoute.component === component)
534
467
  return activatedRoute;
535
- }
536
- while (activatedRoute.firstChild) {
537
- activatedRoute = activatedRoute.firstChild;
538
- if (activatedRoute.component && activatedRoute.component === component) {
539
- return activatedRoute;
540
- }
468
+ for (const child of activatedRoute.children) {
469
+ const result = this.#getActivatedRoute(child, component);
470
+ if (result)
471
+ return result;
541
472
  }
542
473
  return null;
543
474
  };
544
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterOutletComponent, deps: [{ token: i1.Router }, { token: i1.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: SdTabDecoratorService }, { token: SdTabRouterService }, { token: i4.SdNotifyService }], target: i0.ɵɵFactoryTarget.Component });
545
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", 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\n<div class=\"tab-router__list\">\n <ng-container *ngFor=\"let tab of tabs; trackBy: tabTrackBy\">\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 </ng-container>\n</div>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:calc(100vh - 64px)}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1}.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: i5.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdTabRouterNavComponent, selector: "sd-tab-router-nav", inputs: ["tabs"] }] });
475
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
476
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", 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\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>", styles: [":host{display:flex;flex-direction:column;width:100%;height:calc(100vh - 64px)}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1}.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.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdTabRouterNavComponent, selector: "sd-tab-router-nav", inputs: ["tabs"] }] });
546
477
  }
547
478
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdTabRouterOutletComponent, decorators: [{
548
479
  type: Component,
549
- 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\n<div class=\"tab-router__list\">\n <ng-container *ngFor=\"let tab of tabs; trackBy: tabTrackBy\">\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 </ng-container>\n</div>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:calc(100vh - 64px)}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1}.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"] }]
550
- }], ctorParameters: () => [{ type: i1.Router }, { type: i1.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: SdTabDecoratorService }, { type: SdTabRouterService }, { type: i4.SdNotifyService }], propDecorators: { tabRouterNav: [{
480
+ 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\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>", styles: [":host{display:flex;flex-direction:column;width:100%;height:calc(100vh - 64px)}:host ::ng-deep .sd-loading{max-width:100%;max-height:100%}.tab-router__list{flex:1}.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"] }]
481
+ }], ctorParameters: () => [], propDecorators: { tabRouterNav: [{
551
482
  type: ViewChild,
552
483
  args: ['tabRouterNav']
553
484
  }] } });
554
485
  class SdOutletInjector {
555
486
  route;
556
- parent;
557
- constructor(route,
558
- // private childContexts: ChildrenOutletContexts,
559
- parent) {
487
+ parentInjector;
488
+ constructor(route, parentInjector) {
560
489
  this.route = route;
561
- this.parent = parent;
490
+ this.parentInjector = parentInjector;
562
491
  }
563
492
  get(token, notFoundValue) {
564
- if (token === ActivatedRoute && this.route) {
565
- return this.route;
493
+ if (token === ActivatedRoute) {
494
+ return this.route || notFoundValue;
566
495
  }
567
- // if (token === ChildrenOutletContexts) {
568
- // return this.childContexts;
569
- // }
570
- return this.parent.injector.get(token, notFoundValue);
496
+ return this.parentInjector.get(token, notFoundValue);
571
497
  }
572
498
  }
573
499