ng-prime-tools 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +3 -3
  2. package/esm2022/lib/enums/form-input-type.enum.mjs +2 -1
  3. package/esm2022/lib/enums/input-validation.enum.mjs +2 -1
  4. package/esm2022/lib/models/button.model.mjs +1 -1
  5. package/esm2022/lib/ng-prime-tools.module.mjs +9 -5
  6. package/esm2022/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.mjs +109 -95
  7. package/esm2022/lib/pt-button/pt-button.component.mjs +44 -16
  8. package/esm2022/lib/pt-confirm-dialog/index.mjs +2 -0
  9. package/esm2022/lib/pt-confirm-dialog/pt-confirm-dialog.component.mjs +285 -0
  10. package/esm2022/lib/pt-confirm-dialog/pt-confirm-dialog.module.mjs +21 -0
  11. package/esm2022/lib/pt-confirm-dialog/public-api.mjs +3 -0
  12. package/esm2022/lib/pt-dialog/pt-dialog.component.mjs +96 -233
  13. package/esm2022/lib/pt-dialog/pt-dialog.module.mjs +5 -7
  14. package/esm2022/lib/pt-form-builder/pt-dynamic-form-field/pt-dynamic-form-field.component.mjs +3 -3
  15. package/esm2022/lib/pt-form-builder/pt-form-builder.component.mjs +67 -4
  16. package/esm2022/public-api.mjs +2 -1
  17. package/fesm2022/ng-prime-tools.mjs +522 -255
  18. package/fesm2022/ng-prime-tools.mjs.map +1 -1
  19. package/lib/enums/form-input-type.enum.d.ts +1 -0
  20. package/lib/enums/form-input-type.enum.d.ts.map +1 -1
  21. package/lib/enums/input-validation.enum.d.ts +2 -1
  22. package/lib/enums/input-validation.enum.d.ts.map +1 -1
  23. package/lib/models/button.model.d.ts +1 -0
  24. package/lib/models/button.model.d.ts.map +1 -1
  25. package/lib/ng-prime-tools.module.d.ts +3 -2
  26. package/lib/ng-prime-tools.module.d.ts.map +1 -1
  27. package/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.d.ts +43 -13
  28. package/lib/pt-advanced-prime-table/pt-advanced-prime-table.component.d.ts.map +1 -1
  29. package/lib/pt-button/pt-button.component.d.ts +7 -1
  30. package/lib/pt-button/pt-button.component.d.ts.map +1 -1
  31. package/lib/pt-confirm-dialog/index.d.ts +2 -0
  32. package/lib/pt-confirm-dialog/index.d.ts.map +1 -0
  33. package/lib/pt-confirm-dialog/pt-confirm-dialog.component.d.ts +44 -0
  34. package/lib/pt-confirm-dialog/pt-confirm-dialog.component.d.ts.map +1 -0
  35. package/lib/pt-confirm-dialog/pt-confirm-dialog.module.d.ts +12 -0
  36. package/lib/pt-confirm-dialog/pt-confirm-dialog.module.d.ts.map +1 -0
  37. package/lib/pt-confirm-dialog/public-api.d.ts +3 -0
  38. package/lib/pt-confirm-dialog/public-api.d.ts.map +1 -0
  39. package/lib/pt-dialog/pt-dialog.component.d.ts +47 -23
  40. package/lib/pt-dialog/pt-dialog.component.d.ts.map +1 -1
  41. package/lib/pt-dialog/pt-dialog.module.d.ts +1 -3
  42. package/lib/pt-dialog/pt-dialog.module.d.ts.map +1 -1
  43. package/lib/pt-form-builder/pt-form-builder.component.d.ts +5 -1
  44. package/lib/pt-form-builder/pt-form-builder.component.d.ts.map +1 -1
  45. package/lib/pt-metric-panel/pt-metric-panel.component.d.ts +1 -1
  46. package/package.json +1 -1
  47. package/public-api.d.ts +1 -0
  48. package/public-api.d.ts.map +1 -1
@@ -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,8 +47,9 @@ 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
+ import * as i2$3 from 'primeng/dialog';
52
53
  import { DialogModule } from 'primeng/dialog';
53
54
  import * as i2$2 from 'primeng/toast';
54
55
  import { ToastModule } from 'primeng/toast';
