@nova-design-system/nova-angular-18 3.19.0 → 3.21.0

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.
@@ -43,9 +43,10 @@ export const DIRECTIVES = [
43
43
  d.NvSplit,
44
44
  d.NvStack,
45
45
  d.NvTable,
46
+ d.NvTableheader,
46
47
  d.NvToggle,
47
48
  d.NvTogglebutton,
48
49
  d.NvTogglebuttongroup,
49
50
  d.NvTooltip
50
51
  ];
51
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ub3ZhLWNvbXBvbmVudHMvc3JjL2xpYi9zdGVuY2lsLWdlbmVyYXRlZC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssQ0FBQyxNQUFNLGNBQWMsQ0FBQztBQUVsQyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUc7SUFDeEIsQ0FBQyxDQUFDLFdBQVc7SUFDYixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsT0FBTztJQUNULENBQUMsQ0FBQyxRQUFRO0lBQ1YsQ0FBQyxDQUFDLE9BQU87SUFDVCxDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxhQUFhO0lBQ2YsQ0FBQyxDQUFDLFFBQVE7SUFDVixDQUFDLENBQUMsYUFBYTtJQUNmLENBQUMsQ0FBQyxVQUFVO0lBQ1osQ0FBQyxDQUFDLEtBQUs7SUFDUCxDQUFDLENBQUMsVUFBVTtJQUNaLENBQUMsQ0FBQyxnQkFBZ0I7SUFDbEIsQ0FBQyxDQUFDLFFBQVE7SUFDVixDQUFDLENBQUMsY0FBYztJQUNoQixDQUFDLENBQUMsY0FBYztJQUNoQixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsV0FBVztJQUNiLENBQUMsQ0FBQyxnQkFBZ0I7SUFDbEIsQ0FBQyxDQUFDLGVBQWU7SUFDakIsQ0FBQyxDQUFDLG1CQUFtQjtJQUNyQixDQUFDLENBQUMsd0JBQXdCO0lBQzFCLENBQUMsQ0FBQyxrQkFBa0I7SUFDcEIsQ0FBQyxDQUFDLGFBQWE7SUFDZixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxhQUFhO0lBQ2YsQ0FBQyxDQUFDLGFBQWE7SUFDZixDQUFDLENBQUMsV0FBVztJQUNiLENBQUMsQ0FBQyxlQUFlO0lBQ2pCLENBQUMsQ0FBQyxXQUFXO0lBQ2IsQ0FBQyxDQUFDLE1BQU07SUFDUixDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxRQUFRO0lBQ1YsQ0FBQyxDQUFDLE1BQU07SUFDUixDQUFDLENBQUMsVUFBVTtJQUNaLENBQUMsQ0FBQyxjQUFjO0lBQ2hCLENBQUMsQ0FBQyx1QkFBdUI7SUFDekIsQ0FBQyxDQUFDLFNBQVM7SUFDWCxDQUFDLENBQUMsS0FBSztJQUNQLENBQUMsQ0FBQyxPQUFPO0lBQ1QsQ0FBQyxDQUFDLE9BQU87SUFDVCxDQUFDLENBQUMsT0FBTztJQUNULENBQUMsQ0FBQyxRQUFRO0lBQ1YsQ0FBQyxDQUFDLGNBQWM7SUFDaEIsQ0FBQyxDQUFDLG1CQUFtQjtJQUNyQixDQUFDLENBQUMsU0FBUztDQUNaLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCAqIGFzIGQgZnJvbSAnLi9jb21wb25lbnRzJztcblxuZXhwb3J0IGNvbnN0IERJUkVDVElWRVMgPSBbXG4gIGQuTnZBY2NvcmRpb24sXG4gIGQuTnZBY2NvcmRpb25JdGVtLFxuICBkLk52QWxlcnQsXG4gIGQuTnZBdmF0YXIsXG4gIGQuTnZCYWRnZSxcbiAgZC5OdkJyZWFkY3J1bWIsXG4gIGQuTnZCcmVhZGNydW1icyxcbiAgZC5OdkJ1dHRvbixcbiAgZC5OdkJ1dHRvbmdyb3VwLFxuICBkLk52Q2FsZW5kYXIsXG4gIGQuTnZDb2wsXG4gIGQuTnZEYXRhZ3JpZCxcbiAgZC5OdkRhdGFncmlkY29sdW1uLFxuICBkLk52RGlhbG9nLFxuICBkLk52RGlhbG9nZm9vdGVyLFxuICBkLk52RGlhbG9naGVhZGVyLFxuICBkLk52RmllbGRjaGVja2JveCxcbiAgZC5OdkZpZWxkZGF0ZSxcbiAgZC5OdkZpZWxkZGF0ZXJhbmdlLFxuICBkLk52RmllbGRkcm9wZG93bixcbiAgZC5OdkZpZWxkZHJvcGRvd25pdGVtLFxuICBkLk52RmllbGRkcm9wZG93bml0ZW1jaGVjayxcbiAgZC5OdkZpZWxkbXVsdGlzZWxlY3QsXG4gIGQuTnZGaWVsZG51bWJlcixcbiAgZC5OdkZpZWxkcGFzc3dvcmQsXG4gIGQuTnZGaWVsZHJhZGlvLFxuICBkLk52RmllbGRzZWxlY3QsXG4gIGQuTnZGaWVsZHNsaWRlcixcbiAgZC5OdkZpZWxkdGV4dCxcbiAgZC5OdkZpZWxkdGV4dGFyZWEsXG4gIGQuTnZGaWVsZHRpbWUsXG4gIGQuTnZJY29uLFxuICBkLk52SWNvbmJ1dHRvbixcbiAgZC5OdkxvYWRlcixcbiAgZC5Odk1lbnUsXG4gIGQuTnZNZW51aXRlbSxcbiAgZC5Odk5vdGlmaWNhdGlvbixcbiAgZC5Odk5vdGlmaWNhdGlvbmNvbnRhaW5lcixcbiAgZC5OdlBvcG92ZXIsXG4gIGQuTnZSb3csXG4gIGQuTnZTcGxpdCxcbiAgZC5OdlN0YWNrLFxuICBkLk52VGFibGUsXG4gIGQuTnZUb2dnbGUsXG4gIGQuTnZUb2dnbGVidXR0b24sXG4gIGQuTnZUb2dnbGVidXR0b25ncm91cCxcbiAgZC5OdlRvb2x0aXBcbl07XG4iXX0=
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9ub3ZhLWNvbXBvbmVudHMvc3JjL2xpYi9zdGVuY2lsLWdlbmVyYXRlZC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssQ0FBQyxNQUFNLGNBQWMsQ0FBQztBQUVsQyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUc7SUFDeEIsQ0FBQyxDQUFDLFdBQVc7SUFDYixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsT0FBTztJQUNULENBQUMsQ0FBQyxRQUFRO0lBQ1YsQ0FBQyxDQUFDLE9BQU87SUFDVCxDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxhQUFhO0lBQ2YsQ0FBQyxDQUFDLFFBQVE7SUFDVixDQUFDLENBQUMsYUFBYTtJQUNmLENBQUMsQ0FBQyxVQUFVO0lBQ1osQ0FBQyxDQUFDLEtBQUs7SUFDUCxDQUFDLENBQUMsVUFBVTtJQUNaLENBQUMsQ0FBQyxnQkFBZ0I7SUFDbEIsQ0FBQyxDQUFDLFFBQVE7SUFDVixDQUFDLENBQUMsY0FBYztJQUNoQixDQUFDLENBQUMsY0FBYztJQUNoQixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsV0FBVztJQUNiLENBQUMsQ0FBQyxnQkFBZ0I7SUFDbEIsQ0FBQyxDQUFDLGVBQWU7SUFDakIsQ0FBQyxDQUFDLG1CQUFtQjtJQUNyQixDQUFDLENBQUMsd0JBQXdCO0lBQzFCLENBQUMsQ0FBQyxrQkFBa0I7SUFDcEIsQ0FBQyxDQUFDLGFBQWE7SUFDZixDQUFDLENBQUMsZUFBZTtJQUNqQixDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxhQUFhO0lBQ2YsQ0FBQyxDQUFDLGFBQWE7SUFDZixDQUFDLENBQUMsV0FBVztJQUNiLENBQUMsQ0FBQyxlQUFlO0lBQ2pCLENBQUMsQ0FBQyxXQUFXO0lBQ2IsQ0FBQyxDQUFDLE1BQU07SUFDUixDQUFDLENBQUMsWUFBWTtJQUNkLENBQUMsQ0FBQyxRQUFRO0lBQ1YsQ0FBQyxDQUFDLE1BQU07SUFDUixDQUFDLENBQUMsVUFBVTtJQUNaLENBQUMsQ0FBQyxjQUFjO0lBQ2hCLENBQUMsQ0FBQyx1QkFBdUI7SUFDekIsQ0FBQyxDQUFDLFNBQVM7SUFDWCxDQUFDLENBQUMsS0FBSztJQUNQLENBQUMsQ0FBQyxPQUFPO0lBQ1QsQ0FBQyxDQUFDLE9BQU87SUFDVCxDQUFDLENBQUMsT0FBTztJQUNULENBQUMsQ0FBQyxhQUFhO0lBQ2YsQ0FBQyxDQUFDLFFBQVE7SUFDVixDQUFDLENBQUMsY0FBYztJQUNoQixDQUFDLENBQUMsbUJBQW1CO0lBQ3JCLENBQUMsQ0FBQyxTQUFTO0NBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIlxuaW1wb3J0ICogYXMgZCBmcm9tICcuL2NvbXBvbmVudHMnO1xuXG5leHBvcnQgY29uc3QgRElSRUNUSVZFUyA9IFtcbiAgZC5OdkFjY29yZGlvbixcbiAgZC5OdkFjY29yZGlvbkl0ZW0sXG4gIGQuTnZBbGVydCxcbiAgZC5OdkF2YXRhcixcbiAgZC5OdkJhZGdlLFxuICBkLk52QnJlYWRjcnVtYixcbiAgZC5OdkJyZWFkY3J1bWJzLFxuICBkLk52QnV0dG9uLFxuICBkLk52QnV0dG9uZ3JvdXAsXG4gIGQuTnZDYWxlbmRhcixcbiAgZC5OdkNvbCxcbiAgZC5OdkRhdGFncmlkLFxuICBkLk52RGF0YWdyaWRjb2x1bW4sXG4gIGQuTnZEaWFsb2csXG4gIGQuTnZEaWFsb2dmb290ZXIsXG4gIGQuTnZEaWFsb2doZWFkZXIsXG4gIGQuTnZGaWVsZGNoZWNrYm94LFxuICBkLk52RmllbGRkYXRlLFxuICBkLk52RmllbGRkYXRlcmFuZ2UsXG4gIGQuTnZGaWVsZGRyb3Bkb3duLFxuICBkLk52RmllbGRkcm9wZG93bml0ZW0sXG4gIGQuTnZGaWVsZGRyb3Bkb3duaXRlbWNoZWNrLFxuICBkLk52RmllbGRtdWx0aXNlbGVjdCxcbiAgZC5OdkZpZWxkbnVtYmVyLFxuICBkLk52RmllbGRwYXNzd29yZCxcbiAgZC5OdkZpZWxkcmFkaW8sXG4gIGQuTnZGaWVsZHNlbGVjdCxcbiAgZC5OdkZpZWxkc2xpZGVyLFxuICBkLk52RmllbGR0ZXh0LFxuICBkLk52RmllbGR0ZXh0YXJlYSxcbiAgZC5OdkZpZWxkdGltZSxcbiAgZC5Odkljb24sXG4gIGQuTnZJY29uYnV0dG9uLFxuICBkLk52TG9hZGVyLFxuICBkLk52TWVudSxcbiAgZC5Odk1lbnVpdGVtLFxuICBkLk52Tm90aWZpY2F0aW9uLFxuICBkLk52Tm90aWZpY2F0aW9uY29udGFpbmVyLFxuICBkLk52UG9wb3ZlcixcbiAgZC5OdlJvdyxcbiAgZC5OdlNwbGl0LFxuICBkLk52U3RhY2ssXG4gIGQuTnZUYWJsZSxcbiAgZC5OdlRhYmxlaGVhZGVyLFxuICBkLk52VG9nZ2xlLFxuICBkLk52VG9nZ2xlYnV0dG9uLFxuICBkLk52VG9nZ2xlYnV0dG9uZ3JvdXAsXG4gIGQuTnZUb29sdGlwXG5dO1xuIl19
@@ -5,7 +5,7 @@ import { __decorate } from 'tslib';
5
5
  import { fromEvent, BehaviorSubject } from 'rxjs';
