ng-prime-tools 1.0.31 → 1.0.32

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.
@@ -7,7 +7,7 @@ import { FormControl, Validators, ReactiveFormsModule, FormsModule, FormGroup }
7
7
  import * as i2 from 'primeng/table';
8
8
  import { TableModule } from 'primeng/table';
9
9
  import * as i1$1 from 'primeng/api';
10
- import { ConfirmEventType, ConfirmationService, MessageService } from 'primeng/api';
10
+ import { ConfirmationService, MessageService } from 'primeng/api';
11
11
  import * as i4 from 'primeng/inputtext';
12
12
  import { InputTextModule } from 'primeng/inputtext';
13
13
  import * as i3 from 'primeng/button';
@@ -47,7 +47,7 @@ import { filter } from 'rxjs/operators';
47
47
  import { BehaviorSubject } from 'rxjs';
48
48
  import * as i3$6 from 'primeng/breadcrumb';
49
49
  import { BreadcrumbModule } from 'primeng/breadcrumb';
50
- import * as i3$7 from 'primeng/confirmdialog';
50
+ import * as i4$2 from 'primeng/confirmdialog';
51
51
  import { ConfirmDialogModule } from 'primeng/confirmdialog';
52
52
  import { DialogModule } from 'primeng/dialog';
53
53
  import * as i2$2 from 'primeng/toast';
