@kaufmann-lab/ui 0.1.22 → 0.1.24

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.
@@ -261,7 +261,7 @@ declare class Alert {
261
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>;
262
262
  }
263
263
 
264
- type AlertRowTone = 'warn' | 'error';
264
+ type AlertRowTone = 'warn' | 'error' | 'neutral';
265
265
  /**
266
266
  * Fila clickeable de una lista de pendientes/alertas: ícono circular con
267
267
  * tono semántico, texto de una línea, chevron al final. Pensada para
@@ -269,14 +269,43 @@ type AlertRowTone = 'warn' | 'error';
269
269
  * dashboard) — no incluye el contenedor en sí.
270
270
  *
271
271
  * <kf-alert-row icon="file" tone="warn" text="2 cotizaciones esperan tu aprobación" (rowClick)="onNavigate('cotizaciones')" />
272
+ *
273
+ * Extensiones opcionales (la fila sin ellas se ve y se comporta como siempre):
274
+ * - `tone="neutral"`: ícono gris, para una fila sin urgencia ni alerta.
275
+ * - `value`: cifra alineada a la derecha, antes del chevron (ej. el conteo de
276
+ * pendientes). Admite `'—'` cuando no hay dato; en ese caso conviene pasar
277
+ * `valueLabel` con el texto que debe leer un lector de pantalla
278
+ * («Sin datos»), porque la raya sola no dice nada.
279
+ * - `valueLabel`: texto solo para lectores de pantalla que reemplaza a `value`
280
+ * en el árbol de accesibilidad; visualmente se sigue viendo `value`.
281
+ * - `tag`: etiqueta neutra pequeña junto al texto (ej. «Próximamente»).
282
+ * - `disabled`: la fila no es accionable — no emite `rowClick`, no entra en el
283
+ * orden de tabulación, no cambia al pasar el mouse, su chevron se oculta (conserva el
284
+ * espacio para alinear las cifras con las filas activas) y el
285
+ * texto y la cifra se atenúan (sin bajar el contraste de lectura). Expone
286
+ * `disabled` y `aria-disabled="true"`, así que un lector de pantalla la
287
+ * anuncia como no disponible en vez de omitirla.
288
+ *
289
+ * <kf-alert-row icon="file" tone="neutral" text="Documentos por firmar" tag="Próximamente" value="—" valueLabel="Sin datos todavía" disabled />
272
290
  */
273
291
  declare class AlertRow {
274
292
  readonly icon: _angular_core.InputSignal<IconName>;
275
293
  readonly tone: _angular_core.InputSignal<AlertRowTone>;
276
294
  readonly text: _angular_core.InputSignal<string>;
295
+ /** Cifra o texto corto alineado a la derecha (ej. `3`, `'—'`). */
296
+ readonly value: _angular_core.InputSignal<string | number | undefined>;
297
+ /** Texto solo para lectores de pantalla que reemplaza a `value` en el árbol de accesibilidad. */
298
+ readonly valueLabel: _angular_core.InputSignal<string | undefined>;
299
+ /** Etiqueta neutra junto al texto (ej. «Próximamente»). */
300
+ readonly tag: _angular_core.InputSignal<string | undefined>;
301
+ /** La fila no es accionable: sin clic, sin foco ni hover. */
302
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
277
303
  readonly rowClick: _angular_core.OutputEmitterRef<void>;
304
+ /** Emite `rowClick` salvo que la fila esté deshabilitada (también ante clics sintéticos). */
305
+ protected activate(): void;
306
+ protected hasValue(): boolean;
278
307
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AlertRow, never>;
279
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<AlertRow, "kf-alert-row", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; }, { "rowClick": "rowClick"; }, never, never, true, never>;
308
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AlertRow, "kf-alert-row", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "text": { "alias": "text"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "valueLabel": { "alias": "valueLabel"; "required": false; "isSignal": true; }; "tag": { "alias": "tag"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "rowClick": "rowClick"; }, never, never, true, never>;
280
309
  }
281
310
 
282
311
  /**
@@ -985,7 +1014,8 @@ type DataTableSort = `${string}:${'asc' | 'desc'}`;
985
1014
  * el selector, y `pageSizeChange` avisa cuando el usuario lo cambia.
986
1015
  *
987
1016
  * Ordenamiento por columna: cada `DataTableColumn` con `sortable: true`
988
- * vuelve su header clickeable, con el mismo formato `key:direction` que
1017
+ * vuelve su header un botón (Tab, Enter y Espacio) que expone el estado con
1018
+ * `aria-sort` (`ascending`/`descending`/`none`), con el mismo formato `key:direction` que
989
1019
  * usa `sort` de `kf-quote-picker` (two-way manual, no `model()` — el
990
1020
  * consumidor decide si persiste el valor o lo descarta al desmontar):
991
1021
  *
@@ -1133,6 +1163,16 @@ declare class DataTable<T = unknown> {
1133
1163
  /** Fuerza si la fila entera dispara `rowClick` en la vista de tabla —
1134
1164
  * ver `rowInteractive` para el cálculo automático cuando no se define. */
1135
1165
  readonly rowClickable: _angular_core.InputSignal<boolean | null>;