6
6
  import * as i2 from '@angular/common';
7
7
  import { CommonModule } from '@angular/common';
8
- import { memo, createTable, getCoreRowModel, getPaginationRowModel } from '@tanstack/table-core';
8
+ import { memo, createTable, getSortedRowModel, getCoreRowModel, getPaginationRowModel } from '@tanstack/table-core';
9
9
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
10
10
  export * from '@nova-design-system/nova-webcomponents/constants';
11
11
 
@@ -253,11 +253,11 @@ let NvButton = class NvButton {
253
253
  this.el = r.nativeElement;
254
254
  }
255
255
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvButton, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
256
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NvButton, selector: "nv-button", inputs: { active: "active", danger: "danger", disabled: "disabled", emphasis: "emphasis", fluid: "fluid", form: "form", loading: "loading", size: "size", type: "type" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
256
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NvButton, selector: "nv-button", inputs: { active: "active", danger: "danger", disableTabindex: "disableTabindex", disabled: "disabled", emphasis: "emphasis", fluid: "fluid", form: "form", loading: "loading", size: "size", type: "type" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
257
257
  };
258
258
  NvButton = __decorate([
259
259
  ProxyCmp({
260
- inputs: ['active', 'danger', 'disabled', 'emphasis', 'fluid', 'form', 'loading', 'size', 'type']
260
+ inputs: ['active', 'danger', 'disableTabindex', 'disabled', 'emphasis', 'fluid', 'form', 'loading', 'size', 'type']
261
261
  })
262
262
  ], NvButton);
263
263
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvButton, decorators: [{
@@ -267,7 +267,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
267
267
  changeDetection: ChangeDetectionStrategy.OnPush,
268
268
  template: '<ng-content></ng-content>',
269
269
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
270
- inputs: ['active', 'danger', 'disabled', 'emphasis', 'fluid', 'form', 'loading', 'size', 'type'],
270
+ inputs: ['active', 'danger', 'disableTabindex', 'disabled', 'emphasis', 'fluid', 'form', 'loading', 'size', 'type'],
271
271
  standalone: false
272
272
  }]
273
273
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }] });
@@ -903,11 +903,11 @@ let NvIconbutton = class NvIconbutton {
903
903
  this.el = r.nativeElement;
904
904
  }
