ngx-dsxlibrary 2.21.68 → 2.21.69

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.
@@ -1,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, forwardRef, Component, EventEmitter, effect, Output, viewChild, signal, Input, model, inject, computed, Injectable, isDevMode, InjectionToken, output, HostBinding, ChangeDetectorRef, untracked, Pipe, ViewEncapsulation, HostListener, Directive, NgZone, ElementRef, NgModule, Injector } from '@angular/core';
2
+ import { input, forwardRef, Component, EventEmitter, effect, Output, viewChild, signal, Input, model, inject, computed, Injectable, isDevMode, InjectionToken, output, HostBinding, ChangeDetectorRef, untracked, Pipe, ViewEncapsulation, HostListener, Directive, NgZone, ElementRef, ChangeDetectionStrategy, NgModule, Injector, ViewChild } from '@angular/core';
3
3
  import * as i1 from '@angular/forms';
4
4
  import { FormsModule, NG_VALUE_ACCESSOR, AbstractControl, FormControl, NG_VALIDATORS, FormBuilder, Validators, ReactiveFormsModule, NgControl, FormGroup } from '@angular/forms';
5
5
  import * as i2 from 'primeng/togglebutton';
6
6
  import { ToggleButtonModule } from 'primeng/togglebutton';
7
7
  import * as i1$1 from '@angular/common';
8
- import { CommonModule, AsyncPipe, DecimalPipe, Location } from '@angular/common';
8
+ import { CommonModule, AsyncPipe, DecimalPipe, Location, JsonPipe } from '@angular/common';
9
9
  import * as i2$1 from 'primeng/tree';
10
10
  import { TreeModule } from 'primeng/tree';
11
11
  import * as i3 from 'primeng/api';
@@ -54,14 +54,14 @@ import { CardModule } from 'primeng/card';
54
54
  import { CheckboxModule } from 'primeng/checkbox';
55
55
  import { ContextMenuModule } from 'primeng/contextmenu';
56
56
  import { DataViewModule } from 'primeng/dataview';
57
- import { DatePickerModule } from 'primeng/datepicker';
57
+ import { DatePickerModule, DatePicker } from 'primeng/datepicker';
58
58
  import { DividerModule } from 'primeng/divider';
59
59
  import { DrawerModule } from 'primeng/drawer';
60
60
  import { FieldsetModule } from 'primeng/fieldset';
61
61
  import { IconFieldModule } from 'primeng/iconfield';
62
62
  import { InputIconModule } from 'primeng/inputicon';
63
63
  import { InputMaskModule } from 'primeng/inputmask';
64
- import { InputNumberModule } from 'primeng/inputnumber';
64
+ import { InputNumberModule, InputNumber } from 'primeng/inputnumber';
65
65
  import { InputTextModule } from 'primeng/inputtext';
66
66
  import { KeyFilterModule } from 'primeng/keyfilter';
67
67
  import { KnobModule } from 'primeng/knob';
@@ -1079,6 +1079,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1079
1079
  args: [{ selector: 'icon-dsx', imports: [AsyncPipe], template: "<span class=\"dsx-icon\" [innerHTML]=\"svg$ | async\"></span>\r\n", styles: [":host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;width:1em;height:1em;font-size:24px;line-height:1;flex-shrink:0}.dsx-icon{display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%}:host ::ng-deep .dsx-icon svg{width:100%;height:100%;fill:currentColor;shape-rendering:geometricPrecision;stroke:currentColor;stroke-width:4px;stroke-linejoin:round;stroke-linecap:round;overflow:visible;transition:fill .2s ease,stroke .2s ease}\n"] }]
1080
1080
  }], ctorParameters: () => [{ type: IconDsxService }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }] } });
1081
1081
 