1166
+ /**
1167
+ * Con `false`, las filas interactivas de la vista de tabla dejan de ser
1168
+ * paradas de Tab (sin `tabindex`): útil cuando la fila es clickeable con el
1169
+ * mouse pero la acción accesible por teclado es un enlace o botón real
1170
+ * dentro de una celda — así una página de N filas no suma N paradas de Tab
1171
+ * sin rol. El clic con mouse sigue emitiendo `rowClick`. Default `true`
1172
+ * (comportamiento histórico). No afecta a las tarjetas, que son
1173
+ * `role="button"`.
1174
+ */
1175
+ readonly rowFocusable: _angular_core.InputSignal<boolean>;
1136
1176
  readonly rowClick: _angular_core.OutputEmitterRef<{
1137
1177
  row: T;
1138
1178
  index: number;
@@ -1229,6 +1269,8 @@ declare class DataTable<T = unknown> {
1229
1269
  * recortadas a la página actual. */
1230
1270
  protected readonly displayedRows: _angular_core.Signal<T[]>;
1231
1271
  protected sortDirectionFor(column: DataTableColumn): 'asc' | 'desc' | null;
1272
+ /** Valor de `aria-sort` del header de una columna ordenable. */
1273
+ protected ariaSortFor(column: DataTableColumn): 'ascending' | 'descending' | 'none';
1232
1274
  /** Ciclo asc → desc → sin orden, disparado al clickear un header `sortable`. */
1233
1275
  protected toggleSort(column: DataTableColumn): void;
1234
1276
  protected goToPage(target: number): void;
@@ -1304,6 +1346,13 @@ declare class DataTable<T = unknown> {
1304
1346
  * consumidor lo necesita.
1305
1347
  */
1306
1348
  readonly rowInteractive: _angular_core.Signal<boolean>;
1349
+ /**
1350
+ * La fila de la vista de tabla es parada de Tab solo si es interactiva,
1351
+ * `rowFocusable` lo permite y NO hay columnas `interactive`: con botones
1352
+ * propios por celda, la fila además de ellos duplicaría las paradas de Tab
1353
+ * (el clic de la fila sigue emitiendo `rowClick` con el mouse).
1354
+ */
1355
+ protected readonly rowTabStop: _angular_core.Signal<boolean>;
1307
1356
  setView(next: DataTableView): void;
1308
1357
  trackRow(row: T, index: number): string | number;
1309
1358
  /** Alineada al final: `align: 'end'` o el histórico `right: true`. */
@@ -1342,7 +1391,7 @@ declare class DataTable<T = unknown> {
1342
1391
  */
1343
1392
  protected measureStickyOffsets(): void;
1344
1393
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataTable<any>, 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>;
1394
+ 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; }; "rowFocusable": { "alias": "rowFocusable"; "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
1395
  }
1347
1396
 
1348
1397
  /** Forma de contenido que reproduce el preset. */
@@ -1424,6 +1473,12 @@ declare class ContentStateLoading {
1424
1473
  * Las acciones (reintentar, crear) van en el slot `actions` — se ignoran
1425
1474
  * mientras carga, porque no hay nada que reintentar todavía.
1426
1475
  *
1476
+ * Anuncios para lectores de pantalla: al cargar con silueta, `loadingLabel`
1477
+ * se anuncia en una región `status` (con `load="spinner"` ya lo anuncia el
1478
+ * propio `kf-spinner`); un error entra como `role="alert"` (interrumpe) y el
1479
+ * estado vacío como `role="status"` (cortés). `icon` dibuja el glifo de
1480
+ * `kf-empty-state` en esos dos estados.
1481
+ *
1427
1482
  * <kf-content-state [state]="state()" title="No pudimos cargar tus vehículos"
1428
1483
  * subtitle="Revisá tu conexión e intentá de nuevo.">
1429
1484
  * <kf-button actions (click)="retry()">Reintentar</kf-button>
@@ -1452,8 +1507,10 @@ declare class ContentState {
1452
1507
  /** Título de `empty`/`error`. Ignorado mientras carga. */
1453
1508
  readonly title: _angular_core.InputSignal<string>;
1454
1509
  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. */
1510
+ /** Glifo de `empty`/`error` (el mismo input de `kf-empty-state`). Sin valor, no se dibuja ícono. */
1511
+ readonly icon: _angular_core.InputSignal<IconName | undefined>;
1512
+ /** Texto de carga: visible al lado del spinner con `load="spinner"` y, en modo
1513
+ * skeleton, texto visualmente oculto con `role="status"` para lectores de pantalla. */
1457
1514
  readonly loadingLabel: _angular_core.InputSignal<string>;
1458
1515
  /** Plantilla propia del esqueleto (reemplaza las tres líneas genéricas). */
1459
1516
  readonly loadingTemplate: _angular_core.InputSignal<TemplateRef<unknown> | null>;
@@ -1463,7 +1520,7 @@ declare class ContentState {
1463
1520
  protected readonly projectedLoading: _angular_core.Signal<TemplateRef<any> | undefined>;
1464
1521
  protected readonly customLoading: _angular_core.Signal<TemplateRef<any> | null>;
1465
1522
  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>;
1523
+ 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; }; "icon": { "alias": "icon"; "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
1524
  }
1468
1525
 
1469
1526
  type ContentViewerType = 'image' | 'video' | 'pdf';
@@ -1523,6 +1580,47 @@ declare class ContentViewer {
1523
1580
  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>;
1524
1581
  }
1525
1582
 
1583
+ /**
1584
+ * Paginador «Anterior / Siguiente» para listas con cursor: no conoce el
1585
+ * número de página, solo si hay una anterior o una siguiente y un resumen ya
1586
+ * armado. Complementa a `kf-pagination`, que exige número de página y total.
1587
+ *
1588
+ * `summary` ("Mostrando 25 de 96") se anuncia en una región `status`. Los
1589
+ * botones usan `aria-disabled` y no `disabled`, para que el foco no se pierda
1590
+ * al llegar a un extremo (un botón `disabled` deja de ser enfocable y el foco
1591
+ * cae al `body`); pulsarlos en ese estado no emite nada.
1592
+ *
1593
+ * Con `pageSizeOptions` agrega el selector "Filas por página"; vacío lo oculta.
1594
+ *
1595
+ * <kf-cursor-pager summary="Mostrando 25 de 96" [hasPrevious]="!!prev()" [hasNext]="!!next()"
1596
+ * [pageSizeOptions]="[25, 50, 100]" [pageSize]="size()"
1597
+ * (previous)="load(prev())" (next)="load(next())" (pageSizeChange)="size.set($event)" />
1598
+ */
1599
+ declare class CursorPager {
1600
+ /** Texto anunciado y mostrado a la izquierda, p. ej. «Mostrando 25 de 96». */
1601
+ readonly summary: _angular_core.InputSignal<string>;
1602
+ readonly hasPrevious: _angular_core.InputSignal<boolean>;
1603
+ readonly hasNext: _angular_core.InputSignal<boolean>;
1604
+ /** Opciones del selector de filas por página. Vacío oculta el selector. */
1605
+ readonly pageSizeOptions: _angular_core.InputSignal<readonly number[]>;
1606
+ readonly pageSize: _angular_core.InputSignal<number | undefined>;
1607
+ /** Nombre accesible de la navegación. */
1608
+ readonly ariaLabel: _angular_core.InputSignal<string>;
1609
+ readonly previous: _angular_core.OutputEmitterRef<void>;
1610
+ readonly next: _angular_core.OutputEmitterRef<void>;
1611
+ readonly pageSizeChange: _angular_core.OutputEmitterRef<number>;
1612
+ protected readonly sizeOptions: _angular_core.Signal<{
1613
+ value: string;
1614
+ label: string;
1615
+ }[]>;
1616
+ protected readonly sizeValue: _angular_core.Signal<string>;
1617
+ protected onPrevious(): void;
1618
+ protected onNext(): void;
1619
+ protected onPageSize(value: string): void;
1620
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<CursorPager, never>;
1621
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CursorPager, "kf-cursor-pager", never, { "summary": { "alias": "summary"; "required": false; "isSignal": true; }; "hasPrevious": { "alias": "hasPrevious"; "required": false; "isSignal": true; }; "hasNext": { "alias": "hasNext"; "required": false; "isSignal": true; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "previous": "previous"; "next": "next"; "pageSizeChange": "pageSizeChange"; }, never, never, true, never>;
1622
+ }
1623
+
1526
1624
  /**
1527
1625
  * Signal con la vista de `kf-data-table` ('table' | 'cards') derivada de un
1528
1626
  * breakpoint — mismo criterio que cualquier tabla con muchas columnas: bajo
@@ -1742,6 +1840,19 @@ declare class Drawer {
1742
1840
  * de anclaje visual del panel.
1743
1841
  *
1744
1842
  * <kf-dropdown [(open)]="menuOpen"><kf-dropdown-panel>...</kf-dropdown-panel></kf-dropdown>
1843
+ *
1844
+ * Accesibilidad. Disparador: el primer control enfocable del `anchor` (o del
1845
+ * propio host) recibe `aria-haspopup` (`menu` o `dialog`, según el `role` del
1846
+ * panel), `aria-expanded` y, con el panel abierto, `aria-controls`; un atributo
1847
+ * que el consumidor ya declaró nunca se pisa. Foco: el panel vive en un overlay
1848
+ * al final del `body`, así que al abrir el foco pasa al primer elemento
1849
+ * enfocable del panel (`autoFocus`, default `true`; solo si el foco estaba en
1850
+ * el disparador, para no robarlo cuando algo abre el panel por código), y al
1851
+ * cerrar vuelve al disparador si estaba dentro del panel (Escape, elegir una
1852
+ * acción, aplicar). Un clic afuera no devuelve el foco: ya se fue a donde se
1853
+ * hizo clic. Con `role="menu"` las flechas, Home y End recorren los ítems. Tab
1854
+ * desde el último (o Shift+Tab desde el primero) cierra el panel y continúa la
1855
+ * tabulación desde el disparador.
1745
1856
  */
1746
1857
  declare class Dropdown {
1747
1858
  /** Visibilidad del panel, two-way: `[(open)]="menuOpen"`. */
@@ -1754,11 +1865,20 @@ declare class Dropdown {
1754
1865
  * (ej. el avatar de sesión dentro de `PortalHeader`).
1755
1866
  */
1756
1867
  readonly anchor: _angular_core.InputSignal<ElementRef<HTMLElement> | undefined>;
1868
+ /**
1869
+ * Mueve el foco al primer elemento enfocable del panel al abrirlo. Poner
1870
+ * `false` si el contenido ya gestiona su propio foco inicial.
1871
+ */
1872
+ readonly autoFocus: _angular_core.InputSignalWithTransform<boolean, unknown>;
1757
1873
  private readonly panel;
1758
1874
  private readonly overlayService;
1759
1875
  private readonly host;
1760
1876
  private readonly viewContainerRef;
1761
1877
  private readonly destroyRef;
1878
+ private readonly injector;
1879
+ private readonly document;
1880
+ /** Atributos ARIA que este componente puso en el disparador (y por tanto retira él). */
1881
+ private readonly ownedTriggerAttributes;
1762
1882
  private overlayRef;
1763
1883
  /**
1764
1884
  * Suscripciones a `outsidePointerEvents()`/`keydownEvents()` del overlay
@@ -1781,6 +1901,21 @@ declare class Dropdown {
1781
1901
  */
1782
1902
  onDocumentEscape(): boolean;
1783
1903
  private attach;
1904
+ /** Flechas/Home/End entre ítems (solo `role="menu"`) y salida con Tab en los extremos. */
1905
+ private onPanelKeydown;
1906
+ private focusFirstInPanel;
1907
+ private focusableIn;
1908
+ private isFocusOnTrigger;
1909
+ /**
1910
+ * Control que abre el panel: el propio `anchor`/host si ya es enfocable, o
1911
+ * su primer descendiente enfocable (ej. el `<button>` dentro de `kf-button`).
1912
+ */
1913
+ private triggerElement;
1914
+ private syncTriggerAria;
1915
+ /** Escribe el atributo solo si no es del consumidor (ausente, o ya puesto por este componente). */
1916
+ private setOwnedAttribute;
1917
+ private removeOwnedAttribute;
1918
+ private releaseTriggerAria;
1784
1919
  /**
1785
1920
  * El trigger real (el `anchor`, o el propio host si no se pasó ninguno —
1786
1921
  * ver comentario de la clase) vive FUERA del overlay a propósito: el
@@ -1794,7 +1929,7 @@ declare class Dropdown {
1794
1929
  private detach;
1795
1930
  private getOrCreateOverlayRef;
1796
1931
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Dropdown, never>;
1797
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Dropdown, "kf-dropdown", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "anchor": { "alias": "anchor"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, ["panel"], ["*"], true, never>;
1932
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Dropdown, "kf-dropdown", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "anchor": { "alias": "anchor"; "required": false; "isSignal": true; }; "autoFocus": { "alias": "autoFocus"; "required": false; "isSignal": true; }; }, { "open": "openChange"; }, ["panel"], ["*"], true, never>;
1798
1933
  }
1799
1934
 
1800
1935
  type DropdownItemTone = 'neutral' | 'error';
@@ -1822,6 +1957,8 @@ declare class DropdownItem {
1822
1957
  }
1823
1958
 
1824
1959
  type DropdownPanelVariant = 'solid' | 'dark';
1960
+ /** Rol del contenedor del panel: `menu` (ítems de acción) o `dialog` (contenido de formulario o informativo). */
1961
+ type DropdownPanelRole = 'menu' | 'dialog';
1825
1962
  /**
1826
1963
  * Contenido del panel flotante de un `kf-dropdown`. Es solo una plantilla
1827
1964
  * (`<ng-template>`, capturada vía `TemplateRef`) — `Dropdown` la conecta al
@@ -1837,12 +1974,24 @@ type DropdownPanelVariant = 'solid' | 'dark';
1837
1974
  * reposiciona el panel según dónde entra en el viewport y puede terminar
1838
1975
  * cayendo sobre fondo blanco en vez de sobre el rail oscuro — un color
1839
1976
  * sólido se ve intencional sin importar dónde lo posicione el CDK.
1977
+ *
1978
+ * `role`: `'menu'` (default) cuando el contenido son `kf-dropdown-item`;
1979
+ * `'dialog'` cuando lleva campos de formulario, selects, casillas o texto
1980
+ * libre — un `role="menu"` solo admite ítems de menú como hijos. Un panel
1981
+ * `dialog` necesita nombre: pasar `ariaLabel`.
1982
+ *
1983
+ * <kf-dropdown-panel role="dialog" ariaLabel="Filtros">…</kf-dropdown-panel>
1840
1984
  */
1841
1985
  declare class DropdownPanel {
1842
1986
  readonly variant: _angular_core.InputSignal<DropdownPanelVariant>;
1987
+ readonly role: _angular_core.InputSignal<DropdownPanelRole>;
1988
+ /** Nombre accesible del panel (obligatorio en la práctica con `role="dialog"`). */
1989
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
1990
+ /** `id` del contenedor con el rol; el disparador lo referencia con `aria-controls`. */
1991
+ readonly panelId: string;
1843
1992
  readonly templateRef: _angular_core.Signal<TemplateRef<any>>;
1844
1993
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DropdownPanel, never>;
1845
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DropdownPanel, "kf-dropdown-panel", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1994
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DropdownPanel, "kf-dropdown-panel", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "role": { "alias": "role"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1846
1995
  }
1847
1996
 
1848
1997
  /** Tono del estado. `warn`/`info` solo cambian el chip del ícono. */
@@ -2009,14 +2158,19 @@ declare class Field {
2009
2158
  *
2010
2159
  * <kf-field-label [for]="inputId">Patente o VIN</kf-field-label>
2011
2160
  * <kf-field-label [for]="inputId" required>Correo electrónico</kf-field-label>
2161
+ *
2162
+ * `visuallyHidden` deja el texto solo para lectores de pantalla: el `<label
2163
+ * for>` sigue nombrando el control sin ocupar espacio.
2012
2164
  */
2013
2165
  declare class FieldLabel {
2014
2166
  /** `id` del control asociado — se refleja como `for` en el `<label>` interno. */
2015
2167
  readonly for: _angular_core.InputSignal<string | undefined>;
2016
2168
  /** Muestra un asterisco visual indicando que el campo es obligatorio. */
2017
2169
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
2170
+ /** Oculta el texto a la vista pero lo conserva como nombre accesible del control. */
2171
+ readonly visuallyHidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
2018
2172
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FieldLabel, never>;
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>;
2173
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldLabel, "kf-field-label", never, { "for": { "alias": "for"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "visuallyHidden": { "alias": "visuallyHidden"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
2020
2174
  }
2021
2175
 
2022
2176
  /** Por qué se descartó un archivo: formato fuera de `accept` o más grande que `maxSize`. */
@@ -2475,6 +2629,8 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
2475
2629
  private static nextId;
2476
2630
  private readonly nativeInput;
2477
2631
  readonly label: _angular_core.InputSignal<string | undefined>;
2632
+ /** Oculta el `label` a la vista y lo deja como nombre accesible (`<label for>`), sin ocultarlo con CSS desde afuera. */
2633
+ readonly hideLabel: _angular_core.InputSignalWithTransform<boolean, unknown>;
2478
2634
  /** Marca el label con un asterisco visual y aplica `required` al `<input>`
2479
2635
  * nativo — el atributo HTML ya expone el estado obligatorio a lectores de
2480
2636
  * pantalla (mapeo implícito a `aria-required`), sin necesidad de un
@@ -2575,9 +2731,13 @@ declare class Input implements ControlValueAccessor, AfterViewInit {
2575
2731
  */
2576
2732
  protected onTogglePasswordVisibility(): void;
2577
2733
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Input, 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>;
2734
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Input, "kf-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "hideLabel": { "alias": "hideLabel"; "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>;
2579
2735
  }
2580
2736
 
2737
+ type ResolvedJourneyStep = JourneyStep & {
2738
+ status: JourneyStepStatus;
2739
+ progressValue: number | null;
2740
+ };
2581
2741
  type JourneyStepStatus = 'done' | 'current' | 'delayed' | 'pending';
2582
2742
  type JourneyStepperSurface = 'dark' | 'card';
2583
2743
  /**
@@ -2591,32 +2751,71 @@ type JourneyStepperSurface = 'dark' | 'card';
2591
2751
  * Para cuando cada paso comunica su propio estado puntual.
2592
2752
  */
2593
2753
  type JourneyStepperColorScheme = 'brand' | 'semantic';
2754
+ /** `'auto'` elige horizontal o vertical según el ancho del propio componente. */
2755
+ type JourneyStepperOrientation = 'horizontal' | 'vertical' | 'auto';
2594
2756
  interface JourneyStep {
2595
2757
  key: string;
2596
2758
  label: string;
2597
2759
  icon: IconName;
2598
- /** Solo con `orientation="vertical"` — en horizontal el status se calcula desde `currentStep`. */
2760
+ /**
2761
+ * Estado explícito del paso. Si AL MENOS un paso lo define, todos los
2762
+ * estados salen de acá (un paso sin `status` queda `pending`), también en
2763
+ * horizontal y permitiendo varios pasos `current` o estados no
2764
+ * consecutivos. Si ningún paso lo define, horizontal lo deriva de
2765
+ * `currentStep`. Con `orientation="vertical"` siempre se usa el explícito.
2766
+ */
2599
2767
  status?: JourneyStepStatus;
2600
- /** Texto bajo el label — solo con `orientation="vertical"`. */
2768
+ /** Texto bajo el label, junto al label en horizontal sin `caption` (compatibilidad). */
2601
2769
  date?: string;
2770
+ /**
2771
+ * Texto secundario del paso, distinto de `date` (ej. «16 de 18 completaron»).
2772
+ * Se muestra bajo el label en ambas orientaciones.
2773
+ */
2774
+ caption?: string;
2775
+ /**
2776
+ * Avance 0-100 del paso, como barra fina bajo el texto. Se acota a [0, 100];
2777
+ * un valor no finito no dibuja la barra. Si el paso tiene `caption`, la
2778
+ * barra es decorativa (`aria-hidden`) y el `caption` debe comunicar el avance;
2779
+ * sin `caption` expone `role="progressbar"` con el `label` como nombre.
2780
+ */
2781
+ progress?: number;
2782
+ /**
2783
+ * Texto visible del estado (ej. «Completado», «En curso», «Pendiente»), para
2784
+ * que el estado no dependa solo del color y la forma del punto.
2785
+ */
2786
+ statusLabel?: string;
2602
2787
  }
2603
2788
  /**
2604
2789
  * Progreso de un flujo de N pasos.
2605
2790
  *
2606
- * - `orientation` (`'horizontal'` default | `'vertical'`): horizontal
2607
- * deriva done/current/pending de `currentStep`; vertical usa
2608
- * `steps[].status` explícito, con `delayed` como cuarto estado.
2791
+ * - `orientation` (`'horizontal'` default | `'vertical'` | `'auto'`): horizontal
2792
+ * deriva done/current/pending de `currentStep` (salvo que algún paso defina
2793
+ * `status`); vertical usa `steps[].status` explícito, con `delayed` como
2794
+ * cuarto estado. `'auto'` es horizontal cuando el propio componente mide al
2795
+ * menos `autoBreakpoint` px (820 por defecto) y vertical si no; en vertical,
2796
+ * con `caption`/`progress`/`statusLabel` y desde 520 px de ancho, el texto de
2797
+ * cada paso pasa a filas «etiqueta | estado y conteo | barra». En `'auto'`
2798
+ * los puntos son clickeables solo mientras el layout es horizontal.
2609
2799
  * - `surface` (`'dark'` default | `'card'`): fondo sólido oscuro de marca,
2610
2800
  * o superficie clara con borde+sombra.
2611
2801
  * - `colorScheme` (`'brand'` default | `'semantic'`): ver `JourneyStepperColorScheme`.
2802
+ * - `ariaLabel`: nombre de la lista de pasos (lectores de pantalla).
2803
+ *
2804
+ * Los pasos se exponen como lista (`role="list"`/`listitem`) y el paso con
2805
+ * `status === 'current'` lleva `aria-current="step"`.
2612
2806
  *
2613
2807
  * <kf-journey-stepper surface="card" [steps]="steps" [currentStep]="4" (stepClick)="onNavigate($event)" />
2614
2808
  * <kf-journey-stepper orientation="vertical" [steps]="unitSteps" />
2615
2809
  * <kf-journey-stepper orientation="vertical" colorScheme="semantic" [steps]="unitStepsWithDelays" />
2810
+ * <kf-journey-stepper orientation="auto" surface="card" ariaLabel="Avance por etapa" [steps]="stages" />
2616
2811
  */
2617
2812
  declare class JourneyStepper {
2618
2813
  readonly steps: _angular_core.InputSignal<JourneyStep[]>;
2619
- readonly orientation: _angular_core.InputSignal<"horizontal" | "vertical">;
2814
+ readonly orientation: _angular_core.InputSignal<JourneyStepperOrientation>;
2815
+ /** Ancho mínimo (px) del componente para ser horizontal con `orientation="auto"`. */
2816
+ readonly autoBreakpoint: _angular_core.InputSignal<number>;
2817
+ /** Nombre accesible de la lista de pasos. */
2818
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
2620
2819
  readonly surface: _angular_core.InputSignal<JourneyStepperSurface>;
2621
2820
  readonly colorScheme: _angular_core.InputSignal<JourneyStepperColorScheme>;
2622
2821
  /** Índice del paso actual — solo con `orientation="horizontal"`. */
@@ -2627,15 +2826,26 @@ declare class JourneyStepper {
2627
2826
  private readonly destroyRef;
2628
2827
  /** `true` cuando el contenido desborda el ancho visible — controla el fade de los bordes. */
2629
2828
  protected readonly hasOverflow: _angular_core.WritableSignal<boolean>;
2829
+ /** Ancho medido del componente; `null` hasta la primera medición. */
2830
+ private readonly trackWidth;
2831
+ /**
2832
+ * Orientación efectiva: la de `orientation`, o —con `'auto'`— horizontal si el
2833
+ * componente mide al menos `autoBreakpoint` px. Antes de medir (o con ancho
2834
+ * 0) es vertical, que siempre cabe.
2835
+ */
2836
+ protected readonly effectiveOrientation: _angular_core.Signal<"horizontal" | "vertical">;
2837
+ protected readonly vertical: _angular_core.Signal<boolean>;
2630
2838
  protected readonly clickable: _angular_core.Signal<boolean>;
2839
+ /** `true` si algún paso usa `caption`, `progress` o `statusLabel` (layout enriquecido). */
2840
+ protected readonly rich: _angular_core.Signal<boolean>;
2631
2841
  constructor();
2632
2842
  private measureOverflow;
2633
- protected readonly resolvedSteps: _angular_core.Signal<(JourneyStep & {
2634
- status: JourneyStepStatus;
2635
- })[]>;
2843
+ /** Progreso acotado a [0, 100]; `null` si no hay valor finito. */
2844
+ private static progressOf;
2845
+ protected readonly resolvedSteps: _angular_core.Signal<ResolvedJourneyStep[]>;
2636
2846
  protected dotIcon(status: JourneyStepStatus, stepIcon: IconName): IconName;
2637
2847
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<JourneyStepper, never>;
2638
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<JourneyStepper, "kf-journey-stepper", never, { "steps": { "alias": "steps"; "required": true; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "surface": { "alias": "surface"; "required": false; "isSignal": true; }; "colorScheme": { "alias": "colorScheme"; "required": false; "isSignal": true; }; "currentStep": { "alias": "currentStep"; "required": false; "isSignal": true; }; }, { "stepClick": "stepClick"; }, never, never, true, never>;
2848
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<JourneyStepper, "kf-journey-stepper", never, { "steps": { "alias": "steps"; "required": true; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "autoBreakpoint": { "alias": "autoBreakpoint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "surface": { "alias": "surface"; "required": false; "isSignal": true; }; "colorScheme": { "alias": "colorScheme"; "required": false; "isSignal": true; }; "currentStep": { "alias": "currentStep"; "required": false; "isSignal": true; }; }, { "stepClick": "stepClick"; }, never, never, true, never>;
2639
2849
  }
2640
2850
 
2641
2851
  type LinkVariant = 'default' | 'muted';
@@ -4047,10 +4257,27 @@ interface SelectOption {
4047
4257
  * buscador, si está visible). En el panel, flechas y Home/End mueven el
4048
4258
  * foco, Enter/Espacio eligen, Escape cierra y devuelve el foco al trigger,
4049
4259
  * y Tab cierra el panel y continúa la tabulación desde el trigger. Las
4050
- * opciones nunca son paradas de Tab (`tabindex="-1"`).
4260
+ * opciones nunca son paradas de Tab (`tabindex="-1"`). Home/End sobre el
4261
+ * trigger cerrado lo abren en la primera/última opción, y teclear letras
4262
+ * (con el panel abierto o cerrado, sin buscador) salta a la opción cuyo
4263
+ * label empieza con lo tecleado; repetir la misma letra recorre las que
4264
+ * empiezan igual.
4051
4265
  */
4052
4266
  declare class Select {
4053
4267
  readonly label: _angular_core.InputSignal<string | undefined>;
4268
+ /**
4269
+ * Oculta el `label` a la vista y lo deja como nombre accesible (`<label
4270
+ * for>`): para un control cuyo valor se explica solo (ej. un rango de
4271
+ * fechas), sin tener que ocultar la etiqueta con CSS desde afuera.
4272
+ */
4273
+ readonly hideLabel: _angular_core.InputSignalWithTransform<boolean, unknown>;
4274
+ /**
4275
+ * Texto corto visible dentro del trigger, antes del valor (ej. `Rango:
4276
+ * Últimos 30 días`), para un select compacto que no lleva etiqueta
4277
+ * encima. Forma parte del nombre accesible del botón: no combinarlo con
4278
+ * `label`/`ariaLabel`, que reemplazarían ese nombre.
4279
+ */
4280
+ readonly prefix: _angular_core.InputSignal<string | undefined>;
4054
4281
  readonly options: _angular_core.InputSignal<readonly (string | SelectOption)[]>;
4055
4282
  readonly value: _angular_core.InputSignal<string | undefined>;
4056
4283
  readonly placeholder: _angular_core.InputSignal<string>;
@@ -4122,6 +4349,8 @@ declare class Select {
4122
4349
  private readonly searchInputRef;
4123
4350
  private readonly panelRef;
4124
4351
  private readonly document;
4352
+ private typeaheadBuffer;
4353
+ private typeaheadTimer;
4125
4354
  private readonly overlay;
4126
4355
  constructor();
4127
4356
  /**
@@ -4145,7 +4374,11 @@ declare class Select {
4145
4374
  * click afuera no lo restaura: el foco ya se fue a donde se hizo click.
4146
4375
  */
4147
4376
  close(restoreFocus?: boolean): void;
4148
- /** ArrowDown/ArrowUp con el panel cerrado lo abren (patrón listbox). */
4377
+ /**
4378
+ * Con el panel cerrado: ArrowDown/ArrowUp lo abren en la opción activa,
4379
+ * Home/End en la primera/última, y una letra lo abre en la opción que
4380
+ * empieza con ella (patrón listbox).
4381
+ */
4149
4382
  onTriggerKeydown(event: KeyboardEvent): void;
4150
4383
  /**
4151
4384
  * Teclado con el foco en una opción del panel. Las flechas parten SIEMPRE
@@ -4154,6 +4387,15 @@ declare class Select {
4154
4387
  * foco en la opción 1 y el mouse sobre la 4, ArrowDown saltaría a la 5.
4155
4388
  */
4156
4389
  onOptionKeydown(event: KeyboardEvent, option: SelectOption, index: number): void;
4390
+ /** Un carácter imprimible sin modificadores, y solo cuando no hay buscador (ahí la tecla filtra). */
4391
+ private isTypeaheadKey;
4392
+ /**
4393
+ * Índice de la opción cuyo label empieza con lo tecleado, o -1. Una sola
4394
+ * letra (o la misma repetida) busca desde la opción SIGUIENTE a `from`, para
4395
+ * recorrer las que empiezan igual; un prefijo más largo busca desde `from`
4396
+ * inclusive, para que la opción actual se conserve mientras siga coincidiendo.
4397
+ */
4398
+ private findTypeaheadMatch;
4157
4399
  /** Teclas de salida del buscador: Escape y Tab, igual que desde una opción. */
4158
4400
  onSearchKeydown(event: KeyboardEvent): void;
4159
4401
  /**
@@ -4188,7 +4430,7 @@ declare class Select {
4188
4430
  private scrollActiveIntoView;
4189
4431
  selectActive(): void;
4190
4432
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Select, never>;
4191
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<Select, "kf-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "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; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "panelTitle": { "alias": "panelTitle"; "required": false; "isSignal": true; }; "panelWidth": { "alias": "panelWidth"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
4433
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Select, "kf-select", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "hideLabel": { "alias": "hideLabel"; "required": false; "isSignal": true; }; "prefix": { "alias": "prefix"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "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; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "panelTitle": { "alias": "panelTitle"; "required": false; "isSignal": true; }; "panelWidth": { "alias": "panelWidth"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
4192
4434
  }
4193
4435
 
4194
4436
  interface SelectableCardOption {
@@ -4376,6 +4618,8 @@ declare class Spinner {
4376
4618
  }
4377
4619
 
4378
4620
  type StatCardTone = 'primary' | 'success' | 'error' | 'purple' | 'warn' | 'info' | 'neutral';
4621
+ /** Densidad de la card: `'compact'` reduce el padding, el ícono y el valor. */
4622
+ type StatCardDensity = 'default' | 'compact';
4379
4623
  /**
4380
4624
  * Card de estadística horizontal: ícono circular grande a la izquierda,
4381
4625
  * valor + label + nota apilados al centro, chevron opcional al final si es
@@ -4400,6 +4644,18 @@ type StatCardTone = 'primary' | 'success' | 'error' | 'purple' | 'warn' | 'info'
4400
4644
  * <kf-stat-card icon="clock" tone="warn" value="7" label="Por vencer" [bar]="35" hint="7 de 20"
4401
4645
  * clickable [pressed]="filter() === 'due'" (cardClick)="toggle('due')" />
4402
4646
  *
4647
+ * `density` (`'default'` | `'compact'`): `'compact'` es la variante para
4648
+ * pantallas angostas — padding de `--kf-space-md`, ícono de 40px y valor de
4649
+ * `--kf-font-size-title-sm`, con el mismo contenido. Si la card mide 210px de
4650
+ * ancho o menos (ej. una grilla 2x2 en teléfono), pasa además a dos filas:
4651
+ * ícono y valor en la primera, y label, nota, barra y `hint` debajo a todo el
4652
+ * ancho; el chevron se oculta. Solo la variante compacta convierte el host en
4653
+ * contenedor de tamaño (`container-type: inline-size`), así que debe tener un
4654
+ * ancho que no dependa de su contenido (celda de grilla, `width` explícito o
4655
+ * hijo de un contenedor en bloque). `'default'` no cambia nada.
4656
+ *
4657
+ * <kf-stat-card density="compact" icon="clock" value="7" label="Por vencer" />
4658
+ *
4403
4659
  * `loading` (default `false`): mientras es `true` la card dibuja su esqueleto
4404
4660
  * en vez del contenido, con el MISMO cascarón (borde, padding, ícono de 50px)
4405
4661
  * y líneas del alto real de cada texto — valor, etiqueta y, si se pasaron,
@@ -4425,6 +4681,8 @@ declare class StatCard {
4425
4681
  * `null` (default) = no aplica: el atributo no se emite.
4426
4682
  */
4427
4683
  readonly pressed: _angular_core.InputSignal<boolean | null>;
4684
+ /** `'compact'`: variante para pantallas angostas; `'default'` no cambia la card. */
4685
+ readonly density: _angular_core.InputSignal<StatCardDensity>;
4428
4686
  /** Dibuja el esqueleto en lugar del contenido, conservando las dimensiones. */
4429
4687
  readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
4430
4688
  /** Si se escucha `cardClick`, la card se renderiza como botón clickeable con chevron. */
@@ -4433,7 +4691,7 @@ declare class StatCard {
4433
4691
  protected readonly barTone: _angular_core.Signal<ProgressTone>;
4434
4692
  protected readonly hasBar: _angular_core.Signal<boolean>;
4435
4693
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatCard, 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>;
4694
+ 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; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, never, true, never>;
4437
4695
  }
4438
4696
 
4439
4697
  /** Vocabulario semántico único de tono, compartido con `TextTone`. */
@@ -5038,5 +5296,5 @@ declare class ViewToggle {
5038
5296
  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>;
5039
5297
  }
5040
5298
 
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 };
5299
+ export { ActionTile, AdminBadge, Alert, AlertRow, Avatar, Badge, Breadcrumb, BucketProgress, Button, Calendar, Card, Carousel, CarouselSlide, Checkbox, Chip, Collapsible, ContactPopover, ContentSlot, ContentState, ContentStateLoading, ContentViewer, CursorPager, 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 };
5300
+ export type { AlertRowTone, AlertTone, AlertVariant, BreadcrumbItem, BucketProgressItem, CalendarDay, ContentStateKind, ContentStateLoad, ContentViewerType, DataTableCardRole, DataTableCellClick, DataTableColumn, DataTableDensity, DataTableSort, DataTableView, DividerOrientation, DocumentRowTone, DrawerRole, DrawerSide, DropdownItemTone, DropdownPanelRole, DropdownPanelVariant, EmptyStateTone, EventTimelineItem, EventTimelineTone, FileRejection, FileRejectionReason, FilterChipOption, FilterFieldChange, FilterFieldConfig, FilterFieldType, FilterValue, FolderTabOption, FooterLink, IconName, IconRotation, IconSize, InputBound, JourneyStep, JourneyStepStatus, JourneyStepperColorScheme, JourneyStepperOrientation, 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, StatCardDensity, StatCardTone, StatTileTone, StatTileVariant, TabOption, TextAs, TextTone, TextVariant, TimeSlot, ToastAction, ToastOptions, ToastPromiseMessages, ToastState, ToastTone, TooltipPosition, ViewToggleOption };