905
905
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvIconbutton, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
906
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NvIconbutton, selector: "nv-iconbutton", inputs: { active: "active", disabled: "disabled", emphasis: "emphasis", loading: "loading", name: "name", shape: "shape", size: "size", type: "type" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
906
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NvIconbutton, selector: "nv-iconbutton", inputs: { active: "active", disableTabindex: "disableTabindex", disabled: "disabled", emphasis: "emphasis", loading: "loading", name: "name", shape: "shape", size: "size", type: "type" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
907
907
  };
908
908
  NvIconbutton = __decorate([
909
909
  ProxyCmp({
910
- inputs: ['active', 'disabled', 'emphasis', 'loading', 'name', 'shape', 'size', 'type']
910
+ inputs: ['active', 'disableTabindex', 'disabled', 'emphasis', 'loading', 'name', 'shape', 'size', 'type']
911
911
  })
912
912
  ], NvIconbutton);
913
913
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvIconbutton, decorators: [{
@@ -917,7 +917,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
917
917
  changeDetection: ChangeDetectionStrategy.OnPush,
918
918
  template: '<ng-content></ng-content>',
919
919
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
920
- inputs: ['active', 'disabled', 'emphasis', 'loading', 'name', 'shape', 'size', 'type'],
920
+ inputs: ['active', 'disableTabindex', 'disabled', 'emphasis', 'loading', 'name', 'shape', 'size', 'type'],
921
921
  standalone: false
922
922
  }]
923
923
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }] });
@@ -1176,6 +1176,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1176
1176
  standalone: false
1177
1177
  }]