@@ -181,6 +181,7 @@ class PTAdvancedPrimeTableComponent {
181
181
  this.search = new EventEmitter();
182
182
  this.exportExcelEvent = new EventEmitter();
183
183
  this.exportPdfEvent = new EventEmitter();
184
+ this.pageChange = new EventEmitter();
184
185
  this.TableTypeEnum = TableTypeEnum;
185
186
  this.searchValue = '';
186
187
  this.filters = {};
@@ -204,13 +205,15 @@ class PTAdvancedPrimeTableComponent {
204
205
  this.hasGroupedColumns = false;
205
206
  }
206
207
  ngOnInit() {
208
+ console.log('PTAdvancedPrimeTable columns:', this.columns);
209
+ console.log('PTAdvancedPrimeTable totalRecords input:', this.totalRecords);
207
210
  this.hasGroupedColumns = this.columns.some((col) => col.children && col.children.length > 0);
208
211
  this.globalFilterFields = this.columns
209
212
  .filter((col) => col.code !== undefined && col.isFilter !== false)
210
213
  .map((col) => col.code);
211
214
  this.initializePagination();
212
215
  this.initializeActions();
213
- // Set default value for isSortable
216
+ // Set default value for isSortable / isEditable + widths
214
217
  this.columns.forEach((col) => {
215
218
  if (col.type === TableTypeEnum.ACTION) {
216
219
  col.isEditable = false;
@@ -242,85 +245,81 @@ class PTAdvancedPrimeTableComponent {
242
245
  options: col.filterOptions,
243
246
  value: [],
244
247
  label: 'Filter by ' + composedName,
245
- placeholder: 'Select options for ' + composedName,
248
+ placeholder: 'Select option',
246
249
  };
247
250
  });
248
251
  }
249
252
  // Get the column type for composed fields (STRING, IMAGE, etc.)
250
253
  getComposedFieldType(col, composedName) {
251
- // Ensure that col.composedNames and col.composedTypes are valid arrays
252
254
  if (col.composedNames && col.composedTypes) {
253
255
  const index = col.composedNames.indexOf(composedName);
254
- // Check if index is a valid number (not -1) and within bounds of composedTypes array
255
256
  if (index >= 0 && index < col.composedTypes.length) {
256
- return col.composedTypes[index]; // Safe access of composedTypes array
257
+ return col.composedTypes[index];
257
258
  }
258
259
  }
259
- return undefined; // Return undefined if no valid index is found or composedNames/composedTypes are not valid
260
+ return undefined;
260
261
  }
261
- onComposedFilterChange(composedName, selectedValues) {
262
- console.log('Selected Values:', selectedValues);
263
- console.log('Data Before Filtering:', this.data);
264
- // Update the filter value with the selected values
262
+ onComposedFilterChange(col, composedName, selectedValues) {
265
263
  this.filters[composedName].value = selectedValues;
266
- // Emit the filter event to notify the parent component (if needed)
267
264
  this.filter.emit(this.filters);
268
- // Get the filter value (joining array into a string)
269
265
  const filterValue = selectedValues.join(',');
270
- console.log('Filter Values to be Applied:', filterValue);
271
- // Apply global filter using PrimeNG's filterGlobal method
266
+ let matchResults = [];
267
+ selectedValues.forEach((value) => {
268
+ const matches = this.dt.value.filter((row) => {
269
+ return row[col.code]?.[composedName]
270
+ ?.toString()
271
+ .toLowerCase()
272
+ .includes(value.toLowerCase());
273
+ });
274
+ matchResults = [...matchResults, ...matches];
275
+ });
276
+ matchResults = Array.from(new Set(matchResults));
277
+ this.dt.filteredValue = matchResults;
272
278
  this.dt.filterGlobal(filterValue, 'contains');
273
279
  }
280
+ // ⛔ Don't override totalRecords here – we are in server-side mode
274
281
  onFilter(event) {
275
- this.totalRecords = event.filteredValue?.length || 0;
282
+ this.filter.emit(event);
283
+ // this.totalRecords = event.filteredValue?.length || 0; // removed
284
+ }
285
+ onPageChange(event) {
286
+ const page = event.page ?? Math.floor((event.first || 0) / event.rows);
287
+ const rows = event.rows;
288
+ this.rows = rows;
289
+ this.pageChange.emit({ page, rows });
276
290
  }
277
291
  onCalendarFilterChange(event, columnCode, filterCallback) {
278
- // Log the data's date format for debugging
279
- console.log('Data Before Filtering:', this.data.map((item) => item[columnCode]));
280
- console.log('event : ' + event);
281
- // Convert the event value to a string (in the desired date format)
282
292
  const filterValue = event ? new Date(event) : null;
283
- console.log('filterValue : ' + filterValue);
284
- // If the filterValue is empty, do not trigger filterCallback
285
293
  if (!filterValue) {
286
294
  return;
287
295
  }
288
- // Manually trigger the filterCallback after updating the value (passing the string value)
289
296
  filterCallback(filterValue);
290
297
  const filterValueString = event ? this.formatDate(event) : '';
291
- // Call the onFilter event to update totalRecords
292
298
  this.onFilter({
293
299
  filteredValue: this.data.filter((item) => {
294
300
  const columnValue = item[columnCode];
295
- // If the column value is a string, use it as is for comparison
296
301
  if (columnValue) {
297
- // Convert the item value to a string (in the same format)
298
302
  const itemDateString = this.formatDate(new Date(columnValue));
299
- return itemDateString === filterValueString; // Compare the string dates
303
+ return itemDateString === filterValueString;
300
304
  }
301
305
  return false;
302
306
  }),
303
307
  });
304
308
  }
305
- // Filter logic for composed columns (to check against multi-select values)
306
309
  filterComposedData(item, composedName, value) {
307
310
  if (Array.isArray(value) && value.length > 0) {
308
311
  return value.some((filterValue) => item[composedName]?.toLowerCase().includes(filterValue.toLowerCase()));
309
312
  }
310
313
  return true;
311
314
  }
312
- // Function to calculate column width based on text in header and data
313
315
  calculateColumnWidth(col) {
314
316
  const calculatedWidth = calculateTextWidth(col, col.title);
315
317
  const totalWidth = calculatedWidth + this.iconWidth + 20;
316
318
  return `${totalWidth}px`;
317
319
  }
318
320
  getHeaderWidth(col) {
319
- // Remove 'px' from col.width and convert it to a number
320
321
  const widthWithoutPx = parseInt(col.width?.replace('px', '') || '0', 10);
321
- // Add 20 to the calculated width
322
322
  const headerWidth = widthWithoutPx + 20;
323
- // Return the new width in 'px'
324
323
  return `${headerWidth}px`;
325
324
  }
326
325
  clear(table) {
@@ -330,7 +329,6 @@ class PTAdvancedPrimeTableComponent {
330
329
  parseDate(dateString) {
331
330
  const parts = dateString.split('/');
332
331
  if (parts.length === 3) {
333
- // Assuming date format is DD/MM/YYYY
334
332
  const day = parseInt(parts[0], 10);
335
333
  const month = parseInt(parts[1], 10) - 1;
336
334
  const year = parseInt(parts[2], 10);
@@ -341,7 +339,6 @@ class PTAdvancedPrimeTableComponent {
341
339
  }
342
340
  initializePagination() {
343
341
  if (this.isPaginated) {
344
- // Check if rowsPerPage is undefined or an empty array
345
342
  if (!this.rowsPerPage || this.rowsPerPage.length === 0) {
346
343
  this.rowsPerPage = [20, 30, 40];
347
344
  }
@@ -422,7 +419,6 @@ class PTAdvancedPrimeTableComponent {
422
419
  return 'text';
423
420
  }
424
421
  }
425
- // State Check Methods
426
422
  isEditable(key) {
427
423
  let column = this.columns.find((item) => item.code === key);
428
424
  return column?.isEditable !== false;
@@ -444,7 +440,6 @@ class PTAdvancedPrimeTableComponent {
444
440
  return (this.columns.find((item) => item.code === key)?.type ===
445
441
  TableTypeEnum.DATE);
446
442
  }
447
- // Utility Methods
448
443
  dateConverter(value) {
449
444
  return new Date(value).toLocaleDateString('en-US');
450
445
  }
@@ -461,14 +456,12 @@ class PTAdvancedPrimeTableComponent {
461
456
  filterGlobal(event) {
462
457
  const target = event.target;
463
458
  const value = target.value.toLowerCase();
464
- // Create a new filtered dataset
465
459
  const filteredData = this.data.filter((item) => {
466
460
  return this.globalFilterFields.some((field) => {
467
461
  const column = this.columns.find((col) => col.code === field);
468
462
  if (!column) {
469
463
  return false;
470
464
  }
471
- // Handle different column types
472
465
  if (column.type === TableTypeEnum.DATE) {
473
466
  const itemDate = this.formatDate(item[field]);
474
467
  return itemDate && itemDate.includes(value);
@@ -478,7 +471,6 @@ class PTAdvancedPrimeTableComponent {
478
471
  return (item[field] && item[field].toString().toLowerCase().includes(value));
479
472
  }
480
473
  else if (column.type === TableTypeEnum.COMPOSED) {
481
- // Handle composed type by searching for text in the composed cells
482
474
  return this.filterComposedColumn(item[field], value);
483
475
  }
484
476
  else {
@@ -486,14 +478,12 @@ class PTAdvancedPrimeTableComponent {
486
478
  }
487
479
  });
488
480
  });
489
- // Update the table's value
490
481
  this.dt.value = filteredData;
491
- // After filtering, update the totalRecords
492
- this.totalRecords = filteredData.length ?? 0;
482
+ // do NOT override totalRecords in server-side mode
483
+ // this.totalRecords = filteredData.length ?? 0;
493
484
  }
494
485
  filterComposedColumn(composedData, value) {
495
486
  if (composedData) {
496
- // Iterate over composed keys and check if any key's value contains the search text
497
487
  return Object.keys(composedData).some((key) => {
498
488
  const cellValue = composedData[key];
499
489
  if (typeof cellValue === 'string') {
@@ -508,20 +498,17 @@ class PTAdvancedPrimeTableComponent {
508
498
  if (!date)
509
499
  return '';
510
500
  if (date instanceof Date) {
511
- // Handle Date object
512
501
  const day = date.getDate().toString().padStart(2, '0');
513
502
  const month = (date.getMonth() + 1).toString().padStart(2, '0');
514
503
  const year = date.getFullYear().toString();
515
504
  return `${day}/${month}/${year}`;
516
505
  }
517
506
  else if (typeof date === 'string') {
518
- // Handle string date
519
507
  const parts = date.split('/');
520
508
  if (parts.length === 3) {
521
509
  return `${parts[0]}/${parts[1]}/${parts[2]}`;
522
510
  }
523
511
  else {
524
- // Handle partial dates
525
512
  return date;
526
513
  }
527
514
  }
@@ -539,7 +526,6 @@ class PTAdvancedPrimeTableComponent {
539
526
  width: style.width || 'auto',
540
527
  height: style.height || 'auto',
541
528
  };
542
- // Fallback to empty string if margin, marginLeft, or marginRight are undefined
543
529
  if (style.margin) {
544
530
  imageStyle.margin = style.margin;
545
531
  }
@@ -572,15 +558,12 @@ class PTAdvancedPrimeTableComponent {
572
558
  formatNumber(value, decimalPlaces, thousandSeparator = 'comma', decimalSeparator = 'dot') {
573
559
  if (value === null || value === undefined || isNaN(value))
574
560
  return '';
575
- // Convert the number to a string with full precision if decimalPlaces is undefined
576
561
  let formattedNumber = decimalPlaces !== undefined
577
562
  ? value.toFixed(decimalPlaces)
578
563
  : value.toString();
579
- // Replace decimal separator (default is "dot")
580
564
  if (decimalSeparator === 'comma') {
581
565
  formattedNumber = formattedNumber.replace('.', ',');
582
566
  }
583
- // Apply thousand separator only if the number is >= 1000
584
567
  if (thousandSeparator && Math.abs(value) >= 1000) {
585
568
  const parts = formattedNumber.split(decimalSeparator === 'comma' ? ',' : '.');
586
569
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator === 'comma' ? ',' : ' ');
@@ -589,11 +572,11 @@ class PTAdvancedPrimeTableComponent {
589
572
  return formattedNumber;
590
573
  }
591
574
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTAdvancedPrimeTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
592
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTAdvancedPrimeTableComponent, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", isPaginated: "isPaginated", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight" }, outputs: { filter: "filter", search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines\"\n styleClass=\"p-datatable-striped\"\n editMode=\"row\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <!-- Add this wrapper div with ml-auto class -->\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n colspan=\"1\"\n >\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <th\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span>{{ col.title }}</span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\n <!-- TableTypeEnum.COMPOSED -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n (onFilter)=\"onFilter($event)\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [ngModel]=\"filters[composedName]?.value\"\n [options]=\"filters[composedName]?.options\"\n (onChange)=\"\n onComposedFilterChange(\n composedName,\n $event.value\n )\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n [display]=\"'chip'\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n\n <!-- Define itemTemplate here -->\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </ng-template>\n </p-columnFilter>\n\n <!-- other TableTypeEnum.XXX -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- TableTypeEnum.NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n (onFilter)=\"onFilter($event)\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [placeholder]=\"'Enter a number'\"\n />\n </ng-template>\n\n <!-- TableTypeEnum.DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"\n onCalendarFilterChange(\n $event,\n col.code!,\n filterCallback\n )\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n [placeholder]=\"'Choose a date'\"\n ></p-calendar>\n </ng-template>\n\n <!-- TableTypeEnum.MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.MULTISELECT\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n [placeholder]=\"'Choose option'\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </th>\n </ng-container>\n <ng-template #noSortHeader>\n <th>\n <div class=\"header-container\">\n <span>{{ col.title }}</span>\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n ></p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </th>\n </ng-template>\n </th>\n <!-- Grouped headers -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.text-align]=\"'center'\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n <!-- Child headers (Second Row) -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n >\n <!-- Sortable/Filterable header logic for child columns -->\n </th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- Empty message template -->\n <ng-template pTemplate=\"emptymessage\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </ng-template>\n\n <!-- Body -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <!-- Render a table row and make it editable if `isEdit` is true -->\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <!-- Loop through each column -->\n <ng-container *ngFor=\"let col of columns\">\n <!-- Check if the column has children -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- Render a single cell for columns without children -->\n <ng-container\n *ngIf=\"col.code !== undefined && data[col.code] !== undefined\"\n >\n <td\n *ngIf=\"isEditable(col.code); else normalTD\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for the column -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container\n *ngIf=\"isDatePicker(col.code); else normalInput\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code]\"\n [ngModel]=\"data[col.code]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <ng-template #normalTD>\n <td [style.width]=\"getHeaderWidth(col)\">\n <!-- COMPOSED -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.COMPOSED\">\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- Check if the composedType is IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code][composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"getImageStyle(col.composedStyles?.[composedName])\"\n />\n </ng-container>\n\n <!-- Check if the composedType is STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"getTitleStyle(col.composedStyles?.[composedName])\"\n >\n {{ data[col.code][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- AMOUNT-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.AMOUNT\">\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <!-- NUMBER-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.NUMBER\">\n {{\n formatNumber(\n data[col.code],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <!-- DATE -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.DATE\">\n <!-- Format the date using your formatDate method -->\n {{ formatDate(data[col.code]) }}\n </ng-container>\n\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code] }}\n </ng-container>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Render child columns if the column has children -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <ng-container\n *ngIf=\"\n child.code !== undefined && data[child.code] !== undefined\n \"\n >\n <td [style.width]=\"getHeaderWidth(child)\">\n <!-- Render editable or normal cells for child columns -->\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[child.code]\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[child.code] }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ data[child.code] }}\n </ng-template>\n </td>\n </ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n\n <!-- Render action buttons if there are any actions defined -->\n <td *ngIf=\"actions?.length\">\n <div class=\"action-buttons-container\">\n <div *ngIf=\"isDelete\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n <div>\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable{display:flex;flex-direction:column;width:100%;border-collapse:collapse;table-layout:fixed}.pt-advanced-prime-table ::ng-deep .p-datatable thead{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tfoot{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tbody{display:block;overflow-y:auto;overflow-x:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable tbody tr{display:table;width:100%;table-layout:fixed}.pt-advanced-prime-table .empty-message{text-align:center;padding:2rem;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i6.Calendar, selector: "p-calendar", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepYearPicker", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconField", inputs: ["iconPosition"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputIcon", inputs: ["styleClass"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
575
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTAdvancedPrimeTableComponent, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", isPaginated: "isPaginated", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight" }, outputs: { filter: "filter", search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent", pageChange: "pageChange" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"true\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines\"\n styleClass=\"p-datatable-striped\"\n editMode=\"row\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n (onPage)=\"onPageChange($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <!-- Add this wrapper div with ml-auto class -->\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n colspan=\"1\"\n >\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <th\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span>{{ col.title }}</span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\n <!-- TableTypeEnum.COMPOSED -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n (onFilter)=\"onFilter($event)\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [ngModel]=\"filters[composedName]?.value\"\n [options]=\"filters[composedName]?.options\"\n (onChange)=\"\n onComposedFilterChange(\n col,\n composedName,\n $event.value\n )\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n [display]=\"'chip'\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n\n <!-- Define itemTemplate here -->\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </ng-template>\n </p-columnFilter>\n\n <!-- other TableTypeEnum.XXX -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- TableTypeEnum.NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n (onFilter)=\"onFilter($event)\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [placeholder]=\"'Enter a number'\"\n />\n </ng-template>\n\n <!-- TableTypeEnum.DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"\n onCalendarFilterChange(\n $event,\n col.code!,\n filterCallback\n )\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n [placeholder]=\"'Choose a date'\"\n ></p-calendar>\n </ng-template>\n\n <!-- TableTypeEnum.MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n (onFilter)=\"onFilter($event)\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n [placeholder]=\"'Choose option'\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </th>\n </ng-container>\n <ng-template #noSortHeader>\n <th>\n <div class=\"header-container\">\n <span>{{ col.title }}</span>\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n ></p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </th>\n </ng-template>\n </th>\n <!-- Grouped headers -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.text-align]=\"'center'\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n <!-- Child headers (Second Row) -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n >\n <!-- Sortable/Filterable header logic for child columns -->\n </th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- Empty message template -->\n <ng-template pTemplate=\"emptymessage\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </ng-template>\n\n <!-- Body -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <!-- Render a table row and make it editable if `isEdit` is true -->\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <!-- Loop through each column -->\n <ng-container *ngFor=\"let col of columns\">\n <!-- Check if the column has children -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- Render a single cell for columns without children -->\n <ng-container\n *ngIf=\"col.code !== undefined && data[col.code] !== undefined\"\n >\n <td\n *ngIf=\"isEditable(col.code); else normalTD\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for the column -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container\n *ngIf=\"isDatePicker(col.code); else normalInput\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code]\"\n [ngModel]=\"data[col.code]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <ng-template #normalTD>\n <td [style.width]=\"getHeaderWidth(col)\">\n <!-- COMPOSED -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.COMPOSED\">\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- Check if the composedType is IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code][composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"getImageStyle(col.composedStyles?.[composedName])\"\n />\n </ng-container>\n\n <!-- Check if the composedType is STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"getTitleStyle(col.composedStyles?.[composedName])\"\n >\n {{ data[col.code][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- AMOUNT-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.AMOUNT\">\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <!-- NUMBER-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.NUMBER\">\n {{\n formatNumber(\n data[col.code],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <!-- DATE -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.DATE\">\n <!-- Format the date using your formatDate method -->\n {{ formatDate(data[col.code]) }}\n </ng-container>\n\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code] }}\n </ng-container>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Render child columns if the column has children -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <ng-container\n *ngIf=\"\n child.code !== undefined && data[child.code] !== undefined\n \"\n >\n <td [style.width]=\"getHeaderWidth(child)\">\n <!-- Render editable or normal cells for child columns -->\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[child.code]\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[child.code] }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ data[child.code] }}\n </ng-template>\n </td>\n </ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n\n <!-- Render action buttons if there are any actions defined -->\n <td *ngIf=\"actions?.length\">\n <div class=\"action-buttons-container\">\n <div *ngIf=\"isDelete\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n <div>\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable{display:flex;flex-direction:column;width:100%;border-collapse:collapse;table-layout:fixed}.pt-advanced-prime-table ::ng-deep .p-datatable thead{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tfoot{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tbody{display:block;overflow-y:auto;overflow-x:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable tbody tr{display:table;width:100%;table-layout:fixed}.pt-advanced-prime-table .empty-message{text-align:center;padding:2rem;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll", "virtualRowHeight"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["variant"] }, { kind: "directive", type: i3.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain"] }, { kind: "component", type: i6.Calendar, selector: "p-calendar", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepYearPicker", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconField", inputs: ["iconPosition"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputIcon", inputs: ["styleClass"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
593
576
  }
594
577
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTAdvancedPrimeTableComponent, decorators: [{
595
578
  type: Component,
596
- args: [{ selector: 'pt-advanced-prime-table', template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines\"\n styleClass=\"p-datatable-striped\"\n editMode=\"row\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <!-- Add this wrapper div with ml-auto class -->\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n colspan=\"1\"\n >\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <th\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span>{{ col.title }}</span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\n <!-- TableTypeEnum.COMPOSED -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n (onFilter)=\"onFilter($event)\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [ngModel]=\"filters[composedName]?.value\"\n [options]=\"filters[composedName]?.options\"\n (onChange)=\"\n onComposedFilterChange(\n composedName,\n $event.value\n )\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n [display]=\"'chip'\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n\n <!-- Define itemTemplate here -->\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </ng-template>\n </p-columnFilter>\n\n <!-- other TableTypeEnum.XXX -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- TableTypeEnum.NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n (onFilter)=\"onFilter($event)\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [placeholder]=\"'Enter a number'\"\n />\n </ng-template>\n\n <!-- TableTypeEnum.DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"\n onCalendarFilterChange(\n $event,\n col.code!,\n filterCallback\n )\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n [placeholder]=\"'Choose a date'\"\n ></p-calendar>\n </ng-template>\n\n <!-- TableTypeEnum.MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.MULTISELECT\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n [placeholder]=\"'Choose option'\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </th>\n </ng-container>\n <ng-template #noSortHeader>\n <th>\n <div class=\"header-container\">\n <span>{{ col.title }}</span>\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n ></p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </th>\n </ng-template>\n </th>\n <!-- Grouped headers -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.text-align]=\"'center'\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n <!-- Child headers (Second Row) -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n >\n <!-- Sortable/Filterable header logic for child columns -->\n </th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- Empty message template -->\n <ng-template pTemplate=\"emptymessage\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </ng-template>\n\n <!-- Body -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <!-- Render a table row and make it editable if `isEdit` is true -->\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <!-- Loop through each column -->\n <ng-container *ngFor=\"let col of columns\">\n <!-- Check if the column has children -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- Render a single cell for columns without children -->\n <ng-container\n *ngIf=\"col.code !== undefined && data[col.code] !== undefined\"\n >\n <td\n *ngIf=\"isEditable(col.code); else normalTD\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for the column -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container\n *ngIf=\"isDatePicker(col.code); else normalInput\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code]\"\n [ngModel]=\"data[col.code]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <ng-template #normalTD>\n <td [style.width]=\"getHeaderWidth(col)\">\n <!-- COMPOSED -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.COMPOSED\">\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- Check if the composedType is IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code][composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"getImageStyle(col.composedStyles?.[composedName])\"\n />\n </ng-container>\n\n <!-- Check if the composedType is STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"getTitleStyle(col.composedStyles?.[composedName])\"\n >\n {{ data[col.code][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- AMOUNT-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.AMOUNT\">\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <!-- NUMBER-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.NUMBER\">\n {{\n formatNumber(\n data[col.code],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <!-- DATE -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.DATE\">\n <!-- Format the date using your formatDate method -->\n {{ formatDate(data[col.code]) }}\n </ng-container>\n\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code] }}\n </ng-container>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Render child columns if the column has children -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <ng-container\n *ngIf=\"\n child.code !== undefined && data[child.code] !== undefined\n \"\n >\n <td [style.width]=\"getHeaderWidth(child)\">\n <!-- Render editable or normal cells for child columns -->\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[child.code]\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[child.code] }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ data[child.code] }}\n </ng-template>\n </td>\n </ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n\n <!-- Render action buttons if there are any actions defined -->\n <td *ngIf=\"actions?.length\">\n <div class=\"action-buttons-container\">\n <div *ngIf=\"isDelete\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n <div>\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable{display:flex;flex-direction:column;width:100%;border-collapse:collapse;table-layout:fixed}.pt-advanced-prime-table ::ng-deep .p-datatable thead{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tfoot{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tbody{display:block;overflow-y:auto;overflow-x:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable tbody tr{display:table;width:100%;table-layout:fixed}.pt-advanced-prime-table .empty-message{text-align:center;padding:2rem;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}\n"] }]
579
+ args: [{ selector: 'pt-advanced-prime-table', template: "<div class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"data\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"true\"\n dataKey=\"id\"\n styleClass=\"p-datatable-gridlines\"\n styleClass=\"p-datatable-striped\"\n editMode=\"row\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n (onPage)=\"onPageChange($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n <!-- Clear filters -->\n <button\n *ngIf=\"hasSearchFilter\"\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n\n <!-- Export to Excel Button -->\n <button\n *ngIf=\"hasExportExcel\"\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n\n <!-- Export to PDF Button -->\n <button\n *ngIf=\"hasExportPDF\"\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n </div>\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\n <!-- Add this wrapper div with ml-auto class -->\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n <ng-container *ngFor=\"let col of columns\">\n <th\n *ngIf=\"!col.children; else groupHeader\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.padding]=\"'0px'\"\n colspan=\"1\"\n >\n <ng-container\n *ngIf=\"isSortable && col.isSortable !== false; else noSortHeader\"\n >\n <th\n pSortableColumn=\"{{ col.code }}\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width\"\n [style.padding]=\"'0px'\"\n [style.margin]=\"'10px'\"\n >\n <span>{{ col.title }}</span>\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon field=\"{{ col.code }}\" />\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\n <!-- TableTypeEnum.COMPOSED -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n (onFilter)=\"onFilter($event)\"\n >\n <div *ngFor=\"let composedName of col.composedNames\">\n <ng-container\n *ngIf=\"\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n \"\n >\n <p-multiSelect\n [ngModel]=\"filters[composedName]?.value\"\n [options]=\"filters[composedName]?.options\"\n (onChange)=\"\n onComposedFilterChange(\n col,\n composedName,\n $event.value\n )\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n [display]=\"'chip'\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-container>\n </div>\n\n <!-- Define itemTemplate here -->\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n <img\n *ngIf=\"item.image\"\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </ng-template>\n </p-columnFilter>\n\n <!-- other TableTypeEnum.XXX -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n display=\"menu\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- TableTypeEnum.NUMBER -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.NUMBER\"\n (onFilter)=\"onFilter($event)\"\n >\n <input\n pInputText\n type=\"number\"\n [step]=\"\n col.decimalPlaces\n ? '0.' + '1'.padEnd(col.decimalPlaces, '0')\n : 'any'\n \"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [placeholder]=\"'Enter a number'\"\n />\n </ng-template>\n\n <!-- TableTypeEnum.DATE -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n (onFilter)=\"onFilter($event)\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"\n onCalendarFilterChange(\n $event,\n col.code!,\n filterCallback\n )\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n [placeholder]=\"'Choose a date'\"\n ></p-calendar>\n </ng-template>\n\n <!-- TableTypeEnum.MULTISELECT -->\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n (onFilter)=\"onFilter($event)\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n [placeholder]=\"'Choose option'\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </div>\n </th>\n </ng-container>\n <ng-template #noSortHeader>\n <th>\n <div class=\"header-container\">\n <span>{{ col.title }}</span>\n <ng-container *ngIf=\"col.isFilter !== false\">\n <p-columnFilter\n *ngIf=\"col.type === 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n ></p-columnFilter>\n\n <p-columnFilter\n *ngIf=\"col.type !== 'AMOUNT'\"\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-calendar\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-value\n let-filterCallback=\"filterCallback\"\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n [ngModel]=\"value\"\n (ngModelChange)=\"filterCallback($event)\"\n [display]=\"'chip'\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n </ng-container>\n </div>\n </th>\n </ng-template>\n </th>\n <!-- Grouped headers -->\n <ng-template #groupHeader>\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"getHeaderWidth(col)\"\n [style.text-align]=\"'center'\"\n >\n <span>{{ col.title }}</span>\n </th>\n </ng-template>\n </ng-container>\n </tr>\n <!-- Child headers (Second Row) -->\n <tr *ngIf=\"hasGroupedColumns\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"col.children\">\n <th\n *ngFor=\"let child of col.children\"\n [style.width]=\"getHeaderWidth(child)\"\n [style.padding]=\"'0px'\"\n >\n <!-- Sortable/Filterable header logic for child columns -->\n </th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- Empty message template -->\n <ng-template pTemplate=\"emptymessage\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </ng-template>\n\n <!-- Body -->\n <ng-template\n pTemplate=\"body\"\n let-data\n let-editing=\"editing\"\n let-ri=\"rowIndex\"\n >\n <!-- Render a table row and make it editable if `isEdit` is true -->\n <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <!-- Loop through each column -->\n <ng-container *ngFor=\"let col of columns\">\n <!-- Check if the column has children -->\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- Render a single cell for columns without children -->\n <ng-container\n *ngIf=\"col.code !== undefined && data[col.code] !== undefined\"\n >\n <td\n *ngIf=\"isEditable(col.code); else normalTD\"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for the column -->\n <ng-container *ngIf=\"isMultiSelect(col.code); else datePicker\">\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n <ng-container *ngFor=\"let rec of data[col.code]\">\n <p-tag [value]=\"rec\"></p-tag>\n </ng-container>\n </div>\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #datePicker>\n <ng-container\n *ngIf=\"isDatePicker(col.code); else normalInput\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-calendar\n [inputId]=\"data[col.code]\"\n [ngModel]=\"data[col.code]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-calendar>\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[col.code] | customDate }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n </ng-template>\n\n <ng-template #normalInput>\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else normalOutput\n \"\n >\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n <ng-template #normalOutput>\n {{ data[col.code] }}\n </ng-template>\n </ng-template>\n </p-cellEditor>\n </ng-template>\n </td>\n\n <ng-template #normalTD>\n <td [style.width]=\"getHeaderWidth(col)\">\n <!-- COMPOSED -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.COMPOSED\">\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- Check if the composedType is IMAGE -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n \"\n >\n <img\n [src]=\"data[col.code][composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"getImageStyle(col.composedStyles?.[composedName])\"\n />\n </ng-container>\n\n <!-- Check if the composedType is STRING -->\n <ng-container\n *ngIf=\"\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n \"\n >\n <span\n class=\"composed-text\"\n [ngStyle]=\"getTitleStyle(col.composedStyles?.[composedName])\"\n >\n {{ data[col.code][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <!-- AMOUNT-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.AMOUNT\">\n {{\n data[col.code]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n </ng-container>\n\n <!-- NUMBER-->\n <ng-container *ngIf=\"col.type === TableTypeEnum.NUMBER\">\n {{\n formatNumber(\n data[col.code],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <!-- DATE -->\n <ng-container *ngIf=\"col.type === TableTypeEnum.DATE\">\n <!-- Format the date using your formatDate method -->\n {{ formatDate(data[col.code]) }}\n </ng-container>\n\n <!-- STRING, MULTISELECT-->\n <ng-container\n *ngIf=\"\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT\n ].includes(col.type!)\n \"\n >\n {{ data[col.code] }}\n </ng-container>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- Render child columns if the column has children -->\n <ng-template #childColumns>\n <ng-container *ngFor=\"let child of col.children\">\n <ng-container\n *ngIf=\"\n child.code !== undefined && data[child.code] !== undefined\n \"\n >\n <td [style.width]=\"getHeaderWidth(child)\">\n <!-- Render editable or normal cells for child columns -->\n <ng-container\n *ngIf=\"isEditable(child.code); else childNormalTD\"\n >\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[child.code]\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n <ng-template pTemplate=\"output\">\n {{ data[child.code] }}\n </ng-template>\n </p-cellEditor>\n </ng-container>\n\n <ng-template #childNormalTD>\n {{ data[child.code] }}\n </ng-template>\n </td>\n </ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n\n <!-- Render action buttons if there are any actions defined -->\n <td *ngIf=\"actions?.length\">\n <div class=\"action-buttons-container\">\n <div *ngIf=\"isDelete\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data.id)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n <div>\n <button\n pInitEditableRow\n *ngIf=\"!editing\"\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n <button\n *ngIf=\"editing\"\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n </p-table>\n</div>\n", styles: [".pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{width:100%;height:5rem;display:grid;justify-items:start;align-items:center}.pt-advanced-prime-table .filter-container{width:100%;display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .settings{display:flex;gap:1rem}.pt-advanced-prime-table .multi-select-container{display:flex;justify-content:center;align-items:center;gap:.3rem}.pt-advanced-prime-table ::ng-deep p-table{min-width:50rem}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;justify-content:space-between;align-items:center;width:100%}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;justify-content:space-between;align-items:center}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-inputicon{margin-right:-1.5rem;z-index:2;position:relative}.pt-advanced-prime-table ::ng-deep .p-inputtext{padding-left:1.7rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{cursor:pointer;margin-left:1rem}.pt-advanced-prime-table ::ng-deep .p-icon-field-left .p-input-icon:first-of-type{left:-1rem}.pt-advanced-prime-table .table-row{text-align:center;display:flex;gap:1rem;justify-content:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{font-size:1.25em;color:green}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{font-size:1.25em;color:red}.pt-advanced-prime-table .table-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable{display:flex;flex-direction:column;width:100%;border-collapse:collapse;table-layout:fixed}.pt-advanced-prime-table ::ng-deep .p-datatable thead{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tfoot{display:table;width:100%;table-layout:fixed;background:#fff;z-index:2}.pt-advanced-prime-table ::ng-deep .p-datatable tbody{display:block;overflow-y:auto;overflow-x:hidden}.pt-advanced-prime-table ::ng-deep .p-datatable tbody tr{display:table;width:100%;table-layout:fixed}.pt-advanced-prime-table .empty-message{text-align:center;padding:2rem;color:#888;font-size:1.2rem}.pt-advanced-prime-table .empty-message i{display:block;font-size:2rem;margin-bottom:.5rem}.pt-advanced-prime-table th{white-space:normal;word-wrap:break-word}.filter-image{width:22px;height:14px;margin-right:5px}\n"] }]
597
580
  }], ctorParameters: () => [], propDecorators: { data: [{
598
581
  type: Input
599
582
  }], columns: [{
@@ -628,6 +611,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
628
611
  type: Output
629
612
  }], exportPdfEvent: [{
630
613
  type: Output
614
+ }], pageChange: [{
615
+ type: Output
631
616
  }], dt: [{
632
617
  type: ViewChild,
633
618
  args: ['dt', { static: false }]
@@ -3368,6 +3353,7 @@ class PTButtonComponent {
3368
3353
  fontColor: '#000',
3369
3354
  backgroundColor: '#fff',
3370
3355
  borderColor: '#000',
3356
+ outlined: false,
3371
3357
  };
3372
3358
  }
3373
3359
  }
@@ -3381,7 +3367,7 @@ class PTButtonComponent {
3381
3367
  JSON.stringify({ ...prev, disabled: undefined }) ===
3382
3368
  JSON.stringify({ ...curr, disabled: undefined });
3383
3369
  if (onlyDisabledChanged) {
3384
- this.updateDisabledStyles(curr.disabled);
3370
+ this.updateDisabledStyles(curr.disabled ?? false);
3385
3371
  }
3386
3372
  else {
3387
3373
  this.applyButtonStyles();
@@ -3393,14 +3379,6 @@ class PTButtonComponent {
3393
3379
  }
3394
3380
  }
3395
3381
  }
3396
- updateDisabledStyles(isDisabled) {
3397
- const buttonElement = this.el.nativeElement.querySelector('button.p-element');
3398
- if (buttonElement) {
3399
- this.renderer.setStyle(buttonElement, 'color', isDisabled ? '#999' : this.buttonConfig.fontColor);
3400
- this.renderer.setStyle(buttonElement, 'background-color', isDisabled ? '#e0e0e0' : this.buttonConfig.backgroundColor);
3401
- this.renderer.setStyle(buttonElement, 'border-color', isDisabled ? '#bdbdbd' : this.buttonConfig.borderColor);
3402
- }
3403
- }
3404
3382
  ngAfterViewInit() {
3405
3383
  this.applyButtonStyles();
3406
3384
  }
@@ -3410,23 +3388,58 @@ class PTButtonComponent {
3410
3388
  getType() {
3411
3389
  return this.buttonConfig.type || 'button';
3412
3390
  }
3391
+ updateDisabledStyles(isDisabled) {
3392
+ const buttonElement = this.el.nativeElement.querySelector('button.p-element');
3393
+ if (buttonElement) {
3394
+ this.renderer.setStyle(buttonElement, 'color', isDisabled ? '#999' : this.buttonConfig.fontColor);
3395
+ this.renderer.setStyle(buttonElement, 'background-color', isDisabled ? '#e0e0e0' : this.buttonConfig.backgroundColor);
3396
+ this.renderer.setStyle(buttonElement, 'border-color', isDisabled ? '#bdbdbd' : this.buttonConfig.borderColor);
3397
+ }
3398
+ }
3399
+ /**
3400
+ * We delegate colors to PrimeNG theme when:
3401
+ * - outlined = true
3402
+ * - and no manual color is provided (no backgroundColor, borderColor, fontColor)
3403
+ */
3404
+ shouldUseThemeColors() {
3405
+ if (!this.buttonConfig) {
3406
+ return false;
3407
+ }
3408
+ const outlined = !!this.buttonConfig.outlined; // ✅ coerce to boolean
3409
+ return (outlined &&
3410
+ !this.buttonConfig.backgroundColor &&
3411
+ !this.buttonConfig.borderColor &&
3412
+ !this.buttonConfig.fontColor);
3413
+ }
3413
3414
  applyButtonStyles() {
3414
3415
  const buttonElement = this.el.nativeElement.querySelector('button.p-element');
3415
- if (buttonElement && this.buttonConfig) {
3416
- const isDisabled = this.buttonConfig.disabled;
3416
+ if (!buttonElement || !this.buttonConfig) {
3417
+ return;
3418
+ }
3419
+ const isDisabled = !!this.buttonConfig.disabled;
3420
+ const useThemeColors = this.shouldUseThemeColors();
3421
+ // Width / height always applied
3422
+ this.renderer.setStyle(buttonElement, 'width', this.buttonConfig.width || 'auto');
3423
+ this.renderer.setStyle(buttonElement, 'height', this.buttonConfig.height || 'auto');
3424
+ // ✅ Only override colors when we are NOT delegating to PrimeNG theme
3425
+ if (!useThemeColors) {
3417
3426
  this.renderer.setStyle(buttonElement, 'color', isDisabled ? '#999' : this.buttonConfig.fontColor);
3418
3427
  this.renderer.setStyle(buttonElement, 'background-color', isDisabled ? '#e0e0e0' : this.buttonConfig.backgroundColor);
3419
3428
  this.renderer.setStyle(buttonElement, 'border-color', isDisabled ? '#bdbdbd' : this.buttonConfig.borderColor);
3420
- this.renderer.setStyle(buttonElement, 'width', this.buttonConfig.width || 'auto');
3421
- this.renderer.setStyle(buttonElement, 'height', this.buttonConfig.height || 'auto');
3429
+ }
3430
+ else {
3431
+ // If we delegate to theme, clear any inline overrides
3432
+ this.renderer.removeStyle(buttonElement, 'color');
3433
+ this.renderer.removeStyle(buttonElement, 'background-color');
3434
+ this.renderer.removeStyle(buttonElement, 'border-color');
3422
3435
  }
3423
3436
  }
3424
3437
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTButtonComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
3425
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTButtonComponent, selector: "pt-button", inputs: { buttonConfig: "buttonConfig" }, usesOnChanges: true, ngImport: i0, template: "<p-button\n [label]=\"buttonConfig.label\"\n [icon]=\"buttonConfig.icon || ''\"\n [iconPos]=\"getIconPos()\"\n [disabled]=\"buttonConfig.disabled\"\n [loading]=\"buttonConfig.loading\"\n [class]=\"buttonConfig.styleClass || ''\"\n [type]=\"getType()\"\n></p-button>\n", styles: ["::ng-deep p-button{display:block}\n"], dependencies: [{ kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }] }); }
3438
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTButtonComponent, selector: "pt-button", inputs: { buttonConfig: "buttonConfig" }, usesOnChanges: true, ngImport: i0, template: "<p-button\n [label]=\"buttonConfig.label\"\n [icon]=\"buttonConfig.icon || ''\"\n [iconPos]=\"getIconPos()\"\n [disabled]=\"buttonConfig.disabled\"\n [loading]=\"buttonConfig.loading\"\n [class]=\"buttonConfig.styleClass || ''\"\n [type]=\"getType()\"\n [severity]=\"buttonConfig.severity\"\n [outlined]=\"buttonConfig.outlined\"\n></p-button>\n", styles: ["::ng-deep p-button{display:block}\n"], dependencies: [{ kind: "component", type: i3.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }] }); }
3426
3439
  }
3427
3440
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTButtonComponent, decorators: [{
3428
3441
  type: Component,
3429
- args: [{ selector: 'pt-button', template: "<p-button\n [label]=\"buttonConfig.label\"\n [icon]=\"buttonConfig.icon || ''\"\n [iconPos]=\"getIconPos()\"\n [disabled]=\"buttonConfig.disabled\"\n [loading]=\"buttonConfig.loading\"\n [class]=\"buttonConfig.styleClass || ''\"\n [type]=\"getType()\"\n></p-button>\n", styles: ["::ng-deep p-button{display:block}\n"] }]
3442
+ args: [{ selector: 'pt-button', template: "<p-button\n [label]=\"buttonConfig.label\"\n [icon]=\"buttonConfig.icon || ''\"\n [iconPos]=\"getIconPos()\"\n [disabled]=\"buttonConfig.disabled\"\n [loading]=\"buttonConfig.loading\"\n [class]=\"buttonConfig.styleClass || ''\"\n [type]=\"getType()\"\n [severity]=\"buttonConfig.severity\"\n [outlined]=\"buttonConfig.outlined\"\n></p-button>\n", styles: ["::ng-deep p-button{display:block}\n"] }]
3430
3443
  }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { buttonConfig: [{
3431
3444
  type: Input
3432
3445
  }] } });
@@ -3668,49 +3681,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
3668
3681
  }]
3669
3682
  }] });
3670
3683
 
3671
- // Default Styles for Different Dialog Types
3684
+ /**
3685
+ * Styles per severity:
3686
+ * - Only header (text/color) is provided here.
3687
+ * - No default "content" text anymore.
3688
+ */
3672
3689
  const DIALOG_STYLES = {
3673
3690
  [SeverityEnum.WARNING]: {
3674
- header: { text: 'Warning', color: '#d98300' },
3675
- content: { text: 'This is a warning message!', color: '#d98300' },
3676
- confirmButtonConfig: { backgroundColor: '#d98300', fontColor: '#fff' },
3677
- cancelButtonConfig: { backgroundColor: '#6c757d', fontColor: '#fff' },
3691
+ header: { text: 'Avertissement', color: '#8a4b00' },
3678
3692
  },
3679
3693
  [SeverityEnum.SUCCESS]: {
3680
- header: { text: 'Success', color: '#28a745' },
3681
- content: { text: 'Operation was successful!', color: '#28a745' },
3682
- confirmButtonConfig: { backgroundColor: '#28a745', fontColor: '#fff' },
3683
- cancelButtonConfig: { backgroundColor: '#6c757d', fontColor: '#fff' },
3694
+ header: { text: 'Succès', color: '#166534' },
3684
3695
  },
3685
3696
  [SeverityEnum.DANGER]: {
3686
- header: { text: 'Error', color: '#dc3545' },
3687
- content: { text: 'An error occurred!', color: '#dc3545' },
3688
- confirmButtonConfig: { backgroundColor: '#dc3545', fontColor: '#fff' },
3689
- cancelButtonConfig: { backgroundColor: '#6c757d', fontColor: '#fff' },
3697
+ header: { text: 'Erreur', color: '#7f1d1d' },
3690
3698
  },
3691
3699
  [SeverityEnum.INFO]: {
3692
- header: { text: 'Information', color: '#007bff' },
3693
- content: { text: 'Here is some important information.', color: '#007bff' },
3694
- confirmButtonConfig: { backgroundColor: '#007bff', fontColor: '#fff' },
3695
- cancelButtonConfig: { backgroundColor: '#6c757d', fontColor: '#fff' },
3700
+ header: { text: 'Information', color: '#2563eb' },
3696
3701
  },
3697
3702
  };
3698
- // Centralized Default Values
3703
+ /**
3704
+ * Default config:
3705
+ * - content is now empty string (no default message).
3706
+ */
3699
3707
  const DEFAULT_DIALOG_CONFIG = {
3700
3708
  header: { text: 'Confirmation' },
3701
3709
  visible: false,
3702
- width: '400px',
3710
+ width: '720px',
3703
3711
  height: 'auto',
3704
- content: 'Do you want to proceed?',
3712
+ content: '', // no default message
3705
3713
  confirmButtonConfig: {
3706
- label: 'Confirm',
3707
- fontColor: '#fff',
3708
- backgroundColor: '#007bff',
3714
+ label: 'Confirmer',
3709
3715
  },
3710
3716
  cancelButtonConfig: {
3711
- label: 'Cancel',
3712
- fontColor: '#fff',
3713
- backgroundColor: '#6c757d',
3717
+ label: 'Annuler',
3714
3718
  },
3715
3719
  dialogStyle: SeverityEnum.INFO,
3716
3720
  };
@@ -3723,11 +3727,13 @@ class PTDialogComponent {
3723
3727
  this.dialogConfig = { ...DEFAULT_DIALOG_CONFIG };
3724
3728
  this.confirm = new EventEmitter();
3725
3729
  this.cancel = new EventEmitter();
3730
+ this.SeverityEnum = SeverityEnum;
3726
3731
  }
3727
3732
  ngOnChanges(changes) {
3728
3733
  if (changes['dialogConfig']) {
3729
- if (changes['dialogConfig'].currentValue?.dialogStyle !==
3730
- changes['dialogConfig'].previousValue?.dialogStyle) {
3734
+ const current = changes['dialogConfig'].currentValue;
3735
+ if (changes['dialogConfig'].previousValue?.dialogStyle !==
3736
+ current?.dialogStyle) {
3731
3737
  this.applyDialogStyle();
3732
3738
  }
3733
3739
  if (this.dialogConfig.visible) {
@@ -3735,80 +3741,124 @@ class PTDialogComponent {
3735
3741
  }
3736
3742
  }
3737
3743
  }
3744
+ /**
3745
+ * Merge defaults + current config + severity style.
3746
+ * We are careful NOT to spread header (it can be string or object).
3747
+ */
3738
3748
  applyDialogStyle() {
3739
3749
  const dialogStyle = this.dialogConfig.dialogStyle || SeverityEnum.INFO;
3740
3750
  const styleConfig = DIALOG_STYLES[dialogStyle] || {};
3751
+ const current = this.dialogConfig;
3752
+ // Decide which header to use without spreading non-object types
3753
+ const mergedHeader = current.header !== undefined
3754
+ ? current.header
3755
+ : styleConfig.header !== undefined
3756
+ ? styleConfig.header
3757
+ : DEFAULT_DIALOG_CONFIG.header;
3741
3758
  this.dialogConfig = {
3742
3759
  ...DEFAULT_DIALOG_CONFIG,
3760
+ ...current,
3743
3761
  ...styleConfig,
3762
+ header: mergedHeader,
3744
3763
  confirmButtonConfig: {
3745
3764
  ...DEFAULT_DIALOG_CONFIG.confirmButtonConfig,
3746
- ...styleConfig.confirmButtonConfig,
3765
+ ...current.confirmButtonConfig,
3747
3766
  },
3748
3767
  cancelButtonConfig: {
3749
3768
  ...DEFAULT_DIALOG_CONFIG.cancelButtonConfig,
3750
- ...styleConfig.cancelButtonConfig,
3769
+ ...current.cancelButtonConfig,
3751
3770
  },
3771
+ visible: current.visible,
3772
+ };
3773
+ }
3774
+ getSeverityClass() {
3775
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3776
+ switch (style) {
3777
+ case SeverityEnum.DANGER:
3778
+ return 'pt-dialog-danger';
3779
+ case SeverityEnum.WARNING:
3780
+ return 'pt-dialog-warning';
3781
+ case SeverityEnum.SUCCESS:
3782
+ return 'pt-dialog-success';
3783
+ case SeverityEnum.INFO:
3784
+ default:
3785
+ return 'pt-dialog-info';
3786
+ }
3787
+ }
3788
+ /** SUCCESS & INFO share same behaviour, only color differs */
3789
+ getSeverityColors() {
3790
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3791
+ switch (style) {
3792
+ case SeverityEnum.DANGER:
3793
+ return { header: '#b91c1c', message: '#4b5563' };
3794
+ case SeverityEnum.WARNING:
3795
+ return { header: '#b45309', message: '#92400e' };
3796
+ case SeverityEnum.SUCCESS:
3797
+ return { header: '#15803d', message: '#166534' };
3798
+ case SeverityEnum.INFO:
3799
+ default:
3800
+ return { header: '#2563eb', message: '#2563eb' };
3801
+ }
3802
+ }
3803
+ // ───────────── Button models for pt-button ─────────────
3804
+ get confirmButtonModel() {
3805
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3806
+ const confirmSeverity = style === SeverityEnum.DANGER
3807
+ ? SeverityEnum.DANGER
3808
+ : style === SeverityEnum.WARNING
3809
+ ? SeverityEnum.WARNING
3810
+ : style === SeverityEnum.SUCCESS
3811
+ ? SeverityEnum.SUCCESS
3812
+ : SeverityEnum.INFO;
3813
+ return {
3814
+ label: this.dialogConfig.confirmButtonConfig?.label ?? 'Confirmer',
3815
+ icon: this.dialogConfig.confirmButtonConfig?.icon ?? 'pi pi-check',
3816
+ iconPos: 'left',
3817
+ type: 'button',
3818
+ outlined: true,
3819
+ severity: confirmSeverity,
3820
+ styleClass: (this.dialogConfig.confirmButtonConfig?.styleClass || '') +
3821
+ ' pt-dialog-confirm-btn',
3822
+ width: 'auto',
3823
+ };
3824
+ }
3825
+ get cancelButtonModel() {
3826
+ return {
3827
+ label: this.dialogConfig.cancelButtonConfig?.label ?? 'Annuler',
3828
+ icon: this.dialogConfig.cancelButtonConfig?.icon ?? 'pi pi-times',
3829
+ iconPos: 'left',
3830
+ type: 'button',
3831
+ outlined: true,
3832
+ severity: SeverityEnum.INFO,
3833
+ styleClass: (this.dialogConfig.cancelButtonConfig?.styleClass || '') +
3834
+ ' pt-dialog-cancel-btn',
3835
+ width: 'auto',
3752
3836
  };
3753
3837
  }
3754
3838
  showDialog() {
3755
3839
  this.confirmationService.confirm({
3756
- header: this.getDialogHeaderText(),
3840
+ header: '',
3841
+ // message is not really used visually, but kept here
3757
3842
  message: this.getDialogContentText(),
3758
- acceptLabel: this.dialogConfig.confirmButtonConfig?.label || 'Confirm',
3759
- rejectLabel: this.dialogConfig.cancelButtonConfig?.label || 'Cancel',
3760
- acceptButtonStyleClass: this.getButtonStyle(this.dialogConfig.confirmButtonConfig, true),
3761
- rejectButtonStyleClass: this.getButtonStyle(this.dialogConfig.cancelButtonConfig, false),
3762
- acceptIcon: this.dialogConfig.confirmButtonConfig?.icon || 'pi pi-check',
3763
- rejectIcon: this.dialogConfig.cancelButtonConfig?.icon || 'pi pi-times',
3764
- accept: () => {
3765
- this.confirm.emit();
3766
- if (this.dialogConfig.toastOnConfirm) {
3767
- }
3768
- },
3769
- reject: (type) => {
3770
- this.cancel.emit();
3771
- if (type === ConfirmEventType.REJECT &&
3772
- this.dialogConfig.toastOnCancel) {
3773
- }
3774
- },
3843
+ accept: () => this.confirm.emit(),
3844
+ reject: (_type) => this.cancel.emit(),
3775
3845
  });
3776
- // Use renderer to apply dynamic styles
3777
3846
  setTimeout(() => {
3778
- const dialogElement = this.el.nativeElement.querySelector('.p-dialog');
3847
+ const dialogElement = document.querySelector('.p-confirm-dialog');
3779
3848
  if (dialogElement) {
3780
- this.renderer.setStyle(dialogElement, 'width', this.dialogConfig.width || '400px');
3849
+ this.renderer.addClass(dialogElement, 'pt-dialog-overlay');
3850
+ this.renderer.removeClass(dialogElement, 'pt-dialog-danger');
3851
+ this.renderer.removeClass(dialogElement, 'pt-dialog-warning');
3852
+ this.renderer.removeClass(dialogElement, 'pt-dialog-success');
3853
+ this.renderer.removeClass(dialogElement, 'pt-dialog-info');
3854
+ const severityClass = this.getSeverityClass();
3855
+ this.renderer.addClass(dialogElement, severityClass);
3856
+ this.renderer.setStyle(dialogElement, 'width', this.dialogConfig.width || '720px');
3781
3857
  this.renderer.setStyle(dialogElement, 'height', this.dialogConfig.height || 'auto');
3782
3858
  }
3783
3859
  }, 0);
3784
3860
  }
3785
- getButtonStyle(buttonConfig, isConfirm = false) {
3786
- let styleClass = buttonConfig?.styleClass ?? 'p-button-sm';
3787
- // ✅ Apply width dynamically if provided, otherwise default to 100%
3788
- const buttonWidth = buttonConfig?.width ?? '100%';
3789
- // ✅ Set default severity: SUCCESS for confirm, SECONDARY for cancel
3790
- const defaultSeverity = isConfirm ? SeverityEnum.DANGER : SeverityEnum.INFO;
3791
- const severity = buttonConfig?.severity ?? defaultSeverity;
3792
- // ✅ Apply severity-based styles only if no custom background color is set
3793
- if (!buttonConfig?.backgroundColor) {
3794
- switch (severity) {
3795
- case SeverityEnum.WARNING:
3796
- styleClass += ' p-button-warning';
3797
- break;
3798
- case SeverityEnum.DANGER:
3799
- styleClass += ' p-button-danger';
3800
- break;
3801
- case SeverityEnum.SUCCESS:
3802
- styleClass += ' p-button-success';
3803
- break;
3804
- case SeverityEnum.INFO:
3805
- default:
3806
- styleClass += ' p-button-secondary';
3807
- break;
3808
- }
3809
- }
3810
- return `${styleClass.trim()} width-${buttonWidth.replace('%', '')}`;
3811
- }
3861
+ // ── header / icon / content helpers ───────────────────────────────
3812
3862
  getDialogHeaderText() {
3813
3863
  const header = this.dialogConfig.header;
3814
3864
  const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
@@ -3821,88 +3871,85 @@ class PTDialogComponent {
3821
3871
  styleHeader !== null &&
3822
3872
  'text' in styleHeader
3823
3873
  ? styleHeader.text
3824
- : 'Confirmation'; // ✅ Default value
3874
+ : 'Confirmation';
3825
3875
  }
3826
3876
  getDialogHeaderStyle() {
3827
3877
  const header = this.dialogConfig.header;
3828
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3829
- const styleHeader = DIALOG_STYLES[dialogStyle]?.header;
3830
- return typeof header === 'object' && header !== null
3831
- ? {
3832
- color: header.color ||
3833
- (typeof styleHeader === 'object' ? styleHeader?.color : '#333'),
3834
- fontSize: header.fontSize || '25px',
3835
- }
3836
- : {
3837
- color: typeof styleHeader === 'object' ? styleHeader?.color : '#333',
3838
- fontSize: '25px',
3839
- };
3878
+ const { header: color } = this.getSeverityColors();
3879
+ const fontSize = typeof header === 'object' && header !== null && header.fontSize
3880
+ ? header.fontSize
3881
+ : '20px';
3882
+ return {
3883
+ color,
3884
+ fontSize,
3885
+ fontWeight: 700,
3886
+ };
3840
3887
  }
3841
3888
  getDialogIconClass() {
3842
3889
  const header = this.dialogConfig.header;
3843
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO; // ✅ Ensure dialogStyle is always defined
3844
- const styleHeader = DIALOG_STYLES[dialogStyle]?.header; // ✅ Store the style header separately
3845
- // ✅ Ensure header.icon exists and is an object before accessing .code
3890
+ const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3891
+ const styleHeader = DIALOG_STYLES[dialogStyle]?.header;
3846
3892
  const icon = typeof header === 'object' && header !== null && 'icon' in header
3847
3893
  ? header.icon
3848
3894
  : typeof styleHeader === 'object' && 'icon' in styleHeader
3849
3895
  ? styleHeader.icon
3850
3896
  : undefined;
3851
- // ✅ If `icon` is an object, extract `.code`, otherwise return as string or default value
3852
3897
  return typeof icon === 'string'
3853
3898
  ? icon
3854
3899
  : icon?.code || 'pi pi-exclamation-circle';
3855
3900
  }
3856
3901
  getDialogIconStyle() {
3857
3902
  const header = this.dialogConfig.header;
3858
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3859
- const styleHeader = DIALOG_STYLES[dialogStyle]?.header;
3903
+ const { header: defaultColor } = this.getSeverityColors();
3860
3904
  const icon = typeof header === 'object' && header !== null && 'icon' in header
3861
3905
  ? header.icon
3862
3906
  : undefined;
3863
3907
  return {
3864
- color: icon?.color ||
3865
- (typeof styleHeader === 'object' ? styleHeader?.color : '#f39c12'),
3866
- fontSize: icon?.fontSize || '1.5rem',
3867
- backgroundColor: icon?.backgroundColor || 'transparent',
3868
- borderRadius: icon?.shape === 'circular' ? '50%' : '4px',
3869
- padding: '5px',
3908
+ color: icon?.color || defaultColor,
3909
+ fontSize: icon?.fontSize || '2.2rem',
3870
3910
  };
3871
3911
  }
3912
+ /**
3913
+ * No default text anymore.
3914
+ * - If dialogConfig.content is a string, we return it.
3915
+ * - If it is an object with text, we use that.
3916
+ * - Otherwise we return '' (empty) so the body is blank.
3917
+ */
3872
3918
  getDialogContentText() {
3873
3919
  const content = this.dialogConfig.content;
3874
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3875
- const styleContent = DIALOG_STYLES[dialogStyle]?.content;
3876
- return typeof content === 'string'
3877
- ? content
3878
- : content?.text ||
3879
- (typeof styleContent === 'object'
3880
- ? styleContent?.text
3881
- : 'Are you sure?');
3920
+ if (typeof content === 'string') {
3921
+ return content;
3922
+ }
3923
+ if (content && typeof content === 'object' && 'text' in content) {
3924
+ return content.text ?? '';
3925
+ }
3926
+ return '';
3882
3927
  }
3883
3928
  getDialogContentStyle() {
3884
3929
  const content = this.dialogConfig.content;
3885
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3886
- const styleContent = DIALOG_STYLES[dialogStyle]?.content;
3887
- return typeof content === 'object' && content !== null
3888
- ? {
3889
- color: content.color ||
3890
- (typeof styleContent === 'object' ? styleContent?.color : '#333'),
3891
- fontSize: content.fontSize || '20px',
3892
- textAlign: content.position || 'left',
3930
+ const { message } = this.getSeverityColors();
3931
+ let fontSize = '18px';
3932
+ let textAlign;
3933
+ if (typeof content === 'object' && content !== null) {
3934
+ if (content.fontSize) {
3935
+ fontSize = content.fontSize;
3893
3936
  }
3894
- : {
3895
- color: typeof styleContent === 'object' ? styleContent?.color : '#333',
3896
- fontSize: '20px',
3897
- textAlign: 'left',
3898
- };
3937
+ if (content.position) {
3938
+ textAlign = content.position;
3939
+ }
3940
+ }
3941
+ return {
3942
+ color: message,
3943
+ fontSize,
3944
+ ...(textAlign ? { textAlign } : {}),
3945
+ };
3899
3946
  }
3900
3947
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogComponent, deps: [{ token: i1$1.ConfirmationService }, { token: i1$1.MessageService }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
3901
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTDialogComponent, selector: "pt-dialog", inputs: { dialogConfig: "dialogConfig" }, outputs: { confirm: "confirm", cancel: "cancel" }, providers: [ConfirmationService, MessageService], usesOnChanges: true, ngImport: i0, template: "<div class=\"pt-dialog\">\n <p-confirmDialog>\n <!-- Header with Icon and Title aligned horizontally -->\n <ng-template pTemplate=\"header\">\n <div class=\"popup-header bordered-section\">\n <i [class]=\"getDialogIconClass()\" [ngStyle]=\"getDialogIconStyle()\"></i>\n <span class=\"popup-title\" [ngStyle]=\"getDialogHeaderStyle()\">\n {{ getDialogHeaderText() }}\n </span>\n </div>\n </ng-template>\n\n <!-- Message Content with Divider -->\n <ng-template pTemplate=\"message\" let-message>\n <div\n class=\"popup-content bordered-section\"\n [ngStyle]=\"getDialogContentStyle()\"\n >\n <p>{{ getDialogContentText() }}</p>\n </div>\n </ng-template>\n </p-confirmDialog>\n</div>\n", styles: ["::ng-deep .pt-dialog .p-dialog .p-dialog-header{padding-bottom:0}::ng-deep .pt-dialog .p-dialog .p-dialog-content{padding:0}::ng-deep .pt-dialog .full-width-button{width:100%;display:block;text-align:center}::ng-deep .pt-dialog .p-dialog-footer{display:flex;justify-content:center;gap:10px;width:100%;padding:10px}::ng-deep .pt-dialog .p-confirm-dialog-accept,::ng-deep .pt-dialog .p-confirm-dialog-reject{flex:1;max-width:50%;text-align:center;display:flex;justify-content:center;align-items:center;height:40px}::ng-deep .pt-dialog .p-confirm-dialog-accept i,::ng-deep .pt-dialog .p-confirm-dialog-reject i{margin-right:5px}::ng-deep .pt-dialog .p-confirm-dialog-accept .p-button-label,::ng-deep .pt-dialog .p-confirm-dialog-reject .p-button-label{font-weight:700;flex-grow:1;text-align:center}.pt-dialog .popup-header{display:flex;align-items:center;gap:10px;font-size:1.2rem;font-weight:700;padding-bottom:10px;width:100%}.pt-dialog .popup-title{color:#333;font-size:1.2rem}.pt-dialog .bordered-section{width:100%;border-bottom:1px solid rgba(0,0,0,.2);padding-bottom:10px;margin-bottom:10px}.pt-dialog .popup-content{display:flex;justify-content:center;text-align:center;padding:15px;width:100%}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i3$7.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }] }); }
3948
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTDialogComponent, selector: "pt-dialog", inputs: { dialogConfig: "dialogConfig" }, outputs: { confirm: "confirm", cancel: "cancel" }, providers: [ConfirmationService, MessageService], usesOnChanges: true, ngImport: i0, template: "<div class=\"pt-dialog\">\n <p-confirmDialog #cd>\n <ng-template pTemplate=\"header\"></ng-template>\n\n <ng-template pTemplate=\"message\">\n <div class=\"pt-dialog-card\">\n <div class=\"pt-dialog-card-top\">\n <div class=\"pt-dialog-icon-wrapper\">\n <i\n class=\"pt-dialog-icon\"\n [class]=\"getDialogIconClass()\"\n [ngStyle]=\"getDialogIconStyle()\"\n ></i>\n </div>\n\n <div class=\"pt-dialog-text-wrapper\">\n <div class=\"pt-dialog-title\" [ngStyle]=\"getDialogHeaderStyle()\">\n {{ getDialogHeaderText() }}\n </div>\n\n <div class=\"pt-dialog-message\" [ngStyle]=\"getDialogContentStyle()\">\n {{ getDialogContentText() }}\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"pt-dialog-footer-buttons\">\n <pt-button\n *ngIf=\"dialogConfig.cancelButtonConfig\"\n [buttonConfig]=\"cancelButtonModel\"\n (click)=\"cd.reject()\"\n ></pt-button>\n\n <pt-button\n *ngIf=\"dialogConfig.confirmButtonConfig\"\n [buttonConfig]=\"confirmButtonModel\"\n (click)=\"cd.accept()\"\n ></pt-button>\n </div>\n </ng-template>\n </p-confirmDialog>\n</div>\n", styles: ["::ng-deep .p-confirm-dialog.pt-dialog-overlay{border-radius:18px;overflow:hidden;box-shadow:0 20px 45px #0f172a59}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-header{display:none!important;padding:0!important;border:0!important}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px}.pt-dialog-card{border-radius:18px 18px 0 0;overflow:hidden}.pt-dialog-card-top{padding:28px 40px;display:flex;align-items:flex-start}::ng-deep .p-confirm-dialog.pt-dialog-danger .pt-dialog-card{background-color:#fde4e4}::ng-deep .p-confirm-dialog.pt-dialog-warning .pt-dialog-card{background-color:#fff4d1}::ng-deep .p-confirm-dialog.pt-dialog-success .pt-dialog-card{background-color:#dcfce7}::ng-deep .p-confirm-dialog.pt-dialog-info .pt-dialog-card{background-color:#e0f2fe}.pt-dialog-icon-wrapper{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-right:18px;box-sizing:border-box}.pt-dialog-icon{font-size:30px;line-height:1;color:#b91c1c}.pt-dialog-text-wrapper{flex:1}.pt-dialog-title{font-size:22px;font-weight:700;margin-bottom:8px;color:#b91c1c}.pt-dialog-message{font-size:18px;line-height:1.5;color:#4b5563}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-footer{background:#fff;border-top:1px solid rgba(148,163,184,.25);padding:16px 32px 22px}.pt-dialog-footer-buttons{display:flex;justify-content:center;gap:16px}::ng-deep .p-confirm-dialog .p-dialog-footer .p-button{border-radius:9999px;padding:.75rem 1.8rem;font-weight:600}::ng-deep .p-confirm-dialog .p-dialog-footer .p-button i.pi{margin-right:.5rem}::ng-deep .p-confirm-dialog.pt-dialog-danger .p-dialog-footer .p-button{background:#fff!important;border-color:#dc2626!important;color:#dc2626!important}::ng-deep .p-confirm-dialog.pt-dialog-warning .p-dialog-footer .p-button{background:#fff!important;border-color:#d97706!important;color:#b45309!important}::ng-deep .p-confirm-dialog.pt-dialog-success .p-dialog-footer .p-button{background:#fff!important;border-color:#16a34a!important;color:#15803d!important}::ng-deep .p-confirm-dialog.pt-dialog-info .p-dialog-footer .p-button{background:#fff!important;border-color:#2563eb!important;color:#2563eb!important}::ng-deep .p-confirm-dialog.pt-dialog-info .p-dialog-footer .p-button:hover{background:#eff6ff!important}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px;display:block}.pt-dialog-card{border-radius:18px 18px 0 0;overflow:hidden;width:100%}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: PTButtonComponent, selector: "pt-button", inputs: ["buttonConfig"] }, { kind: "component", type: i4$2.ConfirmDialog, selector: "p-confirmDialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "visible", "position"], outputs: ["onHide"] }] }); }
3902
3949
  }
3903
3950
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogComponent, decorators: [{
3904
3951
  type: Component,
3905
- args: [{ selector: 'pt-dialog', providers: [ConfirmationService, MessageService], template: "<div class=\"pt-dialog\">\n <p-confirmDialog>\n <!-- Header with Icon and Title aligned horizontally -->\n <ng-template pTemplate=\"header\">\n <div class=\"popup-header bordered-section\">\n <i [class]=\"getDialogIconClass()\" [ngStyle]=\"getDialogIconStyle()\"></i>\n <span class=\"popup-title\" [ngStyle]=\"getDialogHeaderStyle()\">\n {{ getDialogHeaderText() }}\n </span>\n </div>\n </ng-template>\n\n <!-- Message Content with Divider -->\n <ng-template pTemplate=\"message\" let-message>\n <div\n class=\"popup-content bordered-section\"\n [ngStyle]=\"getDialogContentStyle()\"\n >\n <p>{{ getDialogContentText() }}</p>\n </div>\n </ng-template>\n </p-confirmDialog>\n</div>\n", styles: ["::ng-deep .pt-dialog .p-dialog .p-dialog-header{padding-bottom:0}::ng-deep .pt-dialog .p-dialog .p-dialog-content{padding:0}::ng-deep .pt-dialog .full-width-button{width:100%;display:block;text-align:center}::ng-deep .pt-dialog .p-dialog-footer{display:flex;justify-content:center;gap:10px;width:100%;padding:10px}::ng-deep .pt-dialog .p-confirm-dialog-accept,::ng-deep .pt-dialog .p-confirm-dialog-reject{flex:1;max-width:50%;text-align:center;display:flex;justify-content:center;align-items:center;height:40px}::ng-deep .pt-dialog .p-confirm-dialog-accept i,::ng-deep .pt-dialog .p-confirm-dialog-reject i{margin-right:5px}::ng-deep .pt-dialog .p-confirm-dialog-accept .p-button-label,::ng-deep .pt-dialog .p-confirm-dialog-reject .p-button-label{font-weight:700;flex-grow:1;text-align:center}.pt-dialog .popup-header{display:flex;align-items:center;gap:10px;font-size:1.2rem;font-weight:700;padding-bottom:10px;width:100%}.pt-dialog .popup-title{color:#333;font-size:1.2rem}.pt-dialog .bordered-section{width:100%;border-bottom:1px solid rgba(0,0,0,.2);padding-bottom:10px;margin-bottom:10px}.pt-dialog .popup-content{display:flex;justify-content:center;text-align:center;padding:15px;width:100%}\n"] }]
3952
+ args: [{ selector: 'pt-dialog', providers: [ConfirmationService, MessageService], template: "<div class=\"pt-dialog\">\n <p-confirmDialog #cd>\n <ng-template pTemplate=\"header\"></ng-template>\n\n <ng-template pTemplate=\"message\">\n <div class=\"pt-dialog-card\">\n <div class=\"pt-dialog-card-top\">\n <div class=\"pt-dialog-icon-wrapper\">\n <i\n class=\"pt-dialog-icon\"\n [class]=\"getDialogIconClass()\"\n [ngStyle]=\"getDialogIconStyle()\"\n ></i>\n </div>\n\n <div class=\"pt-dialog-text-wrapper\">\n <div class=\"pt-dialog-title\" [ngStyle]=\"getDialogHeaderStyle()\">\n {{ getDialogHeaderText() }}\n </div>\n\n <div class=\"pt-dialog-message\" [ngStyle]=\"getDialogContentStyle()\">\n {{ getDialogContentText() }}\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"pt-dialog-footer-buttons\">\n <pt-button\n *ngIf=\"dialogConfig.cancelButtonConfig\"\n [buttonConfig]=\"cancelButtonModel\"\n (click)=\"cd.reject()\"\n ></pt-button>\n\n <pt-button\n *ngIf=\"dialogConfig.confirmButtonConfig\"\n [buttonConfig]=\"confirmButtonModel\"\n (click)=\"cd.accept()\"\n ></pt-button>\n </div>\n </ng-template>\n </p-confirmDialog>\n</div>\n", styles: ["::ng-deep .p-confirm-dialog.pt-dialog-overlay{border-radius:18px;overflow:hidden;box-shadow:0 20px 45px #0f172a59}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-header{display:none!important;padding:0!important;border:0!important}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px}.pt-dialog-card{border-radius:18px 18px 0 0;overflow:hidden}.pt-dialog-card-top{padding:28px 40px;display:flex;align-items:flex-start}::ng-deep .p-confirm-dialog.pt-dialog-danger .pt-dialog-card{background-color:#fde4e4}::ng-deep .p-confirm-dialog.pt-dialog-warning .pt-dialog-card{background-color:#fff4d1}::ng-deep .p-confirm-dialog.pt-dialog-success .pt-dialog-card{background-color:#dcfce7}::ng-deep .p-confirm-dialog.pt-dialog-info .pt-dialog-card{background-color:#e0f2fe}.pt-dialog-icon-wrapper{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-right:18px;box-sizing:border-box}.pt-dialog-icon{font-size:30px;line-height:1;color:#b91c1c}.pt-dialog-text-wrapper{flex:1}.pt-dialog-title{font-size:22px;font-weight:700;margin-bottom:8px;color:#b91c1c}.pt-dialog-message{font-size:18px;line-height:1.5;color:#4b5563}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-footer{background:#fff;border-top:1px solid rgba(148,163,184,.25);padding:16px 32px 22px}.pt-dialog-footer-buttons{display:flex;justify-content:center;gap:16px}::ng-deep .p-confirm-dialog .p-dialog-footer .p-button{border-radius:9999px;padding:.75rem 1.8rem;font-weight:600}::ng-deep .p-confirm-dialog .p-dialog-footer .p-button i.pi{margin-right:.5rem}::ng-deep .p-confirm-dialog.pt-dialog-danger .p-dialog-footer .p-button{background:#fff!important;border-color:#dc2626!important;color:#dc2626!important}::ng-deep .p-confirm-dialog.pt-dialog-warning .p-dialog-footer .p-button{background:#fff!important;border-color:#d97706!important;color:#b45309!important}::ng-deep .p-confirm-dialog.pt-dialog-success .p-dialog-footer .p-button{background:#fff!important;border-color:#16a34a!important;color:#15803d!important}::ng-deep .p-confirm-dialog.pt-dialog-info .p-dialog-footer .p-button{background:#fff!important;border-color:#2563eb!important;color:#2563eb!important}::ng-deep .p-confirm-dialog.pt-dialog-info .p-dialog-footer .p-button:hover{background:#eff6ff!important}::ng-deep .p-confirm-dialog.pt-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px;display:block}.pt-dialog-card{border-radius:18px 18px 0 0;overflow:hidden;width:100%}\n"] }]
3906
3953
  }], ctorParameters: () => [{ type: i1$1.ConfirmationService }, { type: i1$1.MessageService }, { type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { dialogConfig: [{
3907
3954
  type: Input
3908
3955
  }], confirm: [{