@sd-angular/core 19.0.11 → 19.0.12

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 (87) hide show
  1. package/README.md +20 -20
  2. package/assets/STYLE-GUIDE.md +19 -19
  3. package/assets/fonts/fonts.scss +115 -115
  4. package/assets/scss/core/scrollbar.scss +30 -30
  5. package/assets/scss/core/utilities/_grid.scss +149 -149
  6. package/components/form-generic/src/components/form-builder/components/expression-builder/expression-builder.component.d.ts +1 -1
  7. package/components/form-generic/src/components/form-builder/components/table/control/table-control.component.d.ts +1 -1
  8. package/components/form-generic/src/components/sd-feel-expression/sd-feel-expression.component.d.ts +1 -1
  9. package/components/table/src/components/filter/column-filter/column-filter.component.d.ts +1 -1
  10. package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
  11. package/fesm2022/sd-angular-core-components-autoid-inspector.mjs.map +1 -1
  12. package/fesm2022/sd-angular-core-components-avatar.mjs +2 -2
  13. package/fesm2022/sd-angular-core-components-avatar.mjs.map +1 -1
  14. package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
  15. package/fesm2022/sd-angular-core-components-chart.mjs +40 -40
  16. package/fesm2022/sd-angular-core-components-chart.mjs.map +1 -1
  17. package/fesm2022/sd-angular-core-components-editor.mjs +2 -2
  18. package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
  19. package/fesm2022/sd-angular-core-components-form-generic.mjs +2 -2
  20. package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
  21. package/fesm2022/sd-angular-core-components-inform.mjs +2 -2
  22. package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -1
  23. package/fesm2022/sd-angular-core-components-modal.mjs +2 -2
  24. package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
  25. package/fesm2022/sd-angular-core-components-org-chart.mjs +2 -2
  26. package/fesm2022/sd-angular-core-components-org-chart.mjs.map +1 -1
  27. package/fesm2022/sd-angular-core-components-preview.mjs +4 -4
  28. package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
  29. package/fesm2022/sd-angular-core-components-query-bar.mjs +10 -10
  30. package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
  31. package/fesm2022/sd-angular-core-components-query-builder.mjs +2 -2
  32. package/fesm2022/sd-angular-core-components-query-builder.mjs.map +1 -1
  33. package/fesm2022/sd-angular-core-components-quick-action.mjs +2 -2
  34. package/fesm2022/sd-angular-core-components-quick-action.mjs.map +1 -1
  35. package/fesm2022/sd-angular-core-components-section.mjs +2 -2
  36. package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
  37. package/fesm2022/sd-angular-core-components-side-drawer.mjs +2 -2
  38. package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
  39. package/fesm2022/sd-angular-core-components-splitter.mjs +6 -6
  40. package/fesm2022/sd-angular-core-components-splitter.mjs.map +1 -1
  41. package/fesm2022/sd-angular-core-components-stepper.mjs +2 -2
  42. package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -1
  43. package/fesm2022/sd-angular-core-components-tab-router.mjs +60 -30
  44. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  45. package/fesm2022/sd-angular-core-components-tab.mjs +2 -2
  46. package/fesm2022/sd-angular-core-components-tab.mjs.map +1 -1
  47. package/fesm2022/sd-angular-core-components-table.mjs +31 -31
  48. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  49. package/fesm2022/sd-angular-core-components-tree.mjs +2 -2
  50. package/fesm2022/sd-angular-core-components-tree.mjs.map +1 -1
  51. package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
  52. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
  53. package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
  54. package/fesm2022/sd-angular-core-forms-date-range.mjs +2 -2
  55. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  56. package/fesm2022/sd-angular-core-forms-datetime.mjs +4 -4
  57. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  58. package/fesm2022/sd-angular-core-forms-inline-text.mjs.map +1 -1
  59. package/fesm2022/sd-angular-core-forms-input-number.mjs +2 -2
  60. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  61. package/fesm2022/sd-angular-core-forms-label.mjs +2 -2
  62. package/fesm2022/sd-angular-core-forms-label.mjs.map +1 -1
  63. package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
  64. package/fesm2022/sd-angular-core-forms-select.mjs +2 -2
  65. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  66. package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
  67. package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
  68. package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -1
  69. package/fesm2022/sd-angular-core-modules-layout.mjs +2 -2
  70. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  71. package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
  72. package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
  73. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  74. package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
  75. package/fesm2022/sd-angular-core-services-loading.mjs +23 -14
  76. package/fesm2022/sd-angular-core-services-loading.mjs.map +1 -1
  77. package/fesm2022/sd-angular-core-services-notify.mjs +2 -2
  78. package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
  79. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  80. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  81. package/fesm2022/sd-angular-core.mjs.map +1 -1
  82. package/modules/keycloak/htmls/auth-keycloak-error.html +54 -54
  83. package/modules/keycloak/htmls/silent-renew.html +7 -7
  84. package/package.json +67 -67
  85. package/sd-angular-core-19.0.12.tgz +0 -0
  86. package/services/loading/src/loading.service.d.ts +1 -1
  87. package/sd-angular-core-19.0.11.tgz +0 -0
@@ -108,11 +108,11 @@ class SdStepper {
108
108
  step?.selectChange.emit();
109
109
  }