@@ -172,6 +173,11 @@ class PTAdvancedPrimeTableComponent {
172
173
  this.hasExportPDF = false;
173
174
  this.hasColumnFilter = false;
174
175
  this.isPaginated = false;
176
+ /**
177
+ * Actions configuration.
178
+ * - code 'edit' / 'delete' garde l'ancien comportement.
179
+ * - tout autre code = action custom, gérée uniquement dans le parent.
180
+ */
175
181
  this.actions = [];
176
182
  this.isSortable = false;
177
183
  this.loading = false;
@@ -181,36 +187,41 @@ class PTAdvancedPrimeTableComponent {
181
187
  this.search = new EventEmitter();
182
188
  this.exportExcelEvent = new EventEmitter();
183
189
  this.exportPdfEvent = new EventEmitter();
190
+ this.pageChange = new EventEmitter();
184
191
  this.TableTypeEnum = TableTypeEnum;
185
192
  this.searchValue = '';
186
193
  this.filters = {};
187
194
  this.validCurrencyCodes = ['USD', 'EUR', 'MAD'];
188
195
  this.iconWidth = 77;
189
196
  // Component state properties
197
+ this.rows = 0;
198
+ this.hasGroupedColumns = false;
199
+ // Flags / handlers for built-in edit/delete support
190
200
  this.isDelete = false;
191
201
  this.isEdit = false;
192
- this.rows = 0;
202
+ this.Delete = () => { };
203
+ this.initEditableRow = () => { };
204
+ this.saveEditableRow = () => { };
205
+ this.cancelEditableRow = () => { };
206
+ // Extra custom actions (codes other than 'edit'/'delete')
207
+ this.customActions = [];
193
208
  // Data management properties
194
209
  this.dataMap = new Map();
195
210
  this.map = new Map();
196
211
  this.optionEntries = new Map();
197
212
  this.optionValues = [];
198
213
  this.globalFilterFields = [];
199
- // CRUD operation handlers
200
- this.Delete = () => { };
201
- this.initEditableRow = () => { };
202
- this.saveEditableRow = () => { };
203
- this.cancelEditableRow = () => { };
204
- this.hasGroupedColumns = false;
205
214
  }
206
215
  ngOnInit() {
216
+ console.log('PTAdvancedPrimeTable columns:', this.columns);
217
+ console.log('PTAdvancedPrimeTable totalRecords input:', this.totalRecords);
207
218
  this.hasGroupedColumns = this.columns.some((col) => col.children && col.children.length > 0);
208
219
  this.globalFilterFields = this.columns
209
220
  .filter((col) => col.code !== undefined && col.isFilter !== false)
210
221
  .map((col) => col.code);
211
222
  this.initializePagination();
212
223
  this.initializeActions();
213
- // Set default value for isSortable
224
+ // Set default value for isSortable / isEditable + widths
214
225
  this.columns.forEach((col) => {
215
226
  if (col.type === TableTypeEnum.ACTION) {
216
227
  col.isEditable = false;
@@ -234,93 +245,137 @@ class PTAdvancedPrimeTableComponent {
234
245
  }
235
246
  });
236
247
  }
248
+ // ---------- ACTIONS INITIALIZATION ----------
249
+ initializeActions() {
250
+ // reset state
251
+ this.isDelete = false;
252
+ this.isEdit = false;
253
+ this.Delete = () => { };
254
+ this.initEditableRow = () => { };
255
+ this.saveEditableRow = () => { };
256
+ this.cancelEditableRow = () => { };
257
+ this.customActions = [];
258
+ if (!this.actions || this.actions.length === 0) {
259
+ return;
260
+ }
261
+ this.actions.forEach((action) => {
262
+ switch (action.code) {
263
+ case 'delete':
264
+ this.isDelete = true;
265
+ this.Delete = (value) => action.action(value);
266
+ break;
267
+ case 'edit':
268
+ this.initializeEditActions(action);
269
+ break;
270
+ default:
271
+ // any other code is a pure custom action
272
+ this.customActions.push(action);
273
+ break;
274
+ }
275
+ });
276
+ }
277
+ initializeEditActions(action) {
278
+ this.isEdit = true;
279
+ this.initEditableRow = (data) => action.action.init(data);
280
+ this.saveEditableRow = (data) => {
281
+ const record = this.map.get(data.id);
282
+ action.action.save(data, record);
283
+ this.dataMap.clear();
284
+ };
285
+ this.cancelEditableRow = (item) => console.log(item);
286
+ }
287
+ /** Called when a custom action button is clicked */
288
+ onCustomActionClick(action, row) {
289
+ if (action && typeof action.action === 'function') {
290
+ action.action(row);
291
+ }
292
+ }
237
293
  // Initialize filters for composed columns
238
294
  initializeComposedFilters(col) {
239
295
  col.composedNames?.forEach((composedName) => {
240
- this.globalFilterFields.push(col.code + '.' + composedName);
296
+ const code = col.code || '';
297
+ this.globalFilterFields.push(code + '.' + composedName);
241
298
  this.filters[composedName] = {
242
299
  options: col.filterOptions,
243
300
  value: [],
244
301
  label: 'Filter by ' + composedName,
245
- placeholder: 'Select options for ' + composedName,
302
+ placeholder: 'Select option',
246
303
  };
247
304
  });
248
305
  }
249
306
  // Get the column type for composed fields (STRING, IMAGE, etc.)
250
307
  getComposedFieldType(col, composedName) {
251
- // Ensure that col.composedNames and col.composedTypes are valid arrays
252
308
  if (col.composedNames && col.composedTypes) {
253
309
  const index = col.composedNames.indexOf(composedName);
254
- // Check if index is a valid number (not -1) and within bounds of composedTypes array
255
310
  if (index >= 0 && index < col.composedTypes.length) {
256
- return col.composedTypes[index]; // Safe access of composedTypes array
311
+ return col.composedTypes[index];
257
312
  }
258
313
  }
259
- return undefined; // Return undefined if no valid index is found or composedNames/composedTypes are not valid
314
+ return undefined;
260
315
  }
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
316
+ onComposedFilterChange(col, composedName, selectedValues) {
265
317
  this.filters[composedName].value = selectedValues;
266
- // Emit the filter event to notify the parent component (if needed)
267
318
  this.filter.emit(this.filters);
268
- // Get the filter value (joining array into a string)
269
319
  const filterValue = selectedValues.join(',');
270
- console.log('Filter Values to be Applied:', filterValue);
271
- // Apply global filter using PrimeNG's filterGlobal method
320
+ let matchResults = [];
321
+ const colCode = col.code;
322
+ selectedValues.forEach((value) => {
323
+ const matches = this.dt.value.filter((row) => {
324
+ return row[colCode]?.[composedName]
325
+ ?.toString()
326
+ .toLowerCase()
327
+ .includes(value.toLowerCase());
328
+ });
329
+ matchResults = [...matchResults, ...matches];
330
+ });
331
+ matchResults = Array.from(new Set(matchResults));
332
+ this.dt.filteredValue = matchResults;
272
333
  this.dt.filterGlobal(filterValue, 'contains');
273
334
  }
335
+ // ⛔ Don't override totalRecords here – we are in server-side mode
274
336
  onFilter(event) {
275
- this.totalRecords = event.filteredValue?.length || 0;
337
+ this.filter.emit(event);
338
+ // this.totalRecords = event.filteredValue?.length || 0; // removed
339
+ }
340
+ onPageChange(event) {
341
+ const page = event.page ?? Math.floor((event.first || 0) / event.rows);
342
+ const rows = event.rows;
343
+ this.rows = rows;
344
+ this.pageChange.emit({ page, rows });
276
345
  }
277
346
  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
347
  const filterValue = event ? new Date(event) : null;
283
- console.log('filterValue : ' + filterValue);
284
- // If the filterValue is empty, do not trigger filterCallback
285
348
  if (!filterValue) {
286
349
  return;
287
350
  }
288
- // Manually trigger the filterCallback after updating the value (passing the string value)
289
351
  filterCallback(filterValue);
290
352
  const filterValueString = event ? this.formatDate(event) : '';
291
- // Call the onFilter event to update totalRecords
292
353
  this.onFilter({
293
354
  filteredValue: this.data.filter((item) => {
294
355
  const columnValue = item[columnCode];
295
- // If the column value is a string, use it as is for comparison
296
356
  if (columnValue) {
297
- // Convert the item value to a string (in the same format)
298
357
  const itemDateString = this.formatDate(new Date(columnValue));
299
- return itemDateString === filterValueString; // Compare the string dates
358
+ return itemDateString === filterValueString;
300
359
  }
301
360
  return false;
302
361
  }),
303
362
  });
304
363
  }
305
- // Filter logic for composed columns (to check against multi-select values)
306
364
  filterComposedData(item, composedName, value) {
307
365
  if (Array.isArray(value) && value.length > 0) {
308
366
  return value.some((filterValue) => item[composedName]?.toLowerCase().includes(filterValue.toLowerCase()));
309
367
  }
310
368
  return true;
311
369
  }
312
- // Function to calculate column width based on text in header and data
313
370
  calculateColumnWidth(col) {
314
371
  const calculatedWidth = calculateTextWidth(col, col.title);
315
372
  const totalWidth = calculatedWidth + this.iconWidth + 20;
316
373
  return `${totalWidth}px`;
317
374
  }
318
375
  getHeaderWidth(col) {
319
- // Remove 'px' from col.width and convert it to a number
320
- const widthWithoutPx = parseInt(col.width?.replace('px', '') || '0', 10);
321
- // Add 20 to the calculated width
376
+ const base = col.width ?? this.calculateColumnWidth(col);
377
+ const widthWithoutPx = parseInt(base.replace('px', '') || '0', 10);
322
378
  const headerWidth = widthWithoutPx + 20;
323
- // Return the new width in 'px'
324
379
  return `${headerWidth}px`;
325
380
  }
326
381
  clear(table) {
@@ -330,7 +385,6 @@ class PTAdvancedPrimeTableComponent {
330
385
  parseDate(dateString) {
331
386
  const parts = dateString.split('/');
332
387
  if (parts.length === 3) {
333
- // Assuming date format is DD/MM/YYYY
334
388
  const day = parseInt(parts[0], 10);
335
389
  const month = parseInt(parts[1], 10) - 1;
336
390
  const year = parseInt(parts[2], 10);
@@ -341,50 +395,21 @@ class PTAdvancedPrimeTableComponent {
341
395
  }
342
396
  initializePagination() {
343
397
  if (this.isPaginated) {
344
- // Check if rowsPerPage is undefined or an empty array
345
398
  if (!this.rowsPerPage || this.rowsPerPage.length === 0) {
346
399
  this.rowsPerPage = [20, 30, 40];
347
400
  }
348
401
  this.rows = this.rowsPerPage[0];
349
402
  }
350
403
  }
351
- initializeActions() {
352
- if (this.actions) {
353
- this.actions.forEach((action) => {
354
- switch (action.code) {
355
- case 'delete':
356
- this.isDelete = true;
357
- this.Delete = (value) => action.action(value);
358
- break;
359
- case 'edit':
360
- this.initializeEditActions(action);
361
- break;
362
- default:
363
- this.isDelete = false;
364
- this.isEdit = false;
365
- }
366
- });
367
- }
368
- }
369
- initializeEditActions(action) {
370
- this.isEdit = true;
371
- this.initEditableRow = (data) => action.action.init(data);
372
- this.saveEditableRow = (data) => {
373
- const record = this.map.get(data.id);
374
- action.action.save(data, record);
375
- this.dataMap.clear();
376
- };
377
- this.cancelEditableRow = (item) => console.log(item);
378
- }
379
404
  onChange(event, id, key) {
380
405
  const target = event.target;
381
406
  this.changeHandler(id, key, target.value);
382
407
  }
383
408
  changeHandler(id, key, value) {
384
- let column = this.columns.find((item) => item.code === key);
409
+ const column = this.columns.find((item) => item.code === key);
385
410
  if (!this.map.get(id)) {
386
411
  if (column?.type === TableTypeEnum.DATE) {
387
- let date = this.parseDate(value);
412
+ const date = this.parseDate(value);
388
413
  this.dataMap.set(key, date);
389
414
  }
390
415
  else {
@@ -393,9 +418,9 @@ class PTAdvancedPrimeTableComponent {
393
418
  this.map.set(id, new Map(this.dataMap));
394
419
  }
395
420
  else {
396
- let mapItem = this.map.get(id);
421
+ const mapItem = this.map.get(id);
397
422
  if (column?.type === TableTypeEnum.DATE) {
398
- let date = this.parseDate(value);
423
+ const date = this.parseDate(value);
399
424
  mapItem.set(key, date);
400
425
  }
401
426
  else {
@@ -422,13 +447,14 @@ class PTAdvancedPrimeTableComponent {
422
447
  return 'text';
423
448
  }
424
449
  }
425
- // State Check Methods
426
450
  isEditable(key) {
427
- let column = this.columns.find((item) => item.code === key);
451
+ if (!key)
452
+ return false;
453
+ const column = this.columns.find((item) => item.code === key);
428
454
  return column?.isEditable !== false;
429
455
  }
430
456
  isMultiSelect(key) {
431
- let column = this.columns.find((item) => item.code === key);
457
+ const column = this.columns.find((item) => item.code === key);
432
458
  if (column?.type === TableTypeEnum.MULTISELECT &&
433
459
  column.options &&
434
460
  column.code !== undefined) {
@@ -444,7 +470,6 @@ class PTAdvancedPrimeTableComponent {
444
470
  return (this.columns.find((item) => item.code === key)?.type ===
445
471
  TableTypeEnum.DATE);
446
472
  }
447
- // Utility Methods
448
473
  dateConverter(value) {
449
474
  return new Date(value).toLocaleDateString('en-US');
450
475
  }
@@ -461,14 +486,12 @@ class PTAdvancedPrimeTableComponent {
461
486
  filterGlobal(event) {
462
487
  const target = event.target;
463
488
  const value = target.value.toLowerCase();
464
- // Create a new filtered dataset
465
489
  const filteredData = this.data.filter((item) => {
466
490
  return this.globalFilterFields.some((field) => {
467
491
  const column = this.columns.find((col) => col.code === field);
468
492
  if (!column) {
469
493
  return false;
470
494
  }
471
- // Handle different column types
472
495
  if (column.type === TableTypeEnum.DATE) {
473
496
  const itemDate = this.formatDate(item[field]);
474
497
  return itemDate && itemDate.includes(value);
@@ -478,7 +501,6 @@ class PTAdvancedPrimeTableComponent {
478
501
  return (item[field] && item[field].toString().toLowerCase().includes(value));
479
502
  }
480
503
  else if (column.type === TableTypeEnum.COMPOSED) {
481
- // Handle composed type by searching for text in the composed cells
482
504
  return this.filterComposedColumn(item[field], value);
483
505
  }
484
506
  else {
@@ -486,14 +508,12 @@ class PTAdvancedPrimeTableComponent {
486
508
  }
487
509
  });
488
510
  });
489
- // Update the table's value
490
511
  this.dt.value = filteredData;
491
- // After filtering, update the totalRecords
492
- this.totalRecords = filteredData.length ?? 0;
512
+ // ne pas toucher à totalRecords en mode serveur
513
+ // this.totalRecords = filteredData.length ?? 0;
493
514
  }
494
515
  filterComposedColumn(composedData, value) {
495
516
  if (composedData) {
496
- // Iterate over composed keys and check if any key's value contains the search text
497
517
  return Object.keys(composedData).some((key) => {
498
518
  const cellValue = composedData[key];
499
519
  if (typeof cellValue === 'string') {
@@ -508,20 +528,17 @@ class PTAdvancedPrimeTableComponent {
508
528
  if (!date)
509
529
  return '';
510
530
  if (date instanceof Date) {
511
- // Handle Date object
512
531
  const day = date.getDate().toString().padStart(2, '0');
513
532
  const month = (date.getMonth() + 1).toString().padStart(2, '0');
514
533
  const year = date.getFullYear().toString();
515
534
  return `${day}/${month}/${year}`;
516
535
  }
517
536
  else if (typeof date === 'string') {
518
- // Handle string date
519
537
  const parts = date.split('/');
520
538
  if (parts.length === 3) {
521
539
  return `${parts[0]}/${parts[1]}/${parts[2]}`;
522
540
  }
523
541
  else {
524
- // Handle partial dates
525
542
  return date;
526
543
  }
527
544
  }
@@ -539,7 +556,6 @@ class PTAdvancedPrimeTableComponent {
539
556
  width: style.width || 'auto',
540
557
  height: style.height || 'auto',
541
558
  };
542
- // Fallback to empty string if margin, marginLeft, or marginRight are undefined
543
559
  if (style.margin) {
544
560
  imageStyle.margin = style.margin;
545
561
  }
@@ -572,15 +588,12 @@ class PTAdvancedPrimeTableComponent {
572
588
  formatNumber(value, decimalPlaces, thousandSeparator = 'comma', decimalSeparator = 'dot') {
573
589
  if (value === null || value === undefined || isNaN(value))
574
590
  return '';
575
- // Convert the number to a string with full precision if decimalPlaces is undefined
576
591
  let formattedNumber = decimalPlaces !== undefined
577
592
  ? value.toFixed(decimalPlaces)
578
593
  : value.toString();
579
- // Replace decimal separator (default is "dot")
580
594
  if (decimalSeparator === 'comma') {
581
595
  formattedNumber = formattedNumber.replace('.', ',');
582
596
  }
583
- // Apply thousand separator only if the number is >= 1000
584
597
  if (thousandSeparator && Math.abs(value) >= 1000) {
585
598
  const parts = formattedNumber.split(decimalSeparator === 'comma' ? ',' : '.');
586
599
  parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator === 'comma' ? ',' : ' ');
@@ -589,11 +602,11 @@ class PTAdvancedPrimeTableComponent {
589
602
  return formattedNumber;
590
603
  }
591
604
  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" }] }); }
605
+ 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 p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n (onPage)=\"onPageChange($event)\"\n >\n <!-- CAPTION -->\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\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\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 <!-- HEADER -->\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 <!-- COMPOSED FILTER -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\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 <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 TYPES -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- 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 <!-- 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 <!-- 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\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\n <!-- GROUPED HEADER -->\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\n <!-- CHILD HEADERS -->\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 ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\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 <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- show cell when:\n - ACTION column (no value needed)\n - OR normal col with value present -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.ACTION ||\n (col.code !== undefined && data[col.code!] !== undefined)\n \"\n >\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\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 <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.ACTION;\n else nonActionCell\n \"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\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\n <!-- built-in inline edit (old behaviour) -->\n <div *ngIf=\"isEdit\">\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\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- 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]=\"\n getImageStyle(\n col.composedStyles?.[composedName]\n )\n \"\n />\n </ng-container>\n\n <!-- 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]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else nonAmount\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\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\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 </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\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 <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 </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.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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
606
  }
594
607
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTAdvancedPrimeTableComponent, decorators: [{
595
608
  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"] }]
609
+ 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 p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onFilter)=\"onFilter($event)\"\n (onPage)=\"onPageChange($event)\"\n >\n <!-- CAPTION -->\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\n <div class=\"ml-auto\" *ngIf=\"hasSearchFilter\">\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 <!-- HEADER -->\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 <!-- COMPOSED FILTER -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type === TableTypeEnum.COMPOSED\"\n showClearButton=\"false\"\n showApplyButton=\"false\"\n >\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 <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 TYPES -->\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n *ngIf=\"col.type !== TableTypeEnum.COMPOSED\"\n hideOnClear=\"true\"\n >\n <!-- 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 <!-- 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 <!-- 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\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\n <!-- GROUPED HEADER -->\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\n <!-- CHILD HEADERS -->\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 ></th>\n </ng-container>\n </ng-container>\n </tr>\n </ng-template>\n\n <!-- EMPTY MESSAGE -->\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 <tr *ngIf=\"!loading\" [pEditableRow]=\"isEdit ? data : null\">\n <ng-container *ngFor=\"let col of columns\">\n <ng-container *ngIf=\"!col.children; else childColumns\">\n <!-- show cell when:\n - ACTION column (no value needed)\n - OR normal col with value present -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.ACTION ||\n (col.code !== undefined && data[col.code!] !== undefined)\n \"\n >\n <td\n *ngIf=\"\n isEditable(col.code!) && col.type !== TableTypeEnum.ACTION;\n else normalTD\n \"\n [style.width]=\"getHeaderWidth(col)\"\n >\n <!-- Editable input for NUMBER/DATE/STRING/MULTISELECT -->\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 <!-- ACTION column: built-in edit/delete + custom actions -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.ACTION;\n else nonActionCell\n \"\n >\n <div class=\"action-buttons-container\">\n <!-- built-in delete -->\n <button\n *ngIf=\"isDelete\"\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\n <!-- built-in inline edit (old behaviour) -->\n <div *ngIf=\"isEdit\">\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\n <!-- custom actions -->\n <button\n *ngFor=\"let act of customActions\"\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n </div>\n </ng-container>\n\n <!-- NON-ACTION cells -->\n <ng-template #nonActionCell>\n <!-- COMPOSED -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.COMPOSED;\n else nonComposed\n \"\n >\n <div class=\"composed-cell\">\n <ng-container\n *ngFor=\"\n let composedName of col.composedNames;\n let i = index\n \"\n >\n <!-- 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]=\"\n getImageStyle(\n col.composedStyles?.[composedName]\n )\n \"\n />\n </ng-container>\n\n <!-- 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]=\"\n getTitleStyle(\n col.composedStyles?.[composedName]\n )\n \"\n >\n {{ data[col.code!][composedName] }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-template #nonComposed>\n <!-- AMOUNT-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.AMOUNT;\n else nonAmount\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\n <ng-template #nonAmount>\n <!-- NUMBER-->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.NUMBER;\n else nonNumber\n \"\n >\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n </ng-container>\n\n <ng-template #nonNumber>\n <!-- DATE -->\n <ng-container\n *ngIf=\"\n col.type === TableTypeEnum.DATE;\n else normalTypes\n \"\n >\n {{ formatDate(data[col.code!]) }}\n </ng-container>\n\n <ng-template #normalTypes>\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 </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </ng-template>\n </td>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <!-- CHILD COLUMNS -->\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 <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 </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
610
  }], ctorParameters: () => [], propDecorators: { data: [{
598
611
  type: Input
599
612
  }], columns: [{
@@ -628,6 +641,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
628
641
  type: Output
629
642
  }], exportPdfEvent: [{
630
643
  type: Output
644
+ }], pageChange: [{
645
+ type: Output
631
646
  }], dt: [{
632
647
  type: ViewChild,
633
648
  args: ['dt', { static: false }]
@@ -818,6 +833,7 @@ var FormInputTypeEnum;
818
833
  (function (FormInputTypeEnum) {
819
834
  FormInputTypeEnum["DATE"] = "DATE";
820
835
  FormInputTypeEnum["TEXT"] = "TEXT";
836
+ FormInputTypeEnum["EMAIL"] = "EMAIL";
821
837
  FormInputTypeEnum["TEXTAREA"] = "TEXTAREA";
822
838
  FormInputTypeEnum["AMOUNT"] = "AMOUNT";
823
839
  FormInputTypeEnum["NUMBER"] = "NUMBER";
@@ -845,6 +861,7 @@ var InputValidationEnum;
845
861
  InputValidationEnum["ONLY_NUMBERS"] = "^[0-9]+$";
846
862
  InputValidationEnum["LETTERS_AND_NUMBERS"] = "^[A-Za-z0-9 ]+$";
847
863
  InputValidationEnum["PHONE_NUMBER"] = "^[0-9 ]+$";
864
+ InputValidationEnum["EMAIL"] = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[A-Za-z]{2,}$";
848
865
  })(InputValidationEnum || (InputValidationEnum = {}));
849
866
 
850
867
  var BadgeType;
@@ -1701,11 +1718,11 @@ class PTDynamicFormFieldComponent {
1701
1718
  return field;
1702
1719
  }
1703
1720
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDynamicFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1704
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTDynamicFormFieldComponent, selector: "pt-dynamic-form-field", inputs: { field: "field", form: "form", inputWidth: "inputWidth" }, ngImport: i0, template: "<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX &&\n field.type !== FormInputTypeEnum.SWITCH\n ? field.width || inputWidth\n : 'auto'\n }\"\n>\n <ng-container [ngSwitch]=\"field.type\">\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXT\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.NUMBER\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.AMOUNT\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n <pt-text-area-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXTAREA\"\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n <pt-date-input\n *ngSwitchCase=\"FormInputTypeEnum.DATE\"\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n <pt-multi-select\n *ngSwitchCase=\"FormInputTypeEnum.MULTISELECT\"\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n <pt-dropdown\n *ngSwitchCase=\"FormInputTypeEnum.SELECT\"\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n <pt-check-box-input\n *ngSwitchCase=\"FormInputTypeEnum.CHECKBOX\"\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n <pt-switch-input\n *ngSwitchCase=\"FormInputTypeEnum.SWITCH\"\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n </ng-container>\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PTCheckBoxInputComponent, selector: "pt-check-box-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDateInputComponent, selector: "pt-date-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTNumberInputComponent, selector: "pt-number-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTSwitchInputComponent, selector: "pt-switch-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextAreaInputComponent, selector: "pt-text-area-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextInputComponent, selector: "pt-text-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDropdownComponent, selector: "pt-dropdown", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTMultiSelectComponent, selector: "pt-multi-select", inputs: ["formGroup", "formField"] }] }); }
1721
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTDynamicFormFieldComponent, selector: "pt-dynamic-form-field", inputs: { field: "field", form: "form", inputWidth: "inputWidth" }, ngImport: i0, template: "<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX &&\n field.type !== FormInputTypeEnum.SWITCH\n ? field.width || inputWidth\n : 'auto'\n }\"\n>\n <ng-container [ngSwitch]=\"field.type\">\n <!-- TEXT -->\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXT\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n\n <!-- EMAIL (NEW) -->\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.EMAIL\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n\n <!-- NUMBER -->\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.NUMBER\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n\n <!-- AMOUNT -->\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.AMOUNT\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n\n <!-- TEXTAREA -->\n <pt-text-area-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXTAREA\"\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n\n <!-- DATE -->\n <pt-date-input\n *ngSwitchCase=\"FormInputTypeEnum.DATE\"\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n\n <!-- MULTISELECT -->\n <pt-multi-select\n *ngSwitchCase=\"FormInputTypeEnum.MULTISELECT\"\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n\n <!-- SELECT -->\n <pt-dropdown\n *ngSwitchCase=\"FormInputTypeEnum.SELECT\"\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n\n <!-- CHECKBOX -->\n <pt-check-box-input\n *ngSwitchCase=\"FormInputTypeEnum.CHECKBOX\"\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n\n <!-- SWITCH -->\n <pt-switch-input\n *ngSwitchCase=\"FormInputTypeEnum.SWITCH\"\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n </ng-container>\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PTCheckBoxInputComponent, selector: "pt-check-box-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDateInputComponent, selector: "pt-date-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTNumberInputComponent, selector: "pt-number-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTSwitchInputComponent, selector: "pt-switch-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextAreaInputComponent, selector: "pt-text-area-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextInputComponent, selector: "pt-text-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDropdownComponent, selector: "pt-dropdown", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTMultiSelectComponent, selector: "pt-multi-select", inputs: ["formGroup", "formField"] }] }); }
1705
1722
  }
1706
1723
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDynamicFormFieldComponent, decorators: [{
1707
1724
  type: Component,
1708
- args: [{ selector: 'pt-dynamic-form-field', template: "<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX &&\n field.type !== FormInputTypeEnum.SWITCH\n ? field.width || inputWidth\n : 'auto'\n }\"\n>\n <ng-container [ngSwitch]=\"field.type\">\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXT\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.NUMBER\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.AMOUNT\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n <pt-text-area-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXTAREA\"\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n <pt-date-input\n *ngSwitchCase=\"FormInputTypeEnum.DATE\"\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n <pt-multi-select\n *ngSwitchCase=\"FormInputTypeEnum.MULTISELECT\"\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n <pt-dropdown\n *ngSwitchCase=\"FormInputTypeEnum.SELECT\"\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n <pt-check-box-input\n *ngSwitchCase=\"FormInputTypeEnum.CHECKBOX\"\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n <pt-switch-input\n *ngSwitchCase=\"FormInputTypeEnum.SWITCH\"\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n </ng-container>\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"] }]
1725
+ args: [{ selector: 'pt-dynamic-form-field', template: "<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX &&\n field.type !== FormInputTypeEnum.SWITCH\n ? field.width || inputWidth\n : 'auto'\n }\"\n>\n <ng-container [ngSwitch]=\"field.type\">\n <!-- TEXT -->\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXT\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n\n <!-- EMAIL (NEW) -->\n <pt-text-input\n *ngSwitchCase=\"FormInputTypeEnum.EMAIL\"\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n\n <!-- NUMBER -->\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.NUMBER\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n\n <!-- AMOUNT -->\n <pt-number-input\n *ngSwitchCase=\"FormInputTypeEnum.AMOUNT\"\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n\n <!-- TEXTAREA -->\n <pt-text-area-input\n *ngSwitchCase=\"FormInputTypeEnum.TEXTAREA\"\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n\n <!-- DATE -->\n <pt-date-input\n *ngSwitchCase=\"FormInputTypeEnum.DATE\"\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n\n <!-- MULTISELECT -->\n <pt-multi-select\n *ngSwitchCase=\"FormInputTypeEnum.MULTISELECT\"\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n\n <!-- SELECT -->\n <pt-dropdown\n *ngSwitchCase=\"FormInputTypeEnum.SELECT\"\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n\n <!-- CHECKBOX -->\n <pt-check-box-input\n *ngSwitchCase=\"FormInputTypeEnum.CHECKBOX\"\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n\n <!-- SWITCH -->\n <pt-switch-input\n *ngSwitchCase=\"FormInputTypeEnum.SWITCH\"\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n </ng-container>\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"] }]
1709
1726
  }], propDecorators: { field: [{
1710
1727
  type: Input
1711
1728
  }], form: [{
@@ -1726,9 +1743,13 @@ class PTFormBuilderComponent {
1726
1743
  this.errorMessages = {
1727
1744
  en: {
1728
1745
  required: 'is required',
1746
+ email: 'is not a valid email address',
1747
+ pattern: 'is invalid',
1729
1748
  },
1730
1749
  fr: {
1731
1750
  required: 'est requis',
1751
+ email: "n'est pas une adresse e-mail valide",
1752
+ pattern: 'est invalide',
1732
1753
  },
1733
1754
  };
1734
1755
  this.form = this.fb.group({});
@@ -1738,18 +1759,77 @@ class PTFormBuilderComponent {
1738
1759
  }
1739
1760
  buildFormGroup(group) {
1740
1761
  group.fields?.forEach((field) => {
1741
- const validators = field.required ? [Validators.required] : [];
1762
+ const validators = this.buildValidators(field);
1742
1763
  this.form.addControl(field.name, this.fb.control(field.value, validators));
1743
1764
  });
1744
1765
  group.groups?.forEach((subGroup) => {
1745
1766
  this.buildFormGroup(subGroup);
1746
1767
  });
1747
1768
  }
1769
+ /**
1770
+ * Build validators depending on field configuration & type.
1771
+ */
1772
+ buildValidators(field) {
1773
+ const validators = [];
1774
+ const anyField = field;
1775
+ // --- Required ---
1776
+ if (field.required) {
1777
+ validators.push(Validators.required);
1778
+ }
1779
+ // --- Length constraints (for text / password / textarea / email) ---
1780
+ if (anyField.minLength) {
1781
+ validators.push(Validators.minLength(anyField.minLength));
1782
+ }
1783
+ if (anyField.maxLength) {
1784
+ validators.push(Validators.maxLength(anyField.maxLength));
1785
+ }
1786
+ // --- InputValidationEnum / custom pattern ---
1787
+ if (anyField.inputValidation) {
1788
+ validators.push(Validators.pattern(new RegExp(anyField.inputValidation)));
1789
+ }
1790
+ else if (anyField.pattern) {
1791
+ validators.push(Validators.pattern(anyField.pattern));
1792
+ }
1793
+ // --- Type specific ---
1794
+ switch (field.type) {
1795
+ case FormInputTypeEnum.EMAIL:
1796
+ // Angular email validator in addition to optional pattern
1797
+ validators.push(Validators.email);
1798
+ break;
1799
+ case FormInputTypeEnum.PASSWORD:
1800
+ // You can keep additional rules here if you want (already covered by minLength/maxLength/pattern above)
1801
+ break;
1802
+ default:
1803
+ // other types: nothing special for now
1804
+ break;
1805
+ }
1806
+ return validators;
1807
+ }
1748
1808
  getErrorMessage(field) {
1749
- if (this.form.get(field.name)?.hasError('required')) {
1809
+ const control = this.form.get(field.name);
1810
+ if (!control) {
1811
+ return '';
1812
+ }
1813
+ if (control.hasError('required')) {
1750
1814
  return (field.errorText ||
1751
1815
  `${field.label} ${this.errorMessages[this.language].required}`);
1752
1816
  }
1817
+ if (control.hasError('email')) {
1818
+ return (field.errorText ||
1819
+ `${field.label} ${this.errorMessages[this.language].email}`);
1820
+ }
1821
+ if (control.hasError('pattern')) {
1822
+ return (field.errorText ||
1823
+ `${field.label} ${this.errorMessages[this.language].pattern}`);
1824
+ }
1825
+ if (control.hasError('minlength')) {
1826
+ const requiredLen = control.getError('minlength').requiredLength;
1827
+ return `${field.label} must be at least ${requiredLen} characters`;
1828
+ }
1829
+ if (control.hasError('maxlength')) {
1830
+ const requiredLen = control.getError('maxlength').requiredLength;
1831
+ return `${field.label} must be at most ${requiredLen} characters`;
1832
+ }
1753
1833
  return '';
1754
1834
  }
1755
1835
  onSubmit() {
@@ -3368,6 +3448,7 @@ class PTButtonComponent {
3368
3448
  fontColor: '#000',
3369
3449
  backgroundColor: '#fff',
3370
3450
  borderColor: '#000',
3451
+ outlined: false,
3371
3452
  };
3372
3453
  }
3373
3454
  }
@@ -3381,7 +3462,7 @@ class PTButtonComponent {
3381
3462
  JSON.stringify({ ...prev, disabled: undefined }) ===
3382
3463
  JSON.stringify({ ...curr, disabled: undefined });
3383
3464
  if (onlyDisabledChanged) {
3384
- this.updateDisabledStyles(curr.disabled);
3465
+ this.updateDisabledStyles(curr.disabled ?? false);
3385
3466
  }
3386
3467
  else {
3387
3468
  this.applyButtonStyles();
@@ -3393,14 +3474,6 @@ class PTButtonComponent {
3393
3474
  }
3394
3475
  }
3395
3476
  }
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
3477
  ngAfterViewInit() {
3405
3478
  this.applyButtonStyles();
3406
3479
  }
@@ -3410,23 +3483,58 @@ class PTButtonComponent {
3410
3483
  getType() {
3411
3484
  return this.buttonConfig.type || 'button';
3412
3485
  }
3486
+ updateDisabledStyles(isDisabled) {
3487
+ const buttonElement = this.el.nativeElement.querySelector('button.p-element');
3488
+ if (buttonElement) {
3489
+ this.renderer.setStyle(buttonElement, 'color', isDisabled ? '#999' : this.buttonConfig.fontColor);
3490
+ this.renderer.setStyle(buttonElement, 'background-color', isDisabled ? '#e0e0e0' : this.buttonConfig.backgroundColor);
3491
+ this.renderer.setStyle(buttonElement, 'border-color', isDisabled ? '#bdbdbd' : this.buttonConfig.borderColor);
3492
+ }
3493
+ }
3494
+ /**
3495
+ * We delegate colors to PrimeNG theme when:
3496
+ * - outlined = true
3497
+ * - and no manual color is provided (no backgroundColor, borderColor, fontColor)
3498
+ */
3499
+ shouldUseThemeColors() {
3500
+ if (!this.buttonConfig) {
3501
+ return false;
3502
+ }
3503
+ const outlined = !!this.buttonConfig.outlined; // ✅ coerce to boolean
3504
+ return (outlined &&
3505
+ !this.buttonConfig.backgroundColor &&
3506
+ !this.buttonConfig.borderColor &&
3507
+ !this.buttonConfig.fontColor);
3508
+ }
3413
3509
  applyButtonStyles() {
3414
3510
  const buttonElement = this.el.nativeElement.querySelector('button.p-element');
3415
- if (buttonElement && this.buttonConfig) {
3416
- const isDisabled = this.buttonConfig.disabled;
3511
+ if (!buttonElement || !this.buttonConfig) {
3512
+ return;
3513
+ }
3514
+ const isDisabled = !!this.buttonConfig.disabled;
3515
+ const useThemeColors = this.shouldUseThemeColors();
3516
+ // Width / height always applied
3517
+ this.renderer.setStyle(buttonElement, 'width', this.buttonConfig.width || 'auto');
3518
+ this.renderer.setStyle(buttonElement, 'height', this.buttonConfig.height || 'auto');
3519
+ // ✅ Only override colors when we are NOT delegating to PrimeNG theme
3520
+ if (!useThemeColors) {
3417
3521
  this.renderer.setStyle(buttonElement, 'color', isDisabled ? '#999' : this.buttonConfig.fontColor);
3418
3522
  this.renderer.setStyle(buttonElement, 'background-color', isDisabled ? '#e0e0e0' : this.buttonConfig.backgroundColor);
3419
3523
  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');
3524
+ }
3525
+ else {
3526
+ // If we delegate to theme, clear any inline overrides
3527
+ this.renderer.removeStyle(buttonElement, 'color');
3528
+ this.renderer.removeStyle(buttonElement, 'background-color');
3529
+ this.renderer.removeStyle(buttonElement, 'border-color');
3422
3530
  }
3423
3531
  }
3424
3532
  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"] }] }); }
3533
+ 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
3534
  }
3427
3535
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTButtonComponent, decorators: [{
3428
3536
  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"] }]
3537
+ 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
3538
  }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { buttonConfig: [{
3431
3539
  type: Input
3432
3540
  }] } });
@@ -3668,53 +3776,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
3668
3776
  }]
3669
3777
  }] });
3670
3778
 
3671
- // Default Styles for Different Dialog Types
3779
+ /**
3780
+ * Styles per severity:
3781
+ * - Only header (text/color) is provided here.
3782
+ * - No default "content" text anymore.
3783
+ */
3672
3784
  const DIALOG_STYLES = {
3673
3785
  [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' },
3786
+ header: { text: 'Avertissement', color: '#8a4b00' },
3678
3787
  },
3679
3788
  [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' },
3789
+ header: { text: 'Succès', color: '#166534' },
3684
3790
  },
3685
3791
  [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' },
3792
+ header: { text: 'Erreur', color: '#7f1d1d' },
3690
3793
  },
3691
3794
  [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' },
3795
+ header: { text: 'Information', color: '#2563eb' },
3696
3796
  },
3697
3797
  };
3698
- // Centralized Default Values
3798
+ /**
3799
+ * Default config:
3800
+ * - content is now empty string (no default message).
3801
+ */
3699
3802
  const DEFAULT_DIALOG_CONFIG = {
3700
3803
  header: { text: 'Confirmation' },
3701
3804
  visible: false,
3702
- width: '400px',
3805
+ width: '720px',
3703
3806
  height: 'auto',
3704
- content: 'Do you want to proceed?',
3807
+ content: '', // no default message
3705
3808
  confirmButtonConfig: {
3706
- label: 'Confirm',
3707
- fontColor: '#fff',
3708
- backgroundColor: '#007bff',
3809
+ label: 'Confirmer',
3709
3810
  },
3710
3811
  cancelButtonConfig: {
3711
- label: 'Cancel',
3712
- fontColor: '#fff',
3713
- backgroundColor: '#6c757d',
3812
+ label: 'Annuler',
3714
3813
  },
3715
3814
  dialogStyle: SeverityEnum.INFO,
3716
3815
  };
3717
- class PTDialogComponent {
3816
+ class PTConfirmDialogComponent {
3718
3817
  constructor(confirmationService, messageService, renderer, el) {
3719
3818
  this.confirmationService = confirmationService;
3720
3819
  this.messageService = messageService;
@@ -3723,11 +3822,13 @@ class PTDialogComponent {
3723
3822
  this.dialogConfig = { ...DEFAULT_DIALOG_CONFIG };
3724
3823
  this.confirm = new EventEmitter();
3725
3824
  this.cancel = new EventEmitter();
3825
+ this.SeverityEnum = SeverityEnum;
3726
3826
  }
3727
3827
  ngOnChanges(changes) {
3728
3828
  if (changes['dialogConfig']) {
3729
- if (changes['dialogConfig'].currentValue?.dialogStyle !==
3730
- changes['dialogConfig'].previousValue?.dialogStyle) {
3829
+ const current = changes['dialogConfig'].currentValue;
3830
+ if (changes['dialogConfig'].previousValue?.dialogStyle !==
3831
+ current?.dialogStyle) {
3731
3832
  this.applyDialogStyle();
3732
3833
  }
3733
3834
  if (this.dialogConfig.visible) {
@@ -3735,80 +3836,124 @@ class PTDialogComponent {
3735
3836
  }
3736
3837
  }
3737
3838
  }
3839
+ /**
3840
+ * Merge defaults + current config + severity style.
3841
+ * We are careful NOT to spread header (it can be string or object).
3842
+ */
3738
3843
  applyDialogStyle() {
3739
3844
  const dialogStyle = this.dialogConfig.dialogStyle || SeverityEnum.INFO;
3740
3845
  const styleConfig = DIALOG_STYLES[dialogStyle] || {};
3846
+ const current = this.dialogConfig;
3847
+ // Decide which header to use without spreading non-object types
3848
+ const mergedHeader = current.header !== undefined
3849
+ ? current.header
3850
+ : styleConfig.header !== undefined
3851
+ ? styleConfig.header
3852
+ : DEFAULT_DIALOG_CONFIG.header;
3741
3853
  this.dialogConfig = {
3742
3854
  ...DEFAULT_DIALOG_CONFIG,
3855
+ ...current,
3743
3856
  ...styleConfig,
3857
+ header: mergedHeader,
3744
3858
  confirmButtonConfig: {
3745
3859
  ...DEFAULT_DIALOG_CONFIG.confirmButtonConfig,
3746
- ...styleConfig.confirmButtonConfig,
3860
+ ...current.confirmButtonConfig,
3747
3861
  },
3748
3862
  cancelButtonConfig: {
3749
3863
  ...DEFAULT_DIALOG_CONFIG.cancelButtonConfig,
3750
- ...styleConfig.cancelButtonConfig,
3864
+ ...current.cancelButtonConfig,
3751
3865
  },
3866
+ visible: current.visible,
3867
+ };
3868
+ }
3869
+ getSeverityClass() {
3870
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3871
+ switch (style) {
3872
+ case SeverityEnum.DANGER:
3873
+ return 'pt-confirm-dialog-danger';
3874
+ case SeverityEnum.WARNING:
3875
+ return 'pt-confirm-dialog-warning';
3876
+ case SeverityEnum.SUCCESS:
3877
+ return 'pt-confirm-dialog-success';
3878
+ case SeverityEnum.INFO:
3879
+ default:
3880
+ return 'pt-confirm-dialog-info';
3881
+ }
3882
+ }
3883
+ /** SUCCESS & INFO share same behaviour, only color differs */
3884
+ getSeverityColors() {
3885
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3886
+ switch (style) {
3887
+ case SeverityEnum.DANGER:
3888
+ return { header: '#b91c1c', message: '#4b5563' };
3889
+ case SeverityEnum.WARNING:
3890
+ return { header: '#b45309', message: '#92400e' };
3891
+ case SeverityEnum.SUCCESS:
3892
+ return { header: '#15803d', message: '#166534' };
3893
+ case SeverityEnum.INFO:
3894
+ default:
3895
+ return { header: '#2563eb', message: '#2563eb' };
3896
+ }
3897
+ }
3898
+ // ───────────── Button models for pt-button ─────────────
3899
+ get confirmButtonModel() {
3900
+ const style = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3901
+ const confirmSeverity = style === SeverityEnum.DANGER
3902
+ ? SeverityEnum.DANGER
3903
+ : style === SeverityEnum.WARNING
3904
+ ? SeverityEnum.WARNING
3905
+ : style === SeverityEnum.SUCCESS
3906
+ ? SeverityEnum.SUCCESS
3907
+ : SeverityEnum.INFO;
3908
+ return {
3909
+ label: this.dialogConfig.confirmButtonConfig?.label ?? 'Confirmer',
3910
+ icon: this.dialogConfig.confirmButtonConfig?.icon ?? 'pi pi-check',
3911
+ iconPos: 'left',
3912
+ type: 'button',
3913
+ outlined: true,
3914
+ severity: confirmSeverity,
3915
+ styleClass: (this.dialogConfig.confirmButtonConfig?.styleClass || '') +
3916
+ ' pt-confirm-dialog-confirm-btn',
3917
+ width: 'auto',
3918
+ };
3919
+ }
3920
+ get cancelButtonModel() {
3921
+ return {
3922
+ label: this.dialogConfig.cancelButtonConfig?.label ?? 'Annuler',
3923
+ icon: this.dialogConfig.cancelButtonConfig?.icon ?? 'pi pi-times',
3924
+ iconPos: 'left',
3925
+ type: 'button',
3926
+ outlined: true,
3927
+ severity: SeverityEnum.INFO,
3928
+ styleClass: (this.dialogConfig.cancelButtonConfig?.styleClass || '') +
3929
+ ' pt-confirm-dialog-cancel-btn',
3930
+ width: 'auto',
3752
3931
  };
3753
3932
  }
3754
3933
  showDialog() {
3755
3934
  this.confirmationService.confirm({
3756
- header: this.getDialogHeaderText(),
3935
+ header: '',
3936
+ // message is not really used visually, but kept here
3757
3937
  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
- },
3938
+ accept: () => this.confirm.emit(),
3939
+ reject: (_type) => this.cancel.emit(),
3775
3940
  });
3776
- // Use renderer to apply dynamic styles
3777
3941
  setTimeout(() => {
3778
- const dialogElement = this.el.nativeElement.querySelector('.p-dialog');
3942
+ const dialogElement = document.querySelector('.p-confirm-dialog');
3779
3943
  if (dialogElement) {
3780
- this.renderer.setStyle(dialogElement, 'width', this.dialogConfig.width || '400px');
3944
+ this.renderer.addClass(dialogElement, 'pt-confirm-dialog-overlay');
3945
+ this.renderer.removeClass(dialogElement, 'pt-confirm-dialog-danger');
3946
+ this.renderer.removeClass(dialogElement, 'pt-confirm-dialog-warning');
3947
+ this.renderer.removeClass(dialogElement, 'pt-confirm-dialog-success');
3948
+ this.renderer.removeClass(dialogElement, 'pt-confirm-dialog-info');
3949
+ const severityClass = this.getSeverityClass();
3950
+ this.renderer.addClass(dialogElement, severityClass);
3951
+ this.renderer.setStyle(dialogElement, 'width', this.dialogConfig.width || '720px');
3781
3952
  this.renderer.setStyle(dialogElement, 'height', this.dialogConfig.height || 'auto');
3782
3953
  }
3783
3954
  }, 0);
3784
3955
  }
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
- }
3956
+ // ── header / icon / content helpers ───────────────────────────────
3812
3957
  getDialogHeaderText() {
3813
3958
  const header = this.dialogConfig.header;
3814
3959
  const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
@@ -3821,88 +3966,85 @@ class PTDialogComponent {
3821
3966
  styleHeader !== null &&
3822
3967
  'text' in styleHeader
3823
3968
  ? styleHeader.text
3824
- : 'Confirmation'; // ✅ Default value
3969
+ : 'Confirmation';
3825
3970
  }
3826
3971
  getDialogHeaderStyle() {
3827
3972
  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
- };
3973
+ const { header: color } = this.getSeverityColors();
3974
+ const fontSize = typeof header === 'object' && header !== null && header.fontSize
3975
+ ? header.fontSize
3976
+ : '20px';
3977
+ return {
3978
+ color,
3979
+ fontSize,
3980
+ fontWeight: 700,
3981
+ };
3840
3982
  }
3841
3983
  getDialogIconClass() {
3842
3984
  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
3985
+ const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3986
+ const styleHeader = DIALOG_STYLES[dialogStyle]?.header;
3846
3987
  const icon = typeof header === 'object' && header !== null && 'icon' in header
3847
3988
  ? header.icon
3848
3989
  : typeof styleHeader === 'object' && 'icon' in styleHeader
3849
3990
  ? styleHeader.icon
3850
3991
  : undefined;
3851
- // ✅ If `icon` is an object, extract `.code`, otherwise return as string or default value
3852
3992
  return typeof icon === 'string'
3853
3993
  ? icon
3854
3994
  : icon?.code || 'pi pi-exclamation-circle';
3855
3995
  }
3856
3996
  getDialogIconStyle() {
3857
3997
  const header = this.dialogConfig.header;
3858
- const dialogStyle = this.dialogConfig.dialogStyle ?? SeverityEnum.INFO;
3859
- const styleHeader = DIALOG_STYLES[dialogStyle]?.header;
3998
+ const { header: defaultColor } = this.getSeverityColors();
3860
3999
  const icon = typeof header === 'object' && header !== null && 'icon' in header
3861
4000
  ? header.icon
3862
4001
  : undefined;
3863
4002
  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',
4003
+ color: icon?.color || defaultColor,
4004
+ fontSize: icon?.fontSize || '2.2rem',
3870
4005
  };
3871
4006
  }
4007
+ /**
4008
+ * No default text anymore.
4009
+ * - If dialogConfig.content is a string, we return it.
4010
+ * - If it is an object with text, we use that.
4011
+ * - Otherwise we return '' (empty) so the body is blank.
4012
+ */
3872
4013
  getDialogContentText() {
3873
4014
  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?');
4015
+ if (typeof content === 'string') {
4016
+ return content;
4017
+ }
4018
+ if (content && typeof content === 'object' && 'text' in content) {
4019
+ return content.text ?? '';
4020
+ }
4021
+ return '';
3882
4022
  }
3883
4023
  getDialogContentStyle() {
3884
4024
  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',
4025
+ const { message } = this.getSeverityColors();
4026
+ let fontSize = '18px';
4027
+ let textAlign;
4028
+ if (typeof content === 'object' && content !== null) {
4029
+ if (content.fontSize) {
4030
+ fontSize = content.fontSize;
3893
4031
  }
3894
- : {
3895
- color: typeof styleContent === 'object' ? styleContent?.color : '#333',
3896
- fontSize: '20px',
3897
- textAlign: 'left',
3898
- };
4032
+ if (content.position) {
4033
+ textAlign = content.position;
4034
+ }
4035
+ }
4036
+ return {
4037
+ color: message,
4038
+ fontSize,
4039
+ ...(textAlign ? { textAlign } : {}),
4040
+ };
3899
4041
  }
3900
- 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"] }] }); }
4042
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogComponent, deps: [{ token: i1$1.ConfirmationService }, { token: i1$1.MessageService }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
4043
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTConfirmDialogComponent, selector: "pt-confirm-dialog", inputs: { dialogConfig: "dialogConfig" }, outputs: { confirm: "confirm", cancel: "cancel" }, providers: [ConfirmationService, MessageService], usesOnChanges: true, ngImport: i0, template: "<div class=\"pt-confirm-dialog\">\n <p-confirmDialog #cd>\n <ng-template pTemplate=\"header\"></ng-template>\n\n <ng-template pTemplate=\"message\">\n <div class=\"pt-confirm-dialog-card\">\n <div class=\"pt-confirm-dialog-card-top\">\n <div class=\"pt-confirm-dialog-icon-wrapper\">\n <i\n class=\"pt-confirm-dialog-icon\"\n [class]=\"getDialogIconClass()\"\n [ngStyle]=\"getDialogIconStyle()\"\n ></i>\n </div>\n\n <div class=\"pt-confirm-dialog-text-wrapper\">\n <div\n class=\"pt-confirm-dialog-title\"\n [ngStyle]=\"getDialogHeaderStyle()\"\n >\n {{ getDialogHeaderText() }}\n </div>\n\n <div\n class=\"pt-confirm-dialog-message\"\n [ngStyle]=\"getDialogContentStyle()\"\n >\n {{ getDialogContentText() }}\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"pt-confirm-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-confirm-dialog-overlay{border-radius:18px;overflow:hidden;box-shadow:0 20px 45px #0f172a59}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-header{display:none!important;padding:0!important;border:0!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px}.pt-confirm-dialog-card{border-radius:18px 18px 0 0;overflow:hidden}.pt-confirm-dialog-card-top{padding:28px 40px;display:flex;align-items:flex-start}::ng-deep .p-confirm-dialog.pt-confirm-dialog-danger .pt-confirm-dialog-card{background-color:#fde4e4}::ng-deep .p-confirm-dialog.pt-confirm-dialog-warning .pt-confirm-dialog-card{background-color:#fff4d1}::ng-deep .p-confirm-dialog.pt-confirm-dialog-success .pt-confirm-dialog-card{background-color:#dcfce7}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .pt-confirm-dialog-card{background-color:#e0f2fe}.pt-confirm-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-confirm-dialog-icon{font-size:30px;line-height:1;color:#b91c1c}.pt-confirm-dialog-text-wrapper{flex:1}.pt-confirm-dialog-title{font-size:22px;font-weight:700;margin-bottom:8px;color:#b91c1c}.pt-confirm-dialog-message{font-size:18px;line-height:1.5;color:#4b5563}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-footer{background:#fff;border-top:1px solid rgba(148,163,184,.25);padding:16px 32px 22px}.pt-confirm-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-confirm-dialog-danger .p-dialog-footer .p-button{background:#fff!important;border-color:#dc2626!important;color:#dc2626!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-warning .p-dialog-footer .p-button{background:#fff!important;border-color:#d97706!important;color:#b45309!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-success .p-dialog-footer .p-button{background:#fff!important;border-color:#16a34a!important;color:#15803d!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .p-dialog-footer .p-button{background:#fff!important;border-color:#2563eb!important;color:#2563eb!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .p-dialog-footer .p-button:hover{background:#eff6ff!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px;display:block}.pt-confirm-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
4044
  }
3903
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogComponent, decorators: [{
4045
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogComponent, decorators: [{
3904
4046
  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"] }]
4047
+ args: [{ selector: 'pt-confirm-dialog', providers: [ConfirmationService, MessageService], template: "<div class=\"pt-confirm-dialog\">\n <p-confirmDialog #cd>\n <ng-template pTemplate=\"header\"></ng-template>\n\n <ng-template pTemplate=\"message\">\n <div class=\"pt-confirm-dialog-card\">\n <div class=\"pt-confirm-dialog-card-top\">\n <div class=\"pt-confirm-dialog-icon-wrapper\">\n <i\n class=\"pt-confirm-dialog-icon\"\n [class]=\"getDialogIconClass()\"\n [ngStyle]=\"getDialogIconStyle()\"\n ></i>\n </div>\n\n <div class=\"pt-confirm-dialog-text-wrapper\">\n <div\n class=\"pt-confirm-dialog-title\"\n [ngStyle]=\"getDialogHeaderStyle()\"\n >\n {{ getDialogHeaderText() }}\n </div>\n\n <div\n class=\"pt-confirm-dialog-message\"\n [ngStyle]=\"getDialogContentStyle()\"\n >\n {{ getDialogContentText() }}\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"footer\">\n <div class=\"pt-confirm-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-confirm-dialog-overlay{border-radius:18px;overflow:hidden;box-shadow:0 20px 45px #0f172a59}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-header{display:none!important;padding:0!important;border:0!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px}.pt-confirm-dialog-card{border-radius:18px 18px 0 0;overflow:hidden}.pt-confirm-dialog-card-top{padding:28px 40px;display:flex;align-items:flex-start}::ng-deep .p-confirm-dialog.pt-confirm-dialog-danger .pt-confirm-dialog-card{background-color:#fde4e4}::ng-deep .p-confirm-dialog.pt-confirm-dialog-warning .pt-confirm-dialog-card{background-color:#fff4d1}::ng-deep .p-confirm-dialog.pt-confirm-dialog-success .pt-confirm-dialog-card{background-color:#dcfce7}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .pt-confirm-dialog-card{background-color:#e0f2fe}.pt-confirm-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-confirm-dialog-icon{font-size:30px;line-height:1;color:#b91c1c}.pt-confirm-dialog-text-wrapper{flex:1}.pt-confirm-dialog-title{font-size:22px;font-weight:700;margin-bottom:8px;color:#b91c1c}.pt-confirm-dialog-message{font-size:18px;line-height:1.5;color:#4b5563}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-footer{background:#fff;border-top:1px solid rgba(148,163,184,.25);padding:16px 32px 22px}.pt-confirm-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-confirm-dialog-danger .p-dialog-footer .p-button{background:#fff!important;border-color:#dc2626!important;color:#dc2626!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-warning .p-dialog-footer .p-button{background:#fff!important;border-color:#d97706!important;color:#b45309!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-success .p-dialog-footer .p-button{background:#fff!important;border-color:#16a34a!important;color:#15803d!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .p-dialog-footer .p-button{background:#fff!important;border-color:#2563eb!important;color:#2563eb!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-info .p-dialog-footer .p-button:hover{background:#eff6ff!important}::ng-deep .p-confirm-dialog.pt-confirm-dialog-overlay .p-dialog-content{padding:0;background:transparent;border-top-left-radius:18px;border-top-right-radius:18px;display:block}.pt-confirm-dialog-card{border-radius:18px 18px 0 0;overflow:hidden;width:100%}\n"] }]
3906
4048
  }], ctorParameters: () => [{ type: i1$1.ConfirmationService }, { type: i1$1.MessageService }, { type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { dialogConfig: [{
3907
4049
  type: Input
3908
4050
  }], confirm: [{
@@ -3911,17 +4053,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
3911
4053
  type: Output
3912
4054
  }] } });
3913
4055
 
3914
- class PTDialogModule {
3915
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3916
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, declarations: [PTDialogComponent], imports: [CommonModule, DialogModule, PTButtonModule, ConfirmDialogModule], exports: [PTDialogComponent] }); }
3917
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, imports: [CommonModule, DialogModule, PTButtonModule, ConfirmDialogModule] }); }
4056
+ class PTConfirmDialogModule {
4057
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4058
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogModule, declarations: [PTConfirmDialogComponent], imports: [CommonModule, DialogModule, PTButtonModule, ConfirmDialogModule], exports: [PTConfirmDialogComponent] }); }
4059
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogModule, imports: [CommonModule, DialogModule, PTButtonModule, ConfirmDialogModule] }); }
3918
4060
  }
3919
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, decorators: [{
4061
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTConfirmDialogModule, decorators: [{
3920
4062
  type: NgModule,
3921
4063
  args: [{
3922
- declarations: [PTDialogComponent],
4064
+ declarations: [PTConfirmDialogComponent],
3923
4065
  imports: [CommonModule, DialogModule, PTButtonModule, ConfirmDialogModule],
3924
- exports: [PTDialogComponent],
4066
+ exports: [PTConfirmDialogComponent],
3925
4067
  }]
3926
4068
  }] });
3927
4069
 
@@ -3965,6 +4107,128 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
3965
4107
  }]
3966
4108
  }] });
3967
4109
 
4110
+ class PTDialogComponent {
4111
+ constructor() {
4112
+ /** Enable scroll when body exceeds given height/width */
4113
+ this.bodyScrollable = true;
4114
+ /** Control footer visibility (default: true) */
4115
+ this.showFooter = true;
4116
+ this.modal = true;
4117
+ this.closable = true;
4118
+ this.draggable = true;
4119
+ this.resizable = true;
4120
+ this.maximizable = false;
4121
+ this.dismissableMask = false;
4122
+ this.closeOnEscape = true;
4123
+ this.blockScroll = true;
4124
+ this.position = 'center';
4125
+ /** internal visible flag used by p-dialog */
4126
+ this._visible = false;
4127
+ this.visibleChange = new EventEmitter();
4128
+ }
4129
+ get visible() {
4130
+ return this._visible;
4131
+ }
4132
+ set visible(v) {
4133
+ this._visible = v;
4134
+ }
4135
+ /** Final class applied to p-dialog */
4136
+ get dialogStyleClass() {
4137
+ return [
4138
+ 'border-round-3xl',
4139
+ 'shadow-6',
4140
+ 'overflow-hidden',
4141
+ 'pt-dialog-header-blue', // for header/footer colors
4142
+ this.styleClass,
4143
+ ]
4144
+ .filter(Boolean)
4145
+ .join(' ');
4146
+ }
4147
+ /** Style applied to the body wrapper */
4148
+ get bodyStyle() {
4149
+ const style = {};
4150
+ if (this.bodyWidth) {
4151
+ style['max-width'] = this.bodyWidth;
4152
+ }
4153
+ if (this.bodyHeight) {
4154
+ style['max-height'] = this.bodyHeight;
4155
+ if (this.bodyScrollable) {
4156
+ style['overflow-y'] = 'auto';
4157
+ style['overflow-x'] = 'auto';
4158
+ }
4159
+ }
4160
+ return style;
4161
+ }
4162
+ onShow() {
4163
+ this.visibleChange.emit(true);
4164
+ }
4165
+ onHide() {
4166
+ this.visibleChange.emit(false);
4167
+ }
4168
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4169
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: PTDialogComponent, selector: "pt-dialog", inputs: { header: "header", style: "style", styleClass: "styleClass", headerIconClass: "headerIconClass", bodyWidth: "bodyWidth", bodyHeight: "bodyHeight", bodyScrollable: "bodyScrollable", showFooter: "showFooter", modal: "modal", closable: "closable", draggable: "draggable", resizable: "resizable", maximizable: "maximizable", dismissableMask: "dismissableMask", closeOnEscape: "closeOnEscape", blockScroll: "blockScroll", breakpoints: "breakpoints", position: "position", contentStyle: "contentStyle", visible: "visible" }, outputs: { visibleChange: "visibleChange" }, ngImport: i0, template: "<p-dialog\n [(visible)]=\"_visible\"\n [header]=\"header\"\n [modal]=\"modal\"\n [style]=\"style\"\n [breakpoints]=\"breakpoints\"\n [closable]=\"closable\"\n [draggable]=\"draggable\"\n [resizable]=\"resizable\"\n [maximizable]=\"maximizable\"\n [dismissableMask]=\"dismissableMask\"\n [closeOnEscape]=\"closeOnEscape\"\n [blockScroll]=\"blockScroll\"\n [position]=\"position\"\n [contentStyle]=\"contentStyle\"\n [styleClass]=\"dialogStyleClass\"\n (onShow)=\"onShow()\"\n (onHide)=\"onHide()\"\n>\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <div\n class=\"flex align-items-center justify-content-between w-full px-4 pt-3 pb-2\"\n >\n <div class=\"flex align-items-center gap-2\">\n <!-- optional icon -->\n <i *ngIf=\"headerIconClass\" [ngClass]=\"headerIconClass\"></i>\n\n <!-- projected custom header -->\n <ng-content select=\"[ptDialogHeader]\"></ng-content>\n\n <!-- fallback header text -->\n <span *ngIf=\"header\" class=\"font-bold text-lg\">\n {{ header }}\n </span>\n </div>\n <!-- close icon from PrimeNG (X) is rendered automatically -->\n </div>\n </ng-template>\n\n <!-- BODY -->\n <div\n class=\"surface-50 px-4 py-4 flex flex-column gap-3\"\n [ngStyle]=\"bodyStyle\"\n >\n <ng-content select=\"[ptDialogContent]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <!-- FOOTER (optional) -->\n <ng-template pTemplate=\"footer\" *ngIf=\"showFooter\">\n <div class=\"surface-100 px-4 py-2 flex justify-content-end gap-2\">\n <ng-content select=\"[ptDialogFooter]\"></ng-content>\n </div>\n </ng-template>\n</p-dialog>\n", styles: [":host ::ng-deep .pt-dialog-header-blue .p-dialog-header{background-color:#e0f2ff;border-bottom:0}:host ::ng-deep .pt-dialog-header-blue .p-dialog-footer{background-color:#f5f6f8!important;border-top:0!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2$3.Dialog, selector: "p-dialog", inputs: ["header", "draggable", "resizable", "positionLeft", "positionTop", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "responsive", "appendTo", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "breakpoint", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "visible", "style", "position"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] }); }
4170
+ }
4171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogComponent, decorators: [{
4172
+ type: Component,
4173
+ args: [{ selector: 'pt-dialog', template: "<p-dialog\n [(visible)]=\"_visible\"\n [header]=\"header\"\n [modal]=\"modal\"\n [style]=\"style\"\n [breakpoints]=\"breakpoints\"\n [closable]=\"closable\"\n [draggable]=\"draggable\"\n [resizable]=\"resizable\"\n [maximizable]=\"maximizable\"\n [dismissableMask]=\"dismissableMask\"\n [closeOnEscape]=\"closeOnEscape\"\n [blockScroll]=\"blockScroll\"\n [position]=\"position\"\n [contentStyle]=\"contentStyle\"\n [styleClass]=\"dialogStyleClass\"\n (onShow)=\"onShow()\"\n (onHide)=\"onHide()\"\n>\n <!-- HEADER -->\n <ng-template pTemplate=\"header\">\n <div\n class=\"flex align-items-center justify-content-between w-full px-4 pt-3 pb-2\"\n >\n <div class=\"flex align-items-center gap-2\">\n <!-- optional icon -->\n <i *ngIf=\"headerIconClass\" [ngClass]=\"headerIconClass\"></i>\n\n <!-- projected custom header -->\n <ng-content select=\"[ptDialogHeader]\"></ng-content>\n\n <!-- fallback header text -->\n <span *ngIf=\"header\" class=\"font-bold text-lg\">\n {{ header }}\n </span>\n </div>\n <!-- close icon from PrimeNG (X) is rendered automatically -->\n </div>\n </ng-template>\n\n <!-- BODY -->\n <div\n class=\"surface-50 px-4 py-4 flex flex-column gap-3\"\n [ngStyle]=\"bodyStyle\"\n >\n <ng-content select=\"[ptDialogContent]\"></ng-content>\n <ng-content></ng-content>\n </div>\n\n <!-- FOOTER (optional) -->\n <ng-template pTemplate=\"footer\" *ngIf=\"showFooter\">\n <div class=\"surface-100 px-4 py-2 flex justify-content-end gap-2\">\n <ng-content select=\"[ptDialogFooter]\"></ng-content>\n </div>\n </ng-template>\n</p-dialog>\n", styles: [":host ::ng-deep .pt-dialog-header-blue .p-dialog-header{background-color:#e0f2ff;border-bottom:0}:host ::ng-deep .pt-dialog-header-blue .p-dialog-footer{background-color:#f5f6f8!important;border-top:0!important}\n"] }]
4174
+ }], propDecorators: { header: [{
4175
+ type: Input
4176
+ }], style: [{
4177
+ type: Input
4178
+ }], styleClass: [{
4179
+ type: Input
4180
+ }], headerIconClass: [{
4181
+ type: Input
4182
+ }], bodyWidth: [{
4183
+ type: Input
4184
+ }], bodyHeight: [{
4185
+ type: Input
4186
+ }], bodyScrollable: [{
4187
+ type: Input
4188
+ }], showFooter: [{
4189
+ type: Input
4190
+ }], modal: [{
4191
+ type: Input
4192
+ }], closable: [{
4193
+ type: Input
4194
+ }], draggable: [{
4195
+ type: Input
4196
+ }], resizable: [{
4197
+ type: Input
4198
+ }], maximizable: [{
4199
+ type: Input
4200
+ }], dismissableMask: [{
4201
+ type: Input
4202
+ }], closeOnEscape: [{
4203
+ type: Input
4204
+ }], blockScroll: [{
4205
+ type: Input
4206
+ }], breakpoints: [{
4207
+ type: Input
4208
+ }], position: [{
4209
+ type: Input
4210
+ }], contentStyle: [{
4211
+ type: Input
4212
+ }], visible: [{
4213
+ type: Input
4214
+ }], visibleChange: [{
4215
+ type: Output
4216
+ }] } });
4217
+
4218
+ class PTDialogModule {
4219
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4220
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, declarations: [PTDialogComponent], imports: [CommonModule, DialogModule], exports: [PTDialogComponent] }); }
4221
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, imports: [CommonModule, DialogModule] }); }
4222
+ }
4223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: PTDialogModule, decorators: [{
4224
+ type: NgModule,
4225
+ args: [{
4226
+ declarations: [PTDialogComponent],
4227
+ imports: [CommonModule, DialogModule],
4228
+ exports: [PTDialogComponent],
4229
+ }]
4230
+ }] });
4231
+
3968
4232
  class NgPrimeToolsModule {
3969
4233
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: NgPrimeToolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3970
4234
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.11", ngImport: i0, type: NgPrimeToolsModule, imports: [CommonModule,
@@ -4004,7 +4268,7 @@ class NgPrimeToolsModule {
4004
4268
  // Button
4005
4269
  PTButtonModule,
4006
4270
  // Dialog
4007
- PTDialogModule,
4271
+ PTConfirmDialogModule,
4008
4272
  // Toasts
4009
4273
  PTToastNotifierModule], exports: [PTAdvancedPrimeTableModule,
4010
4274
  MultiSearchCriteriaModule,
@@ -4041,6 +4305,7 @@ class NgPrimeToolsModule {
4041
4305
  // Button
4042
4306
  PTButtonModule,
4043
4307
  // Dialog
4308
+ PTConfirmDialogModule,
4044
4309
  PTDialogModule,
4045
4310
  // Toasts
4046
4311
  PTToastNotifierModule] }); }