1082
+ // app-message-error.component.ts
1082
1083
  class AppMessageErrorComponent {
1083
1084
  elementRef;
1084
1085
  renderer;
@@ -1106,7 +1107,7 @@ class AppMessageErrorComponent {
1106
1107
  this.lastErrorsCount = nuevoControl.errors
1107
1108
  ? Object.keys(nuevoControl.errors).length
1108
1109
  : 0;
1109
- if (this.debugMode) {
1110
+ if (this.isDevelopmentMode() && this.debugMode) {
1110
1111
  console.log('[ERROR-COMPONENT] Control asignado:', {
1111
1112
  status: nuevoControl.status,
1112
1113
  errors: nuevoControl.errors,
@@ -1131,12 +1132,12 @@ class AppMessageErrorComponent {
1131
1132
  if (this.floatLabelElement) {
1132
1133
  this.previousInlineMarginBottom =
1133
1134
  this.floatLabelElement.style.marginBottom;
1134
- if (this.debugMode) {
1135
+ if (this.isDevelopmentMode() && this.debugMode) {
1135
1136
  console.log('[ERROR-COMPONENT] FloatLabel encontrado, modo absoluto');
1136
1137
  }
1137
1138
  }
1138
1139
  else {
1139
- if (this.debugMode) {
1140
+ if (this.isDevelopmentMode() && this.debugMode) {
1140
1141
  console.log('[ERROR-COMPONENT] No hay FloatLabel, modo estático');
1141
1142
  }
1142
1143
  }
@@ -1145,7 +1146,8 @@ class AppMessageErrorComponent {
1145
1146
  entries.forEach((entry) => {
1146
1147
  const wasVisible = this.isElementAttachedAndVisible;
1147
1148
  this.isElementAttachedAndVisible = entry.isIntersecting;
1148
- if (this.debugMode &&
1149
+ if (this.isDevelopmentMode() &&
1150
+ this.debugMode &&
1149
1151
  wasVisible !== this.isElementAttachedAndVisible) {
1150
1152
  console.log('[ERROR-COMPONENT] Visibilidad:', this.isElementAttachedAndVisible);
1151
1153
  }
@@ -1170,7 +1172,7 @@ class AppMessageErrorComponent {
1170
1172
  this.control.touched !== this.lastControlTouched ||
1171
1173
  this.control.dirty !== this.lastControlDirty ||
1172
1174
  currentErrorsCount !== this.lastErrorsCount) {
1173
- if (this.debugMode) {
1175
+ if (this.isDevelopmentMode() && this.debugMode) {
1174
1176
  console.log('[ERROR-COMPONENT] Cambio detectado:', {
1175
1177
  invalid: this.control.invalid,
1176
1178
  touched: this.control.touched,
@@ -1241,18 +1243,140 @@ class AppMessageErrorComponent {
1241
1243
  }
1242
1244
  return this.defaultFloatLabelErrorSpace;
1243
1245
  }
1244
- formatNumber(value) {
1246
+ /**
1247
+ * Obtiene el mensaje de error de un error específico del control
1248
+ * @param errorKey - La clave del error
1249
+ * @returns El mensaje de error o un string vacío
1250
+ */
1251
+ getErrorMessage(errorKey) {
1252
+ if (!this.control || !this.control.errors) {
1253
+ return '';
1254
+ }
1255
+ const error = this.control.errors[errorKey];
1256
+ if (!error) {
1257
+ return '';
1258
+ }
1259
+ if (typeof error === 'object' && error !== null && 'message' in error) {
1260
+ return error.message;
1261
+ }
1262
+ return '';
1263
+ }
1264
+ /**
1265
+ * Obtiene el valor de un error específico del control
1266
+ * @param errorKey - La clave del error
1267
+ * @param propertyKey - La propiedad del error a obtener
1268
+ * @returns El valor de la propiedad o undefined
1269
+ */
1270
+ getErrorValue(errorKey, propertyKey) {
1271
+ if (!this.control || !this.control.errors) {
1272
+ return undefined;
1273
+ }
1274
+ const error = this.control.errors[errorKey];
1275
+ if (!error || typeof error !== 'object') {
1276
+ return undefined;
1277
+ }
1278
+ return error[propertyKey];
1279
+ }
1280
+ /**
1281
+ * Obtiene los detalles de un error de template
1282
+ * @param errorKey - La clave del error (invalidTemplateVariables o invalidTemplateStructure)
1283
+ * @returns El array de detalles o un array vacío
1284
+ */
1285
+ getTemplateErrorDetails(errorKey) {
1286
+ if (!this.control || !this.control.errors) {
1287
+ return [];
1288
+ }
1289
+ const error = this.control.errors[errorKey];
1290
+ if (!error || typeof error !== 'object' || !('details' in error)) {
1291
+ return [];
1292
+ }
1293
+ const details = error.details;
1294
+ return Array.isArray(details) ? details : [];
1295
+ }
1296
+ /**
1297
+ * Obtiene el primer detalle de un error de template
1298
+ * @param errorKey - La clave del error
1299
+ * @returns El primer detalle o string vacío
1300
+ */
1301
+ getFirstTemplateErrorDetail(errorKey) {
1302
+ const details = this.getTemplateErrorDetails(errorKey);
1303
+ return details.length > 0 ? details[0] : '';
1304
+ }
1305
+ /**
1306
+ * Obtiene el mensaje completo para similitud detectada
1307
+ * @returns El mensaje formateado
1308
+ */
1309
+ getSimilitudMessage() {
1310
+ if (!this.control || !this.control.errors) {
1311
+ return '';
1312
+ }
1313
+ const error = this.control.errors['similitudDetectada'];
1314
+ if (!error || typeof error !== 'object' || !('sugerencia' in error)) {
1315
+ return '';
1316
+ }
1317
+ return `Ya existe un registro muy similar en el sistema: "${error.sugerencia}".`;
1318
+ }
1319
+ /**
1320
+ * Obtiene el mensaje de error de un error específico del formulario
1321
+ * @param errorKey - La clave del error
1322
+ * @returns El mensaje de error o un mensaje por defecto
1323
+ */
1324
+ getFormError(errorKey) {
1325
+ if (!this.form) {
1326
+ return '';
1327
+ }
1328
+ const error = this.form.getError(errorKey);
1329
+ if (error && typeof error === 'object' && 'message' in error) {
1330
+ return error.message;
1331
+ }
1332
+ // Mensaje por defecto según el tipo de error
1333
+ switch (errorKey) {
1334
+ case 'atLeastOneRequired':
1335
+ return 'Al menos un campo es requerido';
1336
+ default:
1337
+ return 'Error en el formulario';
1338
+ }
1339
+ }
1340
+ /**
1341
+ * Formatea un número con separadores de miles (coma) y decimales (punto)
1342
+ * @param value - El valor a formatear (puede ser número o string)
1343
+ * @param showDecimals - Si se deben mostrar siempre los decimales
1344
+ * @returns String formateado con separadores de miles
1345
+ */
1346
+ formatNumber(value, showDecimals = false) {
1347
+ // Si es null o undefined, retornar string vacío
1348
+ if (value === null || value === undefined) {
1349
+ return '';
1350
+ }
1351
+ // Convertir a número
1245
1352
  const num = Number(value);
1246
- if (isNaN(num))
1247
- return String(value ?? '');
1248
- return num % 1 === 0 ? String(num) : parseFloat(num.toFixed(2)).toString();
1353
+ // Si no es un número válido, retornar el valor original como string
1354
+ if (isNaN(num)) {
1355
+ return String(value);
1356
+ }
1357
+ // Si es un número entero y no se piden decimales, mostrar solo enteros
1358
+ if (num % 1 === 0 && !showDecimals) {
1359
+ // Formatear con separadores de miles usando coma
1360
+ return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
1361
+ }
1362
+ // Para números con decimales, usar formato personalizado
1363
+ const parts = num.toFixed(2).split('.');
1364
+ const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
1365
+ const decimalPart = parts[1];
1366
+ return `${integerPart}.${decimalPart}`;
1367
+ }
1368
+ /**
1369
+ * Verifica si estamos en modo desarrollo
1370
+ */
1371
+ isDevelopmentMode() {
1372
+ return typeof window !== 'undefined' && window.ngDevMode !== false;
1249
1373
  }
1250
1374
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AppMessageErrorComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
1251
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AppMessageErrorComponent, isStandalone: true, selector: "app-message-error", inputs: { control: "control", form: "form", debugMode: "debugMode" }, ngImport: i0, template: "<div class=\"dsx-error-slot\" [class.is-visible]=\"isControlErrorVisible()\">\r\n <div class=\"dsx-error-message\">\r\n <div class=\"dsx-error-message-content\">\r\n <icon-dsx name=\"warning\"></icon-dsx>\r\n\r\n @if (control?.errors?.[\"required\"]) {\r\n El campo <strong>es requerido.</strong>\r\n } @else if (control?.errors?.[\"invalidNIT\"]) {\r\n <strong>{{ control?.errors?.[\"invalidNIT\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidCUI\"]) {\r\n <strong>{{ control?.errors?.[\"invalidCUI\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidDateRange\"]) {\r\n <strong>{{ control?.errors?.[\"invalidDateRange\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"dateNotRange\"]) {\r\n <strong>{{ control?.errors?.[\"dateNotRange\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidDate\"]) {\r\n <strong>{{ control?.errors?.[\"invalidDate\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"minimumAge\"]) {\r\n <strong>{{ control?.errors?.[\"minimumAge\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"minlength\"]) {\r\n Debe tener al menos\r\n <strong>{{ control?.errors?.[\"minlength\"]?.requiredLength }}</strong>\r\n caracteres.\r\n } @else if (control?.errors?.[\"maxlength\"]) {\r\n Debe tener como m\u00E1ximo\r\n <strong>{{ control?.errors?.[\"maxlength\"]?.requiredLength }}</strong>\r\n caracteres.\r\n } @else if (control?.errors?.[\"min\"]) {\r\n El valor m\u00EDnimo permitido es\r\n <strong>{{ formatNumber(control?.errors?.[\"min\"]?.min) }}</strong>\r\n } @else if (control?.errors?.[\"max\"]) {\r\n El valor m\u00E1ximo permitido es\r\n <strong>{{ formatNumber(control?.errors?.[\"max\"]?.max) }}</strong>\r\n } @else if (control?.errors?.[\"email\"]) {\r\n Debe ser una direcci\u00F3n de correo v\u00E1lida.\r\n } @else if (control?.errors?.[\"pattern\"]) {\r\n El campo no tiene el formato requerido.\r\n } @else if (control?.errors?.[\"alreadyValueExists\"]) {\r\n <strong>{{ control?.errors?.[\"alreadyValueExists\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidTemplateVariables\"]) {\r\n <div class=\"dsx-template-error\">\r\n <strong>\r\n {{ control?.errors?.[\"invalidTemplateVariables\"]?.message }}\r\n </strong>\r\n @if (control?.errors?.[\"invalidTemplateVariables\"]?.details?.length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ control?.errors?.[\"invalidTemplateVariables\"]?.details?.[0] }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (control?.errors?.[\"invalidTemplateStructure\"]) {\r\n <div class=\"dsx-template-error\">\r\n <strong>\r\n {{ control?.errors?.[\"invalidTemplateStructure\"]?.message }}\r\n </strong>\r\n @if (control?.errors?.[\"invalidTemplateStructure\"]?.details?.length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ control?.errors?.[\"invalidTemplateStructure\"]?.details?.[0] }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (control?.errors?.[\"similitudDetectada\"]) {\r\n Ya existe un registro muy similar en el sistema:\r\n <strong\r\n >\"{{ control?.errors?.[\"similitudDetectada\"]?.sugerencia }}\"</strong\r\n >.\r\n } @else {\r\n Existe un error a\u00FAn no identificado.\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Mensaje para formulario en general -->\r\n@if (form?.invalid && form?.dirty) {\r\n <div class=\"mt-2 mb-2\">\r\n @if (this.form?.errors?.[\"atLeastOneRequired\"]) {\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ form?.getError(\"atLeastOneRequired\")?.message }}\r\n </p-tag>\r\n }\r\n </div>\r\n}\r\n", styles: [".dsx-error-slot{display:block;max-height:0;overflow:hidden;opacity:0;transform:translateY(-4px) scale(.98);transition:max-height .3s cubic-bezier(.4,0,.2,1),opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1),margin .25s cubic-bezier(.4,0,.2,1)}.dsx-error-slot.is-visible{max-height:60px;opacity:1;transform:translateY(0) scale(1)}.dsx-error-message{display:block;width:100%}.dsx-error-message-content{display:flex;align-items:center;gap:.4rem;width:100%;box-sizing:border-box;padding:.25rem .6rem;font-size:.82rem;background:var(--dsx-error-bg, #fff2f0)!important;color:var(--dsx-error-color, #b42318)!important;border-left:3px solid var(--dsx-error-color, #b42318)!important;border-radius:.3rem;box-shadow:0 1px 2px #0000000f;line-height:1.3;animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1)}.dsx-error-icon{flex:0 0 auto;line-height:1;display:inline-flex;align-items:center;justify-content:center}.dsx-error-icon icon-dsx{transform:scale(.85);transition:transform .2s ease}.dsx-error-slot.is-visible .dsx-error-icon icon-dsx{transform:scale(1)}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:var(--dsx-error-color, #ff5a4e)!important;fill:var(--dsx-error-color, #e45036)!important}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000000f}50%{box-shadow:0 2px 8px #b4231826}to{box-shadow:0 1px 2px #0000000f}}.dsx-error-slot.is-visible .dsx-error-message-content{animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1),errorPulse .4s ease .15s}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:10;pointer-events:none}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.08rem}:host-context(.p-floatlabel) .dsx-error-message-content{padding:.2rem .6rem .2rem .4rem}:host-context(:not(.p-floatlabel)){display:block;width:100%}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.15rem;margin-bottom:0}:host-context(:not(.p-floatlabel)) .dsx-error-message-content{padding:.2rem .6rem}@media(max-width:640px){.dsx-error-message-content{padding:.15rem .5rem;font-size:.75rem;gap:.3rem}.dsx-error-icon icon-dsx{transform:scale(.8)}.dsx-error-slot{transition:max-height .25s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-4px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.05rem}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.1rem}}@media(prefers-color-scheme:dark){.dsx-error-message-content{background:#2d1a1a;border-left-color:#ef4444;color:#fca5a5}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:#ef4444!important;fill:#ef4444!important}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000004d}50%{box-shadow:0 2px 8px #ef444433}to{box-shadow:0 1px 2px #0000004d}}}\n"], dependencies: [{ kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$2.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }] });
1375
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: AppMessageErrorComponent, isStandalone: true, selector: "dsx-message-error", inputs: { control: "control", form: "form", debugMode: "debugMode" }, ngImport: i0, template: "<div class=\"dsx-error-slot\" [class.is-visible]=\"isControlErrorVisible()\">\r\n <div class=\"dsx-error-message\">\r\n <div class=\"dsx-error-message-content\">\r\n <icon-dsx name=\"warning\"></icon-dsx>\r\n\r\n <!-- Usamos control.errors en lugar de control?.errors -->\r\n @if (control && control.errors && control.errors[\"required\"]) {\r\n El campo <strong>es requerido.</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidNIT\"]) {\r\n <strong>{{ getErrorMessage(\"invalidNIT\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidCUI\"]) {\r\n <strong>{{ getErrorMessage(\"invalidCUI\") }}</strong>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidDateRange\"]\r\n ) {\r\n <strong>{{ getErrorMessage(\"invalidDateRange\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"dateNotRange\"]) {\r\n <strong>{{ getErrorMessage(\"dateNotRange\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidDate\"]) {\r\n <strong>{{ getErrorMessage(\"invalidDate\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"minimumAge\"]) {\r\n <strong>{{ getErrorMessage(\"minimumAge\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"minlength\"]) {\r\n Debe tener al menos\r\n <strong>{{\r\n formatNumber(getErrorValue(\"minlength\", \"requiredLength\"), false)\r\n }}</strong>\r\n caracteres.\r\n } @else if (control && control.errors && control.errors[\"maxlength\"]) {\r\n Debe tener como m\u00E1ximo\r\n <strong>{{\r\n formatNumber(getErrorValue(\"maxlength\", \"requiredLength\"), false)\r\n }}</strong>\r\n caracteres.\r\n } @else if (control && control.errors && control.errors[\"min\"]) {\r\n El valor m\u00EDnimo permitido es\r\n <strong>{{ formatNumber(getErrorValue(\"min\", \"min\"), true) }}</strong>\r\n } @else if (control && control.errors && control.errors[\"max\"]) {\r\n El valor m\u00E1ximo permitido es\r\n <strong>{{ formatNumber(getErrorValue(\"max\", \"max\"), true) }}</strong>\r\n } @else if (control && control.errors && control.errors[\"email\"]) {\r\n Debe ser una direcci\u00F3n de correo v\u00E1lida.\r\n } @else if (control && control.errors && control.errors[\"pattern\"]) {\r\n El campo no tiene el formato requerido.\r\n } @else if (\r\n control && control.errors && control.errors[\"alreadyValueExists\"]\r\n ) {\r\n <strong>{{ getErrorMessage(\"alreadyValueExists\") }}</strong>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidTemplateVariables\"]\r\n ) {\r\n <div class=\"dsx-template-error\">\r\n <strong>{{ getErrorMessage(\"invalidTemplateVariables\") }}</strong>\r\n @if (getTemplateErrorDetails(\"invalidTemplateVariables\").length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ getFirstTemplateErrorDetail(\"invalidTemplateVariables\") }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidTemplateStructure\"]\r\n ) {\r\n <div class=\"dsx-template-error\">\r\n <strong>{{ getErrorMessage(\"invalidTemplateStructure\") }}</strong>\r\n @if (getTemplateErrorDetails(\"invalidTemplateStructure\").length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ getFirstTemplateErrorDetail(\"invalidTemplateStructure\") }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (\r\n control && control.errors && control.errors[\"similitudDetectada\"]\r\n ) {\r\n <strong>{{ getSimilitudMessage() }}</strong>\r\n } @else {\r\n Existe un error a\u00FAn no identificado.\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Mensaje para formulario en general -->\r\n@if (form && form.invalid && form.dirty) {\r\n <div class=\"mt-2 mb-2\">\r\n @if (form.errors && form.errors[\"atLeastOneRequired\"]) {\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ getFormError(\"atLeastOneRequired\") }}\r\n </p-tag>\r\n }\r\n </div>\r\n}\r\n", styles: [".dsx-error-slot{display:block;max-height:0;overflow:hidden;opacity:0;transform:translateY(-4px) scale(.98);transition:max-height .3s cubic-bezier(.4,0,.2,1),opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1),margin .25s cubic-bezier(.4,0,.2,1)}.dsx-error-slot.is-visible{max-height:60px;opacity:1;transform:translateY(0) scale(1)}.dsx-error-message{display:block;width:100%}.dsx-error-message-content{display:flex;align-items:center;gap:.4rem;width:100%;box-sizing:border-box;padding:.25rem .6rem;font-size:.82rem;background:var(--dsx-error-bg, #fff2f0)!important;color:var(--dsx-error-color, #b42318)!important;border-left:3px solid var(--dsx-error-color, #b42318)!important;border-radius:.3rem;box-shadow:0 1px 2px #0000000f;line-height:1.3;animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1)}.dsx-error-icon{flex:0 0 auto;line-height:1;display:inline-flex;align-items:center;justify-content:center}.dsx-error-icon icon-dsx{transform:scale(.85);transition:transform .2s ease}.dsx-error-slot.is-visible .dsx-error-icon icon-dsx{transform:scale(1)}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:var(--dsx-error-color, #ff5a4e)!important;fill:var(--dsx-error-color, #e45036)!important}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000000f}50%{box-shadow:0 2px 8px #b4231826}to{box-shadow:0 1px 2px #0000000f}}.dsx-error-slot.is-visible .dsx-error-message-content{animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1),errorPulse .4s ease .15s}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:10;pointer-events:none}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.08rem}:host-context(.p-floatlabel) .dsx-error-message-content{padding:.2rem .6rem .2rem .4rem}:host-context(:not(.p-floatlabel)){display:block;width:100%}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.15rem;margin-bottom:0}:host-context(:not(.p-floatlabel)) .dsx-error-message-content{padding:.2rem .6rem}@media(max-width:640px){.dsx-error-message-content{padding:.15rem .5rem;font-size:.75rem;gap:.3rem}.dsx-error-icon icon-dsx{transform:scale(.8)}.dsx-error-slot{transition:max-height .25s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-4px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.05rem}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.1rem}}@media(prefers-color-scheme:dark){.dsx-error-message-content{background:#2d1a1a;border-left-color:#ef4444;color:#fca5a5}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:#ef4444!important;fill:#ef4444!important}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000004d}50%{box-shadow:0 2px 8px #ef444433}to{box-shadow:0 1px 2px #0000004d}}}\n"], dependencies: [{ kind: "ngmodule", type: TagModule }, { kind: "component", type: i1$2.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }] });
1252
1376
  }
1253
1377
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AppMessageErrorComponent, decorators: [{
1254
1378
  type: Component,
1255
- args: [{ selector: 'app-message-error', standalone: true, imports: [TagModule, IconDsxComponent], template: "<div class=\"dsx-error-slot\" [class.is-visible]=\"isControlErrorVisible()\">\r\n <div class=\"dsx-error-message\">\r\n <div class=\"dsx-error-message-content\">\r\n <icon-dsx name=\"warning\"></icon-dsx>\r\n\r\n @if (control?.errors?.[\"required\"]) {\r\n El campo <strong>es requerido.</strong>\r\n } @else if (control?.errors?.[\"invalidNIT\"]) {\r\n <strong>{{ control?.errors?.[\"invalidNIT\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidCUI\"]) {\r\n <strong>{{ control?.errors?.[\"invalidCUI\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidDateRange\"]) {\r\n <strong>{{ control?.errors?.[\"invalidDateRange\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"dateNotRange\"]) {\r\n <strong>{{ control?.errors?.[\"dateNotRange\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidDate\"]) {\r\n <strong>{{ control?.errors?.[\"invalidDate\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"minimumAge\"]) {\r\n <strong>{{ control?.errors?.[\"minimumAge\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"minlength\"]) {\r\n Debe tener al menos\r\n <strong>{{ control?.errors?.[\"minlength\"]?.requiredLength }}</strong>\r\n caracteres.\r\n } @else if (control?.errors?.[\"maxlength\"]) {\r\n Debe tener como m\u00E1ximo\r\n <strong>{{ control?.errors?.[\"maxlength\"]?.requiredLength }}</strong>\r\n caracteres.\r\n } @else if (control?.errors?.[\"min\"]) {\r\n El valor m\u00EDnimo permitido es\r\n <strong>{{ formatNumber(control?.errors?.[\"min\"]?.min) }}</strong>\r\n } @else if (control?.errors?.[\"max\"]) {\r\n El valor m\u00E1ximo permitido es\r\n <strong>{{ formatNumber(control?.errors?.[\"max\"]?.max) }}</strong>\r\n } @else if (control?.errors?.[\"email\"]) {\r\n Debe ser una direcci\u00F3n de correo v\u00E1lida.\r\n } @else if (control?.errors?.[\"pattern\"]) {\r\n El campo no tiene el formato requerido.\r\n } @else if (control?.errors?.[\"alreadyValueExists\"]) {\r\n <strong>{{ control?.errors?.[\"alreadyValueExists\"]?.message }}</strong>\r\n } @else if (control?.errors?.[\"invalidTemplateVariables\"]) {\r\n <div class=\"dsx-template-error\">\r\n <strong>\r\n {{ control?.errors?.[\"invalidTemplateVariables\"]?.message }}\r\n </strong>\r\n @if (control?.errors?.[\"invalidTemplateVariables\"]?.details?.length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ control?.errors?.[\"invalidTemplateVariables\"]?.details?.[0] }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (control?.errors?.[\"invalidTemplateStructure\"]) {\r\n <div class=\"dsx-template-error\">\r\n <strong>\r\n {{ control?.errors?.[\"invalidTemplateStructure\"]?.message }}\r\n </strong>\r\n @if (control?.errors?.[\"invalidTemplateStructure\"]?.details?.length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ control?.errors?.[\"invalidTemplateStructure\"]?.details?.[0] }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (control?.errors?.[\"similitudDetectada\"]) {\r\n Ya existe un registro muy similar en el sistema:\r\n <strong\r\n >\"{{ control?.errors?.[\"similitudDetectada\"]?.sugerencia }}\"</strong\r\n >.\r\n } @else {\r\n Existe un error a\u00FAn no identificado.\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Mensaje para formulario en general -->\r\n@if (form?.invalid && form?.dirty) {\r\n <div class=\"mt-2 mb-2\">\r\n @if (this.form?.errors?.[\"atLeastOneRequired\"]) {\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ form?.getError(\"atLeastOneRequired\")?.message }}\r\n </p-tag>\r\n }\r\n </div>\r\n}\r\n", styles: [".dsx-error-slot{display:block;max-height:0;overflow:hidden;opacity:0;transform:translateY(-4px) scale(.98);transition:max-height .3s cubic-bezier(.4,0,.2,1),opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1),margin .25s cubic-bezier(.4,0,.2,1)}.dsx-error-slot.is-visible{max-height:60px;opacity:1;transform:translateY(0) scale(1)}.dsx-error-message{display:block;width:100%}.dsx-error-message-content{display:flex;align-items:center;gap:.4rem;width:100%;box-sizing:border-box;padding:.25rem .6rem;font-size:.82rem;background:var(--dsx-error-bg, #fff2f0)!important;color:var(--dsx-error-color, #b42318)!important;border-left:3px solid var(--dsx-error-color, #b42318)!important;border-radius:.3rem;box-shadow:0 1px 2px #0000000f;line-height:1.3;animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1)}.dsx-error-icon{flex:0 0 auto;line-height:1;display:inline-flex;align-items:center;justify-content:center}.dsx-error-icon icon-dsx{transform:scale(.85);transition:transform .2s ease}.dsx-error-slot.is-visible .dsx-error-icon icon-dsx{transform:scale(1)}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:var(--dsx-error-color, #ff5a4e)!important;fill:var(--dsx-error-color, #e45036)!important}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000000f}50%{box-shadow:0 2px 8px #b4231826}to{box-shadow:0 1px 2px #0000000f}}.dsx-error-slot.is-visible .dsx-error-message-content{animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1),errorPulse .4s ease .15s}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:10;pointer-events:none}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.08rem}:host-context(.p-floatlabel) .dsx-error-message-content{padding:.2rem .6rem .2rem .4rem}:host-context(:not(.p-floatlabel)){display:block;width:100%}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.15rem;margin-bottom:0}:host-context(:not(.p-floatlabel)) .dsx-error-message-content{padding:.2rem .6rem}@media(max-width:640px){.dsx-error-message-content{padding:.15rem .5rem;font-size:.75rem;gap:.3rem}.dsx-error-icon icon-dsx{transform:scale(.8)}.dsx-error-slot{transition:max-height .25s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-4px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.05rem}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.1rem}}@media(prefers-color-scheme:dark){.dsx-error-message-content{background:#2d1a1a;border-left-color:#ef4444;color:#fca5a5}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:#ef4444!important;fill:#ef4444!important}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000004d}50%{box-shadow:0 2px 8px #ef444433}to{box-shadow:0 1px 2px #0000004d}}}\n"] }]
1379
+ args: [{ selector: 'dsx-message-error', standalone: true, imports: [TagModule, IconDsxComponent], template: "<div class=\"dsx-error-slot\" [class.is-visible]=\"isControlErrorVisible()\">\r\n <div class=\"dsx-error-message\">\r\n <div class=\"dsx-error-message-content\">\r\n <icon-dsx name=\"warning\"></icon-dsx>\r\n\r\n <!-- Usamos control.errors en lugar de control?.errors -->\r\n @if (control && control.errors && control.errors[\"required\"]) {\r\n El campo <strong>es requerido.</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidNIT\"]) {\r\n <strong>{{ getErrorMessage(\"invalidNIT\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidCUI\"]) {\r\n <strong>{{ getErrorMessage(\"invalidCUI\") }}</strong>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidDateRange\"]\r\n ) {\r\n <strong>{{ getErrorMessage(\"invalidDateRange\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"dateNotRange\"]) {\r\n <strong>{{ getErrorMessage(\"dateNotRange\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"invalidDate\"]) {\r\n <strong>{{ getErrorMessage(\"invalidDate\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"minimumAge\"]) {\r\n <strong>{{ getErrorMessage(\"minimumAge\") }}</strong>\r\n } @else if (control && control.errors && control.errors[\"minlength\"]) {\r\n Debe tener al menos\r\n <strong>{{\r\n formatNumber(getErrorValue(\"minlength\", \"requiredLength\"), false)\r\n }}</strong>\r\n caracteres.\r\n } @else if (control && control.errors && control.errors[\"maxlength\"]) {\r\n Debe tener como m\u00E1ximo\r\n <strong>{{\r\n formatNumber(getErrorValue(\"maxlength\", \"requiredLength\"), false)\r\n }}</strong>\r\n caracteres.\r\n } @else if (control && control.errors && control.errors[\"min\"]) {\r\n El valor m\u00EDnimo permitido es\r\n <strong>{{ formatNumber(getErrorValue(\"min\", \"min\"), true) }}</strong>\r\n } @else if (control && control.errors && control.errors[\"max\"]) {\r\n El valor m\u00E1ximo permitido es\r\n <strong>{{ formatNumber(getErrorValue(\"max\", \"max\"), true) }}</strong>\r\n } @else if (control && control.errors && control.errors[\"email\"]) {\r\n Debe ser una direcci\u00F3n de correo v\u00E1lida.\r\n } @else if (control && control.errors && control.errors[\"pattern\"]) {\r\n El campo no tiene el formato requerido.\r\n } @else if (\r\n control && control.errors && control.errors[\"alreadyValueExists\"]\r\n ) {\r\n <strong>{{ getErrorMessage(\"alreadyValueExists\") }}</strong>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidTemplateVariables\"]\r\n ) {\r\n <div class=\"dsx-template-error\">\r\n <strong>{{ getErrorMessage(\"invalidTemplateVariables\") }}</strong>\r\n @if (getTemplateErrorDetails(\"invalidTemplateVariables\").length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ getFirstTemplateErrorDetail(\"invalidTemplateVariables\") }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (\r\n control && control.errors && control.errors[\"invalidTemplateStructure\"]\r\n ) {\r\n <div class=\"dsx-template-error\">\r\n <strong>{{ getErrorMessage(\"invalidTemplateStructure\") }}</strong>\r\n @if (getTemplateErrorDetails(\"invalidTemplateStructure\").length) {\r\n <span class=\"dsx-template-error-detail\">\r\n {{ getFirstTemplateErrorDetail(\"invalidTemplateStructure\") }}\r\n </span>\r\n }\r\n </div>\r\n } @else if (\r\n control && control.errors && control.errors[\"similitudDetectada\"]\r\n ) {\r\n <strong>{{ getSimilitudMessage() }}</strong>\r\n } @else {\r\n Existe un error a\u00FAn no identificado.\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Mensaje para formulario en general -->\r\n@if (form && form.invalid && form.dirty) {\r\n <div class=\"mt-2 mb-2\">\r\n @if (form.errors && form.errors[\"atLeastOneRequired\"]) {\r\n <p-tag severity=\"danger\" [rounded]=\"true\">\r\n {{ getFormError(\"atLeastOneRequired\") }}\r\n </p-tag>\r\n }\r\n </div>\r\n}\r\n", styles: [".dsx-error-slot{display:block;max-height:0;overflow:hidden;opacity:0;transform:translateY(-4px) scale(.98);transition:max-height .3s cubic-bezier(.4,0,.2,1),opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1),margin .25s cubic-bezier(.4,0,.2,1)}.dsx-error-slot.is-visible{max-height:60px;opacity:1;transform:translateY(0) scale(1)}.dsx-error-message{display:block;width:100%}.dsx-error-message-content{display:flex;align-items:center;gap:.4rem;width:100%;box-sizing:border-box;padding:.25rem .6rem;font-size:.82rem;background:var(--dsx-error-bg, #fff2f0)!important;color:var(--dsx-error-color, #b42318)!important;border-left:3px solid var(--dsx-error-color, #b42318)!important;border-radius:.3rem;box-shadow:0 1px 2px #0000000f;line-height:1.3;animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1)}.dsx-error-icon{flex:0 0 auto;line-height:1;display:inline-flex;align-items:center;justify-content:center}.dsx-error-icon icon-dsx{transform:scale(.85);transition:transform .2s ease}.dsx-error-slot.is-visible .dsx-error-icon icon-dsx{transform:scale(1)}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:var(--dsx-error-color, #ff5a4e)!important;fill:var(--dsx-error-color, #e45036)!important}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000000f}50%{box-shadow:0 2px 8px #b4231826}to{box-shadow:0 1px 2px #0000000f}}.dsx-error-slot.is-visible .dsx-error-message-content{animation:errorSlideIn .25s cubic-bezier(.4,0,.2,1),errorPulse .4s ease .15s}:host-context(.p-floatlabel){position:absolute;top:100%;left:0;width:100%;z-index:10;pointer-events:none}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.08rem}:host-context(.p-floatlabel) .dsx-error-message-content{padding:.2rem .6rem .2rem .4rem}:host-context(:not(.p-floatlabel)){display:block;width:100%}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.15rem;margin-bottom:0}:host-context(:not(.p-floatlabel)) .dsx-error-message-content{padding:.2rem .6rem}@media(max-width:640px){.dsx-error-message-content{padding:.15rem .5rem;font-size:.75rem;gap:.3rem}.dsx-error-icon icon-dsx{transform:scale(.8)}.dsx-error-slot{transition:max-height .25s cubic-bezier(.4,0,.2,1),opacity .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}@keyframes errorSlideIn{0%{opacity:0;transform:translateY(-4px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}:host-context(.p-floatlabel) .dsx-error-slot.is-visible{margin-top:.05rem}:host-context(:not(.p-floatlabel)) .dsx-error-slot.is-visible{margin-top:.1rem}}@media(prefers-color-scheme:dark){.dsx-error-message-content{background:#2d1a1a;border-left-color:#ef4444;color:#fca5a5}.dsx-error-message-content icon-dsx,.dsx-error-message-content icon-dsx svg,.dsx-error-message-content icon-dsx svg path{color:#ef4444!important;fill:#ef4444!important}@keyframes errorPulse{0%{box-shadow:0 1px 2px #0000004d}50%{box-shadow:0 2px 8px #ef444433}to{box-shadow:0 1px 2px #0000004d}}}\n"] }]
1256
1380
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { control: [{
1257
1381
  type: Input
1258
1382
  }], form: [{
@@ -4207,6 +4331,8 @@ class DsxButtonComponent {
4207
4331
  renderCount = 0;
4208
4332
  _paramService = inject((ParameterValuesService));
4209
4333
  _router = inject(Router);
4334
+ // Agrega un input para el tamaño
4335
+ size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4210
4336
  _environment = inject(ENVIRONMENT, {
4211
4337
  optional: true,
4212
4338
  });
@@ -4392,8 +4518,18 @@ class DsxButtonComponent {
4392
4518
  get buttonLabel() {
4393
4519
  return this.iconOnly() ? undefined : this.label;
4394
4520
  }
4521
+ // Y modifica el getter buttonSize
4395
4522
  get buttonSize() {
4396
- return this.isCompactIconButton ? 'small' : undefined;
4523
+ // Si el usuario especificó un tamaño, úsalo
4524
+ if (this.size()) {
4525
+ return this.size();
4526
+ }
4527
+ // Si es compacto, siempre small
4528
+ if (this.isCompactIconButton) {
4529
+ return 'small';
4530
+ }
4531
+ // Por defecto, small para todos los botones
4532
+ return 'small';
4397
4533
  }
4398
4534
  get buttonStyleClass() {
4399
4535
  return this.isCompactIconButton ? 'dsx-button-compact' : undefined;
@@ -4635,12 +4771,12 @@ class DsxButtonComponent {
4635
4771
  console.timeEnd(`[dsx-button:${this.type()}] ${label}`);
4636
4772
  }
4637
4773
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4638
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxButtonComponent, isStandalone: true, selector: "dsx-button", inputs: { debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, routerPath: { classPropertyName: "routerPath", publicName: "routerPath", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconOnlyWidth: { classPropertyName: "iconOnlyWidth", publicName: "iconOnlyWidth", isSignal: true, isRequired: false, transformFunction: null }, raised: { classPropertyName: "raised", publicName: "raised", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, parameterName: { classPropertyName: "parameterName", publicName: "parameterName", isSignal: true, isRequired: false, transformFunction: null }, parameterExpectedValue: { classPropertyName: "parameterExpectedValue", publicName: "parameterExpectedValue", isSignal: true, isRequired: false, transformFunction: null }, parameterIndex: { classPropertyName: "parameterIndex", publicName: "parameterIndex", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, requireIdInput: { classPropertyName: "requireIdInput", publicName: "requireIdInput", isSignal: true, isRequired: false, transformFunction: null }, requiresIdGreaterThanZero: { classPropertyName: "requiresIdGreaterThanZero", publicName: "requiresIdGreaterThanZero", isSignal: true, isRequired: false, transformFunction: null }, labelOverride: { classPropertyName: "labelOverride", publicName: "labelOverride", isSignal: true, isRequired: false, transformFunction: null }, tooltipOverride: { classPropertyName: "tooltipOverride", publicName: "tooltipOverride", isSignal: true, isRequired: false, transformFunction: null }, iconOverride: { classPropertyName: "iconOverride", publicName: "iconOverride", isSignal: true, isRequired: false, transformFunction: null }, primeIconOverride: { classPropertyName: "primeIconOverride", publicName: "primeIconOverride", isSignal: true, isRequired: false, transformFunction: null }, colorOverride: { classPropertyName: "colorOverride", publicName: "colorOverride", isSignal: true, isRequired: false, transformFunction: null }, outlinedOverride: { classPropertyName: "outlinedOverride", publicName: "outlinedOverride", isSignal: true, isRequired: false, transformFunction: null }, showValidateButtonOverride: { classPropertyName: "showValidateButtonOverride", publicName: "showValidateButtonOverride", isSignal: true, isRequired: false, transformFunction: null }, showRestoreButtonOverride: { classPropertyName: "showRestoreButtonOverride", publicName: "showRestoreButtonOverride", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { properties: { "class.dsx-button-compact-host": "this.compactHostClass" } }, ngImport: i0, template: "<!--Bot\u00F3n con las configuraciones din\u00E1micas para CRUD -->\r\n@if (visible()) {\r\n<p-button\r\n [label]=\"buttonLabel\"\r\n [style]=\"buttonStyleComputed()\"\r\n [styleClass]=\"buttonStyleClass\"\r\n [pTooltip]=\"tooltip()\"\r\n [tooltipDisabled]=\"disabled()\"\r\n tooltipPosition=\"top\"\r\n [rounded]=\"rounded()\"\r\n [text]=\"isCompactIconButton\"\r\n [size]=\"buttonSize\"\r\n severity=\"secondary\"\r\n [disabled]=\"disabled()\"\r\n [icon]=\"iconOnly() ? primeIcon : undefined\"\r\n (click)=\"onButtonClick()\"\r\n>\r\n @if (!iconOnly()) {\r\n <span class=\"material-symbols-outlined dsx-button-icon-small\"\r\n >{{ materialIcon }}</span\r\n >\r\n }\r\n</p-button>\r\n}\r\n", styles: [".dsx-button-icon-small{font-size:1.25rem;vertical-align:middle}:host{display:inline-flex;margin-bottom:.25rem}:host.dsx-button-compact-host{margin-bottom:0}:host ::ng-deep .p-button .p-button-label{font-family:Montserrat,Roboto,sans-serif;font-weight:500;letter-spacing:.01em}:host ::ng-deep .p-button.dsx-button-compact{min-height:2rem;padding-block:.2rem}:host ::ng-deep .p-button .material-symbols-outlined.p-button-icon{line-height:1;vertical-align:middle}:host ::ng-deep .p-button.dsx-button-compact .p-button-icon{margin:0;font-size:1.2rem;line-height:1}:host ::ng-deep .p-button.dsx-button-compact .material-symbols-outlined.p-button-icon{font-variation-settings:\"FILL\" 1,\"wght\" 500,\"GRAD\" 0,\"opsz\" 24}:host ::ng-deep .p-button:disabled,:host ::ng-deep .p-button.p-disabled{cursor:not-allowed!important;opacity:.45!important;filter:grayscale(.2) saturate(.75)}:host ::ng-deep .p-button:disabled *,:host ::ng-deep .p-button.p-disabled *{cursor:not-allowed!important}.p-button.dsx-button-outlined-neutral,.p-button.dsx-button-outlined-info{background:#f5f7fa!important;border:1.5px solid #0066cc!important;color:#06c!important}.p-button.dsx-button-outlined-neutral:disabled,.p-button.dsx-button-outlined-info:disabled{background:#f5f7fa!important;border:1.5px solid #b0bec5!important;color:#b0bec5!important}\n"], dependencies: [{ kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] });
4774
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxButtonComponent, isStandalone: true, selector: "dsx-button", inputs: { debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, routerPath: { classPropertyName: "routerPath", publicName: "routerPath", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconOnlyWidth: { classPropertyName: "iconOnlyWidth", publicName: "iconOnlyWidth", isSignal: true, isRequired: false, transformFunction: null }, raised: { classPropertyName: "raised", publicName: "raised", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, parameterName: { classPropertyName: "parameterName", publicName: "parameterName", isSignal: true, isRequired: false, transformFunction: null }, parameterExpectedValue: { classPropertyName: "parameterExpectedValue", publicName: "parameterExpectedValue", isSignal: true, isRequired: false, transformFunction: null }, parameterIndex: { classPropertyName: "parameterIndex", publicName: "parameterIndex", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, requireIdInput: { classPropertyName: "requireIdInput", publicName: "requireIdInput", isSignal: true, isRequired: false, transformFunction: null }, requiresIdGreaterThanZero: { classPropertyName: "requiresIdGreaterThanZero", publicName: "requiresIdGreaterThanZero", isSignal: true, isRequired: false, transformFunction: null }, labelOverride: { classPropertyName: "labelOverride", publicName: "labelOverride", isSignal: true, isRequired: false, transformFunction: null }, tooltipOverride: { classPropertyName: "tooltipOverride", publicName: "tooltipOverride", isSignal: true, isRequired: false, transformFunction: null }, iconOverride: { classPropertyName: "iconOverride", publicName: "iconOverride", isSignal: true, isRequired: false, transformFunction: null }, primeIconOverride: { classPropertyName: "primeIconOverride", publicName: "primeIconOverride", isSignal: true, isRequired: false, transformFunction: null }, colorOverride: { classPropertyName: "colorOverride", publicName: "colorOverride", isSignal: true, isRequired: false, transformFunction: null }, outlinedOverride: { classPropertyName: "outlinedOverride", publicName: "outlinedOverride", isSignal: true, isRequired: false, transformFunction: null }, showValidateButtonOverride: { classPropertyName: "showValidateButtonOverride", publicName: "showValidateButtonOverride", isSignal: true, isRequired: false, transformFunction: null }, showRestoreButtonOverride: { classPropertyName: "showRestoreButtonOverride", publicName: "showRestoreButtonOverride", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { properties: { "class.dsx-button-compact-host": "this.compactHostClass" } }, ngImport: i0, template: "<!--Bot\u00F3n con las configuraciones din\u00E1micas para CRUD -->\r\n@if (visible()) {\r\n<p-button\r\n [label]=\"buttonLabel\"\r\n [style]=\"buttonStyleComputed()\"\r\n [styleClass]=\"buttonStyleClass\"\r\n [pTooltip]=\"tooltip()\"\r\n [tooltipDisabled]=\"disabled()\"\r\n tooltipPosition=\"top\"\r\n [rounded]=\"rounded()\"\r\n [text]=\"isCompactIconButton\"\r\n [size]=\"buttonSize\"\r\n severity=\"secondary\"\r\n [disabled]=\"disabled()\"\r\n [icon]=\"iconOnly() ? primeIcon : undefined\"\r\n (click)=\"onButtonClick()\"\r\n>\r\n @if (!iconOnly()) {\r\n <span class=\"material-symbols-outlined dsx-button-icon-small\"\r\n >{{ materialIcon }}</span\r\n >\r\n }\r\n</p-button>\r\n}\r\n", styles: [".dsx-button-icon-small{font-size:1.25rem;vertical-align:middle}:host{display:inline-flex;margin-bottom:.25rem}:host.dsx-button-compact-host{margin-bottom:0}:host ::ng-deep .p-button.dsx-button-compact{min-height:2rem;padding-block:.2rem}:host ::ng-deep .p-button .material-symbols-outlined.p-button-icon{line-height:1;vertical-align:middle}:host ::ng-deep .p-button.dsx-button-compact .p-button-icon{margin:0;font-size:1.2rem;line-height:1}:host ::ng-deep .p-button.dsx-button-compact .material-symbols-outlined.p-button-icon{font-variation-settings:\"FILL\" 1,\"wght\" 500,\"GRAD\" 0,\"opsz\" 24}:host ::ng-deep .p-button:disabled,:host ::ng-deep .p-button.p-disabled{cursor:not-allowed!important;opacity:.45!important;filter:grayscale(.2) saturate(.75)}:host ::ng-deep .p-button:disabled *,:host ::ng-deep .p-button.p-disabled *{cursor:not-allowed!important}.p-button.dsx-button-outlined-neutral,.p-button.dsx-button-outlined-info{background:#f5f7fa!important;border:1.5px solid #0066cc!important;color:#06c!important}.p-button.dsx-button-outlined-neutral:disabled,.p-button.dsx-button-outlined-info:disabled{background:#f5f7fa!important;border:1.5px solid #b0bec5!important;color:#b0bec5!important}\n"], dependencies: [{ kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$3.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] });
4639
4775
  }
4640
4776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxButtonComponent, decorators: [{
4641
4777
  type: Component,
4642
- args: [{ selector: 'dsx-button', imports: [Button, TooltipModule], template: "<!--Bot\u00F3n con las configuraciones din\u00E1micas para CRUD -->\r\n@if (visible()) {\r\n<p-button\r\n [label]=\"buttonLabel\"\r\n [style]=\"buttonStyleComputed()\"\r\n [styleClass]=\"buttonStyleClass\"\r\n [pTooltip]=\"tooltip()\"\r\n [tooltipDisabled]=\"disabled()\"\r\n tooltipPosition=\"top\"\r\n [rounded]=\"rounded()\"\r\n [text]=\"isCompactIconButton\"\r\n [size]=\"buttonSize\"\r\n severity=\"secondary\"\r\n [disabled]=\"disabled()\"\r\n [icon]=\"iconOnly() ? primeIcon : undefined\"\r\n (click)=\"onButtonClick()\"\r\n>\r\n @if (!iconOnly()) {\r\n <span class=\"material-symbols-outlined dsx-button-icon-small\"\r\n >{{ materialIcon }}</span\r\n >\r\n }\r\n</p-button>\r\n}\r\n", styles: [".dsx-button-icon-small{font-size:1.25rem;vertical-align:middle}:host{display:inline-flex;margin-bottom:.25rem}:host.dsx-button-compact-host{margin-bottom:0}:host ::ng-deep .p-button .p-button-label{font-family:Montserrat,Roboto,sans-serif;font-weight:500;letter-spacing:.01em}:host ::ng-deep .p-button.dsx-button-compact{min-height:2rem;padding-block:.2rem}:host ::ng-deep .p-button .material-symbols-outlined.p-button-icon{line-height:1;vertical-align:middle}:host ::ng-deep .p-button.dsx-button-compact .p-button-icon{margin:0;font-size:1.2rem;line-height:1}:host ::ng-deep .p-button.dsx-button-compact .material-symbols-outlined.p-button-icon{font-variation-settings:\"FILL\" 1,\"wght\" 500,\"GRAD\" 0,\"opsz\" 24}:host ::ng-deep .p-button:disabled,:host ::ng-deep .p-button.p-disabled{cursor:not-allowed!important;opacity:.45!important;filter:grayscale(.2) saturate(.75)}:host ::ng-deep .p-button:disabled *,:host ::ng-deep .p-button.p-disabled *{cursor:not-allowed!important}.p-button.dsx-button-outlined-neutral,.p-button.dsx-button-outlined-info{background:#f5f7fa!important;border:1.5px solid #0066cc!important;color:#06c!important}.p-button.dsx-button-outlined-neutral:disabled,.p-button.dsx-button-outlined-info:disabled{background:#f5f7fa!important;border:1.5px solid #b0bec5!important;color:#b0bec5!important}\n"] }]
4643
- }], ctorParameters: () => [], propDecorators: { debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], compactHostClass: [{
4778
+ args: [{ selector: 'dsx-button', imports: [Button, TooltipModule], template: "<!--Bot\u00F3n con las configuraciones din\u00E1micas para CRUD -->\r\n@if (visible()) {\r\n<p-button\r\n [label]=\"buttonLabel\"\r\n [style]=\"buttonStyleComputed()\"\r\n [styleClass]=\"buttonStyleClass\"\r\n [pTooltip]=\"tooltip()\"\r\n [tooltipDisabled]=\"disabled()\"\r\n tooltipPosition=\"top\"\r\n [rounded]=\"rounded()\"\r\n [text]=\"isCompactIconButton\"\r\n [size]=\"buttonSize\"\r\n severity=\"secondary\"\r\n [disabled]=\"disabled()\"\r\n [icon]=\"iconOnly() ? primeIcon : undefined\"\r\n (click)=\"onButtonClick()\"\r\n>\r\n @if (!iconOnly()) {\r\n <span class=\"material-symbols-outlined dsx-button-icon-small\"\r\n >{{ materialIcon }}</span\r\n >\r\n }\r\n</p-button>\r\n}\r\n", styles: [".dsx-button-icon-small{font-size:1.25rem;vertical-align:middle}:host{display:inline-flex;margin-bottom:.25rem}:host.dsx-button-compact-host{margin-bottom:0}:host ::ng-deep .p-button.dsx-button-compact{min-height:2rem;padding-block:.2rem}:host ::ng-deep .p-button .material-symbols-outlined.p-button-icon{line-height:1;vertical-align:middle}:host ::ng-deep .p-button.dsx-button-compact .p-button-icon{margin:0;font-size:1.2rem;line-height:1}:host ::ng-deep .p-button.dsx-button-compact .material-symbols-outlined.p-button-icon{font-variation-settings:\"FILL\" 1,\"wght\" 500,\"GRAD\" 0,\"opsz\" 24}:host ::ng-deep .p-button:disabled,:host ::ng-deep .p-button.p-disabled{cursor:not-allowed!important;opacity:.45!important;filter:grayscale(.2) saturate(.75)}:host ::ng-deep .p-button:disabled *,:host ::ng-deep .p-button.p-disabled *{cursor:not-allowed!important}.p-button.dsx-button-outlined-neutral,.p-button.dsx-button-outlined-info{background:#f5f7fa!important;border:1.5px solid #0066cc!important;color:#06c!important}.p-button.dsx-button-outlined-neutral:disabled,.p-button.dsx-button-outlined-info:disabled{background:#f5f7fa!important;border:1.5px solid #b0bec5!important;color:#b0bec5!important}\n"] }]
4779
+ }], ctorParameters: () => [], propDecorators: { debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], compactHostClass: [{
4644
4780
  type: HostBinding,
4645
4781
  args: ['class.dsx-button-compact-host']
4646
4782
  }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], routerPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerPath", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], iconOnlyWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnlyWidth", required: false }] }], raised: [{ type: i0.Input, args: [{ isSignal: true, alias: "raised", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], parameterName: [{ type: i0.Input, args: [{ isSignal: true, alias: "parameterName", required: false }] }], parameterExpectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "parameterExpectedValue", required: false }] }], parameterIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "parameterIndex", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], requireIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireIdInput", required: false }] }], requiresIdGreaterThanZero: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiresIdGreaterThanZero", required: false }] }], labelOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelOverride", required: false }] }], tooltipOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipOverride", required: false }] }], iconOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOverride", required: false }] }], primeIconOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "primeIconOverride", required: false }] }], colorOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "colorOverride", required: false }] }], outlinedOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "outlinedOverride", required: false }] }], showValidateButtonOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValidateButtonOverride", required: false }] }], showRestoreButtonOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRestoreButtonOverride", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
@@ -4723,7 +4859,7 @@ const ACTION_CONFIG = {
4723
4859
  details: {
4724
4860
  label: 'Detalles',
4725
4861
  icon: 'list',
4726
- primeIcon: 'pi pi-list',
4862
+ primeIcon: 'fa-solid fa-list-ol',
4727
4863
  colorToken: 'details',
4728
4864
  tooltip: 'Detalle de registro',
4729
4865
  },
@@ -5334,11 +5470,11 @@ class JsonValuesDebujComponent {
5334
5470
  }
5335
5471
  }
5336
5472
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JsonValuesDebujComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5337
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JsonValuesDebujComponent, isStandalone: true, selector: "app-json-values-debuj", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (form() && shouldShowVisual) {\r\n <div class=\"custom-container\">\r\n <pre class=\"custom-pre\" [innerHTML]=\"debugValue() | jsonHighlight\"></pre>\r\n </div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;max-height:700px;background:#1e1e1e;border:1px solid #333;border-radius:8px;box-shadow:0 4px 12px #0000004d;padding:1.25rem;margin-bottom:1.25rem}.custom-pre{margin:0;white-space:pre-wrap;word-break:break-word;word-wrap:break-word;font-family:Segoe UI,Fira Code,JetBrains Mono,Consolas,Monaco,Courier New,monospace;font-size:15px;line-height:1.65;color:#d4d4d4;font-weight:400}.json-key{color:#9cdcfe;font-weight:600;font-size:15px}.json-string{color:#ce9178;font-size:15px}.json-number{color:#b5cea8;font-weight:600;font-size:15px}.json-boolean{color:#569cd6;font-weight:700;font-size:15px}.json-null{color:gray;font-style:italic;font-size:15px}.json-bracket{color:gold;font-weight:700;font-size:16px}.json-colon{color:#d4d4d4;font-weight:500}.json-comma{color:gray;font-size:14px}.json-date-part{color:#4fc1ff;font-weight:600;font-size:15px}.json-date-sep{color:gray}.json-date-time{color:#c586c0;font-size:15px}.custom-container::-webkit-scrollbar{width:12px;height:12px}.custom-container::-webkit-scrollbar-track{background:#252526;border-radius:6px}.custom-container::-webkit-scrollbar-thumb{background:#555;border-radius:6px;transition:background .2s ease}.custom-container::-webkit-scrollbar-thumb:hover{background:#777}.custom-container::-webkit-scrollbar-corner{background:#1e1e1e}.custom-container{font-smooth:antialiased;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-pre:hover{background:#252526;transition:background .2s ease;cursor:text}.json-null,.json-undefined{color:#f48771;font-style:italic;opacity:.8}.json-empty{color:gray;font-style:italic}.json-comma+br{margin-bottom:2px}\n"], dependencies: [{ kind: "pipe", type: JsonHighlightPipe, name: "jsonHighlight" }], encapsulation: i0.ViewEncapsulation.None });
5473
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JsonValuesDebujComponent, isStandalone: true, selector: "app-json-values-debuj", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (form() && shouldShowVisual) {\r\n <div class=\"custom-container\">\r\n <pre class=\"custom-pre\" [innerHTML]=\"debugValue() | jsonHighlight\"></pre>\r\n </div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;max-height:700px;background:#1e1e1e;border:1px solid #333;border-radius:8px;box-shadow:0 4px 12px #0000004d;padding:1.25rem;margin-bottom:1.25rem}.custom-pre{margin:0;white-space:pre-wrap;word-break:break-word;word-wrap:break-word;font-family:Segoe UI,Fira Code,JetBrains Mono,Consolas,Monaco,Courier New,monospace;font-size:15px;line-height:1.65;color:#d4d4d4;font-weight:400}.json-key{color:#9cdcfe;font-weight:600;font-size:15px}.json-string{color:#ce9178;font-size:15px}.json-number{color:#b5cea8;font-weight:600;font-size:15px}.json-boolean{color:#569cd6;font-weight:700;font-size:15px}.json-null{color:gray;font-style:italic;font-size:15px}.json-bracket{color:gold;font-weight:700;font-size:16px}.json-colon{color:#d4d4d4;font-weight:500}.json-comma{color:gray;font-size:14px}.json-date-part{color:#4fc1ff;font-weight:600;font-size:15px}.json-date-sep{color:gray}.json-date-time{color:#c586c0;font-size:15px}.custom-container::-webkit-scrollbar{width:12px;height:12px}.custom-container::-webkit-scrollbar-track{background:#252526;border-radius:6px}.custom-container::-webkit-scrollbar-thumb{background:#555;border-radius:6px;transition:background .2s ease}.custom-container::-webkit-scrollbar-thumb:hover{background:#777}.custom-container::-webkit-scrollbar-corner{background:#1e1e1e}.custom-container{font-smooth:antialiased;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.json-null,.json-undefined{color:#f48771;font-style:italic;opacity:.8}.json-empty{color:gray;font-style:italic}.json-comma+br{margin-bottom:2px}\n"], dependencies: [{ kind: "pipe", type: JsonHighlightPipe, name: "jsonHighlight" }], encapsulation: i0.ViewEncapsulation.None });
5338
5474
  }
5339
5475
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JsonValuesDebujComponent, decorators: [{
5340
5476
  type: Component,
5341
- args: [{ selector: 'app-json-values-debuj', standalone: true, imports: [JsonHighlightPipe], encapsulation: ViewEncapsulation.None, template: "@if (form() && shouldShowVisual) {\r\n <div class=\"custom-container\">\r\n <pre class=\"custom-pre\" [innerHTML]=\"debugValue() | jsonHighlight\"></pre>\r\n </div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;max-height:700px;background:#1e1e1e;border:1px solid #333;border-radius:8px;box-shadow:0 4px 12px #0000004d;padding:1.25rem;margin-bottom:1.25rem}.custom-pre{margin:0;white-space:pre-wrap;word-break:break-word;word-wrap:break-word;font-family:Segoe UI,Fira Code,JetBrains Mono,Consolas,Monaco,Courier New,monospace;font-size:15px;line-height:1.65;color:#d4d4d4;font-weight:400}.json-key{color:#9cdcfe;font-weight:600;font-size:15px}.json-string{color:#ce9178;font-size:15px}.json-number{color:#b5cea8;font-weight:600;font-size:15px}.json-boolean{color:#569cd6;font-weight:700;font-size:15px}.json-null{color:gray;font-style:italic;font-size:15px}.json-bracket{color:gold;font-weight:700;font-size:16px}.json-colon{color:#d4d4d4;font-weight:500}.json-comma{color:gray;font-size:14px}.json-date-part{color:#4fc1ff;font-weight:600;font-size:15px}.json-date-sep{color:gray}.json-date-time{color:#c586c0;font-size:15px}.custom-container::-webkit-scrollbar{width:12px;height:12px}.custom-container::-webkit-scrollbar-track{background:#252526;border-radius:6px}.custom-container::-webkit-scrollbar-thumb{background:#555;border-radius:6px;transition:background .2s ease}.custom-container::-webkit-scrollbar-thumb:hover{background:#777}.custom-container::-webkit-scrollbar-corner{background:#1e1e1e}.custom-container{font-smooth:antialiased;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-pre:hover{background:#252526;transition:background .2s ease;cursor:text}.json-null,.json-undefined{color:#f48771;font-style:italic;opacity:.8}.json-empty{color:gray;font-style:italic}.json-comma+br{margin-bottom:2px}\n"] }]
5477
+ args: [{ selector: 'app-json-values-debuj', standalone: true, imports: [JsonHighlightPipe], encapsulation: ViewEncapsulation.None, template: "@if (form() && shouldShowVisual) {\r\n <div class=\"custom-container\">\r\n <pre class=\"custom-pre\" [innerHTML]=\"debugValue() | jsonHighlight\"></pre>\r\n </div>\r\n}\r\n", styles: [".custom-container{width:100%;overflow:auto;max-height:700px;background:#1e1e1e;border:1px solid #333;border-radius:8px;box-shadow:0 4px 12px #0000004d;padding:1.25rem;margin-bottom:1.25rem}.custom-pre{margin:0;white-space:pre-wrap;word-break:break-word;word-wrap:break-word;font-family:Segoe UI,Fira Code,JetBrains Mono,Consolas,Monaco,Courier New,monospace;font-size:15px;line-height:1.65;color:#d4d4d4;font-weight:400}.json-key{color:#9cdcfe;font-weight:600;font-size:15px}.json-string{color:#ce9178;font-size:15px}.json-number{color:#b5cea8;font-weight:600;font-size:15px}.json-boolean{color:#569cd6;font-weight:700;font-size:15px}.json-null{color:gray;font-style:italic;font-size:15px}.json-bracket{color:gold;font-weight:700;font-size:16px}.json-colon{color:#d4d4d4;font-weight:500}.json-comma{color:gray;font-size:14px}.json-date-part{color:#4fc1ff;font-weight:600;font-size:15px}.json-date-sep{color:gray}.json-date-time{color:#c586c0;font-size:15px}.custom-container::-webkit-scrollbar{width:12px;height:12px}.custom-container::-webkit-scrollbar-track{background:#252526;border-radius:6px}.custom-container::-webkit-scrollbar-thumb{background:#555;border-radius:6px;transition:background .2s ease}.custom-container::-webkit-scrollbar-thumb:hover{background:#777}.custom-container::-webkit-scrollbar-corner{background:#1e1e1e}.custom-container{font-smooth:antialiased;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.json-null,.json-undefined{color:#f48771;font-style:italic;opacity:.8}.json-empty{color:gray;font-style:italic}.json-comma+br{margin-bottom:2px}\n"] }]
5342
5478
  }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }] } });
