@acontplus/ng-components 2.1.14 → 2.1.16

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.
@@ -344,38 +344,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
344
344
  /**
345
345
  * Servicio centralizado para manejar z-index de todos los diálogos
346
346
  * Asegura que los diálogos siempre aparezcan en el orden correcto
347
+ * Los AlertDialogs siempre tienen prioridad sobre otros diálogos
347
348
  */
348
349
  class DialogZIndexService {
349
- static currentZIndex = 1000;
350
+ // Rangos de z-index por tipo de diálogo
351
+ static Z_INDEX_RANGES = {
352
+ normal: { base: 1000, current: 1000 }, // Diálogos normales: 1000-1999
353
+ alert: { base: 2000, current: 2000 }, // AlertDialogs: 2000-2999 (siempre encima)
354
+ toast: { base: 3000, current: 3000 }, // Toasts: 3000-3999 (máxima prioridad)
355
+ };
350
356
  static Z_INDEX_INCREMENT = 10;
351
357
  /**
352
- * Obtiene el siguiente z-index disponible
358
+ * Obtiene el siguiente z-index disponible para un tipo específico de diálogo
359
+ * @param type Tipo de diálogo (normal, alert, toast)
353
360
  * @returns El próximo z-index a usar
354
361
  */
355
- getNextZIndex() {
356
- DialogZIndexService.currentZIndex += DialogZIndexService.Z_INDEX_INCREMENT;
357
- return DialogZIndexService.currentZIndex;
362
+ getNextZIndex(type = 'normal') {
363
+ const range = DialogZIndexService.Z_INDEX_RANGES[type];
364
+ range.current += DialogZIndexService.Z_INDEX_INCREMENT;
365
+ return range.current;
366
+ }
367
+ /**
368
+ * Obtiene el z-index actual más alto para un tipo específico
369
+ * @param type Tipo de diálogo
370
+ * @returns El z-index más alto actualmente en uso para ese tipo
371
+ */
372
+ getCurrentZIndex(type = 'normal') {
373
+ return DialogZIndexService.Z_INDEX_RANGES[type].current;
358
374
  }
359
375
  /**
360
- * Obtiene el z-index actual más alto
361
- * @returns El z-index más alto actualmente en uso
376
+ * Obtiene el z-index más alto de todos los tipos
377
+ * @returns El z-index más alto de todos los diálogos
362
378
  */
363
- getCurrentZIndex() {
364
- return DialogZIndexService.currentZIndex;
379
+ getHighestZIndex() {
380
+ return Math.max(...Object.values(DialogZIndexService.Z_INDEX_RANGES).map(range => range.current));
365
381
  }
366
382
  /**
367
383
  * Resetea el contador de z-index (útil para testing)
384
+ * @param type Tipo específico a resetear, o undefined para resetear todos
368
385
  */
369
- reset() {
370
- DialogZIndexService.currentZIndex = 1000;
386
+ reset(type) {
387
+ if (type) {
388
+ const range = DialogZIndexService.Z_INDEX_RANGES[type];
389
+ range.current = range.base;
390
+ }
391
+ else {
392
+ // Resetear todos los tipos
393
+ Object.entries(DialogZIndexService.Z_INDEX_RANGES).forEach(([_, range]) => {
394
+ range.current = range.base;
395
+ });
396
+ }
371
397
  }
372
398
  /**
373
399
  * Aplica z-index a un diálogo específico
374
400
  * @param dialogRef Referencia al diálogo
375
- * @param zIndex Z-index a aplicar (opcional, si no se proporciona usa getNextZIndex())
401
+ * @param type Tipo de diálogo (determina el rango de z-index)
402
+ * @param zIndex Z-index específico a aplicar (opcional)
376
403
  */
377
- applyZIndex(dialogRef, zIndex) {
378
- const targetZIndex = zIndex || this.getNextZIndex();
404
+ applyZIndex(dialogRef, type = 'normal', zIndex) {
405
+ const targetZIndex = zIndex || this.getNextZIndex(type);
379
406
  setTimeout(() => {
380
407
  const overlayRef = dialogRef._overlayRef;
381
408
  if (overlayRef) {
@@ -383,8 +410,23 @@ class DialogZIndexService {
383
410
  const backdrop = overlayRef.backdropElement;
384
411
  if (pane) {
385
412
  pane.style.zIndex = (targetZIndex + 2).toString();
413
+ // Agregar atributo data para debugging
414
+ pane.setAttribute('data-dialog-type', type);
415
+ pane.setAttribute('data-z-index', targetZIndex.toString());
416
+ // Para toasts, agregar clase especial para styling
417
+ if (type === 'toast') {
418
+ pane.classList.add('toast-overlay');
419
+ // Los toasts no deben bloquear interacciones
420
+ pane.style.pointerEvents = 'none';
421
+ // Pero el contenido del toast sí debe ser clickeable
422
+ const dialogContainer = pane.querySelector('.mat-mdc-dialog-container, .mat-dialog-container');
423
+ if (dialogContainer) {
424
+ dialogContainer.style.pointerEvents = 'auto';
425
+ }
426
+ }
386
427
  }
387
- if (backdrop) {
428
+ // Los toasts no tienen backdrop, pero si existe, configurarlo
429
+ if (backdrop && type !== 'toast') {
388
430
  backdrop.style.zIndex = (targetZIndex + 1).toString();
389
431
  }
390
432
  }
@@ -393,12 +435,14 @@ class DialogZIndexService {
393
435
  /**
394
436
  * Trae un diálogo al frente (usado por drag functionality)
395
437
  * @param element Elemento del diálogo a traer al frente
438
+ * @param type Tipo de diálogo
396
439
  */
397
- bringToFront(element) {
440
+ bringToFront(element, type = 'normal') {
398
441
  const pane = element.closest('.cdk-overlay-pane');
399
442
  if (pane) {
400
- const newZIndex = this.getNextZIndex();
443
+ const newZIndex = this.getNextZIndex(type);
401
444
  pane.style.zIndex = (newZIndex + 2).toString();
445
+ pane.setAttribute('data-z-index', newZIndex.toString());
402
446
  // También actualizar el backdrop si existe
403
447
  const backdrop = pane.parentElement?.querySelector('.cdk-overlay-backdrop');
404
448
  if (backdrop) {
@@ -406,6 +450,56 @@ class DialogZIndexService {
406
450
  }
407
451
  }
408
452
  }
453
+ /**
454
+ * Fuerza un diálogo a estar siempre encima de todos los demás
455
+ * Útil para alertas críticas que deben tener máxima prioridad
456
+ * @param dialogRef Referencia al diálogo
457
+ */
458
+ forceToTop(dialogRef) {
459
+ const highestZIndex = this.getHighestZIndex();
460
+ const topZIndex = highestZIndex + DialogZIndexService.Z_INDEX_INCREMENT;
461
+ setTimeout(() => {
462
+ const overlayRef = dialogRef._overlayRef;
463
+ if (overlayRef) {
464
+ const pane = overlayRef.overlayElement;
465
+ const backdrop = overlayRef.backdropElement;
466
+ if (pane) {
467
+ pane.style.zIndex = (topZIndex + 2).toString();
468
+ pane.setAttribute('data-z-index', topZIndex.toString());
469
+ pane.setAttribute('data-forced-top', 'true');
470
+ }
471
+ if (backdrop) {
472
+ backdrop.style.zIndex = (topZIndex + 1).toString();
473
+ }
474
+ }
475
+ }, 0);
476
+ }
477
+ /**
478
+ * Obtiene todos los toasts activos
479
+ * @returns Array de elementos de toast activos
480
+ */
481
+ getActiveToasts() {
482
+ return Array.from(document.querySelectorAll('.cdk-overlay-pane[data-dialog-type="toast"]'));
483
+ }
484
+ /**
485
+ * Cierra todos los toasts activos
486
+ */
487
+ closeAllToasts() {
488
+ const toasts = this.getActiveToasts();
489
+ toasts.forEach(toast => {
490
+ const closeButton = toast.querySelector('[mat-dialog-close], .toast-close-button');
491
+ if (closeButton) {
492
+ closeButton.click();
493
+ }
494
+ });
495
+ }
496
+ /**
497
+ * Obtiene el número de toasts activos
498
+ * @returns Número de toasts actualmente visibles
499
+ */
500
+ getActiveToastCount() {
501
+ return this.getActiveToasts().length;
502
+ }
409
503
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DialogZIndexService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
410
504
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DialogZIndexService, providedIn: 'root' });
411
505
  }
@@ -1718,6 +1812,8 @@ class AlertDialogService {
1718
1812
  position: 'center',
1719
1813
  draggable: false,
1720
1814
  allowMultiple: false, // Por defecto no permitir múltiples alerts
1815
+ forceToTop: true, // Por defecto los alerts siempre van encima
1816
+ dialogType: 'alert', // Por defecto usar el tipo alert (z-index alto)
1721
1817
  // Nuevas opciones por defecto
1722
1818
  layout: 'modern',
1723
1819
  iconPosition: 'left',
@@ -1727,7 +1823,6 @@ class AlertDialogService {
1727
1823
  animation: 'fade',
1728
1824
  animationDuration: 300,
1729
1825
  toastMode: false,
1730
- toastPosition: 'top-right',
1731
1826
  autoClose: true,
1732
1827
  progressBar: true,
1733
1828
  };
@@ -1766,6 +1861,8 @@ class AlertDialogService {
1766
1861
  position: 'center',
1767
1862
  draggable: false,
1768
1863
  allowMultiple: false,
1864
+ forceToTop: true,
1865
+ dialogType: 'alert',
1769
1866
  };
1770
1867
  }
1771
1868
  /**
@@ -1783,14 +1880,22 @@ class AlertDialogService {
1783
1880
  mergedOptions.showConfirmButton = mergedOptions.showConfirmButton ?? false;
1784
1881
  mergedOptions.timer = mergedOptions.timer || 4000;
1785
1882
  mergedOptions.timerProgressBar = mergedOptions.progressBar ?? true;
1786
- mergedOptions.position = this.getToastPosition(mergedOptions.toastPosition || 'top-right');
1883
+ // Si no se especificó position, usar por defecto para toasts
1884
+ if (!mergedOptions.position) {
1885
+ mergedOptions.position = 'top-end'; // Por defecto top-right para toasts
1886
+ }
1787
1887
  mergedOptions.disableClose = false;
1788
1888
  mergedOptions.animation = mergedOptions.animation || 'slide';
1789
- }
1889
+ mergedOptions.dialogType = 'toast'; // Los toasts usan el z-index más alto
1890
+ // Configuración específica para toasts no-intrusivos
1891
+ mergedOptions.closeOnBackdropClick = false; // No hay backdrop en toasts
1892
+ mergedOptions.allowEscapeKey = false; // ESC no debe cerrar toasts
1893
+ mergedOptions.allowMultiple = true; // Permitir múltiples toasts
1894
+ }
1895
+ // Determinar el tipo de diálogo para z-index
1896
+ const dialogType = mergedOptions.dialogType || (mergedOptions.toastMode ? 'toast' : 'alert');
1790
1897
  // Calcular posición del diálogo
1791
- const position = mergedOptions.toastMode
1792
- ? this.getToastDialogPosition(mergedOptions.toastPosition || 'top-right')
1793
- : this.getDialogPosition(mergedOptions.position || 'center');
1898
+ const position = this.getDialogPosition(mergedOptions.position || 'center');
1794
1899
  const dialogRef = this.dialog.open(AlertDialog, {
1795
1900
  width: mergedOptions.width,
1796
1901
  minWidth: mergedOptions.minWidth,
@@ -1804,10 +1909,17 @@ class AlertDialogService {
1804
1909
  closeOnNavigation: true,
1805
1910
  autoFocus: mergedOptions.focusConfirm !== false,
1806
1911
  restoreFocus: true,
1807
- hasBackdrop: !mergedOptions.toastMode,
1912
+ hasBackdrop: !mergedOptions.toastMode, // Los toasts NO tienen backdrop
1808
1913
  });
1809
1914
  // Aplicar z-index dinámico usando el servicio centralizado
1810
- this.zIndexService.applyZIndex(dialogRef);
1915
+ if (mergedOptions.forceToTop) {
1916
+ // Si se requiere forzar al tope, usar forceToTop
1917
+ this.zIndexService.forceToTop(dialogRef);
1918
+ }
1919
+ else {
1920
+ // Usar el tipo de diálogo apropiado para z-index
1921
+ this.zIndexService.applyZIndex(dialogRef, dialogType);
1922
+ }
1811
1923
  // Callbacks de ciclo de vida
1812
1924
  if (mergedOptions.willOpen) {
1813
1925
  mergedOptions.willOpen();
@@ -1941,25 +2053,64 @@ class AlertDialogService {
1941
2053
  });
1942
2054
  }
1943
2055
  /**
1944
- * Toast notification (auto-cierre, posición personalizada)
2056
+ * Toast notification (auto-cierre, posición personalizada, no-intrusivo)
1945
2057
  */
1946
2058
  toast(options) {
1947
2059
  const opts = typeof options === 'string' ? { message: options } : options;
1948
2060
  return this.fire({
2061
+ // Valores por defecto que pueden ser sobrescritos
1949
2062
  timer: 3000,
1950
- timerProgressBar: true,
1951
2063
  showConfirmButton: false,
1952
- position: 'top-end',
2064
+ position: 'bottom-start', // Valor por defecto
1953
2065
  width: '350px',
2066
+ toastMode: true,
2067
+ dialogType: 'toast',
2068
+ forceToTop: false,
2069
+ allowMultiple: true,
2070
+ disableClose: true,
2071
+ closeOnBackdropClick: false,
2072
+ allowEscapeKey: false,
2073
+ allowEnterKey: false,
2074
+ autoClose: true,
2075
+ progressBar: true,
2076
+ // Los valores del usuario sobrescriben los por defecto
1954
2077
  ...opts,
1955
2078
  });
1956
2079
  }
2080
+ /**
2081
+ * Alerta crítica que siempre aparece encima de todo
2082
+ */
2083
+ critical(options) {
2084
+ const opts = typeof options === 'string'
2085
+ ? { message: options, title: '¡Atención!' }
2086
+ : { title: '¡Atención!', ...options };
2087
+ return this.fire({
2088
+ ...opts,
2089
+ type: 'error',
2090
+ forceToTop: true,
2091
+ disableClose: true,
2092
+ closeOnBackdropClick: false,
2093
+ allowEscapeKey: false,
2094
+ });
2095
+ }
1957
2096
  /**
1958
2097
  * Cerrar todos los diálogos abiertos
1959
2098
  */
1960
2099
  closeAll() {
1961
2100
  this.dialog.closeAll();
1962
2101
  }
2102
+ /**
2103
+ * Cerrar solo los toasts activos (mantener otros diálogos abiertos)
2104
+ */
2105
+ closeAllToasts() {
2106
+ this.zIndexService.closeAllToasts();
2107
+ }
2108
+ /**
2109
+ * Obtener el número de toasts activos
2110
+ */
2111
+ getActiveToastCount() {
2112
+ return this.zIndexService.getActiveToastCount();
2113
+ }
1963
2114
  getDialogPosition(position) {
1964
2115
  const positions = {
1965
2116
  top: { top: '20px' },
@@ -2012,28 +2163,6 @@ class AlertDialogService {
2012
2163
  }
2013
2164
  return classes;
2014
2165
  }
2015
- getToastPosition(position) {
2016
- const positionMap = {
2017
- 'top-right': 'top-end',
2018
- 'top-left': 'top-start',
2019
- 'bottom-right': 'bottom-end',
2020
- 'bottom-left': 'bottom-start',
2021
- 'top-center': 'top',
2022
- 'bottom-center': 'bottom',
2023
- };
2024
- return positionMap[position] || 'top-end';
2025
- }
2026
- getToastDialogPosition(position) {
2027
- const positions = {
2028
- 'top-right': { top: '20px', right: '20px' },
2029
- 'top-left': { top: '20px', left: '20px' },
2030
- 'bottom-right': { bottom: '20px', right: '20px' },
2031
- 'bottom-left': { bottom: '20px', left: '20px' },
2032
- 'top-center': { top: '20px' },
2033
- 'bottom-center': { bottom: '20px' },
2034
- };
2035
- return positions[position] || positions['top-right'];
2036
- }
2037
2166
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2038
2167
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: AlertDialogService, providedIn: 'root' });
2039
2168
  }