1178
1178
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }] });
1179
+ let NvTableheader = class NvTableheader {
1180
+ constructor(c, r, z) {
1181
+ this.z = z;
1182
+ c.detach();
1183
+ this.el = r.nativeElement;
1184
+ proxyOutputs(this, this.el, ['sortDirectionChanged']);
1185
+ }
1186
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvTableheader, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
1187
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NvTableheader, selector: "nv-tableheader", inputs: { sortDirection: "sortDirection", sortable: "sortable" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1188
+ };
1189
+ NvTableheader = __decorate([
1190
+ ProxyCmp({
1191
+ inputs: ['sortDirection', 'sortable']
1192
+ })
1193
+ ], NvTableheader);
1194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvTableheader, decorators: [{
1195
+ type: Component,
1196
+ args: [{
1197
+ selector: 'nv-tableheader',
1198
+ changeDetection: ChangeDetectionStrategy.OnPush,
1199
+ template: '<ng-content></ng-content>',
1200
+ // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
1201
+ inputs: ['sortDirection', 'sortable'],
1202
+ standalone: false
1203
+ }]
1204
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.NgZone }] });
1179
1205
  let NvToggle = class NvToggle {
1180
1206
  constructor(c, r, z) {
1181
1207
  this.z = z;
@@ -1325,6 +1351,7 @@ const DIRECTIVES = [
1325
1351
  NvSplit,
1326
1352
  NvStack,
1327
1353
  NvTable,
1354
+ NvTableheader,
1328
1355
  NvToggle,
1329
1356
  NvTogglebutton,
1330
1357
  NvTogglebuttongroup,
@@ -2093,14 +2120,47 @@ function createAngularTable(options) {
2093
2120
 
2094
2121
  /* eslint-disable jsdoc/require-jsdoc */
2095
2122
  /* eslint-disable jsdoc/require-returns */
2123
+ /* eslint-disable jsdoc/require-param */
2096
2124
  /**
2097
- * Nova Datatable built on TanStack Table (Angular).
2125
+ * A powerful, flexible datatable component built on TanStack Table.
2126
+ * Supports custom cell rendering, column configuration, pagination, and full TypeScript typing.
2098
2127
  */
2099
2128
  class NvDatatable {
2100
2129
  /** Public getter for table instance. */
2101
2130
  table() {
2102
2131
  return this.tableInstance();
2103
2132
  }
2133
+ /**
2134
+ * Handle sort direction change from table header
2135
+ * @param {Event} event The sort direction change event or direction string
2136
+ * @param {object} header The table header object
2137
+ */
2138
+ handleSortDirectionChanged(event, header) {
2139
+ // Extract direction from event or use directly if string
2140
+ let direction;
2141
+ if (typeof event === 'string') {
2142
+ direction = event;
2143
+ }
2144
+ else if ('detail' in event && typeof event.detail === 'string') {
2145
+ direction = event.detail;
2146
+ }
2147
+ else {
2148
+ // Fallback - shouldn't happen but handle gracefully
2149
+ console.warn('Unexpected event type in handleSortDirectionChanged:', event);
2150
+ return;
2151
+ }
2152
+ const sortingConfig = this.sorting();
2153
+ // Check if multi-sort is enabled
2154
+ const isMultiSort = sortingConfig?.enableMultiSort ?? false;
2155
+ if (direction === 'none') {
2156
+ // Clear this column's sort
2157
+ header.column.clearSorting();
2158
+ }
2159
+ else {
2160
+ // Toggle sort - TanStack will handle the logic internally
2161
+ header.column.toggleSorting(direction === 'desc', isMultiSort);
2162
+ }
2163
+ }
2104
2164
  constructor() {
2105
2165
  /** Column definitions */
2106
2166
  this.columns = input([]);
@@ -2108,6 +2168,8 @@ class NvDatatable {
2108
2168
  this.rows = input([]);
2109
2169
  /** Optional pagination configuration */
2110
2170
  this.pagination = input(undefined);
2171
+ /** Optional sorting configuration */
2172
+ this.sorting = input(undefined);
2111
2173
  /** Should the header stick to the top of the table when scrolling? */
2112
2174
  this.stickyHeader = input(false);
2113
2175
  /** Signal to track cell templates array */
@@ -2125,6 +2187,8 @@ class NvDatatable {
2125
2187
  pageIndex: 0,
2126
2188
  pageSize: this.pagination()?.initialPageSize || 10,
2127
2189
  });
2190
+ /** Sorting state for controlled sorting (server mode) */
2191
+ this.sortingState = signal(this.sorting()?.sortState || []);
2128
2192
  /** Reference to table rows for infinite scroll observer */
2129
2193
  this.tableRows = viewChild('tableRow');
2130
2194
  /** Intersection observer for infinite scroll */
@@ -2136,45 +2200,114 @@ class NvDatatable {
2136
2200
  const templateMap = this.cellTemplateMap();
2137
2201
  return this.columns()
2138
2202
  .filter((col) => !col.hidden)
2139
- .map((col) => ({
2140
- accessorKey: col.field,
2141
- header: col.headerName || String(col.field),
2142
- size: col.width,
2143
- enableResizing: col.resizable ?? true,
2144
- cell: (context) => {
2203
+ .map((col) => {
2204
+ // Shared cell renderer
2205
+ const cellRenderer = (context) => {
2145
2206
  const fieldName = String(col.field);
2146
2207
  const cellTemplate = templateMap.get(fieldName);
2147
2208
  // Priority: template > renderCell > default
2148
2209
  if (cellTemplate) {
2149
- // Return TemplateRef directly - FlexRender will handle it
2210
+ // Return TemplateRef directly - getValue() returns formatted value
2150
2211
  return cellTemplate;
2151
2212
  }
2152
2213
  // Fall back to renderCell if provided
2153
2214
  if (col.renderCell) {
2154
2215
  return col.renderCell(context);
2155
2216
  }
2156
- // Default: just return the value
2217
+ // Default: just return the value (formatted if valueFormatter was used)
2157
2218
  return context.getValue();
2158
- },
2159
- }));
2219
+ };
2220
+ const columnDef = {
2221
+ accessorKey: col.field,
2222
+ accessorFn: col.valueFormatter
2223
+ ? (row) => {
2224
+ const rawValue = row[col.field];
2225
+ return col.valueFormatter({
2226
+ value: rawValue,
2227
+ row,
2228
+ field: col.field,
2229
+ });
2230
+ }
2231
+ : undefined,
2232
+ header: col.headerName || String(col.field),
2233
+ size: col.width,
2234
+ enableResizing: col.resizable ?? true,
2235
+ // Sorting configuration
2236
+ enableSorting: this.sorting() ? col.sortable ?? true : false,
2237
+ cell: cellRenderer,
2238
+ };
2239
+ // Add optional sorting properties only if defined
2240
+ if (col.sortingFn !== undefined) {
2241
+ // @ts-expect-error - TanStack typing is strict but this works at runtime
2242
+ columnDef.sortingFn = col.sortingFn;
2243
+ }
2244
+ if (col.sortDescFirst !== undefined) {
2245
+ columnDef.sortDescFirst = col.sortDescFirst;
2246
+ }
2247
+ if (col.invertSorting !== undefined) {
2248
+ columnDef.invertSorting = col.invertSorting;
2249
+ }
2250
+ if (col.sortUndefined !== undefined) {
2251
+ columnDef.sortUndefined = col.sortUndefined;
2252
+ }
2253
+ return columnDef;
2254
+ });
2160
2255
  });
2161
2256
  /** TanStack table instance with Signals */
2162
2257
  this.tableInstance = createAngularTable(() => {
2163
2258
  const paginationConfig = this.pagination();
2164
- if (!paginationConfig || paginationConfig.mode === 'infinite') {
2165
- // No pagination or infinite scroll - simple config
2166
- return {
2259
+ const sortingConfig = this.sorting();
2260
+ // Determine base table configuration with sorting
2261
+ const getBaseTableConfig = () => {
2262
+ const baseConfig = {
2167
2263
  data: this.rows(),
2168
2264
  columns: this.tableColumns(),
2169
2265
  getCoreRowModel: getCoreRowModel(),
2266
+ // Sorting configuration
2267
+ ...(sortingConfig && {
2268
+ state: {
2269
+ sorting: sortingConfig.mode === 'server' && sortingConfig.sortState
2270
+ ? sortingConfig.sortState
2271
+ : this.sortingState(),
2272
+ },
2273
+ onSortingChange: (updaterOrValue) => {
2274
+ const currentSort = sortingConfig.mode === 'server' && sortingConfig.sortState
2275
+ ? sortingConfig.sortState
2276
+ : this.sortingState();
2277
+ const newSort = typeof updaterOrValue === 'function'
2278
+ ? updaterOrValue(currentSort)
2279
+ : updaterOrValue;
2280
+ // Always update internal state for reactivity
2281
+ this.sortingState.set(newSort);
2282
+ // For server-side sorting, also call the callback
2283
+ if (sortingConfig?.mode === 'server' &&
2284
+ sortingConfig.onSortingChange) {
2285
+ sortingConfig.onSortingChange(newSort);
2286
+ }
2287
+ },
2288
+ manualSorting: sortingConfig.mode === 'server',
2289
+ enableSorting: true,
2290
+ enableMultiSort: sortingConfig.enableMultiSort ?? false,
2291
+ enableSortingRemoval: sortingConfig.enableSortingRemoval ?? true,
2292
+ maxMultiSortColCount: sortingConfig.maxMultiSortColCount,
2293
+ sortDescFirst: sortingConfig.sortDescFirst ?? false,
2294
+ // When multi-sort is enabled, treat all clicks as multi-sort events
2295
+ isMultiSortEvent: sortingConfig.enableMultiSort
2296
+ ? () => true
2297
+ : undefined,
2298
+ getSortedRowModel: sortingConfig.mode === 'client' ? getSortedRowModel() : undefined,
2299
+ }),
2170
2300
  };
2301
+ return baseConfig;
2302
+ };
2303
+ if (!paginationConfig || paginationConfig.mode === 'infinite') {
2304
+ // No pagination or infinite scroll - simple config
2305
+ return getBaseTableConfig();
2171
2306
  }
2172
2307
  else if (paginationConfig.mode === 'client') {
2173
2308
  // Client-side pagination
2174
2309
  return {
2175
- data: this.rows(),
2176
- columns: this.tableColumns(),
2177
- getCoreRowModel: getCoreRowModel(),
2310
+ ...getBaseTableConfig(),
2178
2311
  getPaginationRowModel: getPaginationRowModel(),
2179
2312
  initialState: {
2180
2313
  pagination: {
@@ -2185,12 +2318,11 @@ class NvDatatable {
2185
2318
  };
2186
2319
  }
2187
2320
  else {
2188
- // Server-side pagination
2321
+ // Server-side pagination - manual pagination with reactive state
2322
+ const baseConfig = getBaseTableConfig();
2189
2323
  const pageSize = this.paginationState().pageSize;
2190
2324
  return {
2191
- data: this.rows(),
2192
- columns: this.tableColumns(),
2193
- getCoreRowModel: getCoreRowModel(),
2325
+ ...baseConfig,
2194
2326
  manualPagination: true,
2195
2327
  pageCount: paginationConfig.totalPageCount !== undefined
2196
2328
  ? paginationConfig.totalPageCount
@@ -2199,13 +2331,19 @@ class NvDatatable {
2199
2331
  : -1,
2200
2332
  state: {
2201
2333
  pagination: this.paginationState(),
2334
+ ...(baseConfig.state && { sorting: baseConfig.state.sorting }),
2202
2335
  },
2203
2336
  onPaginationChange: (updaterOrValue) => {
2204
- if (typeof updaterOrValue === 'function') {
2205
- this.paginationState.set(updaterOrValue(this.paginationState()));
2206
- }
2207
- else {
2208
- this.paginationState.set(updaterOrValue);
2337
+ const newState = typeof updaterOrValue === 'function'
2338
+ ? updaterOrValue(this.paginationState())
2339
+ : updaterOrValue;
2340
+ this.paginationState.set(newState);
2341
+ // Call user's callback for server-side pagination
2342
+ if (paginationConfig.onPaginationChange) {
2343
+ paginationConfig.onPaginationChange({
2344
+ pageIndex: newState.pageIndex,
2345
+ pageSize: newState.pageSize,
2346
+ });
2209
2347
  }
2210
2348
  },
2211
2349
  };
@@ -2244,18 +2382,6 @@ class NvDatatable {
2244
2382
  : undefined,
2245
2383
  };
2246
2384
  });
2247
- // Watch pagination state changes for server mode
2248
- effect(() => {
2249
- const paginationConfig = this.pagination();
2250
- const state = this.paginationState();
2251
- if (paginationConfig?.mode === 'server' &&
2252
- paginationConfig.onPaginationChange) {
2253
- paginationConfig.onPaginationChange({
2254
- pageIndex: state.pageIndex,
2255
- pageSize: state.pageSize,
2256
- });
2257
- }
2258
- }, { allowSignalWrites: true });
2259
2385
  // Set up intersection observer for infinite scroll
2260
2386
  effect(() => {
2261
2387
  const paginationConfig = this.pagination();
@@ -2314,7 +2440,7 @@ class NvDatatable {
2314
2440
  }
2315
2441
  }
2316
2442
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NvDatatable, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2317
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NvDatatable, isStandalone: true, selector: "nv-datatable", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "paginationTemplate", first: true, predicate: ["paginationTemplate"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: NvDatatableCellDirective }], viewQueries: [{ propertyName: "tableRows", first: true, predicate: ["tableRow"], descendants: true, isSignal: true }], ngImport: i0, template: `
2443
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NvDatatable, isStandalone: true, selector: "nv-datatable", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, sorting: { classPropertyName: "sorting", publicName: "sorting", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "paginationTemplate", first: true, predicate: ["paginationTemplate"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: NvDatatableCellDirective }], viewQueries: [{ propertyName: "tableRows", first: true, predicate: ["tableRow"], descendants: true, isSignal: true }], ngImport: i0, template: `
2318
2444
  <nv-table>
2319
2445
  <table>
2320
2446
  <thead [attr.data-sticky-top]="stickyHeader() ? 'true' : null">
@@ -2333,9 +2459,19 @@ class NvDatatable {
2333
2459
  !header.column.columnDef.enableResizing ? 'true' : null
2334
2460
  "
2335
2461
  >
2336
- @if (!header.isPlaceholder) {
2462
+ @if (!header.isPlaceholder) { @if (header.column.getCanSort()) {
2463
+ <nv-tableheader
2464
+ [sortable]="true"
2465
+ [sortDirection]="header.column.getIsSorted() || 'none'"
2466
+ (sortDirectionChanged)="
2467
+ handleSortDirectionChanged($event, header)
2468
+ "
2469
+ >
2470
+ {{ header.column.columnDef.header }}
2471
+ </nv-tableheader>
2472
+ } @else {
2337
2473
  {{ header.column.columnDef.header }}
2338
- }
2474
+ } }
2339
2475
  </th>
2340
2476
  }
2341
2477
  </tr>
@@ -2346,7 +2482,7 @@ class NvDatatable {
2346
2482
  @for (row of table().getRowModel().rows; track row.id; let i = $index)
2347
2483
  {
2348
2484
  <tr
2349
- [attr.data-testid]="'datatable-row-' + row.id"
2485
+ [attr.data-testid]="'datatable-row-' + i"
2350
2486
  #tableRow
2351
2487
  [attr.data-is-last]="
2352
2488
  isInfiniteScroll() && i === table().getRowModel().rows.length - 1
@@ -2355,7 +2491,7 @@ class NvDatatable {
2355
2491
  "
2356
2492
  >
2357
2493
  @for (cell of row.getVisibleCells(); track cell.id) {
2358
- <td [attr.data-testid]="'datatable-cell-' + cell.id">
2494
+ <td [attr.data-testid]="'datatable-cell-' + cell.column.id">
2359
2495
  <ng-container
2360
2496
  *flexRender="
2361
2497
  cell.column.columnDef.cell;
@@ -2410,9 +2546,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2410
2546
  !header.column.columnDef.enableResizing ? 'true' : null
2411
2547
  "
2412
2548
  >
2413
- @if (!header.isPlaceholder) {
2549
+ @if (!header.isPlaceholder) { @if (header.column.getCanSort()) {
2550
+ <nv-tableheader
2551
+ [sortable]="true"
2552
+ [sortDirection]="header.column.getIsSorted() || 'none'"
2553
+ (sortDirectionChanged)="
2554
+ handleSortDirectionChanged($event, header)
2555
+ "
2556
+ >
2557
+ {{ header.column.columnDef.header }}
2558
+ </nv-tableheader>
2559
+ } @else {
2414
2560
  {{ header.column.columnDef.header }}
2415
- }
2561
+ } }
2416
2562
  </th>
2417
2563
  }
2418
2564
  </tr>
@@ -2423,7 +2569,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2423
2569
  @for (row of table().getRowModel().rows; track row.id; let i = $index)
2424
2570
  {
2425
2571
  <tr
2426
- [attr.data-testid]="'datatable-row-' + row.id"
2572
+ [attr.data-testid]="'datatable-row-' + i"
2427
2573
  #tableRow
2428
2574
  [attr.data-is-last]="
2429
2575
  isInfiniteScroll() && i === table().getRowModel().rows.length - 1
@@ -2432,7 +2578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2432
2578
  "
2433
2579
  >
2434
2580
  @for (cell of row.getVisibleCells(); track cell.id) {
2435
- <td [attr.data-testid]="'datatable-cell-' + cell.id">
2581
+ <td [attr.data-testid]="'datatable-cell-' + cell.column.id">
2436
2582
  <ng-container
2437
2583
  *flexRender="
2438
2584
  cell.column.columnDef.cell;
@@ -2468,6 +2614,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2468
2614
  type: ContentChildren,
2469
2615
  args: [NvDatatableCellDirective]
2470
2616
  }] } });
2617
+ /********************************* UTILS **************************************/
2618
+ /**
2619
+ * Creates a strongly-typed column factory for a given row type.
2620
+ *
2621
+ * @template Row The row data type (e.g., `Product`)
2622
+ *
2623
+ * @returns {function} A function that accepts a column definition and infers:
2624
+ * - `K` as the field key (`keyof Row`)
2625
+ * - `F` as the return type of `valueFormatter` (defaults to `Row[K]`)
2626
+ *
2627
+ * @example
2628
+ * ```ts
2629
+ * // Define your row type
2630
+ * interface Product {
2631
+ * name: string;
2632
+ * price: number;
2633
+ * }
2634
+ *
2635
+ * const col = makeColumn<Product>();
2636
+ */
2637
+ function makeColumn() {
2638
+ return function define(col) {
2639
+ return col;
2640
+ };
2641
+ }
2471
2642
 
2472
2643
  class ValueAccessor {
2473
2644
  constructor(el) {
@@ -3353,7 +3524,7 @@ function provideNovaComponents() {
3353
3524
  }
3354
3525
  class NovaComponentsModule {
3355
3526
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3356
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, declarations: [NvAccordion, NvAccordionItem, NvAlert, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCol, NvDatagrid, NvDatagridcolumn, NvDialog, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFielddate, NvFielddaterange, NvFielddropdown, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldnumber, NvFieldpassword, NvFieldradio, NvFieldselect, NvFieldslider, NvFieldtext, NvFieldtextarea, NvFieldtime, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationcontainer, NvPopover, NvRow, NvSplit, NvStack, NvTable, NvToggle, NvTogglebutton, NvTogglebuttongroup, NvTooltip], imports: [NvDatatable], exports: [NvAccordion, NvAccordionItem, NvAlert, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCol, NvDatagrid, NvDatagridcolumn, NvDialog, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFielddate, NvFielddaterange, NvFielddropdown, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldnumber, NvFieldpassword, NvFieldradio, NvFieldselect, NvFieldslider, NvFieldtext, NvFieldtextarea, NvFieldtime, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationcontainer, NvPopover, NvRow, NvSplit, NvStack, NvTable, NvToggle, NvTogglebutton, NvTogglebuttongroup, NvTooltip, NvDatatable] }); }
3527
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, declarations: [NvAccordion, NvAccordionItem, NvAlert, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCol, NvDatagrid, NvDatagridcolumn, NvDialog, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFielddate, NvFielddaterange, NvFielddropdown, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldnumber, NvFieldpassword, NvFieldradio, NvFieldselect, NvFieldslider, NvFieldtext, NvFieldtextarea, NvFieldtime, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationcontainer, NvPopover, NvRow, NvSplit, NvStack, NvTable, NvTableheader, NvToggle, NvTogglebutton, NvTogglebuttongroup, NvTooltip], imports: [NvDatatable], exports: [NvAccordion, NvAccordionItem, NvAlert, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCol, NvDatagrid, NvDatagridcolumn, NvDialog, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFielddate, NvFielddaterange, NvFielddropdown, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldnumber, NvFieldpassword, NvFieldradio, NvFieldselect, NvFieldslider, NvFieldtext, NvFieldtextarea, NvFieldtime, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationcontainer, NvPopover, NvRow, NvSplit, NvStack, NvTable, NvTableheader, NvToggle, NvTogglebutton, NvTogglebuttongroup, NvTooltip, NvDatatable] }); }
3357
3528
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, providers: [provideNovaComponents()], imports: [NvDatatable] }); }
3358
3529
  }
3359
3530
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NovaComponentsModule, decorators: [{
@@ -3402,6 +3573,7 @@ class NotificationService {
3402
3573
  }
3403
3574
  constructor() {
3404
3575
  this._notifications = new BehaviorSubject([]);
3576
+ this.timers = new Map();
3405
3577
  /**
3406
3578
  * Observable stream of active notifications.
3407
3579
  */
@@ -3439,6 +3611,14 @@ class NotificationService {
3439
3611
  clearRefs() {
3440
3612
  this.elRefs.clear();
3441
3613
  }
3614
+ /**
3615
+ * Clean up all timers and references.
3616
+ */
3617
+ ngOnDestroy() {
3618
+ this.timers.forEach((timer) => clearTimeout(timer));
3619
+ this.timers.clear();
3620
+ this.clearRefs();
3621
+ }
3442
3622
  /**
3443
3623
  * Show a new notification.
3444
3624
  *
@@ -3457,6 +3637,7 @@ class NotificationService {
3457
3637
  icon: options.icon,
3458
3638
  actions: options.actions ?? [],
3459
3639
  actionSlot: options.actionSlot,
3640
+ duration: options.duration ?? 0,
3460
3641
  createdAt: Date.now(),
3461
3642
  };
3462
3643
  const currentNotifications = this._notifications.value;
@@ -3471,6 +3652,13 @@ class NotificationService {
3471
3652
  setTimeout(() => {
3472
3653
  const ref = this.elRefs.get(id);
3473
3654
  ref?.show();
3655
+ // Set up auto-dismiss timer if duration > 0
3656
+ if (notification.duration && notification.duration > 0) {
3657
+ const timer = setTimeout(() => {
3658
+ this.dismiss(id);
3659
+ }, notification.duration);
3660
+ this.timers.set(id, timer);
3661
+ }
3474
3662
  }, 0);
3475
3663
  return id;
3476
3664
  }
@@ -3481,6 +3669,12 @@ class NotificationService {
3481
3669
  * @param {string} id The notification ID to dismiss
3482
3670
  */
3483
3671
  dismiss(id) {
3672
+ // Clear timer if exists
3673
+ const timer = this.timers.get(id);
3674
+ if (timer) {
3675
+ clearTimeout(timer);
3676
+ this.timers.delete(id);
3677
+ }
3484
3678
  this.elRefs.get(id)?.dismiss?.();
3485
3679
  }
3486
3680
  /**
@@ -3489,6 +3683,12 @@ class NotificationService {
3489
3683
  * @param {string} id The notification ID to dismiss
3490
3684
  */
3491
3685
  remove(id) {
3686
+ // Clear timer if exists
3687
+ const timer = this.timers.get(id);
3688
+ if (timer) {
3689
+ clearTimeout(timer);
3690
+ this.timers.delete(id);
3691
+ }
3492
3692
  const currentNotifications = this._notifications.value;
3493
3693
  const filteredNotifications = currentNotifications.filter((notification) => notification.id !== id);
3494
3694
  this._notifications.next(filteredNotifications);
@@ -3497,6 +3697,9 @@ class NotificationService {
3497
3697
  * Immediately remove all active notifications.
3498
3698
  */
3499
3699
  removeAll() {
3700
+ // Clear all timers
3701
+ this.timers.forEach((timer) => clearTimeout(timer));
3702
+ this.timers.clear();
3500
3703
  this._notifications.next([]);
3501
3704
  }
3502
3705
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -3695,5 +3898,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3695
3898
  * Generated bundle index. Do not edit.
3696
3899
  */
3697
3900
 
3698
- export { NotificationService, NotificationServiceComponent, NovaComponentsModule, NovaComponentsValueAccessorModule, NvAccordion, NvAccordionItem, NvAccordionValueAccessor, NvAlert, NvAlertValueAccessor, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCalendarValueAccessor, NvCol, NvDatagrid, NvDatagridValueAccessor, NvDatagridcolumn, NvDatatable, NvDatatableCellDirective, NvDialog, NvDialogValueAccessor, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFieldcheckboxValueAccessor, NvFielddate, NvFielddateValueAccessor, NvFielddaterange, NvFielddaterangeValueAccessor, NvFielddropdown, NvFielddropdownValueAccessor, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldmultiselectValueAccessor, NvFieldnumber, NvFieldnumberValueAccessor, NvFieldpassword, NvFieldpasswordValueAccessor, NvFieldradio, NvFieldradioValueAccessor, NvFieldselect, NvFieldselectValueAccessor, NvFieldslider, NvFieldsliderValueAccessor, NvFieldtext, NvFieldtextValueAccessor, NvFieldtextarea, NvFieldtextareaValueAccessor, NvFieldtime, NvFieldtimeValueAccessor, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationValueAccessor, NvNotificationcontainer, NvPopover, NvPopoverValueAccessor, NvRow, NvSplit, NvSplitValueAccessor, NvStack, NvTable, NvToggle, NvToggleValueAccessor, NvTogglebutton, NvTogglebuttongroup, NvTogglebuttongroupValueAccessor, NvTooltip, VALUE_ACCESSORS, flexRenderComponent as nvDatatableRenderComponent, provideNovaComponents };
3901
+ export { NotificationService, NotificationServiceComponent, NovaComponentsModule, NovaComponentsValueAccessorModule, NvAccordion, NvAccordionItem, NvAccordionValueAccessor, NvAlert, NvAlertValueAccessor, NvAvatar, NvBadge, NvBreadcrumb, NvBreadcrumbs, NvButton, NvButtongroup, NvCalendar, NvCalendarValueAccessor, NvCol, NvDatagrid, NvDatagridValueAccessor, NvDatagridcolumn, NvDatatable, NvDatatableCellDirective, NvDialog, NvDialogValueAccessor, NvDialogfooter, NvDialogheader, NvFieldcheckbox, NvFieldcheckboxValueAccessor, NvFielddate, NvFielddateValueAccessor, NvFielddaterange, NvFielddaterangeValueAccessor, NvFielddropdown, NvFielddropdownValueAccessor, NvFielddropdownitem, NvFielddropdownitemcheck, NvFieldmultiselect, NvFieldmultiselectValueAccessor, NvFieldnumber, NvFieldnumberValueAccessor, NvFieldpassword, NvFieldpasswordValueAccessor, NvFieldradio, NvFieldradioValueAccessor, NvFieldselect, NvFieldselectValueAccessor, NvFieldslider, NvFieldsliderValueAccessor, NvFieldtext, NvFieldtextValueAccessor, NvFieldtextarea, NvFieldtextareaValueAccessor, NvFieldtime, NvFieldtimeValueAccessor, NvIcon, NvIconbutton, NvLoader, NvMenu, NvMenuitem, NvNotification, NvNotificationValueAccessor, NvNotificationcontainer, NvPopover, NvPopoverValueAccessor, NvRow, NvSplit, NvSplitValueAccessor, NvStack, NvTable, NvTableheader, NvToggle, NvToggleValueAccessor, NvTogglebutton, NvTogglebuttongroup, NvTogglebuttongroupValueAccessor, NvTooltip, VALUE_ACCESSORS, makeColumn, flexRenderComponent as nvDatatableRenderComponent, provideNovaComponents };
3699
3902
  //# sourceMappingURL=nova-components.mjs.map