5343
5479
 
5344
5480
  class IcoLabel {
@@ -7744,54 +7880,197 @@ function createInitialCache(cacheKeys) {
7744
7880
  }
7745
7881
 
7746
7882
  class HeaderDsx {
7883
+ // Inputs
7747
7884
  id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
7748
7885
  etiqueta = input.required(...(ngDevMode ? [{ debugName: "etiqueta" }] : /* istanbul ignore next */ []));
7749
7886
  defaultPNG = input('icon/folder_001.png', ...(ngDevMode ? [{ debugName: "defaultPNG" }] : /* istanbul ignore next */ []));
7750
7887
  defaultGIF = input('gif/file.gif', ...(ngDevMode ? [{ debugName: "defaultGIF" }] : /* istanbul ignore next */ []));
7751
7888
  icoPNG = input(null, ...(ngDevMode ? [{ debugName: "icoPNG" }] : /* istanbul ignore next */ []));
7752
7889
  icoGIF = input(null, ...(ngDevMode ? [{ debugName: "icoGIF" }] : /* istanbul ignore next */ []));
7753
- icono = null;
7754
- textoEncabezado = null;
7755
7890
  subTitulo = input(null, ...(ngDevMode ? [{ debugName: "subTitulo" }] : /* istanbul ignore next */ []));
7891
+ debug = input(false, ...(ngDevMode ? [{ debugName: "debug" }] : /* istanbul ignore next */ []));
7892
+ // Signals
7893
+ icono = signal(null, ...(ngDevMode ? [{ debugName: "icono" }] : /* istanbul ignore next */ []));
7894
+ textoEncabezado = signal(null, ...(ngDevMode ? [{ debugName: "textoEncabezado" }] : /* istanbul ignore next */ []));
7895
+ // Métricas de performance públicas
7896
+ performanceMetrics = {
7897
+ renderCount: 0,
7898
+ lastRenderTime: 0,
7899
+ totalRenderTime: 0,
7900
+ averageRenderTime: 0,
7901
+ lastUpdateTimestamp: 0,
7902
+ };
7903
+ // Computed
7904
+ modo = computed(() => {
7905
+ const id = this.id();
7906
+ if (id === null)
7907
+ return 'Lista';
7908
+ if (id === 0)
7909
+ return 'Registro';
7910
+ if (id > 0)
7911
+ return 'Edición';
7912
+ return 'Desconocido';
7913
+ }, ...(ngDevMode ? [{ debugName: "modo" }] : /* istanbul ignore next */ []));
7914
+ // Control de producción
7915
+ isProduction = !isDevMode();
7916
+ constructor() {
7917
+ effect(() => {
7918
+ if (this.debug() && !this.isProduction) {
7919
+ this.logPerformance('Debug mode activado');
7920
+ }
7921
+ });
7922
+ }
7756
7923
  ngOnInit() {
7924
+ const startTime = performance.now();
7757
7925
  this.definirTexto();
7758
- //throw new Error('Method not implemented.');
7926
+ this.performanceMetrics.lastUpdateTimestamp = Date.now();
7927
+ this.logPerformance('Componente inicializado');
7928
+ const endTime = performance.now();
7929
+ this.logPerformance(`Tiempo de inicialización: ${(endTime - startTime).toFixed(2)}ms`);
7930
+ }
7931
+ ngOnChanges(changes) {
7932
+ const startTime = performance.now();
7933
+ this.performanceMetrics.renderCount++;
7934
+ // Solo procesar si hay cambios relevantes
7935
+ if (this.tieneCambiosRelevantes(changes)) {
7936
+ this.logPerformance('Detectado cambio en inputs', {
7937
+ cambios: Object.keys(changes),
7938
+ idActual: this.id(),
7939
+ idAnterior: changes['id']?.previousValue,
7940
+ idNuevo: changes['id']?.currentValue,
7941
+ });
7942
+ this.definirTexto();
7943
+ }
7944
+ const endTime = performance.now();
7945
+ const renderTime = endTime - startTime;
7946
+ this.performanceMetrics.lastRenderTime = renderTime;
7947
+ this.performanceMetrics.totalRenderTime += renderTime;
7948
+ this.performanceMetrics.averageRenderTime =
7949
+ this.performanceMetrics.totalRenderTime /
7950
+ this.performanceMetrics.renderCount;
7951
+ this.logPerformance('Cambio procesado', {
7952
+ renderTime: renderTime.toFixed(2) + 'ms',
7953
+ renderCount: this.performanceMetrics.renderCount,
7954
+ avgRenderTime: this.performanceMetrics.averageRenderTime.toFixed(2) + 'ms',
7955
+ });
7956
+ }
7957
+ tieneCambiosRelevantes(changes) {
7958
+ const relevantKeys = ['id', 'etiqueta', 'icoPNG', 'icoGIF', 'subTitulo'];
7959
+ for (const key of relevantKeys) {
7960
+ if (changes[key] &&
7961
+ changes[key].currentValue !== changes[key].previousValue) {
7962
+ return true;
7963
+ }
7964
+ }
7965
+ return false;
7759
7966
  }
7760
7967
  definirTexto() {
7761
- // Validaciones para el texto del encabezado según el valor de ID
7762
- // Caso 1: No se proporcionó ID (indefinido o nulo) -> Plural
7763
- if (this.id() === null) {
7764
- this.textoEncabezado = this.etiqueta();
7968
+ const startTime = performance.now();
7969
+ const idActual = this.id();
7970
+ if (this.debug() && !this.isProduction) {
7971
+ console.group(`🔍 HeaderDsx - Definiendo texto para ID: ${idActual}`);
7972
+ }
7973
+ let nuevoTexto;
7974
+ let nuevoIcono = null;
7975
+ // Determinar texto
7976
+ if (idActual === null) {
7977
+ nuevoTexto = this.etiqueta();
7978
+ this.logDebug('Caso 1: ID null - Modo lista');
7979
+ }
7980
+ else if (idActual === 0) {
7981
+ nuevoTexto = `Registrar ${this.etiqueta()}`;
7982
+ this.logDebug('Caso 2: ID = 0 - Modo registro');
7983
+ }
7984
+ else if (idActual > 0) {
7985
+ nuevoTexto = `Editar ${this.etiqueta()}`;
7986
+ this.logDebug('Caso 3: ID > 0 - Modo edición', {
7987
+ id: idActual,
7988
+ texto: nuevoTexto,
7989
+ });
7990
+ }
7991
+ else {
7992
+ nuevoTexto = this.etiqueta();
7993
+ this.logDebug('Caso desconocido', { id: idActual });
7765
7994
  }
7766
- // Caso 2: El ID existe y vale exactamente 0 -> Registrar
7767
- else if (this.id() === 0) {
7768
- this.textoEncabezado = `Registrar ${this.etiqueta()}`;
7995
+ // Determinar icono
7996
+ if (this.icoPNG() !== null) {
7997
+ nuevoIcono = this.icoPNG();
7998
+ this.logDebug('Icono: Usando PNG personalizado', { icono: nuevoIcono });
7769
7999
  }
7770
- // Caso 3: El ID es mayor que 0 -> Editar
7771
- else if (this.id() > 0) {
7772
- this.textoEncabezado = `Editar ${this.etiqueta()}`;
8000
+ else if (this.icoGIF() !== null) {
8001
+ nuevoIcono = this.icoGIF();
8002
+ this.logDebug('Icono: Usando GIF personalizado', { icono: nuevoIcono });
7773
8003
  }
7774
- // Validaciones para el icono según el valor de ID
7775
- // Caso 1: No se proporcionó ningún icono -> Usar el icono por defecto
7776
- if (this.icoPNG() === null && this.icoGIF() === null) {
7777
- this.icono = this.defaultPNG();
8004
+ else {
8005
+ nuevoIcono = this.defaultPNG();
8006
+ this.logDebug('Icono: Usando default', { icono: nuevoIcono });
7778
8007
  }
7779
- // Caso 2: Se proporcionó un icono PNG -> Usar el icono PNG
7780
- else if (this.icoPNG() !== null) {
7781
- this.icono = this.icoPNG();
8008
+ // Actualizar solo si hay cambios
8009
+ if (this.textoEncabezado() !== nuevoTexto) {
8010
+ this.textoEncabezado.set(nuevoTexto);
7782
8011
  }
7783
- // Caso 3: Se proporcionó un icono GIF -> Usar el icono GIF
7784
- else if (this.icoGIF() !== null) {
7785
- this.icono = this.icoGIF();
8012
+ if (this.icono() !== nuevoIcono) {
8013
+ this.icono.set(nuevoIcono);
8014
+ }
8015
+ this.logDebug('Estado final actualizado', {
8016
+ texto: nuevoTexto,
8017
+ icono: nuevoIcono,
8018
+ id: idActual,
8019
+ modo: this.modo(),
8020
+ });
8021
+ if (this.debug() && !this.isProduction) {
8022
+ console.groupEnd();
8023
+ }
8024
+ const endTime = performance.now();
8025
+ this.logPerformance(`Tiempo de definición de texto: ${(endTime - startTime).toFixed(2)}ms`);
8026
+ }
8027
+ logDebug(message, data) {
8028
+ if (this.debug() && !this.isProduction) {
8029
+ console.log(`[HeaderDsx Debug] ${message}`, data ? data : '');
8030
+ }
8031
+ }
8032
+ logPerformance(message, data) {
8033
+ if (this.debug() && !this.isProduction) {
8034
+ console.log(`⚡ [HeaderDsx Performance] ${message}`, data ? data : '');
8035
+ }
8036
+ }
8037
+ // Métodos públicos
8038
+ getPerformanceMetrics() {
8039
+ return {
8040
+ ...this.performanceMetrics,
8041
+ currentMode: this.modo(),
8042
+ currentText: this.textoEncabezado(),
8043
+ currentIcon: this.icono(),
8044
+ currentId: this.id(),
8045
+ };
8046
+ }
8047
+ getPerformanceSummary() {
8048
+ const metrics = this.performanceMetrics;
8049
+ return `📊 Renders: ${metrics.renderCount} | Promedio: ${metrics.averageRenderTime.toFixed(2)}ms | Último: ${metrics.lastRenderTime.toFixed(2)}ms`;
8050
+ }
8051
+ debugInfo() {
8052
+ if (this.debug() && !this.isProduction) {
8053
+ console.group('=== HeaderDsx Debug Info ===');
8054
+ console.log('ID:', this.id());
8055
+ console.log('Etiqueta:', this.etiqueta());
8056
+ console.log('Texto Encabezado:', this.textoEncabezado());
8057
+ console.log('Icono:', this.icono());
8058
+ console.log('Subtítulo:', this.subTitulo());
8059
+ console.log('Modo:', this.modo());
8060
+ console.log('Debug Mode:', this.debug());
8061
+ console.log('Performance Metrics:', this.getPerformanceMetrics());
8062
+ console.log('Performance Summary:', this.getPerformanceSummary());
8063
+ console.log('===============================');
8064
+ console.groupEnd();
7786
8065
  }
7787
8066
  }
7788
8067
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeaderDsx, deps: [], target: i0.ɵɵFactoryTarget.Component });
7789
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: HeaderDsx, isStandalone: true, selector: "header-dsx", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, etiqueta: { classPropertyName: "etiqueta", publicName: "etiqueta", isSignal: true, isRequired: true, transformFunction: null }, defaultPNG: { classPropertyName: "defaultPNG", publicName: "defaultPNG", isSignal: true, isRequired: false, transformFunction: null }, defaultGIF: { classPropertyName: "defaultGIF", publicName: "defaultGIF", isSignal: true, isRequired: false, transformFunction: null }, icoPNG: { classPropertyName: "icoPNG", publicName: "icoPNG", isSignal: true, isRequired: false, transformFunction: null }, icoGIF: { classPropertyName: "icoGIF", publicName: "icoGIF", isSignal: true, isRequired: false, transformFunction: null }, subTitulo: { classPropertyName: "subTitulo", publicName: "subTitulo", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"area-fieldset-header flex items-center gap-2 px-2\">\r\n <p-avatar [image]=\"icono!\"></p-avatar>\r\n <div class=\"flex flex-col\">\r\n <h3>{{ textoEncabezado }}</h3>\r\n @if(subTitulo() !== null ){\r\n <ng-container>\r\n <span class=\"text-xs text-gray-600\">{{ subTitulo() }}</span>\r\n </ng-container>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }] });
8068
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: HeaderDsx, isStandalone: true, selector: "header-dsx", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, etiqueta: { classPropertyName: "etiqueta", publicName: "etiqueta", isSignal: true, isRequired: true, transformFunction: null }, defaultPNG: { classPropertyName: "defaultPNG", publicName: "defaultPNG", isSignal: true, isRequired: false, transformFunction: null }, defaultGIF: { classPropertyName: "defaultGIF", publicName: "defaultGIF", isSignal: true, isRequired: false, transformFunction: null }, icoPNG: { classPropertyName: "icoPNG", publicName: "icoPNG", isSignal: true, isRequired: false, transformFunction: null }, icoGIF: { classPropertyName: "icoGIF", publicName: "icoGIF", isSignal: true, isRequired: false, transformFunction: null }, subTitulo: { classPropertyName: "subTitulo", publicName: "subTitulo", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"area-fieldset-header flex items-center gap-2 px-2\">\r\n <p-avatar [image]=\"icono()!\"></p-avatar>\r\n <div class=\"flex flex-col\">\r\n <h3>{{ textoEncabezado() }}</h3>\r\n @if(subTitulo() !== null ){\r\n <span class=\"text-xs text-gray-600\">{{ subTitulo() }}</span>\r\n }\r\n <!-- Debug info con m\u00E9tricas de performance -->\r\n @if(debug()){\r\n <div\r\n class=\"text-xs mt-1 px-2 py-1 rounded flex flex-wrap items-center gap-1\"\r\n [class]=\"id() === 0 ? 'bg-blue-50 text-blue-700' : \r\n id() !== null && id()! > 0 ? 'bg-green-50 text-green-700' : \r\n 'bg-gray-50 text-gray-700'\"\r\n >\r\n <span>\uD83D\uDD0D</span>\r\n <span>ID: {{ id() }}</span>\r\n <span>|</span>\r\n <span>Modo: <strong>{{ modo() }}</strong></span>\r\n <span>|</span>\r\n <span>Texto: {{ textoEncabezado() }}</span>\r\n @if(id() !== null && id()! > 0){\r\n <span class=\"ml-1 text-xs\">(Editando ID {{ id() }})</span>\r\n }\r\n <!-- M\u00E9tricas de performance -->\r\n <span class=\"ml-1 text-xs text-gray-400\">\r\n | Render: {{ performanceMetrics.renderCount }} | Avg: {{\r\n performanceMetrics.averageRenderTime.toFixed(1) }}ms\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$3.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7790
8069
  }
7791
8070
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeaderDsx, decorators: [{
7792
8071
  type: Component,
7793
- args: [{ selector: 'header-dsx', imports: [AvatarModule], template: "<div class=\"area-fieldset-header flex items-center gap-2 px-2\">\r\n <p-avatar [image]=\"icono!\"></p-avatar>\r\n <div class=\"flex flex-col\">\r\n <h3>{{ textoEncabezado }}</h3>\r\n @if(subTitulo() !== null ){\r\n <ng-container>\r\n <span class=\"text-xs text-gray-600\">{{ subTitulo() }}</span>\r\n </ng-container>\r\n }\r\n </div>\r\n</div>\r\n" }]
7794
- }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], etiqueta: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiqueta", required: true }] }], defaultPNG: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPNG", required: false }] }], defaultGIF: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultGIF", required: false }] }], icoPNG: [{ type: i0.Input, args: [{ isSignal: true, alias: "icoPNG", required: false }] }], icoGIF: [{ type: i0.Input, args: [{ isSignal: true, alias: "icoGIF", required: false }] }], subTitulo: [{ type: i0.Input, args: [{ isSignal: true, alias: "subTitulo", required: false }] }] } });
8072
+ args: [{ selector: 'header-dsx', imports: [AvatarModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"area-fieldset-header flex items-center gap-2 px-2\">\r\n <p-avatar [image]=\"icono()!\"></p-avatar>\r\n <div class=\"flex flex-col\">\r\n <h3>{{ textoEncabezado() }}</h3>\r\n @if(subTitulo() !== null ){\r\n <span class=\"text-xs text-gray-600\">{{ subTitulo() }}</span>\r\n }\r\n <!-- Debug info con m\u00E9tricas de performance -->\r\n @if(debug()){\r\n <div\r\n class=\"text-xs mt-1 px-2 py-1 rounded flex flex-wrap items-center gap-1\"\r\n [class]=\"id() === 0 ? 'bg-blue-50 text-blue-700' : \r\n id() !== null && id()! > 0 ? 'bg-green-50 text-green-700' : \r\n 'bg-gray-50 text-gray-700'\"\r\n >\r\n <span>\uD83D\uDD0D</span>\r\n <span>ID: {{ id() }}</span>\r\n <span>|</span>\r\n <span>Modo: <strong>{{ modo() }}</strong></span>\r\n <span>|</span>\r\n <span>Texto: {{ textoEncabezado() }}</span>\r\n @if(id() !== null && id()! > 0){\r\n <span class=\"ml-1 text-xs\">(Editando ID {{ id() }})</span>\r\n }\r\n <!-- M\u00E9tricas de performance -->\r\n <span class=\"ml-1 text-xs text-gray-400\">\r\n | Render: {{ performanceMetrics.renderCount }} | Avg: {{\r\n performanceMetrics.averageRenderTime.toFixed(1) }}ms\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n" }]
8073
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], etiqueta: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiqueta", required: true }] }], defaultPNG: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPNG", required: false }] }], defaultGIF: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultGIF", required: false }] }], icoPNG: [{ type: i0.Input, args: [{ isSignal: true, alias: "icoPNG", required: false }] }], icoGIF: [{ type: i0.Input, args: [{ isSignal: true, alias: "icoGIF", required: false }] }], subTitulo: [{ type: i0.Input, args: [{ isSignal: true, alias: "subTitulo", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }] } });
7795
8074
 
