ln-20-lib-components 0.0.61 → 0.0.63
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.
- package/fesm2022/{ln-20-lib-components-ln-20-lib-components-CpOVbJ0r.mjs → ln-20-lib-components-ln-20-lib-components-CYlSQ3zg.mjs} +965 -931
- package/fesm2022/ln-20-lib-components-ln-20-lib-components-CYlSQ3zg.mjs.map +1 -0
- package/fesm2022/{ln-20-lib-components-selected-items-management.component-BGm_5OVT.mjs → ln-20-lib-components-selected-items-management.component-Cn5xvixS.mjs} +2 -2
- package/fesm2022/{ln-20-lib-components-selected-items-management.component-BGm_5OVT.mjs.map → ln-20-lib-components-selected-items-management.component-Cn5xvixS.mjs.map} +1 -1
- package/fesm2022/ln-20-lib-components.mjs +1 -1
- package/lib/components/origin/form/components/inline-input/inline-input.component.d.ts +7 -1
- package/package.json +1 -1
- package/fesm2022/ln-20-lib-components-ln-20-lib-components-CpOVbJ0r.mjs.map +0 -1
|
@@ -423,308 +423,798 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
423
423
|
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"w-full p-2 rounded-lg\" [style.backgroundColor]=\"formConfig()?.backgroundColor || 'transparent'\">\r\n <lib-form-child [controlsData]=\"controls()\" [formGroup]=\"formGroup()\" (formSubmit)=\"submit($event)\">\r\n </lib-form-child>\r\n @if (httpMessage()) {\r\n <lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n }\r\n</div>" }]
|
|
424
424
|
}], ctorParameters: () => [] });
|
|
425
425
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
this.outputValue.emit(this.value());
|
|
443
|
-
});
|
|
444
|
-
const value$ = toObservable(this.value);
|
|
445
|
-
value$
|
|
446
|
-
.pipe(debounceTime(300), // <- adjust ms here
|
|
447
|
-
distinctUntilChanged(), // avoid repeats for same value
|
|
448
|
-
takeUntilDestroyed() // auto-cleanup on destroy
|
|
449
|
-
)
|
|
450
|
-
.subscribe(v => this.outputDebounced.emit(v));
|
|
451
|
-
effect(() => {
|
|
452
|
-
this.valueSelect.update((_prev) => {
|
|
453
|
-
const options = this.config()?.selectConfig?.options;
|
|
454
|
-
const currentValue = this.value();
|
|
455
|
-
if (this.isSelection(currentValue))
|
|
456
|
-
return currentValue;
|
|
457
|
-
if (currentValue === null || currentValue === undefined)
|
|
458
|
-
return undefined;
|
|
459
|
-
return options?.find(option => option.code === currentValue);
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
ngOnInit() {
|
|
426
|
+
/**
|
|
427
|
+
* Utilidades para manejar errores de API según la interfaz IApiError
|
|
428
|
+
*/
|
|
429
|
+
class ApiErrorUtil {
|
|
430
|
+
/**
|
|
431
|
+
* Procesa errores de API y extrae el mensaje según la interfaz IApiError
|
|
432
|
+
* @param error - El error HTTP recibido
|
|
433
|
+
* @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
|
|
434
|
+
* @returns El mensaje de error procesado
|
|
435
|
+
*/
|
|
436
|
+
static handleApiError(error, fallbackMessage) {
|
|
437
|
+
const apiError = error.error;
|
|
438
|
+
const errorMessage = Array.isArray(apiError?.message)
|
|
439
|
+
? apiError.message.join(', ')
|
|
440
|
+
: apiError?.message ?? fallbackMessage;
|
|
441
|
+
return errorMessage;
|
|
464
442
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Procesa errores de API con información detallada de campos
|
|
445
|
+
* y muestra tanto el mensaje general como los errores específicos de campo
|
|
446
|
+
* @param error - El error HTTP recibido
|
|
447
|
+
* @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
|
|
448
|
+
* @returns El mensaje de error procesado con información de campos si está disponible
|
|
449
|
+
*/
|
|
450
|
+
static handleApiErrorWithFields(error, fallbackMessage) {
|
|
451
|
+
const apiError = error.error;
|
|
452
|
+
let errorMessage = Array.isArray(apiError?.message)
|
|
453
|
+
? apiError.message.join(', ')
|
|
454
|
+
: apiError?.message ?? fallbackMessage;
|
|
455
|
+
// Si hay errores de campo específicos, los agregamos al mensaje
|
|
456
|
+
if (apiError?.errors && apiError.errors.length > 0) {
|
|
457
|
+
const fieldErrors = apiError.errors
|
|
458
|
+
.map(fieldError => `${fieldError.field}: ${fieldError.message}`)
|
|
459
|
+
.join(', ');
|
|
460
|
+
errorMessage = `${errorMessage}. Errores de campos: ${fieldErrors}`;
|
|
472
461
|
}
|
|
462
|
+
return errorMessage;
|
|
473
463
|
}
|
|
474
|
-
|
|
475
|
-
|
|
464
|
+
/**
|
|
465
|
+
* Obtiene solo los errores de campo específicos
|
|
466
|
+
* @param error - El error HTTP recibido
|
|
467
|
+
* @returns Array de errores de campo o array vacío si no hay errores
|
|
468
|
+
*/
|
|
469
|
+
static getFieldErrors(error) {
|
|
470
|
+
const apiError = error.error;
|
|
471
|
+
return apiError?.errors ?? [];
|
|
476
472
|
}
|
|
477
|
-
|
|
478
|
-
|
|
473
|
+
/**
|
|
474
|
+
* Verifica si el error tiene errores de campo específicos
|
|
475
|
+
* @param error - El error HTTP recibido
|
|
476
|
+
* @returns true si hay errores de campo, false en caso contrario
|
|
477
|
+
*/
|
|
478
|
+
static hasFieldErrors(error) {
|
|
479
|
+
const apiError = error.error;
|
|
480
|
+
return apiError?.errors && apiError.errors.length > 0;
|
|
479
481
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Obtiene el código de error específico
|
|
484
|
+
* @param error - El error HTTP recibido
|
|
485
|
+
* @returns El código de error o undefined si no está disponible
|
|
486
|
+
*/
|
|
487
|
+
static getErrorCode(error) {
|
|
488
|
+
const apiError = error.error;
|
|
489
|
+
return apiError?.errorCode;
|
|
483
490
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
491
|
+
/**
|
|
492
|
+
* Obtiene el timestamp del error
|
|
493
|
+
* @param error - El error HTTP recibido
|
|
494
|
+
* @returns El timestamp del error o undefined si no está disponible
|
|
495
|
+
*/
|
|
496
|
+
static getErrorTimestamp(error) {
|
|
497
|
+
const apiError = error.error;
|
|
498
|
+
return apiError?.timestamp;
|
|
487
499
|
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
class CookieUtil {
|
|
488
503
|
/**
|
|
489
|
-
*
|
|
490
|
-
*
|
|
504
|
+
* Obtiene el valor de una cookie por su nombre
|
|
505
|
+
* @param name - Nombre de la cookie
|
|
506
|
+
* @returns El valor de la cookie o null si no existe
|
|
491
507
|
*/
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// Detener la propagación del evento hacia el table
|
|
496
|
-
event.stopPropagation();
|
|
508
|
+
static getCookie(name) {
|
|
509
|
+
if (typeof document === 'undefined') {
|
|
510
|
+
return null;
|
|
497
511
|
}
|
|
512
|
+
const nameEQ = name + '=';
|
|
513
|
+
const ca = document.cookie.split(';');
|
|
514
|
+
for (let i = 0; i < ca.length; i++) {
|
|
515
|
+
let c = ca[i];
|
|
516
|
+
while (c.charAt(0) === ' ') {
|
|
517
|
+
c = c.substring(1, c.length);
|
|
518
|
+
}
|
|
519
|
+
if (c.indexOf(nameEQ) === 0) {
|
|
520
|
+
return c.substring(nameEQ.length, c.length);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return null;
|
|
498
524
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
get ETypeInput() {
|
|
510
|
-
return ETypeInput;
|
|
511
|
-
}
|
|
512
|
-
get duplicatesText() {
|
|
513
|
-
return this.duplicateChips.join(', ');
|
|
514
|
-
}
|
|
515
|
-
get currency() {
|
|
516
|
-
return this.config()?.currencyConfig?.currency ?? 'COP';
|
|
517
|
-
}
|
|
518
|
-
get locale() {
|
|
519
|
-
return this.config()?.currencyConfig?.locale ?? 'es-CO';
|
|
520
|
-
}
|
|
521
|
-
get minFractionDigits() {
|
|
522
|
-
return this.config()?.currencyConfig?.minFractionDigits ?? 2;
|
|
523
|
-
}
|
|
524
|
-
get maxFractionDigits() {
|
|
525
|
-
return this.config()?.currencyConfig?.maxFractionDigits ?? 2;
|
|
526
|
-
}
|
|
527
|
-
knobValueInput = computed(() => {
|
|
528
|
-
let response = this.value();
|
|
529
|
-
const knobConfig = this.config()?.knobConfig ?? { min: 0, max: 100, step: 1 };
|
|
530
|
-
response = parseInt(this.value()) ?? 0;
|
|
531
|
-
if (response < (knobConfig?.min ?? 0)) {
|
|
532
|
-
response = knobConfig.min ?? 0;
|
|
525
|
+
/**
|
|
526
|
+
* Establece una cookie
|
|
527
|
+
* @param name - Nombre de la cookie
|
|
528
|
+
* @param value - Valor de la cookie
|
|
529
|
+
* @param days - Días hasta que expire (por defecto 365)
|
|
530
|
+
* @param path - Ruta de la cookie (por defecto '/')
|
|
531
|
+
*/
|
|
532
|
+
static setCookie(name, value, days = 365, path = '/') {
|
|
533
|
+
if (typeof document === 'undefined') {
|
|
534
|
+
return;
|
|
533
535
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
+
let expires = '';
|
|
537
|
+
if (days) {
|
|
538
|
+
const date = new Date();
|
|
539
|
+
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
540
|
+
expires = '; expires=' + date.toUTCString();
|
|
536
541
|
}
|
|
537
|
-
|
|
538
|
-
});
|
|
539
|
-
knobValueTemplate = computed(() => {
|
|
540
|
-
return this.config()?.knobConfig?.valueTemplate ?? '';
|
|
541
|
-
});
|
|
542
|
-
// Métodos para manejo de chips
|
|
543
|
-
onChipInputChange(event) {
|
|
544
|
-
const target = event.target;
|
|
545
|
-
this.currentInput = target.value;
|
|
542
|
+
document.cookie = name + '=' + (value || '') + expires + '; path=' + path;
|
|
546
543
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
544
|
+
/**
|
|
545
|
+
* Elimina una cookie
|
|
546
|
+
* @param name - Nombre de la cookie a eliminar
|
|
547
|
+
* @param path - Ruta de la cookie (por defecto '/')
|
|
548
|
+
*/
|
|
549
|
+
static eraseCookie(name, path = '/') {
|
|
550
|
+
if (typeof document === 'undefined') {
|
|
551
|
+
return;
|
|
551
552
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
553
|
+
document.cookie = name + '=; Path=' + path + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Obtiene un valor booleano desde una cookie
|
|
557
|
+
* @param name - Nombre de la cookie
|
|
558
|
+
* @param defaultValue - Valor por defecto si la cookie no existe
|
|
559
|
+
* @returns El valor booleano
|
|
560
|
+
*/
|
|
561
|
+
static getBooleanCookie(name, defaultValue = false) {
|
|
562
|
+
const value = this.getCookie(name);
|
|
563
|
+
if (value === null) {
|
|
564
|
+
return defaultValue;
|
|
555
565
|
}
|
|
556
|
-
|
|
566
|
+
return value === 'true';
|
|
557
567
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
568
|
+
/**
|
|
569
|
+
* Establece un valor booleano en una cookie
|
|
570
|
+
* @param name - Nombre de la cookie
|
|
571
|
+
* @param value - Valor booleano
|
|
572
|
+
* @param days - Días hasta que expire (por defecto 365)
|
|
573
|
+
* @param path - Ruta de la cookie (por defecto '/')
|
|
574
|
+
*/
|
|
575
|
+
static setBooleanCookie(name, value, days = 365, path = '/') {
|
|
576
|
+
this.setCookie(name, value.toString(), days, path);
|
|
562
577
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const formatCurrency = (amount, currency) => {
|
|
581
|
+
return new Intl.NumberFormat('es-CO', {
|
|
582
|
+
style: 'currency',
|
|
583
|
+
currency: currency || 'COP'
|
|
584
|
+
}).format(amount);
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
const isSameDay = (date1, date2) => {
|
|
588
|
+
const date1Copy = new Date(date1.setHours(0, 0, 0, 0));
|
|
589
|
+
const date2Copy = new Date(date2.setHours(0, 0, 0, 0));
|
|
590
|
+
return date1Copy.getTime() === date2Copy.getTime();
|
|
591
|
+
};
|
|
592
|
+
const formatDateDMA = (date) => {
|
|
593
|
+
return new Date(date).toLocaleDateString('es-CO', {
|
|
594
|
+
year: 'numeric',
|
|
595
|
+
month: '2-digit',
|
|
596
|
+
day: '2-digit'
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
// Crea una funcion que tambien muestre la hora
|
|
600
|
+
const formatDateDMAWithTime = (date) => {
|
|
601
|
+
return new Date(date).toLocaleDateString('es-CO', {
|
|
602
|
+
year: 'numeric',
|
|
603
|
+
month: '2-digit',
|
|
604
|
+
day: '2-digit',
|
|
605
|
+
hour: '2-digit',
|
|
606
|
+
minute: '2-digit'
|
|
607
|
+
});
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Enum con los tipos de archivos más relevantes para la aplicación
|
|
612
|
+
*/
|
|
613
|
+
var EFileType;
|
|
614
|
+
(function (EFileType) {
|
|
615
|
+
// Documentos
|
|
616
|
+
EFileType["PDF"] = "application/pdf";
|
|
617
|
+
EFileType["DOC"] = "application/msword";
|
|
618
|
+
EFileType["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
619
|
+
EFileType["XLS"] = "application/vnd.ms-excel";
|
|
620
|
+
EFileType["XLSX"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
621
|
+
EFileType["PPT"] = "application/vnd.ms-powerpoint";
|
|
622
|
+
EFileType["PPTX"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
623
|
+
EFileType["TXT"] = "text/plain";
|
|
624
|
+
EFileType["RTF"] = "application/rtf";
|
|
625
|
+
// Imágenes
|
|
626
|
+
EFileType["JPG"] = "image/jpeg";
|
|
627
|
+
EFileType["PNG"] = "image/png";
|
|
628
|
+
EFileType["GIF"] = "image/gif";
|
|
629
|
+
EFileType["BMP"] = "image/bmp";
|
|
630
|
+
EFileType["SVG"] = "image/svg+xml";
|
|
631
|
+
EFileType["WEBP"] = "image/webp";
|
|
632
|
+
// Archivos comprimidos
|
|
633
|
+
EFileType["ZIP"] = "application/zip";
|
|
634
|
+
EFileType["RAR"] = "application/vnd.rar";
|
|
635
|
+
EFileType["TAR"] = "application/x-tar";
|
|
636
|
+
EFileType["GZ"] = "application/gzip";
|
|
637
|
+
// Archivos de datos
|
|
638
|
+
EFileType["CSV"] = "text/csv";
|
|
639
|
+
EFileType["JSON"] = "application/json";
|
|
640
|
+
EFileType["XML"] = "application/xml";
|
|
641
|
+
// Archivos de audio
|
|
642
|
+
EFileType["MP3"] = "audio/mpeg";
|
|
643
|
+
EFileType["WAV"] = "audio/wav";
|
|
644
|
+
EFileType["OGG"] = "audio/ogg";
|
|
645
|
+
// Archivos de video
|
|
646
|
+
EFileType["MP4"] = "video/mp4";
|
|
647
|
+
EFileType["AVI"] = "video/x-msvideo";
|
|
648
|
+
EFileType["MOV"] = "video/quicktime";
|
|
649
|
+
EFileType["WMV"] = "video/x-ms-wmv";
|
|
650
|
+
// Todos los tipos de imagen
|
|
651
|
+
EFileType["ALL_IMAGES"] = "image/*";
|
|
652
|
+
// Todos los tipos de documento
|
|
653
|
+
EFileType["ALL_DOCUMENTS"] = "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,application/rtf";
|
|
654
|
+
// Todos los tipos de archivo
|
|
655
|
+
EFileType["ALL_FILES"] = "*/*";
|
|
656
|
+
})(EFileType || (EFileType = {}));
|
|
657
|
+
/**
|
|
658
|
+
* Método mejorado para abrir el selector de archivos
|
|
659
|
+
* @param options - Opciones para configurar el input de archivo
|
|
660
|
+
*/
|
|
661
|
+
const triggerFileInput = (options = {}) => {
|
|
662
|
+
const { accept = EFileType.ALL_FILES, multiple = false, onFileSelected } = options;
|
|
663
|
+
const input = document.createElement('input');
|
|
664
|
+
input.type = 'file';
|
|
665
|
+
input.accept = accept;
|
|
666
|
+
input.multiple = multiple;
|
|
667
|
+
input.style.display = 'none';
|
|
668
|
+
input.onchange = (event) => {
|
|
669
|
+
const target = event.target;
|
|
670
|
+
const files = target.files;
|
|
671
|
+
if (files && files.length > 0 && onFileSelected) {
|
|
672
|
+
if (multiple) {
|
|
673
|
+
// Si es múltiple, llamar al callback con todos los archivos
|
|
674
|
+
Array.from(files).forEach(file => {
|
|
675
|
+
onFileSelected(file);
|
|
676
|
+
});
|
|
570
677
|
}
|
|
571
678
|
else {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
this.hideDuplicateAlert();
|
|
679
|
+
// Si es único, llamar al callback con el primer archivo
|
|
680
|
+
const file = files[0];
|
|
681
|
+
onFileSelected(file);
|
|
576
682
|
}
|
|
577
683
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
if (this.duplicateMessageTimer) {
|
|
592
|
-
clearTimeout(this.duplicateMessageTimer);
|
|
593
|
-
}
|
|
594
|
-
// Ocultar mensaje después de 3 segundos
|
|
595
|
-
this.duplicateMessageTimer = setTimeout(() => {
|
|
596
|
-
this.hideDuplicateAlert();
|
|
597
|
-
}, 3000);
|
|
598
|
-
}
|
|
599
|
-
hideDuplicateAlert() {
|
|
600
|
-
this.showDuplicateMessage = false;
|
|
601
|
-
this.duplicateChips = [];
|
|
602
|
-
if (this.duplicateMessageTimer) {
|
|
603
|
-
clearTimeout(this.duplicateMessageTimer);
|
|
604
|
-
this.duplicateMessageTimer = null;
|
|
684
|
+
document.body.removeChild(input);
|
|
685
|
+
};
|
|
686
|
+
document.body.appendChild(input);
|
|
687
|
+
input.click();
|
|
688
|
+
};
|
|
689
|
+
/**
|
|
690
|
+
* Función para capturar una foto usando la cámara
|
|
691
|
+
*/
|
|
692
|
+
const capturePhotoFromCamera = async (options = {}) => {
|
|
693
|
+
const { quality = 0.9, facingMode = 'environment', onPhotoTaken, onError } = options;
|
|
694
|
+
try {
|
|
695
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
696
|
+
throw new Error('Cámara no soportada en este navegador');
|
|
605
697
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
698
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
699
|
+
video: { facingMode }
|
|
700
|
+
});
|
|
701
|
+
const video = document.createElement('video');
|
|
702
|
+
const canvas = document.createElement('canvas');
|
|
703
|
+
const context = canvas.getContext('2d');
|
|
704
|
+
// Crear modal
|
|
705
|
+
const modal = document.createElement('div');
|
|
706
|
+
modal.style.cssText = `
|
|
707
|
+
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
708
|
+
background: rgba(0,0,0,0.9); display: flex; flex-direction: column;
|
|
709
|
+
align-items: center; justify-content: center; z-index: 10000;
|
|
710
|
+
`;
|
|
711
|
+
video.style.cssText = 'width: 80%; max-width: 500px; border-radius: 8px;';
|
|
712
|
+
video.srcObject = stream;
|
|
713
|
+
video.autoplay = true;
|
|
714
|
+
video.playsInline = true;
|
|
715
|
+
const buttonsDiv = document.createElement('div');
|
|
716
|
+
buttonsDiv.style.cssText = 'display: flex; gap: 20px; margin-top: 20px;';
|
|
717
|
+
const captureBtn = document.createElement('button');
|
|
718
|
+
captureBtn.textContent = 'Tomar Foto';
|
|
719
|
+
captureBtn.style.cssText = `
|
|
720
|
+
padding: 12px 24px; background: #007bff; color: white;
|
|
721
|
+
border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
|
|
722
|
+
`;
|
|
723
|
+
const cancelBtn = document.createElement('button');
|
|
724
|
+
cancelBtn.textContent = 'Cancelar';
|
|
725
|
+
cancelBtn.style.cssText = `
|
|
726
|
+
padding: 12px 24px; background: #6c757d; color: white;
|
|
727
|
+
border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
|
|
728
|
+
`;
|
|
729
|
+
const cleanup = () => {
|
|
730
|
+
stream.getTracks().forEach(track => track.stop());
|
|
731
|
+
modal.remove();
|
|
732
|
+
};
|
|
733
|
+
captureBtn.onclick = () => {
|
|
734
|
+
canvas.width = video.videoWidth;
|
|
735
|
+
canvas.height = video.videoHeight;
|
|
736
|
+
context.drawImage(video, 0, 0);
|
|
737
|
+
canvas.toBlob((blob) => {
|
|
738
|
+
if (blob && onPhotoTaken) {
|
|
739
|
+
const file = new File([blob], `photo-${Date.now()}.jpg`, { type: 'image/jpeg' });
|
|
740
|
+
onPhotoTaken(file);
|
|
625
741
|
}
|
|
626
|
-
|
|
742
|
+
cleanup();
|
|
743
|
+
}, 'image/jpeg', quality);
|
|
744
|
+
};
|
|
745
|
+
cancelBtn.onclick = cleanup;
|
|
746
|
+
document.addEventListener('keydown', (e) => {
|
|
747
|
+
if (e.key === 'Escape')
|
|
748
|
+
cleanup();
|
|
627
749
|
});
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
if (addedChips > 0) {
|
|
632
|
-
this.updateChipsValue();
|
|
633
|
-
}
|
|
634
|
-
// Mostrar alerta si hubo duplicados
|
|
635
|
-
if (foundDuplicates.length > 0) {
|
|
636
|
-
this.duplicateChips = foundDuplicates;
|
|
637
|
-
this.showDuplicateAlert();
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
this.hideDuplicateAlert();
|
|
641
|
-
}
|
|
750
|
+
buttonsDiv.append(captureBtn, cancelBtn);
|
|
751
|
+
modal.append(video, buttonsDiv);
|
|
752
|
+
document.body.appendChild(modal);
|
|
642
753
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
*/
|
|
647
|
-
setChipsFromArray(chipsArray) {
|
|
648
|
-
if (!Array.isArray(chipsArray)) {
|
|
649
|
-
console.warn('setChipsFromArray: El parámetro debe ser un array de strings');
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
// Filtrar elementos válidos (strings no vacíos)
|
|
653
|
-
const validChips = chipsArray
|
|
654
|
-
.filter(chip => typeof chip === 'string' && chip.trim() !== '')
|
|
655
|
-
.map(chip => chip.trim());
|
|
656
|
-
// Actualizar el array de chips
|
|
657
|
-
this.chips = [...validChips];
|
|
658
|
-
// Limpiar el input actual
|
|
659
|
-
this.currentInput = '';
|
|
660
|
-
// Actualizar el valor del componente
|
|
661
|
-
this.updateChipsValue();
|
|
662
|
-
// Ocultar cualquier mensaje de duplicado
|
|
663
|
-
this.hideDuplicateAlert();
|
|
754
|
+
catch (error) {
|
|
755
|
+
if (onError)
|
|
756
|
+
onError(error);
|
|
664
757
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
758
|
+
};
|
|
759
|
+
var EFileIcons;
|
|
760
|
+
(function (EFileIcons) {
|
|
761
|
+
EFileIcons["FILE"] = "file";
|
|
762
|
+
EFileIcons["IMAGE"] = "image";
|
|
763
|
+
EFileIcons["VIDEO"] = "video";
|
|
764
|
+
EFileIcons["FOLDER"] = "folder";
|
|
765
|
+
EFileIcons["EXCEL"] = "excel";
|
|
766
|
+
EFileIcons["SIGNATURE"] = "signature";
|
|
767
|
+
EFileIcons["CONTRACT"] = "contract";
|
|
768
|
+
EFileIcons["FINGERPRINT"] = "fingerprint";
|
|
769
|
+
EFileIcons["ID_CARD"] = "id_card";
|
|
770
|
+
EFileIcons["FILE_BOX"] = "file_box";
|
|
771
|
+
EFileIcons["SECURE_BUILDING"] = "secure_building";
|
|
772
|
+
EFileIcons["POLICE"] = "police";
|
|
773
|
+
})(EFileIcons || (EFileIcons = {}));
|
|
774
|
+
const DocumentIcon = {
|
|
775
|
+
[EFileIcons.FILE]: 'fa-solid fa-file-lines',
|
|
776
|
+
[EFileIcons.IMAGE]: 'fa-solid fa-file-image',
|
|
777
|
+
[EFileIcons.VIDEO]: 'fa-solid fa-file-video',
|
|
778
|
+
[EFileIcons.FOLDER]: 'fa-solid fa-folder',
|
|
779
|
+
[EFileIcons.EXCEL]: 'fa-solid fa-file-excel',
|
|
780
|
+
[EFileIcons.SIGNATURE]: 'fa-solid fa-signature',
|
|
781
|
+
[EFileIcons.CONTRACT]: 'fa-solid fa-file-contract',
|
|
782
|
+
[EFileIcons.FINGERPRINT]: 'fa-solid fa-fingerprint',
|
|
783
|
+
[EFileIcons.ID_CARD]: 'fa-solid fa-id-card',
|
|
784
|
+
[EFileIcons.SECURE_BUILDING]: 'fa-solid fa-building-shield',
|
|
785
|
+
[EFileIcons.POLICE]: 'fa-solid fa-hand-middle-finger',
|
|
786
|
+
[EFileIcons.FILE_BOX]: 'fa-solid fa-box-archive'
|
|
787
|
+
};
|
|
788
|
+
const downloadFile = (blob, fileName) => {
|
|
789
|
+
const url = window.URL.createObjectURL(blob);
|
|
790
|
+
const link = document.createElement('a');
|
|
791
|
+
link.href = url;
|
|
792
|
+
link.download = fileName;
|
|
793
|
+
document.body.appendChild(link);
|
|
794
|
+
link.click();
|
|
795
|
+
document.body.removeChild(link);
|
|
796
|
+
window.URL.revokeObjectURL(url);
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
//sin uuid, codigo propio
|
|
800
|
+
const generateId = () => {
|
|
801
|
+
return Date.now().toString(36) + Math.random().toString(36).substring(2, 15);
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
const formatNumber = (number) => {
|
|
805
|
+
return new Intl.NumberFormat('es-CO', {
|
|
806
|
+
minimumFractionDigits: 2,
|
|
807
|
+
maximumFractionDigits: 2
|
|
808
|
+
}).format(number);
|
|
809
|
+
};
|
|
810
|
+
const fixedNumber = (number) => {
|
|
811
|
+
return Number(number.toFixed(2));
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
const hasValues = (obj) => {
|
|
815
|
+
return Object.values(obj).some(value => value !== null && value !== undefined);
|
|
816
|
+
};
|
|
817
|
+
/**
|
|
818
|
+
* Elimina las propiedades de un objeto que tengan valores null o undefined.
|
|
819
|
+
* Retorna un nuevo objeto sin mutar el original.
|
|
820
|
+
* @param obj - Objeto del cual se eliminarán las propiedades null/undefined
|
|
821
|
+
* @returns Nuevo objeto sin las propiedades con valores null o undefined
|
|
822
|
+
*/
|
|
823
|
+
const removeNullUndefined = (obj) => {
|
|
824
|
+
const result = {};
|
|
825
|
+
Object.keys(obj).forEach(key => {
|
|
826
|
+
const value = obj[key];
|
|
827
|
+
if (value !== null && value !== undefined) {
|
|
828
|
+
result[key] = value;
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
return result;
|
|
832
|
+
};
|
|
833
|
+
/**
|
|
834
|
+
* Realiza un upsert en un array de strings. Si el string ya existe, no hace nada.
|
|
835
|
+
* Si no existe, lo agrega al array.
|
|
836
|
+
* @param targetArray - Array de strings donde se realizará el upsert
|
|
837
|
+
* @param value - String o array de strings a insertar
|
|
838
|
+
* @returns Array actualizado con los nuevos valores
|
|
839
|
+
*/
|
|
840
|
+
const upsertArrayStrings = (targetArray, value) => {
|
|
841
|
+
// Crear una copia del array original para evitar mutaciones
|
|
842
|
+
const result = [...targetArray];
|
|
843
|
+
// Convertir el valor a array para procesamiento uniforme
|
|
844
|
+
const valuesToInsert = Array.isArray(value) ? value : [value];
|
|
845
|
+
// Procesar cada valor
|
|
846
|
+
valuesToInsert.forEach(stringValue => {
|
|
847
|
+
// Solo agregar si no existe en el array
|
|
848
|
+
if (!result.includes(stringValue)) {
|
|
849
|
+
result.push(stringValue);
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
return result;
|
|
853
|
+
};
|
|
854
|
+
const sameArray = (arr1, arr2) => {
|
|
855
|
+
if (arr1.length !== arr2.length)
|
|
856
|
+
return false;
|
|
857
|
+
const sorted1 = Array.from(arr1).sort();
|
|
858
|
+
const sorted2 = Array.from(arr2).sort();
|
|
859
|
+
return sorted1.every((item, index) => item === sorted2[index]);
|
|
860
|
+
};
|
|
861
|
+
const getOptionByCode = (options, code) => {
|
|
862
|
+
if (!code)
|
|
863
|
+
return undefined;
|
|
864
|
+
return options.find((item) => item.code === code);
|
|
865
|
+
};
|
|
866
|
+
const createEnumeratedList = (items) => {
|
|
867
|
+
if (items.length === 0) {
|
|
868
|
+
return '';
|
|
869
|
+
}
|
|
870
|
+
if (items.length === 1) {
|
|
871
|
+
return `1. ${items[0]}`;
|
|
872
|
+
}
|
|
873
|
+
return items
|
|
874
|
+
.map((item, index) => `${index + 1}. ${item}`)
|
|
875
|
+
.join('\n');
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
class PrimeNgUtil {
|
|
879
|
+
static isPrimeNgSelection(value) {
|
|
880
|
+
return typeof value === 'object' && value !== null && 'name' in value && 'code' in value;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
class InlineInputComponent {
|
|
885
|
+
config = input({ typeInput: ETypeInput.TEXT });
|
|
886
|
+
value = model(null);
|
|
887
|
+
outputValue = output();
|
|
888
|
+
outputBlur = output();
|
|
889
|
+
outputDebounced = output();
|
|
890
|
+
// Capturar templates proyectados desde el componente padre
|
|
891
|
+
templates;
|
|
892
|
+
// Para el manejo de chips
|
|
893
|
+
chips = [];
|
|
894
|
+
currentInput = '';
|
|
895
|
+
showDuplicateMessage = false;
|
|
896
|
+
duplicateChips = [];
|
|
897
|
+
duplicateMessageTimer = null;
|
|
898
|
+
constructor() {
|
|
899
|
+
effect(() => {
|
|
900
|
+
this.outputValue.emit(this.value());
|
|
901
|
+
});
|
|
902
|
+
const value$ = toObservable(this.value);
|
|
903
|
+
value$
|
|
904
|
+
.pipe(debounceTime(300), // <- adjust ms here
|
|
905
|
+
distinctUntilChanged(), // avoid repeats for same value
|
|
906
|
+
takeUntilDestroyed() // auto-cleanup on destroy
|
|
907
|
+
)
|
|
908
|
+
.subscribe(v => this.outputDebounced.emit(v));
|
|
909
|
+
effect(() => {
|
|
910
|
+
this.valueSelect.update((_prev) => {
|
|
911
|
+
const options = this.config()?.selectConfig?.options;
|
|
912
|
+
const currentValue = this.value();
|
|
913
|
+
if (this.isSelection(currentValue))
|
|
914
|
+
return currentValue;
|
|
915
|
+
if (currentValue === null || currentValue === undefined)
|
|
916
|
+
return undefined;
|
|
917
|
+
return options?.find(option => option.code === currentValue);
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
ngOnInit() {
|
|
922
|
+
}
|
|
923
|
+
onChange = () => { };
|
|
924
|
+
onTouched = () => { };
|
|
925
|
+
writeValue(value) {
|
|
926
|
+
this.value.set(value);
|
|
927
|
+
// Si es tipo CHIPS, inicializar los chips desde el valor
|
|
928
|
+
if (this.type === ETypeInput.CHIPS && typeof value === 'string') {
|
|
929
|
+
this.chips = value ? value.split(' ').filter(chip => chip.trim() !== '') : [];
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
registerOnChange(fn) {
|
|
933
|
+
this.onChange = fn;
|
|
934
|
+
}
|
|
935
|
+
registerOnTouched(fn) {
|
|
936
|
+
this.onTouched = fn;
|
|
937
|
+
}
|
|
938
|
+
onChangeValue(value) {
|
|
939
|
+
let nextValue = value;
|
|
940
|
+
if (this.type === ETypeInput.MULTISELECT && Array.isArray(value)) {
|
|
941
|
+
nextValue = value.filter((item) => item != null && this.isSelection(item));
|
|
942
|
+
}
|
|
943
|
+
this.value.set(nextValue);
|
|
944
|
+
this.onChange(nextValue);
|
|
945
|
+
}
|
|
946
|
+
onBlur() {
|
|
947
|
+
this.onTouched();
|
|
948
|
+
this.outputBlur.emit(this.value());
|
|
671
949
|
}
|
|
672
950
|
/**
|
|
673
|
-
*
|
|
951
|
+
* Maneja eventos de teclado para prevenir la navegación de PrimeNG Table
|
|
952
|
+
* cuando se usan las flechas izquierda/derecha dentro del input
|
|
674
953
|
*/
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
954
|
+
onKeyDown(event) {
|
|
955
|
+
// Verificar si son teclas de flecha izquierda o derecha
|
|
956
|
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
|
|
957
|
+
// Detener la propagación del evento hacia el table
|
|
958
|
+
event.stopPropagation();
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
isSelection(value) {
|
|
962
|
+
return PrimeNgUtil.isPrimeNgSelection(value);
|
|
680
963
|
}
|
|
681
964
|
/**
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
* @param chipsArray Array de strings a agregar
|
|
965
|
+
* Normaliza el valor del multiselect: PrimeNG ColumnFilter devuelve string[] (name/code)
|
|
966
|
+
* pero p-multiselect espera IPrimeNgSelection[] cuando las options son objetos.
|
|
685
967
|
*/
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
968
|
+
multiSelectValue = computed(() => {
|
|
969
|
+
return this.normalizeMultiSelectValue(this.value());
|
|
970
|
+
});
|
|
971
|
+
normalizeMultiSelectValue(value) {
|
|
972
|
+
if (value == null) {
|
|
973
|
+
return [];
|
|
690
974
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
this.chips.push(chipText);
|
|
701
|
-
addedChips++;
|
|
975
|
+
if (!Array.isArray(value)) {
|
|
976
|
+
return [];
|
|
977
|
+
}
|
|
978
|
+
const options = this.config()?.multiSelectConfig?.options ?? [];
|
|
979
|
+
return value
|
|
980
|
+
.filter((item) => item != null && item !== '')
|
|
981
|
+
.map((item) => {
|
|
982
|
+
if (this.isSelection(item)) {
|
|
983
|
+
return item;
|
|
702
984
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
if (!foundDuplicates.includes(chipText)) {
|
|
706
|
-
foundDuplicates.push(chipText);
|
|
707
|
-
}
|
|
985
|
+
if (typeof item === 'string') {
|
|
986
|
+
return options.find((option) => option.code === item || option.name === item);
|
|
708
987
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
988
|
+
return undefined;
|
|
989
|
+
})
|
|
990
|
+
.filter((item) => !!item);
|
|
991
|
+
}
|
|
992
|
+
valueSelect = signal(undefined);
|
|
993
|
+
setValueSelect(value) {
|
|
994
|
+
this.valueSelect.set(value);
|
|
995
|
+
}
|
|
996
|
+
get type() {
|
|
997
|
+
return this.config()?.typeInput ?? ETypeInput.TEXT;
|
|
998
|
+
}
|
|
999
|
+
get ETypeInput() {
|
|
1000
|
+
return ETypeInput;
|
|
1001
|
+
}
|
|
1002
|
+
get duplicatesText() {
|
|
1003
|
+
return this.duplicateChips.join(', ');
|
|
1004
|
+
}
|
|
1005
|
+
get currency() {
|
|
1006
|
+
return this.config()?.currencyConfig?.currency ?? 'COP';
|
|
1007
|
+
}
|
|
1008
|
+
get locale() {
|
|
1009
|
+
return this.config()?.currencyConfig?.locale ?? 'es-CO';
|
|
1010
|
+
}
|
|
1011
|
+
get minFractionDigits() {
|
|
1012
|
+
return this.config()?.currencyConfig?.minFractionDigits ?? 2;
|
|
1013
|
+
}
|
|
1014
|
+
get maxFractionDigits() {
|
|
1015
|
+
return this.config()?.currencyConfig?.maxFractionDigits ?? 2;
|
|
1016
|
+
}
|
|
1017
|
+
knobValueInput = computed(() => {
|
|
1018
|
+
let response = this.value();
|
|
1019
|
+
const knobConfig = this.config()?.knobConfig ?? { min: 0, max: 100, step: 1 };
|
|
1020
|
+
response = parseInt(this.value()) ?? 0;
|
|
1021
|
+
if (response < (knobConfig?.min ?? 0)) {
|
|
1022
|
+
response = knobConfig.min ?? 0;
|
|
1023
|
+
}
|
|
1024
|
+
if (response > (knobConfig?.max ?? 100)) {
|
|
1025
|
+
response = knobConfig.max ?? 100;
|
|
1026
|
+
}
|
|
1027
|
+
return response;
|
|
1028
|
+
});
|
|
1029
|
+
knobValueTemplate = computed(() => {
|
|
1030
|
+
return this.config()?.knobConfig?.valueTemplate ?? '';
|
|
1031
|
+
});
|
|
1032
|
+
// Métodos para manejo de chips
|
|
1033
|
+
onChipInputChange(event) {
|
|
1034
|
+
const target = event.target;
|
|
1035
|
+
this.currentInput = target.value;
|
|
1036
|
+
}
|
|
1037
|
+
onChipKeydown(event) {
|
|
1038
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
1039
|
+
event.preventDefault();
|
|
1040
|
+
this.addChip();
|
|
1041
|
+
}
|
|
1042
|
+
else if (event.key === 'Backspace' && this.currentInput === '' && this.chips.length > 0) {
|
|
1043
|
+
// Si no hay texto y hay chips, eliminar el último chip
|
|
1044
|
+
this.removeChip(this.chips.length - 1);
|
|
1045
|
+
}
|
|
1046
|
+
// No interceptar las flechas aquí ya que se maneja en onKeyDown
|
|
1047
|
+
}
|
|
1048
|
+
onChipPaste(event) {
|
|
1049
|
+
event.preventDefault();
|
|
1050
|
+
const pastedText = event.clipboardData?.getData('text') || '';
|
|
1051
|
+
this.processPastedText(pastedText);
|
|
1052
|
+
}
|
|
1053
|
+
addChip() {
|
|
1054
|
+
const trimmedValue = this.currentInput.trim();
|
|
1055
|
+
if (trimmedValue) {
|
|
1056
|
+
if (this.chips.includes(trimmedValue)) {
|
|
1057
|
+
// Mostrar mensaje de duplicado con el chip específico
|
|
1058
|
+
this.duplicateChips = [trimmedValue];
|
|
1059
|
+
this.showDuplicateAlert();
|
|
1060
|
+
}
|
|
1061
|
+
else {
|
|
1062
|
+
this.chips.push(trimmedValue);
|
|
1063
|
+
this.currentInput = '';
|
|
1064
|
+
this.updateChipsValue();
|
|
1065
|
+
this.hideDuplicateAlert();
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
removeChip(index) {
|
|
1070
|
+
this.chips.splice(index, 1);
|
|
1071
|
+
this.updateChipsValue();
|
|
1072
|
+
}
|
|
1073
|
+
updateChipsValue() {
|
|
1074
|
+
const chipsValue = this.chips.join(' ');
|
|
1075
|
+
this.value.set(chipsValue);
|
|
1076
|
+
this.onChange(chipsValue);
|
|
1077
|
+
}
|
|
1078
|
+
showDuplicateAlert() {
|
|
1079
|
+
this.showDuplicateMessage = true;
|
|
1080
|
+
// Limpiar timer anterior si existe
|
|
1081
|
+
if (this.duplicateMessageTimer) {
|
|
1082
|
+
clearTimeout(this.duplicateMessageTimer);
|
|
1083
|
+
}
|
|
1084
|
+
// Ocultar mensaje después de 3 segundos
|
|
1085
|
+
this.duplicateMessageTimer = setTimeout(() => {
|
|
1086
|
+
this.hideDuplicateAlert();
|
|
1087
|
+
}, 3000);
|
|
1088
|
+
}
|
|
1089
|
+
hideDuplicateAlert() {
|
|
1090
|
+
this.showDuplicateMessage = false;
|
|
1091
|
+
this.duplicateChips = [];
|
|
1092
|
+
if (this.duplicateMessageTimer) {
|
|
1093
|
+
clearTimeout(this.duplicateMessageTimer);
|
|
1094
|
+
this.duplicateMessageTimer = null;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
processPastedText(text) {
|
|
1098
|
+
// Dividir el texto por espacios y filtrar elementos vacíos
|
|
1099
|
+
const newChips = text
|
|
1100
|
+
.split(/\s+/) // Dividir por uno o más espacios
|
|
1101
|
+
.map(chip => chip.trim()) // Limpiar espacios en cada elemento
|
|
1102
|
+
.filter(chip => chip !== ''); // Filtrar elementos vacíos
|
|
1103
|
+
const foundDuplicates = [];
|
|
1104
|
+
let addedChips = 0;
|
|
1105
|
+
// Agregar cada chip nuevo y recopilar duplicados
|
|
1106
|
+
newChips.forEach(chipText => {
|
|
1107
|
+
if (!this.chips.includes(chipText)) {
|
|
1108
|
+
this.chips.push(chipText);
|
|
1109
|
+
addedChips++;
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
// Solo agregar a duplicados si no está ya en la lista
|
|
1113
|
+
if (!foundDuplicates.includes(chipText)) {
|
|
1114
|
+
foundDuplicates.push(chipText);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
// Limpiar el input actual
|
|
1119
|
+
this.currentInput = '';
|
|
1120
|
+
// Actualizar el valor si se agregaron chips
|
|
1121
|
+
if (addedChips > 0) {
|
|
1122
|
+
this.updateChipsValue();
|
|
1123
|
+
}
|
|
1124
|
+
// Mostrar alerta si hubo duplicados
|
|
1125
|
+
if (foundDuplicates.length > 0) {
|
|
1126
|
+
this.duplicateChips = foundDuplicates;
|
|
1127
|
+
this.showDuplicateAlert();
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
this.hideDuplicateAlert();
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Método público para establecer chips desde un array externo
|
|
1135
|
+
* @param chipsArray Array de strings que representan las chips
|
|
1136
|
+
*/
|
|
1137
|
+
setChipsFromArray(chipsArray) {
|
|
1138
|
+
if (!Array.isArray(chipsArray)) {
|
|
1139
|
+
console.warn('setChipsFromArray: El parámetro debe ser un array de strings');
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
// Filtrar elementos válidos (strings no vacíos)
|
|
1143
|
+
const validChips = chipsArray
|
|
1144
|
+
.filter(chip => typeof chip === 'string' && chip.trim() !== '')
|
|
1145
|
+
.map(chip => chip.trim());
|
|
1146
|
+
// Actualizar el array de chips
|
|
1147
|
+
this.chips = [...validChips];
|
|
1148
|
+
// Limpiar el input actual
|
|
1149
|
+
this.currentInput = '';
|
|
1150
|
+
// Actualizar el valor del componente
|
|
1151
|
+
this.updateChipsValue();
|
|
1152
|
+
// Ocultar cualquier mensaje de duplicado
|
|
1153
|
+
this.hideDuplicateAlert();
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Método público para obtener las chips actuales como array
|
|
1157
|
+
* @returns Array de strings con las chips actuales
|
|
1158
|
+
*/
|
|
1159
|
+
getChipsAsArray() {
|
|
1160
|
+
return [...this.chips];
|
|
1161
|
+
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Método público para limpiar todas las chips
|
|
1164
|
+
*/
|
|
1165
|
+
clearAllChips() {
|
|
1166
|
+
this.chips = [];
|
|
1167
|
+
this.currentInput = '';
|
|
1168
|
+
this.updateChipsValue();
|
|
1169
|
+
this.hideDuplicateAlert();
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Método público para agregar múltiples chips desde un array
|
|
1173
|
+
* Evita duplicados y muestra mensajes de alerta si es necesario
|
|
1174
|
+
* @param chipsArray Array de strings a agregar
|
|
1175
|
+
*/
|
|
1176
|
+
addChipsFromArray(chipsArray) {
|
|
1177
|
+
if (!Array.isArray(chipsArray)) {
|
|
1178
|
+
console.warn('addChipsFromArray: El parámetro debe ser un array de strings');
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
// Filtrar elementos válidos
|
|
1182
|
+
const validChips = chipsArray
|
|
1183
|
+
.filter(chip => typeof chip === 'string' && chip.trim() !== '')
|
|
1184
|
+
.map(chip => chip.trim());
|
|
1185
|
+
const foundDuplicates = [];
|
|
1186
|
+
let addedChips = 0;
|
|
1187
|
+
// Agregar cada chip nuevo y recopilar duplicados
|
|
1188
|
+
validChips.forEach(chipText => {
|
|
1189
|
+
if (!this.chips.includes(chipText)) {
|
|
1190
|
+
this.chips.push(chipText);
|
|
1191
|
+
addedChips++;
|
|
1192
|
+
}
|
|
1193
|
+
else {
|
|
1194
|
+
// Solo agregar a duplicados si no está ya en la lista
|
|
1195
|
+
if (!foundDuplicates.includes(chipText)) {
|
|
1196
|
+
foundDuplicates.push(chipText);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
// Actualizar el valor si se agregaron chips
|
|
1201
|
+
if (addedChips > 0) {
|
|
1202
|
+
this.updateChipsValue();
|
|
1203
|
+
}
|
|
1204
|
+
// Mostrar alerta si hubo duplicados
|
|
1205
|
+
if (foundDuplicates.length > 0) {
|
|
1206
|
+
this.duplicateChips = foundDuplicates;
|
|
1207
|
+
this.showDuplicateAlert();
|
|
1208
|
+
}
|
|
1209
|
+
else {
|
|
1210
|
+
this.hideDuplicateAlert();
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
// Limpiar timer al destruir el componente
|
|
1214
|
+
ngOnDestroy() {
|
|
1215
|
+
if (this.duplicateMessageTimer) {
|
|
1216
|
+
clearTimeout(this.duplicateMessageTimer);
|
|
1217
|
+
}
|
|
728
1218
|
}
|
|
729
1219
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InlineInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
730
1220
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: InlineInputComponent, isStandalone: true, selector: "lib-inline-input", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", outputValue: "outputValue", outputBlur: "outputBlur", outputDebounced: "outputDebounced" }, providers: [
|
|
@@ -733,7 +1223,7 @@ class InlineInputComponent {
|
|
|
733
1223
|
useExisting: forwardRef(() => InlineInputComponent),
|
|
734
1224
|
multi: true
|
|
735
1225
|
}
|
|
736
|
-
], queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: "@let valueInput = value();\n@let isDisabled = config().isDisabled ?? false;\n@let knobConfig = config().knobConfig;\n@let textareaConfig = config().textareaConfig;\n@let dateConfig = config().dateConfig;\n\n@switch (type) {\n@case (ETypeInput.CURRENCY) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\n [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DECIMAL) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DATE) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.DATETIME_LOCAL) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.SELECT) {\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\n @for (template of templates; track $index) {\n <ng-template [pTemplate]=\"template.getType()\" let-item>\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\n </ng-template>\n }\n</p-select>\n}\n@case (ETypeInput.MULTISELECT) {\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"valueInput\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [filter]=\"true\"\n appendTo=\"body\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.OTP) {\n<p-inputotp class=\"w-full\" [mask]=\"config().otpConfig?.mask ?? false\" [length]=\"config().otpConfig?.length ?? 6\"\n [integerOnly]=\"config().otpConfig?.integerOnly ?? false\" [ngModel]=\"valueInput\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.KNOB) {\n<p-knob [ngModel]=\"knobValueInput()\" (ngModelChange)=\"onChangeValue($event)\" class=\"w-full\" [min]=\"knobConfig?.min ?? 0\"\n [max]=\"knobConfig?.max ?? 100\" [step]=\"knobConfig?.step ?? 1\" [disabled]=\"isDisabled\" [readonly]=\"true\"\n [valueTemplate]=\"knobValueTemplate()\" [size]=\"knobConfig?.size ?? 100\" />\n}\n@case (ETypeInput.TEXTAREA) {\n<textarea class=\"w-full h-full p-2 border border-gray-300 rounded-md\" pTextarea [rows]=\"textareaConfig?.rows ?? 3\"\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\n [disabled]=\"isDisabled\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (blur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\"></textarea>\n}\n@case (ETypeInput.CHIPS) {\n<div class=\"chips-input-wrapper\">\n <div\n class=\"chips-container w-full p-2 border border-gray-300 rounded-md min-h-[40px] flex flex-wrap items-center gap-2\"\n [class.border-red-500]=\"showDuplicateMessage\">\n @for (chip of chips; track $index) {\n <p-chip [label]=\"chip\" [removable]=\"!isDisabled\" (onRemove)=\"removeChip($index)\" class=\"chip-item\" />\n }\n <input type=\"text\" class=\"chip-input flex-1 border-0 outline-0 bg-transparent min-w-[100px]\" [value]=\"currentInput\"\n (input)=\"onChipInputChange($event)\" (keydown)=\"onChipKeydown($event); onKeyDown($event)\"\n (paste)=\"onChipPaste($event)\" [disabled]=\"isDisabled\"\n placeholder=\"Escribe o pega elementos separados por espacios...\" />\n </div>\n @if (showDuplicateMessage) {\n <div class=\"duplicate-message text-red-500 text-sm mt-1 flex items-center gap-1\">\n <i class=\"pi pi-exclamation-triangle text-red-500\"></i>\n <span>\n @if (duplicateChips.length === 1) {\n El elemento \"<strong>{{ duplicatesText }}</strong>\" ya existe en la lista\n } @else {\n Los elementos \"<strong>{{ duplicatesText }}</strong>\" ya existen en la lista\n }\n </span>\n </div>\n }\n</div>\n}\n@case (ETypeInput.SWITCH) {\n<div class=\"flex justify-center items-center p-2\">\n <p-toggleswitch [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n class=\"w-full\" [disabled]=\"isDisabled\" />\n</div>\n}\n@default {\n<input pInputText class=\"w-full h-full p-2 border border-gray-300 rounded-md\" [type]=\"type\"\n [readOnly]=\"config().readonly ?? false\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\"\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n}", styles: [":host{width:100%;height:100%}.chips-input-wrapper{width:100%}.chips-input-wrapper .chips-container{cursor:text;transition:border-color .2s ease,box-shadow .2s ease}.chips-input-wrapper .chips-container:focus-within{border-color:#007ad9;box-shadow:0 0 0 1px #007ad9}.chips-input-wrapper .chips-container.border-red-500{border-color:#ef4444!important;box-shadow:0 0 0 1px #ef4444!important}.chips-input-wrapper .chips-container .chip-item{margin:0}.chips-input-wrapper .chips-container .chip-input:focus{outline:none}.chips-input-wrapper .chips-container .chip-input::placeholder{color:#6b7280;font-style:italic}.chips-input-wrapper .duplicate-message{animation:slideDown .3s ease-out}.chips-input-wrapper .duplicate-message i{font-size:14px}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}::ng-deep p-select.inline-input-select{border:1px solid #d1d5db!important;background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out;display:flex;align-items:center;justify-content:space-between}::ng-deep p-select.inline-input-select .p-select-label{border:none}::ng-deep p-select.inline-input-select .p-select-trigger{border:none}::ng-deep .my-app-dark p-select.inline-input-select{border:1px solid transparent!important;background:transparent;color:#f3f4f6}::ng-deep .my-app-dark p-inputnumber .p-inputnumber-input{background-color:#374151;color:#f3f4f6;border-color:transparent}::ng-deep .my-app-dark p-datepicker .p-inputtext{background-color:#374151;color:#f3f4f6}::ng-deep .my-app-dark p-multiselect .p-multiselect-label{background-color:#374151;color:#f3f4f6}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2$1.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i2.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "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", "size", "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: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: InputMaskModule }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i8.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: InputOtpModule }, { kind: "component", type: i6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["invalid", "disabled", "readonly", "variant", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: KnobModule }, { kind: "component", type: i9$1.Knob, selector: "p-knob", inputs: ["styleClass", "style", "ariaLabel", "ariaLabelledBy", "tabindex", "valueColor", "rangeColor", "textColor", "valueTemplate", "name", "size", "step", "min", "max", "strokeWidth", "disabled", "showValue", "readonly"], outputs: ["onChange"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i9.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i11.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "style", "styleClass", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i7.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["style", "styleClass", "tabindex", "inputId", "name", "disabled", "readonly", "trueValue", "falseValue", "ariaLabel", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1226
|
+
], queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: "@let valueInput = value();\n@let isDisabled = config().isDisabled ?? false;\n@let knobConfig = config().knobConfig;\n@let textareaConfig = config().textareaConfig;\n@let dateConfig = config().dateConfig;\n\n@switch (type) {\n@case (ETypeInput.CURRENCY) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\n [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DECIMAL) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DATE) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.DATETIME_LOCAL) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.SELECT) {\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\n @for (template of templates; track $index) {\n <ng-template [pTemplate]=\"template.getType()\" let-item>\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\n </ng-template>\n }\n</p-select>\n}\n@case (ETypeInput.MULTISELECT) {\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"multiSelectValue()\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [filter]=\"true\"\n appendTo=\"body\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.OTP) {\n<p-inputotp class=\"w-full\" [mask]=\"config().otpConfig?.mask ?? false\" [length]=\"config().otpConfig?.length ?? 6\"\n [integerOnly]=\"config().otpConfig?.integerOnly ?? false\" [ngModel]=\"valueInput\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.KNOB) {\n<p-knob [ngModel]=\"knobValueInput()\" (ngModelChange)=\"onChangeValue($event)\" class=\"w-full\" [min]=\"knobConfig?.min ?? 0\"\n [max]=\"knobConfig?.max ?? 100\" [step]=\"knobConfig?.step ?? 1\" [disabled]=\"isDisabled\" [readonly]=\"true\"\n [valueTemplate]=\"knobValueTemplate()\" [size]=\"knobConfig?.size ?? 100\" />\n}\n@case (ETypeInput.TEXTAREA) {\n<textarea class=\"w-full h-full p-2 border border-gray-300 rounded-md\" pTextarea [rows]=\"textareaConfig?.rows ?? 3\"\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\n [disabled]=\"isDisabled\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (blur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\"></textarea>\n}\n@case (ETypeInput.CHIPS) {\n<div class=\"chips-input-wrapper\">\n <div\n class=\"chips-container w-full p-2 border border-gray-300 rounded-md min-h-[40px] flex flex-wrap items-center gap-2\"\n [class.border-red-500]=\"showDuplicateMessage\">\n @for (chip of chips; track $index) {\n <p-chip [label]=\"chip\" [removable]=\"!isDisabled\" (onRemove)=\"removeChip($index)\" class=\"chip-item\" />\n }\n <input type=\"text\" class=\"chip-input flex-1 border-0 outline-0 bg-transparent min-w-[100px]\" [value]=\"currentInput\"\n (input)=\"onChipInputChange($event)\" (keydown)=\"onChipKeydown($event); onKeyDown($event)\"\n (paste)=\"onChipPaste($event)\" [disabled]=\"isDisabled\"\n placeholder=\"Escribe o pega elementos separados por espacios...\" />\n </div>\n @if (showDuplicateMessage) {\n <div class=\"duplicate-message text-red-500 text-sm mt-1 flex items-center gap-1\">\n <i class=\"pi pi-exclamation-triangle text-red-500\"></i>\n <span>\n @if (duplicateChips.length === 1) {\n El elemento \"<strong>{{ duplicatesText }}</strong>\" ya existe en la lista\n } @else {\n Los elementos \"<strong>{{ duplicatesText }}</strong>\" ya existen en la lista\n }\n </span>\n </div>\n }\n</div>\n}\n@case (ETypeInput.SWITCH) {\n<div class=\"flex justify-center items-center p-2\">\n <p-toggleswitch [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n class=\"w-full\" [disabled]=\"isDisabled\" />\n</div>\n}\n@default {\n<input pInputText class=\"w-full h-full p-2 border border-gray-300 rounded-md\" [type]=\"type\"\n [readOnly]=\"config().readonly ?? false\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\"\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n}", styles: [":host{width:100%;height:100%}.chips-input-wrapper{width:100%}.chips-input-wrapper .chips-container{cursor:text;transition:border-color .2s ease,box-shadow .2s ease}.chips-input-wrapper .chips-container:focus-within{border-color:#007ad9;box-shadow:0 0 0 1px #007ad9}.chips-input-wrapper .chips-container.border-red-500{border-color:#ef4444!important;box-shadow:0 0 0 1px #ef4444!important}.chips-input-wrapper .chips-container .chip-item{margin:0}.chips-input-wrapper .chips-container .chip-input:focus{outline:none}.chips-input-wrapper .chips-container .chip-input::placeholder{color:#6b7280;font-style:italic}.chips-input-wrapper .duplicate-message{animation:slideDown .3s ease-out}.chips-input-wrapper .duplicate-message i{font-size:14px}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}::ng-deep p-select.inline-input-select{border:1px solid #d1d5db!important;background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out;display:flex;align-items:center;justify-content:space-between}::ng-deep p-select.inline-input-select .p-select-label{border:none}::ng-deep p-select.inline-input-select .p-select-trigger{border:none}::ng-deep .my-app-dark p-select.inline-input-select{border:1px solid transparent!important;background:transparent;color:#f3f4f6}::ng-deep .my-app-dark p-inputnumber .p-inputnumber-input{background-color:#374151;color:#f3f4f6;border-color:transparent}::ng-deep .my-app-dark p-datepicker .p-inputtext{background-color:#374151;color:#f3f4f6}::ng-deep .my-app-dark p-multiselect .p-multiselect-label{background-color:#374151;color:#f3f4f6}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i2$1.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i2.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "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", "size", "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: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "size", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "fluid", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i3.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: InputMaskModule }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i8.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "style", "placeholder", "size", "maxlength", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "name", "required", "autocomplete", "min", "max", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "step", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "variant", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus", "disabled", "fluid"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: InputOtpModule }, { kind: "component", type: i6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["invalid", "disabled", "readonly", "variant", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: KnobModule }, { kind: "component", type: i9$1.Knob, selector: "p-knob", inputs: ["styleClass", "style", "ariaLabel", "ariaLabelledBy", "tabindex", "valueColor", "rangeColor", "textColor", "valueTemplate", "name", "size", "step", "min", "max", "strokeWidth", "disabled", "showValue", "readonly"], outputs: ["onChange"] }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i9.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "variant", "fluid", "pSize"], outputs: ["onResize"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i11.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "style", "styleClass", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i7.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["style", "styleClass", "tabindex", "inputId", "name", "disabled", "readonly", "trueValue", "falseValue", "ariaLabel", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
737
1227
|
}
|
|
738
1228
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: InlineInputComponent, decorators: [{
|
|
739
1229
|
type: Component,
|
|
@@ -757,7 +1247,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
757
1247
|
useExisting: forwardRef(() => InlineInputComponent),
|
|
758
1248
|
multi: true
|
|
759
1249
|
}
|
|
760
|
-
], template: "@let valueInput = value();\n@let isDisabled = config().isDisabled ?? false;\n@let knobConfig = config().knobConfig;\n@let textareaConfig = config().textareaConfig;\n@let dateConfig = config().dateConfig;\n\n@switch (type) {\n@case (ETypeInput.CURRENCY) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\n [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DECIMAL) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DATE) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.DATETIME_LOCAL) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.SELECT) {\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\n @for (template of templates; track $index) {\n <ng-template [pTemplate]=\"template.getType()\" let-item>\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\n </ng-template>\n }\n</p-select>\n}\n@case (ETypeInput.MULTISELECT) {\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"
|
|
1250
|
+
], template: "@let valueInput = value();\n@let isDisabled = config().isDisabled ?? false;\n@let knobConfig = config().knobConfig;\n@let textareaConfig = config().textareaConfig;\n@let dateConfig = config().dateConfig;\n\n@switch (type) {\n@case (ETypeInput.CURRENCY) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"currency\" [currency]=\"currency\" [locale]=\"locale\"\n [minFractionDigits]=\"minFractionDigits\" [maxFractionDigits]=\"maxFractionDigits\" class=\"w-full\"\n [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DECIMAL) {\n<p-inputnumber [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" mode=\"decimal\" [locale]=\"locale\" [minFractionDigits]=\"2\" [maxFractionDigits]=\"2\"\n [useGrouping]=\"true\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.DATE) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [disabled]=\"isDisabled\" [maxDate]=\"dateConfig?.maxDate || null\"\n [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.DATETIME_LOCAL) {\n<p-datepicker [ngModel]=\"valueInput\" appendTo=\"body\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\" class=\"w-full\" [showTime]=\"true\" [hourFormat]=\"'24'\" [disabled]=\"isDisabled\"\n [maxDate]=\"dateConfig?.maxDate || null\" [minDate]=\"dateConfig?.minDate || null\" [selectionMode]=\"dateConfig?.selectionMode || 'single'\" />\n}\n@case (ETypeInput.SELECT) {\n<p-select [options]=\"config().selectConfig?.options ?? []\" [optionLabel]=\"config().selectConfig?.optionLabel ?? 'name'\"\n [(ngModel)]=\"valueSelect\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\"\n appendTo=\"body\" class=\"w-full inline-input-select\" [disabled]=\"config().isDisabled ?? false\" >\n @for (template of templates; track $index) {\n <ng-template [pTemplate]=\"template.getType()\" let-item>\n <ng-container *ngTemplateOutlet=\"template.template; context: { $implicit: item }\"></ng-container>\n </ng-template>\n }\n</p-select>\n}\n@case (ETypeInput.MULTISELECT) {\n<p-multiselect [options]=\"config().multiSelectConfig?.options ?? []\"\n [optionLabel]=\"config().multiSelectConfig?.optionLabel ?? 'name'\" [ngModel]=\"multiSelectValue()\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [filter]=\"true\"\n appendTo=\"body\" class=\"w-full\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.OTP) {\n<p-inputotp class=\"w-full\" [mask]=\"config().otpConfig?.mask ?? false\" [length]=\"config().otpConfig?.length ?? 6\"\n [integerOnly]=\"config().otpConfig?.integerOnly ?? false\" [ngModel]=\"valueInput\"\n (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n@case (ETypeInput.KNOB) {\n<p-knob [ngModel]=\"knobValueInput()\" (ngModelChange)=\"onChangeValue($event)\" class=\"w-full\" [min]=\"knobConfig?.min ?? 0\"\n [max]=\"knobConfig?.max ?? 100\" [step]=\"knobConfig?.step ?? 1\" [disabled]=\"isDisabled\" [readonly]=\"true\"\n [valueTemplate]=\"knobValueTemplate()\" [size]=\"knobConfig?.size ?? 100\" />\n}\n@case (ETypeInput.TEXTAREA) {\n<textarea class=\"w-full h-full p-2 border border-gray-300 rounded-md\" pTextarea [rows]=\"textareaConfig?.rows ?? 3\"\n [cols]=\"textareaConfig?.cols ?? 30\" [autoResize]=\"true\" [variant]=\"textareaConfig?.variant ?? 'outlined'\"\n [disabled]=\"isDisabled\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (blur)=\"onBlur()\"\n (keydown)=\"onKeyDown($event)\"></textarea>\n}\n@case (ETypeInput.CHIPS) {\n<div class=\"chips-input-wrapper\">\n <div\n class=\"chips-container w-full p-2 border border-gray-300 rounded-md min-h-[40px] flex flex-wrap items-center gap-2\"\n [class.border-red-500]=\"showDuplicateMessage\">\n @for (chip of chips; track $index) {\n <p-chip [label]=\"chip\" [removable]=\"!isDisabled\" (onRemove)=\"removeChip($index)\" class=\"chip-item\" />\n }\n <input type=\"text\" class=\"chip-input flex-1 border-0 outline-0 bg-transparent min-w-[100px]\" [value]=\"currentInput\"\n (input)=\"onChipInputChange($event)\" (keydown)=\"onChipKeydown($event); onKeyDown($event)\"\n (paste)=\"onChipPaste($event)\" [disabled]=\"isDisabled\"\n placeholder=\"Escribe o pega elementos separados por espacios...\" />\n </div>\n @if (showDuplicateMessage) {\n <div class=\"duplicate-message text-red-500 text-sm mt-1 flex items-center gap-1\">\n <i class=\"pi pi-exclamation-triangle text-red-500\"></i>\n <span>\n @if (duplicateChips.length === 1) {\n El elemento \"<strong>{{ duplicatesText }}</strong>\" ya existe en la lista\n } @else {\n Los elementos \"<strong>{{ duplicatesText }}</strong>\" ya existen en la lista\n }\n </span>\n </div>\n }\n</div>\n}\n@case (ETypeInput.SWITCH) {\n<div class=\"flex justify-center items-center p-2\">\n <p-toggleswitch [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\" (onBlur)=\"onBlur()\"\n class=\"w-full\" [disabled]=\"isDisabled\" />\n</div>\n}\n@default {\n<input pInputText class=\"w-full h-full p-2 border border-gray-300 rounded-md\" [type]=\"type\"\n [readOnly]=\"config().readonly ?? false\" [ngModel]=\"valueInput\" (ngModelChange)=\"onChangeValue($event)\"\n (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled\" />\n}\n}", styles: [":host{width:100%;height:100%}.chips-input-wrapper{width:100%}.chips-input-wrapper .chips-container{cursor:text;transition:border-color .2s ease,box-shadow .2s ease}.chips-input-wrapper .chips-container:focus-within{border-color:#007ad9;box-shadow:0 0 0 1px #007ad9}.chips-input-wrapper .chips-container.border-red-500{border-color:#ef4444!important;box-shadow:0 0 0 1px #ef4444!important}.chips-input-wrapper .chips-container .chip-item{margin:0}.chips-input-wrapper .chips-container .chip-input:focus{outline:none}.chips-input-wrapper .chips-container .chip-input::placeholder{color:#6b7280;font-style:italic}.chips-input-wrapper .duplicate-message{animation:slideDown .3s ease-out}.chips-input-wrapper .duplicate-message i{font-size:14px}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}::ng-deep p-select.inline-input-select{border:1px solid #d1d5db!important;background:transparent;color:#111827;height:44px;width:100%;border-radius:.5rem;transition:all .2s ease-in-out;display:flex;align-items:center;justify-content:space-between}::ng-deep p-select.inline-input-select .p-select-label{border:none}::ng-deep p-select.inline-input-select .p-select-trigger{border:none}::ng-deep .my-app-dark p-select.inline-input-select{border:1px solid transparent!important;background:transparent;color:#f3f4f6}::ng-deep .my-app-dark p-inputnumber .p-inputnumber-input{background-color:#374151;color:#f3f4f6;border-color:transparent}::ng-deep .my-app-dark p-datepicker .p-inputtext{background-color:#374151;color:#f3f4f6}::ng-deep .my-app-dark p-multiselect .p-multiselect-label{background-color:#374151;color:#f3f4f6}\n"] }]
|
|
761
1251
|
}], ctorParameters: () => [], propDecorators: { templates: [{
|
|
762
1252
|
type: ContentChildren,
|
|
763
1253
|
args: [PrimeTemplate]
|
|
@@ -870,668 +1360,210 @@ class SpeedDialService {
|
|
|
870
1360
|
this._panelLeft.set(`${rect.left - offsetLeft}px`);
|
|
871
1361
|
break;
|
|
872
1362
|
case 'left':
|
|
873
|
-
this._panelTop.set(`${rect.top - offsetTop}px`);
|
|
874
|
-
this._panelLeft.set(`${rect.left - offsetLeft - this.panelOffset}px`);
|
|
875
|
-
break;
|
|
876
|
-
case 'right':
|
|
877
|
-
this._panelTop.set(`${rect.top - offsetTop}px`);
|
|
878
|
-
this._panelLeft.set(`${rect.right - offsetLeft + this.panelOffset}px`);
|
|
879
|
-
break;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
/**
|
|
883
|
-
* Detecta el ancestro que actúa como containing block para elementos fixed.
|
|
884
|
-
* Si existe (por transform/filter/contain/etc), el panel debe posicionarse
|
|
885
|
-
* relativo a ese contenedor y no al viewport.
|
|
886
|
-
*/
|
|
887
|
-
getFixedContainingBlock(element) {
|
|
888
|
-
let current = element.parentElement;
|
|
889
|
-
while (current) {
|
|
890
|
-
const styles = window.getComputedStyle(current);
|
|
891
|
-
const hasTransformContext = styles.transform !== 'none' ||
|
|
892
|
-
styles.perspective !== 'none' ||
|
|
893
|
-
styles.filter !== 'none' ||
|
|
894
|
-
(styles.backdropFilter && styles.backdropFilter !== 'none') ||
|
|
895
|
-
styles.contain.includes('paint') ||
|
|
896
|
-
styles.contain.includes('layout') ||
|
|
897
|
-
styles.willChange.includes('transform') ||
|
|
898
|
-
styles.willChange.includes('filter') ||
|
|
899
|
-
styles.willChange.includes('perspective');
|
|
900
|
-
if (hasTransformContext) {
|
|
901
|
-
return current;
|
|
902
|
-
}
|
|
903
|
-
current = current.parentElement;
|
|
904
|
-
}
|
|
905
|
-
return null;
|
|
906
|
-
}
|
|
907
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
908
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, providedIn: 'root' });
|
|
909
|
-
}
|
|
910
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, decorators: [{
|
|
911
|
-
type: Injectable,
|
|
912
|
-
args: [{
|
|
913
|
-
providedIn: 'root'
|
|
914
|
-
}]
|
|
915
|
-
}], ctorParameters: () => [] });
|
|
916
|
-
|
|
917
|
-
class AppButtonNgService {
|
|
918
|
-
buttonConfig = signal({});
|
|
919
|
-
constructor() {
|
|
920
|
-
// Effect para manejar automáticamente la rotación de mensajes
|
|
921
|
-
effect(() => {
|
|
922
|
-
const config = this.buttonConfig();
|
|
923
|
-
if (config.loading && config.loadingMessages && config.loadingMessages.length > 1) {
|
|
924
|
-
this.startMessageRotation();
|
|
925
|
-
}
|
|
926
|
-
else {
|
|
927
|
-
this.stopMessageRotation();
|
|
928
|
-
}
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
|
-
setButtonConfig(buttonConfig) {
|
|
932
|
-
this.buttonConfig.set(buttonConfig);
|
|
933
|
-
}
|
|
934
|
-
// Computed público para acceder al label dinámico
|
|
935
|
-
label = computed(() => {
|
|
936
|
-
const config = this.buttonConfig();
|
|
937
|
-
// Si está cargando y tiene mensajes de carga, rotar entre ellos
|
|
938
|
-
if (config.loading && config.loadingMessages && config.loadingMessages.length > 0) {
|
|
939
|
-
const messages = config.loadingMessages;
|
|
940
|
-
const index = this.messageIndex() % messages.length; // Wrap around
|
|
941
|
-
return messages[index];
|
|
942
|
-
}
|
|
943
|
-
// Si no está cargando, retornar el label normal
|
|
944
|
-
return config.label ? config.label : '';
|
|
945
|
-
});
|
|
946
|
-
//#region Loading Messages
|
|
947
|
-
messageIndex = signal(0);
|
|
948
|
-
intervalId;
|
|
949
|
-
startMessageRotation() {
|
|
950
|
-
if (this.intervalId)
|
|
951
|
-
return;
|
|
952
|
-
this.intervalId = setInterval(() => {
|
|
953
|
-
this.messageIndex.update(index => index + 1);
|
|
954
|
-
}, 6000);
|
|
955
|
-
}
|
|
956
|
-
stopMessageRotation() {
|
|
957
|
-
if (this.intervalId) {
|
|
958
|
-
clearInterval(this.intervalId);
|
|
959
|
-
this.intervalId = undefined;
|
|
960
|
-
this.messageIndex.set(0);
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
964
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, providedIn: 'root' });
|
|
965
|
-
}
|
|
966
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, decorators: [{
|
|
967
|
-
type: Injectable,
|
|
968
|
-
args: [{
|
|
969
|
-
providedIn: 'root'
|
|
970
|
-
}]
|
|
971
|
-
}], ctorParameters: () => [] });
|
|
972
|
-
|
|
973
|
-
class ButtonNgComponent {
|
|
974
|
-
appButtonNgService = inject(AppButtonNgService);
|
|
975
|
-
buttonConfig = model.required();
|
|
976
|
-
onClick = output();
|
|
977
|
-
constructor() {
|
|
978
|
-
effect(() => {
|
|
979
|
-
this.appButtonNgService.setButtonConfig(this.buttonConfig());
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
get label() {
|
|
983
|
-
return this.appButtonNgService.label();
|
|
984
|
-
}
|
|
985
|
-
onClickButton() {
|
|
986
|
-
if (this.buttonConfig().onClick) {
|
|
987
|
-
return;
|
|
988
|
-
}
|
|
989
|
-
this.onClick.emit();
|
|
990
|
-
}
|
|
991
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
992
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: ButtonNgComponent, isStandalone: true, selector: "lib-button-ng", inputs: { buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { buttonConfig: "buttonConfigChange", onClick: "onClick" }, providers: [AppButtonNgService], ngImport: i0, template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
993
|
-
}
|
|
994
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, decorators: [{
|
|
995
|
-
type: Component,
|
|
996
|
-
args: [{ selector: 'lib-button-ng', imports: [
|
|
997
|
-
ButtonModule,
|
|
998
|
-
TooltipModule,
|
|
999
|
-
CommonModule
|
|
1000
|
-
], providers: [AppButtonNgService], template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"] }]
|
|
1001
|
-
}], ctorParameters: () => [] });
|
|
1002
|
-
|
|
1003
|
-
class SpeedDialComponent {
|
|
1004
|
-
mainButtonContainer;
|
|
1005
|
-
speedDialConfig = input.required();
|
|
1006
|
-
speedDialService = inject(SpeedDialService);
|
|
1007
|
-
constructor() {
|
|
1008
|
-
effect(() => {
|
|
1009
|
-
this.speedDialService.setSpeedDialConfig(this.speedDialConfig());
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
get buttons() {
|
|
1013
|
-
return this.speedDialService.buttons();
|
|
1014
|
-
}
|
|
1015
|
-
get overlayButtons() {
|
|
1016
|
-
return this.speedDialService.overlayButtons();
|
|
1017
|
-
}
|
|
1018
|
-
get mainButton() {
|
|
1019
|
-
return this.speedDialService.mainButton();
|
|
1020
|
-
}
|
|
1021
|
-
get isMenuOpen() {
|
|
1022
|
-
return this.speedDialService.isMenuOpen();
|
|
1023
|
-
}
|
|
1024
|
-
get panelTop() {
|
|
1025
|
-
return this.speedDialService.panelTop();
|
|
1026
|
-
}
|
|
1027
|
-
get panelLeft() {
|
|
1028
|
-
return this.speedDialService.panelLeft();
|
|
1029
|
-
}
|
|
1030
|
-
get direction() {
|
|
1031
|
-
return this.speedDialService.direction();
|
|
1032
|
-
}
|
|
1033
|
-
ngAfterViewInit() {
|
|
1034
|
-
const hostElement = this.mainButtonContainer?.nativeElement;
|
|
1035
|
-
if (!hostElement)
|
|
1036
|
-
return;
|
|
1037
|
-
this.speedDialService.setMainButtonHost(hostElement);
|
|
1038
|
-
}
|
|
1039
|
-
ngOnDestroy() {
|
|
1040
|
-
this.speedDialService.destroy();
|
|
1041
|
-
}
|
|
1042
|
-
closeMenu() {
|
|
1043
|
-
this.speedDialService.closeMenu();
|
|
1044
|
-
}
|
|
1045
|
-
onMainButtonClick(event) {
|
|
1046
|
-
const target = event.target;
|
|
1047
|
-
const anchor = target?.closest('button,[role="button"]');
|
|
1048
|
-
this.speedDialService.toggleMenu(anchor ?? this.mainButtonContainer?.nativeElement);
|
|
1049
|
-
}
|
|
1050
|
-
stopPropagation(event) {
|
|
1051
|
-
event.stopPropagation();
|
|
1052
|
-
}
|
|
1053
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1054
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SpeedDialComponent, isStandalone: true, selector: "lib-speed-dial", inputs: { speedDialConfig: { classPropertyName: "speedDialConfig", publicName: "speedDialConfig", isSignal: true, isRequired: true, transformFunction: null } }, providers: [SpeedDialService], viewQueries: [{ propertyName: "mainButtonContainer", first: true, predicate: ["mainButtonContainer"], descendants: true }], ngImport: i0, template: "<div\r\n #mainButtonContainer\r\n class=\"speed-dial-main-button\"\r\n [class.speed-dial-main-button--open]=\"isMenuOpen\"\r\n (click)=\"onMainButtonClick($event)\"\r\n>\r\n <lib-button-ng [buttonConfig]=\"mainButton\"></lib-button-ng>\r\n</div>\r\n\r\n@if (isMenuOpen) {\r\n <div class=\"speed-dial-overlay\" (click)=\"closeMenu()\">\r\n <div\r\n class=\"speed-dial-panel bg-gray-100 dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg\"\r\n [style.top]=\"panelTop\"\r\n [style.left]=\"panelLeft\"\r\n (click)=\"stopPropagation($event)\"\r\n [ngClass]=\"{\r\n 'speed-dial-panel--top': direction === 'top',\r\n 'speed-dial-panel--bottom': direction === 'bottom',\r\n 'speed-dial-panel--left': direction === 'left',\r\n 'speed-dial-panel--right': direction === 'right'\r\n }\"\r\n >\r\n @for (button of overlayButtons; track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".speed-dial-main-button{display:inline-flex}.speed-dial-main-button--open{position:relative;z-index:2147483647}.speed-dial-overlay{position:fixed;inset:0;z-index:2147483645}.speed-dial-panel{position:fixed;z-index:2147483646;display:flex;gap:.5rem;overflow:auto;padding:.75rem;border-radius:.75rem;background:#fff;box-shadow:0 10px 30px #0f172a40}.speed-dial-panel--top{flex-direction:column;max-width:22rem;max-height:30rem;transform:translateY(-100%)}.speed-dial-panel--bottom{flex-direction:column;max-width:22rem;max-height:30rem}.speed-dial-panel--left{flex-direction:row;max-width:40rem;max-height:8rem;transform:translate(-100%)}.speed-dial-panel--right{flex-direction:row;max-width:40rem;max-height:8rem}:host-context(.dark) .speed-dial-panel{background:#111827}\n"], dependencies: [{ kind: "component", type: ButtonNgComponent, selector: "lib-button-ng", inputs: ["buttonConfig"], outputs: ["buttonConfigChange", "onClick"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
1055
|
-
}
|
|
1056
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialComponent, decorators: [{
|
|
1057
|
-
type: Component,
|
|
1058
|
-
args: [{ selector: 'lib-speed-dial', imports: [ButtonNgComponent, CommonModule], providers: [SpeedDialService], template: "<div\r\n #mainButtonContainer\r\n class=\"speed-dial-main-button\"\r\n [class.speed-dial-main-button--open]=\"isMenuOpen\"\r\n (click)=\"onMainButtonClick($event)\"\r\n>\r\n <lib-button-ng [buttonConfig]=\"mainButton\"></lib-button-ng>\r\n</div>\r\n\r\n@if (isMenuOpen) {\r\n <div class=\"speed-dial-overlay\" (click)=\"closeMenu()\">\r\n <div\r\n class=\"speed-dial-panel bg-gray-100 dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg\"\r\n [style.top]=\"panelTop\"\r\n [style.left]=\"panelLeft\"\r\n (click)=\"stopPropagation($event)\"\r\n [ngClass]=\"{\r\n 'speed-dial-panel--top': direction === 'top',\r\n 'speed-dial-panel--bottom': direction === 'bottom',\r\n 'speed-dial-panel--left': direction === 'left',\r\n 'speed-dial-panel--right': direction === 'right'\r\n }\"\r\n >\r\n @for (button of overlayButtons; track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".speed-dial-main-button{display:inline-flex}.speed-dial-main-button--open{position:relative;z-index:2147483647}.speed-dial-overlay{position:fixed;inset:0;z-index:2147483645}.speed-dial-panel{position:fixed;z-index:2147483646;display:flex;gap:.5rem;overflow:auto;padding:.75rem;border-radius:.75rem;background:#fff;box-shadow:0 10px 30px #0f172a40}.speed-dial-panel--top{flex-direction:column;max-width:22rem;max-height:30rem;transform:translateY(-100%)}.speed-dial-panel--bottom{flex-direction:column;max-width:22rem;max-height:30rem}.speed-dial-panel--left{flex-direction:row;max-width:40rem;max-height:8rem;transform:translate(-100%)}.speed-dial-panel--right{flex-direction:row;max-width:40rem;max-height:8rem}:host-context(.dark) .speed-dial-panel{background:#111827}\n"] }]
|
|
1059
|
-
}], ctorParameters: () => [], propDecorators: { mainButtonContainer: [{
|
|
1060
|
-
type: ViewChild,
|
|
1061
|
-
args: ['mainButtonContainer']
|
|
1062
|
-
}] } });
|
|
1063
|
-
|
|
1064
|
-
class KeyToDisplayNamePipe {
|
|
1065
|
-
transform(key, keysNames) {
|
|
1066
|
-
return keysNames?.[key] ?? key;
|
|
1067
|
-
}
|
|
1068
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1069
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, isStandalone: true, name: "keyToDisplayName" });
|
|
1070
|
-
}
|
|
1071
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, decorators: [{
|
|
1072
|
-
type: Pipe,
|
|
1073
|
-
args: [{
|
|
1074
|
-
name: 'keyToDisplayName'
|
|
1075
|
-
}]
|
|
1076
|
-
}] });
|
|
1077
|
-
|
|
1078
|
-
/**
|
|
1079
|
-
* Utilidades para manejar errores de API según la interfaz IApiError
|
|
1080
|
-
*/
|
|
1081
|
-
class ApiErrorUtil {
|
|
1082
|
-
/**
|
|
1083
|
-
* Procesa errores de API y extrae el mensaje según la interfaz IApiError
|
|
1084
|
-
* @param error - El error HTTP recibido
|
|
1085
|
-
* @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
|
|
1086
|
-
* @returns El mensaje de error procesado
|
|
1087
|
-
*/
|
|
1088
|
-
static handleApiError(error, fallbackMessage) {
|
|
1089
|
-
const apiError = error.error;
|
|
1090
|
-
const errorMessage = Array.isArray(apiError?.message)
|
|
1091
|
-
? apiError.message.join(', ')
|
|
1092
|
-
: apiError?.message ?? fallbackMessage;
|
|
1093
|
-
return errorMessage;
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* Procesa errores de API con información detallada de campos
|
|
1097
|
-
* y muestra tanto el mensaje general como los errores específicos de campo
|
|
1098
|
-
* @param error - El error HTTP recibido
|
|
1099
|
-
* @param fallbackMessage - Mensaje por defecto si no se puede extraer el mensaje del error
|
|
1100
|
-
* @returns El mensaje de error procesado con información de campos si está disponible
|
|
1101
|
-
*/
|
|
1102
|
-
static handleApiErrorWithFields(error, fallbackMessage) {
|
|
1103
|
-
const apiError = error.error;
|
|
1104
|
-
let errorMessage = Array.isArray(apiError?.message)
|
|
1105
|
-
? apiError.message.join(', ')
|
|
1106
|
-
: apiError?.message ?? fallbackMessage;
|
|
1107
|
-
// Si hay errores de campo específicos, los agregamos al mensaje
|
|
1108
|
-
if (apiError?.errors && apiError.errors.length > 0) {
|
|
1109
|
-
const fieldErrors = apiError.errors
|
|
1110
|
-
.map(fieldError => `${fieldError.field}: ${fieldError.message}`)
|
|
1111
|
-
.join(', ');
|
|
1112
|
-
errorMessage = `${errorMessage}. Errores de campos: ${fieldErrors}`;
|
|
1113
|
-
}
|
|
1114
|
-
return errorMessage;
|
|
1115
|
-
}
|
|
1116
|
-
/**
|
|
1117
|
-
* Obtiene solo los errores de campo específicos
|
|
1118
|
-
* @param error - El error HTTP recibido
|
|
1119
|
-
* @returns Array de errores de campo o array vacío si no hay errores
|
|
1120
|
-
*/
|
|
1121
|
-
static getFieldErrors(error) {
|
|
1122
|
-
const apiError = error.error;
|
|
1123
|
-
return apiError?.errors ?? [];
|
|
1124
|
-
}
|
|
1125
|
-
/**
|
|
1126
|
-
* Verifica si el error tiene errores de campo específicos
|
|
1127
|
-
* @param error - El error HTTP recibido
|
|
1128
|
-
* @returns true si hay errores de campo, false en caso contrario
|
|
1129
|
-
*/
|
|
1130
|
-
static hasFieldErrors(error) {
|
|
1131
|
-
const apiError = error.error;
|
|
1132
|
-
return apiError?.errors && apiError.errors.length > 0;
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Obtiene el código de error específico
|
|
1136
|
-
* @param error - El error HTTP recibido
|
|
1137
|
-
* @returns El código de error o undefined si no está disponible
|
|
1138
|
-
*/
|
|
1139
|
-
static getErrorCode(error) {
|
|
1140
|
-
const apiError = error.error;
|
|
1141
|
-
return apiError?.errorCode;
|
|
1142
|
-
}
|
|
1143
|
-
/**
|
|
1144
|
-
* Obtiene el timestamp del error
|
|
1145
|
-
* @param error - El error HTTP recibido
|
|
1146
|
-
* @returns El timestamp del error o undefined si no está disponible
|
|
1147
|
-
*/
|
|
1148
|
-
static getErrorTimestamp(error) {
|
|
1149
|
-
const apiError = error.error;
|
|
1150
|
-
return apiError?.timestamp;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
class CookieUtil {
|
|
1155
|
-
/**
|
|
1156
|
-
* Obtiene el valor de una cookie por su nombre
|
|
1157
|
-
* @param name - Nombre de la cookie
|
|
1158
|
-
* @returns El valor de la cookie o null si no existe
|
|
1159
|
-
*/
|
|
1160
|
-
static getCookie(name) {
|
|
1161
|
-
if (typeof document === 'undefined') {
|
|
1162
|
-
return null;
|
|
1163
|
-
}
|
|
1164
|
-
const nameEQ = name + '=';
|
|
1165
|
-
const ca = document.cookie.split(';');
|
|
1166
|
-
for (let i = 0; i < ca.length; i++) {
|
|
1167
|
-
let c = ca[i];
|
|
1168
|
-
while (c.charAt(0) === ' ') {
|
|
1169
|
-
c = c.substring(1, c.length);
|
|
1170
|
-
}
|
|
1171
|
-
if (c.indexOf(nameEQ) === 0) {
|
|
1172
|
-
return c.substring(nameEQ.length, c.length);
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
return null;
|
|
1176
|
-
}
|
|
1177
|
-
/**
|
|
1178
|
-
* Establece una cookie
|
|
1179
|
-
* @param name - Nombre de la cookie
|
|
1180
|
-
* @param value - Valor de la cookie
|
|
1181
|
-
* @param days - Días hasta que expire (por defecto 365)
|
|
1182
|
-
* @param path - Ruta de la cookie (por defecto '/')
|
|
1183
|
-
*/
|
|
1184
|
-
static setCookie(name, value, days = 365, path = '/') {
|
|
1185
|
-
if (typeof document === 'undefined') {
|
|
1186
|
-
return;
|
|
1187
|
-
}
|
|
1188
|
-
let expires = '';
|
|
1189
|
-
if (days) {
|
|
1190
|
-
const date = new Date();
|
|
1191
|
-
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
1192
|
-
expires = '; expires=' + date.toUTCString();
|
|
1193
|
-
}
|
|
1194
|
-
document.cookie = name + '=' + (value || '') + expires + '; path=' + path;
|
|
1195
|
-
}
|
|
1196
|
-
/**
|
|
1197
|
-
* Elimina una cookie
|
|
1198
|
-
* @param name - Nombre de la cookie a eliminar
|
|
1199
|
-
* @param path - Ruta de la cookie (por defecto '/')
|
|
1200
|
-
*/
|
|
1201
|
-
static eraseCookie(name, path = '/') {
|
|
1202
|
-
if (typeof document === 'undefined') {
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1205
|
-
document.cookie = name + '=; Path=' + path + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
|
1206
|
-
}
|
|
1207
|
-
/**
|
|
1208
|
-
* Obtiene un valor booleano desde una cookie
|
|
1209
|
-
* @param name - Nombre de la cookie
|
|
1210
|
-
* @param defaultValue - Valor por defecto si la cookie no existe
|
|
1211
|
-
* @returns El valor booleano
|
|
1212
|
-
*/
|
|
1213
|
-
static getBooleanCookie(name, defaultValue = false) {
|
|
1214
|
-
const value = this.getCookie(name);
|
|
1215
|
-
if (value === null) {
|
|
1216
|
-
return defaultValue;
|
|
1217
|
-
}
|
|
1218
|
-
return value === 'true';
|
|
1219
|
-
}
|
|
1220
|
-
/**
|
|
1221
|
-
* Establece un valor booleano en una cookie
|
|
1222
|
-
* @param name - Nombre de la cookie
|
|
1223
|
-
* @param value - Valor booleano
|
|
1224
|
-
* @param days - Días hasta que expire (por defecto 365)
|
|
1225
|
-
* @param path - Ruta de la cookie (por defecto '/')
|
|
1226
|
-
*/
|
|
1227
|
-
static setBooleanCookie(name, value, days = 365, path = '/') {
|
|
1228
|
-
this.setCookie(name, value.toString(), days, path);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
const formatCurrency = (amount, currency) => {
|
|
1233
|
-
return new Intl.NumberFormat('es-CO', {
|
|
1234
|
-
style: 'currency',
|
|
1235
|
-
currency: currency || 'COP'
|
|
1236
|
-
}).format(amount);
|
|
1237
|
-
};
|
|
1238
|
-
|
|
1239
|
-
const isSameDay = (date1, date2) => {
|
|
1240
|
-
const date1Copy = new Date(date1.setHours(0, 0, 0, 0));
|
|
1241
|
-
const date2Copy = new Date(date2.setHours(0, 0, 0, 0));
|
|
1242
|
-
return date1Copy.getTime() === date2Copy.getTime();
|
|
1243
|
-
};
|
|
1244
|
-
const formatDateDMA = (date) => {
|
|
1245
|
-
return new Date(date).toLocaleDateString('es-CO', {
|
|
1246
|
-
year: 'numeric',
|
|
1247
|
-
month: '2-digit',
|
|
1248
|
-
day: '2-digit'
|
|
1249
|
-
});
|
|
1250
|
-
};
|
|
1251
|
-
// Crea una funcion que tambien muestre la hora
|
|
1252
|
-
const formatDateDMAWithTime = (date) => {
|
|
1253
|
-
return new Date(date).toLocaleDateString('es-CO', {
|
|
1254
|
-
year: 'numeric',
|
|
1255
|
-
month: '2-digit',
|
|
1256
|
-
day: '2-digit',
|
|
1257
|
-
hour: '2-digit',
|
|
1258
|
-
minute: '2-digit'
|
|
1259
|
-
});
|
|
1260
|
-
};
|
|
1261
|
-
|
|
1262
|
-
/**
|
|
1263
|
-
* Enum con los tipos de archivos más relevantes para la aplicación
|
|
1264
|
-
*/
|
|
1265
|
-
var EFileType;
|
|
1266
|
-
(function (EFileType) {
|
|
1267
|
-
// Documentos
|
|
1268
|
-
EFileType["PDF"] = "application/pdf";
|
|
1269
|
-
EFileType["DOC"] = "application/msword";
|
|
1270
|
-
EFileType["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
1271
|
-
EFileType["XLS"] = "application/vnd.ms-excel";
|
|
1272
|
-
EFileType["XLSX"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
1273
|
-
EFileType["PPT"] = "application/vnd.ms-powerpoint";
|
|
1274
|
-
EFileType["PPTX"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
1275
|
-
EFileType["TXT"] = "text/plain";
|
|
1276
|
-
EFileType["RTF"] = "application/rtf";
|
|
1277
|
-
// Imágenes
|
|
1278
|
-
EFileType["JPG"] = "image/jpeg";
|
|
1279
|
-
EFileType["PNG"] = "image/png";
|
|
1280
|
-
EFileType["GIF"] = "image/gif";
|
|
1281
|
-
EFileType["BMP"] = "image/bmp";
|
|
1282
|
-
EFileType["SVG"] = "image/svg+xml";
|
|
1283
|
-
EFileType["WEBP"] = "image/webp";
|
|
1284
|
-
// Archivos comprimidos
|
|
1285
|
-
EFileType["ZIP"] = "application/zip";
|
|
1286
|
-
EFileType["RAR"] = "application/vnd.rar";
|
|
1287
|
-
EFileType["TAR"] = "application/x-tar";
|
|
1288
|
-
EFileType["GZ"] = "application/gzip";
|
|
1289
|
-
// Archivos de datos
|
|
1290
|
-
EFileType["CSV"] = "text/csv";
|
|
1291
|
-
EFileType["JSON"] = "application/json";
|
|
1292
|
-
EFileType["XML"] = "application/xml";
|
|
1293
|
-
// Archivos de audio
|
|
1294
|
-
EFileType["MP3"] = "audio/mpeg";
|
|
1295
|
-
EFileType["WAV"] = "audio/wav";
|
|
1296
|
-
EFileType["OGG"] = "audio/ogg";
|
|
1297
|
-
// Archivos de video
|
|
1298
|
-
EFileType["MP4"] = "video/mp4";
|
|
1299
|
-
EFileType["AVI"] = "video/x-msvideo";
|
|
1300
|
-
EFileType["MOV"] = "video/quicktime";
|
|
1301
|
-
EFileType["WMV"] = "video/x-ms-wmv";
|
|
1302
|
-
// Todos los tipos de imagen
|
|
1303
|
-
EFileType["ALL_IMAGES"] = "image/*";
|
|
1304
|
-
// Todos los tipos de documento
|
|
1305
|
-
EFileType["ALL_DOCUMENTS"] = "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,application/rtf";
|
|
1306
|
-
// Todos los tipos de archivo
|
|
1307
|
-
EFileType["ALL_FILES"] = "*/*";
|
|
1308
|
-
})(EFileType || (EFileType = {}));
|
|
1309
|
-
/**
|
|
1310
|
-
* Método mejorado para abrir el selector de archivos
|
|
1311
|
-
* @param options - Opciones para configurar el input de archivo
|
|
1312
|
-
*/
|
|
1313
|
-
const triggerFileInput = (options = {}) => {
|
|
1314
|
-
const { accept = EFileType.ALL_FILES, multiple = false, onFileSelected } = options;
|
|
1315
|
-
const input = document.createElement('input');
|
|
1316
|
-
input.type = 'file';
|
|
1317
|
-
input.accept = accept;
|
|
1318
|
-
input.multiple = multiple;
|
|
1319
|
-
input.style.display = 'none';
|
|
1320
|
-
input.onchange = (event) => {
|
|
1321
|
-
const target = event.target;
|
|
1322
|
-
const files = target.files;
|
|
1323
|
-
if (files && files.length > 0 && onFileSelected) {
|
|
1324
|
-
if (multiple) {
|
|
1325
|
-
// Si es múltiple, llamar al callback con todos los archivos
|
|
1326
|
-
Array.from(files).forEach(file => {
|
|
1327
|
-
onFileSelected(file);
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
else {
|
|
1331
|
-
// Si es único, llamar al callback con el primer archivo
|
|
1332
|
-
const file = files[0];
|
|
1333
|
-
onFileSelected(file);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
document.body.removeChild(input);
|
|
1337
|
-
};
|
|
1338
|
-
document.body.appendChild(input);
|
|
1339
|
-
input.click();
|
|
1340
|
-
};
|
|
1341
|
-
/**
|
|
1342
|
-
* Función para capturar una foto usando la cámara
|
|
1343
|
-
*/
|
|
1344
|
-
const capturePhotoFromCamera = async (options = {}) => {
|
|
1345
|
-
const { quality = 0.9, facingMode = 'environment', onPhotoTaken, onError } = options;
|
|
1346
|
-
try {
|
|
1347
|
-
if (!navigator.mediaDevices?.getUserMedia) {
|
|
1348
|
-
throw new Error('Cámara no soportada en este navegador');
|
|
1349
|
-
}
|
|
1350
|
-
const stream = await navigator.mediaDevices.getUserMedia({
|
|
1351
|
-
video: { facingMode }
|
|
1352
|
-
});
|
|
1353
|
-
const video = document.createElement('video');
|
|
1354
|
-
const canvas = document.createElement('canvas');
|
|
1355
|
-
const context = canvas.getContext('2d');
|
|
1356
|
-
// Crear modal
|
|
1357
|
-
const modal = document.createElement('div');
|
|
1358
|
-
modal.style.cssText = `
|
|
1359
|
-
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
1360
|
-
background: rgba(0,0,0,0.9); display: flex; flex-direction: column;
|
|
1361
|
-
align-items: center; justify-content: center; z-index: 10000;
|
|
1362
|
-
`;
|
|
1363
|
-
video.style.cssText = 'width: 80%; max-width: 500px; border-radius: 8px;';
|
|
1364
|
-
video.srcObject = stream;
|
|
1365
|
-
video.autoplay = true;
|
|
1366
|
-
video.playsInline = true;
|
|
1367
|
-
const buttonsDiv = document.createElement('div');
|
|
1368
|
-
buttonsDiv.style.cssText = 'display: flex; gap: 20px; margin-top: 20px;';
|
|
1369
|
-
const captureBtn = document.createElement('button');
|
|
1370
|
-
captureBtn.textContent = 'Tomar Foto';
|
|
1371
|
-
captureBtn.style.cssText = `
|
|
1372
|
-
padding: 12px 24px; background: #007bff; color: white;
|
|
1373
|
-
border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
|
|
1374
|
-
`;
|
|
1375
|
-
const cancelBtn = document.createElement('button');
|
|
1376
|
-
cancelBtn.textContent = 'Cancelar';
|
|
1377
|
-
cancelBtn.style.cssText = `
|
|
1378
|
-
padding: 12px 24px; background: #6c757d; color: white;
|
|
1379
|
-
border: none; border-radius: 6px; cursor: pointer; font-size: 16px;
|
|
1380
|
-
`;
|
|
1381
|
-
const cleanup = () => {
|
|
1382
|
-
stream.getTracks().forEach(track => track.stop());
|
|
1383
|
-
modal.remove();
|
|
1384
|
-
};
|
|
1385
|
-
captureBtn.onclick = () => {
|
|
1386
|
-
canvas.width = video.videoWidth;
|
|
1387
|
-
canvas.height = video.videoHeight;
|
|
1388
|
-
context.drawImage(video, 0, 0);
|
|
1389
|
-
canvas.toBlob((blob) => {
|
|
1390
|
-
if (blob && onPhotoTaken) {
|
|
1391
|
-
const file = new File([blob], `photo-${Date.now()}.jpg`, { type: 'image/jpeg' });
|
|
1392
|
-
onPhotoTaken(file);
|
|
1393
|
-
}
|
|
1394
|
-
cleanup();
|
|
1395
|
-
}, 'image/jpeg', quality);
|
|
1396
|
-
};
|
|
1397
|
-
cancelBtn.onclick = cleanup;
|
|
1398
|
-
document.addEventListener('keydown', (e) => {
|
|
1399
|
-
if (e.key === 'Escape')
|
|
1400
|
-
cleanup();
|
|
1401
|
-
});
|
|
1402
|
-
buttonsDiv.append(captureBtn, cancelBtn);
|
|
1403
|
-
modal.append(video, buttonsDiv);
|
|
1404
|
-
document.body.appendChild(modal);
|
|
1405
|
-
}
|
|
1406
|
-
catch (error) {
|
|
1407
|
-
if (onError)
|
|
1408
|
-
onError(error);
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
var EFileIcons;
|
|
1412
|
-
(function (EFileIcons) {
|
|
1413
|
-
EFileIcons["FILE"] = "file";
|
|
1414
|
-
EFileIcons["IMAGE"] = "image";
|
|
1415
|
-
EFileIcons["VIDEO"] = "video";
|
|
1416
|
-
EFileIcons["FOLDER"] = "folder";
|
|
1417
|
-
EFileIcons["EXCEL"] = "excel";
|
|
1418
|
-
EFileIcons["SIGNATURE"] = "signature";
|
|
1419
|
-
EFileIcons["CONTRACT"] = "contract";
|
|
1420
|
-
EFileIcons["FINGERPRINT"] = "fingerprint";
|
|
1421
|
-
EFileIcons["ID_CARD"] = "id_card";
|
|
1422
|
-
EFileIcons["FILE_BOX"] = "file_box";
|
|
1423
|
-
EFileIcons["SECURE_BUILDING"] = "secure_building";
|
|
1424
|
-
EFileIcons["POLICE"] = "police";
|
|
1425
|
-
})(EFileIcons || (EFileIcons = {}));
|
|
1426
|
-
const DocumentIcon = {
|
|
1427
|
-
[EFileIcons.FILE]: 'fa-solid fa-file-lines',
|
|
1428
|
-
[EFileIcons.IMAGE]: 'fa-solid fa-file-image',
|
|
1429
|
-
[EFileIcons.VIDEO]: 'fa-solid fa-file-video',
|
|
1430
|
-
[EFileIcons.FOLDER]: 'fa-solid fa-folder',
|
|
1431
|
-
[EFileIcons.EXCEL]: 'fa-solid fa-file-excel',
|
|
1432
|
-
[EFileIcons.SIGNATURE]: 'fa-solid fa-signature',
|
|
1433
|
-
[EFileIcons.CONTRACT]: 'fa-solid fa-file-contract',
|
|
1434
|
-
[EFileIcons.FINGERPRINT]: 'fa-solid fa-fingerprint',
|
|
1435
|
-
[EFileIcons.ID_CARD]: 'fa-solid fa-id-card',
|
|
1436
|
-
[EFileIcons.SECURE_BUILDING]: 'fa-solid fa-building-shield',
|
|
1437
|
-
[EFileIcons.POLICE]: 'fa-solid fa-hand-middle-finger',
|
|
1438
|
-
[EFileIcons.FILE_BOX]: 'fa-solid fa-box-archive'
|
|
1439
|
-
};
|
|
1440
|
-
const downloadFile = (blob, fileName) => {
|
|
1441
|
-
const url = window.URL.createObjectURL(blob);
|
|
1442
|
-
const link = document.createElement('a');
|
|
1443
|
-
link.href = url;
|
|
1444
|
-
link.download = fileName;
|
|
1445
|
-
document.body.appendChild(link);
|
|
1446
|
-
link.click();
|
|
1447
|
-
document.body.removeChild(link);
|
|
1448
|
-
window.URL.revokeObjectURL(url);
|
|
1449
|
-
};
|
|
1450
|
-
|
|
1451
|
-
//sin uuid, codigo propio
|
|
1452
|
-
const generateId = () => {
|
|
1453
|
-
return Date.now().toString(36) + Math.random().toString(36).substring(2, 15);
|
|
1454
|
-
};
|
|
1455
|
-
|
|
1456
|
-
const formatNumber = (number) => {
|
|
1457
|
-
return new Intl.NumberFormat('es-CO', {
|
|
1458
|
-
minimumFractionDigits: 2,
|
|
1459
|
-
maximumFractionDigits: 2
|
|
1460
|
-
}).format(number);
|
|
1461
|
-
};
|
|
1462
|
-
const fixedNumber = (number) => {
|
|
1463
|
-
return Number(number.toFixed(2));
|
|
1464
|
-
};
|
|
1363
|
+
this._panelTop.set(`${rect.top - offsetTop}px`);
|
|
1364
|
+
this._panelLeft.set(`${rect.left - offsetLeft - this.panelOffset}px`);
|
|
1365
|
+
break;
|
|
1366
|
+
case 'right':
|
|
1367
|
+
this._panelTop.set(`${rect.top - offsetTop}px`);
|
|
1368
|
+
this._panelLeft.set(`${rect.right - offsetLeft + this.panelOffset}px`);
|
|
1369
|
+
break;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Detecta el ancestro que actúa como containing block para elementos fixed.
|
|
1374
|
+
* Si existe (por transform/filter/contain/etc), el panel debe posicionarse
|
|
1375
|
+
* relativo a ese contenedor y no al viewport.
|
|
1376
|
+
*/
|
|
1377
|
+
getFixedContainingBlock(element) {
|
|
1378
|
+
let current = element.parentElement;
|
|
1379
|
+
while (current) {
|
|
1380
|
+
const styles = window.getComputedStyle(current);
|
|
1381
|
+
const hasTransformContext = styles.transform !== 'none' ||
|
|
1382
|
+
styles.perspective !== 'none' ||
|
|
1383
|
+
styles.filter !== 'none' ||
|
|
1384
|
+
(styles.backdropFilter && styles.backdropFilter !== 'none') ||
|
|
1385
|
+
styles.contain.includes('paint') ||
|
|
1386
|
+
styles.contain.includes('layout') ||
|
|
1387
|
+
styles.willChange.includes('transform') ||
|
|
1388
|
+
styles.willChange.includes('filter') ||
|
|
1389
|
+
styles.willChange.includes('perspective');
|
|
1390
|
+
if (hasTransformContext) {
|
|
1391
|
+
return current;
|
|
1392
|
+
}
|
|
1393
|
+
current = current.parentElement;
|
|
1394
|
+
}
|
|
1395
|
+
return null;
|
|
1396
|
+
}
|
|
1397
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1398
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, providedIn: 'root' });
|
|
1399
|
+
}
|
|
1400
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialService, decorators: [{
|
|
1401
|
+
type: Injectable,
|
|
1402
|
+
args: [{
|
|
1403
|
+
providedIn: 'root'
|
|
1404
|
+
}]
|
|
1405
|
+
}], ctorParameters: () => [] });
|
|
1465
1406
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1407
|
+
class AppButtonNgService {
|
|
1408
|
+
buttonConfig = signal({});
|
|
1409
|
+
constructor() {
|
|
1410
|
+
// Effect para manejar automáticamente la rotación de mensajes
|
|
1411
|
+
effect(() => {
|
|
1412
|
+
const config = this.buttonConfig();
|
|
1413
|
+
if (config.loading && config.loadingMessages && config.loadingMessages.length > 1) {
|
|
1414
|
+
this.startMessageRotation();
|
|
1415
|
+
}
|
|
1416
|
+
else {
|
|
1417
|
+
this.stopMessageRotation();
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
setButtonConfig(buttonConfig) {
|
|
1422
|
+
this.buttonConfig.set(buttonConfig);
|
|
1423
|
+
}
|
|
1424
|
+
// Computed público para acceder al label dinámico
|
|
1425
|
+
label = computed(() => {
|
|
1426
|
+
const config = this.buttonConfig();
|
|
1427
|
+
// Si está cargando y tiene mensajes de carga, rotar entre ellos
|
|
1428
|
+
if (config.loading && config.loadingMessages && config.loadingMessages.length > 0) {
|
|
1429
|
+
const messages = config.loadingMessages;
|
|
1430
|
+
const index = this.messageIndex() % messages.length; // Wrap around
|
|
1431
|
+
return messages[index];
|
|
1481
1432
|
}
|
|
1433
|
+
// Si no está cargando, retornar el label normal
|
|
1434
|
+
return config.label ? config.label : '';
|
|
1482
1435
|
});
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
valuesToInsert.forEach(stringValue => {
|
|
1499
|
-
// Solo agregar si no existe en el array
|
|
1500
|
-
if (!result.includes(stringValue)) {
|
|
1501
|
-
result.push(stringValue);
|
|
1436
|
+
//#region Loading Messages
|
|
1437
|
+
messageIndex = signal(0);
|
|
1438
|
+
intervalId;
|
|
1439
|
+
startMessageRotation() {
|
|
1440
|
+
if (this.intervalId)
|
|
1441
|
+
return;
|
|
1442
|
+
this.intervalId = setInterval(() => {
|
|
1443
|
+
this.messageIndex.update(index => index + 1);
|
|
1444
|
+
}, 6000);
|
|
1445
|
+
}
|
|
1446
|
+
stopMessageRotation() {
|
|
1447
|
+
if (this.intervalId) {
|
|
1448
|
+
clearInterval(this.intervalId);
|
|
1449
|
+
this.intervalId = undefined;
|
|
1450
|
+
this.messageIndex.set(0);
|
|
1502
1451
|
}
|
|
1503
|
-
});
|
|
1504
|
-
return result;
|
|
1505
|
-
};
|
|
1506
|
-
const sameArray = (arr1, arr2) => {
|
|
1507
|
-
if (arr1.length !== arr2.length)
|
|
1508
|
-
return false;
|
|
1509
|
-
const sorted1 = Array.from(arr1).sort();
|
|
1510
|
-
const sorted2 = Array.from(arr2).sort();
|
|
1511
|
-
return sorted1.every((item, index) => item === sorted2[index]);
|
|
1512
|
-
};
|
|
1513
|
-
const getOptionByCode = (options, code) => {
|
|
1514
|
-
if (!code)
|
|
1515
|
-
return undefined;
|
|
1516
|
-
return options.find((item) => item.code === code);
|
|
1517
|
-
};
|
|
1518
|
-
const createEnumeratedList = (items) => {
|
|
1519
|
-
if (items.length === 0) {
|
|
1520
|
-
return '';
|
|
1521
1452
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1453
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1454
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, providedIn: 'root' });
|
|
1455
|
+
}
|
|
1456
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: AppButtonNgService, decorators: [{
|
|
1457
|
+
type: Injectable,
|
|
1458
|
+
args: [{
|
|
1459
|
+
providedIn: 'root'
|
|
1460
|
+
}]
|
|
1461
|
+
}], ctorParameters: () => [] });
|
|
1462
|
+
|
|
1463
|
+
class ButtonNgComponent {
|
|
1464
|
+
appButtonNgService = inject(AppButtonNgService);
|
|
1465
|
+
buttonConfig = model.required();
|
|
1466
|
+
onClick = output();
|
|
1467
|
+
constructor() {
|
|
1468
|
+
effect(() => {
|
|
1469
|
+
this.appButtonNgService.setButtonConfig(this.buttonConfig());
|
|
1470
|
+
});
|
|
1524
1471
|
}
|
|
1525
|
-
|
|
1526
|
-
.
|
|
1527
|
-
|
|
1528
|
-
|
|
1472
|
+
get label() {
|
|
1473
|
+
return this.appButtonNgService.label();
|
|
1474
|
+
}
|
|
1475
|
+
onClickButton() {
|
|
1476
|
+
if (this.buttonConfig().onClick) {
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
this.onClick.emit();
|
|
1480
|
+
}
|
|
1481
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1482
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: ButtonNgComponent, isStandalone: true, selector: "lib-button-ng", inputs: { buttonConfig: { classPropertyName: "buttonConfig", publicName: "buttonConfig", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { buttonConfig: "buttonConfigChange", onClick: "onClick" }, providers: [AppButtonNgService], ngImport: i0, template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"], dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "fluid", "buttonProps"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
1483
|
+
}
|
|
1484
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: ButtonNgComponent, decorators: [{
|
|
1485
|
+
type: Component,
|
|
1486
|
+
args: [{ selector: 'lib-button-ng', imports: [
|
|
1487
|
+
ButtonModule,
|
|
1488
|
+
TooltipModule,
|
|
1489
|
+
CommonModule
|
|
1490
|
+
], providers: [AppButtonNgService], template: "@let config = buttonConfig(); @let tooltipConfig = buttonConfig().tooltipConfig;\r\n@if (!config.hideButton) {\r\n <div\r\n [ngClass]=\"{\r\n 'full-width-button': config.fullWidth,\r\n 'full-height-button': config.fullHeight,\r\n 'cursor-pointer': this.onClick\r\n }\"\r\n [class]=\"config.class ?? ''\"\r\n >\r\n <p-button\r\n [label]=\"config.hasTemplate ? undefined : label\"\r\n [icon]=\"config.hasTemplate ? undefined : config.icon\"\r\n [severity]=\"config.hasTemplate ? 'secondary' : config.severity\"\r\n [loading]=\"config.loading || false\"\r\n [disabled]=\"config.disabled || false\"\r\n [rounded]=\"config.rounded || false\"\r\n [raised]=\"config.raised || false\"\r\n [variant]=\"config.hasTemplate ? 'text' : config.variant\"\r\n [badge]=\"config.badge\"\r\n (onClick)=\"config?.onClick?.() ?? onClickButton()\"\r\n [size]=\"config?.size\"\r\n pTooltip=\"{{ tooltipConfig?.pTooltip }}\"\r\n [tooltipPosition]=\"tooltipConfig?.tooltipPosition ?? 'top'\"\r\n [iconPos]=\"config?.iconPos ?? 'left'\"\r\n [ngClass]=\"{\r\n 'cursor-pointer': (config.onClick || config.hasStaticClick) && !config.disabled,\r\n 'cursor-auto': !((config.onClick || config.hasStaticClick) && !config.disabled),\r\n 'no-hover-template': config.hasTemplate\r\n }\"\r\n [outlined]=\"config.outlined || false\"\r\n [text]=\"config.text || false\"\r\n >\r\n @if (config.hasTemplate) {\r\n <ng-content></ng-content>\r\n }\r\n </p-button>\r\n </div>\r\n}\r\n", styles: [".full-width-button ::ng-deep p-button button{width:100%}.full-height-button ::ng-deep p-button button{height:100%}::ng-deep .cursor-auto button{cursor:auto!important}::ng-deep .cursor-pointer button{cursor:pointer!important}::ng-deep .no-hover-template button{background:transparent!important;border:none!important;box-shadow:none!important;padding:0!important}::ng-deep .no-hover-template button:hover,::ng-deep .no-hover-template button:focus,::ng-deep .no-hover-template button:active{background:transparent!important;border:none!important;box-shadow:none!important}\n"] }]
|
|
1491
|
+
}], ctorParameters: () => [] });
|
|
1529
1492
|
|
|
1530
|
-
class
|
|
1531
|
-
|
|
1532
|
-
|
|
1493
|
+
class SpeedDialComponent {
|
|
1494
|
+
mainButtonContainer;
|
|
1495
|
+
speedDialConfig = input.required();
|
|
1496
|
+
speedDialService = inject(SpeedDialService);
|
|
1497
|
+
constructor() {
|
|
1498
|
+
effect(() => {
|
|
1499
|
+
this.speedDialService.setSpeedDialConfig(this.speedDialConfig());
|
|
1500
|
+
});
|
|
1533
1501
|
}
|
|
1502
|
+
get buttons() {
|
|
1503
|
+
return this.speedDialService.buttons();
|
|
1504
|
+
}
|
|
1505
|
+
get overlayButtons() {
|
|
1506
|
+
return this.speedDialService.overlayButtons();
|
|
1507
|
+
}
|
|
1508
|
+
get mainButton() {
|
|
1509
|
+
return this.speedDialService.mainButton();
|
|
1510
|
+
}
|
|
1511
|
+
get isMenuOpen() {
|
|
1512
|
+
return this.speedDialService.isMenuOpen();
|
|
1513
|
+
}
|
|
1514
|
+
get panelTop() {
|
|
1515
|
+
return this.speedDialService.panelTop();
|
|
1516
|
+
}
|
|
1517
|
+
get panelLeft() {
|
|
1518
|
+
return this.speedDialService.panelLeft();
|
|
1519
|
+
}
|
|
1520
|
+
get direction() {
|
|
1521
|
+
return this.speedDialService.direction();
|
|
1522
|
+
}
|
|
1523
|
+
ngAfterViewInit() {
|
|
1524
|
+
const hostElement = this.mainButtonContainer?.nativeElement;
|
|
1525
|
+
if (!hostElement)
|
|
1526
|
+
return;
|
|
1527
|
+
this.speedDialService.setMainButtonHost(hostElement);
|
|
1528
|
+
}
|
|
1529
|
+
ngOnDestroy() {
|
|
1530
|
+
this.speedDialService.destroy();
|
|
1531
|
+
}
|
|
1532
|
+
closeMenu() {
|
|
1533
|
+
this.speedDialService.closeMenu();
|
|
1534
|
+
}
|
|
1535
|
+
onMainButtonClick(event) {
|
|
1536
|
+
const target = event.target;
|
|
1537
|
+
const anchor = target?.closest('button,[role="button"]');
|
|
1538
|
+
this.speedDialService.toggleMenu(anchor ?? this.mainButtonContainer?.nativeElement);
|
|
1539
|
+
}
|
|
1540
|
+
stopPropagation(event) {
|
|
1541
|
+
event.stopPropagation();
|
|
1542
|
+
}
|
|
1543
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1544
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SpeedDialComponent, isStandalone: true, selector: "lib-speed-dial", inputs: { speedDialConfig: { classPropertyName: "speedDialConfig", publicName: "speedDialConfig", isSignal: true, isRequired: true, transformFunction: null } }, providers: [SpeedDialService], viewQueries: [{ propertyName: "mainButtonContainer", first: true, predicate: ["mainButtonContainer"], descendants: true }], ngImport: i0, template: "<div\r\n #mainButtonContainer\r\n class=\"speed-dial-main-button\"\r\n [class.speed-dial-main-button--open]=\"isMenuOpen\"\r\n (click)=\"onMainButtonClick($event)\"\r\n>\r\n <lib-button-ng [buttonConfig]=\"mainButton\"></lib-button-ng>\r\n</div>\r\n\r\n@if (isMenuOpen) {\r\n <div class=\"speed-dial-overlay\" (click)=\"closeMenu()\">\r\n <div\r\n class=\"speed-dial-panel bg-gray-100 dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg\"\r\n [style.top]=\"panelTop\"\r\n [style.left]=\"panelLeft\"\r\n (click)=\"stopPropagation($event)\"\r\n [ngClass]=\"{\r\n 'speed-dial-panel--top': direction === 'top',\r\n 'speed-dial-panel--bottom': direction === 'bottom',\r\n 'speed-dial-panel--left': direction === 'left',\r\n 'speed-dial-panel--right': direction === 'right'\r\n }\"\r\n >\r\n @for (button of overlayButtons; track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".speed-dial-main-button{display:inline-flex}.speed-dial-main-button--open{position:relative;z-index:2147483647}.speed-dial-overlay{position:fixed;inset:0;z-index:2147483645}.speed-dial-panel{position:fixed;z-index:2147483646;display:flex;gap:.5rem;overflow:auto;padding:.75rem;border-radius:.75rem;background:#fff;box-shadow:0 10px 30px #0f172a40}.speed-dial-panel--top{flex-direction:column;max-width:22rem;max-height:30rem;transform:translateY(-100%)}.speed-dial-panel--bottom{flex-direction:column;max-width:22rem;max-height:30rem}.speed-dial-panel--left{flex-direction:row;max-width:40rem;max-height:8rem;transform:translate(-100%)}.speed-dial-panel--right{flex-direction:row;max-width:40rem;max-height:8rem}:host-context(.dark) .speed-dial-panel{background:#111827}\n"], dependencies: [{ kind: "component", type: ButtonNgComponent, selector: "lib-button-ng", inputs: ["buttonConfig"], outputs: ["buttonConfigChange", "onClick"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
1545
|
+
}
|
|
1546
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SpeedDialComponent, decorators: [{
|
|
1547
|
+
type: Component,
|
|
1548
|
+
args: [{ selector: 'lib-speed-dial', imports: [ButtonNgComponent, CommonModule], providers: [SpeedDialService], template: "<div\r\n #mainButtonContainer\r\n class=\"speed-dial-main-button\"\r\n [class.speed-dial-main-button--open]=\"isMenuOpen\"\r\n (click)=\"onMainButtonClick($event)\"\r\n>\r\n <lib-button-ng [buttonConfig]=\"mainButton\"></lib-button-ng>\r\n</div>\r\n\r\n@if (isMenuOpen) {\r\n <div class=\"speed-dial-overlay\" (click)=\"closeMenu()\">\r\n <div\r\n class=\"speed-dial-panel bg-gray-100 dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg\"\r\n [style.top]=\"panelTop\"\r\n [style.left]=\"panelLeft\"\r\n (click)=\"stopPropagation($event)\"\r\n [ngClass]=\"{\r\n 'speed-dial-panel--top': direction === 'top',\r\n 'speed-dial-panel--bottom': direction === 'bottom',\r\n 'speed-dial-panel--left': direction === 'left',\r\n 'speed-dial-panel--right': direction === 'right'\r\n }\"\r\n >\r\n @for (button of overlayButtons; track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".speed-dial-main-button{display:inline-flex}.speed-dial-main-button--open{position:relative;z-index:2147483647}.speed-dial-overlay{position:fixed;inset:0;z-index:2147483645}.speed-dial-panel{position:fixed;z-index:2147483646;display:flex;gap:.5rem;overflow:auto;padding:.75rem;border-radius:.75rem;background:#fff;box-shadow:0 10px 30px #0f172a40}.speed-dial-panel--top{flex-direction:column;max-width:22rem;max-height:30rem;transform:translateY(-100%)}.speed-dial-panel--bottom{flex-direction:column;max-width:22rem;max-height:30rem}.speed-dial-panel--left{flex-direction:row;max-width:40rem;max-height:8rem;transform:translate(-100%)}.speed-dial-panel--right{flex-direction:row;max-width:40rem;max-height:8rem}:host-context(.dark) .speed-dial-panel{background:#111827}\n"] }]
|
|
1549
|
+
}], ctorParameters: () => [], propDecorators: { mainButtonContainer: [{
|
|
1550
|
+
type: ViewChild,
|
|
1551
|
+
args: ['mainButtonContainer']
|
|
1552
|
+
}] } });
|
|
1553
|
+
|
|
1554
|
+
class KeyToDisplayNamePipe {
|
|
1555
|
+
transform(key, keysNames) {
|
|
1556
|
+
return keysNames?.[key] ?? key;
|
|
1557
|
+
}
|
|
1558
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1559
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, isStandalone: true, name: "keyToDisplayName" });
|
|
1534
1560
|
}
|
|
1561
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: KeyToDisplayNamePipe, decorators: [{
|
|
1562
|
+
type: Pipe,
|
|
1563
|
+
args: [{
|
|
1564
|
+
name: 'keyToDisplayName'
|
|
1565
|
+
}]
|
|
1566
|
+
}] });
|
|
1535
1567
|
|
|
1536
1568
|
class BadgeNgComponent {
|
|
1537
1569
|
config = model.required();
|
|
@@ -2442,7 +2474,7 @@ class TableNgService {
|
|
|
2442
2474
|
//#endregion
|
|
2443
2475
|
//#region Selection
|
|
2444
2476
|
async openModalManagementSelectedItems(selectedItems, config) {
|
|
2445
|
-
const { SelectedItemsManagementComponent } = await import('./ln-20-lib-components-selected-items-management.component-
|
|
2477
|
+
const { SelectedItemsManagementComponent } = await import('./ln-20-lib-components-selected-items-management.component-Cn5xvixS.mjs');
|
|
2446
2478
|
let configSelectedItems = config;
|
|
2447
2479
|
if (config) {
|
|
2448
2480
|
configSelectedItems = structuredClone(config);
|
|
@@ -3011,8 +3043,10 @@ class TableNgComponent {
|
|
|
3011
3043
|
inlineFormChanges(inlineValue, filter, typeInput, key) {
|
|
3012
3044
|
const lazyLoadingConfig = this.config()?.lazyLoadingConfig;
|
|
3013
3045
|
if (typeInput === ETypeInput.MULTISELECT) {
|
|
3014
|
-
const options = inlineValue
|
|
3015
|
-
|
|
3046
|
+
const options = Array.isArray(inlineValue)
|
|
3047
|
+
? inlineValue.filter((item) => PrimeNgUtil.isPrimeNgSelection(item))
|
|
3048
|
+
: [];
|
|
3049
|
+
const arrayValue = options.length > 0
|
|
3016
3050
|
? options.map((data) => lazyLoadingConfig?.isEnabled ? data.code : data.name)
|
|
3017
3051
|
: undefined;
|
|
3018
3052
|
if (Array.isArray(arrayValue) && arrayValue.length === 0) {
|
|
@@ -3438,13 +3472,13 @@ class TableNgComponent {
|
|
|
3438
3472
|
}
|
|
3439
3473
|
handleTableValueToSourceElements() {
|
|
3440
3474
|
const value = this.data();
|
|
3441
|
-
if (!value.some((item) => item.rowData['identifier'])) {
|
|
3475
|
+
if (!value.some((item) => item.rowData?.['identifier'])) {
|
|
3442
3476
|
return;
|
|
3443
3477
|
}
|
|
3444
3478
|
const sourceElements = value.map((item) => ({
|
|
3445
3479
|
id: item.id,
|
|
3446
3480
|
buttonConfig: {
|
|
3447
|
-
label: item.rowData['identifier'],
|
|
3481
|
+
label: item.rowData?.['identifier'],
|
|
3448
3482
|
fullWidth: true,
|
|
3449
3483
|
fullHeight: true
|
|
3450
3484
|
},
|
|
@@ -3454,10 +3488,10 @@ class TableNgComponent {
|
|
|
3454
3488
|
}
|
|
3455
3489
|
handleSelectedItemsToSourceElements() {
|
|
3456
3490
|
const selectedItems = this.selectedItems();
|
|
3457
|
-
if (!selectedItems.some((item) => item.rowData['identifier'])) {
|
|
3491
|
+
if (!selectedItems.some((item) => item.rowData?.['identifier'])) {
|
|
3458
3492
|
return;
|
|
3459
3493
|
}
|
|
3460
|
-
const identifiers = selectedItems.map((item) => item.rowData['identifier']);
|
|
3494
|
+
const identifiers = selectedItems.map((item) => item.rowData?.['identifier']);
|
|
3461
3495
|
const sourceElements = this.sourceElements().map((item) => ({
|
|
3462
3496
|
...item,
|
|
3463
3497
|
isSelected: identifiers.includes(item.buttonConfig?.label)
|
|
@@ -3614,7 +3648,7 @@ class TableNgComponent {
|
|
|
3614
3648
|
return this.tableNgService.refreshButton();
|
|
3615
3649
|
}
|
|
3616
3650
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3617
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: TableNgComponent, isStandalone: true, selector: "lib-table-ng", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, editConfig: { classPropertyName: "editConfig", publicName: "editConfig", isSignal: true, isRequired: false, transformFunction: null }, footerConfig: { classPropertyName: "footerConfig", publicName: "footerConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarButtons: { classPropertyName: "toolbarButtons", publicName: "toolbarButtons", isSignal: true, isRequired: false, transformFunction: null }, toolbarSpeedDialButtons: { classPropertyName: "toolbarSpeedDialButtons", publicName: "toolbarSpeedDialButtons", isSignal: true, isRequired: false, transformFunction: null }, sourceElements: { classPropertyName: "sourceElements", publicName: "sourceElements", isSignal: true, isRequired: false, transformFunction: null }, targetElements: { classPropertyName: "targetElements", publicName: "targetElements", isSignal: true, isRequired: false, transformFunction: null }, httpMessage: { classPropertyName: "httpMessage", publicName: "httpMessage", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, itemTemplateInput: { classPropertyName: "itemTemplateInput", publicName: "itemTemplateInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", isLoading: "isLoadingChange", config: "configChange", editConfig: "editConfigChange", footerConfig: "footerConfigChange", toolbarButtons: "toolbarButtonsChange", toolbarSpeedDialButtons: "toolbarSpeedDialButtonsChange", sourceElements: "sourceElementsChange", targetElements: "targetElementsChange", httpMessage: "httpMessageChange", lazyLoading: "lazyLoading", outputChangeData: "outputChangeData", outputHandleEditInitButton: "outputHandleEditInitButton", outputAddRow: "outputAddRow", outputDeleteRow: "outputDeleteRow", outputRowInlineChange: "outputRowInlineChange", outputRowDataChange: "outputRowDataChange", outputEditData: "outputEditData", outputIsEditing: "outputIsEditing", outputCheckAll: "outputCheckAll", selectedItems: "selectedItemsChange" }, providers: [TableNgService, TableNgEditService], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true, static: true }], viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n@let inputConfig = config()?.inputConfig;\r\n@let hasCheckRows = config()?.hasCheckRows ?? false;\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (hasCheckRows) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"checkAllHeaderReflectValue()\"\r\n (ngModelChange)=\"checkAll($event)\"\r\n [config]=\"inlineConfigCheckHeaderCheckAll\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarSpeedDialButtons().length > 0) {\r\n @for (speedDial of toolbarSpeedDialButtons(); track $index) {\r\n <lib-speed-dial [speedDialConfig]=\"speedDial\"></lib-speed-dial>\r\n }\r\n }\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n @if (enableRefreshButton) {\r\n <lib-button-ng [buttonConfig]=\"refreshButton\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" tableStyleClass=\"table table-xs\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? lazyLoadingConfig!.totalRecords\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"getCustomPageReport()\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[column.field]?.isEnabled) {\r\n @let columnInputConfig = inputConfig![column.field]!;\r\n @if (columnInputConfig.type === ETypeInput.SWITCH || columnInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(column.field)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, column.field)\"\r\n [config]=\"inlineConfigCheckHeader(column.field, columnInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![column.field]!;\r\n <p-columnFilter [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n \r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[key]?.isEnabled) {\r\n @let keyInputConfig = inputConfig![key]!;\r\n @if (keyInputConfig.type === ETypeInput.SWITCH || keyInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(key)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, key)\"\r\n [config]=\"inlineConfigCheckHeader(key, keyInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![key]!;\r\n <p-columnFilter [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Loading state -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ getLoadingMessage() }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- No data available -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ getNoDataMessage() }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[column.field]\r\n | number: (\r\n inlineControls?.[column.field]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[column.field]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n }@else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field]?.name ?? item.rowData[column.field]?.value ?? '' }}\r\n </div>\r\n }\r\n @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id][column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ columnFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n inlineControls?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key]?.name ?? item.rowData[key]?.value ?? '' }}\r\n </div>\r\n } @else if (inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id][key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ keyFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[column.field] && errorConfig.fieldErrors[item.id][column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ columnFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[key] && errorConfig.fieldErrors[item.id][key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ keyFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @case (ETypeInput.INPUT) {\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\"\r\n [config]=\"item.rowDataInput?.[key] ?? {typeInput: ETypeInput.TEXT}\"\r\n (outputValue)=\"handleCheckValue()\"\r\n >\r\n </lib-inline-input>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n item.rowDataInput?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n item.rowDataInput?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"mt-6 p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700 dark:text-gray-300\">{{ getSelectedItemsLabel() }}</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900 dark:text-gray-100\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">{{ getRecordsLabel() }}</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.my-app-dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.my-app-dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.my-app-dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$2.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", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], 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: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i2$2.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i2$2.RowToggler, selector: "[pRowToggler]", inputs: ["pRowToggler", "pRowTogglerDisabled"] }, { kind: "directive", type: i2$2.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i2$2.EditableColumn, selector: "[pEditableColumn]", inputs: ["pEditableColumn", "pEditableColumnField", "pEditableColumnRowIndex", "pEditableColumnDisabled", "pFocusCellSelector"] }, { kind: "component", type: i2$2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2$2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i2$2.TableCheckbox, selector: "p-tableCheckbox", inputs: ["value", "disabled", "required", "index", "inputId", "name", "ariaLabel"] }, { kind: "component", type: i2$2.TableHeaderCheckbox, selector: "p-tableHeaderCheckbox", inputs: ["disabled", "inputId", "name", "ariaLabel"] }, { kind: "directive", type: i2$2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2$2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2$2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2$2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2$2.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", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "component", type: ButtonNgComponent, selector: "lib-button-ng", inputs: ["buttonConfig"], outputs: ["buttonConfigChange", "onClick"] }, { kind: "component", type: ToolbarNgComponent, selector: "lib-toolbar-ng" }, { kind: "component", type: FormComponent, selector: "lib-form", inputs: ["formGroup", "controls", "formConfig", "httpMessage"], outputs: ["formGroupChange", "httpMessageChange", "formSubmit", "formChanges", "formChangesDebounced"] }, { kind: "pipe", type: KeyToDisplayNamePipe, name: "keyToDisplayName" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InlineInputComponent, selector: "lib-inline-input", inputs: ["config", "value"], outputs: ["valueChange", "outputValue", "outputBlur", "outputDebounced"] }, { kind: "component", type: BadgeNgComponent, selector: "lib-badge-ng", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: HttpMessageComponent, selector: "lib-http-message", inputs: ["httpMessage"], outputs: ["httpMessageChange"] }, { kind: "component", type: SpeedDialComponent, selector: "lib-speed-dial", inputs: ["speedDialConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3651
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: TableNgComponent, isStandalone: true, selector: "lib-table-ng", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, editConfig: { classPropertyName: "editConfig", publicName: "editConfig", isSignal: true, isRequired: false, transformFunction: null }, footerConfig: { classPropertyName: "footerConfig", publicName: "footerConfig", isSignal: true, isRequired: false, transformFunction: null }, toolbarButtons: { classPropertyName: "toolbarButtons", publicName: "toolbarButtons", isSignal: true, isRequired: false, transformFunction: null }, toolbarSpeedDialButtons: { classPropertyName: "toolbarSpeedDialButtons", publicName: "toolbarSpeedDialButtons", isSignal: true, isRequired: false, transformFunction: null }, sourceElements: { classPropertyName: "sourceElements", publicName: "sourceElements", isSignal: true, isRequired: false, transformFunction: null }, targetElements: { classPropertyName: "targetElements", publicName: "targetElements", isSignal: true, isRequired: false, transformFunction: null }, httpMessage: { classPropertyName: "httpMessage", publicName: "httpMessage", isSignal: true, isRequired: false, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: false, transformFunction: null }, itemTemplateInput: { classPropertyName: "itemTemplateInput", publicName: "itemTemplateInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "dataChange", isLoading: "isLoadingChange", config: "configChange", editConfig: "editConfigChange", footerConfig: "footerConfigChange", toolbarButtons: "toolbarButtonsChange", toolbarSpeedDialButtons: "toolbarSpeedDialButtonsChange", sourceElements: "sourceElementsChange", targetElements: "targetElementsChange", httpMessage: "httpMessageChange", lazyLoading: "lazyLoading", outputChangeData: "outputChangeData", outputHandleEditInitButton: "outputHandleEditInitButton", outputAddRow: "outputAddRow", outputDeleteRow: "outputDeleteRow", outputRowInlineChange: "outputRowInlineChange", outputRowDataChange: "outputRowDataChange", outputEditData: "outputEditData", outputIsEditing: "outputIsEditing", outputCheckAll: "outputCheckAll", selectedItems: "selectedItemsChange" }, providers: [TableNgService, TableNgEditService], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true, static: true }], viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n@let inputConfig = config()?.inputConfig;\r\n@let hasCheckRows = config()?.hasCheckRows ?? false;\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (hasCheckRows) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"checkAllHeaderReflectValue()\"\r\n (ngModelChange)=\"checkAll($event)\"\r\n [config]=\"inlineConfigCheckHeaderCheckAll\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarSpeedDialButtons().length > 0) {\r\n @for (speedDial of toolbarSpeedDialButtons(); track $index) {\r\n <lib-speed-dial [speedDialConfig]=\"speedDial\"></lib-speed-dial>\r\n }\r\n }\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n @if (enableRefreshButton) {\r\n <lib-button-ng [buttonConfig]=\"refreshButton\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" tableStyleClass=\"table table-xs\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? lazyLoadingConfig!.totalRecords\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"getCustomPageReport()\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[column.field]?.isEnabled) {\r\n @let columnInputConfig = inputConfig![column.field]!;\r\n @if (columnInputConfig.type === ETypeInput.SWITCH || columnInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(column.field)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, column.field)\"\r\n [config]=\"inlineConfigCheckHeader(column.field, columnInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![column.field]!;\r\n <p-columnFilter [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n \r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[key]?.isEnabled) {\r\n @let keyInputConfig = inputConfig![key]!;\r\n @if (keyInputConfig.type === ETypeInput.SWITCH || keyInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(key)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, key)\"\r\n [config]=\"inlineConfigCheckHeader(key, keyInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![key]!;\r\n <p-columnFilter [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Loading state -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ getLoadingMessage() }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- No data available -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ getNoDataMessage() }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[column.field]\r\n | number: (\r\n inlineControls?.[column.field]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[column.field]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n }@else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field]?.name ?? item.rowData[column.field]?.value ?? '' }}\r\n </div>\r\n }\r\n @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id]?.[column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ columnFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n inlineControls?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key]?.name ?? item.rowData[key]?.value ?? '' }}\r\n </div>\r\n } @else if (inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id]?.[key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ keyFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[column.field] && errorConfig.fieldErrors[item.id]?.[column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ columnFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[key] && errorConfig.fieldErrors[item.id]?.[key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ keyFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @case (ETypeInput.INPUT) {\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\"\r\n [config]=\"item.rowDataInput?.[key] ?? {typeInput: ETypeInput.TEXT}\"\r\n (outputValue)=\"handleCheckValue()\"\r\n >\r\n </lib-inline-input>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n item.rowDataInput?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n item.rowDataInput?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"mt-6 p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700 dark:text-gray-300\">{{ getSelectedItemsLabel() }}</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900 dark:text-gray-100\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">{{ getRecordsLabel() }}</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.my-app-dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.my-app-dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.my-app-dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$2.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", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "selectAll"], 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: i4$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i2$2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i2$2.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i2$2.RowToggler, selector: "[pRowToggler]", inputs: ["pRowToggler", "pRowTogglerDisabled"] }, { kind: "directive", type: i2$2.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i2$2.EditableColumn, selector: "[pEditableColumn]", inputs: ["pEditableColumn", "pEditableColumnField", "pEditableColumnRowIndex", "pEditableColumnDisabled", "pFocusCellSelector"] }, { kind: "component", type: i2$2.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i2$2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i2$2.TableCheckbox, selector: "p-tableCheckbox", inputs: ["value", "disabled", "required", "index", "inputId", "name", "ariaLabel"] }, { kind: "component", type: i2$2.TableHeaderCheckbox, selector: "p-tableHeaderCheckbox", inputs: ["disabled", "inputId", "name", "ariaLabel"] }, { kind: "directive", type: i2$2.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i2$2.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i2$2.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i2$2.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i2$2.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", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "component", type: ButtonNgComponent, selector: "lib-button-ng", inputs: ["buttonConfig"], outputs: ["buttonConfigChange", "onClick"] }, { kind: "component", type: ToolbarNgComponent, selector: "lib-toolbar-ng" }, { kind: "component", type: FormComponent, selector: "lib-form", inputs: ["formGroup", "controls", "formConfig", "httpMessage"], outputs: ["formGroupChange", "httpMessageChange", "formSubmit", "formChanges", "formChangesDebounced"] }, { kind: "pipe", type: KeyToDisplayNamePipe, name: "keyToDisplayName" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InlineInputComponent, selector: "lib-inline-input", inputs: ["config", "value"], outputs: ["valueChange", "outputValue", "outputBlur", "outputDebounced"] }, { kind: "component", type: BadgeNgComponent, selector: "lib-badge-ng", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: HttpMessageComponent, selector: "lib-http-message", inputs: ["httpMessage"], outputs: ["httpMessageChange"] }, { kind: "component", type: SpeedDialComponent, selector: "lib-speed-dial", inputs: ["speedDialConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3618
3652
|
}
|
|
3619
3653
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TableNgComponent, decorators: [{
|
|
3620
3654
|
type: Component,
|
|
@@ -3630,7 +3664,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
3630
3664
|
BadgeNgComponent,
|
|
3631
3665
|
HttpMessageComponent,
|
|
3632
3666
|
SpeedDialComponent
|
|
3633
|
-
], providers: [TableNgService, TableNgEditService], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n@let inputConfig = config()?.inputConfig;\r\n@let hasCheckRows = config()?.hasCheckRows ?? false;\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (hasCheckRows) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"checkAllHeaderReflectValue()\"\r\n (ngModelChange)=\"checkAll($event)\"\r\n [config]=\"inlineConfigCheckHeaderCheckAll\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarSpeedDialButtons().length > 0) {\r\n @for (speedDial of toolbarSpeedDialButtons(); track $index) {\r\n <lib-speed-dial [speedDialConfig]=\"speedDial\"></lib-speed-dial>\r\n }\r\n }\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n @if (enableRefreshButton) {\r\n <lib-button-ng [buttonConfig]=\"refreshButton\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" tableStyleClass=\"table table-xs\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? lazyLoadingConfig!.totalRecords\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"getCustomPageReport()\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[column.field]?.isEnabled) {\r\n @let columnInputConfig = inputConfig![column.field]!;\r\n @if (columnInputConfig.type === ETypeInput.SWITCH || columnInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(column.field)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, column.field)\"\r\n [config]=\"inlineConfigCheckHeader(column.field, columnInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![column.field]!;\r\n <p-columnFilter [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n \r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[key]?.isEnabled) {\r\n @let keyInputConfig = inputConfig![key]!;\r\n @if (keyInputConfig.type === ETypeInput.SWITCH || keyInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(key)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, key)\"\r\n [config]=\"inlineConfigCheckHeader(key, keyInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![key]!;\r\n <p-columnFilter [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Loading state -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ getLoadingMessage() }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- No data available -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ getNoDataMessage() }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[column.field]\r\n | number: (\r\n inlineControls?.[column.field]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[column.field]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n }@else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field]?.name ?? item.rowData[column.field]?.value ?? '' }}\r\n </div>\r\n }\r\n @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id][column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ columnFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n inlineControls?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key]?.name ?? item.rowData[key]?.value ?? '' }}\r\n </div>\r\n } @else if (inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id][key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ keyFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[column.field] && errorConfig.fieldErrors[item.id][column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ columnFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[key] && errorConfig.fieldErrors[item.id][key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ keyFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @case (ETypeInput.INPUT) {\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\"\r\n [config]=\"item.rowDataInput?.[key] ?? {typeInput: ETypeInput.TEXT}\"\r\n (outputValue)=\"handleCheckValue()\"\r\n >\r\n </lib-inline-input>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n item.rowDataInput?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n item.rowDataInput?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"mt-6 p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700 dark:text-gray-300\">{{ getSelectedItemsLabel() }}</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900 dark:text-gray-100\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">{{ getRecordsLabel() }}</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.my-app-dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.my-app-dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.my-app-dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
3667
|
+
], providers: [TableNgService, TableNgEditService], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let paginationConfig = config()?.paginationConfig;\r\n@let globalFilterConfig = config()?.globalFilterConfig;\r\n@let selectionTableConfig = config()?.selectionTableConfig;\r\n@let filterConfigByKey = config()?.filterConfigByKey;\r\n@let frozenColumnConfigByKey = config()?.frozenColumnConfigByKey;\r\n@let scrollConfig = config()?.scrollConfig;\r\n@let lazyLoadingConfig = config()?.lazyLoadingConfig;\r\n@let keysNames = config()?.keysNames;\r\n@let columnConfig = config()?.columnConfig;\r\n@let editEnabled = editConfig()?.isEnabled ?? false;\r\n@let editType = editConfig()?.type ?? 'cell';\r\n@let inlineControls = editConfig()?.inlineControls;\r\n@let rowErrorConfig = editConfig()?.rowEditConfig?.rowErrorConfig;\r\n@let footerRows = footerConfig()?.footerRows;\r\n@let footerEnabled = footerConfig()?.isEnabled ?? false;\r\n@let titleConfig = config()?.titleConfig;\r\n@let selectedColumns = config()?.selectedColumns;\r\n@let rowExpansionConfig = config()?.rowExpansionConfig;\r\n@let advancedIdentifierFiltersConfig = config()?.globalFilterConfig?.advancedIdentifierFiltersConfig;\r\n@let inputConfig = config()?.inputConfig;\r\n@let hasCheckRows = config()?.hasCheckRows ?? false;\r\n<div class=\"p-datatable-wrapper\">\r\n @if (titleConfig?.isEnabled && titleConfig?.title) {\r\n <div class=\"table-title-container\">\r\n <h2 class=\"table-title\">{{ titleConfig!.title }}</h2>\r\n </div>\r\n }\r\n @if (!hideToolbar || (filteredValue || advancedFiltersPerformed.length > 0)) {\r\n <lib-toolbar-ng class=\"p-toolbar-header sticky top-0 z-30 dark:bg-gray-800\">\r\n <div class=\"flex gap-2\" toolbarStart>\r\n @if (globalFilterConfig?.isEnabled && !lazyLoadingConfig?.isEnabled) {\r\n <lib-form [controls]=\"controlsGlobalFilter\" [(formGroup)]=\"searchFormGroupGlobalFilter\"\r\n (formSubmit)=\"submitGlobalSearch($event)\"></lib-form>\r\n }\r\n @if (advancedIdentifierFiltersConfig?.isEnabled) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\"\r\n [buttonConfig]=\"advancedIdentifierFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (filteredValue || advancedFiltersPerformed.length > 0) {\r\n <lib-button-ng class=\"animate__animated animate__fadeIn\" [buttonConfig]=\"clearFiltersButton()\"></lib-button-ng>\r\n }\r\n @if (hasCheckRows) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"checkAllHeaderReflectValue()\"\r\n (ngModelChange)=\"checkAll($event)\"\r\n [config]=\"inlineConfigCheckHeaderCheckAll\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n </div>\r\n <div class=\"flex gap-2\" toolbarEnd>\r\n @if (toolbarSpeedDialButtons().length > 0) {\r\n @for (speedDial of toolbarSpeedDialButtons(); track $index) {\r\n <lib-speed-dial [speedDialConfig]=\"speedDial\"></lib-speed-dial>\r\n }\r\n }\r\n @if (toolbarButtons().length > 0) {\r\n @for (button of toolbarButtons(); track $index) {\r\n <lib-button-ng [buttonConfig]=\"button\"></lib-button-ng>\r\n }\r\n }\r\n @if ((editType === 'row' || editType === 'cell') && editEnabled) {\r\n <lib-button-ng [buttonConfig]=\"addRowButton()\"></lib-button-ng>\r\n }\r\n @if (enableExcelButton()) {\r\n <lib-button-ng [buttonConfig]=\"excelButton\" (onClick)=\"exportData(dt,'excel')\"></lib-button-ng>\r\n }\r\n @if (enablePdfButton()) {\r\n <lib-button-ng [buttonConfig]=\"pdfButton\" (onClick)=\"exportData(dt,'pdf')\"></lib-button-ng>\r\n }\r\n @if (enableRefreshButton) {\r\n <lib-button-ng [buttonConfig]=\"refreshButton\"></lib-button-ng>\r\n }\r\n </div>\r\n </lib-toolbar-ng>\r\n }\r\n <p-table #dt styleClass=\"p-datatable-sm\" tableStyleClass=\"table table-xs\" [value]=\"data()\" [lazy]=\"lazyLoadingConfig?.isEnabled ?? false\"\r\n [editMode]=\"editType\" [totalRecords]=\"\r\n lazyLoadingConfig?.isEnabled\r\n ? lazyLoadingConfig!.totalRecords\r\n : data().length\r\n \" [customSort]=\"true\" [paginator]=\"paginationConfig?.paginator ?? true\" [showCurrentPageReport]=\"true\"\r\n [rows]=\"paginationConfig?.rows ?? 5\" [rowsPerPageOptions]=\"paginationConfig?.rowsPerPageOptions ?? [5, 10, 20]\"\r\n [paginatorStyleClass]=\"paginatorStyleClass()\" [resizableColumns]=\"true\" [rowTrackBy]=\"trackById\"\r\n [columns]=\"selectedColumns\" [scrollable]=\"scrollConfig?.isEnabled ?? false\"\r\n [scrollHeight]=\"scrollConfig?.isEnabled ? scrollHeight() : undefined\" (onLazyLoad)=\"onLazyLoad($event)\"\r\n (sortFunction)=\"customSort($event)\" (onFilter)=\"onFilter($event)\" [(selection)]=\"selectedItems\"\r\n [currentPageReportTemplate]=\"getCustomPageReport()\" selectionPageOnly=\"true\" dataKey=\"id\" class=\"w-full\">\r\n <ng-template #header let-columns>\r\n <tr>\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n\r\n </th>\r\n }\r\n @if (selectionTableConfig?.isEnabled) {\r\n <th alignFrozen=\"left\" pFrozenColumn style=\"width: 2rem\" class=\"p-datatable-header-cell p-frozen-column\">\r\n <p-tableHeaderCheckbox />\r\n </th>\r\n }\r\n\r\n @if (selectedColumns) {\r\n @for (column of columns; track $index) {\r\n <th pResizableColumn [id]=\"column.field\" alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[column.field])\" [pSortableColumn]=\"column.field\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[column.field] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(\r\n frozenColumnConfigByKey?.[column.field]\r\n ),\r\n }\">\r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ column.field | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[column.field]?.isEnabled) {\r\n @let columnInputConfig = inputConfig![column.field]!;\r\n @if (columnInputConfig.type === ETypeInput.SWITCH || columnInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(column.field)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, column.field)\"\r\n [config]=\"inlineConfigCheckHeader(column.field, columnInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"column.field\" />\r\n }\r\n @if (filterConfigByKey?.[column.field]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![column.field]!;\r\n <p-columnFilter [field]=\"`rowData.${column.field}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(column.field),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, column.field)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }@else {\r\n @for (key of keys(); track $index) {\r\n <th [id]=\"key\" pResizableColumn alignFrozen=\"right\" pFrozenColumn\r\n [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\" [pSortableColumn]=\"key\"\r\n class=\"p-datatable-header-cell\" [style.width.%]=\"columnConfig?.sizeByKey?.[key] ?? null\" [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n }\">\r\n \r\n <div class=\"flex gap-2 justify-center items-center py-0 px-0\">\r\n {{ key | keyToDisplayName: keysNames }}\r\n @if (inputConfig?.[key]?.isEnabled) {\r\n @let keyInputConfig = inputConfig![key]!;\r\n @if (keyInputConfig.type === ETypeInput.SWITCH || keyInputConfig.type === ETypeInput.CHECKBOX) {\r\n <div class=\"inline-flex\" (click)=\"$event.stopPropagation()\">\r\n <lib-inline-input\r\n [ngModel]=\"booleanColumnHeaderReflectValue(key)\"\r\n (ngModelChange)=\"applyBulkBooleanToColumn($event, key)\"\r\n [config]=\"inlineConfigCheckHeader(key, keyInputConfig.type)\">\r\n </lib-inline-input>\r\n </div>\r\n }\r\n }\r\n @if(!editEnabled){\r\n <p-sortIcon [field]=\"key\" />\r\n }\r\n @if (filterConfigByKey?.[key]?.isEnabled) {\r\n @let columnFilterConfig = filterConfigByKey![key]!;\r\n <p-columnFilter [field]=\"`rowData.${key}`\" display=\"menu\" [ngClass]=\"{\r\n 'bg-green-200 rounded-full p-1 shadow-sm text-green-500 transition-all duration-300 ease-in-out':\r\n advancedFiltersPerformed.includes(key),\r\n }\" [type]=\"columnFilterConfig.primeNgColumnFilterConfig?.type ?? 'text'\"\r\n [matchMode]=\"columnFilterConfig.primeNgColumnFilterConfig?.matchMode\"\r\n [showMatchModes]=\"columnFilterConfig.primeNgColumnFilterConfig?.showMatchModes ?? false\"\r\n [showOperator]=\"columnFilterConfig.primeNgColumnFilterConfig?.showOperator ?? false\"\r\n [showAddButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showAddButton ?? false\"\r\n [showApplyButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showApplyButton ?? false\"\r\n [showClearButton]=\"columnFilterConfig.primeNgColumnFilterConfig?.showClearButton ?? false\">\r\n @if (isCustomColumnFilterEnabled(columnFilterConfig)) {\r\n <ng-template pTemplate=\"filter\" let-value let-filter=\"filterCallback\">\r\n <div style=\"min-width: 20rem\">\r\n <lib-inline-input\r\n [ngModel]=\"value\"\r\n (outputValue)=\"inlineFormChanges($event, filter, columnFilterConfig.customColumnFilterConfig?.inlineControlConfig?.typeInput, key)\"\r\n [config]=\"columnFilterConfig.customColumnFilterConfig?.inlineControlConfig ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </div>\r\n </ng-template>\r\n }\r\n </p-columnFilter>\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (editType === 'cell' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n @if (editType === 'row' && editEnabled) {\r\n <th class=\"p-datatable-header-cell\" style=\"width: 100px\">\r\n </th>\r\n }\r\n\r\n </tr>\r\n </ng-template>\r\n\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumns()\">\r\n @if (isLoading()) {\r\n <!-- Loading state -->\r\n <div class=\"p-8 text-center\">\r\n <div class=\"flex flex-col items-center justify-center gap-4\">\r\n <i class=\"pi pi-spin pi-spinner text-4xl text-blue-500\"></i>\r\n <p class=\"text-gray-600 text-lg\">{{ getLoadingMessage() }}</p>\r\n </div>\r\n </div>\r\n } @else if (timeoutExpired()) {\r\n <!-- No data available -->\r\n <div class=\"p-8 text-center text-gray-500\">\r\n <div class=\"flex flex-col items-center justify-center gap-3\">\r\n <i class=\"pi pi-info-circle text-4xl text-gray-400\"></i>\r\n <p class=\"text-lg\">{{ getNoDataMessage() }}</p>\r\n </div>\r\n </div>\r\n }\r\n </td>\r\n </tr>\r\n </ng-template>\r\n\r\n @if (hasRecords()) {\r\n @if (editEnabled) {\r\n @switch (editType) {\r\n @case ('cell') {\r\n <ng-template #body let-item let-editing=\"editing\">\r\n <tr class=\"p-datatable-row p-selectable-row\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td [pEditableColumn]=\"column.field\" pEditableColumnField=\"rowData.{{column.field}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[column.field]\r\n | number: (\r\n inlineControls?.[column.field]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[column.field]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n }@else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field]?.name ?? item.rowData[column.field]?.value ?? '' }}\r\n </div>\r\n }\r\n @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id]?.[column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ columnFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td [pEditableColumn]=\"key\" pEditableColumnField=\"rowData.{{key}}\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n inlineControls?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n inlineControls?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SELECT) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[key]?.name ?? item.rowData[key]?.value ?? '' }}\r\n </div>\r\n } @else if (inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && errorConfig.fieldErrors[item.id]?.[key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">\r\n {{ keyFieldError.message }}\r\n </span>\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n @if (editType === 'cell' && editEnabled) {\r\n <td class=\"px-2 py-1 text-center\">\r\n <div class=\"flex justify-center items-center gap-2\">\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n </div>\r\n </td>\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n @case ('row') {\r\n <ng-template #body let-item let-editing=\"editing\" let-ri=\"rowIndex\">\r\n <tr [pEditableRow]=\"item\" class=\"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 border-b\">\r\n @if (selectedColumns) {\r\n @for (column of selectedColumns; track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[column.field]\"\r\n (outputValue)=\"inlineChange($event, column.field)\" (outputDebounced)=\"onEditData()\"\r\n [config]=\"inlineControls?.[column.field] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[column.field]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | number: '1.2-2' }}\r\n\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[column.field] | currency: item?.currencyTypeCellConfig?.[column.field]?.currency ??\r\n 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATE) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.DATETIME_LOCAL) {\r\n <div class=\"text-left\">\r\n {{ item.rowData[column.field] | date: \"dd/MM/yyyy HH:mm\" }}\r\n </div>\r\n } @else if(inlineControls?.[column.field]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[column.field]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[column.field]?.name) {\r\n {{ item.rowData[column.field]?.name }}\r\n } @else {\r\n {{ item.rowData[column.field] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[column.field] && errorConfig.fieldErrors[item.id]?.[column.field]; as columnFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ columnFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n } @else {\r\n @for (key of keys(); track $index){\r\n <td>\r\n <div class=\"flex flex-col gap-2\">\r\n <p-cellEditor>\r\n <ng-template #input>\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\" (outputValue)=\"inlineChange($event, key)\"\r\n (outputDebounced)=\"onEditData()\" [config]=\"inlineControls?.[key] ?? {typeInput: ETypeInput.TEXT}\">\r\n </lib-inline-input>\r\n </ng-template>\r\n <ng-template #output>\r\n\r\n @if (inlineControls?.[key]?.typeInput === ETypeInput.NUMBER) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | number: '1.2-2' }}\r\n\r\n </div>\r\n }\r\n @else if(inlineControls?.[key]?.typeInput === ETypeInput.CURRENCY) {\r\n <div class=\"text-right\">\r\n {{ item.rowData[key] | currency: item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n </div>\r\n } @else if(inlineControls?.[key]?.typeInput === ETypeInput.SWITCH) {\r\n <div class=\"text-center\">\r\n @if (item.rowData[key]) {\r\n <i class=\"fa-solid fa-check text-green-500\"></i>\r\n } @else {\r\n <i class=\"fa-solid fa-times text-red-500\"></i>\r\n }\r\n </div>\r\n } @else {\r\n @if (item.rowData[key]?.name) {\r\n {{ item.rowData[key]?.name }}\r\n } @else {\r\n {{ item.rowData[key] }}\r\n }\r\n }\r\n\r\n\r\n </ng-template>\r\n </p-cellEditor>\r\n\r\n @if (rowErrorConfig; as errorConfig) {\r\n @if (errorConfig.isEnabled && enableErrors && !rowFieldsHasValue()[key] && errorConfig.fieldErrors[item.id]?.[key]; as keyFieldError) {\r\n <span class=\"text-red-500 italic text-xs\">{{ keyFieldError.message }}</span>\r\n }\r\n }\r\n </div>\r\n </td>\r\n }\r\n }\r\n <td>\r\n <div class=\"flex justify-center items-center gap-2\">\r\n @if(!editing){\r\n <lib-button-ng pButton pRipple pInitEditableRow [buttonConfig]=\"getEditInitButton(item.id)\"\r\n (onClick)=\"onRowEditInit(item)\"></lib-button-ng>\r\n @if(!editConfig()?.rowEditConfig?.isDisabledDeleteButton){\r\n <lib-button-ng [buttonConfig]=\"getDeleteRowButton()\" (onClick)=\"deleteRow(item)\"></lib-button-ng>\r\n }\r\n }\r\n @if(editing){\r\n @if (hasErrorValues(rowErrorConfig?.fieldErrors?.[item.id] ?? {})) {\r\n <lib-button-ng [buttonConfig]=\"editSaveButtonWithErrors()\"\r\n (onClick)=\"onEditSaveWithErrors()\"></lib-button-ng>\r\n }\r\n @else {\r\n <lib-button-ng pButton pRipple pSaveEditableRow [buttonConfig]=\"editSaveButton()\"\r\n (onClick)=\"onRowEditSave(item)\"></lib-button-ng>\r\n }\r\n <lib-button-ng pButton pRipple pCancelEditableRow [buttonConfig]=\"editCancelButton()\"\r\n (onClick)=\"onRowEditCancel(item, ri)\"></lib-button-ng>\r\n }\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n } @else {\r\n\r\n <ng-template #body let-item let-expanded=\"expanded\">\r\n <tr class=\"p-datatable-row p-selectable-row\" [ngClass]=\"{\r\n 'bg-gray-50 dark:bg-gray-800 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700': item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600': !item.onClick && !item.isSelected && !item.isLoading,\r\n 'bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 hover:bg-blue-200 dark:hover:bg-blue-800': item.isSelected && !item.isLoading,\r\n 'skeleton-row': item.isLoading\r\n }\" (click)=\"item?.isLoading ? null : onRowClick(item)\">\r\n\r\n @if (rowExpansionConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" [class.skeleton-cell]=\"item.isLoading\"\r\n [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <lib-button-ng [buttonConfig]=\"rowExpansionButton(expanded)()\" type=\"button\" pRipple\r\n [pRowToggler]=\"item\"></lib-button-ng>\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @if (selectionTableConfig?.isEnabled) {\r\n <td (click)=\"$event.stopPropagation()\" alignFrozen=\"left\" pFrozenColumn class=\"shadow-lg\"\r\n [class.skeleton-cell]=\"item.isLoading\" [style.height]=\"item.isLoading ? '3rem' : 'auto'\">\r\n @if (!item.isLoading) {\r\n <p-tableCheckbox [id]=\"item\" [value]=\"item\" />\r\n } @else {\r\n <div class=\"skeleton-content\"></div>\r\n }\r\n </td>\r\n }\r\n\r\n @for (key of keys(); track $index) {\r\n @if (isThatItemInTheProductSelection(key)) {\r\n <td [id]=\"key\" class=\"p-datatable-cell\" [style.height]=\"item.isLoading ? '3rem' : 'min-content'\"\r\n alignFrozen=\"right\" pFrozenColumn [ngClass]=\"{\r\n 'p-frozen-column': frozenHandle(frozenColumnConfigByKey?.[key]),\r\n 'text-center': item.rowDataButtons?.[key] || item.typeCell?.[key] === ETypeInput.BADGE,\r\n 'skeleton-cell': item.isLoading\r\n }\" [frozen]=\"frozenHandle(frozenColumnConfigByKey?.[key])\">\r\n @if (item.isLoading) {\r\n <div class=\"skeleton-content\"></div>\r\n } @else {\r\n @if (item.rowDataButtons?.[key]) {\r\n <div class=\"flex gap-4 w-full justify-center items-center\">\r\n @for (btn of item.rowDataButtons[key]; track $index) {\r\n @if (btn) {\r\n <lib-button-ng class=\"w-full\" (click)=\"$event.stopPropagation()\" [buttonConfig]=\"btn\"></lib-button-ng>\r\n }\r\n }\r\n </div>\r\n } @else {\r\n @switch (item.typeCell?.[key]) {\r\n @case (ETypeInput.IMAGE) {\r\n <img [src]=\"item.rowData[key]\" alt=\"Image\" class=\"w-10 h-10 mx-auto\">\r\n }\r\n @case (ETypeInput.DATE) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n }\r\n @case (ETypeInput.DATETIME_LOCAL) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy HH:mm\" }}\r\n }\r\n @case (ETypeInput.CURRENCY) {\r\n {{item?.currencyTypeCellConfig?.[key]?.currency}} {{ item.rowData[key] | currency:\r\n item?.currencyTypeCellConfig?.[key]?.currency ?? 'USD' }}\r\n }\r\n @case (ETypeInput.BADGE) {\r\n <lib-badge-ng [config]=\"item.rowData[key]\"></lib-badge-ng>\r\n }\r\n @case (ETypeInput.COMPONENT) {\r\n <ng-container\r\n *ngTemplateOutlet=\"item.rowDataComponents?.[key]; context: { $implicit: item.raw }\"></ng-container>\r\n }\r\n @case (ETypeInput.INPUT) {\r\n <lib-inline-input [(ngModel)]=\"item.rowData[key]\"\r\n [config]=\"item.rowDataInput?.[key] ?? {typeInput: ETypeInput.TEXT}\"\r\n (outputValue)=\"handleCheckValue()\"\r\n >\r\n </lib-inline-input>\r\n }\r\n @default {\r\n @if (isDate(item.rowData[key])) {\r\n {{ item.rowData[key] | date: \"dd/MM/yyyy\" }}\r\n } @else if (typeof item.rowData[key] === \"string\") {\r\n {{ item.rowData[key] }}\r\n } @else if (isPrimeNgSelection(item.rowData[key])) {\r\n {{ item.rowData[key].name }}\r\n } @else if(typeof item.rowData[key] === \"number\") {\r\n <p class=\"text-right\">\r\n {{\r\n item.rowData[key]\r\n | number: (\r\n item.rowDataInput?.[key]?.numberConfig?.minFractionDigits === 0 &&\r\n item.rowDataInput?.[key]?.numberConfig?.maxFractionDigits === 0\r\n ? '1.0-0'\r\n : '1.2-2'\r\n )\r\n }}\r\n </p>\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n }\r\n </tr>\r\n </ng-template>\r\n }\r\n }\r\n\r\n <ng-template #footer>\r\n @if (footerEnabled) {\r\n @for (row of footerRows; track $index) {\r\n <tr class=\"p-datatable-row p-datatable-footer-row\">\r\n @for (cell of row; track $index) {\r\n <td colSpan=\"{{ cell.colSpan }}\" class=\"{{ cell.class }} text-right font-bold p-3 pb-0\">{{\r\n applyPipe(cell.value,\r\n cell.pipeConfig) }}</td>\r\n\r\n }\r\n </tr>\r\n }\r\n\r\n }\r\n </ng-template>\r\n <ng-template #expandedrow let-item>\r\n <tr>\r\n <td colspan=\"100%\">\r\n <div class=\"p-datatable-row-expansion\">\r\n <ng-container *ngTemplateOutlet=\"currentItemTemplate; context: { $implicit: item }\"></ng-container>\r\n\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n @if (showBottomToolbar()) {\r\n <div class=\"mt-6 p-datatable-footer sticky bottom-2 z-9 animate__animated animate__fadeIn\">\r\n <lib-toolbar-ng>\r\n @if (showManagementSelectionConfig()) {\r\n <div toolbarStart\r\n class=\"p-datatable-footer-content flex items-center gap-3 px-4 rounded-lg animate__animated animate__fadeIn\">\r\n <span class=\"font-medium text-gray-700 dark:text-gray-300\">{{ getSelectedItemsLabel() }}</span>\r\n <div class=\"p-datatable-footer-badge flex items-center justify-center min-w-[28px] h-7 px-2 rounded-md\">\r\n <span class=\"font-semibold text-gray-900 dark:text-gray-100\">{{\r\n totalItemsSelected().toLocaleString()\r\n }}</span>\r\n </div>\r\n <span class=\"text-sm text-gray-600\">{{ getRecordsLabel() }}</span>\r\n <lib-button-ng [buttonConfig]=\"showSelectedItemsManagementButton()\"></lib-button-ng>\r\n </div>\r\n }\r\n </lib-toolbar-ng>\r\n </div>\r\n }\r\n</div>\r\n@if (httpMessage()) {\r\n<lib-http-message [(httpMessage)]=\"httpMessage\"></lib-http-message>\r\n}", styles: [".cursor-pointer{cursor:pointer}.empty-data-message{text-align:center;padding:2rem;color:#6c757d;font-style:italic}.table-title-container{background:var(--p-surface-50);border-bottom:1px solid var(--p-surface-200);padding:1.25rem 2rem;position:relative}.table-title{color:var(--p-text-color);font-size:1.5rem;font-weight:600;text-align:center;margin:0;letter-spacing:-.025em;text-shadow:0 1px 2px rgba(0,0,0,.05);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative}.table-title:after{content:\"\";position:absolute;bottom:-.5rem;left:50%;transform:translate(-50%);width:60px;height:2px;background:linear-gradient(90deg,var(--p-primary-color),var(--p-primary-600));border-radius:1px}:host ::ng-deep .p-datatable-paginator{background:var(--p-surface-100);border-top:1px solid var(--p-surface-300);padding:1rem}:host ::ng-deep .p-datatable-paginator .p-paginator{background:transparent;border:none;padding:0}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-300);border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-100);border-color:var(--p-surface-300);color:var(--p-text-muted-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color);font-weight:500}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-200);border:1px solid var(--p-surface-300);color:var(--p-text-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.skeleton-row{pointer-events:none;-webkit-user-select:none;user-select:none;min-height:3rem}.skeleton-cell{position:relative;overflow:hidden;min-height:3rem;padding:.75rem .5rem!important}.skeleton-cell .skeleton-content{position:absolute;inset:.5rem;min-height:1.5rem;background:linear-gradient(90deg,#d1d5db33,#d1d5db66,#d1d5db33);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}:host-context(.my-app-dark) .skeleton-cell .skeleton-content{background:linear-gradient(90deg,#4b556333,#4b556366,#4b556333);background-size:200% 100%}:host ::ng-deep .p-datatable .p-datatable-tbody .skeleton-row .skeleton-cell{width:auto;min-width:fit-content}:host-context(.my-app-dark) .table-title-container{background:var(--p-surface-800);border-bottom-color:var(--p-surface-700)}:host-context(.my-app-dark) .table-title{color:var(--p-text-color);background:linear-gradient(135deg,var(--p-text-color) 0%,var(--p-text-muted-color) 100%);background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator{background:var(--p-surface-900);border-top-color:var(--p-surface-800)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-pages .p-paginator-page.p-highlight{background:var(--p-primary-color);border-color:var(--p-primary-color);color:var(--p-primary-contrast-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:hover,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:hover{background:var(--p-surface-700);border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-first:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-prev:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-next:disabled,:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-last:disabled{background:var(--p-surface-900);border-color:var(--p-surface-800);color:var(--p-text-muted-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-paginator-current{color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown{background:var(--p-surface-800);border-color:var(--p-surface-700);color:var(--p-text-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:hover{border-color:var(--p-primary-color)}:host-context(.my-app-dark) ::ng-deep .p-datatable-paginator .p-paginator .p-dropdown:focus{border-color:var(--p-primary-color);box-shadow:0 0 0 2px var(--p-primary-color-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.justify-center{justify-content:center}.items-center{align-items:center}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.text-gray-400{color:#9ca3af}.text-gray-500{color:#6b7280}.text-gray-600{color:#4b5563}.text-gray-700{color:#374151}.text-gray-900{color:#111827}.text-blue-500{color:#3b82f6}.text-red-500{color:#ef4444}.text-green-500{color:#22c55e}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.italic{font-style:italic}.w-full{width:100%}.w-10{width:2.5rem}.h-10{height:2.5rem}.h-7{height:1.75rem}.min-w-28{min-width:28px}.mx-auto{margin-left:auto;margin-right:auto}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-top:0;padding-bottom:0}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-4{padding-left:1rem;padding-right:1rem}.pb-0{padding-bottom:0}.bg-gray-50{background-color:#f9fafb}.bg-gray-100{background-color:#f3f4f6}.bg-gray-200{background-color:#e5e7eb}.bg-gray-600{background-color:#4b5563}.bg-gray-700{background-color:#374151}.bg-gray-800{background-color:#1f2937}.bg-blue-100{background-color:#dbeafe}.bg-blue-200{background-color:#bfdbfe}.bg-blue-800{background-color:#1e40af}.bg-blue-900{background-color:#1e3a8a}.bg-green-200{background-color:#bbf7d0}.border-b{border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--p-surface-300)}.border-l-4{border-left-width:4px;border-left-style:solid}.border-blue-500{border-color:#3b82f6}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.shadow-sm{box-shadow:0 1px 2px #0000000d}.shadow-lg{box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.sticky{position:sticky}.top-0{top:0}.bottom-2{bottom:.5rem}.bottom-18{bottom:4.5rem}.z-9{z-index:9}.z-10{z-index:10}.z-30{z-index:30}.hover\\:bg-gray-50:hover{background-color:#f9fafb}.hover\\:bg-gray-100:hover{background-color:#f3f4f6}.hover\\:bg-gray-200:hover{background-color:#e5e7eb}.hover\\:bg-blue-200:hover{background-color:#bfdbfe}.hover\\:bg-blue-800:hover{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:bg-gray-800{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:bg-gray-700{background-color:#374151}:host-context(.my-app-dark) .dark\\:bg-gray-600{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:bg-blue-900{background-color:#1e3a8a}:host-context(.my-app-dark) .dark\\:bg-blue-800{background-color:#1e40af}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-800:hover{background-color:#1f2937}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-700:hover{background-color:#374151}:host-context(.my-app-dark) .dark\\:hover\\:bg-gray-600:hover{background-color:#4b5563}:host-context(.my-app-dark) .dark\\:hover\\:bg-blue-800:hover{background-color:#1e40af}.animate__animated{animation-duration:1s;animation-fill-mode:both}.animate__fadeIn{animation-name:fadeIn}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
3634
3668
|
}], ctorParameters: () => [], propDecorators: { dt: [{
|
|
3635
3669
|
type: ViewChild,
|
|
3636
3670
|
args: ['dt']
|
|
@@ -3711,4 +3745,4 @@ de13d65e8a0357ce9f2e18c899c8e7f6f728181baa031761ecdd7ef5cb166eb2
|
|
|
3711
3745
|
*/
|
|
3712
3746
|
|
|
3713
3747
|
export { AminatedContainerComponent as A, BaseDialogComponent as B, DisabledContainerComponent as D, ETypeInput as E, FormComponent as F, HttpMessageComponent as H, InlineInputComponent as I, LibComponentsService as L, SpeedDialComponent as S, TableNgComponent as T, ButtonNgComponent as a, LibComponentsComponent as b, SpeedDialService as c, SpeedDialNgComponent as d };
|
|
3714
|
-
//# sourceMappingURL=ln-20-lib-components-ln-20-lib-components-
|
|
3748
|
+
//# sourceMappingURL=ln-20-lib-components-ln-20-lib-components-CYlSQ3zg.mjs.map
|