@kaufmann-lab/ui 0.1.21 → 0.1.22

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,5 +1,5 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { AfterContentInit, TemplateRef, Signal, ElementRef, AfterViewInit } from '@angular/core';
2
+ import { AfterContentInit, TemplateRef, Signal, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
3
3
  import { ControlValueAccessor } from '@angular/forms';
4
4
  import { SafeResourceUrl } from '@angular/platform-browser';
5
5
 
@@ -179,10 +179,10 @@ declare class AdminBadge {
179
179
  declare class Button {
180
180
  readonly variant: _angular_core.InputSignal<"primary" | "secondary" | "ghost" | "outline" | "danger" | "surface">;
181
181
  readonly size: _angular_core.InputSignal<"sm" | "md" | "lg">;
182
- readonly shape: _angular_core.InputSignal<"circle" | "rect">;
182
+ readonly shape: _angular_core.InputSignal<"rect" | "circle">;
183
183
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
184
184
  /** Igual al default nativo: hace submit dentro de un `<form>`. */
185
- readonly type: _angular_core.InputSignal<"button" | "reset" | "submit">;
185
+ readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
186
186
  /** Ícono líder, renderizado con `kf-icon` antes del label proyectado. */
187
187
  readonly icon: _angular_core.InputSignal<IconName | undefined>;
188
188
  /** Estira el botón a todo el ancho de su contenedor. */
@@ -205,7 +205,7 @@ declare class Button {
205
205
  readonly ariaPressed: _angular_core.InputSignal<boolean | undefined>;
206
206
  /** Tipo de elemento emergente que abre el botón (ej. `'dialog'` para un
207
207
  * panel de filtros, `'listbox'`) — mismo motivo de reenvío manual. */
208
- readonly ariaHaspopup: _angular_core.InputSignal<"dialog" | "menu" | "listbox" | "true" | undefined>;
208
+ readonly ariaHaspopup: _angular_core.InputSignal<"menu" | "dialog" | "listbox" | "true" | undefined>;
209
209
  private readonly nativeButton;
210
210
  /** Enfoca el `<button>` interno (mismas opciones que `HTMLElement.focus`). */
211
211
  focus(options?: FocusOptions): void;
@@ -218,6 +218,8 @@ declare class Button {
218
218
  }
219
219
 
220
220
  type AlertTone = 'info' | 'ok' | 'warn' | 'error';
221
+ /** Forma del aviso: `card` (default, con borde y esquinas) o `bar` (franja compacta de ancho completo). */
222
+ type AlertVariant = 'card' | 'bar';
221
223
  /**
222
224
  * Banner contextual que vive dentro del flujo: validaciones, avisos de
223
225
  * vencimiento, confirmaciones. Persiste hasta que se descarta o hasta que la
@@ -229,9 +231,21 @@ type AlertTone = 'info' | 'ok' | 'warn' | 'error';
229
231
  *
230
232
  * <kf-alert tone="warn" title="SOAT por vencer">Vence el 15/08.</kf-alert>
231
233
  * <kf-alert tone="ok" [(open)]="saved" dismissible>Pago registrado.</kf-alert>
234
+ *
235
+ * `variant="bar"` es una franja compacta de ancho completo, sin tarjeta: sin
236
+ * esquinas ni bordes laterales (solo la línea superior e inferior del tono),
237
+ * ícono, título y mensaje en una sola línea que envuelve si no entra. Mismos
238
+ * tonos y mismo `role` (`alert` para `error`/`warn`, `status` para el resto)
239
+ * que la variante `card`. Pensada para el borde de una página o de un panel
240
+ * (ej. "Estás viendo datos de otro cliente"), donde una tarjeta con margen
241
+ * sobra.
242
+ *
243
+ * <kf-alert variant="bar" tone="warn" title="Modo suplantación">Viendo como Ana Pérez.</kf-alert>
232
244
  */
233
245
  declare class Alert {
234
246
  readonly tone: _angular_core.InputSignal<AlertTone>;
247
+ /** `card` (default) o `bar` (franja compacta de ancho completo). */
248
+ readonly variant: _angular_core.InputSignal<AlertVariant>;
235
249
  /** Línea en negrita arriba del mensaje. Vacío deja solo el contenido proyectado. */
236
250
  readonly title: _angular_core.InputSignal<string>;
237
251
  readonly dismissible: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -241,10 +255,10 @@ declare class Alert {
241
255
  * `alert` interrumpe al lector de pantalla; se reserva para error/warn.
242
256
  * Los avisos informativos se anuncian sin cortar lo que se esté leyendo.
243
257
  */
244
- protected readonly ariaRole: _angular_core.Signal<"status" | "alert">;
258
+ protected readonly ariaRole: _angular_core.Signal<"alert" | "status">;
245
259
  protected readonly toneIcon: _angular_core.Signal<IconName>;
246
260
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Alert, never>;
247
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Alert, "kf-alert", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["*"], true, never>;
261
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Alert, "kf-alert", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["*"], true, never>;
248
262
  }
249
263
 
250
264
  type AlertRowTone = 'warn' | 'error';
@@ -313,7 +327,7 @@ declare class Avatar {
313
327
  * <kf-badge tone="warn" dot truncate [title]="q.statusLabel">{{ q.statusLabel }}</kf-badge>
314
328
  */
315
329
  declare class Badge {
316
- readonly tone: _angular_core.InputSignal<"error" | "info" | "neutral" | "ok" | "warn" | "service">;
330
+ readonly tone: _angular_core.InputSignal<"info" | "neutral" | "ok" | "warn" | "error" | "service">;
317
331
  readonly variant: _angular_core.InputSignal<"soft" | "glass">;
318
332
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
319
333
  /** Corta el texto con elipsis al ancho del contenedor. Ver JSDoc de la clase. */
@@ -546,14 +560,26 @@ declare class Calendar {
546
560
  * <kf-button>Guardar</kf-button>
547
561
  * </div>
548
562
  * </kf-card>
563
+ *
564
+ * `loading` (default `false`): cubre el cuerpo con un bloque de carga animado
565
+ * sin sacar el contenido del layout (queda invisible y fuera del foco y de
566
+ * lectores de pantalla), así la card conserva exactamente sus dimensiones. Los
567
+ * slots `[kf-card-media]` y `[kf-card-actions]` también se ocultan. Marca el
568
+ * host con `aria-busy="true"`. Para una forma más fiel (líneas separadas) usa
569
+ * `kf-skeleton` dentro de la card, o la card propia del dominio con su
570
+ * `loading` (`kf-stat-card`, `kf-metric-card`).
571
+ *
572
+ * <kf-card [loading]="isLoading()"><h3>{{ title() }}</h3><p>{{ text() }}</p></kf-card>
549
573
  */
550
574
  declare class Card {
551
575
  /** Quita la sombra — para cards anidadas dentro de otra superficie ya elevada. */
552
576
  readonly flush: _angular_core.InputSignalWithTransform<boolean, unknown>;
553
577
  /** Espacio entre los hijos directos del cuerpo. `md` es el default. */
554
578
  readonly gap: _angular_core.InputSignal<"sm" | "md" | "lg" | "xs" | "xl">;
579
+ /** Cubre el cuerpo con un bloque de carga conservando las dimensiones. */
580
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
555
581
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Card, never>;
556
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Card, "kf-card", never, { "flush": { "alias": "flush"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; }, {}, never, ["[kf-card-media]", "*", "[kf-card-actions]"], true, never>;
582
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Card, "kf-card", never, { "flush": { "alias": "flush"; "required": false; "isSignal": true; }; "gap": { "alias": "gap"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, ["[kf-card-media]", "*", "[kf-card-actions]"], true, never>;
557
583
  }
558
584
 
559
585
  /**
@@ -675,7 +701,7 @@ declare class Checkbox implements ControlValueAccessor {
675
701
  * de superficie/borde/texto-muted más cercanos).
676
702
  */
677
703
  declare class Chip {
678
- readonly tone: _angular_core.InputSignal<"error" | "neutral" | "ok" | "warn">;
704
+ readonly tone: _angular_core.InputSignal<"neutral" | "ok" | "warn" | "error">;
679
705
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
680
706
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Chip, never>;
681
707
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Chip, "kf-chip", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -769,99 +795,6 @@ declare class ContentSlot {
769
795
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentSlot, "kf-content-slot", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "compact": { "alias": "compact"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
770
796
  }
771
797
 
772
- /** En qué estado está la sección. */
773
- type ContentStateKind = 'ready' | 'loading' | 'empty' | 'error';
774
- /** Cómo se dibuja `loading`. Default `'skeleton'`. */
775
- type ContentStateLoad = 'skeleton' | 'spinner';
776
- /**
777
- * Wrapper de los cuatro estados que toda sección tiene: cargando, con datos,
778
- * vacía y con error. Un componente en vez de tres `@if` sueltos, porque es
779
- * siempre el mismo slot el que va rotando entre los cuatro.
780
- *
781
- * Con `state="ready"` proyecta el contenido real y desaparece; en los otros
782
- * tres dibuja el placeholder correspondiente y el contenido no se instancia.
783
- * No inventa visuales propios: `loading` usa `kf-skeleton` (o `kf-spinner` con
784
- * `load="spinner"`), y `empty`/`error` usan `kf-empty-state`.
785
- *
786
- * Las acciones (reintentar, crear) van en el slot `actions` — se ignoran
787
- * mientras carga, porque no hay nada que reintentar todavía.
788
- *
789
- * <kf-content-state [state]="state()" title="No pudimos cargar tus vehículos"
790
- * subtitle="Revisá tu conexión e intentá de nuevo.">
791
- * <kf-button actions (click)="retry()">Reintentar</kf-button>
792
- * <kf-data-table [columns]="cols" [rows]="rows()" />
793
- * </kf-content-state>
794
- */
795
- declare class ContentState {
796
- readonly state: _angular_core.InputSignal<ContentStateKind>;
797
- /** Forma del estado de carga: silueta (default) o spinner. */
798
- readonly load: _angular_core.InputSignal<ContentStateLoad>;
799
- /** Título de `empty`/`error`. Ignorado mientras carga. */
800
- readonly title: _angular_core.InputSignal<string>;
801
- readonly subtitle: _angular_core.InputSignal<string>;
802
- /** Texto al lado del spinner cuando `load="spinner"`. */
803
- readonly loadingLabel: _angular_core.InputSignal<string>;
804
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentState, never>;
805
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentState, "kf-content-state", never, { "state": { "alias": "state"; "required": true; "isSignal": true; }; "load": { "alias": "load"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "loadingLabel": { "alias": "loadingLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*", "[actions]"], true, never>;
806
- }
807
-
808
- type ContentViewerType = 'image' | 'video' | 'pdf';
809
- /**
810
- * Visor a pantalla completa para ampliar una pieza de contenido: imagen,
811
- * video o PDF (`type="pdf"`, renderizado por el visor nativo del navegador).
812
- * Mismo mecanismo que `kf-modal` (el `<dialog>` nativo resuelve backdrop,
813
- * atrapado de foco, top-layer y `Escape`), pero sin panel/título/footer:
814
- * el contenido ocupa toda la pantalla sobre un backdrop oscuro.
815
- *
816
- * `src` acepta lo que venga del backend sin que el consumidor tenga que
817
- * normalizarlo primero: una URL (`http(s)://`), un data URI ya armado
818
- * (`data:...`), o base64 crudo (se le antepone el prefijo `data:` según
819
- * `type`, asumiendo JPEG para imagen, MP4 para video y PDF para pdf). Un PDF
820
- * solo acepta contenido local (`blob:`, data URI o base64), nunca una URL remota.
821
- *
822
- * Lo proyectado con el atributo `actions` (p. ej. un botón de descarga) va en
823
- * la barra superior, junto al título.
824
- *
825
- * <kf-content-viewer [(open)]="viewerOpen" [src]="viewerSrc()" alt="Foto del vehículo" />
826
- * <kf-content-viewer [(open)]="viewerOpen" type="video" [src]="viewerSrc()" title="Inspección" />
827
- * <kf-content-viewer [(open)]="viewerOpen" type="pdf" [src]="blobUrl()" title="Contrato">
828
- * <kf-button actions variant="surface" icon="download" (click)="save()">Descargar</kf-button>
829
- * </kf-content-viewer>
830
- */
831
- declare class ContentViewer {
832
- readonly type: _angular_core.InputSignal<ContentViewerType>;
833
- /** URL, data URI, o base64 crudo — ver JSDoc de la clase. */
834
- readonly src: _angular_core.InputSignal<string | null>;
835
- /** Texto alternativo cuando `type="image"`. */
836
- readonly alt: _angular_core.InputSignal<string>;
837
- readonly title: _angular_core.InputSignal<string>;
838
- /** Visibilidad, two-way: `[(open)]="viewerOpen"`. */
839
- readonly open: _angular_core.ModelSignal<boolean>;
840
- /** Permite cerrar con el botón, `Escape` o clic en el backdrop. */
841
- readonly dismissible: _angular_core.InputSignalWithTransform<boolean, unknown>;
842
- protected readonly titleId: string;
843
- /** Detecta si `src` ya es una URL o un data URI armado; si no, asume
844
- * base64 crudo y le antepone el prefijo `data:` correspondiente a `type`
845
- * — el backend a veces manda una cosa, a veces la otra. */
846
- protected readonly resolvedSrc: _angular_core.Signal<string | null>;
847
- protected readonly pdfSrc: _angular_core.Signal<SafeResourceUrl | null>;
848
- protected readonly fallbackLabel: _angular_core.Signal<string>;
849
- private readonly dialog;
850
- private readonly document;
851
- private readonly sanitizer;
852
- constructor();
853
- /** `Escape` dispara `cancel`; cancelarlo lo deja abierto. */
854
- protected onCancel(event: Event): void;
855
- /**
856
- * Clic en el backdrop. Un clic en la zona del backdrop tiene como `target` al
857
- * propio `<dialog>` (el contenido vive en el panel de adentro), así que basta
858
- * comparar contra él — no hace falta cortar la propagación en el panel.
859
- */
860
- protected onHostClick(event: MouseEvent): void;
861
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentViewer, never>;
862
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentViewer, "kf-content-viewer", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; "alt": { "alias": "alt"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["[actions]"], true, never>;
863
- }
864
-
865
798
  /**
866
799
  * Zona que ocupa la columna en la vista de cards. La vista de tabla ignora
867
800
  * esto (salvo `media`, que igual se rinde como thumbnail en vez de imprimir
@@ -940,7 +873,25 @@ interface DataTableColumn {
940
873
  /** Destaca el valor (peso y color de tinta) — ej. el monto. En la vista
941
874
  * tarjetas, una columna `meta` con `emphasis` va al final de su fila. */
942
875
  emphasis?: boolean;
876
+ /** Celda interactiva: su contenido (texto, `cellTemplates` o `render`) se
877
+ * renderiza dentro de un `<button type="button">` real —enfocable con Tab,
878
+ * con foco visible y activable con Enter o Espacio—, tanto en la vista de
879
+ * tabla como en la de tarjetas. Al activarla emite `cellClick`
880
+ * (`{ row, column, index }`) y NO emite `rowClick`. El contenido de un
881
+ * `cellTemplates` en una columna interactiva debe ser fraseo no interactivo
882
+ * (texto, íconos, indicadores): un enlace o botón dentro de otro botón es
883
+ * HTML inválido. El nombre accesible sale del contenido o, si no alcanza
884
+ * (un indicador sin texto), de `cellAriaLabel`. */
885
+ interactive?: boolean;
886
+ }
887
+ /** Payload de `cellClick`: la fila, la columna interactiva y el índice de la fila renderizada. */
888
+ interface DataTableCellClick<T = unknown> {
889
+ row: T;
890
+ column: DataTableColumn;
891
+ index: number;
943
892
  }
893
+ /** Tope de filas (o tarjetas) esqueleto: con `loading`, una página de 50 no pinta 50. */
894
+ declare const DATA_TABLE_MAX_SKELETON_ROWS = 12;
944
895
  /** Vistas disponibles cuando `cardable` está activo. */
945
896
  type DataTableView = 'table' | 'cards';
946
897
  /** Opciones de "filas por página" estándar del portal — 10 como default
@@ -988,12 +939,21 @@ type DataTableSort = `${string}:${'asc' | 'desc'}`;
988
939
  * <kf-data-table [columns]="columns" [rows]="rows" [cardable]="true" defaultView="cards" />
989
940
  *
990
941
  * Loading nativo: con `loading` en `true`, la tabla se reemplaza por un
991
- * placeholder (`kf-skeleton` por celda/card) — mismo número de filas que
992
- * `pageSize`, o 5 si no hay paginación activa. Ignora `rows()`/el slot
942
+ * placeholder (`kf-skeleton` por celda/card) — `skeletonRows` filas si se
943
+ * pasa; si no, las de `pageSize`, o 5 si no hay paginación activa. Nunca más
944
+ * de 12 (`DATA_TABLE_MAX_SKELETON_ROWS`): con una página de 50 no se pintan
945
+ * 50 placeholders. Ignora `rows()`/el slot
993
946
  * `[empty]` mientras dura (no sabemos aún si el resultado real estará
994
947
  * vacío), y respeta la vista activa (tabla o cards) para no cambiar el
995
948
  * layout de golpe cuando los datos reales lleguen. El toggle tabla/cards y
996
- * el header de columnas siguen visibles — solo el cuerpo se reemplaza:
949
+ * el header de columnas siguen visibles — solo el cuerpo se reemplaza.
950
+ *
951
+ * El placeholder respeta la columna: en la tabla cada celda conserva su
952
+ * `align`, `width`, `minWidth` y `maxWidth` (una columna numérica lleva una
953
+ * barra corta alineada al final, una de acciones un cuadrado chico, el resto
954
+ * barras de anchos distintos) y la fila reserva el alto de una línea de texto.
955
+ * En tarjetas reproduce la estructura según `cardRole`: encabezado (miniatura,
956
+ * título y estado), campos con su rótulo, fila de `meta` y pie de acciones:
997
957
  *
998
958
  * <kf-data-table [columns]="columns" [rows]="rows()" [loading]="isLoading()">
999
959
  * <kf-empty-state empty>No hay resultados para mostrar.</kf-empty-state>
@@ -1086,6 +1046,30 @@ type DataTableSort = `${string}:${'asc' | 'desc'}`;
1086
1046
  * <kf-data-table [columns]="columns" [rows]="quotes" cardable [(view)]="view"
1087
1047
  * [showViewToggle]="false" cardMinWidth="300px" [rowClickable]="true"
1088
1048
  * (rowClick)="open($event.row)" />
1049
+ *
1050
+ * Celdas interactivas (modo aditivo, ej. una matriz unidad × etapa donde cada
1051
+ * celda de etapa es un indicador de estado): una columna con
1052
+ * `interactive: true` renderiza su contenido dentro de un `<button>` real
1053
+ * —focusable, con foco visible y activación con Enter o Espacio— en la vista
1054
+ * de tabla y en la de tarjetas, y emite `cellClick` con `{ row, column, index }`.
1055
+ * `cellAriaLabel` da el nombre accesible de cada celda cuando el contenido no
1056
+ * lo aporta por sí solo (un indicador sin texto); en tarjetas conviene incluir
1057
+ * el contexto de la fila, porque no hay encabezado de columna que lo dé:
1058
+ *
1059
+ * columns = [
1060
+ * { key: 'unit', label: 'Unidad', cardRole: 'title', sticky: 'left' },
1061
+ * { key: 'stage1', label: 'Recepción', interactive: true, align: 'center' },
1062
+ * { key: 'stage2', label: 'Entrega', interactive: true, align: 'center' },
1063
+ * ];
1064
+ * <kf-data-table [columns]="columns" [rows]="units" cardable [rowKey]="unitId"
1065
+ * [cellTemplates]="{ stage1: stageCell, stage2: stageCell }"
1066
+ * [cellAriaLabel]="stageLabel" (cellClick)="openStage($event.row, $event.column)" />
1067
+ *
1068
+ * Convive con `rowClick`: la fila sigue emitiéndolo desde cualquier punto que
1069
+ * no sea una celda interactiva. En tarjetas, la tarjeta deja de ser un botón
1070
+ * (un botón dentro de un `role="button"` es inválido) salvo que se fuerce con
1071
+ * `[rowClickable]="true"`. `sticky`, `cellTemplates`, `currentRowKey`, la
1072
+ * ordenación y la paginación no cambian.
1089
1073
  */
1090
1074
  declare class DataTable<T = unknown> {
1091
1075
  readonly columns: _angular_core.InputSignal<DataTableColumn[]>;
@@ -1093,6 +1077,10 @@ declare class DataTable<T = unknown> {
1093
1077
  /** Placeholder nativo (`kf-skeleton`) mientras los datos reales cargan —
1094
1078
  * ver el doc-comment de la clase para el detalle. */
1095
1079
  readonly loading: _angular_core.InputSignal<boolean>;
1080
+ /** Filas (o tarjetas) esqueleto mientras `loading` es `true`. Sin valor: el
1081
+ * `pageSize` con paginación activa, o 5. Máximo
1082
+ * {@link DATA_TABLE_MAX_SKELETON_ROWS}. */
1083
+ readonly skeletonRows: _angular_core.InputSignal<number | undefined>;
1096
1084
  private readonly scrollEl;
1097
1085
  private readonly destroyRef;
1098
1086
  /**
@@ -1132,10 +1120,13 @@ declare class DataTable<T = unknown> {
1132
1120
  * real (badges, links, botones) usar `cellTemplates`.
1133
1121
  */
1134
1122
  readonly render: _angular_core.InputSignal<((row: T) => string) | undefined>;
1135
- /** Mapa `columnKey -> TemplateRef` para celdas con contenido custom. */
1123
+ /** Mapa `columnKey -> TemplateRef` para celdas con contenido custom. El
1124
+ * contexto trae `$implicit` (la fila), `index` y `column` (la columna), así
1125
+ * que un mismo template puede servir a varias columnas. */
1136
1126
  readonly cellTemplates: _angular_core.InputSignal<Record<string, TemplateRef<{
1137
1127
  $implicit: T;
1138
1128
  index: number;
1129
+ column?: DataTableColumn;
1139
1130
  }>> | undefined>;
1140
1131
  /** Densidad de fila — ver `DataTableDensity`. */
1141
1132
  readonly density: _angular_core.InputSignal<DataTableDensity>;
@@ -1146,6 +1137,18 @@ declare class DataTable<T = unknown> {
1146
1137
  row: T;
1147
1138
  index: number;
1148
1139
  }>;
1140
+ /**
1141
+ * Se emite al activar (clic, Enter o Espacio) una celda de una columna
1142
+ * `interactive`. `index` es el de la fila dentro de las filas mostradas
1143
+ * (misma convención que `rowClick`). No emite `rowClick`.
1144
+ */
1145
+ readonly cellClick: _angular_core.OutputEmitterRef<DataTableCellClick<T>>;
1146
+ /**
1147
+ * Nombre accesible (`aria-label`) del botón de cada celda interactiva:
1148
+ * `(row, column, index) => string`. Sin esta función, el botón se nombra
1149
+ * por su contenido. Se usa solo en columnas `interactive`.
1150
+ */
1151
+ readonly cellAriaLabel: _angular_core.InputSignal<((row: T, column: DataTableColumn, index: number) => string) | undefined>;
1149
1152
  /** Nombre accesible del contenedor con scroll horizontal (solo se aplica cuando hay overflow). */
1150
1153
  readonly ariaLabel: _angular_core.InputSignal<string>;
1151
1154
  /**
@@ -1191,10 +1194,22 @@ declare class DataTable<T = unknown> {
1191
1194
  * (si `pageSizeOptions` está activo), o el `pageSize` del consumidor. */
1192
1195
  protected readonly effectivePageSize: _angular_core.Signal<number | null>;
1193
1196
  /** Cantidad de filas/cards placeholder mientras `loading` es true — el
1194
- * `pageSize` efectivo si hay paginación activa (así el placeholder ya
1195
- * "adivina" cuántas filas reales van a aparecer, sin salto de layout),
1196
- * o 5 si no hay paginación. */
1197
+ * `skeletonRows` explícito; si no hay, el `pageSize` efectivo con
1198
+ * paginación activa (así el placeholder ya "adivina" cuántas filas reales
1199
+ * van a aparecer, sin salto de layout) o 5 sin paginación. Siempre entre 1 y
1200
+ * {@link DATA_TABLE_MAX_SKELETON_ROWS}: con una página de 50 filas no se
1201
+ * pintan 50 placeholders. */
1197
1202
  protected readonly skeletonRowIndexes: _angular_core.Signal<number[]>;
1203
+ /** Las tarjetas esqueleto llevan encabezado cuando la real lo tendría. */
1204
+ protected readonly skeletonCardHeader: _angular_core.Signal<boolean>;
1205
+ /**
1206
+ * Ancho (%) de la barra de una celda esqueleto: no todas iguales — una
1207
+ * columna numérica (alineada al final) es corta, un identificador
1208
+ * (`mono`) mediano, una de acciones (`hideLabel`) un cuadrado chico, y el
1209
+ * resto alterna entre tres anchos según su posición para que la tabla no
1210
+ * parezca un patrón repetido.
1211
+ */
1212
+ protected skeletonBarWidth(column: DataTableColumn, row: number, index: number): string;
1198
1213
  protected readonly totalPages: _angular_core.Signal<number>;
1199
1214
  /** Texto informativo del footer de paginación interna ("1–5 de 7
1200
1215
  * beneficios") — se recalcula con cada cambio de página/tamaño/dataset,
@@ -1207,8 +1222,8 @@ declare class DataTable<T = unknown> {
1207
1222
  * asc → desc → sin orden; clickear otra columna reinicia el ciclo en esa
1208
1223
  * columna nueva.
1209
1224
  */
1210
- readonly sort: _angular_core.InputSignal<`${string}:asc` | `${string}:desc` | null>;
1211
- readonly sortChange: _angular_core.OutputEmitterRef<`${string}:asc` | `${string}:desc` | null>;
1225
+ readonly sort: _angular_core.InputSignal<`${string}:desc` | `${string}:asc` | null>;
1226
+ readonly sortChange: _angular_core.OutputEmitterRef<`${string}:desc` | `${string}:asc` | null>;
1212
1227
  protected readonly sortedRows: _angular_core.Signal<T[]>;
1213
1228
  /** Filas realmente renderizadas: ordenadas y, si `pageSize` está activo,
1214
1229
  * recortadas a la página actual. */
@@ -1278,6 +1293,8 @@ declare class DataTable<T = unknown> {
1278
1293
  * Con columnas `action`, la interacción la manejan esos botones.
1279
1294
  */
1280
1295
  readonly cardInteractive: _angular_core.Signal<boolean>;
1296
+ /** Hay al menos una columna `interactive` (celdas con botón propio). */
1297
+ protected readonly hasInteractiveColumns: _angular_core.Signal<boolean>;
1281
1298
  /**
1282
1299
  * Mismo criterio que `cardInteractive`, para la vista de tabla: la fila
1283
1300
  * entera dispara `rowClick` solo si no hay una columna `action` que ya
@@ -1310,6 +1327,10 @@ declare class DataTable<T = unknown> {
1310
1327
  * `event` es opcional para no romper llamadas programáticas existentes.
1311
1328
  */
1312
1329
  onRowClick(row: T, index: number, event?: Event): void;
1330
+ /** Activación de una celda interactiva (clic, o Enter/Espacio sobre su botón). */
1331
+ protected onCellClick(row: T, column: DataTableColumn, index: number): void;
1332
+ /** `aria-label` del botón de una celda interactiva, o `null` si lo da su contenido. */
1333
+ protected cellLabel(row: T, column: DataTableColumn, index: number): string | null;
1313
1334
  private originatesInInteractiveControl;
1314
1335
  /**
1315
1336
  * Ancho real de cada columna `sticky` — se mide después de cada render
@@ -1321,7 +1342,185 @@ declare class DataTable<T = unknown> {
1321
1342
  */
1322
1343
  protected measureStickyOffsets(): void;
1323
1344
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataTable<any>, never>;
1324
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTable<any>, "kf-data-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "rowKey": { "alias": "rowKey"; "required": false; "isSignal": true; }; "flush": { "alias": "flush"; "required": false; "isSignal": true; }; "cardable": { "alias": "cardable"; "required": false; "isSignal": true; }; "defaultView": { "alias": "defaultView"; "required": false; "isSignal": true; }; "showViewToggle": { "alias": "showViewToggle"; "required": false; "isSignal": true; }; "cardMinWidth": { "alias": "cardMinWidth"; "required": false; "isSignal": true; }; "render": { "alias": "render"; "required": false; "isSignal": true; }; "cellTemplates": { "alias": "cellTemplates"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "rowClickable": { "alias": "rowClickable"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "currentRowKey": { "alias": "currentRowKey"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "page": { "alias": "page"; "required": false; "isSignal": true; }; "keepPageOnRowsChange": { "alias": "keepPageOnRowsChange"; "required": false; "isSignal": true; }; "itemLabel": { "alias": "itemLabel"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; "page": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "view": "viewChange"; }, never, ["[empty]", "[footer]"], true, never>;
1345
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataTable<any>, "kf-data-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "skeletonRows": { "alias": "skeletonRows"; "required": false; "isSignal": true; }; "rowKey": { "alias": "rowKey"; "required": false; "isSignal": true; }; "flush": { "alias": "flush"; "required": false; "isSignal": true; }; "cardable": { "alias": "cardable"; "required": false; "isSignal": true; }; "defaultView": { "alias": "defaultView"; "required": false; "isSignal": true; }; "showViewToggle": { "alias": "showViewToggle"; "required": false; "isSignal": true; }; "cardMinWidth": { "alias": "cardMinWidth"; "required": false; "isSignal": true; }; "render": { "alias": "render"; "required": false; "isSignal": true; }; "cellTemplates": { "alias": "cellTemplates"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "rowClickable": { "alias": "rowClickable"; "required": false; "isSignal": true; }; "cellAriaLabel": { "alias": "cellAriaLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "currentRowKey": { "alias": "currentRowKey"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "page": { "alias": "page"; "required": false; "isSignal": true; }; "keepPageOnRowsChange": { "alias": "keepPageOnRowsChange"; "required": false; "isSignal": true; }; "itemLabel": { "alias": "itemLabel"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; "cellClick": "cellClick"; "page": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "view": "viewChange"; }, never, ["[empty]", "[footer]"], true, never>;
1346
+ }
1347
+
1348
+ /** Forma de contenido que reproduce el preset. */
1349
+ type SkeletonPresetVariant = 'kpi-grid' | 'card-grid' | 'form' | 'list' | 'table' | 'timeline' | 'detail-header';
1350
+ /** Tope de elementos: un `count` mayor se acota, no tiene sentido pintar más. */
1351
+ declare const SKELETON_PRESET_MAX_COUNT = 12;
1352
+ /**
1353
+ * Esqueletos listos para usar que reproducen la FORMA del contenido real, para
1354
+ * que al llegar los datos nada se mueva. Cada variante se arma con la misma
1355
+ * geometría que su equivalente cargado (mismos cascarones, alturas, radios y
1356
+ * gaps, todo por tokens):
1357
+ *
1358
+ * | `variant` | Equivalente cargado | `count` | `columns` |
1359
+ * | ---------------- | ---------------------------- | -------------- | ------------------ |
1360
+ * | `kpi-grid` | `kf-stat-card` | tarjetas (4) | columnas de la grilla |
1361
+ * | `card-grid` | `kf-card` | tarjetas (6) | columnas de la grilla |
1362
+ * | `form` | `kf-input` con label | campos (4) | `1` o `2` |
1363
+ * | `list` | `kf-document-row` | filas (4) | — |
1364
+ * | `table` | `kf-data-table` | filas (5) | columnas (4) |
1365
+ * | `timeline` | `kf-milestone-timeline` | etapas (4) | — |
1366
+ * | `detail-header` | `kf-page-header` con ícono | — | — |
1367
+ *
1368
+ * Sin `columns`, las grillas (`kpi-grid`, `card-grid`) se reparten solas con un
1369
+ * ancho mínimo por tarjeta. `count` se acota a 12.
1370
+ *
1371
+ * El preset es decorativo (`aria-hidden` por dentro) y marca su contenedor con
1372
+ * `aria-busy="true"`. Con `label` agrega un texto visualmente oculto con
1373
+ * `role="status"` que lo anuncia a lectores de pantalla; dentro de
1374
+ * `kf-content-state` no hace falta (ya lo anuncia él).
1375
+ *
1376
+ * <kf-skeleton-preset variant="kpi-grid" [count]="4" />
1377
+ * <kf-skeleton-preset variant="form" [count]="3" [columns]="2" label="Cargando formulario" />
1378
+ * <kf-content-state [state]="state()" loadingPreset="table">…</kf-content-state>
1379
+ */
1380
+ declare class SkeletonPreset {
1381
+ readonly variant: _angular_core.InputSignal<SkeletonPresetVariant>;
1382
+ /** Cantidad de elementos. Sin valor, el de la variante. Máximo 12. */
1383
+ readonly count: _angular_core.InputSignal<number | undefined>;
1384
+ /** Columnas: de la grilla (`kpi-grid`, `card-grid`), del formulario (`1`|`2`) o de la tabla. */
1385
+ readonly columns: _angular_core.InputSignal<number | undefined>;
1386
+ /** Texto accesible (visualmente oculto, `role="status"`). Vacío, no se emite. */
1387
+ readonly label: _angular_core.InputSignal<string>;
1388
+ protected readonly total: _angular_core.Signal<number>;
1389
+ protected readonly items: _angular_core.Signal<number[]>;
1390
+ /** Columnas de la tabla sintética (encabezados en blanco: lo real aún no llegó). */
1391
+ protected readonly tableColumns: _angular_core.Signal<DataTableColumn[]>;
1392
+ protected readonly formColumns: _angular_core.Signal<2 | 1>;
1393
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SkeletonPreset, never>;
1394
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SkeletonPreset, "kf-skeleton-preset", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1395
+ }
1396
+
1397
+ /** En qué estado está la sección. */
1398
+ type ContentStateKind = 'ready' | 'loading' | 'empty' | 'error';
1399
+ /** Cómo se dibuja `loading`. Default `'skeleton'`. */
1400
+ type ContentStateLoad = 'skeleton' | 'spinner';
1401
+ /**
1402
+ * Marca el `ng-template` que reemplaza el esqueleto genérico de
1403
+ * `kf-content-state` mientras carga (`state="loading"`, `load="skeleton"`).
1404
+ *
1405
+ * <kf-content-state [state]="state()">
1406
+ * <ng-template kfContentStateLoading><kf-skeleton-preset variant="kpi-grid" /></ng-template>
1407
+ * …
1408
+ * </kf-content-state>
1409
+ */
1410
+ declare class ContentStateLoading {
1411
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentStateLoading, never>;
1412
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ContentStateLoading, "ng-template[kfContentStateLoading]", never, {}, {}, never, never, true, never>;
1413
+ }
1414
+ /**
1415
+ * Wrapper de los cuatro estados que toda sección tiene: cargando, con datos,
1416
+ * vacía y con error. Un componente en vez de tres `@if` sueltos, porque es
1417
+ * siempre el mismo slot el que va rotando entre los cuatro.
1418
+ *
1419
+ * Con `state="ready"` proyecta el contenido real y desaparece; en los otros
1420
+ * tres dibuja el placeholder correspondiente y el contenido no se instancia.
1421
+ * No inventa visuales propios: `loading` usa `kf-skeleton` (o `kf-spinner` con
1422
+ * `load="spinner"`), y `empty`/`error` usan `kf-empty-state`.
1423
+ *
1424
+ * Las acciones (reintentar, crear) van en el slot `actions` — se ignoran
1425
+ * mientras carga, porque no hay nada que reintentar todavía.
1426
+ *
1427
+ * <kf-content-state [state]="state()" title="No pudimos cargar tus vehículos"
1428
+ * subtitle="Revisá tu conexión e intentá de nuevo.">
1429
+ * <kf-button actions (click)="retry()">Reintentar</kf-button>
1430
+ * <kf-data-table [columns]="cols" [rows]="rows()" />
1431
+ * </kf-content-state>
1432
+ *
1433
+ * Esqueleto de carga: por defecto son tres líneas genéricas. Para que la
1434
+ * carga se parezca a lo que va a aparecer, hay tres vías (de la más corta a la
1435
+ * más libre): `loadingPreset` (una variante de `kf-skeleton-preset`), el input
1436
+ * `loadingTemplate` (un `TemplateRef`) o un `ng-template` marcado con
1437
+ * `kfContentStateLoading` dentro del contenido. Si hay más de una, gana la
1438
+ * plantilla proyectada, luego `loadingTemplate` y por último `loadingPreset`.
1439
+ *
1440
+ * <kf-content-state [state]="state()" loadingPreset="kpi-grid">…</kf-content-state>
1441
+ *
1442
+ * Accesibilidad: en modo skeleton el contenedor lleva `aria-busy="true"` y un
1443
+ * texto visualmente oculto con `role="status"` (`loadingLabel`, "Cargando…" por
1444
+ * defecto) que anuncia el estado una vez. Con `load="spinner"` el texto es el
1445
+ * del propio `kf-spinner`. El contenedor reserva un ancho mínimo, así que el
1446
+ * esqueleto no colapsa a 0 dentro de un padre que se ajusta a su contenido.
1447
+ */
1448
+ declare class ContentState {
1449
+ readonly state: _angular_core.InputSignal<ContentStateKind>;
1450
+ /** Forma del estado de carga: silueta (default) o spinner. */
1451
+ readonly load: _angular_core.InputSignal<ContentStateLoad>;
1452
+ /** Título de `empty`/`error`. Ignorado mientras carga. */
1453
+ readonly title: _angular_core.InputSignal<string>;
1454
+ readonly subtitle: _angular_core.InputSignal<string>;
1455
+ /** Texto de carga: al lado del spinner con `load="spinner"` y, en modo skeleton,
1456
+ * texto visualmente oculto con `role="status"` para lectores de pantalla. */
1457
+ readonly loadingLabel: _angular_core.InputSignal<string>;
1458
+ /** Plantilla propia del esqueleto (reemplaza las tres líneas genéricas). */
1459
+ readonly loadingTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
1460
+ /** Variante de `kf-skeleton-preset` como esqueleto de carga. */
1461
+ readonly loadingPreset: _angular_core.InputSignal<SkeletonPresetVariant | null>;
1462
+ /** `ng-template[kfContentStateLoading]` proyectado como contenido. */
1463
+ protected readonly projectedLoading: _angular_core.Signal<TemplateRef<any> | undefined>;
1464
+ protected readonly customLoading: _angular_core.Signal<TemplateRef<any> | null>;
1465
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentState, never>;
1466
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentState, "kf-content-state", never, { "state": { "alias": "state"; "required": true; "isSignal": true; }; "load": { "alias": "load"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "loadingLabel": { "alias": "loadingLabel"; "required": false; "isSignal": true; }; "loadingTemplate": { "alias": "loadingTemplate"; "required": false; "isSignal": true; }; "loadingPreset": { "alias": "loadingPreset"; "required": false; "isSignal": true; }; }, {}, ["projectedLoading"], ["*", "[actions]"], true, never>;
1467
+ }
1468
+
1469
+ type ContentViewerType = 'image' | 'video' | 'pdf';
1470
+ /**
1471
+ * Visor a pantalla completa para ampliar una pieza de contenido: imagen,
1472
+ * video o PDF (`type="pdf"`, renderizado por el visor nativo del navegador).
1473
+ * Mismo mecanismo que `kf-modal` (el `<dialog>` nativo resuelve backdrop,
1474
+ * atrapado de foco, top-layer y `Escape`), pero sin panel/título/footer:
1475
+ * el contenido ocupa toda la pantalla sobre un backdrop oscuro.
1476
+ *
1477
+ * `src` acepta lo que venga del backend sin que el consumidor tenga que
1478
+ * normalizarlo primero: una URL (`http(s)://`), un data URI ya armado
1479
+ * (`data:...`), o base64 crudo (se le antepone el prefijo `data:` según
1480
+ * `type`, asumiendo JPEG para imagen, MP4 para video y PDF para pdf). Un PDF
1481
+ * solo acepta contenido local (`blob:`, data URI o base64), nunca una URL remota.
1482
+ *
1483
+ * Lo proyectado con el atributo `actions` (p. ej. un botón de descarga) va en
1484
+ * la barra superior, junto al título.
1485
+ *
1486
+ * <kf-content-viewer [(open)]="viewerOpen" [src]="viewerSrc()" alt="Foto del vehículo" />
1487
+ * <kf-content-viewer [(open)]="viewerOpen" type="video" [src]="viewerSrc()" title="Inspección" />
1488
+ * <kf-content-viewer [(open)]="viewerOpen" type="pdf" [src]="blobUrl()" title="Contrato">
1489
+ * <kf-button actions variant="surface" icon="download" (click)="save()">Descargar</kf-button>
1490
+ * </kf-content-viewer>
1491
+ */
1492
+ declare class ContentViewer {
1493
+ readonly type: _angular_core.InputSignal<ContentViewerType>;
1494
+ /** URL, data URI, o base64 crudo — ver JSDoc de la clase. */
1495
+ readonly src: _angular_core.InputSignal<string | null>;
1496
+ /** Texto alternativo cuando `type="image"`. */
1497
+ readonly alt: _angular_core.InputSignal<string>;
1498
+ readonly title: _angular_core.InputSignal<string>;
1499
+ /** Visibilidad, two-way: `[(open)]="viewerOpen"`. */
1500
+ readonly open: _angular_core.ModelSignal<boolean>;
1501
+ /** Permite cerrar con el botón, `Escape` o clic en el backdrop. */
1502
+ readonly dismissible: _angular_core.InputSignalWithTransform<boolean, unknown>;
1503
+ protected readonly titleId: string;
1504
+ /** Detecta si `src` ya es una URL o un data URI armado; si no, asume
1505
+ * base64 crudo y le antepone el prefijo `data:` correspondiente a `type`
1506
+ * — el backend a veces manda una cosa, a veces la otra. */
1507
+ protected readonly resolvedSrc: _angular_core.Signal<string | null>;
1508
+ protected readonly pdfSrc: _angular_core.Signal<SafeResourceUrl | null>;
1509
+ protected readonly fallbackLabel: _angular_core.Signal<string>;
1510
+ private readonly dialog;
1511
+ private readonly document;
1512
+ private readonly sanitizer;
1513
+ constructor();
1514
+ /** `Escape` dispara `cancel`; cancelarlo lo deja abierto. */
1515
+ protected onCancel(event: Event): void;
1516
+ /**
1517
+ * Clic en el backdrop. Un clic en la zona del backdrop tiene como `target` al
1518
+ * propio `<dialog>` (el contenido vive en el panel de adentro), así que basta
1519
+ * comparar contra él — no hace falta cortar la propagación en el panel.
1520
+ */
1521
+ protected onHostClick(event: MouseEvent): void;
1522
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentViewer, never>;
1523
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentViewer, "kf-content-viewer", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "src": { "alias": "src"; "required": false; "isSignal": true; }; "alt": { "alias": "alt"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, never, ["[actions]"], true, never>;
1325
1524
  }
1326
1525
 
1327
1526
  /**
@@ -1367,6 +1566,14 @@ type DocumentRowTone = 'neutral' | 'ok' | 'warn' | 'error' | 'info';
1367
1566
  * título, metadata y la acción de descarga al final. Sin `href` rinde
1368
1567
  * `pendingLabel` en vez de un link roto. El contenido proyectado cae entre
1369
1568
  * la metadata y la acción, como slot para un `kf-badge` de estado.
1569
+ *
1570
+ * `loading` (default `false`): dibuja el esqueleto de la fila — chip, título,
1571
+ * metadata y acción como bloques del alto real de cada texto — con el mismo
1572
+ * cascarón, así que al llegar los datos no hay salto de layout. Pasa los
1573
+ * mismos inputs que usarás cargada (`meta` incluido, para reservar su línea).
1574
+ * Marca el host con `aria-busy="true"` y oculta el contenido proyectado.
1575
+ *
1576
+ * <kf-document-row title="Factura" meta="PDF · 120 KB" [loading]="isLoading()" />
1370
1577
  */
1371
1578
  declare class DocumentRow {
1372
1579
  readonly icon: _angular_core.InputSignal<IconName>;
@@ -1382,8 +1589,10 @@ declare class DocumentRow {
1382
1589
  readonly downloadLabel: _angular_core.InputSignal<string>;
1383
1590
  /** Qué se dice cuando no hay `href`. */
1384
1591
  readonly pendingLabel: _angular_core.InputSignal<string>;
1592
+ /** Dibuja el esqueleto en lugar del contenido, conservando las dimensiones. */
1593
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
1385
1594
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DocumentRow, never>;
1386
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DocumentRow, "kf-document-row", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "downloadLabel": { "alias": "downloadLabel"; "required": false; "isSignal": true; }; "pendingLabel": { "alias": "pendingLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1595
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DocumentRow, "kf-document-row", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "href": { "alias": "href"; "required": false; "isSignal": true; }; "downloadLabel": { "alias": "downloadLabel"; "required": false; "isSignal": true; }; "pendingLabel": { "alias": "pendingLabel"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, ["*", "*"], true, never>;
1387
1596
  }
1388
1597
 
1389
1598
  /** Borde de anclaje del panel. `bottom` es una hoja inferior (bottom sheet). */
@@ -1447,8 +1656,9 @@ type DrawerRole = 'navigation' | 'dialog';
1447
1656
  * redondeadas, alto máximo 80vh) — pensado para un resumen en mobile.
1448
1657
  *
1449
1658
  * Escape cierra el panel salvo que un control interno ya haya consumido la
1450
- * tecla (`event.defaultPrevented`, ej. un `kf-select` abierto dentro del
1451
- * drawer cierra solo su propio panel).
1659
+ * tecla (`event.defaultPrevented`): un `kf-select`, `kf-multi-select` o
1660
+ * `kf-dropdown` abierto dentro del drawer cierra primero su propio panel y
1661
+ * un segundo Escape cierra el drawer.
1452
1662
  *
1453
1663
  * Nombres por defecto: con `role="navigation"` el panel se llama "Menú" y
1454
1664
  * el cierre "Cerrar menú" (comportamiento histórico). Con `role="dialog"`
@@ -1456,12 +1666,25 @@ type DrawerRole = 'navigation' | 'dialog';
1456
1666
  * avisa por consola si no hay `title` ni `ariaLabel`: un diálogo sin nombre
1457
1667
  * propio no le dice nada al lector de pantalla.
1458
1668
  *
1459
- * Limitación conocida: NO colocar un `kf-select` (ni otro control con panel
1460
- * flotante del CDK) dentro de un drawer `role="dialog"`. Su listbox se
1461
- * monta en `.cdk-overlay-container`, fuera del diálogo con `aria-modal`: un
1462
- * lector de pantalla puede tratarlo como contenido inerte y la trampa de
1463
- * foco no lo incluye. Para elegir una opción dentro del panel usar
1464
- * `kf-option-list`.
1669
+ * ## Selectores y otros paneles flotantes dentro del drawer
1670
+ *
1671
+ * `kf-select`, `kf-multi-select` y `kf-dropdown` funcionan
1672
+ * dentro de un drawer (incluido el pie `[kf-drawer-footer]`): sus paneles
1673
+ * quedan por encima del drawer, se abren hacia arriba si abajo no hay lugar
1674
+ * y no se cortan con el borde del panel ni con el scroll del cuerpo. Con
1675
+ * `role="dialog"` el contenedor de overlays de CDK se reubica dentro del
1676
+ * panel mientras está abierto: el listbox queda dentro del diálogo
1677
+ * `aria-modal`, no fuera de él, y el atrapado de foco lo incluye. Al cerrar
1678
+ * el drawer vuelve a `<body>`. Escape cierra primero el panel flotante
1679
+ * (devolviendo el foco a su disparador) y el siguiente cierra el drawer.
1680
+ *
1681
+ * <kf-drawer [(open)]="open" role="dialog" side="right" title="Unidad VIN-1003">
1682
+ * ...
1683
+ * <div kf-drawer-footer>
1684
+ * <kf-select label="Saltar a otra unidad" width="full"
1685
+ * [options]="units" [value]="unit()" (valueChange)="unit.set($event)" />
1686
+ * </div>
1687
+ * </kf-drawer>
1465
1688
  *
1466
1689
  * Al cerrar, el foco vuelve al elemento que lo tenía al abrir solo si sigue
1467
1690
  * en el documento (`isConnected`); si fue desmontado mientras el drawer
@@ -1494,6 +1717,8 @@ declare class Drawer {
1494
1717
  private readonly panelRef;
1495
1718
  private readonly focusTrapFactory;
1496
1719
  private readonly document;
1720
+ private readonly overlayContainer;
1721
+ private registeredPanel;
1497
1722
  private focusTrap;
1498
1723
  private lastFocusedElement;
1499
1724
  constructor();
@@ -1549,9 +1774,12 @@ declare class Dropdown {
1549
1774
  * Respaldo de `overlayRef.keydownEvents()`: ese observable del CDK solo
1550
1775
  * ve teclas con el foco DENTRO del panel. Si el foco queda en el botón
1551
1776
  * disparador (caso común), `keydownEvents()` nunca dispara — este
1552
- * listener a nivel de documento cubre ese caso.
1777
+ * listener a nivel de documento cubre ese caso. Va en fase de captura
1778
+ * (ver `listenEscapeCapture`) y consume la tecla solo si había un menú
1779
+ * abierto, así un `kf-drawer`/`kf-modal` contenedor no se cierra con el
1780
+ * mismo Escape. Devuelve si cerró algo.
1553
1781
  */
1554
- onDocumentEscape(): void;
1782
+ onDocumentEscape(): boolean;
1555
1783
  private attach;
1556
1784
  /**
1557
1785
  * El trigger real (el `anchor`, o el propio host si no se pasó ninguno —
@@ -1671,7 +1899,7 @@ declare class EmptyState {
1671
1899
  /** `neutral` (default): cero resultados. `error`: fallo real de carga. `warn`/`info`: tiñen el chip del ícono. */
1672
1900
  readonly tone: _angular_core.InputSignal<EmptyStateTone>;
1673
1901
  /** `inline` (default, histórico) o `card` (tarjeta centrada). Ver JSDoc de la clase. */
1674
- readonly variant: _angular_core.InputSignal<"inline" | "card">;
1902
+ readonly variant: _angular_core.InputSignal<"card" | "inline">;
1675
1903
  /** Título destacado sobre el contenido. Opcional en ambas variantes. */
1676
1904
  readonly title: _angular_core.InputSignal<string | undefined>;
1677
1905
  protected readonly iconSize: _angular_core.Signal<IconSize>;
@@ -1791,6 +2019,128 @@ declare class FieldLabel {
1791
2019
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldLabel, "kf-field-label", never, { "for": { "alias": "for"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1792
2020
  }
1793
2021
 
2022
+ /** Por qué se descartó un archivo: formato fuera de `accept` o más grande que `maxSize`. */
2023
+ type FileRejectionReason = 'type' | 'size';
2024
+ /** Un archivo descartado y el motivo. */
2025
+ interface FileRejection {
2026
+ file: File;
2027
+ reason: FileRejectionReason;
2028
+ }
2029
+ /** Tamaño en bytes como texto (`5 MB`, `120 KB`), base 1024. */
2030
+ declare function formatFileSize(bytes: number): string;
2031
+ /**
2032
+ * Selector de archivo accesible, con la misma apariencia y contrato de campo
2033
+ * que `kf-input`: label arriba, ayuda y error debajo, `invalid`.
2034
+ *
2035
+ * El control real es un `<input type="file">` nativo, visualmente oculto pero
2036
+ * enfocable: se llega con Tab, se abre con Enter o Espacio y el anillo de foco
2037
+ * se dibuja sobre el botón visible. Su nombre accesible es el `label` (o
2038
+ * `ariaLabel`); la ayuda, el archivo elegido y el error lo describen
2039
+ * (`aria-describedby`).
2040
+ *
2041
+ * **Ayuda antes de elegir.** `hint` es texto libre; si no se pasa, se arma sola
2042
+ * con los formatos de `accept` y el tamaño de `maxSize` (`PDF, JPG · máx. 5 MB`),
2043
+ * para que el usuario sepa qué sirve ANTES de abrir el selector.
2044
+ *
2045
+ * **Validación.** Cada archivo se revisa contra `accept` (extensiones `.pdf`,
2046
+ * tipos `image/png` o comodines `image/*`) y `maxSize` (bytes). Los válidos
2047
+ * quedan elegidos y se emiten en `fileChange` (siempre `File[]`, vacío al
2048
+ * quitar); los descartados se emiten uno a uno en `fileRejected` con su
2049
+ * motivo (`'type'` o `'size'`) y se muestran como error bajo el campo
2050
+ * (`rejectedTypeText` / `rejectedSizeText`); la ayuda sigue visible bajo ese
2051
+ * mensaje, para que se vea qué sí sirve. Un `error` del consumidor tiene
2052
+ * prioridad sobre ese mensaje y reemplaza a la ayuda, igual que `errorMessage`
2053
+ * sobre `hint` en `kf-input`. La validación del navegador no reemplaza la del servidor.
2054
+ *
2055
+ * **Archivo elegido.** Su nombre y tamaño aparecen UNA vez, con un botón para
2056
+ * quitarlo (`removeLabel`, con el nombre del archivo en su `aria-label`); el
2057
+ * nombre del `<input>` nativo queda oculto. Con `multiple` se listan todos y
2058
+ * cada uno se quita por separado. Elegir de nuevo reemplaza la selección.
2059
+ *
2060
+ * `dropzone` agrega arrastrar y soltar sobre el área; el botón y el teclado
2061
+ * siguen siendo la vía principal.
2062
+ *
2063
+ * Es un `ControlValueAccessor`: con `[(ngModel)]`/`formControl` el valor es
2064
+ * `File | null` (o `File[]` con `multiple`); `writeValue(null)` limpia.
2065
+ *
2066
+ * <kf-file-input label="Comprobante" accept=".pdf,.jpg,.png" [maxSize]="5242880"
2067
+ * (fileChange)="onFiles($event)" (fileRejected)="onRejected($event)" />
2068
+ * <kf-file-input label="Fotos" accept="image/*" multiple dropzone formControlName="photos" />
2069
+ * <kf-file-input label="Contrato" error="Adjunta el contrato firmado." formControlName="contract" />
2070
+ */
2071
+ declare class FileInput implements ControlValueAccessor {
2072
+ private readonly nativeInput;
2073
+ readonly label: _angular_core.InputSignal<string | undefined>;
2074
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
2075
+ /** Texto de ayuda. Sin valor, se arma con `accept` y `maxSize`. */
2076
+ readonly hint: _angular_core.InputSignal<string | undefined>;
2077
+ /** Formatos admitidos, como el `accept` nativo: `.pdf,.jpg`, `image/png`, `image/*`. */
2078
+ readonly accept: _angular_core.InputSignal<string | undefined>;
2079
+ /** Tamaño máximo por archivo, en bytes. Sin valor, sin límite. */
2080
+ readonly maxSize: _angular_core.InputSignal<number | undefined>;
2081
+ readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
2082
+ /** Agrega arrastrar y soltar sobre el área del control. */
2083
+ readonly dropzone: _angular_core.InputSignalWithTransform<boolean, unknown>;
2084
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
2085
+ /** Borde rojo y `aria-invalid`. Se activa solo con `error`; úsalo para marcar un error sin mensaje. */
2086
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
2087
+ /** Mensaje de error del consumidor (`role="alert"`); reemplaza a la ayuda y al motivo de rechazo, como `errorMessage` en `kf-input`. */
2088
+ readonly error: _angular_core.InputSignal<string | undefined>;
2089
+ /** Nombre accesible cuando no hay `label` visible. */
2090
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
2091
+ /** Texto del botón cuando no hay archivo elegido. */
2092
+ readonly buttonLabel: _angular_core.InputSignal<string>;
2093
+ /** Texto del botón con `multiple` o cuando ya hay un archivo (cambiar). */
2094
+ readonly changeLabel: _angular_core.InputSignal<string>;
2095
+ /** Nombre accesible del botón de quitar; se le agrega el nombre del archivo. */
2096
+ readonly removeLabel: _angular_core.InputSignal<string>;
2097
+ /** Texto de arrastrar y soltar (solo con `dropzone`). */
2098
+ readonly dropzoneText: _angular_core.InputSignal<string>;
2099
+ readonly rejectedTypeText: _angular_core.InputSignal<string>;
2100
+ readonly rejectedSizeText: _angular_core.InputSignal<string>;
2101
+ /** Selección vigente (`File[]`, vacío al quitar todo). */
2102
+ readonly fileChange: _angular_core.OutputEmitterRef<File[]>;
2103
+ /** Un archivo descartado y su motivo. */
2104
+ readonly fileRejected: _angular_core.OutputEmitterRef<FileRejection>;
2105
+ protected readonly inputId: string;
2106
+ protected readonly hintId: string;
2107
+ protected readonly errorId: string;
2108
+ protected readonly filesId: string;
2109
+ protected readonly files: _angular_core.WritableSignal<File[]>;
2110
+ protected readonly rejection: _angular_core.WritableSignal<FileRejectionReason | null>;
2111
+ protected readonly dragging: _angular_core.WritableSignal<boolean>;
2112
+ private readonly disabledByForm;
2113
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
2114
+ private onChange;
2115
+ private onTouched;
2116
+ /** Mensaje visible: el del consumidor, o el motivo del último rechazo. */
2117
+ protected readonly message: _angular_core.Signal<string | null>;
2118
+ /** Ayuda efectiva: la del consumidor o la armada con formatos y tamaño. */
2119
+ protected readonly effectiveHint: _angular_core.Signal<string>;
2120
+ protected readonly isInvalid: _angular_core.Signal<boolean>;
2121
+ protected readonly describedBy: _angular_core.Signal<string | null>;
2122
+ protected readonly triggerText: _angular_core.Signal<string>;
2123
+ /** Enfoca el `<input>` nativo. */
2124
+ focus(options?: FocusOptions): void;
2125
+ writeValue(value: File | File[] | null): void;
2126
+ registerOnChange(fn: (value: File | File[] | null) => void): void;
2127
+ registerOnTouched(fn: () => void): void;
2128
+ setDisabledState(isDisabled: boolean): void;
2129
+ protected onPick(event: Event): void;
2130
+ protected onDragOver(event: DragEvent): void;
2131
+ protected onDragLeave(): void;
2132
+ protected onDrop(event: DragEvent): void;
2133
+ protected remove(index: number): void;
2134
+ protected formatSize(file: File): string;
2135
+ /** Valida lo recibido, emite los rechazos y reemplaza la selección si hay algo válido. */
2136
+ private receive;
2137
+ private reject;
2138
+ private matchesAccept;
2139
+ private commit;
2140
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileInput, never>;
2141
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileInput, "kf-file-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "maxSize": { "alias": "maxSize"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "dropzone": { "alias": "dropzone"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; "changeLabel": { "alias": "changeLabel"; "required": false; "isSignal": true; }; "removeLabel": { "alias": "removeLabel"; "required": false; "isSignal": true; }; "dropzoneText": { "alias": "dropzoneText"; "required": false; "isSignal": true; }; "rejectedTypeText": { "alias": "rejectedTypeText"; "required": false; "isSignal": true; }; "rejectedSizeText": { "alias": "rejectedSizeText"; "required": false; "isSignal": true; }; }, { "fileChange": "fileChange"; "fileRejected": "fileRejected"; }, never, never, true, never>;
2142
+ }
2143
+
1794
2144
  interface MultiSelectOption {
1795
2145
  value: string;
1796
2146
  label: string;
@@ -1884,7 +2234,13 @@ declare class MultiSelect {
1884
2234
  /** Mueve `activeIndex` sobre las opciones YA FILTRADAS visibles. Clamp simple, sin wraparound. */
1885
2235
  moveActive(delta: number): void;
1886
2236
  toggleActive(): void;
1887
- onEscape(): void;
2237
+ /**
2238
+ * Escape con el panel abierto, en fase de captura sobre `document` (ver
2239
+ * `listenEscapeCapture`): consume la tecla solo si había un panel que
2240
+ * cerrar, así un `kf-drawer`/`kf-modal` contenedor no se cierra con el
2241
+ * mismo Escape. Devuelve si cerró algo.
2242
+ */
2243
+ onEscape(): boolean;
1888
2244
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MultiSelect, never>;
1889
2245
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MultiSelect, "kf-multi-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "values": { "alias": "values"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchThreshold": { "alias": "searchThreshold"; "required": false; "isSignal": true; }; }, { "valuesChange": "valuesChange"; }, never, never, true, never>;
1890
2246
  }
@@ -2035,6 +2391,8 @@ declare class Footer {
2035
2391
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Footer, "kf-footer", never, { "logoSrc": { "alias": "logoSrc"; "required": false; "isSignal": true; }; "logoAlt": { "alias": "logoAlt"; "required": false; "isSignal": true; }; "copyright": { "alias": "copyright"; "required": true; "isSignal": true; }; "links": { "alias": "links"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2036
2392
  }
2037
2393
 
2394
+ /** Valor de `min`/`max`/`step`: número, o texto cuando el tipo lo pide (una fecha `'2026-01-31'`, un mes, una hora). */
2395
+ type InputBound = string | number | null | undefined;
2038
2396
  /**
2039
2397
  * Input de formulario apilado: label arriba (en mayúsculas vía CSS), campo con
2040
2398
  * fondo gris que pasa a blanco con anillo de foco azul al enfocar.
@@ -2098,6 +2456,20 @@ declare class Footer {
2098
2456
  *
2099
2457
  * <kf-input label="RUT" autocomplete="username" name="rut" inputmode="text" formControlName="rut" />
2100
2458
  * <kf-input type="password" label="Contraseña" toggleable autocomplete="current-password" name="password" formControlName="password" />
2459
+ *
2460
+ * `min`, `max`, `step` y `maxlength` se reenvían al `<input>` nativo (mismo
2461
+ * motivo: un atributo en el host no llega adentro) y sin valor no se
2462
+ * renderiza ningún atributo. `min`/`max`/`step` aceptan número o texto según
2463
+ * el `type` (`number`, `range`, `date`, `time`, `month`…): con `type="date"` el
2464
+ * límite es una fecha ISO. `maxlength` es un entero positivo y aplica a los
2465
+ * tipos de texto (`text`, `search`, `email`, `tel`, `url`, `password`). El
2466
+ * navegador usa los límites para la validación nativa (`:invalid`,
2467
+ * `validity.rangeUnderflow`) y para el selector de fechas; no reemplazan la
2468
+ * validación del formulario ni el `errorMessage`.
2469
+ *
2470
+ * <kf-input type="date" label="Fecha de entrega" min="2026-01-01" max="2026-12-31" />
2471
+ * <kf-input type="number" label="Cantidad" [min]="1" [max]="20" [step]="1" />
2472
+ * <kf-input label="Placa" [maxlength]="7" />
2101
2473
  */
2102
2474
  declare class Input implements ControlValueAccessor, AfterViewInit {
2103
2475
  private static nextId;
@@ -2136,6 +2508,14 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
2136
2508
  /** Sugiere el teclado virtual (`numeric`, `email`, `tel`, etc.) sin cambiar
2137
2509
  * el `type`. Sin valor, el atributo no se renderiza. */
2138
2510
  readonly inputmode: _angular_core.InputSignal<string | null | undefined>;
2511
+ /** Límite inferior del control (`min` nativo): número, o texto para fechas/horas (`'2026-01-01'`). */
2512
+ readonly min: _angular_core.InputSignalWithTransform<string | number | null, InputBound>;
2513
+ /** Límite superior del control (`max` nativo). Ver `min`. */
2514
+ readonly max: _angular_core.InputSignalWithTransform<string | number | null, InputBound>;
2515
+ /** Paso del control (`step` nativo): número o `'any'`. */
2516
+ readonly step: _angular_core.InputSignalWithTransform<string | number | null, InputBound>;
2517
+ /** Largo máximo del texto (`maxlength` nativo), entero positivo. Solo aplica a tipos de texto. */
2518
+ readonly maxlength: _angular_core.InputSignalWithTransform<number | null, string | number | null | undefined>;
2139
2519
  /** Agrega el botón de mostrar/ocultar — sin efecto si `type` no es `"password"`. */
2140
2520
  readonly toggleable: _angular_core.InputSignalWithTransform<boolean, unknown>;
2141
2521
  /** Nombre accesible del `<input>` cuando no hay `label` visible. Ignorado
@@ -2195,7 +2575,7 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
2195
2575
  */
2196
2576
  protected onTogglePasswordVisibility(): void;
2197
2577
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Input, never>;
2198
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Input, "kf-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "inputmode": { "alias": "inputmode"; "required": false; "isSignal": true; }; "toggleable": { "alias": "toggleable"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; }, { "cleared": "cleared"; }, never, never, true, never>;
2578
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Input, "kf-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "inputmode": { "alias": "inputmode"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "toggleable": { "alias": "toggleable"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; }, { "cleared": "cleared"; }, never, never, true, never>;
2199
2579
  }
2200
2580
 
2201
2581
  type JourneyStepStatus = 'done' | 'current' | 'delayed' | 'pending';
@@ -2508,6 +2888,14 @@ declare class ListToolbar {
2508
2888
  * <kf-metric-card label="Saldo Pendiente" value="$45,000">
2509
2889
  * <kf-button actions variant="primary" size="sm">Pagar Ahora</kf-button>
2510
2890
  * </kf-metric-card>
2891
+ *
2892
+ * `loading` (default `false`): dibuja el esqueleto de la card — etiqueta,
2893
+ * ícono, valor y `foot` como bloques del alto real de cada línea — dentro del
2894
+ * mismo `kf-card`, y reserva (sin mostrar) el espacio de las acciones, así que
2895
+ * al llegar los datos no hay salto de layout. Pasa los mismos inputs que
2896
+ * usarás cargada. Marca el host con `aria-busy="true"`.
2897
+ *
2898
+ * <kf-metric-card label="Tickets abiertos" value="11" foot="+2 hoy" [loading]="isLoading()" />
2511
2899
  */
2512
2900
  declare class MetricCard {
2513
2901
  readonly label: _angular_core.InputSignal<string>;
@@ -2520,8 +2908,132 @@ declare class MetricCard {
2520
2908
  readonly valueColor: _angular_core.InputSignal<string | undefined>;
2521
2909
  /** Badge de esquina opcional, pegado al valor (ej. "+2%"). */
2522
2910
  readonly badge: _angular_core.InputSignal<string | undefined>;
2911
+ /** Dibuja el esqueleto en lugar del contenido, conservando las dimensiones. */
2912
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
2523
2913
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MetricCard, never>;
2524
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MetricCard, "kf-metric-card", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "unit": { "alias": "unit"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "foot": { "alias": "foot"; "required": false; "isSignal": true; }; "valueColor": { "alias": "valueColor"; "required": false; "isSignal": true; }; "badge": { "alias": "badge"; "required": false; "isSignal": true; }; }, {}, never, ["[actions]"], true, never>;
2914
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MetricCard, "kf-metric-card", never, { "label": { "alias": "label"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "unit": { "alias": "unit"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "foot": { "alias": "foot"; "required": false; "isSignal": true; }; "valueColor": { "alias": "valueColor"; "required": false; "isSignal": true; }; "badge": { "alias": "badge"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, {}, never, ["[actions]"], true, never>;
2915
+ }
2916
+
2917
+ /** Estado de avance de una etapa o hito; nunca se comunica solo con color. */
2918
+ type ProgressStatus = 'done' | 'current' | 'pending';
2919
+ declare const PROGRESS_STATUS: {
2920
+ readonly DONE: "done";
2921
+ readonly CURRENT: "current";
2922
+ readonly PENDING: "pending";
2923
+ };
2924
+ /**
2925
+ * Texto por defecto (español) de cada estado: el estado nunca se comunica solo
2926
+ * con color. Los componentes que lo muestran aceptan sus propios textos.
2927
+ */
2928
+ declare const PROGRESS_STATUS_LABEL: {
2929
+ readonly done: "Completado";
2930
+ readonly current: "En curso";
2931
+ readonly pending: "Pendiente";
2932
+ };
2933
+
2934
+ /**
2935
+ * Hito de una etapa. `date` llega ya formateada; `exception` excluye el hito
2936
+ * del avance (se muestra en un bloque aparte y solo si ocurrió).
2937
+ */
2938
+ interface MilestoneItem {
2939
+ id: string;
2940
+ label: string;
2941
+ done: boolean;
2942
+ date?: string;
2943
+ exception?: boolean;
2944
+ }
2945
+ /**
2946
+ * Etapa expandible de la línea de tiempo. `date` llega ya formateada y solo
2947
+ * aplica si la etapa está completada. Una etapa sin `items` no es expandible.
2948
+ */
2949
+ interface MilestoneGroup {
2950
+ id: string;
2951
+ label: string;
2952
+ status: ProgressStatus;
2953
+ icon: IconName;
2954
+ date?: string;
2955
+ items: readonly MilestoneItem[];
2956
+ }
2957
+ /** Textos de `kf-milestone-timeline`; todos tienen valor por defecto en español. */
2958
+ interface MilestoneTimelineLabels {
2959
+ heading: string;
2960
+ expandAll: string;
2961
+ collapseAll: string;
2962
+ statusDone: string;
2963
+ statusPending: string;
2964
+ /** Texto de una etapa en curso; recibe los hitos completados y el total que cuenta en el avance. */
2965
+ currentMeta: (done: number, total: number) => string;
2966
+ /** Insignia del hito destacado como el siguiente a completar. */
2967
+ next: string;
2968
+ exceptionsTitle: string;
2969
+ noExceptions: string;
2970
+ /** Texto solo para lectores de pantalla tras un hito completado. */
2971
+ itemDone: string;
2972
+ /** Texto solo para lectores de pantalla tras un hito pendiente. */
2973
+ itemPending: string;
2974
+ }
2975
+ declare const DEFAULT_MILESTONE_TIMELINE_LABELS: MilestoneTimelineLabels;
2976
+
2977
+ /**
2978
+ * Línea de tiempo de etapas con hitos. Cada etapa es un encabezado expandible
2979
+ * (`aria-expanded`/`aria-controls`) con un panel de hitos y, si la etapa tiene
2980
+ * hitos de excepción, un bloque aparte que no cuenta en el avance. Una etapa
2981
+ * sin hitos es solo informativa (no es un botón).
2982
+ *
2983
+ * El estado nunca se comunica solo con color: cada etapa y cada hito llevan su
2984
+ * estado en texto (visible o solo para lectores de pantalla) y los nodos y
2985
+ * marcas lo dibujan también con la forma. Todos los textos salen de `labels`
2986
+ * (español por defecto) y las fechas llegan ya formateadas.
2987
+ *
2988
+ * El conector entre etapas se deriva del tamaño del nodo
2989
+ * (`--kf-status-node-size`, default `2.125rem`) y de la separación del
2990
+ * encabezado: cambiar el tamaño del nodo mueve la línea con él.
2991
+ *
2992
+ * <kf-milestone-timeline
2993
+ * [groups]="stages()"
2994
+ * [(expandedIds)]="expanded"
2995
+ * nextItemId="stage2-docs"
2996
+ * ariaLabel="Avance de la entrega"
2997
+ * [labels]="{ heading: 'Progress', expandAll: 'Expand all' }"
2998
+ * />
2999
+ */
3000
+ declare class MilestoneTimeline {
3001
+ private readonly host;
3002
+ private readonly instanceId;
3003
+ readonly groups: _angular_core.InputSignal<readonly MilestoneGroup[]>;
3004
+ /** Ids de las etapas expandidas, two-way: `[(expandedIds)]`. El padre controla el estado inicial. */
3005
+ readonly expandedIds: _angular_core.ModelSignal<readonly string[]>;
3006
+ /** Id del hito que se destaca como el siguiente a completar. */
3007
+ readonly nextItemId: _angular_core.InputSignal<string | undefined>;
3008
+ /** Textos; los que no se pasen usan el español por defecto. */
3009
+ readonly labels: _angular_core.InputSignal<Partial<MilestoneTimelineLabels>>;
3010
+ /** Nombre accesible de la lista de etapas. */
3011
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
3012
+ /** Nivel (2-6) del título "Avance por etapa", para respetar el esquema de títulos de la página. */
3013
+ readonly headingLevel: _angular_core.InputSignal<2 | 3 | 4 | 5 | 6>;
3014
+ protected readonly text: _angular_core.Signal<MilestoneTimelineLabels>;
3015
+ protected readonly rows: _angular_core.Signal<{
3016
+ group: MilestoneGroup;
3017
+ main: MilestoneItem[];
3018
+ exceptions: MilestoneItem[];
3019
+ happened: MilestoneItem[];
3020
+ expandable: boolean;
3021
+ meta: string;
3022
+ }[]>;
3023
+ private readonly expandableIds;
3024
+ protected readonly hasExpandable: _angular_core.Signal<boolean>;
3025
+ protected readonly allExpanded: _angular_core.Signal<boolean>;
3026
+ protected isExpanded(groupId: string): boolean;
3027
+ protected headId(groupId: string): string;
3028
+ protected panelId(groupId: string): string;
3029
+ protected itemStatus(item: MilestoneItem): 'done' | 'pending';
3030
+ protected toggle(groupId: string): void;
3031
+ protected toggleAll(): void;
3032
+ /** Lleva el foco al encabezado de una etapa expandible; devuelve el elemento, o `null` si no existe o no es expandible. */
3033
+ focusGroup(groupId: string): HTMLElement | null;
3034
+ private metaOf;
3035
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MilestoneTimeline, never>;
3036
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MilestoneTimeline, "kf-milestone-timeline", never, { "groups": { "alias": "groups"; "required": true; "isSignal": true; }; "expandedIds": { "alias": "expandedIds"; "required": false; "isSignal": true; }; "nextItemId": { "alias": "nextItemId"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; }, { "expandedIds": "expandedIdsChange"; }, never, never, true, never>;
2525
3037
  }
2526
3038
 
2527
3039
  /**
@@ -2918,6 +3430,140 @@ declare class Panel {
2918
3430
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Panel, "kf-panel", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; "actionHref": { "alias": "actionHref"; "required": false; "isSignal": true; }; }, { "actionClick": "actionClick"; }, never, ["*"], true, never>;
2919
3431
  }
2920
3432
 
3433
+ type PopoverPlacement = 'top' | 'bottom' | 'left' | 'right';
3434
+ /**
3435
+ * Popover de contenido enriquecido anclado a un elemento — la contraparte de
3436
+ * `kfTooltip` para cuando el texto plano no alcanza (varias líneas, énfasis,
3437
+ * un desglose, enlaces). Mismo mecanismo de `@angular/cdk/overlay`. El host
3438
+ * sigue siendo el elemento que recibe el foco: la directiva no lo hace
3439
+ * focusable, así que va sobre un `<button>`, un `<a>` o un elemento con
3440
+ * `tabindex="0"`.
3441
+ *
3442
+ * <button [kfPopover]="detail" kfPopoverPlacement="top">Etapa</button>
3443
+ * <ng-template #detail><strong>Recepción</strong><p>Completada el 12/05.</p></ng-template>
3444
+ *
3445
+ * Apertura: puntero (hover, tras `kfPopoverShowDelay` ms; NO se abre con puntero
3446
+ * táctil) y foco de teclado (al instante, solo si el foco es visible: un
3447
+ * clic con el mouse no lo abre). Cierre: Escape (descarta el panel hasta que
3448
+ * el puntero y el foco salgan y vuelvan), salida del puntero tras
3449
+ * `kfPopoverHideDelay` ms, pérdida de foco, scroll de cualquier contenedor y
3450
+ * redimensionado de la ventana. El panel se reposiciona dentro del viewport
3451
+ * (invierte el lado si no cabe).
3452
+ *
3453
+ * Con `kfPopoverInteractive`, el puntero puede entrar al panel sin cerrarlo y
3454
+ * el panel es un `dialog` no modal: Tab desde el anfitrión entra al primer
3455
+ * control del panel y Mayús+Tab desde ese control vuelve al anfitrión. Sin
3456
+ * `kfPopoverInteractive` (default), el panel es un `tooltip` que no captura
3457
+ * el puntero y no debe contener controles.
3458
+ *
3459
+ * Si el anfitrión no es interactivo pero vive dentro de un control (un botón,
3460
+ * un enlace, un elemento con `tabindex`), los eventos de puntero, foco y
3461
+ * teclado se escuchan en ese control y el panel se ancla al anfitrión. Es el
3462
+ * caso de un indicador dentro de una celda interactiva de `kf-data-table`:
3463
+ *
3464
+ * <ng-template #stageCell let-row>
3465
+ * <span [kfPopover]="detail"><kf-status-mark [status]="row.status" /></span>
3466
+ * </ng-template>
3467
+ *
3468
+ * Accesibilidad: mientras está abierto, el elemento que recibe el foco
3469
+ * referencia el panel con `aria-describedby` (se conserva cualquier valor
3470
+ * previo).
3471
+ */
3472
+ declare class PopoverDirective implements OnDestroy {
3473
+ /** Contenido del popover (un `ng-template`). `null`/`undefined` = no se abre. */
3474
+ readonly kfPopover: _angular_core.InputSignal<TemplateRef<unknown> | null | undefined>;
3475
+ /** Lado preferido; si no cabe en el viewport, se invierte. Default `bottom`. */
3476
+ readonly kfPopoverPlacement: _angular_core.InputSignal<PopoverPlacement>;
3477
+ /** Retardo (ms) antes de abrir con el puntero. El foco de teclado abre sin retardo. */
3478
+ readonly kfPopoverShowDelay: _angular_core.InputSignalWithTransform<number, unknown>;
3479
+ /** Retardo (ms) antes de cerrar al salir el puntero. */
3480
+ readonly kfPopoverHideDelay: _angular_core.InputSignalWithTransform<number, unknown>;
3481
+ /** Desactiva el popover (y lo cierra si estaba abierto). */
3482
+ readonly kfPopoverDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
3483
+ /** Permite que el puntero entre al panel sin cerrarlo y que el teclado llegue a sus controles. */
3484
+ readonly kfPopoverInteractive: _angular_core.InputSignalWithTransform<boolean, unknown>;
3485
+ /** Nombre accesible del panel cuando es `interactive` (rol `dialog`). */
3486
+ readonly kfPopoverLabel: _angular_core.InputSignal<string | null>;
3487
+ /** Emite `true` al abrirse y `false` al cerrarse. */
3488
+ readonly kfPopoverOpenChange: _angular_core.OutputEmitterRef<boolean>;
3489
+ private readonly host;
3490
+ private readonly overlayService;
3491
+ private readonly viewContainerRef;
3492
+ private readonly injector;
3493
+ private readonly document;
3494
+ private readonly destroyRef;
3495
+ private readonly panelId;
3496
+ private readonly openState;
3497
+ /** `true` mientras el panel está abierto. */
3498
+ readonly isOpen: _angular_core.Signal<boolean>;
3499
+ /**
3500
+ * Elemento que recibe los eventos de puntero, foco y teclado: el propio
3501
+ * anfitrión o, si este no es interactivo pero vive dentro de un control
3502
+ * (botón, enlace, `tabindex`), ese control. `aria-describedby` va en él.
3503
+ */
3504
+ private trigger;
3505
+ private overlayRef;
3506
+ private panelElement;
3507
+ private showTimer;
3508
+ private hideTimer;
3509
+ private openedAt;
3510
+ private teardownGlobalListeners;
3511
+ private destroyed;
3512
+ private pointerOnHost;
3513
+ private pointerOnPanel;
3514
+ private focusOnHost;
3515
+ private focusOnPanel;
3516
+ /** Escape lo descartó: no reabre hasta que puntero y foco hayan salido. */
3517
+ private dismissed;
3518
+ constructor();
3519
+ ngOnDestroy(): void;
3520
+ /** Cierra el panel de inmediato, sin retardo. */
3521
+ close(): void;
3522
+ private readonly onHostPointerEnter;
3523
+ private readonly onHostPointerLeave;
3524
+ private readonly onHostFocusIn;
3525
+ private readonly onHostFocusOut;
3526
+ private readonly onHostKeydown;
3527
+ private get wanted();
3528
+ /** Abre o cierra según los cuatro orígenes (puntero/foco × anfitrión/panel). */
3529
+ private reevaluate;
3530
+ private scheduleOpen;
3531
+ private scheduleClose;
3532
+ private open;
3533
+ private dispose;
3534
+ private onPanelFocusOut;
3535
+ /** Mayús+Tab desde el primer control del panel devuelve el foco al anfitrión. */
3536
+ private readonly onPanelKeydown;
3537
+ private focusHost;
3538
+ /**
3539
+ * Escape, scroll y resize mientras el panel está abierto. En fase de captura
3540
+ * y sobre `document`: `scroll` no burbujea (hay que capturarlo para ver el
3541
+ * de cualquier contenedor) y Escape debe cerrar primero el popover sin
3542
+ * llegar al modal o drawer que lo contenga.
3543
+ */
3544
+ private listenGlobal;
3545
+ private resolveTrigger;
3546
+ /** Foco de teclado (`:focus-visible`); sin soporte del selector, se asume teclado. */
3547
+ private isKeyboardFocus;
3548
+ private addDescribedBy;
3549
+ private removeDescribedBy;
3550
+ private describedByTokens;
3551
+ private clearShowTimer;
3552
+ private clearHideTimer;
3553
+ private clearTimers;
3554
+ /**
3555
+ * Posiciones en orden de preferencia: el lado pedido (centrado, luego
3556
+ * alineado al inicio y al final del anfitrión), el lado opuesto con las
3557
+ * mismas tres alineaciones y, por último, los dos lados perpendiculares.
3558
+ * Así un anfitrión pegado a una esquina encuentra una posición que cabe
3559
+ * entera en vez de depender solo del empuje al viewport.
3560
+ */
3561
+ private positionsFor;
3562
+ private positionFor;
3563
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<PopoverDirective, never>;
3564
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<PopoverDirective, "[kfPopover]", ["kfPopover"], { "kfPopover": { "alias": "kfPopover"; "required": true; "isSignal": true; }; "kfPopoverPlacement": { "alias": "kfPopoverPlacement"; "required": false; "isSignal": true; }; "kfPopoverShowDelay": { "alias": "kfPopoverShowDelay"; "required": false; "isSignal": true; }; "kfPopoverHideDelay": { "alias": "kfPopoverHideDelay"; "required": false; "isSignal": true; }; "kfPopoverDisabled": { "alias": "kfPopoverDisabled"; "required": false; "isSignal": true; }; "kfPopoverInteractive": { "alias": "kfPopoverInteractive"; "required": false; "isSignal": true; }; "kfPopoverLabel": { "alias": "kfPopoverLabel"; "required": false; "isSignal": true; }; }, { "kfPopoverOpenChange": "kfPopoverOpenChange"; }, never, never, true, never>;
3565
+ }
3566
+
2921
3567
  /** Un ítem de navegación de la barra de marca. `icon` es opcional y solo se
2922
3568
  * usa en el drawer mobile (columna, ver template) — el `<nav>` horizontal de
2923
3569
  * escritorio se mantiene solo texto, sin ícono ni chevron. */
@@ -3052,9 +3698,12 @@ declare class PortalHeader {
3052
3698
  * que no aplican a un valor de progreso): `neutral` es el color de marca
3053
3699
  * por defecto (sin implicar buen/mal estado), `primary` es el color
3054
3700
  * primario para un avance de proceso (ej. una carga), y `ok`/`warn`/`error`
3055
- * sí comunican severidad. La librería no conoce el dominio que produce ese
3701
+ * sí comunican severidad. `purple` es el acento morado de marca, igual al tono
3702
+ * `purple` de `kf-stat-card`. La librería no conoce el dominio que produce ese
3056
3703
  * valor (SLA, storage, lo que sea) — el consumidor decide qué tone usar. */
3057
- type ProgressTone = 'neutral' | 'primary' | 'ok' | 'warn' | 'error';
3704
+ type ProgressTone = 'neutral' | 'primary' | 'ok' | 'warn' | 'error' | 'purple';
3705
+ /** Grosor de la pista: `sm` 4px (el histórico), `md` 8px, `lg` 12px. */
3706
+ type ProgressSize = 'sm' | 'md' | 'lg';
3058
3707
  /**
3059
3708
  * Barra de progreso de un solo valor (0-100%) con color por severidad —
3060
3709
  * para un porcentaje simple, a diferencia de `kf-bucket-progress`, que
@@ -3065,16 +3714,24 @@ type ProgressTone = 'neutral' | 'primary' | 'ok' | 'warn' | 'error';
3065
3714
  *
3066
3715
  * `value` se clampea a [0, 100] — un consumidor que calcule un ratio fuera
3067
3716
  * de rango (ej. tiempo transcurrido sobre un SLA ya vencido) no rompe el
3068
- * ancho de la barra. `label` es texto libre opcional sobre la barra (ej.
3717
+ * ancho de la barra. `size` cambia el grosor de la pista (`sm` 4px, `md` 8px,
3718
+ * `lg` 12px; sin él, 4px como siempre); el `role="progressbar"` y sus valores
3719
+ * accesibles no cambian. `label` es texto libre opcional sobre la barra (ej.
3069
3720
  * "80%"); sin él, no se renderiza ningún texto, solo la barra.
3070
3721
  */
3071
3722
  declare class Progress {
3072
3723
  readonly value: _angular_core.InputSignal<number>;
3073
3724
  readonly tone: _angular_core.InputSignal<ProgressTone>;
3725
+ /** Grosor de la pista. Default `sm` (4px). */
3726
+ readonly size: _angular_core.InputSignal<ProgressSize>;
3074
3727
  readonly label: _angular_core.InputSignal<string | undefined>;
3728
+ /** Nombre accesible de la barra (`aria-label`). Sin él, el `progressbar`
3729
+ * queda sin nombre: dalo siempre que el contexto no lo nombre ya (por
3730
+ * ejemplo con un `label` visible asociado). */
3731
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
3075
3732
  protected readonly clampedValue: _angular_core.Signal<number>;
3076
3733
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Progress, never>;
3077
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Progress, "kf-progress", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3734
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Progress, "kf-progress", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3078
3735
  }
3079
3736
 
3080
3737
  /**
@@ -3402,7 +4059,7 @@ declare class Select {
3402
4059
  readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
3403
4060
  /** Mensaje de error con `role="alert"`, debajo del trigger. */
3404
4061
  readonly errorMessage: _angular_core.InputSignal<string | undefined>;
3405
- readonly variant: _angular_core.InputSignal<"compact" | "field">;
4062
+ readonly variant: _angular_core.InputSignal<"field" | "compact">;
3406
4063
  /**
3407
4064
  * Ancho del control. 'md' (240px) es el default histórico y preserva el
3408
4065
  * comportamiento actual sin cambios para consumidores existentes.
@@ -3468,12 +4125,16 @@ declare class Select {
3468
4125
  private readonly overlay;
3469
4126
  constructor();
3470
4127
  /**
3471
- * Respaldo de `overlayRef.keydownEvents()`: ese observable del CDK solo ve
3472
- * teclas presionadas con el foco DENTRO del pane del overlay. Si el foco
3473
- * sigue en el trigger (o en cualquier otro lado de la página) mientras el
3474
- * panel está abierto, `keydownEvents()` nunca dispara.
4128
+ * Escape con el panel abierto, escuchado en fase de captura sobre
4129
+ * `document` (ver `listenEscapeCapture`). Respaldo de
4130
+ * `overlayRef.keydownEvents()`: ese observable del CDK solo ve teclas
4131
+ * presionadas con el foco DENTRO del pane del overlay; si el foco sigue en
4132
+ * el trigger (o en cualquier otro lado) mientras el panel está abierto,
4133
+ * nunca dispara. Consume la tecla (`preventDefault`) solo si había un
4134
+ * panel que cerrar, así un `kf-drawer`/`kf-modal` que contenga al select
4135
+ * no se cierra con el mismo Escape. Devuelve si cerró algo.
3475
4136
  */
3476
- onDocumentEscape(): void;
4137
+ onDocumentEscape(): boolean;
3477
4138
  toggle(): void;
3478
4139
  /** Abre el panel con la opción seleccionada como activa (o la primera). */
3479
4140
  open(): void;
@@ -3714,7 +4375,7 @@ declare class Spinner {
3714
4375
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Spinner, "kf-spinner", never, { "size": { "alias": "size"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "onDark": { "alias": "onDark"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
3715
4376
  }
3716
4377
 
3717
- type StatCardTone = 'primary' | 'success' | 'error' | 'purple';
4378
+ type StatCardTone = 'primary' | 'success' | 'error' | 'purple' | 'warn' | 'info' | 'neutral';
3718
4379
  /**
3719
4380
  * Card de estadística horizontal: ícono circular grande a la izquierda,
3720
4381
  * valor + label + nota apilados al centro, chevron opcional al final si es
@@ -3723,6 +4384,31 @@ type StatCardTone = 'primary' | 'success' | 'error' | 'purple';
3723
4384
  * otorgados", "Cortesías otorgadas"), no una variante de la misma card.
3724
4385
  *
3725
4386
  * <kf-stat-card icon="gift" tone="purple" value="4" label="Bonos otorgados" note="$15,000.00 en beneficios" (cardClick)="onNavigate('beneficios')" />
4387
+ *
4388
+ * Extensiones opcionales (la card sin ellas se ve y se comporta como siempre):
4389
+ * - `tone`: además de `primary|success|error|purple`, `warn`, `info` y `neutral`.
4390
+ * - `bar` (0-100): barra de progreso accesible (`kf-progress`, `role="progressbar"`
4391
+ * con `aria-valuenow`/`min`/`max` y el `label` como nombre) bajo la nota. Se
4392
+ * acota a [0, 100]; `null`/`undefined` no la dibuja. Es un refuerzo visual:
4393
+ * el valor exacto conviene darlo también en texto (`hint`), porque el relleno
4394
+ * de algunos tonos de `kf-progress` tiene poco contraste con su pista.
4395
+ * - `hint`: texto secundario bajo la barra (ej. "12 de 20 completadas").
4396
+ * - `pressed` (`boolean | null`): con `clickable`, la card es un botón de
4397
+ * alternancia (`aria-pressed`), útil como filtro. `null` (default) = no
4398
+ * aplica y no emite el atributo. Sin `clickable` no tiene efecto.
4399
+ *
4400
+ * <kf-stat-card icon="clock" tone="warn" value="7" label="Por vencer" [bar]="35" hint="7 de 20"
4401
+ * clickable [pressed]="filter() === 'due'" (cardClick)="toggle('due')" />
4402
+ *
4403
+ * `loading` (default `false`): mientras es `true` la card dibuja su esqueleto
4404
+ * en vez del contenido, con el MISMO cascarón (borde, padding, ícono de 50px)
4405
+ * y líneas del alto real de cada texto — valor, etiqueta y, si se pasaron,
4406
+ * nota, barra y `hint` —, así que al llegar los datos no hay salto de
4407
+ * layout. Pasa los mismos inputs que usarás cargada para que el esqueleto
4408
+ * reserve las mismas líneas. Marca la card con `aria-busy="true"`, no es
4409
+ * clicable ni expone su texto a lectores de pantalla mientras carga.
4410
+ *
4411
+ * <kf-stat-card icon="clock" value="7" label="Por vencer" note="Esta semana" [loading]="isLoading()" />
3726
4412
  */
3727
4413
  declare class StatCard {
3728
4414
  readonly icon: _angular_core.InputSignal<IconName>;
@@ -3730,11 +4416,24 @@ declare class StatCard {
3730
4416
  readonly value: _angular_core.InputSignal<string | number>;
3731
4417
  readonly label: _angular_core.InputSignal<string>;
3732
4418
  readonly note: _angular_core.InputSignal<string | undefined>;
4419
+ /** Avance 0-100 (barra de progreso accesible); `null`/`undefined` = sin barra. */
4420
+ readonly bar: _angular_core.InputSignal<number | null | undefined>;
4421
+ /** Texto secundario bajo la barra (o bajo la nota si no hay barra). */
4422
+ readonly hint: _angular_core.InputSignal<string | undefined>;
4423
+ /**
4424
+ * Estado de alternancia (`aria-pressed`) cuando la card es `clickable`.
4425
+ * `null` (default) = no aplica: el atributo no se emite.
4426
+ */
4427
+ readonly pressed: _angular_core.InputSignal<boolean | null>;
4428
+ /** Dibuja el esqueleto en lugar del contenido, conservando las dimensiones. */
4429
+ readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
3733
4430
  /** Si se escucha `cardClick`, la card se renderiza como botón clickeable con chevron. */
3734
4431
  readonly clickable: _angular_core.InputSignalWithTransform<boolean, unknown>;
3735
4432
  readonly cardClick: _angular_core.OutputEmitterRef<void>;
4433
+ protected readonly barTone: _angular_core.Signal<ProgressTone>;
4434
+ protected readonly hasBar: _angular_core.Signal<boolean>;
3736
4435
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatCard, never>;
3737
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatCard, "kf-stat-card", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "note": { "alias": "note"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, never, true, never>;
4436
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatCard, "kf-stat-card", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": true; "isSignal": true; }; "note": { "alias": "note"; "required": false; "isSignal": true; }; "bar": { "alias": "bar"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "pressed": { "alias": "pressed"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, never, true, never>;
3738
4437
  }
3739
4438
 
3740
4439
  /** Vocabulario semántico único de tono, compartido con `TextTone`. */
@@ -3792,6 +4491,57 @@ declare class StatTile {
3792
4491
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatTile, "kf-stat-tile", never, { "cta": { "alias": "cta"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "note": { "alias": "note"; "required": false; "isSignal": true; }; "notePlaceholder": { "alias": "notePlaceholder"; "required": false; "isSignal": true; }; "valueMissing": { "alias": "valueMissing"; "required": false; "isSignal": true; }; "hasProjectedValue": { "alias": "hasProjectedValue"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; "actionHref": { "alias": "actionHref"; "required": false; "isSignal": true; }; }, { "actionClick": "actionClick"; }, never, ["[valueContent]"], true, never>;
3793
4492
  }
3794
4493
 
4494
+ /**
4495
+ * Marca pequeña de estado para leyendas y listas de hitos: círculo relleno
4496
+ * con check (completado), anillo con punto (en curso) o anillo vacío
4497
+ * (pendiente). La forma comunica el estado y el color solo lo refuerza.
4498
+ * `exception` la pinta con borde discontinuo y tono de aviso.
4499
+ *
4500
+ * Es decorativa por defecto (`aria-hidden`): el texto del estado va en el
4501
+ * contexto que la usa. Para usarla suelta (ej. una leyenda sin texto al lado),
4502
+ * `label` la expone como imagen con ese nombre.
4503
+ *
4504
+ * <kf-status-mark status="done" small />
4505
+ * <kf-status-mark status="current" label="En curso" />
4506
+ *
4507
+ * Tamaño: variables CSS `--kf-status-mark-size` y `--kf-status-mark-size-sm`.
4508
+ */
4509
+ declare class StatusMark {
4510
+ readonly status: _angular_core.InputSignal<ProgressStatus>;
4511
+ /** Versión reducida, para listas de hitos. */
4512
+ readonly small: _angular_core.InputSignal<boolean>;
4513
+ /** Hito de excepción: borde discontinuo y tono de aviso. */
4514
+ readonly exception: _angular_core.InputSignal<boolean>;
4515
+ /** Nombre accesible; sin él la marca es decorativa. */
4516
+ readonly label: _angular_core.InputSignal<string | null>;
4517
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusMark, never>;
4518
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusMark, "kf-status-mark", never, { "status": { "alias": "status"; "required": true; "isSignal": true; }; "small": { "alias": "small"; "required": false; "isSignal": true; }; "exception": { "alias": "exception"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
4519
+ }
4520
+
4521
+ /**
4522
+ * Nodo circular de una etapa: ícono de la etapa más una insignia de estado.
4523
+ * La forma comunica el estado (relleno con check, anillo con punto, anillo
4524
+ * vacío) y el color solo lo refuerza.
4525
+ *
4526
+ * Es decorativo por defecto (`aria-hidden`): el texto del estado debe estar en
4527
+ * el contexto que lo usa. Para usarlo suelto, `label` lo expone como imagen
4528
+ * con ese nombre.
4529
+ *
4530
+ * <kf-status-node status="current" icon="truck" />
4531
+ * <kf-status-node status="done" icon="check" size="sm" label="Entrega completada" />
4532
+ *
4533
+ * Tamaño: variables CSS `--kf-status-node-size` y `--kf-status-node-size-sm`.
4534
+ */
4535
+ declare class StatusNode {
4536
+ readonly status: _angular_core.InputSignal<ProgressStatus>;
4537
+ readonly icon: _angular_core.InputSignal<IconName>;
4538
+ readonly size: _angular_core.InputSignal<"sm" | "md">;
4539
+ /** Nombre accesible; sin él el nodo es decorativo. */
4540
+ readonly label: _angular_core.InputSignal<string | null>;
4541
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusNode, never>;
4542
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusNode, "kf-status-node", never, { "status": { "alias": "status"; "required": true; "isSignal": true; }; "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
4543
+ }
4544
+
3795
4545
  /**
3796
4546
  * Pill con borde, en mayúsculas y con letter-spacing, pensada para indicadores
3797
4547
  * de estado únicos y prominentes (ej. "ESTADO TÉCNICO"). El fondo es siempre
@@ -3801,7 +4551,7 @@ declare class StatTile {
3801
4551
  * <kf-status-pill tone="error" dot>Fuera de servicio</kf-status-pill>
3802
4552
  */
3803
4553
  declare class StatusPill {
3804
- readonly tone: _angular_core.InputSignal<"error" | "ok" | "warn" | "blue">;
4554
+ readonly tone: _angular_core.InputSignal<"ok" | "warn" | "error" | "blue">;
3805
4555
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
3806
4556
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusPill, never>;
3807
4557
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusPill, "kf-status-pill", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -4065,7 +4815,12 @@ interface ToastAction {
4065
4815
  interface ToastOptions {
4066
4816
  /** Color tone. Defaults to `'info'`. */
4067
4817
  tone?: ToastTone;
4068
- /** Milliseconds before auto-dismiss. Ignored when `tone` is `'loading'`. Defaults to `2800`. */
4818
+ /**
4819
+ * Milliseconds before auto-dismiss. Ignored when `tone` is `'loading'`. When
4820
+ * omitted it depends on the tone (see {@link TOAST_DEFAULT_DURATION_MS}):
4821
+ * `2800` for `success`/`info`, `5000` for `warning`, `8000` for `error`. An
4822
+ * explicit value always wins over the per-tone default.
4823
+ */
4069
4824
  duration?: number;
4070
4825
  /** Botón de acción opcional, ej. ir al registro sobre el que avisa el toast. */
4071
4826
  action?: ToastAction;
@@ -4085,6 +4840,13 @@ interface ToastState {
4085
4840
  leaving: boolean;
4086
4841
  action?: ToastAction;
4087
4842
  }
4843
+ /**
4844
+ * Auto-dismiss time per tone when the caller doesn't pass `duration`. Errors and
4845
+ * warnings stay longer than confirmations: they carry something to read and
4846
+ * act on, while a success only has to be noticed. `success`/`info` keep the
4847
+ * historical 2800ms. `loading` never auto-dismisses.
4848
+ */
4849
+ declare const TOAST_DEFAULT_DURATION_MS: Readonly<Record<Exclude<ToastTone, 'loading'>, number>>;
4088
4850
  /** What's currently holding the auto-dismiss timer paused. Tracked as a set so hover and
4089
4851
  * focus can overlap (e.g. mouse leaves while focus is still on the action button) without
4090
4852
  * resuming the timer early. */
@@ -4093,6 +4855,11 @@ type ToastPauseSource = 'hover' | 'focus';
4093
4855
  * Shows one toast at a time — a new `show()` call replaces whatever is
4094
4856
  * currently up (this mirrors a global status line, not a notification stack).
4095
4857
  *
4858
+ * Duration by tone (when `duration` isn't passed): `success`/`info` 2800ms,
4859
+ * `warning` 5000ms, `error` 8000ms (`TOAST_DEFAULT_DURATION_MS`); an explicit
4860
+ * `duration` always wins. The countdown pauses while the pointer or focus is
4861
+ * on the toast. Error toasts also get a larger, always-opaque close button.
4862
+ *
4096
4863
  * Angular has no global function that can mount UI on its own, so the
4097
4864
  * imperative `showToast(...)` of the reference design system becomes a
4098
4865
  * root-provided service holding signal state: `ToastService.show(...)` sets
@@ -4271,5 +5038,5 @@ declare class ViewToggle {
4271
5038
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ViewToggle, "kf-view-toggle", never, { "view": { "alias": "view"; "required": true; "isSignal": true; }; "iconOnly": { "alias": "iconOnly"; "required": false; "isSignal": true; }; "tableLabel": { "alias": "tableLabel"; "required": false; "isSignal": true; }; "cardsLabel": { "alias": "cardsLabel"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "viewChange": "viewChange"; }, never, never, true, never>;
4272
5039
  }
4273
5040
 
4274
- export { ActionTile, AdminBadge, Alert, AlertRow, Avatar, Badge, Breadcrumb, BucketProgress, Button, Calendar, Card, Carousel, CarouselSlide, Checkbox, Chip, Collapsible, ContactPopover, ContentSlot, ContentState, ContentViewer, DEFAULT_PAGE_SIZE_OPTIONS, DataTable, Divider, DocumentRow, Drawer, Dropdown, DropdownItem, DropdownPanel, EmptyState, EventTimeline, FeatureCard, Field, FieldLabel, Filter, FilterChips, FolderTabs, FolderTabsPanel, Footer, FormatInputDirective, Icon, Input, JourneyStepper, LIST_TOOLBAR_HYSTERESIS, Link, ListToolbar, MetricCard, Modal, MultiSelect, NoteBlock, OptionList, PageHeader, Pagination, Panel, PortalHeader, Progress, PulseDot, RowActions, SectionHeader, SectionNav, SectionNavItem, SectionNavSubsection, Segmented, Select, SelectableCardGroup, SidebarShell, Skeleton, Spinner, StatCard, StatTile, StatusPill, Tabs, Text, Textarea, TileGrid, TimeSlotPicker, ToastHost, ToastService, TooltipDirective, ViewToggle, dataTableViewSignal, resolveListToolbarMode };
4275
- export type { AlertRowTone, AlertTone, BreadcrumbItem, BucketProgressItem, CalendarDay, ContentStateKind, ContentStateLoad, ContentViewerType, DataTableCardRole, DataTableColumn, DataTableDensity, DataTableSort, DataTableView, DividerOrientation, DocumentRowTone, DrawerRole, DrawerSide, DropdownItemTone, DropdownPanelVariant, EmptyStateTone, EventTimelineItem, EventTimelineTone, FilterChipOption, FilterFieldChange, FilterFieldConfig, FilterFieldType, FilterValue, FolderTabOption, FooterLink, IconName, IconRotation, IconSize, JourneyStep, JourneyStepStatus, JourneyStepperColorScheme, JourneyStepperSurface, LinkVariant, ListToolbarMode, MultiSelectOption, NoteBlockTone, OptionListOption, PageHeaderTitleSize, PaginationItem, PortalHeaderAdminAction, PortalHeaderNavItem, ProgressTone, RowAction, RowActionKind, RowActionsMode, SectionNavSubsectionData, SegmentedOption, SelectOption, SelectableCardOption, SidebarNavItemData, SkeletonVariant, SpinnerSize, StatCardTone, StatTileTone, StatTileVariant, TabOption, TextAs, TextTone, TextVariant, TimeSlot, ToastAction, ToastOptions, ToastPromiseMessages, ToastState, ToastTone, TooltipPosition, ViewToggleOption };
5041
+ export { ActionTile, AdminBadge, Alert, AlertRow, Avatar, Badge, Breadcrumb, BucketProgress, Button, Calendar, Card, Carousel, CarouselSlide, Checkbox, Chip, Collapsible, ContactPopover, ContentSlot, ContentState, ContentStateLoading, ContentViewer, DATA_TABLE_MAX_SKELETON_ROWS, DEFAULT_MILESTONE_TIMELINE_LABELS, DEFAULT_PAGE_SIZE_OPTIONS, DataTable, Divider, DocumentRow, Drawer, Dropdown, DropdownItem, DropdownPanel, EmptyState, EventTimeline, FeatureCard, Field, FieldLabel, FileInput, Filter, FilterChips, FolderTabs, FolderTabsPanel, Footer, FormatInputDirective, Icon, Input, JourneyStepper, LIST_TOOLBAR_HYSTERESIS, Link, ListToolbar, MetricCard, MilestoneTimeline, Modal, MultiSelect, NoteBlock, OptionList, PROGRESS_STATUS, PROGRESS_STATUS_LABEL, PageHeader, Pagination, Panel, PopoverDirective, PortalHeader, Progress, PulseDot, RowActions, SKELETON_PRESET_MAX_COUNT, SectionHeader, SectionNav, SectionNavItem, SectionNavSubsection, Segmented, Select, SelectableCardGroup, SidebarShell, Skeleton, SkeletonPreset, Spinner, StatCard, StatTile, StatusMark, StatusNode, StatusPill, TOAST_DEFAULT_DURATION_MS, Tabs, Text, Textarea, TileGrid, TimeSlotPicker, ToastHost, ToastService, TooltipDirective, ViewToggle, dataTableViewSignal, formatFileSize, resolveListToolbarMode };
5042
+ export type { AlertRowTone, AlertTone, AlertVariant, BreadcrumbItem, BucketProgressItem, CalendarDay, ContentStateKind, ContentStateLoad, ContentViewerType, DataTableCardRole, DataTableCellClick, DataTableColumn, DataTableDensity, DataTableSort, DataTableView, DividerOrientation, DocumentRowTone, DrawerRole, DrawerSide, DropdownItemTone, DropdownPanelVariant, EmptyStateTone, EventTimelineItem, EventTimelineTone, FileRejection, FileRejectionReason, FilterChipOption, FilterFieldChange, FilterFieldConfig, FilterFieldType, FilterValue, FolderTabOption, FooterLink, IconName, IconRotation, IconSize, InputBound, JourneyStep, JourneyStepStatus, JourneyStepperColorScheme, JourneyStepperSurface, LinkVariant, ListToolbarMode, MilestoneGroup, MilestoneItem, MilestoneTimelineLabels, MultiSelectOption, NoteBlockTone, OptionListOption, PageHeaderTitleSize, PaginationItem, PopoverPlacement, PortalHeaderAdminAction, PortalHeaderNavItem, ProgressSize, ProgressStatus, ProgressTone, RowAction, RowActionKind, RowActionsMode, SectionNavSubsectionData, SegmentedOption, SelectOption, SelectableCardOption, SidebarNavItemData, SkeletonPresetVariant, SkeletonVariant, SpinnerSize, StatCardTone, StatTileTone, StatTileVariant, TabOption, TextAs, TextTone, TextVariant, TimeSlot, ToastAction, ToastOptions, ToastPromiseMessages, ToastState, ToastTone, TooltipPosition, ViewToggleOption };