7796
8075
  class DsxAddToolsModule {
7797
8076
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxAddToolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -8123,6 +8402,456 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8123
8402
  }]
8124
8403
  }] });
8125
8404
 
8405
+ // dsxdate-short.ts
8406
+ class DsxdateShort {
8407
+ injector = inject(Injector);
8408
+ // ✅ Exponer isDevMode como propiedad pública
8409
+ isDevMode = isDevMode();
8410
+ // === INPUTS CONFIGURABLES ===
8411
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
8412
+ placeholder = input('dd/mm/yyyy', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
8413
+ dateFormat = input('dd/mm/yy', ...(ngDevMode ? [{ debugName: "dateFormat" }] : /* istanbul ignore next */ []));
8414
+ showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon" }] : /* istanbul ignore next */ []));
8415
+ showOnFocus = input(false, ...(ngDevMode ? [{ debugName: "showOnFocus" }] : /* istanbul ignore next */ []));
8416
+ showButtonBar = input(true, ...(ngDevMode ? [{ debugName: "showButtonBar" }] : /* istanbul ignore next */ []));
8417
+ debug = input(false, ...(ngDevMode ? [{ debugName: "debug" }] : /* istanbul ignore next */ []));
8418
+ // === STATE ===
8419
+ debugEnabled = signal(false, ...(ngDevMode ? [{ debugName: "debugEnabled" }] : /* istanbul ignore next */ []));
8420
+ // === OBTENER EL CONTROL PADRE ===
8421
+ ngControl = computed(() => {
8422
+ try {
8423
+ return this.injector.get(NgControl);
8424
+ }
8425
+ catch {
8426
+ return null;
8427
+ }
8428
+ }, ...(ngDevMode ? [{ debugName: "ngControl" }] : /* istanbul ignore next */ []));
8429
+ // === CONTROL PADRE PARA ERRORES ===
8430
+ parentControl = computed(() => {
8431
+ const control = this.ngControl();
8432
+ return control?.control || null;
8433
+ }, ...(ngDevMode ? [{ debugName: "parentControl" }] : /* istanbul ignore next */ []));
8434
+ // === CONTROL INTERNO (para el template) ===
8435
+ fechaControl = new FormControl(null);
8436
+ // === CONTROL VALUE ACCESSOR ===
8437
+ onChange = () => { };
8438
+ onTouched = () => { };
8439
+ constructor() {
8440
+ // Debug effect
8441
+ effect(() => {
8442
+ const isDebug = this.debug() && this.isDevMode;
8443
+ this.debugEnabled.set(isDebug);
8444
+ if (isDebug) {
8445
+ console.log('[dsxdate-short] === DEBUG MODE ACTIVADO ===');
8446
+ console.log('[dsxdate-short] Configuración:', {
8447
+ label: this.label(),
8448
+ placeholder: this.placeholder(),
8449
+ dateFormat: this.dateFormat(),
8450
+ showIcon: this.showIcon(),
8451
+ showOnFocus: this.showOnFocus(),
8452
+ showButtonBar: this.showButtonBar(),
8453
+ });
8454
+ console.log('[dsxdate-short] Control padre:', this.parentControl());
8455
+ }
8456
+ });
8457
+ // ✅ SINCRONIZAR VALIDADORES DEL PADRE AL CONTROL INTERNO
8458
+ effect(() => {
8459
+ const parentCtrl = this.parentControl();
8460
+ if (parentCtrl) {
8461
+ // Copiar validadores del padre al control interno
8462
+ const validators = parentCtrl.validator;
8463
+ const asyncValidators = parentCtrl.asyncValidator;
8464
+ if (this.debugEnabled()) {
8465
+ console.log('[dsxdate-short] 🔄 Sincronizando validadores del padre');
8466
+ console.log('[dsxdate-short] Validadores del padre:', validators);
8467
+ }
8468
+ this.fechaControl.setValidators(validators ? [validators] : []);
8469
+ this.fechaControl.setAsyncValidators(asyncValidators ? [asyncValidators] : []);
8470
+ this.fechaControl.updateValueAndValidity({ emitEvent: false });
8471
+ if (this.debugEnabled()) {
8472
+ console.log('[dsxdate-short] ✅ Validadores sincronizados');
8473
+ console.log('[dsxdate-short] Estado del control interno:', {
8474
+ valid: this.fechaControl.valid,
8475
+ invalid: this.fechaControl.invalid,
8476
+ errors: this.fechaControl.errors,
8477
+ });
8478
+ }
8479
+ }
8480
+ });
8481
+ // Monitorear cambios del control padre
8482
+ effect(() => {
8483
+ if (this.debugEnabled()) {
8484
+ const parentCtrl = this.parentControl();
8485
+ console.log('[dsxdate-short] 📊 Parent Control state:', {
8486
+ value: parentCtrl?.value,
8487
+ status: parentCtrl?.status,
8488
+ errors: parentCtrl?.errors,
8489
+ valid: parentCtrl?.valid,
8490
+ invalid: parentCtrl?.invalid,
8491
+ touched: parentCtrl?.touched,
8492
+ dirty: parentCtrl?.dirty,
8493
+ });
8494
+ }
8495
+ });
8496
+ // Sincronizar cambios del control interno al padre
8497
+ this.fechaControl.valueChanges.subscribe((value) => {
8498
+ if (this.debugEnabled()) {
8499
+ console.log('[dsxdate-short] 🔄 valueChanges - Nuevo valor:', value);
8500
+ }
8501
+ this.onChange(value);
8502
+ });
8503
+ // Sincronizar touched
8504
+ this.fechaControl.statusChanges.subscribe(() => {
8505
+ if (this.debugEnabled()) {
8506
+ console.log('[dsxdate-short] 📊 statusChanges - Estado:', this.fechaControl.status);
8507
+ }
8508
+ this.onTouched();
8509
+ });
8510
+ }
8511
+ // === MÉTODOS DE DEBUG ===
8512
+ log(message, data) {
8513
+ if (this.debugEnabled() && this.isDevMode) {
8514
+ if (data !== undefined) {
8515
+ console.log(`[dsxdate-short] ${message}`, data);
8516
+ }
8517
+ else {
8518
+ console.log(`[dsxdate-short] ${message}`);
8519
+ }
8520
+ }
8521
+ }
8522
+ /**
8523
+ * Convierte cualquier fecha (string ISO, Date, moment) a Date válido
8524
+ */
8525
+ convertirFechaADate(fecha) {
8526
+ if (this.debugEnabled()) {
8527
+ this.log('🔄 convertirFechaADate - entrada:', fecha);
8528
+ }
8529
+ if (!fecha) {
8530
+ this.log('convertirFechaADate - fecha vacía, retornando null');
8531
+ return null;
8532
+ }
8533
+ if (fecha instanceof Date && !isNaN(fecha.getTime())) {
8534
+ this.log('✅ convertirFechaADate - es Date válido:', fecha);
8535
+ return fecha;
8536
+ }
8537
+ if (typeof fecha === 'string') {
8538
+ this.log('📝 convertirFechaADate - procesando string:', fecha);
8539
+ const momentDate = moment(fecha);
8540
+ if (momentDate.isValid()) {
8541
+ const result = momentDate.toDate();
8542
+ this.log('✅ convertirFechaADate - string convertido a Date:', result);
8543
+ return result;
8544
+ }
8545
+ this.log('❌ convertirFechaADate - string inválido para moment');
8546
+ }
8547
+ if (moment.isMoment(fecha)) {
8548
+ this.log('✅ convertirFechaADate - es objeto moment');
8549
+ return fecha.toDate();
8550
+ }
8551
+ const parsed = new Date(fecha);
8552
+ if (!isNaN(parsed.getTime())) {
8553
+ this.log('✅ convertirFechaADate - parseo directo exitoso:', parsed);
8554
+ return parsed;
8555
+ }
8556
+ this.log('❌ convertirFechaADate - no se pudo convertir, retornando null');
8557
+ return null;
8558
+ }
8559
+ // === CONTROL VALUE ACCESSOR IMPLEMENTATION ===
8560
+ writeValue(value) {
8561
+ if (this.debugEnabled()) {
8562
+ this.log('📥 writeValue - Valor recibido:', value);
8563
+ }
8564
+ const fechaConvertida = this.convertirFechaADate(value);
8565
+ if (this.debugEnabled()) {
8566
+ this.log('📥 writeValue - Valor convertido:', fechaConvertida);
8567
+ }
8568
+ this.fechaControl.setValue(fechaConvertida, { emitEvent: false });
8569
+ }
8570
+ registerOnChange(fn) {
8571
+ if (this.debugEnabled()) {
8572
+ this.log('📞 registerOnChange - Callback registrado');
8573
+ }
8574
+ this.onChange = fn;
8575
+ }
8576
+ registerOnTouched(fn) {
8577
+ if (this.debugEnabled()) {
8578
+ this.log('📞 registerOnTouched - Callback registrado');
8579
+ }
8580
+ this.onTouched = fn;
8581
+ }
8582
+ setDisabledState(isDisabled) {
8583
+ if (this.debugEnabled()) {
8584
+ this.log(`🚫 setDisabledState - Deshabilitado: ${isDisabled}`);
8585
+ }
8586
+ if (isDisabled) {
8587
+ this.fechaControl.disable({ emitEvent: false });
8588
+ }
8589
+ else {
8590
+ this.fechaControl.enable({ emitEvent: false });
8591
+ }
8592
+ }
8593
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxdateShort, deps: [], target: i0.ɵɵFactoryTarget.Component });
8594
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxdateShort, isStandalone: true, selector: "dsxdate-short", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, showOnFocus: { classPropertyName: "showOnFocus", publicName: "showOnFocus", isSignal: true, isRequired: false, transformFunction: null }, showButtonBar: { classPropertyName: "showButtonBar", publicName: "showButtonBar", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
8595
+ {
8596
+ provide: NG_VALUE_ACCESSOR,
8597
+ useExisting: forwardRef(() => DsxdateShort),
8598
+ multi: true,
8599
+ },
8600
+ ], ngImport: i0, template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] });
8601
+ }
8602
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxdateShort, decorators: [{
8603
+ type: Component,
8604
+ args: [{ selector: 'dsxdate-short', imports: [
8605
+ CommonModule,
8606
+ FloatLabel,
8607
+ DatePicker,
8608
+ ReactiveFormsModule,
8609
+ AppMessageErrorComponent,
8610
+ JsonPipe,
8611
+ ], providers: [
8612
+ {
8613
+ provide: NG_VALUE_ACCESSOR,
8614
+ useExisting: forwardRef(() => DsxdateShort),
8615
+ multi: true,
8616
+ },
8617
+ ], template: "<!-- dsxdate-short.html -->\r\n<p-floatLabel variant=\"on\">\r\n <p-datepicker\r\n [formControl]=\"fechaControl\"\r\n [fluid]=\"true\"\r\n [showIcon]=\"showIcon()\"\r\n [showOnFocus]=\"showOnFocus()\"\r\n [showButtonBar]=\"showButtonBar()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [placeholder]=\"placeholder()\"\r\n pInputMask=\"99/99/9999\"\r\n />\r\n <label>{{ label() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 SIN CONDICI\u00D3N - IGUAL QUE EL ORIGINAL -->\r\n<dsx-message-error [control]=\"fechaControl\" />\r\n\r\n<!-- Debug info -->\r\n@if (debugEnabled() && isDevMode) {\r\n<div\r\n class=\"debug-info\"\r\n style=\"\r\n font-size: 12px;\r\n color: #666;\r\n margin-top: 4px;\r\n border-top: 1px dashed #ccc;\r\n padding-top: 4px;\r\n \"\r\n>\r\n <small>\r\n <strong>Debug:</strong>\r\n Value: {{ fechaControl.value | json }} | Valid: {{ fechaControl.valid }} |\r\n Invalid: {{ fechaControl.invalid }} | Errors: {{ fechaControl.errors | json\r\n }} | Dirty: {{ fechaControl.dirty }} | Touched: {{ fechaControl.touched }} |\r\n Status: {{ fechaControl.status }}\r\n </small>\r\n</div>\r\n}\r\n" }]
8618
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], showOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOnFocus", required: false }] }], showButtonBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtonBar", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }] } });
8619
+
8620
+ // dsx-input-currency.ts
8621
+ class DsxInputCurrency {
8622
+ inputNumber;
8623
+ injector = inject(Injector);
8624
+ // === INPUTS CONFIGURABLES ===
8625
+ label = input('Saldo Actual', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
8626
+ currency = input('GTQ', ...(ngDevMode ? [{ debugName: "currency" }] : /* istanbul ignore next */ []));
8627
+ locale = input('es-GT', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
8628
+ minFractionDigits = input(2, ...(ngDevMode ? [{ debugName: "minFractionDigits" }] : /* istanbul ignore next */ []));
8629
+ maxFractionDigits = input(2, ...(ngDevMode ? [{ debugName: "maxFractionDigits" }] : /* istanbul ignore next */ []));
8630
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
8631
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
8632
+ selectAllOnFocus = input(true, ...(ngDevMode ? [{ debugName: "selectAllOnFocus" }] : /* istanbul ignore next */ []));
8633
+ debug = input(false, ...(ngDevMode ? [{ debugName: "debug" }] : /* istanbul ignore next */ []));
8634
+ showError = input(true, ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
8635
+ // === OUTPUTS ===
8636
+ valueChange = output();
8637
+ focus = output();
8638
+ blur = output();
8639
+ // === STATE ===
8640
+ valueSignal = signal(null, ...(ngDevMode ? [{ debugName: "valueSignal" }] : /* istanbul ignore next */ []));
8641
+ touched = signal(false, ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
8642
+ debugEnabled = signal(false, ...(ngDevMode ? [{ debugName: "debugEnabled" }] : /* istanbul ignore next */ []));
8643
+ // === COMPUTED ===
8644
+ resolvedLabel = computed(() => this.label(), ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
8645
+ resolvedCurrency = computed(() => this.currency(), ...(ngDevMode ? [{ debugName: "resolvedCurrency" }] : /* istanbul ignore next */ []));
8646
+ resolvedLocale = computed(() => this.locale(), ...(ngDevMode ? [{ debugName: "resolvedLocale" }] : /* istanbul ignore next */ []));
8647
+ // === OBTENER EL CONTROL PADRE ===
8648
+ ngControl = computed(() => {
8649
+ try {
8650
+ return this.injector.get(NgControl);
8651
+ }
8652
+ catch {
8653
+ return null;
8654
+ }
8655
+ }, ...(ngDevMode ? [{ debugName: "ngControl" }] : /* istanbul ignore next */ []));
8656
+ // === CONTROL PADRE PARA ERRORES ===
8657
+ parentControl = computed(() => {
8658
+ const control = this.ngControl();
8659
+ return control?.control || null;
8660
+ }, ...(ngDevMode ? [{ debugName: "parentControl" }] : /* istanbul ignore next */ []));
8661
+ // === CONTROL INTERNO (para el template) ===
8662
+ control = new FormControl();
8663
+ // === CONTROL VALUE ACCESSOR ===
8664
+ onChange = () => { };
8665
+ onTouched = () => { };
8666
+ constructor() {
8667
+ // Debug effect
8668
+ effect(() => {
8669
+ const isDebug = this.debug() && isDevMode();
8670
+ this.debugEnabled.set(isDebug);
8671
+ if (isDebug) {
8672
+ console.log('[dsx-input-currency] === DEBUG MODE ACTIVADO ===');
8673
+ console.log('[dsx-input-currency] Configuración:', {
8674
+ label: this.label(),
8675
+ currency: this.currency(),
8676
+ locale: this.locale(),
8677
+ minFractionDigits: this.minFractionDigits(),
8678
+ maxFractionDigits: this.maxFractionDigits(),
8679
+ placeholder: this.placeholder(),
8680
+ readonly: this.readonly(),
8681
+ selectAllOnFocus: this.selectAllOnFocus(),
8682
+ });
8683
+ console.log('[dsx-input-currency] Control padre:', this.parentControl());
8684
+ }
8685
+ });
8686
+ // Monitorear cambios del control padre
8687
+ effect(() => {
8688
+ if (this.debugEnabled()) {
8689
+ const parentCtrl = this.parentControl();
8690
+ console.log('[dsx-input-currency] 📊 Parent Control state:', {
8691
+ value: parentCtrl?.value,
8692
+ status: parentCtrl?.status,
8693
+ errors: parentCtrl?.errors,
8694
+ valid: parentCtrl?.valid,
8695
+ invalid: parentCtrl?.invalid,
8696
+ touched: parentCtrl?.touched,
8697
+ dirty: parentCtrl?.dirty,
8698
+ });
8699
+ }
8700
+ });
8701
+ }
8702
+ ngAfterViewInit() {
8703
+ if (this.debugEnabled()) {
8704
+ console.log('[dsx-input-currency] ngAfterViewInit - Vista inicializada');
8705
+ }
8706
+ // Sincronizar el control padre con el interno
8707
+ const parentCtrl = this.parentControl();
8708
+ if (parentCtrl) {
8709
+ this.control.setValue(parentCtrl.value, { emitEvent: false });
8710
+ }
8711
+ if (this.inputNumber && this.selectAllOnFocus()) {
8712
+ const inputElement = this.inputNumber.input
8713
+ .nativeElement;
8714
+ if (this.debugEnabled()) {
8715
+ console.log('[dsx-input-currency] Input element encontrado');
8716
+ }
8717
+ const originalFocus = inputElement.focus.bind(inputElement);
8718
+ const enhancedFocus = function () {
8719
+ originalFocus();
8720
+ setTimeout(() => this.select(), 0);
8721
+ };
8722
+ inputElement.focus = enhancedFocus;
8723
+ }
8724
+ }
8725
+ // === MÉTODOS PÚBLICOS ===
8726
+ onValueChange(value) {
8727
+ // ✅ Solo procesar si es un número válido
8728
+ if (value === null || value === undefined || isNaN(value)) {
8729
+ return;
8730
+ }
8731
+ if (this.debugEnabled()) {
8732
+ console.log(`[dsx-input-currency] 📝 onValueChange - Valor: ${value}`);
8733
+ }
8734
+ this.valueSignal.set(value);
8735
+ this.onChange(value);
8736
+ this.valueChange.emit(value);
8737
+ const parentCtrl = this.parentControl();
8738
+ if (parentCtrl) {
8739
+ parentCtrl.setValue(value, { emitEvent: true });
8740
+ }
8741
+ }
8742
+ onFocus() {
8743
+ if (this.debugEnabled()) {
8744
+ console.log(`[dsx-input-currency] 🔍 onFocus - Evento focus emitido`);
8745
+ }
8746
+ if (this.selectAllOnFocus() && this.inputNumber) {
8747
+ const inputElement = this.inputNumber.input
8748
+ .nativeElement;
8749
+ if (inputElement && typeof inputElement.select === 'function') {
8750
+ setTimeout(() => {
8751
+ inputElement.select();
8752
+ if (this.debugEnabled()) {
8753
+ console.log('[dsx-input-currency] ✅ Input seleccionado completamente');
8754
+ }
8755
+ }, 0);
8756
+ }
8757
+ }
8758
+ this.focus.emit();
8759
+ }
8760
+ onBlur() {
8761
+ const wasTouched = this.touched();
8762
+ this.touched.set(true);
8763
+ this.control.markAsTouched();
8764
+ const parentCtrl = this.parentControl();
8765
+ if (parentCtrl) {
8766
+ parentCtrl.markAsTouched();
8767
+ }
8768
+ if (this.debugEnabled()) {
8769
+ console.log(`[dsx-input-currency] 👋 onBlur - touched: ${!wasTouched ? 'Primera vez' : 'Ya estaba touched'}`);
8770
+ }
8771
+ this.blur.emit();
8772
+ }
8773
+ // === MÉTODOS DE DEBUG ===
8774
+ log(message, data) {
8775
+ if (this.debugEnabled() && isDevMode()) {
8776
+ if (data !== undefined) {
8777
+ console.log(`[dsx-input-currency] ${message}`, data);
8778
+ }
8779
+ else {
8780
+ console.log(`[dsx-input-currency] ${message}`);
8781
+ }
8782
+ }
8783
+ }
8784
+ // === CONTROL VALUE ACCESSOR IMPLEMENTATION ===
8785
+ writeValue(value) {
8786
+ if (this.debugEnabled()) {
8787
+ console.log(`[dsx-input-currency] 📥 writeValue - Valor recibido: ${value}`);
8788
+ }
8789
+ this.valueSignal.set(value);
8790
+ this.control.setValue(value, { emitEvent: false });
8791
+ }
8792
+ registerOnChange(fn) {
8793
+ if (this.debugEnabled()) {
8794
+ console.log('[dsx-input-currency] 📞 registerOnChange - Callback registrado');
8795
+ }
8796
+ this.onChange = fn;
8797
+ this.control.valueChanges.subscribe((val) => {
8798
+ if (this.debugEnabled()) {
8799
+ console.log(`[dsx-input-currency] 🔄 valueChanges - Nuevo valor: ${val}`);
8800
+ }
8801
+ this.onChange(val);
8802
+ });
8803
+ }
8804
+ registerOnTouched(fn) {
8805
+ if (this.debugEnabled()) {
8806
+ console.log('[dsx-input-currency] 📞 registerOnTouched - Callback registrado');
8807
+ }
8808
+ this.onTouched = fn;
8809
+ this.control.statusChanges.subscribe(() => {
8810
+ if (this.debugEnabled()) {
8811
+ console.log(`[dsx-input-currency] 📊 statusChanges - Estado: ${this.control.status}`);
8812
+ }
8813
+ this.onTouched();
8814
+ });
8815
+ }
8816
+ setDisabledState(isDisabled) {
8817
+ if (this.debugEnabled()) {
8818
+ console.log(`[dsx-input-currency] 🚫 setDisabledState - Deshabilitado: ${isDisabled}`);
8819
+ }
8820
+ if (isDisabled) {
8821
+ this.control.disable({ emitEvent: false });
8822
+ }
8823
+ else {
8824
+ this.control.enable({ emitEvent: false });
8825
+ }
8826
+ }
8827
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxInputCurrency, deps: [], target: i0.ɵɵFactoryTarget.Component });
8828
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxInputCurrency, isStandalone: true, selector: "dsx-input-currency", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, minFractionDigits: { classPropertyName: "minFractionDigits", publicName: "minFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, maxFractionDigits: { classPropertyName: "maxFractionDigits", publicName: "maxFractionDigits", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, selectAllOnFocus: { classPropertyName: "selectAllOnFocus", publicName: "selectAllOnFocus", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, showError: { classPropertyName: "showError", publicName: "showError", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", focus: "focus", blur: "blur" }, providers: [
8829
+ {
8830
+ provide: NG_VALUE_ACCESSOR,
8831
+ useExisting: forwardRef(() => DsxInputCurrency),
8832
+ multi: true,
8833
+ },
8834
+ ], viewQueries: [{ propertyName: "inputNumber", first: true, predicate: InputNumber, descendants: true }], ngImport: i0, template: "<!-- dsx-input-currency.html -->\r\n<p-floatLabel [variant]=\"'on'\">\r\n <p-inputNumber\r\n #inputNumber\r\n fluid\r\n [mode]=\"'currency'\"\r\n [currency]=\"resolvedCurrency()\"\r\n [locale]=\"resolvedLocale()\"\r\n [minFractionDigits]=\"minFractionDigits()\"\r\n [maxFractionDigits]=\"maxFractionDigits()\"\r\n [placeholder]=\"placeholder()\"\r\n [autocomplete]=\"'off'\"\r\n [formControl]=\"control\"\r\n [readonly]=\"readonly()\"\r\n (onFocus)=\"onFocus()\"\r\n (onBlur)=\"onBlur()\"\r\n (onInput)=\"onValueChange($event.value)\"\r\n />\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error usando el control padre -->\r\n@if (showError() && parentControl()) {\r\n<!-- [debugMode]=\"true\" -->\r\n<dsx-message-error [control]=\"parentControl()\" />\r\n}\r\n", styles: [":host ::ng-deep .p-inputnumber-input{text-align:right}\n"], dependencies: [{ kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
8835
+ }
8836
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxInputCurrency, decorators: [{
8837
+ type: Component,
8838
+ args: [{ selector: 'dsx-input-currency', imports: [
8839
+ FloatLabel,
8840
+ InputNumber,
8841
+ AppMessageErrorComponent,
8842
+ ReactiveFormsModule,
8843
+ ], providers: [
8844
+ {
8845
+ provide: NG_VALUE_ACCESSOR,
8846
+ useExisting: forwardRef(() => DsxInputCurrency),
8847
+ multi: true,
8848
+ },
8849
+ ], template: "<!-- dsx-input-currency.html -->\r\n<p-floatLabel [variant]=\"'on'\">\r\n <p-inputNumber\r\n #inputNumber\r\n fluid\r\n [mode]=\"'currency'\"\r\n [currency]=\"resolvedCurrency()\"\r\n [locale]=\"resolvedLocale()\"\r\n [minFractionDigits]=\"minFractionDigits()\"\r\n [maxFractionDigits]=\"maxFractionDigits()\"\r\n [placeholder]=\"placeholder()\"\r\n [autocomplete]=\"'off'\"\r\n [formControl]=\"control\"\r\n [readonly]=\"readonly()\"\r\n (onFocus)=\"onFocus()\"\r\n (onBlur)=\"onBlur()\"\r\n (onInput)=\"onValueChange($event.value)\"\r\n />\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error usando el control padre -->\r\n@if (showError() && parentControl()) {\r\n<!-- [debugMode]=\"true\" -->\r\n<dsx-message-error [control]=\"parentControl()\" />\r\n}\r\n", styles: [":host ::ng-deep .p-inputnumber-input{text-align:right}\n"] }]
8850
+ }], ctorParameters: () => [], propDecorators: { inputNumber: [{
8851
+ type: ViewChild,
8852
+ args: [InputNumber]
8853
+ }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], minFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "minFractionDigits", required: false }] }], maxFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFractionDigits", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], selectAllOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllOnFocus", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], focus: [{ type: i0.Output, args: ["focus"] }], blur: [{ type: i0.Output, args: ["blur"] }] } });
8854
+
8126
8855
  // dsx-select.component.ts
