orbiq-neural-ui-kit 1.0.32 → 1.0.34

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.
@@ -12207,8 +12207,8 @@ class NeuralDataTableComponent {
12207
12207
  ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
12208
12208
  count = input(/* @ts-ignore */
12209
12209
  ...(ngDevMode ? [undefined, { debugName: "count" }] : /* istanbul ignore next */ []));
12210
- infoLink = input('', /* @ts-ignore */
12211
- ...(ngDevMode ? [{ debugName: "infoLink" }] : /* istanbul ignore next */ []));
12210
+ hasInfo = input(false, /* @ts-ignore */
12211
+ ...(ngDevMode ? [{ debugName: "hasInfo" }] : /* istanbul ignore next */ []));
12212
12212
  searchPlaceholder = input('Search', /* @ts-ignore */
12213
12213
  ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
12214
12214
  allColumns = input([], /* @ts-ignore */
@@ -12228,6 +12228,11 @@ class NeuralDataTableComponent {
12228
12228
  onSearch = new EventEmitter();
12229
12229
  onPageChange = new EventEmitter();
12230
12230
  sortChange = new EventEmitter();
12231
+ // New Emitters for Advanced Actions
12232
+ onInfoClick = new EventEmitter();
12233
+ onRefreshClick = new EventEmitter();
12234
+ onViewChange = new EventEmitter();
12235
+ onFilterClick = new EventEmitter();
12231
12236
  cellTemplate;
12232
12237
  isPreferencesOpen = signal(false, /* @ts-ignore */
12233
12238
  ...(ngDevMode ? [{ debugName: "isPreferencesOpen" }] : /* istanbul ignore next */ []));
@@ -12259,37 +12264,55 @@ class NeuralDataTableComponent {
12259
12264
  this.sortChange.emit(key);
12260
12265
  }
12261
12266
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NeuralDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12262
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: NeuralDataTableComponent, isStandalone: true, selector: "neural-data-table", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, infoLink: { classPropertyName: "infoLink", publicName: "infoLink", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, allColumns: { classPropertyName: "allColumns", publicName: "allColumns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: true, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: false, transformFunction: null }, emptyStateTitle: { classPropertyName: "emptyStateTitle", publicName: "emptyStateTitle", isSignal: true, isRequired: false, transformFunction: null }, emptyStateDesc: { classPropertyName: "emptyStateDesc", publicName: "emptyStateDesc", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSearch: "onSearch", onPageChange: "onPageChange", sortChange: "sortChange" }, queries: [{ propertyName: "cellTemplate", first: true, predicate: ["cellTemplate"], descendants: true }], ngImport: i0, template: `
12267
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: NeuralDataTableComponent, isStandalone: true, selector: "neural-data-table", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, hasInfo: { classPropertyName: "hasInfo", publicName: "hasInfo", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, allColumns: { classPropertyName: "allColumns", publicName: "allColumns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: true, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: false, transformFunction: null }, emptyStateTitle: { classPropertyName: "emptyStateTitle", publicName: "emptyStateTitle", isSignal: true, isRequired: false, transformFunction: null }, emptyStateDesc: { classPropertyName: "emptyStateDesc", publicName: "emptyStateDesc", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSearch: "onSearch", onPageChange: "onPageChange", sortChange: "sortChange", onInfoClick: "onInfoClick", onRefreshClick: "onRefreshClick", onViewChange: "onViewChange", onFilterClick: "onFilterClick" }, queries: [{ propertyName: "cellTemplate", first: true, predicate: ["cellTemplate"], descendants: true }], ngImport: i0, template: `
12263
12268
  <div class="flex flex-col w-full h-full bg-white rounded-md border border-outline-gray-2 shadow-sm overflow-hidden">
12264
12269
 
12265
12270
  <!-- Top Header Area -->
12266
- <div class="flex items-start justify-between px-4 py-4 border-b border-outline-gray-2 bg-surface-base">
12267
- <div class="flex flex-col gap-1">
12268
- <div class="flex items-center gap-2">
12269
- <h2 class="text-[17px] font-semibold text-ink-gray-9">{{ title() }}</h2>
12270
- @if (count() !== undefined) {
12271
- <span class="text-[15px] font-medium text-ink-gray-5">({{ count() }})</span>
12272
- }
12273
- @if (infoLink()) {
12274
- <a [href]="infoLink()" class="text-xs font-medium text-blue-600 hover:underline ml-2 cursor-pointer">Información</a>
12275
- }
12276
- </div>
12277
- @if (subtitle()) {
12278
- <p class="text-[13px] text-ink-gray-6">{{ subtitle() }}</p>
12271
+ <div class="flex items-center justify-between px-4 py-2.5 border-b border-outline-gray-2 bg-white">
12272
+ <!-- Left: Title & Info -->
12273
+ <div class="flex items-center gap-3">
12274
+ <h2 class="text-[14px] font-semibold text-ink-gray-9">{{ title() }}</h2>
12275
+ @if (count() !== undefined) {
12276
+ <span class="text-[12px] font-medium text-ink-gray-5 px-1.5 py-0.5 rounded-full bg-surface-gray-2">{{ count() }}</span>
12277
+ }
12278
+ @if (hasInfo()) {
12279
+ <button class="text-[12px] font-medium text-blue-600 hover:underline cursor-pointer flex items-center gap-1" (click)="onInfoClick.emit()">
12280
+ Información
12281
+ </button>
12279
12282
  }
12280
12283
  </div>
12281
12284
 
12282
- <div class="flex items-center gap-2">
12285
+ <!-- Right: Actions Toolbar -->
12286
+ <div class="flex items-center gap-1.5">
12287
+
12288
+ <!-- Built-in Actions Group (Clean, no background) -->
12289
+ <div class="flex items-center gap-0.5">
12290
+ <neural-button variant="ghost" size="sm" icon="lucide-list" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" (click)="onViewChange.emit('report')">Vista</neural-button>
12291
+ <neural-button variant="ghost" size="sm" icon="lucide-filter" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" (click)="onFilterClick.emit()">Filtrar</neural-button>
12292
+ <neural-button variant="ghost" size="sm" icon="lucide-arrow-up-down" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" title="Orden">Orden</neural-button>
12293
+ </div>
12294
+
12295
+ <div class="w-px h-4 bg-outline-gray-2 mx-1"></div>
12296
+
12297
+ <div class="flex items-center gap-0.5">
12298
+ <button class="flex items-center justify-center size-7 rounded-md hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors" title="Actualizar" (click)="onRefreshClick.emit()">
12299
+ <i class="lucide-refresh-cw size-3.5" style="stroke-width: 1.5px;"></i>
12300
+ </button>
12301
+ <button class="flex items-center justify-center size-7 rounded-md hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors" title="Más acciones">
12302
+ <i class="lucide-more-horizontal size-3.5" style="stroke-width: 1.5px;"></i>
12303
+ </button>
12304
+ </div>
12305
+
12306
+ <div class="w-px h-5 bg-outline-gray-2 mx-1"></div>
12307
+
12283
12308
  <!-- External Actions (Refresh, Create, etc) -->
12284
12309
  <ng-content select="[header-actions]"></ng-content>
12285
12310
  </div>
12286
12311
  </div>
12287
12312
 
12288
- <!-- Toolbar Area -->
12289
- <div class="flex items-center justify-between px-4 py-2 border-b border-outline-gray-1 bg-surface-gray-1 min-h-[52px]">
12290
-
12291
- <!-- Search -->
12292
- <div class="w-72">
12313
+ <!-- Search Area -->
12314
+ <div class="flex items-center justify-between px-4 py-2 border-b border-outline-gray-1 bg-surface-base">
12315
+ <div class="w-full max-w-sm">
12293
12316
  <neural-text-input
12294
12317
  [placeholder]="searchPlaceholder()"
12295
12318
  icon="lucide-search"
@@ -12297,69 +12320,11 @@ class NeuralDataTableComponent {
12297
12320
  (valueModelChange)="onSearch.emit($event)"
12298
12321
  ></neural-text-input>
12299
12322
  </div>
12300
-
12301
- <!-- Pagination & Settings -->
12302
- <div class="flex items-center gap-3">
12303
- <div class="flex items-center gap-1 text-sm text-ink-gray-7 font-medium">
12304
- <button class="p-1 hover:bg-surface-gray-3 rounded text-ink-gray-4 hover:text-ink-gray-8 disabled:opacity-50" [disabled]="page() === 1" (click)="onPageChange.emit(page() - 1)">
12305
- <i class="lucide-chevron-left size-4"></i>
12306
- </button>
12307
- <span class="px-2">{{ page() }}</span>
12308
- <button class="p-1 hover:bg-surface-gray-3 rounded text-ink-gray-4 hover:text-ink-gray-8 disabled:opacity-50" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(page() + 1)">
12309
- <i class="lucide-chevron-right size-4"></i>
12310
- </button>
12311
- </div>
12312
-
12313
- <div class="w-px h-4 bg-outline-gray-3 mx-1"></div>
12314
-
12315
- <!-- Preferences Dialog Trigger -->
12316
- <button class="p-1.5 hover:bg-surface-gray-3 rounded text-ink-gray-5 hover:text-ink-gray-8 transition-colors" (click)="isPreferencesOpen.set(true)">
12317
- <i class="lucide-settings size-4"></i>
12318
- </button>
12319
-
12320
- <!-- Preferences Dialog Content -->
12321
- <neural-dialog [openModel]="isPreferencesOpen()" (openModelChange)="isPreferencesOpen.set($event)" [hasTitleSlot]="true" [hasActionsSlot]="true" size="md">
12322
- <div title>
12323
- <h3 class="text-lg font-semibold text-ink-gray-9">Preferencias</h3>
12324
- </div>
12325
-
12326
- <div class="flex flex-col gap-6 py-2">
12327
- <div class="flex items-start gap-4">
12328
- <neural-checkbox [checkedModel]="wrapLines()" (checkedModelChange)="wrapLines.set($event)"></neural-checkbox>
12329
- <div class="flex flex-col">
12330
- <span class="text-sm font-medium text-ink-gray-9">Ajustar líneas</span>
12331
- <span class="text-xs text-ink-gray-5">Seleccione la casilla de verificación para ajustar todas las líneas.</span>
12332
- </div>
12333
- </div>
12334
-
12335
- <div class="border-t border-outline-gray-2 pt-4">
12336
- <div class="flex flex-col mb-3">
12337
- <span class="text-sm font-semibold text-ink-gray-9">Seleccionar columnas visibles</span>
12338
- <span class="text-xs text-ink-gray-5">Personalice la visibilidad y el orden de las columnas.</span>
12339
- </div>
12340
-
12341
- <div class="flex flex-col gap-0 border border-outline-gray-2 rounded-md bg-white overflow-hidden">
12342
- @for (col of allColumns(); track col.key) {
12343
- <div class="flex items-center justify-between p-3 border-b border-outline-gray-1 last:border-0 hover:bg-surface-gray-1">
12344
- <div class="flex items-center gap-2">
12345
- <i class="lucide-grip-vertical size-4 text-ink-gray-4 cursor-grab"></i>
12346
- <span class="text-sm text-ink-gray-8 font-medium">{{ col.label }}</span>
12347
- </div>
12348
- <neural-switch [valueModel]="isColumnVisible(col.key)" (valueModelChange)="toggleColumnVisibility(col.key, $event)"></neural-switch>
12349
- </div>
12350
- }
12351
- </div>
12352
- </div>
12353
- </div>
12354
-
12355
- <div actions>
12356
- <div class="flex items-center justify-end gap-2 w-full">
12357
- <neural-button variant="ghost" (click)="isPreferencesOpen.set(false)">Cancelar</neural-button>
12358
- <neural-button variant="solid" theme="blue" (click)="applyPreferences()">Continuar</neural-button>
12359
- </div>
12360
- </div>
12361
- </neural-dialog>
12362
- </div>
12323
+
12324
+ <!-- Preferences / Columns Dialog Trigger (Moved to search row) -->
12325
+ <button class="flex items-center justify-center size-7 rounded-md border border-outline-gray-2 bg-white hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors shadow-sm" (click)="isPreferencesOpen.set(true)" title="Configurar columnas">
12326
+ <i class="lucide-settings size-3.5" style="stroke-width: 1.5px;"></i>
12327
+ </button>
12363
12328
  </div>
12364
12329
 
12365
12330
  <!-- Table Content -->
@@ -12369,7 +12334,7 @@ class NeuralDataTableComponent {
12369
12334
  <tr class="border-b border-outline-gray-2 bg-white">
12370
12335
  @for (col of visibleColumns(); track col.key) {
12371
12336
  <th
12372
- class="px-4 py-3 text-[13px] font-semibold text-ink-gray-7 truncate border-r border-outline-gray-2 last:border-r-0"
12337
+ class="px-4 py-2.5 text-[12px] font-semibold text-ink-gray-6 uppercase tracking-wider truncate border-r border-outline-gray-2 last:border-r-0"
12373
12338
  [style.width]="col.width || 'auto'"
12374
12339
  >
12375
12340
  <div class="flex items-center justify-between group cursor-pointer hover:text-ink-gray-9" (click)="col.sortable ? onSort(col.key) : null">
@@ -12388,7 +12353,7 @@ class NeuralDataTableComponent {
12388
12353
  <tr class="border-b border-outline-gray-1 hover:bg-surface-gray-1 transition-colors group">
12389
12354
  @for (col of visibleColumns(); track col.key) {
12390
12355
  <td
12391
- class="px-4 py-3 text-[13.5px] text-ink-gray-9"
12356
+ class="px-4 py-2.5 text-[12px] font-medium text-ink-gray-9"
12392
12357
  [class.truncate]="!wrapLines()"
12393
12358
  [class.whitespace-nowrap]="!wrapLines()"
12394
12359
  >
@@ -12413,6 +12378,78 @@ class NeuralDataTableComponent {
12413
12378
  </tbody>
12414
12379
  </table>
12415
12380
  </div>
12381
+
12382
+ <!-- Footer / Pagination Area -->
12383
+ <div class="flex items-center justify-between px-4 py-2 border-t border-outline-gray-2 bg-white">
12384
+ <!-- Left Footer -->
12385
+ <div class="text-[12px] text-ink-gray-5">
12386
+ <!-- Espacio para contadores de selección -->
12387
+ </div>
12388
+
12389
+ <!-- Right Footer: Pagination & Settings -->
12390
+ <div class="flex items-center gap-4">
12391
+ <div class="flex items-center gap-0.5 text-[12px] text-ink-gray-7 font-medium">
12392
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() === 1" (click)="onPageChange.emit(1)" title="Primera página">
12393
+ <i class="lucide-chevrons-left size-3.5" style="stroke-width: 1.5px;"></i>
12394
+ </button>
12395
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() === 1" (click)="onPageChange.emit(page() - 1)" title="Anterior">
12396
+ <i class="lucide-chevron-left size-3.5" style="stroke-width: 1.5px;"></i>
12397
+ </button>
12398
+
12399
+ <span class="px-2 min-w-[70px] text-center">{{ page() }} <span class="text-ink-gray-4 mx-1">/</span> {{ totalPages() }}</span>
12400
+
12401
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(page() + 1)" title="Siguiente">
12402
+ <i class="lucide-chevron-right size-3.5" style="stroke-width: 1.5px;"></i>
12403
+ </button>
12404
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(totalPages())" title="Última página">
12405
+ <i class="lucide-chevrons-right size-3.5" style="stroke-width: 1.5px;"></i>
12406
+ </button>
12407
+ </div>
12408
+ </div>
12409
+ </div>
12410
+
12411
+ <!-- Dialog moved outside of the main flex flows -->
12412
+ <neural-dialog [openModel]="isPreferencesOpen()" (openModelChange)="isPreferencesOpen.set($event)" [hasTitleSlot]="true" [hasActionsSlot]="true" size="md">
12413
+ <div title>
12414
+ <h3 class="text-lg font-semibold text-ink-gray-9">Preferencias</h3>
12415
+ </div>
12416
+
12417
+ <div class="flex flex-col gap-6 py-2">
12418
+ <div class="flex items-start gap-4">
12419
+ <neural-checkbox [checkedModel]="wrapLines()" (checkedModelChange)="wrapLines.set($event)"></neural-checkbox>
12420
+ <div class="flex flex-col">
12421
+ <span class="text-sm font-medium text-ink-gray-9">Ajustar líneas</span>
12422
+ <span class="text-xs text-ink-gray-5">Seleccione la casilla de verificación para ajustar todas las líneas.</span>
12423
+ </div>
12424
+ </div>
12425
+
12426
+ <div class="border-t border-outline-gray-2 pt-4">
12427
+ <div class="flex flex-col mb-3">
12428
+ <span class="text-sm font-semibold text-ink-gray-9">Seleccionar columnas visibles</span>
12429
+ <span class="text-xs text-ink-gray-5">Personalice la visibilidad y el orden de las columnas.</span>
12430
+ </div>
12431
+
12432
+ <div class="flex flex-col gap-0 border border-outline-gray-2 rounded-md bg-white overflow-hidden">
12433
+ @for (col of allColumns(); track col.key) {
12434
+ <div class="flex items-center justify-between p-3 border-b border-outline-gray-1 last:border-0 hover:bg-surface-gray-1">
12435
+ <div class="flex items-center gap-2">
12436
+ <i class="lucide-grip-vertical size-4 text-ink-gray-4 cursor-grab"></i>
12437
+ <span class="text-sm text-ink-gray-8 font-medium">{{ col.label }}</span>
12438
+ </div>
12439
+ <neural-switch [valueModel]="isColumnVisible(col.key)" (valueModelChange)="toggleColumnVisibility(col.key, $event)"></neural-switch>
12440
+ </div>
12441
+ }
12442
+ </div>
12443
+ </div>
12444
+ </div>
12445
+
12446
+ <div actions>
12447
+ <div class="flex items-center justify-end gap-2 w-full">
12448
+ <neural-button variant="ghost" (click)="isPreferencesOpen.set(false)">Cancelar</neural-button>
12449
+ <neural-button variant="solid" theme="blue" (click)="applyPreferences()">Continuar</neural-button>
12450
+ </div>
12451
+ </div>
12452
+ </neural-dialog>
12416
12453
  </div>
12417
12454
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NeuralButtonComponent, selector: "neural-button", inputs: ["variant", "theme", "size", "type", "disabled", "loading", "icon", "iconLeft", "iconRight", "iconOnly"], outputs: ["clicked"] }, { kind: "component", type: NeuralTextInputComponent, selector: "neural-text-input", inputs: ["valueModel", "type", "size", "variant", "placeholder", "disabled", "readonly", "required", "label", "description", "error", "id", "debounce", "wrapperClass", "wrapperStyle", "hasLabelSlot", "hasDescriptionSlot", "hasPrefixSlot", "hasSuffixSlot"], outputs: ["valueModelChange", "debounceChange"] }, { kind: "component", type: NeuralDialogComponent, selector: "neural-dialog", inputs: ["openModel", "title", "message", "icon", "size", "position", "paddingTop", "actions", "dismissible", "showCloseButton", "bare", "hasTitleSlot", "hasActionsSlot", "hasDefaultSlot"], outputs: ["openModelChange"] }, { kind: "component", type: NeuralSwitchComponent, selector: "neural-switch", inputs: ["valueModel", "size", "padded", "disabled", "required", "controlPosition", "icon", "label", "description", "error", "id", "hasLabelSlot", "hasDescriptionSlot"], outputs: ["valueModelChange"] }, { kind: "component", type: NeuralCheckboxComponent, selector: "neural-checkbox", inputs: ["checkedModel", "size", "padded", "indeterminate", "disabled", "required", "label", "description", "error", "id", "hasLabelSlot", "hasDescriptionSlot"], outputs: ["checkedModelChange"] }] });
12418
12455
  }
@@ -12433,33 +12470,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12433
12470
  <div class="flex flex-col w-full h-full bg-white rounded-md border border-outline-gray-2 shadow-sm overflow-hidden">
12434
12471
 
12435
12472
  <!-- Top Header Area -->
12436
- <div class="flex items-start justify-between px-4 py-4 border-b border-outline-gray-2 bg-surface-base">
12437
- <div class="flex flex-col gap-1">
12438
- <div class="flex items-center gap-2">
12439
- <h2 class="text-[17px] font-semibold text-ink-gray-9">{{ title() }}</h2>
12440
- @if (count() !== undefined) {
12441
- <span class="text-[15px] font-medium text-ink-gray-5">({{ count() }})</span>
12442
- }
12443
- @if (infoLink()) {
12444
- <a [href]="infoLink()" class="text-xs font-medium text-blue-600 hover:underline ml-2 cursor-pointer">Información</a>
12445
- }
12446
- </div>
12447
- @if (subtitle()) {
12448
- <p class="text-[13px] text-ink-gray-6">{{ subtitle() }}</p>
12473
+ <div class="flex items-center justify-between px-4 py-2.5 border-b border-outline-gray-2 bg-white">
12474
+ <!-- Left: Title & Info -->
12475
+ <div class="flex items-center gap-3">
12476
+ <h2 class="text-[14px] font-semibold text-ink-gray-9">{{ title() }}</h2>
12477
+ @if (count() !== undefined) {
12478
+ <span class="text-[12px] font-medium text-ink-gray-5 px-1.5 py-0.5 rounded-full bg-surface-gray-2">{{ count() }}</span>
12479
+ }
12480
+ @if (hasInfo()) {
12481
+ <button class="text-[12px] font-medium text-blue-600 hover:underline cursor-pointer flex items-center gap-1" (click)="onInfoClick.emit()">
12482
+ Información
12483
+ </button>
12449
12484
  }
12450
12485
  </div>
12451
12486
 
12452
- <div class="flex items-center gap-2">
12487
+ <!-- Right: Actions Toolbar -->
12488
+ <div class="flex items-center gap-1.5">
12489
+
12490
+ <!-- Built-in Actions Group (Clean, no background) -->
12491
+ <div class="flex items-center gap-0.5">
12492
+ <neural-button variant="ghost" size="sm" icon="lucide-list" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" (click)="onViewChange.emit('report')">Vista</neural-button>
12493
+ <neural-button variant="ghost" size="sm" icon="lucide-filter" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" (click)="onFilterClick.emit()">Filtrar</neural-button>
12494
+ <neural-button variant="ghost" size="sm" icon="lucide-arrow-up-down" [iconLeft]="true" class="!px-1.5 !text-[12px] !font-medium !text-ink-gray-6 hover:!text-ink-gray-9" title="Orden">Orden</neural-button>
12495
+ </div>
12496
+
12497
+ <div class="w-px h-4 bg-outline-gray-2 mx-1"></div>
12498
+
12499
+ <div class="flex items-center gap-0.5">
12500
+ <button class="flex items-center justify-center size-7 rounded-md hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors" title="Actualizar" (click)="onRefreshClick.emit()">
12501
+ <i class="lucide-refresh-cw size-3.5" style="stroke-width: 1.5px;"></i>
12502
+ </button>
12503
+ <button class="flex items-center justify-center size-7 rounded-md hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors" title="Más acciones">
12504
+ <i class="lucide-more-horizontal size-3.5" style="stroke-width: 1.5px;"></i>
12505
+ </button>
12506
+ </div>
12507
+
12508
+ <div class="w-px h-5 bg-outline-gray-2 mx-1"></div>
12509
+
12453
12510
  <!-- External Actions (Refresh, Create, etc) -->
12454
12511
  <ng-content select="[header-actions]"></ng-content>
12455
12512
  </div>
12456
12513
  </div>
12457
12514
 
12458
- <!-- Toolbar Area -->
12459
- <div class="flex items-center justify-between px-4 py-2 border-b border-outline-gray-1 bg-surface-gray-1 min-h-[52px]">
12460
-
12461
- <!-- Search -->
12462
- <div class="w-72">
12515
+ <!-- Search Area -->
12516
+ <div class="flex items-center justify-between px-4 py-2 border-b border-outline-gray-1 bg-surface-base">
12517
+ <div class="w-full max-w-sm">
12463
12518
  <neural-text-input
12464
12519
  [placeholder]="searchPlaceholder()"
12465
12520
  icon="lucide-search"
@@ -12467,69 +12522,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12467
12522
  (valueModelChange)="onSearch.emit($event)"
12468
12523
  ></neural-text-input>
12469
12524
  </div>
12470
-
12471
- <!-- Pagination & Settings -->
12472
- <div class="flex items-center gap-3">
12473
- <div class="flex items-center gap-1 text-sm text-ink-gray-7 font-medium">
12474
- <button class="p-1 hover:bg-surface-gray-3 rounded text-ink-gray-4 hover:text-ink-gray-8 disabled:opacity-50" [disabled]="page() === 1" (click)="onPageChange.emit(page() - 1)">
12475
- <i class="lucide-chevron-left size-4"></i>
12476
- </button>
12477
- <span class="px-2">{{ page() }}</span>
12478
- <button class="p-1 hover:bg-surface-gray-3 rounded text-ink-gray-4 hover:text-ink-gray-8 disabled:opacity-50" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(page() + 1)">
12479
- <i class="lucide-chevron-right size-4"></i>
12480
- </button>
12481
- </div>
12482
-
12483
- <div class="w-px h-4 bg-outline-gray-3 mx-1"></div>
12484
-
12485
- <!-- Preferences Dialog Trigger -->
12486
- <button class="p-1.5 hover:bg-surface-gray-3 rounded text-ink-gray-5 hover:text-ink-gray-8 transition-colors" (click)="isPreferencesOpen.set(true)">
12487
- <i class="lucide-settings size-4"></i>
12488
- </button>
12489
-
12490
- <!-- Preferences Dialog Content -->
12491
- <neural-dialog [openModel]="isPreferencesOpen()" (openModelChange)="isPreferencesOpen.set($event)" [hasTitleSlot]="true" [hasActionsSlot]="true" size="md">
12492
- <div title>
12493
- <h3 class="text-lg font-semibold text-ink-gray-9">Preferencias</h3>
12494
- </div>
12495
-
12496
- <div class="flex flex-col gap-6 py-2">
12497
- <div class="flex items-start gap-4">
12498
- <neural-checkbox [checkedModel]="wrapLines()" (checkedModelChange)="wrapLines.set($event)"></neural-checkbox>
12499
- <div class="flex flex-col">
12500
- <span class="text-sm font-medium text-ink-gray-9">Ajustar líneas</span>
12501
- <span class="text-xs text-ink-gray-5">Seleccione la casilla de verificación para ajustar todas las líneas.</span>
12502
- </div>
12503
- </div>
12504
-
12505
- <div class="border-t border-outline-gray-2 pt-4">
12506
- <div class="flex flex-col mb-3">
12507
- <span class="text-sm font-semibold text-ink-gray-9">Seleccionar columnas visibles</span>
12508
- <span class="text-xs text-ink-gray-5">Personalice la visibilidad y el orden de las columnas.</span>
12509
- </div>
12510
-
12511
- <div class="flex flex-col gap-0 border border-outline-gray-2 rounded-md bg-white overflow-hidden">
12512
- @for (col of allColumns(); track col.key) {
12513
- <div class="flex items-center justify-between p-3 border-b border-outline-gray-1 last:border-0 hover:bg-surface-gray-1">
12514
- <div class="flex items-center gap-2">
12515
- <i class="lucide-grip-vertical size-4 text-ink-gray-4 cursor-grab"></i>
12516
- <span class="text-sm text-ink-gray-8 font-medium">{{ col.label }}</span>
12517
- </div>
12518
- <neural-switch [valueModel]="isColumnVisible(col.key)" (valueModelChange)="toggleColumnVisibility(col.key, $event)"></neural-switch>
12519
- </div>
12520
- }
12521
- </div>
12522
- </div>
12523
- </div>
12524
-
12525
- <div actions>
12526
- <div class="flex items-center justify-end gap-2 w-full">
12527
- <neural-button variant="ghost" (click)="isPreferencesOpen.set(false)">Cancelar</neural-button>
12528
- <neural-button variant="solid" theme="blue" (click)="applyPreferences()">Continuar</neural-button>
12529
- </div>
12530
- </div>
12531
- </neural-dialog>
12532
- </div>
12525
+
12526
+ <!-- Preferences / Columns Dialog Trigger (Moved to search row) -->
12527
+ <button class="flex items-center justify-center size-7 rounded-md border border-outline-gray-2 bg-white hover:bg-surface-gray-1 text-ink-gray-6 hover:text-ink-gray-9 transition-colors shadow-sm" (click)="isPreferencesOpen.set(true)" title="Configurar columnas">
12528
+ <i class="lucide-settings size-3.5" style="stroke-width: 1.5px;"></i>
12529
+ </button>
12533
12530
  </div>
12534
12531
 
12535
12532
  <!-- Table Content -->
@@ -12539,7 +12536,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12539
12536
  <tr class="border-b border-outline-gray-2 bg-white">
12540
12537
  @for (col of visibleColumns(); track col.key) {
12541
12538
  <th
12542
- class="px-4 py-3 text-[13px] font-semibold text-ink-gray-7 truncate border-r border-outline-gray-2 last:border-r-0"
12539
+ class="px-4 py-2.5 text-[12px] font-semibold text-ink-gray-6 uppercase tracking-wider truncate border-r border-outline-gray-2 last:border-r-0"
12543
12540
  [style.width]="col.width || 'auto'"
12544
12541
  >
12545
12542
  <div class="flex items-center justify-between group cursor-pointer hover:text-ink-gray-9" (click)="col.sortable ? onSort(col.key) : null">
@@ -12558,7 +12555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12558
12555
  <tr class="border-b border-outline-gray-1 hover:bg-surface-gray-1 transition-colors group">
12559
12556
  @for (col of visibleColumns(); track col.key) {
12560
12557
  <td
12561
- class="px-4 py-3 text-[13.5px] text-ink-gray-9"
12558
+ class="px-4 py-2.5 text-[12px] font-medium text-ink-gray-9"
12562
12559
  [class.truncate]="!wrapLines()"
12563
12560
  [class.whitespace-nowrap]="!wrapLines()"
12564
12561
  >
@@ -12583,15 +12580,95 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
12583
12580
  </tbody>
12584
12581
  </table>
12585
12582
  </div>
12583
+
12584
+ <!-- Footer / Pagination Area -->
12585
+ <div class="flex items-center justify-between px-4 py-2 border-t border-outline-gray-2 bg-white">
12586
+ <!-- Left Footer -->
12587
+ <div class="text-[12px] text-ink-gray-5">
12588
+ <!-- Espacio para contadores de selección -->
12589
+ </div>
12590
+
12591
+ <!-- Right Footer: Pagination & Settings -->
12592
+ <div class="flex items-center gap-4">
12593
+ <div class="flex items-center gap-0.5 text-[12px] text-ink-gray-7 font-medium">
12594
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() === 1" (click)="onPageChange.emit(1)" title="Primera página">
12595
+ <i class="lucide-chevrons-left size-3.5" style="stroke-width: 1.5px;"></i>
12596
+ </button>
12597
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() === 1" (click)="onPageChange.emit(page() - 1)" title="Anterior">
12598
+ <i class="lucide-chevron-left size-3.5" style="stroke-width: 1.5px;"></i>
12599
+ </button>
12600
+
12601
+ <span class="px-2 min-w-[70px] text-center">{{ page() }} <span class="text-ink-gray-4 mx-1">/</span> {{ totalPages() }}</span>
12602
+
12603
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(page() + 1)" title="Siguiente">
12604
+ <i class="lucide-chevron-right size-3.5" style="stroke-width: 1.5px;"></i>
12605
+ </button>
12606
+ <button class="p-1 hover:bg-surface-gray-2 rounded text-ink-gray-5 hover:text-ink-gray-8 disabled:opacity-30 disabled:hover:bg-transparent" [disabled]="page() >= totalPages()" (click)="onPageChange.emit(totalPages())" title="Última página">
12607
+ <i class="lucide-chevrons-right size-3.5" style="stroke-width: 1.5px;"></i>
12608
+ </button>
12609
+ </div>
12610
+ </div>
12611
+ </div>
12612
+
12613
+ <!-- Dialog moved outside of the main flex flows -->
12614
+ <neural-dialog [openModel]="isPreferencesOpen()" (openModelChange)="isPreferencesOpen.set($event)" [hasTitleSlot]="true" [hasActionsSlot]="true" size="md">
12615
+ <div title>
12616
+ <h3 class="text-lg font-semibold text-ink-gray-9">Preferencias</h3>
12617
+ </div>
12618
+
12619
+ <div class="flex flex-col gap-6 py-2">
12620
+ <div class="flex items-start gap-4">
12621
+ <neural-checkbox [checkedModel]="wrapLines()" (checkedModelChange)="wrapLines.set($event)"></neural-checkbox>
12622
+ <div class="flex flex-col">
12623
+ <span class="text-sm font-medium text-ink-gray-9">Ajustar líneas</span>
12624
+ <span class="text-xs text-ink-gray-5">Seleccione la casilla de verificación para ajustar todas las líneas.</span>
12625
+ </div>
12626
+ </div>
12627
+
12628
+ <div class="border-t border-outline-gray-2 pt-4">
12629
+ <div class="flex flex-col mb-3">
12630
+ <span class="text-sm font-semibold text-ink-gray-9">Seleccionar columnas visibles</span>
12631
+ <span class="text-xs text-ink-gray-5">Personalice la visibilidad y el orden de las columnas.</span>
12632
+ </div>
12633
+
12634
+ <div class="flex flex-col gap-0 border border-outline-gray-2 rounded-md bg-white overflow-hidden">
12635
+ @for (col of allColumns(); track col.key) {
12636
+ <div class="flex items-center justify-between p-3 border-b border-outline-gray-1 last:border-0 hover:bg-surface-gray-1">
12637
+ <div class="flex items-center gap-2">
12638
+ <i class="lucide-grip-vertical size-4 text-ink-gray-4 cursor-grab"></i>
12639
+ <span class="text-sm text-ink-gray-8 font-medium">{{ col.label }}</span>
12640
+ </div>
12641
+ <neural-switch [valueModel]="isColumnVisible(col.key)" (valueModelChange)="toggleColumnVisibility(col.key, $event)"></neural-switch>
12642
+ </div>
12643
+ }
12644
+ </div>
12645
+ </div>
12646
+ </div>
12647
+
12648
+ <div actions>
12649
+ <div class="flex items-center justify-end gap-2 w-full">
12650
+ <neural-button variant="ghost" (click)="isPreferencesOpen.set(false)">Cancelar</neural-button>
12651
+ <neural-button variant="solid" theme="blue" (click)="applyPreferences()">Continuar</neural-button>
12652
+ </div>
12653
+ </div>
12654
+ </neural-dialog>
12586
12655
  </div>
12587
12656
  `
12588
12657
  }]
12589
- }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], infoLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoLink", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], allColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "allColumns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: true }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: false }] }], emptyStateTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTitle", required: false }] }], emptyStateDesc: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateDesc", required: false }] }], onSearch: [{
12658
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], hasInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasInfo", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], allColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "allColumns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: true }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: false }] }], emptyStateTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTitle", required: false }] }], emptyStateDesc: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateDesc", required: false }] }], onSearch: [{
12590
12659
  type: Output
12591
12660
  }], onPageChange: [{
12592
12661
  type: Output
12593
12662
  }], sortChange: [{
12594
12663
  type: Output
12664
+ }], onInfoClick: [{
12665
+ type: Output
12666
+ }], onRefreshClick: [{
12667
+ type: Output
12668
+ }], onViewChange: [{
12669
+ type: Output
12670
+ }], onFilterClick: [{
12671
+ type: Output
12595
12672
  }], cellTemplate: [{
12596
12673
  type: ContentChild,
12597
12674
  args: ['cellTemplate']