110
110
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdStepper, isStandalone: true, selector: "sd-stepper", inputs: { selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, headerPosition: { classPropertyName: "headerPosition", publicName: "headerPosition", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, disableRipple: { classPropertyName: "disableRipple", publicName: "disableRipple", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange", selectionChange: "selectionChange" }, host: { properties: { "attr.data-autoId": "this.autoIdAttr", "style.--sd-stepper-active-color": "this.cssActive", "style.--sd-stepper-active-bg": "this.cssActiveBg", "style.--sd-stepper-completed-color": "this.cssCompleted", "style.--sd-stepper-line-active-color": "this.cssLine" } }, queries: [{ propertyName: "steps", predicate: SdStep, isSignal: true }], viewQueries: [{ propertyName: "matStepper", first: true, predicate: MatStepper, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-stepper\n class=\"sd-stepper\"\n [(selectedIndex)]=\"selectedIndex\"\n [linear]=\"linear()\"\n [orientation]=\"orientation()\"\n [labelPosition]=\"labelPosition()\"\n [headerPosition]=\"headerPosition()\"\n [animationDuration]=\"animationDuration()\"\n [disableRipple]=\"disableRipple()\"\n (selectionChange)=\"onSelectionChange($event)\">\n @for (step of steps(); track step; let i = $index) {\n <mat-step\n [stepControl]=\"step.stepControl() ?? undefined!\"\n [optional]=\"step.optional()\"\n [editable]=\"step.editable()\"\n [state]=\"step.state() ?? ''\"\n [errorMessage]=\"step.errorMessage() ?? ''\">\n <ng-template matStepLabel>\n <span class=\"sd-step__label\">\n @if (step.icon(); as ic) {\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\n }\n <span class=\"sd-step__text\">{{ step.label() }}</span>\n </span>\n </ng-template>\n\n <ng-template matStepContent>\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\n </ng-template>\n </mat-step>\n }\n</mat-stepper>\n", styles: [":host{display:block;--sd-stepper-active-color: var(--sd-primary, #1565c0);--sd-stepper-active-bg: var(--sd-primary, #1565c0);--sd-stepper-completed-color: var(--sd-primary, #1565c0);--sd-stepper-line-active-color: var(--sd-primary, #1565c0);--sd-stepper-error-color: var(--sd-error, #f44336);--sd-stepper-pending-bg: #e0e0e0;--sd-stepper-pending-color: rgba(0, 0, 0, .54);--sd-stepper-text-color: var(--sd-text-primary, #1a1a1a)}.sd-step__label{display:inline-flex;align-items:center;gap:4px}.sd-step__icon{font-size:18px;width:18px;height:18px;line-height:18px}.sd-step__text{white-space:nowrap}:host ::ng-deep .mat-step-icon{background-color:var(--sd-stepper-pending-bg);color:var(--sd-stepper-pending-color)}:host ::ng-deep .mat-step-icon-selected{background-color:var(--sd-stepper-active-bg)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-done,:host ::ng-deep .mat-step-icon-state-edit{background-color:var(--sd-stepper-completed-color)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-error{background-color:var(--sd-stepper-error-color)!important;color:#fff!important}:host ::ng-deep .mat-step-label.mat-step-label-active .mat-step-text-label{color:var(--sd-stepper-text-color);font-weight:500}:host ::ng-deep .mat-step-label-selected .mat-step-text-label{color:var(--sd-stepper-active-color);font-weight:600}:host ::ng-deep .mat-stepper-horizontal-line,:host ::ng-deep .mat-stepper-vertical-line:before{border-color:#0000001f}:host ::ng-deep .mat-step-header.cdk-program-focused,:host ::ng-deep .mat-step-header:hover{background-color:#00000005}\n"], dependencies: [{ kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i1.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i1.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i1.MatStepContent, selector: "ng-template[matStepContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
111
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdStepper, isStandalone: true, selector: "sd-stepper", inputs: { selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, labelPosition: { classPropertyName: "labelPosition", publicName: "labelPosition", isSignal: true, isRequired: false, transformFunction: null }, headerPosition: { classPropertyName: "headerPosition", publicName: "headerPosition", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, disableRipple: { classPropertyName: "disableRipple", publicName: "disableRipple", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange", selectionChange: "selectionChange" }, host: { properties: { "attr.data-autoId": "this.autoIdAttr", "style.--sd-stepper-active-color": "this.cssActive", "style.--sd-stepper-active-bg": "this.cssActiveBg", "style.--sd-stepper-completed-color": "this.cssCompleted", "style.--sd-stepper-line-active-color": "this.cssLine" } }, queries: [{ propertyName: "steps", predicate: SdStep, isSignal: true }], viewQueries: [{ propertyName: "matStepper", first: true, predicate: MatStepper, descendants: true, isSignal: true }], ngImport: i0, template: "<mat-stepper\r\n class=\"sd-stepper\"\r\n [(selectedIndex)]=\"selectedIndex\"\r\n [linear]=\"linear()\"\r\n [orientation]=\"orientation()\"\r\n [labelPosition]=\"labelPosition()\"\r\n [headerPosition]=\"headerPosition()\"\r\n [animationDuration]=\"animationDuration()\"\r\n [disableRipple]=\"disableRipple()\"\r\n (selectionChange)=\"onSelectionChange($event)\">\r\n @for (step of steps(); track step; let i = $index) {\r\n <mat-step\r\n [stepControl]=\"step.stepControl() ?? undefined!\"\r\n [optional]=\"step.optional()\"\r\n [editable]=\"step.editable()\"\r\n [state]=\"step.state() ?? ''\"\r\n [errorMessage]=\"step.errorMessage() ?? ''\">\r\n <ng-template matStepLabel>\r\n <span class=\"sd-step__label\">\r\n @if (step.icon(); as ic) {\r\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\r\n }\r\n <span class=\"sd-step__text\">{{ step.label() }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template matStepContent>\r\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\r\n </ng-template>\r\n </mat-step>\r\n }\r\n</mat-stepper>\r\n", styles: [":host{display:block;--sd-stepper-active-color: var(--sd-primary, #1565c0);--sd-stepper-active-bg: var(--sd-primary, #1565c0);--sd-stepper-completed-color: var(--sd-primary, #1565c0);--sd-stepper-line-active-color: var(--sd-primary, #1565c0);--sd-stepper-error-color: var(--sd-error, #f44336);--sd-stepper-pending-bg: #e0e0e0;--sd-stepper-pending-color: rgba(0, 0, 0, .54);--sd-stepper-text-color: var(--sd-text-primary, #1a1a1a)}.sd-step__label{display:inline-flex;align-items:center;gap:4px}.sd-step__icon{font-size:18px;width:18px;height:18px;line-height:18px}.sd-step__text{white-space:nowrap}:host ::ng-deep .mat-step-icon{background-color:var(--sd-stepper-pending-bg);color:var(--sd-stepper-pending-color)}:host ::ng-deep .mat-step-icon-selected{background-color:var(--sd-stepper-active-bg)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-done,:host ::ng-deep .mat-step-icon-state-edit{background-color:var(--sd-stepper-completed-color)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-error{background-color:var(--sd-stepper-error-color)!important;color:#fff!important}:host ::ng-deep .mat-step-label.mat-step-label-active .mat-step-text-label{color:var(--sd-stepper-text-color);font-weight:500}:host ::ng-deep .mat-step-label-selected .mat-step-text-label{color:var(--sd-stepper-active-color);font-weight:600}:host ::ng-deep .mat-stepper-horizontal-line,:host ::ng-deep .mat-stepper-vertical-line:before{border-color:#0000001f}:host ::ng-deep .mat-step-header.cdk-program-focused,:host ::ng-deep .mat-step-header:hover{background-color:#00000005}\n"], dependencies: [{ kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i1.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i1.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i1.MatStepContent, selector: "ng-template[matStepContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
112
112
  }
113
113
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdStepper, decorators: [{
114
114
  type: Component,
115
- args: [{ selector: 'sd-stepper', standalone: true, imports: [MatStepperModule, MatIconModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-stepper\n class=\"sd-stepper\"\n [(selectedIndex)]=\"selectedIndex\"\n [linear]=\"linear()\"\n [orientation]=\"orientation()\"\n [labelPosition]=\"labelPosition()\"\n [headerPosition]=\"headerPosition()\"\n [animationDuration]=\"animationDuration()\"\n [disableRipple]=\"disableRipple()\"\n (selectionChange)=\"onSelectionChange($event)\">\n @for (step of steps(); track step; let i = $index) {\n <mat-step\n [stepControl]=\"step.stepControl() ?? undefined!\"\n [optional]=\"step.optional()\"\n [editable]=\"step.editable()\"\n [state]=\"step.state() ?? ''\"\n [errorMessage]=\"step.errorMessage() ?? ''\">\n <ng-template matStepLabel>\n <span class=\"sd-step__label\">\n @if (step.icon(); as ic) {\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\n }\n <span class=\"sd-step__text\">{{ step.label() }}</span>\n </span>\n </ng-template>\n\n <ng-template matStepContent>\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\n </ng-template>\n </mat-step>\n }\n</mat-stepper>\n", styles: [":host{display:block;--sd-stepper-active-color: var(--sd-primary, #1565c0);--sd-stepper-active-bg: var(--sd-primary, #1565c0);--sd-stepper-completed-color: var(--sd-primary, #1565c0);--sd-stepper-line-active-color: var(--sd-primary, #1565c0);--sd-stepper-error-color: var(--sd-error, #f44336);--sd-stepper-pending-bg: #e0e0e0;--sd-stepper-pending-color: rgba(0, 0, 0, .54);--sd-stepper-text-color: var(--sd-text-primary, #1a1a1a)}.sd-step__label{display:inline-flex;align-items:center;gap:4px}.sd-step__icon{font-size:18px;width:18px;height:18px;line-height:18px}.sd-step__text{white-space:nowrap}:host ::ng-deep .mat-step-icon{background-color:var(--sd-stepper-pending-bg);color:var(--sd-stepper-pending-color)}:host ::ng-deep .mat-step-icon-selected{background-color:var(--sd-stepper-active-bg)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-done,:host ::ng-deep .mat-step-icon-state-edit{background-color:var(--sd-stepper-completed-color)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-error{background-color:var(--sd-stepper-error-color)!important;color:#fff!important}:host ::ng-deep .mat-step-label.mat-step-label-active .mat-step-text-label{color:var(--sd-stepper-text-color);font-weight:500}:host ::ng-deep .mat-step-label-selected .mat-step-text-label{color:var(--sd-stepper-active-color);font-weight:600}:host ::ng-deep .mat-stepper-horizontal-line,:host ::ng-deep .mat-stepper-vertical-line:before{border-color:#0000001f}:host ::ng-deep .mat-step-header.cdk-program-focused,:host ::ng-deep .mat-step-header:hover{background-color:#00000005}\n"] }]
115
+ args: [{ selector: 'sd-stepper', standalone: true, imports: [MatStepperModule, MatIconModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-stepper\r\n class=\"sd-stepper\"\r\n [(selectedIndex)]=\"selectedIndex\"\r\n [linear]=\"linear()\"\r\n [orientation]=\"orientation()\"\r\n [labelPosition]=\"labelPosition()\"\r\n [headerPosition]=\"headerPosition()\"\r\n [animationDuration]=\"animationDuration()\"\r\n [disableRipple]=\"disableRipple()\"\r\n (selectionChange)=\"onSelectionChange($event)\">\r\n @for (step of steps(); track step; let i = $index) {\r\n <mat-step\r\n [stepControl]=\"step.stepControl() ?? undefined!\"\r\n [optional]=\"step.optional()\"\r\n [editable]=\"step.editable()\"\r\n [state]=\"step.state() ?? ''\"\r\n [errorMessage]=\"step.errorMessage() ?? ''\">\r\n <ng-template matStepLabel>\r\n <span class=\"sd-step__label\">\r\n @if (step.icon(); as ic) {\r\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\r\n }\r\n <span class=\"sd-step__text\">{{ step.label() }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template matStepContent>\r\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\r\n </ng-template>\r\n </mat-step>\r\n }\r\n</mat-stepper>\r\n", styles: [":host{display:block;--sd-stepper-active-color: var(--sd-primary, #1565c0);--sd-stepper-active-bg: var(--sd-primary, #1565c0);--sd-stepper-completed-color: var(--sd-primary, #1565c0);--sd-stepper-line-active-color: var(--sd-primary, #1565c0);--sd-stepper-error-color: var(--sd-error, #f44336);--sd-stepper-pending-bg: #e0e0e0;--sd-stepper-pending-color: rgba(0, 0, 0, .54);--sd-stepper-text-color: var(--sd-text-primary, #1a1a1a)}.sd-step__label{display:inline-flex;align-items:center;gap:4px}.sd-step__icon{font-size:18px;width:18px;height:18px;line-height:18px}.sd-step__text{white-space:nowrap}:host ::ng-deep .mat-step-icon{background-color:var(--sd-stepper-pending-bg);color:var(--sd-stepper-pending-color)}:host ::ng-deep .mat-step-icon-selected{background-color:var(--sd-stepper-active-bg)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-done,:host ::ng-deep .mat-step-icon-state-edit{background-color:var(--sd-stepper-completed-color)!important;color:#fff!important}:host ::ng-deep .mat-step-icon-state-error{background-color:var(--sd-stepper-error-color)!important;color:#fff!important}:host ::ng-deep .mat-step-label.mat-step-label-active .mat-step-text-label{color:var(--sd-stepper-text-color);font-weight:500}:host ::ng-deep .mat-step-label-selected .mat-step-text-label{color:var(--sd-stepper-active-color);font-weight:600}:host ::ng-deep .mat-stepper-horizontal-line,:host ::ng-deep .mat-stepper-vertical-line:before{border-color:#0000001f}:host ::ng-deep .mat-step-header.cdk-program-focused,:host ::ng-deep .mat-step-header:hover{background-color:#00000005}\n"] }]
116
116
  }], ctorParameters: () => [], propDecorators: { autoIdAttr: [{
117
117
  type: HostBinding,
118
118
  args: ['attr.data-autoId']
@@ -1 +1 @@
1
- {"version":3,"file":"sd-angular-core-components-stepper.mjs","sources":["../../../projects/sd-angular/components/stepper/src/step.component.ts","../../../projects/sd-angular/components/stepper/src/stepper.component.ts","../../../projects/sd-angular/components/stepper/src/stepper.component.html","../../../projects/sd-angular/components/stepper/sd-angular-core-components-stepper.ts"],"sourcesContent":["import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n input,\n output,\n TemplateRef,\n viewChild,\n} from '@angular/core';\nimport { AbstractControl } from '@angular/forms';\n\nexport type SdStepState = 'pending' | 'active' | 'completed' | 'error' | string;\n\n@Component({\n selector: 'sd-step',\n standalone: true,\n // why: identical pattern to <sd-tab> — capture projected content via #body\n // template ref so <sd-stepper> can render it inside mat-step's matStepContent\n // (lazy mount + animation-friendly).\n template: `<ng-template #body><ng-content></ng-content></ng-template>`,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SdStep {\n label = input.required<string>();\n // Optional Material icon name shown when the step is in 'pending' state\n // (overrides the default numbered indicator).\n icon = input<string | null | undefined>(undefined);\n // Set true to mark the step skippable in linear mode.\n optional = input(false, { transform: booleanAttribute });\n // When false, user cannot return to this step after it's been completed.\n editable = input(true, { transform: booleanAttribute });\n // Reactive form / control. When the stepper is linear, the user can only\n // proceed past this step once stepControl.valid is true.\n stepControl = input<AbstractControl | null | undefined>(undefined);\n // Override the auto-derived state (eg force 'error' from outside on async validation).\n state = input<SdStepState | undefined>(undefined);\n // Error message rendered next to the step header when state is 'error'.\n errorMessage = input<string | undefined>(undefined);\n\n // Emitted when this step transitions to selected.\n selectChange = output<void>();\n\n // Body template captured from projected <ng-content>.\n bodyTpl = viewChild.required<TemplateRef<unknown>>('body');\n}\n","import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n booleanAttribute,\r\n ChangeDetectionStrategy,\r\n Component,\r\n contentChildren,\r\n effect,\r\n HostBinding,\r\n input,\r\n model,\r\n output,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { StepperSelectionEvent } from '@angular/cdk/stepper';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatStepperModule, MatStepper } from '@angular/material/stepper';\r\nimport { Color } from '@sdcorejs/utils/models';\r\nimport { SdStep } from './step.component';\r\n\r\n@Component({\r\n selector: 'sd-stepper',\r\n standalone: true,\r\n imports: [MatStepperModule, MatIconModule, NgTemplateOutlet],\r\n templateUrl: './stepper.component.html',\r\n styleUrl: './stepper.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SdStepper {\r\n steps = contentChildren(SdStep);\r\n\r\n selectedIndex = model<number>(0);\r\n // why: enforce sequential gating — only valid steps unlock the next.\r\n linear = input(false, { transform: booleanAttribute });\r\n orientation = input<'horizontal' | 'vertical'>('horizontal');\r\n labelPosition = input<'end' | 'bottom'>('end');\r\n headerPosition = input<'top' | 'bottom'>('top');\r\n animationDuration = input<string>('500ms');\r\n disableRipple = input(false, { transform: booleanAttribute });\r\n // Drives the Core color CSS vars on indicators / connector / line.\r\n color = input<Color>('primary');\r\n autoId = input<string | undefined>(undefined);\r\n\r\n // Emits {previousIndex, selectedIndex, previousStep, selectedStep}.\r\n selectionChange = output<StepperSelectionEvent>();\r\n\r\n protected matStepper = viewChild(MatStepper);\r\n\r\n @HostBinding('attr.data-autoId') get autoIdAttr(): string | null {\r\n return this.autoId() ?? null;\r\n }\r\n\r\n // Core color CSS vars — same mechanism as <sd-tab-group>.\r\n @HostBinding('style.--sd-stepper-active-color') get cssActive(): string {\r\n return `var(--sd-${this.color()})`;\r\n }\r\n @HostBinding('style.--sd-stepper-active-bg') get cssActiveBg(): string {\r\n return `var(--sd-${this.color()})`;\r\n }\r\n @HostBinding('style.--sd-stepper-completed-color') get cssCompleted(): string {\r\n return `var(--sd-${this.color()})`;\r\n }\r\n @HostBinding('style.--sd-stepper-line-active-color') get cssLine(): string {\r\n return `var(--sd-${this.color()})`;\r\n }\r\n\r\n constructor() {\r\n // why: clamp selectedIndex when a step is removed past the active one.\r\n effect(() => {\r\n const len = this.steps().length;\r\n const cur = untracked(() => this.selectedIndex());\r\n if (len > 0 && cur >= len) {\r\n this.selectedIndex.set(Math.max(0, len - 1));\r\n }\r\n });\r\n }\r\n\r\n next(): void {\r\n this.matStepper()?.next();\r\n }\r\n\r\n previous(): void {\r\n this.matStepper()?.previous();\r\n }\r\n\r\n reset(): void {\r\n this.matStepper()?.reset();\r\n }\r\n\r\n goTo(index: number): void {\r\n const len = this.steps().length;\r\n if (len === 0) {\r\n this.selectedIndex.set(0);\r\n return;\r\n }\r\n this.selectedIndex.set(Math.max(0, Math.min(index, len - 1)));\r\n }\r\n\r\n protected onSelectionChange(ev: StepperSelectionEvent): void {\r\n this.selectionChange.emit(ev);\r\n // Forward to each step that just became selected so consumer can react.\r\n const step = this.steps()[ev.selectedIndex];\r\n step?.selectChange.emit();\r\n }\r\n}\r\n","<mat-stepper\n class=\"sd-stepper\"\n [(selectedIndex)]=\"selectedIndex\"\n [linear]=\"linear()\"\n [orientation]=\"orientation()\"\n [labelPosition]=\"labelPosition()\"\n [headerPosition]=\"headerPosition()\"\n [animationDuration]=\"animationDuration()\"\n [disableRipple]=\"disableRipple()\"\n (selectionChange)=\"onSelectionChange($event)\">\n @for (step of steps(); track step; let i = $index) {\n <mat-step\n [stepControl]=\"step.stepControl() ?? undefined!\"\n [optional]=\"step.optional()\"\n [editable]=\"step.editable()\"\n [state]=\"step.state() ?? ''\"\n [errorMessage]=\"step.errorMessage() ?? ''\">\n <ng-template matStepLabel>\n <span class=\"sd-step__label\">\n @if (step.icon(); as ic) {\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\n }\n <span class=\"sd-step__text\">{{ step.label() }}</span>\n </span>\n </ng-template>\n\n <ng-template matStepContent>\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\n </ng-template>\n </mat-step>\n }\n</mat-stepper>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sd-angular-core-components-stepper.mjs","sources":["../../../projects/sd-angular/components/stepper/src/step.component.ts","../../../projects/sd-angular/components/stepper/src/stepper.component.ts","../../../projects/sd-angular/components/stepper/src/stepper.component.html","../../../projects/sd-angular/components/stepper/sd-angular-core-components-stepper.ts"],"sourcesContent":["import {\r\n booleanAttribute,\r\n ChangeDetectionStrategy,\r\n Component,\r\n input,\r\n output,\r\n TemplateRef,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { AbstractControl } from '@angular/forms';\r\n\r\nexport type SdStepState = 'pending' | 'active' | 'completed' | 'error' | string;\r\n\r\n@Component({\r\n selector: 'sd-step',\r\n standalone: true,\r\n // why: identical pattern to <sd-tab> — capture projected content via #body\r\n // template ref so <sd-stepper> can render it inside mat-step's matStepContent\r\n // (lazy mount + animation-friendly).\r\n template: `<ng-template #body><ng-content></ng-content></ng-template>`,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SdStep {\r\n label = input.required<string>();\r\n // Optional Material icon name shown when the step is in 'pending' state\r\n // (overrides the default numbered indicator).\r\n icon = input<string | null | undefined>(undefined);\r\n // Set true to mark the step skippable in linear mode.\r\n optional = input(false, { transform: booleanAttribute });\r\n // When false, user cannot return to this step after it's been completed.\r\n editable = input(true, { transform: booleanAttribute });\r\n // Reactive form / control. When the stepper is linear, the user can only\r\n // proceed past this step once stepControl.valid is true.\r\n stepControl = input<AbstractControl | null | undefined>(undefined);\r\n // Override the auto-derived state (eg force 'error' from outside on async validation).\r\n state = input<SdStepState | undefined>(undefined);\r\n // Error message rendered next to the step header when state is 'error'.\r\n errorMessage = input<string | undefined>(undefined);\r\n\r\n // Emitted when this step transitions to selected.\r\n selectChange = output<void>();\r\n\r\n // Body template captured from projected <ng-content>.\r\n bodyTpl = viewChild.required<TemplateRef<unknown>>('body');\r\n}\r\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n contentChildren,\n effect,\n HostBinding,\n input,\n model,\n output,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { StepperSelectionEvent } from '@angular/cdk/stepper';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatStepperModule, MatStepper } from '@angular/material/stepper';\nimport { Color } from '@sdcorejs/utils/models';\nimport { SdStep } from './step.component';\n\n@Component({\n selector: 'sd-stepper',\n standalone: true,\n imports: [MatStepperModule, MatIconModule, NgTemplateOutlet],\n templateUrl: './stepper.component.html',\n styleUrl: './stepper.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SdStepper {\n steps = contentChildren(SdStep);\n\n selectedIndex = model<number>(0);\n // why: enforce sequential gating — only valid steps unlock the next.\n linear = input(false, { transform: booleanAttribute });\n orientation = input<'horizontal' | 'vertical'>('horizontal');\n labelPosition = input<'end' | 'bottom'>('end');\n headerPosition = input<'top' | 'bottom'>('top');\n animationDuration = input<string>('500ms');\n disableRipple = input(false, { transform: booleanAttribute });\n // Drives the Core color CSS vars on indicators / connector / line.\n color = input<Color>('primary');\n autoId = input<string | undefined>(undefined);\n\n // Emits {previousIndex, selectedIndex, previousStep, selectedStep}.\n selectionChange = output<StepperSelectionEvent>();\n\n protected matStepper = viewChild(MatStepper);\n\n @HostBinding('attr.data-autoId') get autoIdAttr(): string | null {\n return this.autoId() ?? null;\n }\n\n // Core color CSS vars — same mechanism as <sd-tab-group>.\n @HostBinding('style.--sd-stepper-active-color') get cssActive(): string {\n return `var(--sd-${this.color()})`;\n }\n @HostBinding('style.--sd-stepper-active-bg') get cssActiveBg(): string {\n return `var(--sd-${this.color()})`;\n }\n @HostBinding('style.--sd-stepper-completed-color') get cssCompleted(): string {\n return `var(--sd-${this.color()})`;\n }\n @HostBinding('style.--sd-stepper-line-active-color') get cssLine(): string {\n return `var(--sd-${this.color()})`;\n }\n\n constructor() {\n // why: clamp selectedIndex when a step is removed past the active one.\n effect(() => {\n const len = this.steps().length;\n const cur = untracked(() => this.selectedIndex());\n if (len > 0 && cur >= len) {\n this.selectedIndex.set(Math.max(0, len - 1));\n }\n });\n }\n\n next(): void {\n this.matStepper()?.next();\n }\n\n previous(): void {\n this.matStepper()?.previous();\n }\n\n reset(): void {\n this.matStepper()?.reset();\n }\n\n goTo(index: number): void {\n const len = this.steps().length;\n if (len === 0) {\n this.selectedIndex.set(0);\n return;\n }\n this.selectedIndex.set(Math.max(0, Math.min(index, len - 1)));\n }\n\n protected onSelectionChange(ev: StepperSelectionEvent): void {\n this.selectionChange.emit(ev);\n // Forward to each step that just became selected so consumer can react.\n const step = this.steps()[ev.selectedIndex];\n step?.selectChange.emit();\n }\n}\n","<mat-stepper\r\n class=\"sd-stepper\"\r\n [(selectedIndex)]=\"selectedIndex\"\r\n [linear]=\"linear()\"\r\n [orientation]=\"orientation()\"\r\n [labelPosition]=\"labelPosition()\"\r\n [headerPosition]=\"headerPosition()\"\r\n [animationDuration]=\"animationDuration()\"\r\n [disableRipple]=\"disableRipple()\"\r\n (selectionChange)=\"onSelectionChange($event)\">\r\n @for (step of steps(); track step; let i = $index) {\r\n <mat-step\r\n [stepControl]=\"step.stepControl() ?? undefined!\"\r\n [optional]=\"step.optional()\"\r\n [editable]=\"step.editable()\"\r\n [state]=\"step.state() ?? ''\"\r\n [errorMessage]=\"step.errorMessage() ?? ''\">\r\n <ng-template matStepLabel>\r\n <span class=\"sd-step__label\">\r\n @if (step.icon(); as ic) {\r\n <mat-icon class=\"sd-step__icon\">{{ ic }}</mat-icon>\r\n }\r\n <span class=\"sd-step__text\">{{ step.label() }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template matStepContent>\r\n <ng-container [ngTemplateOutlet]=\"step.bodyTpl()\"></ng-container>\r\n </ng-template>\r\n </mat-step>\r\n }\r\n</mat-stepper>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Injectable, Pipe, Input, ChangeDetectionStrategy, Component, viewChild, input, inject, ChangeDetectorRef, ElementRef, HostListener, booleanAttribute, signal, Injector, afterNextRender, NgModuleFactory, createNgModule } from '@angular/core';
3
3
  import * as i2 from '@angular/router';
4
- import { Router, RoutesRecognized, NavigationEnd, RouterOutlet, ActivatedRoute } from '@angular/router';
4
+ import { Router, RoutesRecognized, NavigationEnd, NavigationSkipped, NavigationCancel, NavigationError, NavigationSkippedCode, RouterOutlet, ActivatedRoute } from '@angular/router';
5
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';
9
9
  import { MatTooltipModule } from '@angular/material/tooltip';
10
10
  import { BehaviorSubject, Subscription, from, isObservable, lastValueFrom, Subject } from 'rxjs';
11
- import { debounceTime, startWith, filter, concatMap, take } from 'rxjs/operators';
11
+ import { debounceTime, startWith, filter, map, concatMap, take } from 'rxjs/operators';
12
12
  import { SdNotifyService } from '@sd-angular/core/services/notify';
13
13
  import { I18nService } from '@sd-angular/core/i18n';
14
14
  import { Utilities } from '@sdcorejs/utils/fns';
@@ -262,11 +262,11 @@ class SdTabRouterNavComponent {
262
262
  moveItemInArray(this.tabs(), event.previousIndex, event.currentIndex);
263
263
  };
264
264
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
265
- 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\r\n #tabRouterNav\r\n cdkDropList\r\n cdkDropListLockAxis=\"x\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\r\n [class.d-none]=\"tabs().length > 1\">\r\n @for (tab of tabs(); track tab.key) {\r\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\r\n }\r\n</div>\r\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 });
265
+ 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\r\n #tabRouterNav\r\n cdkDropList\r\n cdkDropListLockAxis=\"x\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\r\n [class.d-none]=\"tabs().length > 1\">\r\n @for (tab of tabs(); track tab.injector ?? tab.key) {\r\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\r\n }\r\n</div>\r\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 });
266
266
  }
267
267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterNavComponent, decorators: [{
268
268
  type: Component,
269
- args: [{ selector: 'sd-tab-router-nav', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DragDropModule, SdTabRouterItemComponent], template: "<div\r\n #tabRouterNav\r\n cdkDropList\r\n cdkDropListLockAxis=\"x\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\r\n [class.d-none]=\"tabs().length > 1\">\r\n @for (tab of tabs(); track tab.key) {\r\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\r\n }\r\n</div>\r\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"] }]
269
+ args: [{ selector: 'sd-tab-router-nav', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DragDropModule, SdTabRouterItemComponent], template: "<div\r\n #tabRouterNav\r\n cdkDropList\r\n cdkDropListLockAxis=\"x\"\r\n cdkDropListOrientation=\"horizontal\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"tab-router__nav tab-router__nav--{{ mode }} d-flex align-items-center flex-nowrap\"\r\n [class.d-none]=\"tabs().length > 1\">\r\n @for (tab of tabs(); track tab.injector ?? tab.key) {\r\n <sd-tab-router-item [tab]=\"tab\" cdkDrag [cdkDragBoundary]=\"elementRef.nativeElement\"></sd-tab-router-item>\r\n }\r\n</div>\r\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"] }]
270
270
  }], propDecorators: { onResize: [{
271
271
  type: HostListener,
272
272
  args: ['window:resize']
@@ -288,10 +288,8 @@ class SdTabRouterOutletComponent {
288
288
  #tabDecoratorService = inject(SdTabDecoratorService);
289
289
  #rootRoute;
290
290
  #subscription = new Subscription();
291
- // State của navigation hiện tại (replaceTab, switchTab, ...) được capture RoutesRecognized
292
- // dùng lại ở NavigationEnd. Lý do: tại NavigationEnd, getCurrentNavigation() đã trả về null,
293
- // còn lastSuccessfulNavigation và window.history.state không đáng tin cậy với mọi case.
294
- #pendingNavigationState = {};
291
+ // Lưu state theo navigation id để các navigation chồng lấn không ghi đè lẫn nhau.
292
+ #pendingNavigationStates = new Map();
295
293
  // Serialize mọi #activeRoute (router events + initial sync) để tránh race tạo duplicate tab.
296
294
  #activationQueue = Promise.resolve();
297
295
  constructor() {
@@ -300,13 +298,23 @@ class SdTabRouterOutletComponent {
300
298
  // KHÔNG unwrap event.routerEvent (vd Scroll wrap NavigationEnd):
301
299
  // Angular emit NavigationEnd RAW trước, RouterScroller emit Scroll(NavigationEnd) sau.
302
300
  // Nếu unwrap thêm Scroll → handler fire 2 lần cho 1 nav → race condition tạo duplicate tabs.
303
- // Hybrid: cần CẢ HAI event vì mỗi event chứa data khác nhau ở thời điểm khác nhau.
301
+ // Navigation thành công cần CẢ HAI event vì mỗi event chứa data ở thời điểm khác nhau.
304
302
  // - RoutesRecognized: navigation đang in-flight → getCurrentNavigation().extras.state đọc được
305
303
  // - NavigationEnd: navigation hoàn tất → routerState.root đã update với route mới (cần cho lazy routes)
306
- filter((event) => event instanceof RoutesRecognized || event instanceof NavigationEnd),
304
+ // Các terminal event khác chỉ xử same-URL forceReload hoặc dọn state theo navigation id.
305
+ filter((event) => event instanceof RoutesRecognized ||
306
+ event instanceof NavigationEnd ||
307
+ event instanceof NavigationSkipped ||
308
+ event instanceof NavigationCancel ||
309
+ event instanceof NavigationError),
310
+ // Chụp getCurrentNavigation đồng bộ vì concatMap có thể chạy sau khi Angular đã xoá navigation hiện tại.
311
+ map((event) => ({
312
+ event,
313
+ navigationState: this.#router.getCurrentNavigation()?.extras?.state ?? {},
314
+ })),
307
315
  // Serialize: #handleEvent async (await getBestInjector). 2 nav liên tiếp
308
316
  // không await xen kẽ → tránh race đọc this.tabs() = [] khi tab đầu chưa kịp set.
309
- concatMap(event => from(this.#handleEvent(event))))
317
+ concatMap(context => from(this.#handleEvent(context))))
310
318
  .subscribe());
311
319
  this.#subscription.add(this.#tabRouterService.actions.subscribe((event) => {
312
320
  if (this.disabled())
@@ -323,31 +331,45 @@ class SdTabRouterOutletComponent {
323
331
  }
324
332
  ngOnDestroy() {
325
333
  this.#subscription.unsubscribe();
334
+ this.#pendingNavigationStates.clear();
326
335
  }
327
336
  #scheduleActivation = (task) => {
328
337
  const run = this.#activationQueue.then(task);
329
338
  this.#activationQueue = run.catch(() => undefined);
330
339
  return run;
331
340
  };
332
- #handleEvent = async (event) => {
341
+ #handleEvent = async ({ event, navigationState }) => {
333
342
  if (this.disabled()) {
334
- this.#pendingNavigationState = {};
343
+ this.#pendingNavigationStates.clear();
335
344
  return;
336
345
  }
337
346
  if (event instanceof RoutesRecognized) {
338
- // Capture state ngay lúc nav còn in-flight. Đây là điểm duy nhất chắc chắn
339
- // getCurrentNavigation() trả về Navigation object với extras.state nguyên vẹn.
340
- this.#pendingNavigationState = this.#router.getCurrentNavigation()?.extras?.state ?? {};
347
+ this.#pendingNavigationStates.set(event.id, navigationState);
341
348
  return;
342
349
  }
343
- // NavigationEnd: dùng routerState.snapshot.root (canonical state tại NavigationEnd),
344
- // KHÔNG dùng injected ActivatedRoute.snapshot — có thể chưa sync trên initial load.
345
- const navigationState = this.#pendingNavigationState;
346
- this.#pendingNavigationState = {};
350
+ if (event instanceof NavigationCancel || event instanceof NavigationError) {
351
+ this.#pendingNavigationStates.delete(event.id);
352
+ return;
353
+ }
354
+ let state;
355
+ let fullUrl;
356
+ if (event instanceof NavigationSkipped) {
357
+ this.#pendingNavigationStates.delete(event.id);
358
+ if (event.code !== NavigationSkippedCode.IgnoredSameUrlNavigation || navigationState['forceReload'] !== true) {
359
+ return;
360
+ }
361
+ state = navigationState;
362
+ fullUrl = event.url;
363
+ }
364
+ else {
365
+ state = this.#pendingNavigationStates.get(event.id) ?? navigationState;
366
+ this.#pendingNavigationStates.delete(event.id);
367
+ fullUrl = event.urlAfterRedirects || event.url;
368
+ }
347
369
  await this.#scheduleActivation(async () => {
348
370
  const route = this.#getActivatedRouteSnapshot(this.#router.routerState.snapshot.root);
349
371
  this.#rootRoute = this.#router.routerState.root;
350
- await this.#activeRoute(event.urlAfterRedirects || event.url, route, navigationState);
372
+ await this.#activeRoute(fullUrl, route, state);
351
373
  });
352
374
  };
353
375
  // Bù initial navigation nếu NavigationEnd đã fire trước khi outlet subscribe.
@@ -422,7 +444,7 @@ class SdTabRouterOutletComponent {
422
444
  const params = { ...(route.params || {}) };
423
445
  const data = { ...(route.data || {}) };
424
446
  const [url] = fullUrl.split('?');
425
- // Tab identity = hash(url + queryParams). Cùng key = cùng tab, không tạo lại.
447
+ // Tab identity = hash(url + queryParams). Cùng key mặc định giữ tab cũ; forceReload mới tạo lại.
426
448
  const key = Utilities.hash({ url, queryParams });
427
449
  let existedIndex = -1;
428
450
  let activatedIndex = -1;
@@ -449,6 +471,7 @@ class SdTabRouterOutletComponent {
449
471
  }
450
472
  }
451
473
  const replaceTab = state['replaceTab'];
474
+ const forceReload = state['forceReload'] === true;
452
475
  // Resolve injector phù hợp với route. Cần xử lý 3 trường hợp:
453
476
  // - Standalone route (Angular đã set _injector trên routeConfig sau khi activate)
454
477
  // - NgModule lazy load (cần createNgModule từ class)
@@ -518,17 +541,24 @@ class SdTabRouterOutletComponent {
518
541
  updatedTabs = updatedTabs.filter((_, i) => i !== activatedIndex);
519
542
  }
520
543
  if (existedIndex >= 0) {
521
- // Tab đã tồn tại (cùng url + queryParams) → CHỈ activate, KHÔNG thay tab object.
522
- // do: thay tab object = đổi reference của tab.injector ngComponentOutlet recreate
523
- // component → tab bị "reload" mỗi khi click lại hoặc navigate cùng URL.
544
+ // Mặc định tab đã tồn tại chỉ được activate, không thay tab object. forceReload là nhánh
545
+ // explicit duy nhất thay SdTab + injector để body nav item được tạo lại.
524
546
  //
525
547
  // splice phía trên có thể đã shift index nếu activatedIndex < existedIndex.
526
548
  const idx = replaceTab && activatedIndex >= 0 && activatedIndex < existedIndex
527
549
  ? existedIndex - 1
528
550
  : existedIndex;
529
- this.#tabRouterService.setCurrentTab(updatedTabs[idx]);
530
- this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);
531
- this.tabs.set(updatedTabs);
551
+ if (forceReload) {
552
+ updatedTabs = updatedTabs.map((tab, index) => (index === idx ? newTab : tab));
553
+ this.#tabRouterService.setCurrentTab(newTab);
554
+ this.#tabRouterService.pushEvent(newTab, SdTabActivated);
555
+ this.tabs.set(updatedTabs);
556
+ }
557
+ else {
558
+ this.#tabRouterService.setCurrentTab(updatedTabs[idx]);
559
+ this.#tabRouterService.pushEvent(updatedTabs[idx], SdTabActivated);
560
+ this.tabs.set(updatedTabs);
561
+ }
532
562
  }
533
563
  else {
534
564
  // Tab chưa tồn tại → thêm mới ở cuối.
@@ -561,11 +591,11 @@ class SdTabRouterOutletComponent {
561
591
  return null;
562
592
  };
563
593
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
564
- 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()) {\r\n <div class=\"tab-router__disabled-outlet\">\r\n <router-outlet></router-outlet>\r\n </div>\r\n} @else {\r\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\r\n <div class=\"tab-router__list\">\r\n @for (tab of tabs(); track tab.key) {\r\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\r\n <div class=\"tab-router__content\">\r\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"tab-router__empty\">\r\n </div>\r\n }\r\n </div>\r\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"] }] });
594
+ 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()) {\r\n <div class=\"tab-router__disabled-outlet\">\r\n <router-outlet></router-outlet>\r\n </div>\r\n} @else {\r\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\r\n <div class=\"tab-router__list\">\r\n @for (tab of tabs(); track tab.injector ?? tab.key) {\r\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\r\n <div class=\"tab-router__content\">\r\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"tab-router__empty\">\r\n </div>\r\n }\r\n </div>\r\n}\r\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"] }] });
565
595
  }
566
596
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdTabRouterOutletComponent, decorators: [{
567
597
  type: Component,
568
- args: [{ selector: 'sd-tab-router-outlet', standalone: true, imports: [CommonModule, MatIconModule, MatTooltipModule, RouterOutlet, SdTabRouterNavComponent], template: "@if (disabled()) {\r\n <div class=\"tab-router__disabled-outlet\">\r\n <router-outlet></router-outlet>\r\n </div>\r\n} @else {\r\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\r\n <div class=\"tab-router__list\">\r\n @for (tab of tabs(); track tab.key) {\r\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\r\n <div class=\"tab-router__content\">\r\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"tab-router__empty\">\r\n </div>\r\n }\r\n </div>\r\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"] }]
598
+ args: [{ selector: 'sd-tab-router-outlet', standalone: true, imports: [CommonModule, MatIconModule, MatTooltipModule, RouterOutlet, SdTabRouterNavComponent], template: "@if (disabled()) {\r\n <div class=\"tab-router__disabled-outlet\">\r\n <router-outlet></router-outlet>\r\n </div>\r\n} @else {\r\n <sd-tab-router-nav [tabs]=\"tabs()\" #tabRouterNav></sd-tab-router-nav>\r\n <div class=\"tab-router__list\">\r\n @for (tab of tabs(); track tab.injector ?? tab.key) {\r\n <div class=\"tab-router__pane\" [class.active]=\"tab.isActive\" [id]=\"tab.key\">\r\n <div class=\"tab-router__content\">\r\n <ng-container *ngComponentOutlet=\"tab.component; injector: tab.injector\"></ng-container>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div class=\"tab-router__empty\">\r\n </div>\r\n }\r\n </div>\r\n}\r\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"] }]
569
599
  }], ctorParameters: () => [] });
570
600
  // Custom Injector cho từng tab: override ActivatedRoute thành route của TAB ĐÓ
571
601
  // (không phải route hiện tại của router). Nếu không override, mọi tab sẽ inject ActivatedRoute