8127
8856
  class DsxSelect {
8128
8857
  injector = inject(Injector);
@@ -8137,22 +8866,28 @@ class DsxSelect {
8137
8866
  dataList = input.required(...(ngDevMode ? [{ debugName: "dataList" }] : /* istanbul ignore next */ []));
8138
8867
  variant = input('on', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
8139
8868
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
8140
- filterPlaceholder = input('Buscar ...', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
8869
+ filterPlaceholder = input('Buscar item...', ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
8141
8870
  showClear = input(true, ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
8142
8871
  // Override opcional (solo cuando la convención no aplica)
8143
8872
  optionLabel = input(undefined, ...(ngDevMode ? [{ debugName: "optionLabel" }] : /* istanbul ignore next */ []));
8144
8873
  optionValue = input(undefined, ...(ngDevMode ? [{ debugName: "optionValue" }] : /* istanbul ignore next */ []));
8874
+ // ✨ NUEVO: Campo secundario opcional (para mostrar información adicional)
8875
+ secondaryField = input(undefined, ...(ngDevMode ? [{ debugName: "secondaryField" }] : /* istanbul ignore next */ []));
8876
+ showSecondaryField = computed(() => !!this.secondaryField(), ...(ngDevMode ? [{ debugName: "showSecondaryField" }] : /* istanbul ignore next */ []));
8877
+ // ✨ NUEVO: Virtual Scroll (por defecto desactivado)
8878
+ virtualScroll = input(false, ...(ngDevMode ? [{ debugName: "virtualScroll" }] : /* istanbul ignore next */ []));
8879
+ virtualScrollItemSize = input(40, ...(ngDevMode ? [{ debugName: "virtualScrollItemSize" }] : /* istanbul ignore next */ []));
8145
8880
  // Iconos
8146
8881
  useIcon = input(true, ...(ngDevMode ? [{ debugName: "useIcon" }] : /* istanbul ignore next */ []));
8147
8882
  itemIcon = input('keyboard_arrow_right', ...(ngDevMode ? [{ debugName: "itemIcon" }] : /* istanbul ignore next */ []));
8148
8883
  selectedIcon = input('done_outline', ...(ngDevMode ? [{ debugName: "selectedIcon" }] : /* istanbul ignore next */ []));
8149
8884
  // Debug solo consola
8150
8885
  debug = input(false, ...(ngDevMode ? [{ debugName: "debug" }] : /* istanbul ignore next */ []));
8151
- // Mostrar mensajes de error (por defecto true)
8886
+ // Mostrar mensajes de error (por defecto true)
8152
8887
  showError = input(true, ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
8153
8888
  // Signal model para two-way binding
8154
8889
  selectedValue = model(null, ...(ngDevMode ? [{ debugName: "selectedValue" }] : /* istanbul ignore next */ []));
8155
- // Computed: OptionValue inferido automáticamente (siempre string)
8890
+ // Computed: OptionValue inferido automáticamente
8156
8891
  resolvedOptionValue = computed(() => {
8157
8892
  if (this.optionValue()) {
8158
8893
  return this.optionValue();
@@ -8166,7 +8901,7 @@ class DsxSelect {
8166
8901
  }
8167
8902
  return 'id';
8168
8903
  }, ...(ngDevMode ? [{ debugName: "resolvedOptionValue" }] : /* istanbul ignore next */ []));
8169
- // Computed: OptionLabel inferido automáticamente (siempre string)
8904
+ // Computed: OptionLabel inferido automáticamente
8170
8905
  resolvedOptionLabel = computed(() => {
8171
8906
  if (this.optionLabel()) {
8172
8907
  return this.optionLabel();
@@ -8180,7 +8915,7 @@ class DsxSelect {
8180
8915
  }
8181
8916
  return 'nombre';
8182
8917
  }, ...(ngDevMode ? [{ debugName: "resolvedOptionLabel" }] : /* istanbul ignore next */ []));
8183
- // Computed: Label inferido automáticamente (siempre string)
8918
+ // Computed: Label inferido automáticamente
8184
8919
  resolvedLabel = computed(() => {
8185
8920
  if (this.label()) {
8186
8921
  return this.label();
@@ -8193,7 +8928,7 @@ class DsxSelect {
8193
8928
  }
8194
8929
  return 'Campo';
8195
8930
  }, ...(ngDevMode ? [{ debugName: "resolvedLabel" }] : /* istanbul ignore next */ []));
8196
- // Computed: Obtener el control para errores (solo si showError es true)
8931
+ // Computed: Obtener el control para errores
8197
8932
  errorControl = computed(() => {
8198
8933
  if (!this.showError())
8199
8934
  return null;
@@ -8215,6 +8950,8 @@ class DsxSelect {
8215
8950
  optionLabel: this.resolvedOptionLabel(),
8216
8951
  label: this.resolvedLabel(),
8217
8952
  showError: this.showError(),
8953
+ virtualScroll: this.virtualScroll(),
8954
+ secondaryField: this.secondaryField(),
8218
8955
  });
8219
8956
  }
8220
8957
  });
@@ -8228,14 +8965,22 @@ class DsxSelect {
8228
8965
  console.log(`Control: ${this.getFormControlName()}`);
8229
8966
  console.log(`Items: ${dataList.length}`);
8230
8967
  console.log(`Using: optionValue="${this.resolvedOptionValue()}", optionLabel="${this.resolvedOptionLabel()}"`);
8968
+ if (this.secondaryField()) {
8969
+ console.log(`Secondary field: "${this.secondaryField()}"`);
8970
+ }
8231
8971
  console.log(`Time since last update: ${(currentTime - this.lastChangeTimestamp).toFixed(2)}ms`);
8232
8972
  if (dataList.length > 0 && this.debug()) {
8233
8973
  console.log(`Sample:`, dataList[0]);
8234
8974
  console.log(`Value sample:`, dataList[0][this.resolvedOptionValue()]);
8235
8975
  console.log(`Label sample:`, dataList[0][this.resolvedOptionLabel()]);
8976
+ if (this.secondaryField()) {
8977
+ const secondary = this.secondaryField();
8978
+ console.log(`Secondary sample:`, dataList[0][secondary]);
8979
+ }
8236
8980
  }
8237
8981
  if (dataList.length > 500) {
8238
8982
  console.warn(`⚠️ Large dataset: ${dataList.length} items`);
8983
+ console.log(`💡 Consider enabling virtualScroll="true"`);
8239
8984
  }
8240
8985
  console.groupEnd();
8241
8986
  }
@@ -8302,14 +9047,41 @@ class DsxSelect {
8302
9047
  console.groupEnd();
8303
9048
  }
8304
9049
  }
9050
+ // dsx-select.component.ts - Agregar estos métodos
9051
+ /**
9052
+ * Cuando el select recibe foco
9053
+ */
9054
+ onFocus() {
9055
+ if (this.debug()) {
9056
+ console.log('[DsxSelect] onFocus');
9057
+ }
9058
+ }
9059
+ /**
9060
+ * Cuando el panel de opciones se cierra (el usuario ha interactuado)
9061
+ * Este es el evento clave que marca el control como touched
9062
+ */
9063
+ onHide() {
9064
+ if (this.debug()) {
9065
+ console.log('[DsxSelect] onHide - dropdown closed');
9066
+ }
9067
+ // Marcar como touched cuando el usuario cierra el dropdown
9068
+ // Esto incluye: seleccionar un valor O hacer clic fuera
9069
+ if (this.ngControl?.control && !this.ngControl.control.touched) {
9070
+ this.ngControl.control.markAsTouched();
9071
+ this.onTouched();
9072
+ if (this.debug()) {
9073
+ console.log('[DsxSelect] Control marked as touched (onHide)');
9074
+ }
9075
+ }
9076
+ }
8305
9077
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
8306
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxSelect, isStandalone: true, selector: "dsx-select", inputs: { dataList: { classPropertyName: "dataList", publicName: "dataList", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, useIcon: { classPropertyName: "useIcon", publicName: "useIcon", isSignal: true, isRequired: false, transformFunction: null }, itemIcon: { classPropertyName: "itemIcon", publicName: "itemIcon", isSignal: true, isRequired: false, transformFunction: null }, selectedIcon: { classPropertyName: "selectedIcon", publicName: "selectedIcon", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, showError: { classPropertyName: "showError", publicName: "showError", isSignal: true, isRequired: false, transformFunction: null }, selectedValue: { classPropertyName: "selectedValue", publicName: "selectedValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedValue: "selectedValueChange" }, providers: [
9078
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: DsxSelect, isStandalone: true, selector: "dsx-select", inputs: { dataList: { classPropertyName: "dataList", publicName: "dataList", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: false, transformFunction: null }, secondaryField: { classPropertyName: "secondaryField", publicName: "secondaryField", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, useIcon: { classPropertyName: "useIcon", publicName: "useIcon", isSignal: true, isRequired: false, transformFunction: null }, itemIcon: { classPropertyName: "itemIcon", publicName: "itemIcon", isSignal: true, isRequired: false, transformFunction: null }, selectedIcon: { classPropertyName: "selectedIcon", publicName: "selectedIcon", isSignal: true, isRequired: false, transformFunction: null }, debug: { classPropertyName: "debug", publicName: "debug", isSignal: true, isRequired: false, transformFunction: null }, showError: { classPropertyName: "showError", publicName: "showError", isSignal: true, isRequired: false, transformFunction: null }, selectedValue: { classPropertyName: "selectedValue", publicName: "selectedValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedValue: "selectedValueChange" }, providers: [
8307
9079
  {
8308
9080
  provide: NG_VALUE_ACCESSOR,
8309
9081
  useExisting: forwardRef(() => DsxSelect),
8310
9082
  multi: true,
8311
9083
  },
8312
- ], ngImport: i0, template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n >\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\"></icon-dsx>\r\n } {{ item[resolvedOptionLabel()] }}\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center\">\r\n @if (useIcon()) {\r\n <icon-dsx\r\n [name]=\"selectedIcon()\"\r\n class=\"text-green-600! mr-1\"\r\n ></icon-dsx>\r\n } {{ selectedOptions?.[resolvedOptionLabel()] }}\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 Mensaje de error condicional (dentro del floatLabel) -->\r\n@if (showError() && errorControl()) {\r\n<app-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }, { kind: "component", type: AppMessageErrorComponent, selector: "app-message-error", inputs: ["control", "form", "debugMode"] }] });
9084
+ ], ngImport: i0, template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-2\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-cyan-500! mr-1\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-2\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "component", type: IconDsxComponent, selector: "icon-dsx", inputs: ["name", "style", "debug"] }, { kind: "component", type: AppMessageErrorComponent, selector: "dsx-message-error", inputs: ["control", "form", "debugMode"] }] });
8313
9085
  }
8314
9086
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DsxSelect, decorators: [{
8315
9087
  type: Component,
@@ -8325,8 +9097,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8325
9097
  useExisting: forwardRef(() => DsxSelect),
8326
9098
  multi: true,
8327
9099
  },
8328
- ], template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n >\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\"></icon-dsx>\r\n } {{ item[resolvedOptionLabel()] }}\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center\">\r\n @if (useIcon()) {\r\n <icon-dsx\r\n [name]=\"selectedIcon()\"\r\n class=\"text-green-600! mr-1\"\r\n ></icon-dsx>\r\n } {{ selectedOptions?.[resolvedOptionLabel()] }}\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- \u2705 Mensaje de error condicional (dentro del floatLabel) -->\r\n@if (showError() && errorControl()) {\r\n<app-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"] }]
8329
- }], ctorParameters: () => [], propDecorators: { dataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataList", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], useIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "useIcon", required: false }] }], itemIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemIcon", required: false }] }], selectedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIcon", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], selectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValue", required: false }] }, { type: i0.Output, args: ["selectedValueChange"] }] } });
9100
+ ], template: "<!-- dsx-select.html -->\r\n<p-floatLabel [variant]=\"variant()\">\r\n <p-select\r\n fluid\r\n appendTo=\"body\"\r\n [options]=\"dataList()\"\r\n [filter]=\"true\"\r\n [filterPlaceholder]=\"filterPlaceholder()\"\r\n [showClear]=\"showClear()\"\r\n [disabled]=\"disabled\"\r\n [optionLabel]=\"resolvedOptionLabel()\"\r\n [optionValue]=\"resolvedOptionValue()\"\r\n [virtualScroll]=\"virtualScroll()\"\r\n [virtualScrollItemSize]=\"virtualScrollItemSize()\"\r\n [(ngModel)]=\"value\"\r\n (ngModelChange)=\"onValueChange($event)\"\r\n (onFocus)=\"onFocus()\"\r\n (onHide)=\"onHide()\"\r\n >\r\n <!-- Item template -->\r\n <ng-template let-item #item>\r\n <div class=\"flex align-items-center gap-2\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"itemIcon()\" class=\"text-cyan-500! mr-1\"></icon-dsx>\r\n } @if (showSecondaryField()) {\r\n <div class=\"flex flex-col\">\r\n <span class=\"font-semibold text-sky-800\">\r\n {{ item[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-xs text-gray-400\">\r\n {{ item[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ item[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Selected item template -->\r\n <ng-template #selectedItem let-selectedOptions>\r\n <div class=\"flex align-items-center gap-2\">\r\n @if (useIcon()) {\r\n <icon-dsx [name]=\"selectedIcon()\" class=\"text-green-600!\"></icon-dsx>\r\n } @if (showSecondaryField() && selectedOptions) {\r\n <div class=\"flex gap-x-2\">\r\n <span class=\"font-semibold text-sky-700\">\r\n {{ selectedOptions[resolvedOptionLabel()] }}\r\n </span>\r\n <span class=\"text-gray-400\">\r\n {{ selectedOptions[secondaryField()!] }}\r\n </span>\r\n </div>\r\n } @else { {{ selectedOptions?.[resolvedOptionLabel()] }} }\r\n </div>\r\n </ng-template>\r\n </p-select>\r\n <label>{{ resolvedLabel() }}</label>\r\n</p-floatLabel>\r\n\r\n<!-- Mensaje de error condicional -->\r\n@if (showError() && errorControl()) {\r\n<dsx-message-error [control]=\"errorControl()\" />\r\n}\r\n", styles: ["icon-dsx{font-size:1.5em}\n"] }]
9101
+ }], ctorParameters: () => [], propDecorators: { dataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataList", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], optionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionValue", required: false }] }], secondaryField: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryField", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], useIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "useIcon", required: false }] }], itemIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemIcon", required: false }] }], selectedIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIcon", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], selectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValue", required: false }] }, { type: i0.Output, args: ["selectedValueChange"] }] } });
8330
9102
 