@@ -4081,7 +4346,7 @@ class NgPrimeToolsModule {
4081
4346
  // Button
4082
4347
  PTButtonModule,
4083
4348
  // Dialog
4084
- PTDialogModule,
4349
+ PTConfirmDialogModule,
4085
4350
  // Toasts
4086
4351
  PTToastNotifierModule, PTAdvancedPrimeTableModule,
4087
4352
  MultiSearchCriteriaModule,
@@ -4118,6 +4383,7 @@ class NgPrimeToolsModule {
4118
4383
  // Button
4119
4384
  PTButtonModule,
4120
4385
  // Dialog
4386
+ PTConfirmDialogModule,
4121
4387
  PTDialogModule,
4122
4388
  // Toasts
4123
4389
  PTToastNotifierModule] }); }
@@ -4163,7 +4429,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
4163
4429
  // Button
4164
4430
  PTButtonModule,
4165
4431
  // Dialog
4166
- PTDialogModule,
4432
+ PTConfirmDialogModule,
4167
4433
  // Toasts
4168
4434
  PTToastNotifierModule,
4169
4435
  ],
@@ -4203,6 +4469,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
4203
4469
  // Button
4204
4470
  PTButtonModule,
4205
4471
  // Dialog
4472
+ PTConfirmDialogModule,
4206
4473
  PTDialogModule,