8331
9103
  /**
8332
9104
  * Servicio genérico para consumir endpoints REST de la API.
@@ -9583,24 +10355,69 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9583
10355
 
9584
10356
  // form-preview.service.ts
9585
10357
  class FormPreviewService {
10358
+ environment;
10359
+ constructor() {
10360
+ // Inyectar el token en el constructor
10361
+ this.environment = inject(ENVIRONMENT);
10362
+ }
10363
+ /**
10364
+ * Construye el HTML para el preview de un objeto
10365
+ * @param data - Objeto con los datos a mostrar
10366
+ * @param fields - Configuración de los campos a mostrar
10367
+ * @param options - Opciones de configuración
10368
+ * @returns String con el HTML generado
10369
+ *
10370
+ * @example
10371
+ * ```typescript
10372
+ * const data = {
10373
+ * usuario: {
10374
+ * nombre: 'Juan Pérez',
10375
+ * email: 'juan@email.com'
10376
+ * },
10377
+ * estado: 1
10378
+ * };
10379
+ *
10380
+ * const fields = [
10381
+ * { key: 'usuario.nombre', label: 'Nombre' },
10382
+ * { key: 'usuario.email', label: 'Email' },
10383
+ * {
10384
+ * key: 'estado',
10385
+ * label: 'Estado',
10386
+ * referenceMap: new Map([[1, 'Activo'], [2, 'Inactivo']])
10387
+ * }
10388
+ * ];
10389
+ *
10390
+ * const html = this.formPreviewService.buildObjectSummaryHtml(data, fields, {
10391
+ * title: 'Datos del Usuario',
10392
+ * showEmpty: false,
10393
+ * compact: true,
10394
+ * debug: false
10395
+ * });
10396
+ * ```
10397
+ */
9586
10398
  buildObjectSummaryHtml(data, fields, options) {
9587
10399
  const debug = options?.debug ?? false;
9588
- if (debug) {
10400
+ const isDev = !this.environment.production;
10401
+ // Solo ejecutar logs si estamos en desarrollo y debug está activado
10402
+ if (debug && isDev) {
9589
10403
  this.debugInputData(data, fields, options);
9590
10404
  }
10405
+ // Logs de error siempre se muestran en desarrollo si debug está activado
9591
10406
  if (!data) {
9592
- if (debug)
10407
+ if (debug && isDev) {
9593
10408
  console.error('❌ FormPreview: data es null o undefined');
10409
+ }
9594
10410
  return '';
9595
10411
  }
9596
10412
  if (!fields || fields.length === 0) {
9597
- if (debug)
10413
+ if (debug && isDev) {
9598
10414
  console.error('❌ FormPreview: fields está vacío');
10415
+ }
9599
10416
  return '';
9600
10417
  }
9601
10418
  const showEmpty = options?.showEmpty ?? false;
9602
10419
  const compact = options?.compact ?? true;
9603
- const title = options?.title || 'Datos del formulario';
10420
+ const title = options?.title || '📋 Datos a guardar';
9604
10421
  const cells = [];
9605
10422
  const propiedadesNoEncontradas = [];
9606
10423
  for (const field of fields) {
@@ -9609,7 +10426,8 @@ class FormPreviewService {
9609
10426
  if (field.referenceMap && value !== undefined && value !== null) {
9610
10427
  const originalValue = value;
9611
10428
  value = this.resolveReferenceValue(value, field);
9612
- if (debug) {
10429
+ // Logs de depuración solo en desarrollo
10430
+ if (debug && isDev) {
9613
10431
  console.log(`🔍 Resolviendo referencia para "${field.key}":`, {
9614
10432
  original: originalValue,
9615
10433
  resuelto: value,
@@ -9636,7 +10454,8 @@ class FormPreviewService {
9636
10454
  value: valueText || '—',
9637
10455
  });
9638
10456
  }
9639
- if (debug) {
10457
+ // Logs de depuración solo en desarrollo
10458
+ if (debug && isDev) {
9640
10459
  if (propiedadesNoEncontradas.length > 0) {
9641
10460
  console.warn('⚠️ FormPreview: Propiedades no encontradas:', propiedadesNoEncontradas);
9642
10461
  console.warn('📋 Propiedades disponibles en data:', Object.keys(data));
@@ -9656,7 +10475,6 @@ class FormPreviewService {
9656
10475
  return this.generateHtml(title, cells, compact);
9657
10476
  }
9658
10477
  resolveReferenceValue(value, field) {
9659
- // Si es array (multi-select)
9660
10478
  if (Array.isArray(value)) {
9661
10479
  return value.map((item) => this.resolveSingleReference(item, field));
9662
10480
  }
@@ -9665,40 +10483,32 @@ class FormPreviewService {
9665
10483
  resolveSingleReference(value, field) {
9666
10484
  if (!value)
9667
10485
  return value;
9668
- // Si ya es objeto, devolverlo
9669
- if (typeof value === 'object' && value !== null) {
10486
+ if (typeof value === 'object' && value !== null)
9670
10487
  return value;
9671
- }
9672
10488
  const map = field.referenceMap;
9673
10489
  if (!map)
9674
10490
  return value;
9675
10491
  let referencedItem = null;
9676
- // Si es función
9677
10492
  if (typeof map === 'function') {
9678
10493
  referencedItem = map(value);
9679
10494
  }
9680
- // Si es Map
9681
10495
  else if (map instanceof Map) {
9682
10496
  referencedItem = map.get(value);
9683
10497
  }
9684
- // Si es Array
9685
10498
  else if (Array.isArray(map)) {
9686
10499
  const idKey = field.referenceId || 'id';
9687
10500
  referencedItem = map.find((item) => item[idKey] === value);
9688
10501
  }
9689
- // Si es objeto literal
9690
10502
  else if (typeof map === 'object') {
9691
10503
  referencedItem = map[String(value)];
9692
10504
  }
9693
10505
  if (referencedItem) {
9694
10506
  const labelProp = field.referenceLabel || 'nombre';
9695
10507
  if (typeof referencedItem === 'object' && referencedItem !== null) {
9696
- // Buscar la propiedad en el objeto
9697
10508
  if (referencedItem[labelProp] !== undefined &&
9698
10509
  referencedItem[labelProp] !== null) {
9699
10510
  return referencedItem[labelProp];
9700
10511
  }
9701
- // Si no encuentra la propiedad, devolver el objeto completo
9702
10512
  return referencedItem;
9703
10513
  }
9704
10514
  return referencedItem;
@@ -9711,9 +10521,8 @@ class FormPreviewService {
9711
10521
  const parts = path.split('.');
9712
10522
  let result = obj;
9713
10523
  for (const part of parts) {
9714
- if (result === null || result === undefined) {
10524
+ if (result === null || result === undefined)
9715
10525
  return undefined;
9716
- }
9717
10526
  result = result[part];
9718
10527
  }
9719
10528
  return result;
@@ -9816,6 +10625,9 @@ class FormPreviewService {
9816
10625
  `;
9817
10626
  }
9818
10627
  debugInputData(data, fields, options) {
10628
+ const isDev = !this.environment.production;
10629
+ if (!isDev)
10630
+ return;
9819
10631
  console.group('🔍 FormPreview Debug');
9820
10632
  console.log('📊 Data:', data);
9821
10633
  console.log('📋 Propiedades disponibles:', data ? Object.keys(data) : 'data es null');
@@ -9866,13 +10678,17 @@ class FormPreviewService {
9866
10678
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FormPreviewService, decorators: [{
9867
10679
  type: Injectable,
9868
10680
  args: [{ providedIn: 'root' }]
9869
- }] });
10681
+ }], ctorParameters: () => [] });
9870
10682
 
9871
10683
  // table-preview.service.ts
9872
10684
  class TablePreviewService {
10685
+ environment = inject(ENVIRONMENT);
10686
+ isProduction = this.environment?.production ?? false;
9873
10687
  buildSingleRowSummaryHtml(row, columns, options) {
9874
- const debug = options?.debug ?? false; // Por defecto false
9875
- // Solo mostrar logs si debug está activado
10688
+ const debug = !this.isProduction && (options?.debug ?? false);
10689
+ const showRowId = options?.showRowId ?? false;
10690
+ const title = options?.title || '🗑️ Datos a eliminar';
10691
+ const icon = options?.icon || '';
9876
10692
  if (debug) {
9877
10693
  this.debugInputData(row, columns, options);
9878
10694
  }
@@ -9892,33 +10708,50 @@ class TablePreviewService {
9892
10708
  const rowId = options?.rowId?.trim() || '1';
9893
10709
  const cells = [];
9894
10710
  const propiedadesNoEncontradas = [];
10711
+ // Si showRowId está activo, agregamos una fila con el ID
10712
+ if (showRowId) {
10713
+ cells.push({ label: 'ID', value: rowId });
10714
+ }
9895
10715
  for (const col of columns) {
9896
- // Obtener key
9897
10716
  const key = typeof col === 'string' ? col : col.key;
9898
- // Obtener valor con validación
10717
+ const formatFn = typeof col === 'object' ? col.format : undefined;
9899
10718
  const value = this.getNestedValue(row, key);
9900
- const valueText = this.formatValue(value);
9901
- // Registrar si no se encontró la propiedad
10719
+ let valueText;
10720
+ if (formatFn && typeof formatFn === 'function') {
10721
+ try {
10722
+ valueText = formatFn(value, row) ?? '';
10723
+ }
10724
+ catch (error) {
10725
+ if (debug) {
10726
+ console.error(`❌ Error al formatear "${key}":`, error);
10727
+ }
10728
+ valueText = this.formatValue(value);
10729
+ }
10730
+ }
10731
+ else {
10732
+ valueText = this.formatValue(value);
10733
+ }
9902
10734
  if (value === undefined) {
9903
10735
  propiedadesNoEncontradas.push(key);
9904
10736
  }
9905
- // Filtrar vacíos
9906
- if (!includeEmpty && !valueText)
10737
+ const isEmpty = value === null ||
10738
+ value === undefined ||
10739
+ value === '' ||
10740
+ (Array.isArray(value) && value.length === 0);
10741
+ if (!includeEmpty && isEmpty)
9907
10742
  continue;
9908
- // Obtener label
9909
10743
  let label = headerMap[key];
9910
10744
  if (!label && typeof col === 'object' && col.label)
9911
10745
  label = col.label;
9912
10746
  if (!label)
9913
10747
  label = this.humanizeKey(key);
9914
- cells.push({ label, value: valueText || '—' });
10748
+ const displayValue = isEmpty ? '—' : valueText;
10749
+ cells.push({ label, value: displayValue });
9915
10750
  }
9916
- // Solo mostrar logs si debug está activado
9917
10751
  if (debug) {
9918
10752
  if (propiedadesNoEncontradas.length > 0) {
9919
10753
  console.warn('⚠️ TablePreview: Propiedades no encontradas:', propiedadesNoEncontradas);
9920
10754
  console.warn('📋 Propiedades disponibles en rowData:', Object.keys(row));
9921
- console.warn('💡 Sugerencia: Verifica que los nombres coincidan exactamente');
9922
10755
  }
9923
10756
  if (cells.length === 0) {
9924
10757
  console.error('❌ TablePreview: No se generaron celdas. Verifica tus columnas y datos.');
@@ -9931,7 +10764,7 @@ class TablePreviewService {
9931
10764
  }
9932
10765
  if (!cells.length)
9933
10766
  return '';
9934
- return this.generateCompactHtml(rowId, cells, showLabel);
10767
+ return this.generateCompactHtml(cells, showLabel, title, icon);
9935
10768
  }
9936
10769
  getNestedValue(obj, path) {
9937
10770
  if (!obj || !path)
@@ -9949,6 +10782,8 @@ class TablePreviewService {
9949
10782
  formatValue(value) {
9950
10783
  if (value === null || value === undefined)
9951
10784
  return '';
10785
+ if (typeof value === 'number')
10786
+ return String(value);
9952
10787
  if (value instanceof Date)
9953
10788
  return value.toLocaleDateString();
9954
10789
  if (typeof value === 'object') {
@@ -9970,30 +10805,29 @@ class TablePreviewService {
9970
10805
  .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
9971
10806
  .join(' ');
9972
10807
  }
9973
- generateCompactHtml(rowId, cells, showLabel) {
9974
- const rowIdWidth = Math.min(Math.max(rowId.length, 1), 3);
10808
+ generateCompactHtml(cells, showLabel, title, icon) {
9975
10809
  return `
9976
10810
  <div style="margin: 8px 0; border: 1px solid #e9ecef; border-radius: 6px; overflow: hidden; background: #ffffff; font-size: 13px;">
10811
+ <!-- Encabezado con título e ícono -->
10812
+ <div style="padding: 10px 12px; background: #f8f9fa; border-bottom: 1px solid #e9ecef; font-weight: 600; color: #212529; text-align: center; font-size: 14px;">
10813
+ ${icon ? `<span style="margin-right: 8px; font-size: 18px;">${icon}</span>` : ''}
10814
+ ${this.escapeHtml(title)}
10815
+ </div>
10816
+
10817
+ <!-- Tabla de datos -->
9977
10818
  <table style="width: 100%; border-collapse: collapse; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
9978
10819
  <tbody>
9979
10820
  ${cells
9980
10821
  .map((cell, i) => `
9981
10822
  <tr style="border-bottom: ${i < cells.length - 1 ? '0.5px solid #f1f3f5' : 'none'}">
9982
- ${i === 0
9983
- ? `
9984
- <td style="padding: 6px 8px; background: #f8f9fa; font-weight: 600; color: #6c757d; border-right: 0.5px solid #f1f3f5; vertical-align: top;">
9985
- ${this.escapeHtml(rowId)}
9986
- </td>
9987
- `
9988
- : ''}
9989
10823
  ${showLabel
9990
10824
  ? `
9991
- <td style="padding: 6px 8px; background: #f8f9fa; text-transform: uppercase; width: auto; color: #6c757d; border-right: 0.5px solid #f1f3f5;">
10825
+ <td style="padding: 8px 12px; background: #f8f9fa; text-transform: uppercase; width: 40%; color: #6c757d; border-right: 0.5px solid #f1f3f5; font-weight: 600; font-size: 11px; letter-spacing: 0.3px;">
9992
10826
  ${this.escapeHtml(cell.label)}
9993
10827
  </td>
9994
10828
  `
9995
10829
  : ''}
9996
- <td style="padding: 6px 8px; color: #212529; font-weight: 500;">
10830
+ <td style="padding: 8px 12px; color: #212529; font-weight: 500;">
9997
10831
  ${this.escapeHtml(cell.value)}
9998
10832
  </td>
9999
10833
  </tr>
@@ -10010,7 +10844,6 @@ class TablePreviewService {
10010
10844
  console.log('📋 Propiedades disponibles:', row ? Object.keys(row) : 'row es null');
10011
10845
  console.log('🎯 Columns solicitadas:', columns);
10012
10846
  console.log('⚙️ Options:', options);
10013
- // Verificar cada columna
10014
10847
  if (row) {
10015
10848
  for (const col of columns) {
10016
10849
  const key = typeof col === 'string' ? col : col.key;
@@ -10018,7 +10851,6 @@ class TablePreviewService {
10018
10851
  const existe = value !== undefined;
10019
10852
  if (!existe) {
10020
10853
  console.warn(`❌ Propiedad "${key}" NO existe en rowData`);
10021
- // Sugerir propiedades similares
10022
10854
  const similares = this.findSimilarProperties(key, Object.keys(row));
10023
10855
  if (similares.length > 0) {
10024
10856
  console.warn(`💡 Quizás quisiste decir: ${similares.join(', ')}`);
@@ -10036,16 +10868,14 @@ class TablePreviewService {
10036
10868
  const searchLower = search.toLowerCase();
10037
10869
  for (const prop of properties) {
10038
10870
  const propLower = prop.toLowerCase();
10039
- // Buscar similitudes (contiene o es similar)
10040
10871
  if (propLower.includes(searchLower) || searchLower.includes(propLower)) {
10041
10872
  similares.push(prop);
10042
10873
  }
10043
- // Distancia de Levenshtein simple (máximo 3 caracteres de diferencia)
10044
10874
  else if (this.levenshteinDistance(searchLower, propLower) <= 3) {
10045
10875
  similares.push(prop);
10046
10876
  }
10047
10877
  }
10048
- return similares.slice(0, 3); // Máximo 3 sugerencias
10878
+ return similares.slice(0, 3);
10049
10879
  }
10050
10880
  levenshteinDistance(a, b) {
10051
10881
  if (a.length === 0)
@@ -10769,5 +11599,5 @@ function sorensenDiceValidator(dataSource, key, umbral = 0.7) {
10769
11599
  * Generated bundle index. Do not edit.
10770
11600
  */
10771
11601
 
10772
- export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, AppMessageHelpComponent, ArrowNavigationDirective, AuthorizeService, AutoScrollHeightDirective, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxAutocomplete, DsxButtonComponent, DsxEnableDisable, DsxMessagesService, DsxSelect, DsxStatusToggle, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, FormPreviewService, GTQFormatter, HeaderDsx, HelpersService, HttpHelpersService, INITIAL_PARAMETERS, IcoLabel, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, QrGenerator, ResultFileService, SWEET_ALERT_THEMES, ScreenInspector, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, SweetAlert2DialogService, TablePreviewService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, getActionMessageConfig, getZeroBasedRolIndex, guardTokenPurposeGuard, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, sorensenDiceValidator, templateStructureValidator, templateVariablesValidator, validateEnvironmentConfig };
11602
+ export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, AppMessageHelpComponent, ArrowNavigationDirective, AuthorizeService, AutoScrollHeightDirective, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxAutocomplete, DsxButtonComponent, DsxEnableDisable, DsxInputCurrency, DsxMessagesService, DsxSelect, DsxStatusToggle, DsxdateShort, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, FormPreviewService, GTQFormatter, HeaderDsx, HelpersService, HttpHelpersService, INITIAL_PARAMETERS, IcoLabel, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, QrGenerator, ResultFileService, SWEET_ALERT_THEMES, ScreenInspector, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, SweetAlert2DialogService, TablePreviewService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, getActionMessageConfig, getZeroBasedRolIndex, guardTokenPurposeGuard, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, sorensenDiceValidator, templateStructureValidator, templateVariablesValidator, validateEnvironmentConfig };
10773
11603
  //# sourceMappingURL=ngx-dsxlibrary.mjs.map