4207
4474
  // Toasts
4208
4475
  PTToastNotifierModule,
@@ -4646,5 +4913,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImpo
4646
4913
  * Generated bundle index. Do not edit.
4647
4914
  */
4648
4915
 
4649
- export { BadgeType, BadgeTypeStyles, ButtonColorEnum, DateUtilityService, FormInputTypeEnum, InputValidationEnum, MultiSearchCriteriaComponent, MultiSearchCriteriaModule, NgPrimeToolsModule, PTAdvancedPrimeTableComponent, PTAdvancedPrimeTableModule, PTBreadCrumbComponent, PTBreadCrumbModule, PTButtonComponent, PTButtonModule, PTCardComponent, PTCardModule, PTChartComparisonComponent, PTChartComparisonModule, PTChartComponent, PTChartModule, PTCheckBoxInputComponent, PTCheckBoxInputModule, PTDateInputComponent, PTDateInputModule, PTDialogComponent, PTDialogModule, PTDropdownComponent, PTDropdownModule, PTFooterComponent, PTFooterModule, PTFormBuilderComponent, PTFormBuilderModule, PTGroupComponent, PTGroupModule, PTLineChartComponent, PTLineChartModule, PTLoginPageComponent, PTLoginPageModule, PTMenuComponent, PTMenuFancyComponent, PTMenuFancyModule, PTMenuModule, PTMetricCardComponent, PTMetricCardGroupComponent, PTMetricCardGroupModule, PTMetricCardModule, PTMetricPanelComponent, PTMetricPanelModule, PTNavbarMenuComponent, PTNavbarMenuModule, PTNumberInputComponent, PTNumberInputModule, PTPageSkeletonComponent, PTPageSkeletonModule, PTSideBarMenuComponent, PTSideBarMenuModule, PTSwitchInputComponent, PTSwitchInputModule, PTTextAreaInputComponent, PTTextAreaInputModule, PTTextInputComponent, PTTextInputModule, PTToastNotifierComponent, PTToastNotifierModule, SearchCriteriaTypeEnum, SeverityEnum, TableTypeEnum };
4916
+ export { BadgeType, BadgeTypeStyles, ButtonColorEnum, DateUtilityService, FormInputTypeEnum, InputValidationEnum, MultiSearchCriteriaComponent, MultiSearchCriteriaModule, NgPrimeToolsModule, PTAdvancedPrimeTableComponent, PTAdvancedPrimeTableModule, PTBreadCrumbComponent, PTBreadCrumbModule, PTButtonComponent, PTButtonModule, PTCardComponent, PTCardModule, PTChartComparisonComponent, PTChartComparisonModule, PTChartComponent, PTChartModule, PTCheckBoxInputComponent, PTCheckBoxInputModule, PTConfirmDialogComponent, PTConfirmDialogModule, PTDateInputComponent, PTDateInputModule, PTDialogComponent, PTDialogModule, PTDropdownComponent, PTDropdownModule, PTFooterComponent, PTFooterModule, PTFormBuilderComponent, PTFormBuilderModule, PTGroupComponent, PTGroupModule, PTLineChartComponent, PTLineChartModule, PTLoginPageComponent, PTLoginPageModule, PTMenuComponent, PTMenuFancyComponent, PTMenuFancyModule, PTMenuModule, PTMetricCardComponent, PTMetricCardGroupComponent, PTMetricCardGroupModule, PTMetricCardModule, PTMetricPanelComponent, PTMetricPanelModule, PTNavbarMenuComponent, PTNavbarMenuModule, PTNumberInputComponent, PTNumberInputModule, PTPageSkeletonComponent, PTPageSkeletonModule, PTSideBarMenuComponent, PTSideBarMenuModule, PTSwitchInputComponent, PTSwitchInputModule, PTTextAreaInputComponent, PTTextAreaInputModule, PTTextInputComponent, PTTextInputModule, PTToastNotifierComponent, PTToastNotifierModule, SearchCriteriaTypeEnum, SeverityEnum, TableTypeEnum };
4650
4917
  //# sourceMappingURL=ng-prime-tools.mjs.map