@kaufmann-lab/ui 0.1.26 → 0.1.28

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.
@@ -1237,6 +1237,34 @@ const TONE_ICON = {
1237
1237
  * vencimiento, confirmaciones. Persiste hasta que se descarta o hasta que la
1238
1238
  * condición que lo causó desaparece — para feedback efímero está el toast.
1239
1239
  *
1240
+ * Diseño sobrio: el título va en peso 600 con la tipografía de cuerpo y el
1241
+ * mensaje con medida de lectura limitada, ambos en los neutros del sistema (el
1242
+ * color del tono nunca se usa para texto). El ícono va centrado en vertical
1243
+ * respecto al aviso. El color sale siempre de los tokens (`*-strong`), nunca de
1244
+ * un input. Ninguna apariencia lleva borde ni acento lateral de color.
1245
+ *
1246
+ * `appearance` elige cómo se muestra el tono (solo aplica a `variant="card"`):
1247
+ *
1248
+ * - `tile` (default): aviso estándar dentro de pantallas y cards. Tarjeta de
1249
+ * superficie y borde neutros; el color vive solo en el ícono, un tile sólido de
1250
+ * 40px con glifo blanco.
1251
+ *
1252
+ * <kf-alert tone="warn" title="SOAT por vencer">Vence el 15/08.</kf-alert>
1253
+ *
1254
+ * - `tint`: aviso liviano sobre fondos neutros o en zonas densas, donde el tinte
1255
+ * basta. Relleno suave del tono, sin borde ni tile; glifo de 24px en el color
1256
+ * fuerte del tono.
1257
+ *
1258
+ * <kf-alert appearance="tint" tone="info">Cita confirmada para el jueves.</kf-alert>
1259
+ *
1260
+ * - `rail`: aviso destacado que debe notarse al primer vistazo, p. ej. errores o
1261
+ * bloqueos. Panel de ícono de 56px a todo el alto, con el fondo del tono más
1262
+ * intenso, y cuerpo neutro con borde neutro.
1263
+ *
1264
+ * <kf-alert appearance="rail" tone="error" title="Pago rechazado">
1265
+ * Tu banco no autorizó el cargo.
1266
+ * </kf-alert>
1267
+ *
1240
1268
  * `open` es two-way: el botón de cerrar lo pone en `false` y el componente
1241
1269
  * deja de renderizar. El consumidor puede volver a abrirlo poniéndolo en
1242
1270
  * `true` (ej. cuando la validación falla otra vez).
@@ -1250,9 +1278,21 @@ const TONE_ICON = {
1250
1278
  * tonos y mismo `role` (`alert` para `error`/`warn`, `status` para el resto)
1251
1279
  * que la variante `card`. Pensada para el borde de una página o de un panel
1252
1280
  * (ej. "Estás viendo datos de otro cliente"), donde una tarjeta con margen
1253
- * sobra.
1281
+ * sobra. `variant="bar"` ignora `appearance`: la franja siempre usa su propia
1282
+ * superficie tintada.
1254
1283
  *
1255
1284
  * <kf-alert variant="bar" tone="warn" title="Modo suplantación">Viendo como Ana Pérez.</kf-alert>
1285
+ *
1286
+ * Los elementos con el atributo `kfAlertActions` se proyectan a la derecha del
1287
+ * mensaje cuando hay ancho y, si no caben, en una fila propia bajo él, apilados
1288
+ * y alineados al inicio (en la variante `bar` siempre van en fila propia). Si los
1289
+ * envuelves en un solo `<div kfAlertActions>`, el aviso separa a sus hijos (12px).
1290
+ * Sin ellos la zona no existe y el aviso queda igual.
1291
+ *
1292
+ * <kf-alert tone="warn" title="SOAT por vencer">
1293
+ * Vence el 15/08.
1294
+ * <div kfAlertActions><kf-button size="sm">Renovar</kf-button></div>
1295
+ * </kf-alert>
1256
1296
  */
1257
1297
  class Alert {
1258
1298
  tone = input('info', /* @ts-ignore */
@@ -1260,7 +1300,13 @@ class Alert {
1260
1300
  /** `card` (default) o `bar` (franja compacta de ancho completo). */
1261
1301
  variant = input('card', /* @ts-ignore */
1262
1302
  ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1263
- /** Línea en negrita arriba del mensaje. Vacío deja solo el contenido proyectado. */
1303
+ /**
1304
+ * `tile` (default), `tint` o `rail`. Solo aplica a `variant="card"`; `bar` la
1305
+ * ignora. Se expone en el host como `data-appearance`.
1306
+ */
1307
+ appearance = input('tile', /* @ts-ignore */
1308
+ ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
1309
+ /** Título (peso 600) arriba del mensaje. Vacío deja solo el contenido proyectado. */
1264
1310
  title = input('', /* @ts-ignore */
1265
1311
  ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
1266
1312
  dismissible = input(false, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -1275,13 +1321,20 @@ class Alert {
1275
1321
  ...(ngDevMode ? [{ debugName: "ariaRole" }] : /* istanbul ignore next */ []));
1276
1322
  toneIcon = computed(() => TONE_ICON[this.tone()], /* @ts-ignore */
1277
1323
  ...(ngDevMode ? [{ debugName: "toneIcon" }] : /* istanbul ignore next */ []));
1324
+ /** Glifo: 16px en `bar`, 20px en `tile` y 24px en `tint`/`rail`. */
1325
+ iconSize = computed(() => {
1326
+ if (this.variant() === 'bar')
1327
+ return 'sm';
1328
+ return this.appearance() === 'tile' ? 'md' : 'lg';
1329
+ }, /* @ts-ignore */
1330
+ ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
1278
1331
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Alert, deps: [], target: i0.ɵɵFactoryTarget.Component });
1279
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Alert, isStandalone: true, selector: "kf-alert", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, ngImport: i0, template: "@if (open()) {\n <div\n class=\"kf-alert\"\n [class]=\"'kf-alert--' + tone()\"\n [class.kf-alert--bar]=\"variant() === 'bar'\"\n [attr.role]=\"ariaRole()\"\n >\n <kf-icon class=\"kf-alert__icon\" [name]=\"toneIcon()\" size=\"sm\" />\n <div class=\"kf-alert__body\">\n @if (title()) {\n <p class=\"kf-alert__title\">{{ title() }}</p>\n }\n <div class=\"kf-alert__message\"><ng-content /></div>\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-alert__close\"\n aria-label=\"Cerrar aviso\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n}\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-alert{display:flex;align-items:flex-start;gap:var(--kf-space-sm);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid transparent;border-radius:var(--kf-radius-sm);font-size:.9rem}.kf-alert--info{background:var(--kf-color-info-soft);border-color:var(--kf-color-info);color:var(--kf-color-info-strong)}.kf-alert--ok{background:var(--kf-color-success-soft);border-color:var(--kf-color-success);color:var(--kf-color-success-strong)}.kf-alert--warn{background:var(--kf-color-warning-soft);border-color:var(--kf-color-warning);color:var(--kf-color-warning-strong)}.kf-alert--error{background:var(--kf-color-error-soft);border-color:var(--kf-color-error);color:var(--kf-color-error-strong)}.kf-alert__body{flex:1;min-width:0}.kf-alert__title{margin:0;font-family:var(--kf-font-title);font-weight:700}.kf-alert__message{color:inherit}.kf-alert__close{flex:none;display:inline-flex;padding:2px;border:none;background:transparent;color:inherit;border-radius:var(--kf-radius-xs);cursor:pointer;opacity:.7}.kf-alert__close:hover{opacity:1}.kf-alert__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-alert--bar{align-items:center;padding:var(--kf-space-xs) var(--kf-space-md);border-width:1px 0;border-radius:0;font-size:.875rem}.kf-alert--bar .kf-alert__body{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-xs)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
1332
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Alert, isStandalone: true, selector: "kf-alert", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { properties: { "attr.data-appearance": "appearance()" } }, ngImport: i0, template: "@if (open()) {\n <div\n class=\"kf-alert\"\n [class]=\"'kf-alert--' + tone()\"\n [class.kf-alert--bar]=\"variant() === 'bar'\"\n [attr.role]=\"ariaRole()\"\n >\n <kf-icon class=\"kf-alert__icon\" [name]=\"toneIcon()\" [size]=\"iconSize()\" />\n <div class=\"kf-alert__body\">\n <div class=\"kf-alert__content\">\n @if (title()) {\n <p class=\"kf-alert__title\">{{ title() }}</p>\n }\n <div class=\"kf-alert__message\"><ng-content /></div>\n </div>\n <div class=\"kf-alert__actions\"><ng-content select=\"[kfAlertActions]\" /></div>\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-alert__close\"\n aria-label=\"Cerrar aviso\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n}\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-alert{display:flex;align-items:center;gap:var(--kf-space-md);padding:calc(var(--kf-space-sm) + var(--kf-space-xs)) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);color:var(--kf-color-text);font-size:var(--kf-font-size-body-sm);line-height:1.5}.kf-alert--info{--_tone: var(--kf-color-info);--_soft: var(--kf-color-info-soft);--_strong: var(--kf-color-info-strong)}.kf-alert--ok{--_tone: var(--kf-color-success);--_soft: var(--kf-color-success-soft);--_strong: var(--kf-color-success-strong)}.kf-alert--warn{--_tone: var(--kf-color-warning);--_soft: var(--kf-color-warning-soft);--_strong: var(--kf-color-warning-strong)}.kf-alert--error{--_tone: var(--kf-color-error);--_soft: var(--kf-color-error-soft);--_strong: var(--kf-color-error-strong)}.kf-alert__icon{align-items:center;justify-content:center;inline-size:40px;block-size:40px;border-radius:var(--kf-radius-sm);background:var(--_strong);color:var(--kf-color-white)}.kf-alert__body{display:flex;flex:1 1 0;flex-wrap:wrap;align-items:center;gap:var(--kf-space-md) var(--kf-space-lg);min-width:0}.kf-alert__content{display:flex;flex:1 1 20rem;flex-direction:column;gap:2px;min-width:0}.kf-alert__title{margin:0;color:var(--kf-color-ink);font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-medium);line-height:1.5}.kf-alert__message{max-inline-size:72ch;color:var(--kf-color-text);overflow-wrap:anywhere}.kf-alert__message:has(>div,>section,>form,>table){max-inline-size:none}.kf-alert__message:empty{display:none}.kf-alert__actions{display:flex;flex:0 1 auto;flex-wrap:wrap;align-items:center;gap:calc(var(--kf-space-sm) + var(--kf-space-xs));min-width:0;max-width:100%}.kf-alert__actions:empty{display:none}.kf-alert__actions>*{max-width:100%;min-width:0}.kf-alert__actions ::ng-deep>:is(div,span,ul)[kfAlertActions]{display:flex;flex-wrap:wrap;align-items:center;gap:calc(var(--kf-space-sm) + var(--kf-space-xs));margin:0;padding:0;list-style:none}.kf-alert__close{position:relative;flex:none;display:inline-flex;align-self:center;margin-inline-start:var(--kf-space-sm);padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer;transition:background-color .14s ease,color .14s ease}.kf-alert__close:after{content:\"\";position:absolute;top:50%;left:calc(-1 * var(--kf-space-sm));width:44px;height:44px;transform:translateY(-50%)}.kf-alert__close:hover{background:var(--kf-color-gray-100);color:var(--kf-color-ink)}.kf-alert__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){.kf-alert__close{transition:none}}.kf-alert--bar{gap:var(--kf-space-sm);padding:var(--kf-space-sm) var(--kf-space-md);border-color:color-mix(in srgb,var(--_tone) 40%,var(--_soft));border-width:1px 0;border-radius:0;background:var(--_soft);box-shadow:none}.kf-alert--bar .kf-alert__icon{inline-size:auto;block-size:auto;border-radius:0;background:none;color:var(--_strong)}.kf-alert--bar .kf-alert__body{row-gap:var(--kf-space-sm)}.kf-alert--bar .kf-alert__content{flex-flow:row wrap;align-items:baseline;column-gap:var(--kf-space-xs)}.kf-alert--bar .kf-alert__title{font-size:inherit}.kf-alert--bar .kf-alert__message{max-inline-size:none}.kf-alert--bar .kf-alert__actions{flex-basis:100%}.kf-alert--bar .kf-alert__close:hover{background:color-mix(in srgb,var(--_strong) 12%,transparent)}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar){padding-block:var(--kf-space-md);border-color:transparent;background:var(--_soft);box-shadow:none}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__icon{inline-size:24px;block-size:24px;border-radius:0;background:none;color:var(--_strong)}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__close:hover{background:color-mix(in srgb,var(--_strong) 12%,transparent)}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar){gap:0;padding:0}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__icon{align-self:stretch;box-sizing:border-box;inline-size:56px;block-size:auto;min-block-size:56px;border-inline-end:1px solid var(--kf-color-border);border-radius:calc(var(--kf-radius-md) - 1px) 0 0 calc(var(--kf-radius-md) - 1px);background:color-mix(in srgb,var(--_tone) 22%,var(--_soft));color:color-mix(in srgb,var(--_strong) 75%,var(--kf-color-ink))}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__body{padding:var(--kf-space-md)}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__close{margin-inline-end:var(--kf-space-md)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
1280
1333
  }
1281
1334
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Alert, decorators: [{
1282
1335
  type: Component,
1283
- args: [{ selector: 'kf-alert', imports: [Icon], template: "@if (open()) {\n <div\n class=\"kf-alert\"\n [class]=\"'kf-alert--' + tone()\"\n [class.kf-alert--bar]=\"variant() === 'bar'\"\n [attr.role]=\"ariaRole()\"\n >\n <kf-icon class=\"kf-alert__icon\" [name]=\"toneIcon()\" size=\"sm\" />\n <div class=\"kf-alert__body\">\n @if (title()) {\n <p class=\"kf-alert__title\">{{ title() }}</p>\n }\n <div class=\"kf-alert__message\"><ng-content /></div>\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-alert__close\"\n aria-label=\"Cerrar aviso\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n}\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-alert{display:flex;align-items:flex-start;gap:var(--kf-space-sm);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid transparent;border-radius:var(--kf-radius-sm);font-size:.9rem}.kf-alert--info{background:var(--kf-color-info-soft);border-color:var(--kf-color-info);color:var(--kf-color-info-strong)}.kf-alert--ok{background:var(--kf-color-success-soft);border-color:var(--kf-color-success);color:var(--kf-color-success-strong)}.kf-alert--warn{background:var(--kf-color-warning-soft);border-color:var(--kf-color-warning);color:var(--kf-color-warning-strong)}.kf-alert--error{background:var(--kf-color-error-soft);border-color:var(--kf-color-error);color:var(--kf-color-error-strong)}.kf-alert__body{flex:1;min-width:0}.kf-alert__title{margin:0;font-family:var(--kf-font-title);font-weight:700}.kf-alert__message{color:inherit}.kf-alert__close{flex:none;display:inline-flex;padding:2px;border:none;background:transparent;color:inherit;border-radius:var(--kf-radius-xs);cursor:pointer;opacity:.7}.kf-alert__close:hover{opacity:1}.kf-alert__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-alert--bar{align-items:center;padding:var(--kf-space-xs) var(--kf-space-md);border-width:1px 0;border-radius:0;font-size:.875rem}.kf-alert--bar .kf-alert__body{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-xs)}\n"] }]
1284
- }], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }] } });
1336
+ args: [{ selector: 'kf-alert', imports: [Icon], host: { '[attr.data-appearance]': 'appearance()' }, template: "@if (open()) {\n <div\n class=\"kf-alert\"\n [class]=\"'kf-alert--' + tone()\"\n [class.kf-alert--bar]=\"variant() === 'bar'\"\n [attr.role]=\"ariaRole()\"\n >\n <kf-icon class=\"kf-alert__icon\" [name]=\"toneIcon()\" [size]=\"iconSize()\" />\n <div class=\"kf-alert__body\">\n <div class=\"kf-alert__content\">\n @if (title()) {\n <p class=\"kf-alert__title\">{{ title() }}</p>\n }\n <div class=\"kf-alert__message\"><ng-content /></div>\n </div>\n <div class=\"kf-alert__actions\"><ng-content select=\"[kfAlertActions]\" /></div>\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-alert__close\"\n aria-label=\"Cerrar aviso\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n}\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-alert{display:flex;align-items:center;gap:var(--kf-space-md);padding:calc(var(--kf-space-sm) + var(--kf-space-xs)) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);color:var(--kf-color-text);font-size:var(--kf-font-size-body-sm);line-height:1.5}.kf-alert--info{--_tone: var(--kf-color-info);--_soft: var(--kf-color-info-soft);--_strong: var(--kf-color-info-strong)}.kf-alert--ok{--_tone: var(--kf-color-success);--_soft: var(--kf-color-success-soft);--_strong: var(--kf-color-success-strong)}.kf-alert--warn{--_tone: var(--kf-color-warning);--_soft: var(--kf-color-warning-soft);--_strong: var(--kf-color-warning-strong)}.kf-alert--error{--_tone: var(--kf-color-error);--_soft: var(--kf-color-error-soft);--_strong: var(--kf-color-error-strong)}.kf-alert__icon{align-items:center;justify-content:center;inline-size:40px;block-size:40px;border-radius:var(--kf-radius-sm);background:var(--_strong);color:var(--kf-color-white)}.kf-alert__body{display:flex;flex:1 1 0;flex-wrap:wrap;align-items:center;gap:var(--kf-space-md) var(--kf-space-lg);min-width:0}.kf-alert__content{display:flex;flex:1 1 20rem;flex-direction:column;gap:2px;min-width:0}.kf-alert__title{margin:0;color:var(--kf-color-ink);font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-medium);line-height:1.5}.kf-alert__message{max-inline-size:72ch;color:var(--kf-color-text);overflow-wrap:anywhere}.kf-alert__message:has(>div,>section,>form,>table){max-inline-size:none}.kf-alert__message:empty{display:none}.kf-alert__actions{display:flex;flex:0 1 auto;flex-wrap:wrap;align-items:center;gap:calc(var(--kf-space-sm) + var(--kf-space-xs));min-width:0;max-width:100%}.kf-alert__actions:empty{display:none}.kf-alert__actions>*{max-width:100%;min-width:0}.kf-alert__actions ::ng-deep>:is(div,span,ul)[kfAlertActions]{display:flex;flex-wrap:wrap;align-items:center;gap:calc(var(--kf-space-sm) + var(--kf-space-xs));margin:0;padding:0;list-style:none}.kf-alert__close{position:relative;flex:none;display:inline-flex;align-self:center;margin-inline-start:var(--kf-space-sm);padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer;transition:background-color .14s ease,color .14s ease}.kf-alert__close:after{content:\"\";position:absolute;top:50%;left:calc(-1 * var(--kf-space-sm));width:44px;height:44px;transform:translateY(-50%)}.kf-alert__close:hover{background:var(--kf-color-gray-100);color:var(--kf-color-ink)}.kf-alert__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){.kf-alert__close{transition:none}}.kf-alert--bar{gap:var(--kf-space-sm);padding:var(--kf-space-sm) var(--kf-space-md);border-color:color-mix(in srgb,var(--_tone) 40%,var(--_soft));border-width:1px 0;border-radius:0;background:var(--_soft);box-shadow:none}.kf-alert--bar .kf-alert__icon{inline-size:auto;block-size:auto;border-radius:0;background:none;color:var(--_strong)}.kf-alert--bar .kf-alert__body{row-gap:var(--kf-space-sm)}.kf-alert--bar .kf-alert__content{flex-flow:row wrap;align-items:baseline;column-gap:var(--kf-space-xs)}.kf-alert--bar .kf-alert__title{font-size:inherit}.kf-alert--bar .kf-alert__message{max-inline-size:none}.kf-alert--bar .kf-alert__actions{flex-basis:100%}.kf-alert--bar .kf-alert__close:hover{background:color-mix(in srgb,var(--_strong) 12%,transparent)}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar){padding-block:var(--kf-space-md);border-color:transparent;background:var(--_soft);box-shadow:none}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__icon{inline-size:24px;block-size:24px;border-radius:0;background:none;color:var(--_strong)}:host([data-appearance=\"tint\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__close:hover{background:color-mix(in srgb,var(--_strong) 12%,transparent)}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar){gap:0;padding:0}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__icon{align-self:stretch;box-sizing:border-box;inline-size:56px;block-size:auto;min-block-size:56px;border-inline-end:1px solid var(--kf-color-border);border-radius:calc(var(--kf-radius-md) - 1px) 0 0 calc(var(--kf-radius-md) - 1px);background:color-mix(in srgb,var(--_tone) 22%,var(--_soft));color:color-mix(in srgb,var(--_strong) 75%,var(--kf-color-ink))}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__body{padding:var(--kf-space-md)}:host([data-appearance=\"rail\"]) .kf-alert:not(.kf-alert--bar) .kf-alert__close{margin-inline-end:var(--kf-space-md)}\n"] }]
1337
+ }], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }] } });
1285
1338
 
1286
1339
  /**
1287
1340
  * Fila clickeable de una lista de pendientes/alertas: ícono circular con
@@ -2050,7 +2103,7 @@ class Checkbox {
2050
2103
  useExisting: forwardRef(() => Checkbox),
2051
2104
  multi: true,
2052
2105
  },
2053
- ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<label class=\"kf-checkbox\" [class.kf-checkbox--disabled]=\"disabled()\">\n <input\n #inputRef\n type=\"checkbox\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (change)=\"onChange($event)\"\n (blur)=\"onTouched()\"\n />\n <span\n class=\"kf-checkbox__box kf-checkbox-box\"\n [class.kf-checkbox__box--invalid]=\"invalid()\"\n ></span>\n @if (label()) {\n <span class=\"kf-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".kf-checkbox-box{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-checkbox-box--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}:host{display:inline-block}.kf-checkbox{display:inline-flex;align-items:center;gap:var(--kf-space-sm);cursor:pointer;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-checkbox--disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-checkbox input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kf-checkbox__box{display:inline-flex;align-items:center;justify-content:center}.kf-checkbox input:checked+.kf-checkbox__box,.kf-checkbox input:indeterminate+.kf-checkbox__box{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-checkbox input:checked+.kf-checkbox__box:after{content:\"\";width:var(--kf-checkbox-mark-width);height:var(--kf-checkbox-mark-height);border:var(--kf-checkbox-mark-border);border-width:var(--kf-checkbox-mark-border-width);transform:rotate(45deg) translate(-1px,-1px)}.kf-checkbox input:indeterminate+.kf-checkbox__box:after{content:\"\";width:var(--kf-checkbox-dash-width);height:var(--kf-checkbox-dash-height);background:var(--kf-color-white);border-radius:var(--kf-radius-xs)}.kf-checkbox input:focus-visible+.kf-checkbox__box{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-checkbox__box--invalid{border-color:var(--kf-color-error)}.kf-checkbox--disabled .kf-checkbox__box{opacity:.5}.kf-checkbox__label{-webkit-user-select:none;user-select:none}\n"] });
2106
+ ], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<label class=\"kf-checkbox\" [class.kf-checkbox--disabled]=\"disabled()\">\n <input\n #inputRef\n type=\"checkbox\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (change)=\"onChange($event)\"\n (blur)=\"onTouched()\"\n />\n <span\n class=\"kf-checkbox__box kf-checkbox-box\"\n [class.kf-checkbox__box--invalid]=\"invalid()\"\n ></span>\n @if (label()) {\n <span class=\"kf-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".kf-checkbox-box{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-checkbox-box--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}:host{display:inline-flex}.kf-checkbox{display:inline-flex;align-items:center;gap:var(--kf-space-sm);cursor:pointer;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-checkbox--disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-checkbox input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kf-checkbox__box{display:inline-flex;align-items:center;justify-content:center}.kf-checkbox input:checked+.kf-checkbox__box,.kf-checkbox input:indeterminate+.kf-checkbox__box{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-checkbox input:checked+.kf-checkbox__box:after{content:\"\";position:absolute;inset:0;margin:auto;width:var(--kf-checkbox-mark-width);height:var(--kf-checkbox-mark-height);border:var(--kf-checkbox-mark-border);border-width:var(--kf-checkbox-mark-border-width);transform:rotate(45deg) translate(-1px,-1px)}.kf-checkbox input:indeterminate+.kf-checkbox__box:after{content:\"\";position:absolute;inset:0;margin:auto;width:var(--kf-checkbox-dash-width);height:var(--kf-checkbox-dash-height);background:var(--kf-color-white);border-radius:var(--kf-radius-xs)}.kf-checkbox input:focus-visible+.kf-checkbox__box{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-checkbox__box--invalid{border-color:var(--kf-color-error)}.kf-checkbox--disabled .kf-checkbox__box{opacity:.5}.kf-checkbox__label{-webkit-user-select:none;user-select:none}\n"] });
2054
2107
  }
2055
2108
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Checkbox, decorators: [{
2056
2109
  type: Component,
@@ -2060,7 +2113,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
2060
2113
  useExisting: forwardRef(() => Checkbox),
2061
2114
  multi: true,
2062
2115
  },
2063
- ], template: "<label class=\"kf-checkbox\" [class.kf-checkbox--disabled]=\"disabled()\">\n <input\n #inputRef\n type=\"checkbox\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (change)=\"onChange($event)\"\n (blur)=\"onTouched()\"\n />\n <span\n class=\"kf-checkbox__box kf-checkbox-box\"\n [class.kf-checkbox__box--invalid]=\"invalid()\"\n ></span>\n @if (label()) {\n <span class=\"kf-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".kf-checkbox-box{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-checkbox-box--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}:host{display:inline-block}.kf-checkbox{display:inline-flex;align-items:center;gap:var(--kf-space-sm);cursor:pointer;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-checkbox--disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-checkbox input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kf-checkbox__box{display:inline-flex;align-items:center;justify-content:center}.kf-checkbox input:checked+.kf-checkbox__box,.kf-checkbox input:indeterminate+.kf-checkbox__box{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-checkbox input:checked+.kf-checkbox__box:after{content:\"\";width:var(--kf-checkbox-mark-width);height:var(--kf-checkbox-mark-height);border:var(--kf-checkbox-mark-border);border-width:var(--kf-checkbox-mark-border-width);transform:rotate(45deg) translate(-1px,-1px)}.kf-checkbox input:indeterminate+.kf-checkbox__box:after{content:\"\";width:var(--kf-checkbox-dash-width);height:var(--kf-checkbox-dash-height);background:var(--kf-color-white);border-radius:var(--kf-radius-xs)}.kf-checkbox input:focus-visible+.kf-checkbox__box{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-checkbox__box--invalid{border-color:var(--kf-color-error)}.kf-checkbox--disabled .kf-checkbox__box{opacity:.5}.kf-checkbox__label{-webkit-user-select:none;user-select:none}\n"] }]
2116
+ ], template: "<label class=\"kf-checkbox\" [class.kf-checkbox--disabled]=\"disabled()\">\n <input\n #inputRef\n type=\"checkbox\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (change)=\"onChange($event)\"\n (blur)=\"onTouched()\"\n />\n <span\n class=\"kf-checkbox__box kf-checkbox-box\"\n [class.kf-checkbox__box--invalid]=\"invalid()\"\n ></span>\n @if (label()) {\n <span class=\"kf-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".kf-checkbox-box{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-checkbox-box--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}:host{display:inline-flex}.kf-checkbox{display:inline-flex;align-items:center;gap:var(--kf-space-sm);cursor:pointer;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-checkbox--disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-checkbox input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kf-checkbox__box{display:inline-flex;align-items:center;justify-content:center}.kf-checkbox input:checked+.kf-checkbox__box,.kf-checkbox input:indeterminate+.kf-checkbox__box{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-checkbox input:checked+.kf-checkbox__box:after{content:\"\";position:absolute;inset:0;margin:auto;width:var(--kf-checkbox-mark-width);height:var(--kf-checkbox-mark-height);border:var(--kf-checkbox-mark-border);border-width:var(--kf-checkbox-mark-border-width);transform:rotate(45deg) translate(-1px,-1px)}.kf-checkbox input:indeterminate+.kf-checkbox__box:after{content:\"\";position:absolute;inset:0;margin:auto;width:var(--kf-checkbox-dash-width);height:var(--kf-checkbox-dash-height);background:var(--kf-color-white);border-radius:var(--kf-radius-xs)}.kf-checkbox input:focus-visible+.kf-checkbox__box{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-checkbox__box--invalid{border-color:var(--kf-color-error)}.kf-checkbox--disabled .kf-checkbox__box{opacity:.5}.kf-checkbox__label{-webkit-user-select:none;user-select:none}\n"] }]
2064
2117
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], checkedChange: [{ type: i0.Output, args: ["checkedChange"] }], inputRef: [{ type: i0.ViewChild, args: ['inputRef', { isSignal: true }] }] } });
2065
2118
 
2066
2119
  /**
@@ -2963,6 +3016,12 @@ class Select {
2963
3016
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2964
3017
  /** Borde en rojo y `aria-invalid` en el trigger. Ver `errorMessage` para el mensaje asociado — mismo contrato que `kf-input`. */
2965
3018
  invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3019
+ /**
3020
+ * Pone el asterisco rojo en la etiqueta (igual que `kf-input`) y
3021
+ * `aria-required="true"` en el trigger. Solo señaliza: la validación sigue
3022
+ * en el formulario del consumidor.
3023
+ */
3024
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2966
3025
  /** Mensaje de error con `role="alert"`, debajo del trigger. */
2967
3026
  errorMessage = input(/* @ts-ignore */
2968
3027
  ...(ngDevMode ? [undefined, { debugName: "errorMessage" }] : /* istanbul ignore next */ []));
@@ -3388,7 +3447,7 @@ class Select {
3388
3447
  }
3389
3448
  }
3390
3449
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component });
3391
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Select, isStandalone: true, selector: "kf-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchThreshold: { classPropertyName: "searchThreshold", publicName: "searchThreshold", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, panelTitle: { classPropertyName: "panelTitle", publicName: "panelTitle", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.kf-select--compact": "variant() === 'compact'", "class.kf-select--width-sm": "width() === 'sm'", "class.kf-select--width-lg": "width() === 'lg'", "class.kf-select--width-full": "width() === 'full'", "class.kf-select--width-fit": "width() === 'fit'", "class.kf-select--size-sm": "size() === 'sm'" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }, { propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\" [visuallyHidden]=\"hideLabel()\">{{ label() }}</kf-field-label>\n}\n<button\n #trigger\n type=\"button\"\n [id]=\"triggerId\"\n class=\"kf-select__trigger\"\n [class.kf-select__trigger--disabled]=\"disabled()\"\n [class.kf-select__trigger--invalid]=\"invalid()\"\n [class.kf-select__trigger--with-icon]=\"!!icon()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-label]=\"triggerAriaLabel()\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [class.kf-select__trigger--tagged]=\"!!selectedOption()?.tag\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-select__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n @if (prefix(); as prefixText) {\n <span class=\"kf-select__prefix\">{{ prefixText }}</span>\n }\n <span\n class=\"kf-select__value\"\n [class.kf-select__value--placeholder]=\"!selectedOption()\"\n [class.kf-select__value--fit]=\"width() === 'fit'\"\n >\n @if (width() === 'fit') {\n <span class=\"kf-select__value-text\">{{ triggerText() }}</span>\n <!-- Reserva el ancho de la opci\u00F3n m\u00E1s larga: oculto a la vista y al\n \u00E1rbol de accesibilidad, solo aporta tama\u00F1o. -->\n <span class=\"kf-select__sizer\" aria-hidden=\"true\">\n @for (text of fitTexts(); track text) {\n <span>{{ text }}</span>\n }\n </span>\n } @else {\n {{ triggerText() }}\n }\n </span>\n @if (width() === 'fit' && fitTags().length) {\n <!-- Con `fit` el hueco del tag se reserva siempre con el m\u00E1s ancho: los\n dem\u00E1s se apilan en la misma celda y solo el elegido se ve. -->\n <span class=\"kf-select__tag-slot\">\n @for (tag of fitTags(); track tag) {\n <kf-badge\n class=\"kf-select__tag\"\n [class.kf-select__tag--reserved]=\"tag !== selectedOption()?.tag\"\n [attr.aria-hidden]=\"tag !== selectedOption()?.tag ? 'true' : null\"\n >{{ tag }}</kf-badge\n >\n }\n </span>\n } @else if (selectedOption()?.tag; as tag) {\n <kf-badge class=\"kf-select__tag\">{{ tag }}</kf-badge>\n }\n <span\n class=\"kf-select__caret kf-caret\"\n [class.kf-select__caret--open]=\"isOpen()\"\n [class.kf-caret--open]=\"isOpen()\"\n aria-hidden=\"true\"\n ></span>\n</button>\n@if (errorMessage(); as message) {\n <span class=\"kf-select__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n}\n<ng-template #panelTemplate>\n <div #panel class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (panelTitle(); as title) {\n <div class=\"kf-select__panel-title kf-overline-text\" aria-hidden=\"true\">{{ title }}</div>\n }\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\n aria-label=\"Buscar opci\u00F3n\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"filteredOptions().length ? optionId(activeIndex()) : null\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n (keydown.enter)=\"$event.preventDefault(); selectActive()\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n }\n <ul\n class=\"kf-select__list\"\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : triggerId\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [id]=\"optionId(i)\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"-1\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-label]=\"optionAriaLabel(option)\"\n [class.kf-select__option--rich]=\"!!(option.tag || option.detail)\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown)=\"onOptionKeydown($event, option, i)\"\n >\n @if (option.tag || option.detail) {\n <span class=\"kf-select__option-main\">\n <span class=\"kf-select__option-label\">{{ option.label }}</span>\n @if (option.tag) {\n <kf-badge class=\"kf-select__tag\">{{ option.tag }}</kf-badge>\n }\n </span>\n @if (option.detail) {\n <span class=\"kf-select__option-detail\">{{ option.detail }}</span>\n }\n } @else {\n {{ option.label }}\n }\n </li>\n } @empty {\n <li class=\"kf-select__empty\">\n {{ searchQuery() ? 'Sin resultados' : 'Sin opciones disponibles' }}\n </li>\n }\n </ul>\n </div>\n</ng-template>\n", styles: [".kf-caret{flex-shrink:0;width:8px;height:8px;border-right:2px solid var(--kf-color-text-muted);border-bottom:2px solid var(--kf-color-text-muted);transform:rotate(45deg);transition:transform .14s;margin-top:-4px}.kf-caret--open{transform:rotate(-135deg);margin-top:4px}.kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:var(--kf-select-width-md);font-family:var(--kf-font-body)}:host(.kf-select--compact){width:max-content;max-width:160px}:host(.kf-select--width-sm){width:var(--kf-select-width-sm)}:host(.kf-select--width-lg){width:var(--kf-select-width-lg)}:host(.kf-select--width-full){width:100%}:host(.kf-select--width-fit){width:max-content;max-width:var(--kf-select-fit-max-width, 20rem)}:host(.kf-select--compact) .kf-select__trigger{padding:6px var(--kf-space-sm);font-size:.85rem;gap:var(--kf-space-xs)}:host(.kf-select--compact) .kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);background:var(--kf-color-white);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}:host(.kf-select--size-sm){--kf-select-min-height: 2rem}:host(.kf-select--size-sm) .kf-select__trigger{box-sizing:border-box;min-height:var(--kf-select-min-height);padding-block:0}:host(.kf-select--size-sm:not(.kf-select--compact)) .kf-select__trigger{font-size:var(--kf-font-size-body-sm)}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-text-muted)}.kf-select__trigger:focus-visible{outline:none;border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-select__trigger--disabled{opacity:.5;cursor:not-allowed}.kf-select__trigger--invalid{border-color:var(--kf-color-error)}.kf-select__trigger--invalid:focus-visible{border-color:var(--kf-color-error);box-shadow:var(--kf-shadow-focus-error)}.kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--fit{display:grid;grid-template-columns:minmax(0,1fr);text-align:start}.kf-select__value-text{grid-area:1 / 1;overflow:hidden;text-overflow:ellipsis}.kf-select__sizer{grid-area:1 / 1;display:grid;height:0;overflow:hidden;visibility:hidden}.kf-select__sizer>span{grid-area:1 / 1;white-space:nowrap}.kf-select__icon{flex:none;color:var(--kf-color-text-muted)}.kf-select__trigger--with-icon .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}:host(.kf-select--compact) .kf-select__trigger--with-icon .kf-select__value{color:var(--kf-color-ink);font-weight:600}.kf-select__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__tag-slot{display:grid;flex:none;justify-items:end}.kf-select__tag-slot>.kf-select__tag{grid-area:1 / 1}.kf-select__tag--reserved{visibility:hidden}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__prefix{flex:none;color:var(--kf-color-text-muted);white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;font-family:var(--kf-font-body);width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md);overflow:hidden}.kf-select__panel-title{padding:var(--kf-space-sm) var(--kf-space-md) var(--kf-space-xs)}.kf-select__panel--compact .kf-select__panel-title{padding:var(--kf-space-xs) var(--kf-space-sm) 2px}.kf-select__search{box-sizing:border-box;width:100%;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-bottom:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm) var(--kf-radius-sm) 0 0;outline:none}.kf-select__search:focus-visible{box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__list{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--kf-color-gray-400) transparent}.kf-select__list::-webkit-scrollbar{width:6px}.kf-select__list::-webkit-scrollbar-track{background:transparent}.kf-select__list::-webkit-scrollbar-thumb{background-color:var(--kf-color-gray-400);border-radius:var(--kf-radius-pill)}.kf-select__list::-webkit-scrollbar-thumb:hover{background-color:var(--kf-color-gray-500)}.kf-select__option{padding:var(--kf-space-sm) var(--kf-space-md);outline:none;color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kf-select__option--rich{display:flex;flex-direction:column;gap:2px}.kf-select__option-main{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);min-width:0}.kf-select__option-label,.kf-select__option-detail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.kf-select__option-detail{font-size:var(--kf-font-size-body-sm);font-weight:400;color:var(--kf-color-text-muted)}.kf-select__panel--compact .kf-select__option{padding:6px var(--kf-space-sm);font-size:.85rem}.kf-select__option:hover{background:var(--kf-color-primary-soft)}.kf-select__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select__option--active{background:var(--kf-color-primary-soft)}.kf-select__option:focus-visible{background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"], dependencies: [{ kind: "component", type: Badge, selector: "kf-badge", inputs: ["tone", "variant", "dot", "truncate"] }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required", "visuallyHidden"] }, { kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
3450
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Select, isStandalone: true, selector: "kf-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchThreshold: { classPropertyName: "searchThreshold", publicName: "searchThreshold", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, panelTitle: { classPropertyName: "panelTitle", publicName: "panelTitle", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.kf-select--compact": "variant() === 'compact'", "class.kf-select--width-sm": "width() === 'sm'", "class.kf-select--width-lg": "width() === 'lg'", "class.kf-select--width-full": "width() === 'full'", "class.kf-select--width-fit": "width() === 'fit'", "class.kf-select--size-sm": "size() === 'sm'" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }, { propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\" [required]=\"required()\" [visuallyHidden]=\"hideLabel()\">{{\n label()\n }}</kf-field-label>\n}\n<button\n #trigger\n type=\"button\"\n [id]=\"triggerId\"\n class=\"kf-select__trigger\"\n [class.kf-select__trigger--disabled]=\"disabled()\"\n [class.kf-select__trigger--invalid]=\"invalid()\"\n [class.kf-select__trigger--with-icon]=\"!!icon()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-label]=\"triggerAriaLabel()\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [class.kf-select__trigger--tagged]=\"!!selectedOption()?.tag\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-select__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n @if (prefix(); as prefixText) {\n <span class=\"kf-select__prefix\">{{ prefixText }}</span>\n }\n <span\n class=\"kf-select__value\"\n [class.kf-select__value--placeholder]=\"!selectedOption()\"\n [class.kf-select__value--fit]=\"width() === 'fit'\"\n >\n @if (width() === 'fit') {\n <span class=\"kf-select__value-text\">{{ triggerText() }}</span>\n <!-- Reserva el ancho de la opci\u00F3n m\u00E1s larga: oculto a la vista y al\n \u00E1rbol de accesibilidad, solo aporta tama\u00F1o. -->\n <span class=\"kf-select__sizer\" aria-hidden=\"true\">\n @for (text of fitTexts(); track text) {\n <span>{{ text }}</span>\n }\n </span>\n } @else {\n {{ triggerText() }}\n }\n </span>\n @if (width() === 'fit' && fitTags().length) {\n <!-- Con `fit` el hueco del tag se reserva siempre con el m\u00E1s ancho: los\n dem\u00E1s se apilan en la misma celda y solo el elegido se ve. -->\n <span class=\"kf-select__tag-slot\">\n @for (tag of fitTags(); track tag) {\n <kf-badge\n class=\"kf-select__tag\"\n [class.kf-select__tag--reserved]=\"tag !== selectedOption()?.tag\"\n [attr.aria-hidden]=\"tag !== selectedOption()?.tag ? 'true' : null\"\n >{{ tag }}</kf-badge\n >\n }\n </span>\n } @else if (selectedOption()?.tag; as tag) {\n <kf-badge class=\"kf-select__tag\">{{ tag }}</kf-badge>\n }\n <span\n class=\"kf-select__caret kf-caret\"\n [class.kf-select__caret--open]=\"isOpen()\"\n [class.kf-caret--open]=\"isOpen()\"\n aria-hidden=\"true\"\n ></span>\n</button>\n@if (errorMessage(); as message) {\n <span class=\"kf-select__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n}\n<ng-template #panelTemplate>\n <div #panel class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (panelTitle(); as title) {\n <div class=\"kf-select__panel-title kf-overline-text\" aria-hidden=\"true\">{{ title }}</div>\n }\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\n aria-label=\"Buscar opci\u00F3n\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"filteredOptions().length ? optionId(activeIndex()) : null\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n (keydown.enter)=\"$event.preventDefault(); selectActive()\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n }\n <ul\n class=\"kf-select__list\"\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : triggerId\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [id]=\"optionId(i)\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"-1\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-label]=\"optionAriaLabel(option)\"\n [class.kf-select__option--rich]=\"!!(option.tag || option.detail)\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown)=\"onOptionKeydown($event, option, i)\"\n >\n @if (option.tag || option.detail) {\n <span class=\"kf-select__option-main\">\n <span class=\"kf-select__option-label\">{{ option.label }}</span>\n @if (option.tag) {\n <kf-badge class=\"kf-select__tag\">{{ option.tag }}</kf-badge>\n }\n </span>\n @if (option.detail) {\n <span class=\"kf-select__option-detail\">{{ option.detail }}</span>\n }\n } @else {\n {{ option.label }}\n }\n </li>\n } @empty {\n <li class=\"kf-select__empty\">\n {{ searchQuery() ? 'Sin resultados' : 'Sin opciones disponibles' }}\n </li>\n }\n </ul>\n </div>\n</ng-template>\n", styles: [".kf-caret{flex-shrink:0;width:8px;height:8px;border-right:2px solid var(--kf-color-text-muted);border-bottom:2px solid var(--kf-color-text-muted);transform:rotate(45deg);transition:transform .14s;margin-top:-4px}.kf-caret--open{transform:rotate(-135deg);margin-top:4px}.kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:var(--kf-select-width-md);font-family:var(--kf-font-body)}:host(.kf-select--compact){width:max-content;max-width:160px}:host(.kf-select--width-sm){width:var(--kf-select-width-sm)}:host(.kf-select--width-lg){width:var(--kf-select-width-lg)}:host(.kf-select--width-full){width:100%}:host(.kf-select--width-fit){width:max-content;max-width:var(--kf-select-fit-max-width, 20rem)}:host(.kf-select--compact) .kf-select__trigger{padding:6px var(--kf-space-sm);font-size:.85rem;gap:var(--kf-space-xs)}:host(.kf-select--compact) .kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);background:var(--kf-color-white);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}:host(.kf-select--size-sm){--kf-select-min-height: 2rem}:host(.kf-select--size-sm) .kf-select__trigger{box-sizing:border-box;min-height:var(--kf-select-min-height);padding-block:0}:host(.kf-select--size-sm:not(.kf-select--compact)) .kf-select__trigger{font-size:var(--kf-font-size-body-sm)}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-text-muted)}.kf-select__trigger:focus-visible{outline:none;border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-select__trigger--disabled{opacity:.5;cursor:not-allowed}.kf-select__trigger--invalid{border-color:var(--kf-color-error)}.kf-select__trigger--invalid:focus-visible{border-color:var(--kf-color-error);box-shadow:var(--kf-shadow-focus-error)}.kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--fit{display:grid;grid-template-columns:minmax(0,1fr);text-align:start}.kf-select__value-text{grid-area:1 / 1;overflow:hidden;text-overflow:ellipsis}.kf-select__sizer{grid-area:1 / 1;display:grid;height:0;overflow:hidden;visibility:hidden}.kf-select__sizer>span{grid-area:1 / 1;white-space:nowrap}.kf-select__icon{flex:none;color:var(--kf-color-text-muted)}.kf-select__trigger--with-icon .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}:host(.kf-select--compact) .kf-select__trigger--with-icon .kf-select__value{color:var(--kf-color-ink);font-weight:600}.kf-select__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__tag-slot{display:grid;flex:none;justify-items:end}.kf-select__tag-slot>.kf-select__tag{grid-area:1 / 1}.kf-select__tag--reserved{visibility:hidden}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__prefix{flex:none;color:var(--kf-color-text-muted);white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;font-family:var(--kf-font-body);width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md);overflow:hidden}.kf-select__panel-title{padding:var(--kf-space-sm) var(--kf-space-md) var(--kf-space-xs)}.kf-select__panel--compact .kf-select__panel-title{padding:var(--kf-space-xs) var(--kf-space-sm) 2px}.kf-select__search{box-sizing:border-box;width:100%;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-bottom:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm) var(--kf-radius-sm) 0 0;outline:none}.kf-select__search:focus-visible{box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__list{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--kf-color-gray-400) transparent}.kf-select__list::-webkit-scrollbar{width:6px}.kf-select__list::-webkit-scrollbar-track{background:transparent}.kf-select__list::-webkit-scrollbar-thumb{background-color:var(--kf-color-gray-400);border-radius:var(--kf-radius-pill)}.kf-select__list::-webkit-scrollbar-thumb:hover{background-color:var(--kf-color-gray-500)}.kf-select__option{padding:var(--kf-space-sm) var(--kf-space-md);outline:none;color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kf-select__option--rich{display:flex;flex-direction:column;gap:2px}.kf-select__option-main{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);min-width:0}.kf-select__option-label,.kf-select__option-detail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.kf-select__option-detail{font-size:var(--kf-font-size-body-sm);font-weight:400;color:var(--kf-color-text-muted)}.kf-select__panel--compact .kf-select__option{padding:6px var(--kf-space-sm);font-size:.85rem}.kf-select__option:hover{background:var(--kf-color-primary-soft)}.kf-select__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select__option--active{background:var(--kf-color-primary-soft)}.kf-select__option:focus-visible{background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"], dependencies: [{ kind: "component", type: Badge, selector: "kf-badge", inputs: ["tone", "variant", "dot", "truncate"] }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required", "visuallyHidden"] }, { kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
3392
3451
  }
3393
3452
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, decorators: [{
3394
3453
  type: Component,
@@ -3399,8 +3458,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
3399
3458
  '[class.kf-select--width-full]': "width() === 'full'",
3400
3459
  '[class.kf-select--width-fit]': "width() === 'fit'",
3401
3460
  '[class.kf-select--size-sm]': "size() === 'sm'",
3402
- }, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\" [visuallyHidden]=\"hideLabel()\">{{ label() }}</kf-field-label>\n}\n<button\n #trigger\n type=\"button\"\n [id]=\"triggerId\"\n class=\"kf-select__trigger\"\n [class.kf-select__trigger--disabled]=\"disabled()\"\n [class.kf-select__trigger--invalid]=\"invalid()\"\n [class.kf-select__trigger--with-icon]=\"!!icon()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-label]=\"triggerAriaLabel()\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [class.kf-select__trigger--tagged]=\"!!selectedOption()?.tag\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-select__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n @if (prefix(); as prefixText) {\n <span class=\"kf-select__prefix\">{{ prefixText }}</span>\n }\n <span\n class=\"kf-select__value\"\n [class.kf-select__value--placeholder]=\"!selectedOption()\"\n [class.kf-select__value--fit]=\"width() === 'fit'\"\n >\n @if (width() === 'fit') {\n <span class=\"kf-select__value-text\">{{ triggerText() }}</span>\n <!-- Reserva el ancho de la opci\u00F3n m\u00E1s larga: oculto a la vista y al\n \u00E1rbol de accesibilidad, solo aporta tama\u00F1o. -->\n <span class=\"kf-select__sizer\" aria-hidden=\"true\">\n @for (text of fitTexts(); track text) {\n <span>{{ text }}</span>\n }\n </span>\n } @else {\n {{ triggerText() }}\n }\n </span>\n @if (width() === 'fit' && fitTags().length) {\n <!-- Con `fit` el hueco del tag se reserva siempre con el m\u00E1s ancho: los\n dem\u00E1s se apilan en la misma celda y solo el elegido se ve. -->\n <span class=\"kf-select__tag-slot\">\n @for (tag of fitTags(); track tag) {\n <kf-badge\n class=\"kf-select__tag\"\n [class.kf-select__tag--reserved]=\"tag !== selectedOption()?.tag\"\n [attr.aria-hidden]=\"tag !== selectedOption()?.tag ? 'true' : null\"\n >{{ tag }}</kf-badge\n >\n }\n </span>\n } @else if (selectedOption()?.tag; as tag) {\n <kf-badge class=\"kf-select__tag\">{{ tag }}</kf-badge>\n }\n <span\n class=\"kf-select__caret kf-caret\"\n [class.kf-select__caret--open]=\"isOpen()\"\n [class.kf-caret--open]=\"isOpen()\"\n aria-hidden=\"true\"\n ></span>\n</button>\n@if (errorMessage(); as message) {\n <span class=\"kf-select__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n}\n<ng-template #panelTemplate>\n <div #panel class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (panelTitle(); as title) {\n <div class=\"kf-select__panel-title kf-overline-text\" aria-hidden=\"true\">{{ title }}</div>\n }\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\n aria-label=\"Buscar opci\u00F3n\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"filteredOptions().length ? optionId(activeIndex()) : null\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n (keydown.enter)=\"$event.preventDefault(); selectActive()\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n }\n <ul\n class=\"kf-select__list\"\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : triggerId\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [id]=\"optionId(i)\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"-1\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-label]=\"optionAriaLabel(option)\"\n [class.kf-select__option--rich]=\"!!(option.tag || option.detail)\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown)=\"onOptionKeydown($event, option, i)\"\n >\n @if (option.tag || option.detail) {\n <span class=\"kf-select__option-main\">\n <span class=\"kf-select__option-label\">{{ option.label }}</span>\n @if (option.tag) {\n <kf-badge class=\"kf-select__tag\">{{ option.tag }}</kf-badge>\n }\n </span>\n @if (option.detail) {\n <span class=\"kf-select__option-detail\">{{ option.detail }}</span>\n }\n } @else {\n {{ option.label }}\n }\n </li>\n } @empty {\n <li class=\"kf-select__empty\">\n {{ searchQuery() ? 'Sin resultados' : 'Sin opciones disponibles' }}\n </li>\n }\n </ul>\n </div>\n</ng-template>\n", styles: [".kf-caret{flex-shrink:0;width:8px;height:8px;border-right:2px solid var(--kf-color-text-muted);border-bottom:2px solid var(--kf-color-text-muted);transform:rotate(45deg);transition:transform .14s;margin-top:-4px}.kf-caret--open{transform:rotate(-135deg);margin-top:4px}.kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:var(--kf-select-width-md);font-family:var(--kf-font-body)}:host(.kf-select--compact){width:max-content;max-width:160px}:host(.kf-select--width-sm){width:var(--kf-select-width-sm)}:host(.kf-select--width-lg){width:var(--kf-select-width-lg)}:host(.kf-select--width-full){width:100%}:host(.kf-select--width-fit){width:max-content;max-width:var(--kf-select-fit-max-width, 20rem)}:host(.kf-select--compact) .kf-select__trigger{padding:6px var(--kf-space-sm);font-size:.85rem;gap:var(--kf-space-xs)}:host(.kf-select--compact) .kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);background:var(--kf-color-white);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}:host(.kf-select--size-sm){--kf-select-min-height: 2rem}:host(.kf-select--size-sm) .kf-select__trigger{box-sizing:border-box;min-height:var(--kf-select-min-height);padding-block:0}:host(.kf-select--size-sm:not(.kf-select--compact)) .kf-select__trigger{font-size:var(--kf-font-size-body-sm)}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-text-muted)}.kf-select__trigger:focus-visible{outline:none;border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-select__trigger--disabled{opacity:.5;cursor:not-allowed}.kf-select__trigger--invalid{border-color:var(--kf-color-error)}.kf-select__trigger--invalid:focus-visible{border-color:var(--kf-color-error);box-shadow:var(--kf-shadow-focus-error)}.kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--fit{display:grid;grid-template-columns:minmax(0,1fr);text-align:start}.kf-select__value-text{grid-area:1 / 1;overflow:hidden;text-overflow:ellipsis}.kf-select__sizer{grid-area:1 / 1;display:grid;height:0;overflow:hidden;visibility:hidden}.kf-select__sizer>span{grid-area:1 / 1;white-space:nowrap}.kf-select__icon{flex:none;color:var(--kf-color-text-muted)}.kf-select__trigger--with-icon .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}:host(.kf-select--compact) .kf-select__trigger--with-icon .kf-select__value{color:var(--kf-color-ink);font-weight:600}.kf-select__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__tag-slot{display:grid;flex:none;justify-items:end}.kf-select__tag-slot>.kf-select__tag{grid-area:1 / 1}.kf-select__tag--reserved{visibility:hidden}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__prefix{flex:none;color:var(--kf-color-text-muted);white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;font-family:var(--kf-font-body);width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md);overflow:hidden}.kf-select__panel-title{padding:var(--kf-space-sm) var(--kf-space-md) var(--kf-space-xs)}.kf-select__panel--compact .kf-select__panel-title{padding:var(--kf-space-xs) var(--kf-space-sm) 2px}.kf-select__search{box-sizing:border-box;width:100%;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-bottom:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm) var(--kf-radius-sm) 0 0;outline:none}.kf-select__search:focus-visible{box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__list{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--kf-color-gray-400) transparent}.kf-select__list::-webkit-scrollbar{width:6px}.kf-select__list::-webkit-scrollbar-track{background:transparent}.kf-select__list::-webkit-scrollbar-thumb{background-color:var(--kf-color-gray-400);border-radius:var(--kf-radius-pill)}.kf-select__list::-webkit-scrollbar-thumb:hover{background-color:var(--kf-color-gray-500)}.kf-select__option{padding:var(--kf-space-sm) var(--kf-space-md);outline:none;color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kf-select__option--rich{display:flex;flex-direction:column;gap:2px}.kf-select__option-main{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);min-width:0}.kf-select__option-label,.kf-select__option-detail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.kf-select__option-detail{font-size:var(--kf-font-size-body-sm);font-weight:400;color:var(--kf-color-text-muted)}.kf-select__panel--compact .kf-select__option{padding:6px var(--kf-space-sm);font-size:.85rem}.kf-select__option:hover{background:var(--kf-color-primary-soft)}.kf-select__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select__option--active{background:var(--kf-color-primary-soft)}.kf-select__option:focus-visible{background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
3403
- }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchThreshold", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], panelTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelTitle", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelTemplate: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], searchInputRef: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
3461
+ }, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\" [required]=\"required()\" [visuallyHidden]=\"hideLabel()\">{{\n label()\n }}</kf-field-label>\n}\n<button\n #trigger\n type=\"button\"\n [id]=\"triggerId\"\n class=\"kf-select__trigger\"\n [class.kf-select__trigger--disabled]=\"disabled()\"\n [class.kf-select__trigger--invalid]=\"invalid()\"\n [class.kf-select__trigger--with-icon]=\"!!icon()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-label]=\"triggerAriaLabel()\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [attr.aria-required]=\"required() ? true : null\"\n [class.kf-select__trigger--tagged]=\"!!selectedOption()?.tag\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-select__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n @if (prefix(); as prefixText) {\n <span class=\"kf-select__prefix\">{{ prefixText }}</span>\n }\n <span\n class=\"kf-select__value\"\n [class.kf-select__value--placeholder]=\"!selectedOption()\"\n [class.kf-select__value--fit]=\"width() === 'fit'\"\n >\n @if (width() === 'fit') {\n <span class=\"kf-select__value-text\">{{ triggerText() }}</span>\n <!-- Reserva el ancho de la opci\u00F3n m\u00E1s larga: oculto a la vista y al\n \u00E1rbol de accesibilidad, solo aporta tama\u00F1o. -->\n <span class=\"kf-select__sizer\" aria-hidden=\"true\">\n @for (text of fitTexts(); track text) {\n <span>{{ text }}</span>\n }\n </span>\n } @else {\n {{ triggerText() }}\n }\n </span>\n @if (width() === 'fit' && fitTags().length) {\n <!-- Con `fit` el hueco del tag se reserva siempre con el m\u00E1s ancho: los\n dem\u00E1s se apilan en la misma celda y solo el elegido se ve. -->\n <span class=\"kf-select__tag-slot\">\n @for (tag of fitTags(); track tag) {\n <kf-badge\n class=\"kf-select__tag\"\n [class.kf-select__tag--reserved]=\"tag !== selectedOption()?.tag\"\n [attr.aria-hidden]=\"tag !== selectedOption()?.tag ? 'true' : null\"\n >{{ tag }}</kf-badge\n >\n }\n </span>\n } @else if (selectedOption()?.tag; as tag) {\n <kf-badge class=\"kf-select__tag\">{{ tag }}</kf-badge>\n }\n <span\n class=\"kf-select__caret kf-caret\"\n [class.kf-select__caret--open]=\"isOpen()\"\n [class.kf-caret--open]=\"isOpen()\"\n aria-hidden=\"true\"\n ></span>\n</button>\n@if (errorMessage(); as message) {\n <span class=\"kf-select__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n}\n<ng-template #panelTemplate>\n <div #panel class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (panelTitle(); as title) {\n <div class=\"kf-select__panel-title kf-overline-text\" aria-hidden=\"true\">{{ title }}</div>\n }\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\n aria-label=\"Buscar opci\u00F3n\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"filteredOptions().length ? optionId(activeIndex()) : null\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n (keydown.enter)=\"$event.preventDefault(); selectActive()\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n }\n <ul\n class=\"kf-select__list\"\n [id]=\"listboxId\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabel() ? null : triggerId\"\n >\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [id]=\"optionId(i)\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"-1\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-label]=\"optionAriaLabel(option)\"\n [class.kf-select__option--rich]=\"!!(option.tag || option.detail)\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown)=\"onOptionKeydown($event, option, i)\"\n >\n @if (option.tag || option.detail) {\n <span class=\"kf-select__option-main\">\n <span class=\"kf-select__option-label\">{{ option.label }}</span>\n @if (option.tag) {\n <kf-badge class=\"kf-select__tag\">{{ option.tag }}</kf-badge>\n }\n </span>\n @if (option.detail) {\n <span class=\"kf-select__option-detail\">{{ option.detail }}</span>\n }\n } @else {\n {{ option.label }}\n }\n </li>\n } @empty {\n <li class=\"kf-select__empty\">\n {{ searchQuery() ? 'Sin resultados' : 'Sin opciones disponibles' }}\n </li>\n }\n </ul>\n </div>\n</ng-template>\n", styles: [".kf-caret{flex-shrink:0;width:8px;height:8px;border-right:2px solid var(--kf-color-text-muted);border-bottom:2px solid var(--kf-color-text-muted);transform:rotate(45deg);transition:transform .14s;margin-top:-4px}.kf-caret--open{transform:rotate(-135deg);margin-top:4px}.kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:var(--kf-select-width-md);font-family:var(--kf-font-body)}:host(.kf-select--compact){width:max-content;max-width:160px}:host(.kf-select--width-sm){width:var(--kf-select-width-sm)}:host(.kf-select--width-lg){width:var(--kf-select-width-lg)}:host(.kf-select--width-full){width:100%}:host(.kf-select--width-fit){width:max-content;max-width:var(--kf-select-fit-max-width, 20rem)}:host(.kf-select--compact) .kf-select__trigger{padding:6px var(--kf-space-sm);font-size:.85rem;gap:var(--kf-space-xs)}:host(.kf-select--compact) .kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);background:var(--kf-color-white);border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}:host(.kf-select--size-sm){--kf-select-min-height: 2rem}:host(.kf-select--size-sm) .kf-select__trigger{box-sizing:border-box;min-height:var(--kf-select-min-height);padding-block:0}:host(.kf-select--size-sm:not(.kf-select--compact)) .kf-select__trigger{font-size:var(--kf-font-size-body-sm)}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-text-muted)}.kf-select__trigger:focus-visible{outline:none;border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-select__trigger--disabled{opacity:.5;cursor:not-allowed}.kf-select__trigger--invalid{border-color:var(--kf-color-error)}.kf-select__trigger--invalid:focus-visible{border-color:var(--kf-color-error);box-shadow:var(--kf-shadow-focus-error)}.kf-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--fit{display:grid;grid-template-columns:minmax(0,1fr);text-align:start}.kf-select__value-text{grid-area:1 / 1;overflow:hidden;text-overflow:ellipsis}.kf-select__sizer{grid-area:1 / 1;display:grid;height:0;overflow:hidden;visibility:hidden}.kf-select__sizer>span{grid-area:1 / 1;white-space:nowrap}.kf-select__icon{flex:none;color:var(--kf-color-text-muted)}.kf-select__trigger--with-icon .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}:host(.kf-select--compact) .kf-select__trigger--with-icon .kf-select__value{color:var(--kf-color-ink);font-weight:600}.kf-select__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__tag-slot{display:grid;flex:none;justify-items:end}.kf-select__tag-slot>.kf-select__tag{grid-area:1 / 1}.kf-select__tag--reserved{visibility:hidden}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__prefix{flex:none;color:var(--kf-color-text-muted);white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;font-family:var(--kf-font-body);width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md);overflow:hidden}.kf-select__panel-title{padding:var(--kf-space-sm) var(--kf-space-md) var(--kf-space-xs)}.kf-select__panel--compact .kf-select__panel-title{padding:var(--kf-space-xs) var(--kf-space-sm) 2px}.kf-select__search{box-sizing:border-box;width:100%;font:inherit;font-family:var(--kf-font-body);color:var(--kf-color-text);padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-bottom:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm) var(--kf-radius-sm) 0 0;outline:none}.kf-select__search:focus-visible{box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__list{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--kf-color-gray-400) transparent}.kf-select__list::-webkit-scrollbar{width:6px}.kf-select__list::-webkit-scrollbar-track{background:transparent}.kf-select__list::-webkit-scrollbar-thumb{background-color:var(--kf-color-gray-400);border-radius:var(--kf-radius-pill)}.kf-select__list::-webkit-scrollbar-thumb:hover{background-color:var(--kf-color-gray-500)}.kf-select__option{padding:var(--kf-space-sm) var(--kf-space-md);outline:none;color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kf-select__option--rich{display:flex;flex-direction:column;gap:2px}.kf-select__option-main{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);min-width:0}.kf-select__option-label,.kf-select__option-detail{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.kf-select__option-detail{font-size:var(--kf-font-size-body-sm);font-weight:400;color:var(--kf-color-text-muted)}.kf-select__panel--compact .kf-select__option{padding:6px var(--kf-space-sm);font-size:.85rem}.kf-select__option:hover{background:var(--kf-color-primary-soft)}.kf-select__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select__option--active{background:var(--kf-color-primary-soft)}.kf-select__option:focus-visible{background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 2px var(--kf-color-primary)}.kf-select__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
3462
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchThreshold", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], panelTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelTitle", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelTemplate: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], searchInputRef: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
3404
3463
 
3405
3464
  const SIBLINGS = 1;
3406
3465
  /**
@@ -3474,7 +3533,7 @@ class Pagination {
3474
3533
  this.pageChange.emit(clamped);
3475
3534
  }
3476
3535
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Pagination, deps: [], target: i0.ɵɵFactoryTarget.Component });
3477
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Pagination, isStandalone: true, selector: "kf-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pages: { classPropertyName: "pages", publicName: "pages", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSize: "pageSizeChange" }, ngImport: i0, template: "<div class=\"kf-pagination\">\n <div class=\"kf-pagination__info kf-caption-text\" aria-live=\"polite\">\n <ng-content />\n </div>\n\n <div class=\"kf-pagination__controls\">\n @if (pageSizeOptions().length > 0) {\n <div class=\"kf-pagination__size\">\n <span class=\"kf-pagination__size-label kf-caption-text\">Filas</span>\n <kf-select\n variant=\"compact\"\n ariaLabel=\"Filas por p\u00E1gina\"\n [options]=\"pageSizeSelectOptions()\"\n [value]=\"pageSizeValue()\"\n (valueChange)=\"setPageSize($event)\"\n />\n </div>\n @if (hasNav()) {\n <div class=\"kf-pagination__divider\" aria-hidden=\"true\"></div>\n }\n }\n\n @if (hasNav()) {\n <nav class=\"kf-pagination__nav\" aria-label=\"Paginaci\u00F3n\">\n <button\n type=\"button\"\n class=\"kf-pagination__control\"\n [disabled]=\"page() <= 1\"\n aria-label=\"P\u00E1gina anterior\"\n (click)=\"goTo(page() - 1)\"\n >\n \u2039\n </button>\n\n @for (item of items(); track $index) {\n @if (item.type === 'page') {\n <button\n type=\"button\"\n class=\"kf-pagination__page\"\n [class.kf-pagination__page--active]=\"item.page === page()\"\n [attr.aria-current]=\"item.page === page() ? 'page' : null\"\n [attr.aria-label]=\"'Ir a la p\u00E1gina ' + item.page\"\n (click)=\"goTo(item.page)\"\n >\n {{ item.page }}\n </button>\n } @else {\n <span class=\"kf-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n }\n }\n\n <button\n type=\"button\"\n class=\"kf-pagination__control\"\n [disabled]=\"page() >= pages()\"\n aria-label=\"P\u00E1gina siguiente\"\n (click)=\"goTo(page() + 1)\"\n >\n \u203A\n </button>\n </nav>\n }\n </div>\n</div>\n", styles: [".kf-caption-text{font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}:host{display:block;font-family:var(--kf-font-body)}.kf-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-md);flex-wrap:wrap}.kf-pagination__info:empty{display:none}.kf-pagination__controls{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kf-space-sm) var(--kf-space-md)}.kf-pagination__size{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-pagination__size-label{white-space:nowrap}.kf-pagination__divider{width:1px;height:1.25rem;background:var(--kf-color-border)}.kf-pagination__nav{display:flex;align-items:center;gap:var(--kf-space-xs)}.kf-pagination__control,.kf-pagination__page{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;padding:0 var(--kf-space-xs);font:inherit;font-size:.85rem;color:var(--kf-color-text);background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);cursor:pointer;transition:background .14s,border-color .14s,color .14s}.kf-pagination__control:hover:not(:disabled),.kf-pagination__page:hover:not(.kf-pagination__page--active){background:var(--kf-color-surface);border-color:var(--kf-color-border-strong)}.kf-pagination__control:focus-visible,.kf-pagination__page:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-pagination__control:disabled{opacity:.5;cursor:not-allowed}.kf-pagination__page--active{color:var(--kf-color-white);background:var(--kf-color-primary);border-color:var(--kf-color-primary);cursor:default}.kf-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--kf-color-text-muted)}@media(max-width:480px){.kf-pagination__controls{width:100%}.kf-pagination__divider{display:none}}\n"], dependencies: [{ kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
3536
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Pagination, isStandalone: true, selector: "kf-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pages: { classPropertyName: "pages", publicName: "pages", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSize: "pageSizeChange" }, ngImport: i0, template: "<div class=\"kf-pagination\">\n <div class=\"kf-pagination__info kf-caption-text\" aria-live=\"polite\">\n <ng-content />\n </div>\n\n <div class=\"kf-pagination__controls\">\n @if (pageSizeOptions().length > 0) {\n <div class=\"kf-pagination__size\">\n <span class=\"kf-pagination__size-label kf-caption-text\">Filas</span>\n <kf-select\n variant=\"compact\"\n ariaLabel=\"Filas por p\u00E1gina\"\n [options]=\"pageSizeSelectOptions()\"\n [value]=\"pageSizeValue()\"\n (valueChange)=\"setPageSize($event)\"\n />\n </div>\n @if (hasNav()) {\n <div class=\"kf-pagination__divider\" aria-hidden=\"true\"></div>\n }\n }\n\n @if (hasNav()) {\n <nav class=\"kf-pagination__nav\" aria-label=\"Paginaci\u00F3n\">\n <button\n type=\"button\"\n class=\"kf-pagination__control\"\n [disabled]=\"page() <= 1\"\n aria-label=\"P\u00E1gina anterior\"\n (click)=\"goTo(page() - 1)\"\n >\n \u2039\n </button>\n\n @for (item of items(); track $index) {\n @if (item.type === 'page') {\n <button\n type=\"button\"\n class=\"kf-pagination__page\"\n [class.kf-pagination__page--active]=\"item.page === page()\"\n [attr.aria-current]=\"item.page === page() ? 'page' : null\"\n [attr.aria-label]=\"'Ir a la p\u00E1gina ' + item.page\"\n (click)=\"goTo(item.page)\"\n >\n {{ item.page }}\n </button>\n } @else {\n <span class=\"kf-pagination__ellipsis\" aria-hidden=\"true\">\u2026</span>\n }\n }\n\n <button\n type=\"button\"\n class=\"kf-pagination__control\"\n [disabled]=\"page() >= pages()\"\n aria-label=\"P\u00E1gina siguiente\"\n (click)=\"goTo(page() + 1)\"\n >\n \u203A\n </button>\n </nav>\n }\n </div>\n</div>\n", styles: [".kf-caption-text{font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}:host{display:block;font-family:var(--kf-font-body)}.kf-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-md);flex-wrap:wrap}.kf-pagination__info:empty{display:none}.kf-pagination__controls{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kf-space-sm) var(--kf-space-md)}.kf-pagination__size{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-pagination__size-label{white-space:nowrap}.kf-pagination__divider{width:1px;height:1.25rem;background:var(--kf-color-border)}.kf-pagination__nav{display:flex;align-items:center;gap:var(--kf-space-xs)}.kf-pagination__control,.kf-pagination__page{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;padding:0 var(--kf-space-xs);font:inherit;font-size:.85rem;color:var(--kf-color-text);background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);cursor:pointer;transition:background .14s,border-color .14s,color .14s}.kf-pagination__control:hover:not(:disabled),.kf-pagination__page:hover:not(.kf-pagination__page--active){background:var(--kf-color-surface);border-color:var(--kf-color-border-strong)}.kf-pagination__control:focus-visible,.kf-pagination__page:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-pagination__control:disabled{opacity:.5;cursor:not-allowed}.kf-pagination__page--active{color:var(--kf-color-white);background:var(--kf-color-primary);border-color:var(--kf-color-primary);cursor:default}.kf-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--kf-color-text-muted)}@media(max-width:480px){.kf-pagination__controls{width:100%}.kf-pagination__divider{display:none}}\n"], dependencies: [{ kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "required", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
3478
3537
  }
3479
3538
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Pagination, decorators: [{
3480
3539
  type: Component,
@@ -3651,9 +3710,11 @@ const DEFAULT_PAGE_SIZE_OPTIONS = [10, 25, 50];
3651
3710
  * por página" viene activo por defecto con `DEFAULT_PAGE_SIZE_OPTIONS`
3652
3711
  * ([10, 25, 50], estándar del portal) — pasar `pageSizeOptions` propio lo
3653
3712
  * pisa, y pasar `[]` lo desactiva (paginación sin selector). `itemLabel`
3654
- * completa el texto informativo ("1–10 de 42 beneficios").
3713
+ * completa el texto informativo ("1–10 de 42 beneficios"); con
3714
+ * `{ one, other }` usa el singular cuando el total es 1 ("1–1 de 1 beneficio").
3655
3715
  *
3656
3716
  * <kf-data-table [columns]="columns" [rows]="rows" [pageSize]="25" itemLabel="beneficios" />
3717
+ * <kf-data-table [columns]="columns" [rows]="rows" [pageSize]="25" [itemLabel]="{ one: 'unidad', other: 'unidades' }" />
3657
3718
  * <kf-data-table [columns]="columns" [rows]="rows" [pageSize]="25" [pageSizeOptions]="[]" />
3658
3719
  *
3659
3720
  * La página es `[(page)]` (el consumidor puede llevarla a la URL) y se
@@ -3962,9 +4023,12 @@ class DataTable {
3962
4023
  pageSizeChange = output();
3963
4024
  /** Nombre de la entidad listada (ej. "beneficios", "facturas"), en
3964
4025
  * plural — se agrega al final del texto informativo de la paginación
3965
- * interna ("1–5 de 7 beneficios"). Sin esto, el texto queda solo con
3966
- * números ("1–5 de 7"): la librería no impone un idioma ni un nombre
3967
- * fijo, cada consumidor decide el suyo. */
4026
+ * interna ("1–5 de 7 beneficios"). Acepta `{ one, other }` para usar el
4027
+ * singular cuando el total es 1 ("1–1 de 1 beneficio"); un `string`
4028
+ * conserva el comportamiento de siempre (mismo texto para cualquier
4029
+ * total). Sin esto, el texto queda solo con números ("1–5 de 7"): la
4030
+ * librería no impone un idioma ni un nombre fijo, cada consumidor decide
4031
+ * el suyo. */
3968
4032
  itemLabel = input('', /* @ts-ignore */
3969
4033
  ...(ngDevMode ? [{ debugName: "itemLabel" }] : /* istanbul ignore next */ []));
3970
4034
  internalPageSize = signal(null, /* @ts-ignore */
@@ -4029,7 +4093,8 @@ class DataTable {
4029
4093
  }
4030
4094
  const start = (this.page() - 1) * size + 1;
4031
4095
  const end = Math.min(start + size - 1, total);
4032
- const label = this.itemLabel();
4096
+ const itemLabel = this.itemLabel();
4097
+ const label = typeof itemLabel === 'string' ? itemLabel : total === 1 ? itemLabel.one : itemLabel.other;
4033
4098
  return label ? `${start}–${end} de ${total} ${label}` : `${start}–${end} de ${total}`;
4034
4099
  }, /* @ts-ignore */
4035
4100
  ...(ngDevMode ? [{ debugName: "paginationSummary" }] : /* istanbul ignore next */ []));
@@ -4528,6 +4593,21 @@ const BAR_TONE = {
4528
4593
  * <kf-stat-card icon="clock" tone="warn" value="7" label="Por vencer" [bar]="35" hint="7 de 20"
4529
4594
  * clickable [pressed]="filter() === 'due'" (cardClick)="toggle('due')" />
4530
4595
  *
4596
+ * - `badge` (+ `badgeTone`, default `'neutral'`): insignia (`kf-badge`) a la
4597
+ * derecha de la etiqueta, para un estado puntual ("Urgente", "Nuevo"). Es
4598
+ * texto real en el DOM, así que un lector de pantalla lo lee tras la
4599
+ * etiqueta: el tono refuerza el significado, no lo porta solo. Si el
4600
+ * ancho no alcanza, baja a la línea siguiente en vez de recortarse. Sin
4601
+ * `badge` (o con texto vacío) la card no cambia. Funciona con `density`,
4602
+ * `clickable` y `loading`.
4603
+ *
4604
+ * <kf-stat-card icon="clock" tone="warn" value="7" label="Por vencer" badge="Urgente" badgeTone="error" />
4605
+ *
4606
+ * Alto: la card ocupa el 100% del alto de su contenedor cuando este lo fija
4607
+ * (celda de una grilla o ítem estirado de un flex), de modo que las cards de
4608
+ * una misma fila miden igual sin `::ng-deep`. En un contenedor de alto
4609
+ * automático mide lo que su contenido, como siempre.
4610
+ *
4531
4611
  * `density` (`'default'` | `'compact'`): `'compact'` es la variante para
4532
4612
  * pantallas angostas — padding de `--kf-space-md`, ícono de 40px y valor de
4533
4613
  * `--kf-font-size-title-sm`, con el mismo contenido. Si la card mide 210px de
@@ -4543,7 +4623,7 @@ const BAR_TONE = {
4543
4623
  * `loading` (default `false`): mientras es `true` la card dibuja su esqueleto
4544
4624
  * en vez del contenido, con el MISMO cascarón (borde, padding, ícono de 50px)
4545
4625
  * y líneas del alto real de cada texto — valor, etiqueta y, si se pasaron,
4546
- * nota, barra y `hint` —, así que al llegar los datos no hay salto de
4626
+ * nota, barra, `hint` e insignia —, así que al llegar los datos no hay salto de
4547
4627
  * layout. Pasa los mismos inputs que usarás cargada para que el esqueleto
4548
4628
  * reserve las mismas líneas. Marca la card con `aria-busy="true"`, no es
4549
4629
  * clicable ni expone su texto a lectores de pantalla mientras carga.
@@ -4567,6 +4647,12 @@ class StatCard {
4567
4647
  /** Texto secundario bajo la barra (o bajo la nota si no hay barra). */
4568
4648
  hint = input(/* @ts-ignore */
4569
4649
  ...(ngDevMode ? [undefined, { debugName: "hint" }] : /* istanbul ignore next */ []));
4650
+ /** Texto de la insignia a la derecha de la etiqueta; vacío/ausente = sin insignia. */
4651
+ badge = input(/* @ts-ignore */
4652
+ ...(ngDevMode ? [undefined, { debugName: "badge" }] : /* istanbul ignore next */ []));
4653
+ /** Tono semántico de la insignia (`kf-badge`). */
4654
+ badgeTone = input('neutral', /* @ts-ignore */
4655
+ ...(ngDevMode ? [{ debugName: "badgeTone" }] : /* istanbul ignore next */ []));
4570
4656
  /**
4571
4657
  * Estado de alternancia (`aria-pressed`) cuando la card es `clickable`.
4572
4658
  * `null` (default) = no aplica: el atributo no se emite.
@@ -4589,14 +4675,14 @@ class StatCard {
4589
4675
  }, /* @ts-ignore */
4590
4676
  ...(ngDevMode ? [{ debugName: "hasBar" }] : /* istanbul ignore next */ []));
4591
4677
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
4592
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: StatCard, isStandalone: true, selector: "kf-stat-card", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, bar: { classPropertyName: "bar", publicName: "bar", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, pressed: { classPropertyName: "pressed", publicName: "pressed", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardClick: "cardClick" }, host: { properties: { "class.kf-stat-card-host--compact": "density() === 'compact'" } }, ngImport: i0, template: "@if (loading()) {\n <div\n class=\"kf-stat-card\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n aria-busy=\"true\"\n >\n <span\n class=\"kf-stat-card__icon kf-stat-card__icon--bone kf-bone-fill\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"kf-stat-card__body\" aria-hidden=\"true\">\n <span class=\"kf-stat-card__value kf-bone\" style=\"--kf-bone-width: 40%\">{{ value() }}</span>\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{ label() }}</span>\n @if (note()) {\n <span class=\"kf-stat-card__note kf-bone\" style=\"--kf-bone-width: 55%\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <span class=\"kf-stat-card__bar\">\n <span class=\"kf-stat-card__bar-bone kf-bone-fill\"></span>\n </span>\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint kf-bone\" style=\"--kf-bone-width: 45%\">{{ hint() }}</span>\n }\n </span>\n </div>\n} @else if (clickable()) {\n <button\n type=\"button\"\n class=\"kf-stat-card kf-stat-card--clickable\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n [class.kf-stat-card--pressed]=\"pressed() === true\"\n [attr.aria-pressed]=\"pressed()\"\n (click)=\"cardClick.emit()\"\n >\n <ng-container *ngTemplateOutlet=\"content\" />\n <kf-icon class=\"kf-stat-card__chevron\" name=\"chevron-right\" size=\"sm\" />\n </button>\n} @else {\n <div class=\"kf-stat-card\" [class.kf-stat-card--compact]=\"density() === 'compact'\">\n <ng-container *ngTemplateOutlet=\"content\" />\n </div>\n}\n\n<ng-template #content>\n <span class=\"kf-stat-card__icon\" [class]=\"'kf-stat-card__icon--' + tone()\">\n <kf-icon [name]=\"icon()\" size=\"md\" />\n </span>\n <span class=\"kf-stat-card__body\">\n <span class=\"kf-stat-card__value\">{{ value() }}</span>\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n @if (note()) {\n <span class=\"kf-stat-card__note\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <kf-progress\n class=\"kf-stat-card__bar\"\n [value]=\"bar()!\"\n [tone]=\"barTone()\"\n [ariaLabel]=\"label()\"\n />\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint\">{{ hint() }}</span>\n }\n </span>\n</ng-template>\n", styles: [".kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}:host{display:block}.kf-stat-card{display:flex;align-items:center;gap:var(--kf-space-md);width:100%;padding:var(--kf-space-lg);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-sm);font:inherit;text-align:left}.kf-stat-card--clickable{cursor:pointer;transition:box-shadow .14s,transform .14s}.kf-stat-card--clickable:hover{box-shadow:var(--kf-shadow-md);transform:translateY(-2px)}.kf-stat-card--clickable:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-stat-card--pressed{border-color:var(--kf-color-primary);background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 1px var(--kf-color-primary)}.kf-stat-card--pressed:focus-visible{box-shadow:inset 0 0 0 1px var(--kf-color-primary),var(--kf-shadow-focus)}.kf-stat-card__icon{display:grid;place-items:center;width:50px;height:50px;flex:none;border-radius:var(--kf-radius-md)}.kf-stat-card__icon--primary{background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}.kf-stat-card__icon--success{background:var(--kf-color-success-soft);color:var(--kf-color-success-strong)}.kf-stat-card__icon--error{background:var(--kf-color-error-soft);color:var(--kf-color-error)}.kf-stat-card__icon--purple{background:var(--kf-color-purple-soft);color:var(--kf-color-purple)}.kf-stat-card__icon--warn{background:var(--kf-color-warning-soft);color:var(--kf-color-warning-strong)}.kf-stat-card__icon--info{background:var(--kf-color-info-soft);color:var(--kf-color-info-strong)}.kf-stat-card__icon--neutral{background:var(--kf-color-gray-100);color:var(--kf-color-text)}.kf-stat-card__body{display:flex;flex-direction:column;gap:2px;min-width:0}.kf-stat-card__value{font-family:var(--kf-font-title);font-weight:700;font-size:var(--kf-font-size-title-md);color:var(--kf-color-ink)}.kf-stat-card__label{font-size:.875rem;font-weight:700;color:var(--kf-color-ink)}.kf-stat-card__note{font-size:.78rem;color:var(--kf-color-text-muted)}.kf-stat-card__bar{padding-block-start:var(--kf-space-xs)}.kf-stat-card__hint{font-size:.78rem;color:var(--kf-color-text)}.kf-stat-card__chevron{margin-left:auto;flex:none;color:var(--kf-color-gray-400)}.kf-stat-card__icon--bone{border-radius:var(--kf-radius-md)}.kf-stat-card__bar-bone{display:block;height:4px;border-radius:var(--kf-radius-pill)}.kf-stat-card--compact{gap:var(--kf-space-sm) 12px;padding:var(--kf-space-md)}.kf-stat-card--compact .kf-stat-card__icon{width:40px;height:40px}.kf-stat-card--compact .kf-stat-card__value{font-size:var(--kf-font-size-title-sm)}:host(.kf-stat-card-host--compact){container-type:inline-size}@container (max-width: 210px){.kf-stat-card--compact{display:grid;grid-template-columns:auto minmax(0,1fr);align-content:start;align-items:center;gap:2px 10px;padding:12px}.kf-stat-card--compact .kf-stat-card__body{display:contents}.kf-stat-card--compact .kf-stat-card__icon{grid-row:1;grid-column:1;width:36px;height:36px}.kf-stat-card--compact .kf-stat-card__value{grid-row:1;grid-column:2}.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__note,.kf-stat-card--compact .kf-stat-card__bar,.kf-stat-card--compact .kf-stat-card__hint{grid-column:1 / -1}.kf-stat-card--compact .kf-stat-card__label{margin-top:6px}.kf-stat-card--compact .kf-stat-card__chevron{display:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Progress, selector: "kf-progress", inputs: ["value", "tone", "size", "label", "ariaLabel"] }] });
4678
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: StatCard, isStandalone: true, selector: "kf-stat-card", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, bar: { classPropertyName: "bar", publicName: "bar", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeTone: { classPropertyName: "badgeTone", publicName: "badgeTone", isSignal: true, isRequired: false, transformFunction: null }, pressed: { classPropertyName: "pressed", publicName: "pressed", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardClick: "cardClick" }, host: { properties: { "class.kf-stat-card-host--compact": "density() === 'compact'" } }, ngImport: i0, template: "@if (loading()) {\n <div\n class=\"kf-stat-card\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n aria-busy=\"true\"\n >\n <span\n class=\"kf-stat-card__icon kf-stat-card__icon--bone kf-bone-fill\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"kf-stat-card__body\" aria-hidden=\"true\">\n <span class=\"kf-stat-card__value kf-bone\" style=\"--kf-bone-width: 40%\">{{ value() }}</span>\n @if (badge()) {\n <span class=\"kf-stat-card__heading kf-stat-card__heading--bone\">\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{\n label()\n }}</span>\n <span class=\"kf-stat-card__badge-bone kf-bone\" style=\"--kf-bone-width: auto\">{{\n badge()\n }}</span>\n </span>\n } @else {\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{ label() }}</span>\n }\n @if (note()) {\n <span class=\"kf-stat-card__note kf-bone\" style=\"--kf-bone-width: 55%\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <span class=\"kf-stat-card__bar\">\n <span class=\"kf-stat-card__bar-bone kf-bone-fill\"></span>\n </span>\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint kf-bone\" style=\"--kf-bone-width: 45%\">{{ hint() }}</span>\n }\n </span>\n </div>\n} @else if (clickable()) {\n <button\n type=\"button\"\n class=\"kf-stat-card kf-stat-card--clickable\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n [class.kf-stat-card--pressed]=\"pressed() === true\"\n [attr.aria-pressed]=\"pressed()\"\n (click)=\"cardClick.emit()\"\n >\n <ng-container *ngTemplateOutlet=\"content\" />\n <kf-icon class=\"kf-stat-card__chevron\" name=\"chevron-right\" size=\"sm\" />\n </button>\n} @else {\n <div class=\"kf-stat-card\" [class.kf-stat-card--compact]=\"density() === 'compact'\">\n <ng-container *ngTemplateOutlet=\"content\" />\n </div>\n}\n\n<ng-template #content>\n <span class=\"kf-stat-card__icon\" [class]=\"'kf-stat-card__icon--' + tone()\">\n <kf-icon [name]=\"icon()\" size=\"md\" />\n </span>\n <span class=\"kf-stat-card__body\">\n <span class=\"kf-stat-card__value\">{{ value() }}</span>\n @if (badge()) {\n <span class=\"kf-stat-card__heading\">\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n <kf-badge class=\"kf-stat-card__badge\" [tone]=\"badgeTone()\">{{ badge() }}</kf-badge>\n </span>\n } @else {\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n }\n @if (note()) {\n <span class=\"kf-stat-card__note\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <kf-progress\n class=\"kf-stat-card__bar\"\n [value]=\"bar()!\"\n [tone]=\"barTone()\"\n [ariaLabel]=\"label()\"\n />\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint\">{{ hint() }}</span>\n }\n </span>\n</ng-template>\n", styles: [".kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}:host{display:block}.kf-stat-card{display:flex;align-items:center;gap:var(--kf-space-md);width:100%;height:100%;box-sizing:border-box;padding:var(--kf-space-lg);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-sm);font:inherit;text-align:left}.kf-stat-card--clickable{cursor:pointer;transition:box-shadow .14s,transform .14s}.kf-stat-card--clickable:hover{box-shadow:var(--kf-shadow-md);transform:translateY(-2px)}.kf-stat-card--clickable:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-stat-card--pressed{border-color:var(--kf-color-primary);background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 1px var(--kf-color-primary)}.kf-stat-card--pressed:focus-visible{box-shadow:inset 0 0 0 1px var(--kf-color-primary),var(--kf-shadow-focus)}.kf-stat-card__icon{display:grid;place-items:center;width:50px;height:50px;flex:none;border-radius:var(--kf-radius-md)}.kf-stat-card__icon--primary{background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}.kf-stat-card__icon--success{background:var(--kf-color-success-soft);color:var(--kf-color-success-strong)}.kf-stat-card__icon--error{background:var(--kf-color-error-soft);color:var(--kf-color-error)}.kf-stat-card__icon--purple{background:var(--kf-color-purple-soft);color:var(--kf-color-purple)}.kf-stat-card__icon--warn{background:var(--kf-color-warning-soft);color:var(--kf-color-warning-strong)}.kf-stat-card__icon--info{background:var(--kf-color-info-soft);color:var(--kf-color-info-strong)}.kf-stat-card__icon--neutral{background:var(--kf-color-gray-100);color:var(--kf-color-text)}.kf-stat-card__body{display:flex;flex-direction:column;gap:2px;min-width:0}.kf-stat-card__value{font-family:var(--kf-font-title);font-weight:700;font-size:var(--kf-font-size-title-md);color:var(--kf-color-ink)}.kf-stat-card__label{font-size:.875rem;font-weight:700;color:var(--kf-color-ink)}.kf-stat-card__heading{display:flex;flex-wrap:wrap;align-items:center;gap:2px var(--kf-space-sm);min-width:0}.kf-stat-card__heading--bone{flex-wrap:nowrap}.kf-stat-card__note{font-size:.78rem;color:var(--kf-color-text-muted)}.kf-stat-card__bar{padding-block-start:var(--kf-space-xs)}.kf-stat-card__hint{font-size:.78rem;color:var(--kf-color-text)}.kf-stat-card__chevron{margin-left:auto;flex:none;color:var(--kf-color-gray-400)}.kf-stat-card__icon--bone{border-radius:var(--kf-radius-md)}.kf-stat-card__badge-bone{padding:var(--kf-space-xs) var(--kf-space-sm);border-radius:var(--kf-radius-pill);font-size:var(--kf-font-size-caption);font-weight:600;line-height:1}.kf-stat-card__bar-bone{display:block;height:4px;border-radius:var(--kf-radius-pill)}.kf-stat-card--compact{gap:var(--kf-space-sm) 12px;padding:var(--kf-space-md)}.kf-stat-card--compact .kf-stat-card__icon{width:40px;height:40px}.kf-stat-card--compact .kf-stat-card__value{font-size:var(--kf-font-size-title-sm)}:host(.kf-stat-card-host--compact){container-type:inline-size}@container (max-width: 210px){.kf-stat-card--compact{display:grid;grid-template-columns:auto minmax(0,1fr);align-content:start;align-items:center;gap:2px 10px;padding:12px}.kf-stat-card--compact .kf-stat-card__body{display:contents}.kf-stat-card--compact .kf-stat-card__icon{grid-row:1;grid-column:1;width:36px;height:36px}.kf-stat-card--compact .kf-stat-card__value{grid-row:1;grid-column:2}.kf-stat-card--compact .kf-stat-card__heading,.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__note,.kf-stat-card--compact .kf-stat-card__bar,.kf-stat-card--compact .kf-stat-card__hint{grid-column:1 / -1}.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__heading{margin-top:6px}.kf-stat-card--compact .kf-stat-card__heading .kf-stat-card__label{margin-top:0}.kf-stat-card--compact .kf-stat-card__chevron{display:none}}\n"], dependencies: [{ kind: "component", type: Badge, selector: "kf-badge", inputs: ["tone", "variant", "dot", "truncate"] }, { kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Progress, selector: "kf-progress", inputs: ["value", "tone", "size", "label", "ariaLabel"] }] });
4593
4679
  }
4594
4680
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatCard, decorators: [{
4595
4681
  type: Component,
4596
- args: [{ selector: 'kf-stat-card', imports: [Icon, NgTemplateOutlet, Progress], host: {
4682
+ args: [{ selector: 'kf-stat-card', imports: [Badge, Icon, NgTemplateOutlet, Progress], host: {
4597
4683
  '[class.kf-stat-card-host--compact]': "density() === 'compact'",
4598
- }, template: "@if (loading()) {\n <div\n class=\"kf-stat-card\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n aria-busy=\"true\"\n >\n <span\n class=\"kf-stat-card__icon kf-stat-card__icon--bone kf-bone-fill\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"kf-stat-card__body\" aria-hidden=\"true\">\n <span class=\"kf-stat-card__value kf-bone\" style=\"--kf-bone-width: 40%\">{{ value() }}</span>\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{ label() }}</span>\n @if (note()) {\n <span class=\"kf-stat-card__note kf-bone\" style=\"--kf-bone-width: 55%\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <span class=\"kf-stat-card__bar\">\n <span class=\"kf-stat-card__bar-bone kf-bone-fill\"></span>\n </span>\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint kf-bone\" style=\"--kf-bone-width: 45%\">{{ hint() }}</span>\n }\n </span>\n </div>\n} @else if (clickable()) {\n <button\n type=\"button\"\n class=\"kf-stat-card kf-stat-card--clickable\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n [class.kf-stat-card--pressed]=\"pressed() === true\"\n [attr.aria-pressed]=\"pressed()\"\n (click)=\"cardClick.emit()\"\n >\n <ng-container *ngTemplateOutlet=\"content\" />\n <kf-icon class=\"kf-stat-card__chevron\" name=\"chevron-right\" size=\"sm\" />\n </button>\n} @else {\n <div class=\"kf-stat-card\" [class.kf-stat-card--compact]=\"density() === 'compact'\">\n <ng-container *ngTemplateOutlet=\"content\" />\n </div>\n}\n\n<ng-template #content>\n <span class=\"kf-stat-card__icon\" [class]=\"'kf-stat-card__icon--' + tone()\">\n <kf-icon [name]=\"icon()\" size=\"md\" />\n </span>\n <span class=\"kf-stat-card__body\">\n <span class=\"kf-stat-card__value\">{{ value() }}</span>\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n @if (note()) {\n <span class=\"kf-stat-card__note\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <kf-progress\n class=\"kf-stat-card__bar\"\n [value]=\"bar()!\"\n [tone]=\"barTone()\"\n [ariaLabel]=\"label()\"\n />\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint\">{{ hint() }}</span>\n }\n </span>\n</ng-template>\n", styles: [".kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}:host{display:block}.kf-stat-card{display:flex;align-items:center;gap:var(--kf-space-md);width:100%;padding:var(--kf-space-lg);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-sm);font:inherit;text-align:left}.kf-stat-card--clickable{cursor:pointer;transition:box-shadow .14s,transform .14s}.kf-stat-card--clickable:hover{box-shadow:var(--kf-shadow-md);transform:translateY(-2px)}.kf-stat-card--clickable:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-stat-card--pressed{border-color:var(--kf-color-primary);background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 1px var(--kf-color-primary)}.kf-stat-card--pressed:focus-visible{box-shadow:inset 0 0 0 1px var(--kf-color-primary),var(--kf-shadow-focus)}.kf-stat-card__icon{display:grid;place-items:center;width:50px;height:50px;flex:none;border-radius:var(--kf-radius-md)}.kf-stat-card__icon--primary{background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}.kf-stat-card__icon--success{background:var(--kf-color-success-soft);color:var(--kf-color-success-strong)}.kf-stat-card__icon--error{background:var(--kf-color-error-soft);color:var(--kf-color-error)}.kf-stat-card__icon--purple{background:var(--kf-color-purple-soft);color:var(--kf-color-purple)}.kf-stat-card__icon--warn{background:var(--kf-color-warning-soft);color:var(--kf-color-warning-strong)}.kf-stat-card__icon--info{background:var(--kf-color-info-soft);color:var(--kf-color-info-strong)}.kf-stat-card__icon--neutral{background:var(--kf-color-gray-100);color:var(--kf-color-text)}.kf-stat-card__body{display:flex;flex-direction:column;gap:2px;min-width:0}.kf-stat-card__value{font-family:var(--kf-font-title);font-weight:700;font-size:var(--kf-font-size-title-md);color:var(--kf-color-ink)}.kf-stat-card__label{font-size:.875rem;font-weight:700;color:var(--kf-color-ink)}.kf-stat-card__note{font-size:.78rem;color:var(--kf-color-text-muted)}.kf-stat-card__bar{padding-block-start:var(--kf-space-xs)}.kf-stat-card__hint{font-size:.78rem;color:var(--kf-color-text)}.kf-stat-card__chevron{margin-left:auto;flex:none;color:var(--kf-color-gray-400)}.kf-stat-card__icon--bone{border-radius:var(--kf-radius-md)}.kf-stat-card__bar-bone{display:block;height:4px;border-radius:var(--kf-radius-pill)}.kf-stat-card--compact{gap:var(--kf-space-sm) 12px;padding:var(--kf-space-md)}.kf-stat-card--compact .kf-stat-card__icon{width:40px;height:40px}.kf-stat-card--compact .kf-stat-card__value{font-size:var(--kf-font-size-title-sm)}:host(.kf-stat-card-host--compact){container-type:inline-size}@container (max-width: 210px){.kf-stat-card--compact{display:grid;grid-template-columns:auto minmax(0,1fr);align-content:start;align-items:center;gap:2px 10px;padding:12px}.kf-stat-card--compact .kf-stat-card__body{display:contents}.kf-stat-card--compact .kf-stat-card__icon{grid-row:1;grid-column:1;width:36px;height:36px}.kf-stat-card--compact .kf-stat-card__value{grid-row:1;grid-column:2}.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__note,.kf-stat-card--compact .kf-stat-card__bar,.kf-stat-card--compact .kf-stat-card__hint{grid-column:1 / -1}.kf-stat-card--compact .kf-stat-card__label{margin-top:6px}.kf-stat-card--compact .kf-stat-card__chevron{display:none}}\n"] }]
4599
- }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], bar: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }] } });
4684
+ }, template: "@if (loading()) {\n <div\n class=\"kf-stat-card\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n aria-busy=\"true\"\n >\n <span\n class=\"kf-stat-card__icon kf-stat-card__icon--bone kf-bone-fill\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"kf-stat-card__body\" aria-hidden=\"true\">\n <span class=\"kf-stat-card__value kf-bone\" style=\"--kf-bone-width: 40%\">{{ value() }}</span>\n @if (badge()) {\n <span class=\"kf-stat-card__heading kf-stat-card__heading--bone\">\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{\n label()\n }}</span>\n <span class=\"kf-stat-card__badge-bone kf-bone\" style=\"--kf-bone-width: auto\">{{\n badge()\n }}</span>\n </span>\n } @else {\n <span class=\"kf-stat-card__label kf-bone\" style=\"--kf-bone-width: 70%\">{{ label() }}</span>\n }\n @if (note()) {\n <span class=\"kf-stat-card__note kf-bone\" style=\"--kf-bone-width: 55%\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <span class=\"kf-stat-card__bar\">\n <span class=\"kf-stat-card__bar-bone kf-bone-fill\"></span>\n </span>\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint kf-bone\" style=\"--kf-bone-width: 45%\">{{ hint() }}</span>\n }\n </span>\n </div>\n} @else if (clickable()) {\n <button\n type=\"button\"\n class=\"kf-stat-card kf-stat-card--clickable\"\n [class.kf-stat-card--compact]=\"density() === 'compact'\"\n [class.kf-stat-card--pressed]=\"pressed() === true\"\n [attr.aria-pressed]=\"pressed()\"\n (click)=\"cardClick.emit()\"\n >\n <ng-container *ngTemplateOutlet=\"content\" />\n <kf-icon class=\"kf-stat-card__chevron\" name=\"chevron-right\" size=\"sm\" />\n </button>\n} @else {\n <div class=\"kf-stat-card\" [class.kf-stat-card--compact]=\"density() === 'compact'\">\n <ng-container *ngTemplateOutlet=\"content\" />\n </div>\n}\n\n<ng-template #content>\n <span class=\"kf-stat-card__icon\" [class]=\"'kf-stat-card__icon--' + tone()\">\n <kf-icon [name]=\"icon()\" size=\"md\" />\n </span>\n <span class=\"kf-stat-card__body\">\n <span class=\"kf-stat-card__value\">{{ value() }}</span>\n @if (badge()) {\n <span class=\"kf-stat-card__heading\">\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n <kf-badge class=\"kf-stat-card__badge\" [tone]=\"badgeTone()\">{{ badge() }}</kf-badge>\n </span>\n } @else {\n <span class=\"kf-stat-card__label\">{{ label() }}</span>\n }\n @if (note()) {\n <span class=\"kf-stat-card__note\">{{ note() }}</span>\n }\n @if (hasBar()) {\n <kf-progress\n class=\"kf-stat-card__bar\"\n [value]=\"bar()!\"\n [tone]=\"barTone()\"\n [ariaLabel]=\"label()\"\n />\n }\n @if (hint()) {\n <span class=\"kf-stat-card__hint\">{{ hint() }}</span>\n }\n </span>\n</ng-template>\n", styles: [".kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}:host{display:block}.kf-stat-card{display:flex;align-items:center;gap:var(--kf-space-md);width:100%;height:100%;box-sizing:border-box;padding:var(--kf-space-lg);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-md);background:var(--kf-color-white);box-shadow:var(--kf-shadow-sm);font:inherit;text-align:left}.kf-stat-card--clickable{cursor:pointer;transition:box-shadow .14s,transform .14s}.kf-stat-card--clickable:hover{box-shadow:var(--kf-shadow-md);transform:translateY(-2px)}.kf-stat-card--clickable:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-stat-card--pressed{border-color:var(--kf-color-primary);background:var(--kf-color-primary-soft);box-shadow:inset 0 0 0 1px var(--kf-color-primary)}.kf-stat-card--pressed:focus-visible{box-shadow:inset 0 0 0 1px var(--kf-color-primary),var(--kf-shadow-focus)}.kf-stat-card__icon{display:grid;place-items:center;width:50px;height:50px;flex:none;border-radius:var(--kf-radius-md)}.kf-stat-card__icon--primary{background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}.kf-stat-card__icon--success{background:var(--kf-color-success-soft);color:var(--kf-color-success-strong)}.kf-stat-card__icon--error{background:var(--kf-color-error-soft);color:var(--kf-color-error)}.kf-stat-card__icon--purple{background:var(--kf-color-purple-soft);color:var(--kf-color-purple)}.kf-stat-card__icon--warn{background:var(--kf-color-warning-soft);color:var(--kf-color-warning-strong)}.kf-stat-card__icon--info{background:var(--kf-color-info-soft);color:var(--kf-color-info-strong)}.kf-stat-card__icon--neutral{background:var(--kf-color-gray-100);color:var(--kf-color-text)}.kf-stat-card__body{display:flex;flex-direction:column;gap:2px;min-width:0}.kf-stat-card__value{font-family:var(--kf-font-title);font-weight:700;font-size:var(--kf-font-size-title-md);color:var(--kf-color-ink)}.kf-stat-card__label{font-size:.875rem;font-weight:700;color:var(--kf-color-ink)}.kf-stat-card__heading{display:flex;flex-wrap:wrap;align-items:center;gap:2px var(--kf-space-sm);min-width:0}.kf-stat-card__heading--bone{flex-wrap:nowrap}.kf-stat-card__note{font-size:.78rem;color:var(--kf-color-text-muted)}.kf-stat-card__bar{padding-block-start:var(--kf-space-xs)}.kf-stat-card__hint{font-size:.78rem;color:var(--kf-color-text)}.kf-stat-card__chevron{margin-left:auto;flex:none;color:var(--kf-color-gray-400)}.kf-stat-card__icon--bone{border-radius:var(--kf-radius-md)}.kf-stat-card__badge-bone{padding:var(--kf-space-xs) var(--kf-space-sm);border-radius:var(--kf-radius-pill);font-size:var(--kf-font-size-caption);font-weight:600;line-height:1}.kf-stat-card__bar-bone{display:block;height:4px;border-radius:var(--kf-radius-pill)}.kf-stat-card--compact{gap:var(--kf-space-sm) 12px;padding:var(--kf-space-md)}.kf-stat-card--compact .kf-stat-card__icon{width:40px;height:40px}.kf-stat-card--compact .kf-stat-card__value{font-size:var(--kf-font-size-title-sm)}:host(.kf-stat-card-host--compact){container-type:inline-size}@container (max-width: 210px){.kf-stat-card--compact{display:grid;grid-template-columns:auto minmax(0,1fr);align-content:start;align-items:center;gap:2px 10px;padding:12px}.kf-stat-card--compact .kf-stat-card__body{display:contents}.kf-stat-card--compact .kf-stat-card__icon{grid-row:1;grid-column:1;width:36px;height:36px}.kf-stat-card--compact .kf-stat-card__value{grid-row:1;grid-column:2}.kf-stat-card--compact .kf-stat-card__heading,.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__note,.kf-stat-card--compact .kf-stat-card__bar,.kf-stat-card--compact .kf-stat-card__hint{grid-column:1 / -1}.kf-stat-card--compact .kf-stat-card__label,.kf-stat-card--compact .kf-stat-card__heading{margin-top:6px}.kf-stat-card--compact .kf-stat-card__heading .kf-stat-card__label{margin-top:0}.kf-stat-card--compact .kf-stat-card__chevron{display:none}}\n"] }]
4685
+ }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], bar: [{ type: i0.Input, args: [{ isSignal: true, alias: "bar", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgeTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeTone", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }] } });
4600
4686
 
4601
4687
  /** Cantidad de elementos por defecto de cada variante (`count` sin valor). */
4602
4688
  const DEFAULT_COUNT = {
@@ -4666,7 +4752,7 @@ class SkeletonPreset {
4666
4752
  formColumns = computed(() => (this.columns() === 2 ? 2 : 1), /* @ts-ignore */
4667
4753
  ...(ngDevMode ? [{ debugName: "formColumns" }] : /* istanbul ignore next */ []));
4668
4754
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SkeletonPreset, deps: [], target: i0.ɵɵFactoryTarget.Component });
4669
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SkeletonPreset, isStandalone: true, selector: "kf-skeleton-preset", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n [class]=\"'kf-skeleton-preset kf-skeleton-preset--' + variant()\"\n aria-busy=\"true\"\n [style.--kf-skeleton-preset-columns]=\"columns() ?? null\"\n>\n @if (label()) {\n <span class=\"kf-sr-only\" role=\"status\">{{ label() }}</span>\n }\n @switch (variant()) {\n @case ('kpi-grid') {\n <div class=\"kf-skeleton-preset__grid\" [class.kf-skeleton-preset__grid--fixed]=\"!!columns()\">\n @for (i of items(); track i) {\n <kf-stat-card [loading]=\"true\" icon=\"bell\" value=\"0\" label=\"Etiqueta\" note=\"Nota\" />\n }\n </div>\n }\n @case ('card-grid') {\n <div class=\"kf-skeleton-preset__grid\" [class.kf-skeleton-preset__grid--fixed]=\"!!columns()\">\n @for (i of items(); track i) {\n <kf-card gap=\"sm\" aria-hidden=\"true\">\n <kf-skeleton variant=\"rect\" height=\"7.5rem\" />\n <kf-skeleton width=\"60%\" height=\"1.25rem\" />\n <kf-skeleton />\n <kf-skeleton width=\"80%\" />\n </kf-card>\n }\n </div>\n }\n @case ('form') {\n <div\n class=\"kf-skeleton-preset__form\"\n [class.kf-skeleton-preset__form--two]=\"formColumns() === 2\"\n aria-hidden=\"true\"\n >\n @for (i of items(); track i) {\n <div class=\"kf-skeleton-preset__field\">\n <span\n class=\"kf-skeleton-preset__label kf-overline-text kf-bone\"\n style=\"--kf-bone-width: 30%\"\n >\n Etiqueta\n </span>\n <span class=\"kf-skeleton-preset__control\">\n <span class=\"kf-skeleton-preset__value kf-bone\" style=\"--kf-bone-width: 55%\"\n >Valor</span\n >\n </span>\n </div>\n }\n </div>\n }\n @case ('list') {\n <div class=\"kf-skeleton-preset__stack\">\n @for (i of items(); track i) {\n <kf-document-row [loading]=\"true\" title=\"Documento\" meta=\"Archivo \u00B7 120 KB\" />\n }\n </div>\n }\n @case ('table') {\n <kf-data-table\n [columns]=\"tableColumns()\"\n [rows]=\"[]\"\n [loading]=\"true\"\n [skeletonRows]=\"total()\"\n />\n }\n @case ('timeline') {\n <div class=\"kf-skeleton-preset__timeline\" aria-hidden=\"true\">\n <div class=\"kf-skeleton-preset__timeline-toolbar\">\n <span class=\"kf-skeleton-preset__timeline-heading kf-bone\" style=\"--kf-bone-width: 30%\">\n Etapas\n </span>\n <span class=\"kf-skeleton-preset__timeline-toggle kf-bone\" style=\"--kf-bone-width: 7rem\">\n Expandir todo\n </span>\n </div>\n <ol class=\"kf-skeleton-preset__timeline-list\">\n @for (i of items(); track i) {\n <li class=\"kf-skeleton-preset__timeline-group\">\n <span class=\"kf-skeleton-preset__timeline-node kf-bone-fill\"></span>\n <span class=\"kf-skeleton-preset__timeline-text\">\n <span\n class=\"kf-skeleton-preset__timeline-title kf-bone\"\n style=\"--kf-bone-width: 45%\"\n >\n Etapa\n </span>\n <span\n class=\"kf-skeleton-preset__timeline-meta kf-bone\"\n style=\"--kf-bone-width: 30%\"\n >\n Detalle\n </span>\n </span>\n </li>\n }\n </ol>\n </div>\n }\n @case ('detail-header') {\n <div class=\"kf-skeleton-preset__header\" aria-hidden=\"true\">\n <span class=\"kf-skeleton-preset__header-icon kf-bone-fill\"></span>\n <span class=\"kf-skeleton-preset__header-heading\">\n <span class=\"kf-skeleton-preset__header-title kf-bone\" style=\"--kf-bone-width: 40%\">\n T\u00EDtulo\n </span>\n <span class=\"kf-skeleton-preset__header-subtitle kf-bone\" style=\"--kf-bone-width: 60%\">\n Subt\u00EDtulo\n </span>\n </span>\n </div>\n }\n }\n</div>\n", styles: [".kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}.kf-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}:host{display:block;font-family:var(--kf-font-body)}.kf-skeleton-preset__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,15rem),1fr));gap:var(--kf-space-md)}.kf-skeleton-preset__grid--fixed{grid-template-columns:repeat(var(--kf-skeleton-preset-columns),minmax(0,1fr))}.kf-skeleton-preset__stack{display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-skeleton-preset__form{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--kf-space-md)}.kf-skeleton-preset__form--two{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:640px){.kf-skeleton-preset__form--two{grid-template-columns:minmax(0,1fr)}}.kf-skeleton-preset__field{display:flex;flex-direction:column;gap:var(--kf-space-xs)}.kf-skeleton-preset__control{display:block;padding:var(--kf-space-sm) var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm)}.kf-skeleton-preset__timeline{--_node: var(--kf-status-node-size, 2.125rem);--_gutter: var(--kf-space-sm);--_pad-y: var(--kf-space-sm);--_line: 2px;display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-skeleton-preset__timeline-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm)}.kf-skeleton-preset__timeline-heading{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-sm);font-weight:var(--kf-font-weight-title)}.kf-skeleton-preset__timeline-toggle{box-sizing:border-box;padding:6px var(--kf-space-sm);border:1px solid transparent;font-size:.85rem;font-weight:600;border-radius:var(--kf-radius-sm)}@media(max-width:640px),(pointer:coarse){.kf-skeleton-preset__timeline-toggle{min-height:44px}}.kf-skeleton-preset__timeline-list{list-style:none;margin:0;padding:0}.kf-skeleton-preset__timeline-group{position:relative;display:flex;align-items:flex-start;gap:var(--kf-space-md);box-sizing:border-box;min-height:2.75rem;padding:var(--_pad-y) var(--_gutter)}.kf-skeleton-preset__timeline-group:not(:last-child):before{content:\"\";position:absolute;inset-inline-start:calc(var(--_gutter) + var(--_node) / 2 - var(--_line) / 2);top:calc(var(--_pad-y) + var(--_node));bottom:calc(var(--kf-space-xs) - var(--_pad-y));width:var(--_line);background:var(--kf-color-border)}.kf-skeleton-preset__timeline-node{flex:none;width:var(--_node);height:var(--_node);border-radius:50%}.kf-skeleton-preset__timeline-text{flex:1;display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;min-height:var(--_node)}.kf-skeleton-preset__timeline-title{font-weight:700;font-size:var(--kf-font-size-body)}.kf-skeleton-preset__timeline-meta{font-size:var(--kf-font-size-body-sm)}.kf-skeleton-preset__header{display:flex;align-items:center;gap:var(--kf-space-md);padding-bottom:var(--kf-space-lg);border-bottom:1px solid var(--kf-color-border)}.kf-skeleton-preset__header-icon{flex:none;width:52px;height:52px;border:1px solid transparent;border-radius:var(--kf-radius-md)}.kf-skeleton-preset__header-heading{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.kf-skeleton-preset__header-title{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:var(--kf-font-weight-title);line-height:1.2}.kf-skeleton-preset__header-subtitle{font-size:.9375rem}@media(max-width:900px){.kf-skeleton-preset__header-icon{width:40px;height:40px}.kf-skeleton-preset__header-title{font-size:var(--kf-font-size-title-sm)}.kf-skeleton-preset__header-subtitle{font-size:.8125rem}}\n"], dependencies: [{ kind: "component", type: Card, selector: "kf-card", inputs: ["flush", "gap", "loading"] }, { kind: "component", type: DataTable, selector: "kf-data-table", inputs: ["columns", "rows", "loading", "skeletonRows", "rowKey", "flush", "cardable", "defaultView", "showViewToggle", "cardMinWidth", "render", "cellTemplates", "density", "rowClickable", "rowFocusable", "cellAriaLabel", "ariaLabel", "currentRowKey", "pageSize", "pageSizeOptions", "page", "keepPageOnRowsChange", "itemLabel", "sort", "view"], outputs: ["rowClick", "cellClick", "pageChange", "pageSizeChange", "sortChange", "viewChange"] }, { kind: "component", type: DocumentRow, selector: "kf-document-row", inputs: ["icon", "tone", "title", "meta", "href", "downloadLabel", "pendingLabel", "loading"] }, { kind: "component", type: Skeleton, selector: "kf-skeleton", inputs: ["variant", "width", "height"] }, { kind: "component", type: StatCard, selector: "kf-stat-card", inputs: ["icon", "tone", "value", "label", "note", "bar", "hint", "pressed", "density", "loading", "clickable"], outputs: ["cardClick"] }] });
4755
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SkeletonPreset, isStandalone: true, selector: "kf-skeleton-preset", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n [class]=\"'kf-skeleton-preset kf-skeleton-preset--' + variant()\"\n aria-busy=\"true\"\n [style.--kf-skeleton-preset-columns]=\"columns() ?? null\"\n>\n @if (label()) {\n <span class=\"kf-sr-only\" role=\"status\">{{ label() }}</span>\n }\n @switch (variant()) {\n @case ('kpi-grid') {\n <div class=\"kf-skeleton-preset__grid\" [class.kf-skeleton-preset__grid--fixed]=\"!!columns()\">\n @for (i of items(); track i) {\n <kf-stat-card [loading]=\"true\" icon=\"bell\" value=\"0\" label=\"Etiqueta\" note=\"Nota\" />\n }\n </div>\n }\n @case ('card-grid') {\n <div class=\"kf-skeleton-preset__grid\" [class.kf-skeleton-preset__grid--fixed]=\"!!columns()\">\n @for (i of items(); track i) {\n <kf-card gap=\"sm\" aria-hidden=\"true\">\n <kf-skeleton variant=\"rect\" height=\"7.5rem\" />\n <kf-skeleton width=\"60%\" height=\"1.25rem\" />\n <kf-skeleton />\n <kf-skeleton width=\"80%\" />\n </kf-card>\n }\n </div>\n }\n @case ('form') {\n <div\n class=\"kf-skeleton-preset__form\"\n [class.kf-skeleton-preset__form--two]=\"formColumns() === 2\"\n aria-hidden=\"true\"\n >\n @for (i of items(); track i) {\n <div class=\"kf-skeleton-preset__field\">\n <span\n class=\"kf-skeleton-preset__label kf-overline-text kf-bone\"\n style=\"--kf-bone-width: 30%\"\n >\n Etiqueta\n </span>\n <span class=\"kf-skeleton-preset__control\">\n <span class=\"kf-skeleton-preset__value kf-bone\" style=\"--kf-bone-width: 55%\"\n >Valor</span\n >\n </span>\n </div>\n }\n </div>\n }\n @case ('list') {\n <div class=\"kf-skeleton-preset__stack\">\n @for (i of items(); track i) {\n <kf-document-row [loading]=\"true\" title=\"Documento\" meta=\"Archivo \u00B7 120 KB\" />\n }\n </div>\n }\n @case ('table') {\n <kf-data-table\n [columns]=\"tableColumns()\"\n [rows]=\"[]\"\n [loading]=\"true\"\n [skeletonRows]=\"total()\"\n />\n }\n @case ('timeline') {\n <div class=\"kf-skeleton-preset__timeline\" aria-hidden=\"true\">\n <div class=\"kf-skeleton-preset__timeline-toolbar\">\n <span class=\"kf-skeleton-preset__timeline-heading kf-bone\" style=\"--kf-bone-width: 30%\">\n Etapas\n </span>\n <span class=\"kf-skeleton-preset__timeline-toggle kf-bone\" style=\"--kf-bone-width: 7rem\">\n Expandir todo\n </span>\n </div>\n <ol class=\"kf-skeleton-preset__timeline-list\">\n @for (i of items(); track i) {\n <li class=\"kf-skeleton-preset__timeline-group\">\n <span class=\"kf-skeleton-preset__timeline-node kf-bone-fill\"></span>\n <span class=\"kf-skeleton-preset__timeline-text\">\n <span\n class=\"kf-skeleton-preset__timeline-title kf-bone\"\n style=\"--kf-bone-width: 45%\"\n >\n Etapa\n </span>\n <span\n class=\"kf-skeleton-preset__timeline-meta kf-bone\"\n style=\"--kf-bone-width: 30%\"\n >\n Detalle\n </span>\n </span>\n </li>\n }\n </ol>\n </div>\n }\n @case ('detail-header') {\n <div class=\"kf-skeleton-preset__header\" aria-hidden=\"true\">\n <span class=\"kf-skeleton-preset__header-icon kf-bone-fill\"></span>\n <span class=\"kf-skeleton-preset__header-heading\">\n <span class=\"kf-skeleton-preset__header-title kf-bone\" style=\"--kf-bone-width: 40%\">\n T\u00EDtulo\n </span>\n <span class=\"kf-skeleton-preset__header-subtitle kf-bone\" style=\"--kf-bone-width: 60%\">\n Subt\u00EDtulo\n </span>\n </span>\n </div>\n }\n }\n</div>\n", styles: [".kf-overline-text{font-family:var(--kf-font-title);font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-medium);letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-bone-shimmer 1.4s ease infinite}.kf-bone{display:block;box-sizing:border-box;width:var(--kf-bone-width, 60%);max-width:100%;overflow:hidden;white-space:nowrap;border-radius:var(--kf-radius-xs);-webkit-user-select:none;user-select:none;pointer-events:none}.kf-bone.kf-bone{color:transparent!important;-webkit-text-fill-color:transparent}.kf-bone>*{visibility:hidden}@keyframes kf-bone-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-bone.kf-bone,.kf-bone-fill.kf-bone-fill,.kf-bone-overlay.kf-bone-overlay:after{animation:none;background:var(--kf-color-border)}}.kf-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}:host{display:block;font-family:var(--kf-font-body)}.kf-skeleton-preset__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,15rem),1fr));gap:var(--kf-space-md)}.kf-skeleton-preset__grid--fixed{grid-template-columns:repeat(var(--kf-skeleton-preset-columns),minmax(0,1fr))}.kf-skeleton-preset__stack{display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-skeleton-preset__form{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--kf-space-md)}.kf-skeleton-preset__form--two{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:640px){.kf-skeleton-preset__form--two{grid-template-columns:minmax(0,1fr)}}.kf-skeleton-preset__field{display:flex;flex-direction:column;gap:var(--kf-space-xs)}.kf-skeleton-preset__control{display:block;padding:var(--kf-space-sm) var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm)}.kf-skeleton-preset__timeline{--_node: var(--kf-status-node-size, 2.125rem);--_gutter: var(--kf-space-sm);--_pad-y: var(--kf-space-sm);--_line: 2px;display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-skeleton-preset__timeline-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm)}.kf-skeleton-preset__timeline-heading{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-sm);font-weight:var(--kf-font-weight-title)}.kf-skeleton-preset__timeline-toggle{box-sizing:border-box;padding:6px var(--kf-space-sm);border:1px solid transparent;font-size:.85rem;font-weight:600;border-radius:var(--kf-radius-sm)}@media(max-width:640px),(pointer:coarse){.kf-skeleton-preset__timeline-toggle{min-height:44px}}.kf-skeleton-preset__timeline-list{list-style:none;margin:0;padding:0}.kf-skeleton-preset__timeline-group{position:relative;display:flex;align-items:flex-start;gap:var(--kf-space-md);box-sizing:border-box;min-height:2.75rem;padding:var(--_pad-y) var(--_gutter)}.kf-skeleton-preset__timeline-group:not(:last-child):before{content:\"\";position:absolute;inset-inline-start:calc(var(--_gutter) + var(--_node) / 2 - var(--_line) / 2);top:calc(var(--_pad-y) + var(--_node));bottom:calc(var(--kf-space-xs) - var(--_pad-y));width:var(--_line);background:var(--kf-color-border)}.kf-skeleton-preset__timeline-node{flex:none;width:var(--_node);height:var(--_node);border-radius:50%}.kf-skeleton-preset__timeline-text{flex:1;display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;min-height:var(--_node)}.kf-skeleton-preset__timeline-title{font-weight:700;font-size:var(--kf-font-size-body)}.kf-skeleton-preset__timeline-meta{font-size:var(--kf-font-size-body-sm)}.kf-skeleton-preset__header{display:flex;align-items:center;gap:var(--kf-space-md);padding-bottom:var(--kf-space-lg);border-bottom:1px solid var(--kf-color-border)}.kf-skeleton-preset__header-icon{flex:none;width:52px;height:52px;border:1px solid transparent;border-radius:var(--kf-radius-md)}.kf-skeleton-preset__header-heading{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;min-width:0}.kf-skeleton-preset__header-title{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:var(--kf-font-weight-title);line-height:1.2}.kf-skeleton-preset__header-subtitle{font-size:.9375rem}@media(max-width:900px){.kf-skeleton-preset__header-icon{width:40px;height:40px}.kf-skeleton-preset__header-title{font-size:var(--kf-font-size-title-sm)}.kf-skeleton-preset__header-subtitle{font-size:.8125rem}}\n"], dependencies: [{ kind: "component", type: Card, selector: "kf-card", inputs: ["flush", "gap", "loading"] }, { kind: "component", type: DataTable, selector: "kf-data-table", inputs: ["columns", "rows", "loading", "skeletonRows", "rowKey", "flush", "cardable", "defaultView", "showViewToggle", "cardMinWidth", "render", "cellTemplates", "density", "rowClickable", "rowFocusable", "cellAriaLabel", "ariaLabel", "currentRowKey", "pageSize", "pageSizeOptions", "page", "keepPageOnRowsChange", "itemLabel", "sort", "view"], outputs: ["rowClick", "cellClick", "pageChange", "pageSizeChange", "sortChange", "viewChange"] }, { kind: "component", type: DocumentRow, selector: "kf-document-row", inputs: ["icon", "tone", "title", "meta", "href", "downloadLabel", "pendingLabel", "loading"] }, { kind: "component", type: Skeleton, selector: "kf-skeleton", inputs: ["variant", "width", "height"] }, { kind: "component", type: StatCard, selector: "kf-stat-card", inputs: ["icon", "tone", "value", "label", "note", "bar", "hint", "badge", "badgeTone", "pressed", "density", "loading", "clickable"], outputs: ["cardClick"] }] });
4670
4756
  }
4671
4757
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SkeletonPreset, decorators: [{
4672
4758
  type: Component,
@@ -4954,7 +5040,7 @@ class CursorPager {
4954
5040
  }
4955
5041
  }
4956
5042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: CursorPager, deps: [], target: i0.ɵɵFactoryTarget.Component });
4957
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: CursorPager, isStandalone: true, selector: "kf-cursor-pager", inputs: { summary: { classPropertyName: "summary", publicName: "summary", isSignal: true, isRequired: false, transformFunction: null }, hasPrevious: { classPropertyName: "hasPrevious", publicName: "hasPrevious", isSignal: true, isRequired: false, transformFunction: null }, hasNext: { classPropertyName: "hasNext", publicName: "hasNext", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previous: "previous", next: "next", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"kf-cursor-pager\">\n <div class=\"kf-cursor-pager__summary\" role=\"status\" aria-live=\"polite\">{{ summary() }}</div>\n\n <div class=\"kf-cursor-pager__controls\">\n @if (sizeOptions().length > 0) {\n <div class=\"kf-cursor-pager__size\">\n <span class=\"kf-cursor-pager__size-label\" aria-hidden=\"true\">Filas</span>\n <kf-select\n variant=\"compact\"\n label=\"Filas por p\u00E1gina\"\n hideLabel\n [options]=\"sizeOptions()\"\n [value]=\"sizeValue()\"\n (valueChange)=\"onPageSize($event)\"\n />\n </div>\n <span class=\"kf-cursor-pager__divider\" aria-hidden=\"true\"></span>\n }\n\n <nav class=\"kf-cursor-pager__nav\" [attr.aria-label]=\"ariaLabel()\">\n <button\n type=\"button\"\n class=\"kf-cursor-pager__button\"\n [attr.aria-disabled]=\"!hasPrevious()\"\n (click)=\"onPrevious()\"\n >\n <kf-icon name=\"chevron-left\" size=\"sm\" />\n Anterior\n </button>\n <button\n type=\"button\"\n class=\"kf-cursor-pager__button kf-cursor-pager__button--next\"\n [attr.aria-disabled]=\"!hasNext()\"\n (click)=\"onNext()\"\n >\n Siguiente\n <kf-icon name=\"chevron-right\" size=\"sm\" />\n </button>\n </nav>\n </div>\n</div>\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-cursor-pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--kf-space-md)}.kf-cursor-pager__summary{font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);color:var(--kf-color-text)}.kf-cursor-pager__summary:empty{display:none}.kf-cursor-pager__controls{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kf-space-sm) var(--kf-space-md)}.kf-cursor-pager__size{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-cursor-pager__size-label{font-size:var(--kf-font-size-body-sm);color:var(--kf-color-text);white-space:nowrap}.kf-cursor-pager__divider{width:1px;height:1.25rem;background:var(--kf-color-border)}.kf-cursor-pager__nav{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-cursor-pager__button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);min-height:32px;padding:0 var(--kf-space-sm);font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);color:var(--kf-color-text);background:transparent;border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-sm);cursor:pointer}.kf-cursor-pager__button:hover:not([aria-disabled=true]){background:var(--kf-color-white);border-color:var(--kf-color-text-muted)}.kf-cursor-pager__button:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-cursor-pager__button[aria-disabled=true]{opacity:.5;cursor:not-allowed}@media(max-width:599.98px){.kf-cursor-pager__controls{width:100%}.kf-cursor-pager__divider{display:none}.kf-cursor-pager__nav{width:100%}.kf-cursor-pager__button{flex:1 1 0;min-height:36px}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
5043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: CursorPager, isStandalone: true, selector: "kf-cursor-pager", inputs: { summary: { classPropertyName: "summary", publicName: "summary", isSignal: true, isRequired: false, transformFunction: null }, hasPrevious: { classPropertyName: "hasPrevious", publicName: "hasPrevious", isSignal: true, isRequired: false, transformFunction: null }, hasNext: { classPropertyName: "hasNext", publicName: "hasNext", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previous: "previous", next: "next", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"kf-cursor-pager\">\n <div class=\"kf-cursor-pager__summary\" role=\"status\" aria-live=\"polite\">{{ summary() }}</div>\n\n <div class=\"kf-cursor-pager__controls\">\n @if (sizeOptions().length > 0) {\n <div class=\"kf-cursor-pager__size\">\n <span class=\"kf-cursor-pager__size-label\" aria-hidden=\"true\">Filas</span>\n <kf-select\n variant=\"compact\"\n label=\"Filas por p\u00E1gina\"\n hideLabel\n [options]=\"sizeOptions()\"\n [value]=\"sizeValue()\"\n (valueChange)=\"onPageSize($event)\"\n />\n </div>\n <span class=\"kf-cursor-pager__divider\" aria-hidden=\"true\"></span>\n }\n\n <nav class=\"kf-cursor-pager__nav\" [attr.aria-label]=\"ariaLabel()\">\n <button\n type=\"button\"\n class=\"kf-cursor-pager__button\"\n [attr.aria-disabled]=\"!hasPrevious()\"\n (click)=\"onPrevious()\"\n >\n <kf-icon name=\"chevron-left\" size=\"sm\" />\n Anterior\n </button>\n <button\n type=\"button\"\n class=\"kf-cursor-pager__button kf-cursor-pager__button--next\"\n [attr.aria-disabled]=\"!hasNext()\"\n (click)=\"onNext()\"\n >\n Siguiente\n <kf-icon name=\"chevron-right\" size=\"sm\" />\n </button>\n </nav>\n </div>\n</div>\n", styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-cursor-pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--kf-space-md)}.kf-cursor-pager__summary{font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);color:var(--kf-color-text)}.kf-cursor-pager__summary:empty{display:none}.kf-cursor-pager__controls{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kf-space-sm) var(--kf-space-md)}.kf-cursor-pager__size{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-cursor-pager__size-label{font-size:var(--kf-font-size-body-sm);color:var(--kf-color-text);white-space:nowrap}.kf-cursor-pager__divider{width:1px;height:1.25rem;background:var(--kf-color-border)}.kf-cursor-pager__nav{display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-cursor-pager__button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);min-height:32px;padding:0 var(--kf-space-sm);font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);color:var(--kf-color-text);background:transparent;border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-sm);cursor:pointer}.kf-cursor-pager__button:hover:not([aria-disabled=true]){background:var(--kf-color-white);border-color:var(--kf-color-text-muted)}.kf-cursor-pager__button:focus-visible{outline:2px solid transparent;box-shadow:var(--kf-shadow-focus)}.kf-cursor-pager__button[aria-disabled=true]{opacity:.5;cursor:not-allowed}@media(max-width:599.98px){.kf-cursor-pager__controls{width:100%}.kf-cursor-pager__divider{display:none}.kf-cursor-pager__nav{width:100%}.kf-cursor-pager__button{flex:1 1 0;min-height:36px}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "required", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
4958
5044
  }
4959
5045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: CursorPager, decorators: [{
4960
5046
  type: Component,
@@ -5766,15 +5852,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
5766
5852
  ], template: "@if (label()) {\n <kf-field-label [for]=\"inputId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<div\n class=\"kf-file-input__area\"\n [class.kf-file-input__area--dropzone]=\"dropzone()\"\n [class.kf-file-input__area--dragging]=\"dragging()\"\n [class.kf-file-input__area--invalid]=\"isInvalid()\"\n [class.kf-file-input__area--disabled]=\"isDisabled()\"\n (dragover)=\"dropzone() ? onDragOver($event) : null\"\n (dragleave)=\"dropzone() ? onDragLeave() : null\"\n (drop)=\"dropzone() ? onDrop($event) : null\"\n>\n <input\n #nativeInput\n type=\"file\"\n class=\"kf-file-input__native\"\n [id]=\"inputId\"\n [attr.accept]=\"accept() || null\"\n [multiple]=\"multiple()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required() && !files().length\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"isInvalid() ? true : null\"\n [attr.aria-label]=\"label() ? null : ariaLabel() || null\"\n (change)=\"onPick($event)\"\n />\n <label class=\"kf-file-input__button\" [for]=\"inputId\" aria-hidden=\"true\">\n <kf-icon name=\"upload-cloud\" size=\"sm\" />\n {{ triggerText() }}\n </label>\n @if (dropzone()) {\n <span class=\"kf-file-input__drop-text\" aria-hidden=\"true\">{{ dropzoneText() }}</span>\n }\n</div>\n@if (files().length) {\n <ul class=\"kf-file-input__files\" [id]=\"filesId\">\n @for (file of files(); track $index) {\n <li class=\"kf-file-input__file\">\n <kf-icon class=\"kf-file-input__file-icon\" name=\"file\" size=\"sm\" />\n <span class=\"kf-file-input__file-name\">{{ file.name }}</span>\n <span class=\"kf-file-input__file-size\">{{ formatSize(file) }}</span>\n <button\n type=\"button\"\n class=\"kf-file-input__remove\"\n [attr.aria-label]=\"removeLabel() + ' ' + file.name\"\n [disabled]=\"isDisabled()\"\n (click)=\"remove($index)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n </li>\n }\n </ul>\n}\n@if (message(); as text) {\n <span class=\"kf-file-input__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ text }}</span>\n}\n@if (effectiveHint() && !error()) {\n <span class=\"kf-file-input__hint kf-field-hint\" [id]=\"hintId\">{{ effectiveHint() }}</span>\n}\n", styles: [".kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);font-family:var(--kf-font-body)}.kf-file-input__area{position:relative;display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-file-input__native{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}.kf-file-input__native:disabled{cursor:not-allowed}.kf-file-input__button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);min-height:2.25rem;padding:var(--kf-space-sm) var(--kf-space-md);box-sizing:border-box;border:1px solid var(--kf-color-primary);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);color:var(--kf-color-primary-active);font:inherit;font-weight:600;pointer-events:none;transition:background .14s,box-shadow .14s}.kf-file-input__area:hover .kf-file-input__native:not(:disabled)+.kf-file-input__button{background:var(--kf-color-primary-soft)}.kf-file-input__native:focus-visible+.kf-file-input__button{box-shadow:var(--kf-shadow-focus);outline:2px solid transparent}.kf-file-input__area--invalid .kf-file-input__button{border-color:var(--kf-color-error);color:var(--kf-color-error-strong)}.kf-file-input__area--invalid .kf-file-input__native:focus-visible+.kf-file-input__button{box-shadow:var(--kf-shadow-focus-error)}.kf-file-input__area--disabled{opacity:.5}.kf-file-input__area--dropzone{flex-direction:column;justify-content:center;gap:var(--kf-space-xs);padding:var(--kf-space-lg) var(--kf-space-md);border:1px dashed var(--kf-color-border-strong);border-radius:var(--kf-radius-sm);background:var(--kf-color-surface);transition:background .14s,border-color .14s}.kf-file-input__area--dragging{border-color:var(--kf-color-primary);background:var(--kf-color-primary-soft)}.kf-file-input__area--dropzone.kf-file-input__area--invalid{border-color:var(--kf-color-error)}.kf-file-input__drop-text{font-size:.875rem;color:var(--kf-color-text);pointer-events:none}.kf-file-input__files{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--kf-space-xs)}.kf-file-input__file{display:flex;align-items:center;gap:var(--kf-space-sm);padding:var(--kf-space-xs) var(--kf-space-sm);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);min-width:0}.kf-file-input__file-icon{flex:none;color:var(--kf-color-text-muted)}.kf-file-input__file-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--kf-color-ink);font-weight:600}.kf-file-input__file-size{flex:none;font-size:.75rem;color:var(--kf-color-text)}.kf-file-input__remove{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:2rem;min-height:2rem;padding:0;border:none;border-radius:var(--kf-radius-xs);background:transparent;color:var(--kf-color-text);cursor:pointer}.kf-file-input__remove:hover:not(:disabled){background:var(--kf-color-surface);color:var(--kf-color-ink)}.kf-file-input__remove:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-file-input__hint{color:var(--kf-color-text)}@media(pointer:coarse),(max-width:760px){.kf-file-input__button{min-height:44px}.kf-file-input__remove{min-width:44px;min-height:44px}}\n"] }]
5767
5853
  }], propDecorators: { nativeInput: [{ type: i0.ViewChild, args: ['nativeInput', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], dropzone: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropzone", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], buttonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLabel", required: false }] }], changeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeLabel", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], dropzoneText: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropzoneText", required: false }] }], rejectedTypeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejectedTypeText", required: false }] }], rejectedSizeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejectedSizeText", required: false }] }], fileChange: [{ type: i0.Output, args: ["fileChange"] }], fileRejected: [{ type: i0.Output, args: ["fileRejected"] }] } });
5768
5854
 
5769
- /** Vacío o `undefined` no emiten el atributo; `0` sí es un límite válido. */
5770
- function normalizeBound(value) {
5771
- return value === undefined || value === '' ? null : value;
5772
- }
5773
5855
  /** `maxlength` como entero positivo; cualquier otra cosa (vacío, NaN, 0, negativo) no se emite. */
5774
5856
  function toMaxLength(value) {
5775
5857
  const parsed = typeof value === 'string' ? Number.parseInt(value, 10) : value;
5776
5858
  return typeof parsed === 'number' && Number.isInteger(parsed) && parsed > 0 ? parsed : null;
5777
5859
  }
5860
+
5861
+ /** Vacío o `undefined` no emiten el atributo; `0` sí es un límite válido. */
5862
+ function normalizeBound(value) {
5863
+ return value === undefined || value === '' ? null : value;
5864
+ }
5778
5865
  /**
5779
5866
  * Input de formulario apilado: label arriba (en mayúsculas vía CSS), campo con
5780
5867
  * fondo gris que pasa a blanco con anillo de foco azul al enfocar.
@@ -6304,7 +6391,7 @@ class Filter {
6304
6391
  this.fieldChange.emit({ key, value });
6305
6392
  }
6306
6393
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Filter, deps: [], target: i0.ɵɵFactoryTarget.Component });
6307
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Filter, isStandalone: true, selector: "kf-filter", inputs: { fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, mobileTitle: { classPropertyName: "mobileTitle", publicName: "mobileTitle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<ng-template #fieldsTpl let-stacked=\"stacked\">\n @for (field of fields(); track field.key) {\n @switch (field.type) {\n @case ('select') {\n <kf-select\n [label]=\"field.label ?? ''\"\n [options]=\"optionsFor(field.key)\"\n [value]=\"singleValueFor(field.key)\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n (valueChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n @case ('multi-select') {\n <kf-multi-select\n [label]=\"field.label ?? ''\"\n [options]=\"multiOptionsFor(field.key)\"\n [values]=\"multiValueFor(field.key)\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n (valuesChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n @case ('search') {\n <kf-input\n [label]=\"field.label ?? ''\"\n [icon]=\"field.icon ?? 'search'\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n [ngModel]=\"singleValueFor(field.key)\"\n (ngModelChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n }\n @if (!stacked && field.showDivider) {\n <kf-divider orientation=\"vertical\" />\n }\n }\n</ng-template>\n\n<div class=\"kf-filter kf-filter--row\">\n <ng-container [ngTemplateOutlet]=\"fieldsTpl\" [ngTemplateOutletContext]=\"{ stacked: false }\" />\n</div>\n\n<kf-collapsible class=\"kf-filter__collapsible\" [title]=\"mobileTitle()\">\n <div class=\"kf-filter kf-filter--stack\">\n <ng-container [ngTemplateOutlet]=\"fieldsTpl\" [ngTemplateOutletContext]=\"{ stacked: true }\" />\n </div>\n</kf-collapsible>\n", styles: ["@charset \"UTF-8\";:host{display:block}.kf-filter--row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--kf-space-md)}.kf-filter--stack{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-filter__collapsible{display:none}@media(max-width:768px){.kf-filter--row{display:none}.kf-filter__collapsible{display:block}}\n"], dependencies: [{ kind: "component", type: Collapsible, selector: "kf-collapsible", inputs: ["title", "expanded"], outputs: ["expandedChange"] }, { kind: "component", type: Divider, selector: "kf-divider", inputs: ["orientation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Input, selector: "kf-input", inputs: ["label", "hideLabel", "required", "icon", "suffix", "hint", "invalid", "errorMessage", "disabled", "readonly", "type", "placeholder", "autocomplete", "name", "inputmode", "min", "max", "step", "maxlength", "toggleable", "ariaLabel", "clearable", "clearLabel"], outputs: ["cleared"] }, { kind: "component", type: MultiSelect, selector: "kf-multi-select", inputs: ["label", "options", "values", "placeholder", "disabled", "width", "searchable", "searchThreshold"], outputs: ["valuesChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
6394
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Filter, isStandalone: true, selector: "kf-filter", inputs: { fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: true, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, mobileTitle: { classPropertyName: "mobileTitle", publicName: "mobileTitle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fieldChange: "fieldChange" }, ngImport: i0, template: "<ng-template #fieldsTpl let-stacked=\"stacked\">\n @for (field of fields(); track field.key) {\n @switch (field.type) {\n @case ('select') {\n <kf-select\n [label]=\"field.label ?? ''\"\n [options]=\"optionsFor(field.key)\"\n [value]=\"singleValueFor(field.key)\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n (valueChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n @case ('multi-select') {\n <kf-multi-select\n [label]=\"field.label ?? ''\"\n [options]=\"multiOptionsFor(field.key)\"\n [values]=\"multiValueFor(field.key)\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n (valuesChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n @case ('search') {\n <kf-input\n [label]=\"field.label ?? ''\"\n [icon]=\"field.icon ?? 'search'\"\n [placeholder]=\"field.placeholder ?? ''\"\n [style.width]=\"stacked ? '100%' : fieldWidth(field)\"\n [ngModel]=\"singleValueFor(field.key)\"\n (ngModelChange)=\"onFieldChange(field.key, $event)\"\n />\n }\n }\n @if (!stacked && field.showDivider) {\n <kf-divider orientation=\"vertical\" />\n }\n }\n</ng-template>\n\n<div class=\"kf-filter kf-filter--row\">\n <ng-container [ngTemplateOutlet]=\"fieldsTpl\" [ngTemplateOutletContext]=\"{ stacked: false }\" />\n</div>\n\n<kf-collapsible class=\"kf-filter__collapsible\" [title]=\"mobileTitle()\">\n <div class=\"kf-filter kf-filter--stack\">\n <ng-container [ngTemplateOutlet]=\"fieldsTpl\" [ngTemplateOutletContext]=\"{ stacked: true }\" />\n </div>\n</kf-collapsible>\n", styles: ["@charset \"UTF-8\";:host{display:block}.kf-filter--row{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--kf-space-md)}.kf-filter--stack{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-filter__collapsible{display:none}@media(max-width:768px){.kf-filter--row{display:none}.kf-filter__collapsible{display:block}}\n"], dependencies: [{ kind: "component", type: Collapsible, selector: "kf-collapsible", inputs: ["title", "expanded"], outputs: ["expandedChange"] }, { kind: "component", type: Divider, selector: "kf-divider", inputs: ["orientation"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Input, selector: "kf-input", inputs: ["label", "hideLabel", "required", "icon", "suffix", "hint", "invalid", "errorMessage", "disabled", "readonly", "type", "placeholder", "autocomplete", "name", "inputmode", "min", "max", "step", "maxlength", "toggleable", "ariaLabel", "clearable", "clearLabel"], outputs: ["cleared"] }, { kind: "component", type: MultiSelect, selector: "kf-multi-select", inputs: ["label", "options", "values", "placeholder", "disabled", "width", "searchable", "searchThreshold"], outputs: ["valuesChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Select, selector: "kf-select", inputs: ["label", "hideLabel", "prefix", "options", "value", "placeholder", "disabled", "invalid", "required", "errorMessage", "variant", "width", "size", "searchable", "searchThreshold", "ariaLabel", "icon", "panelTitle", "panelWidth"], outputs: ["valueChange"] }] });
6308
6395
  }
6309
6396
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Filter, decorators: [{
6310
6397
  type: Component,
@@ -7456,11 +7543,11 @@ class Modal {
7456
7543
  }
7457
7544
  }
7458
7545
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Modal, deps: [], target: i0.ɵɵFactoryTarget.Component });
7459
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Modal, isStandalone: true, selector: "kf-modal", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, dividers: { classPropertyName: "dividers", publicName: "dividers", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fullscreenOnMobile: { classPropertyName: "fullscreenOnMobile", publicName: "fullscreenOnMobile", isSignal: true, isRequired: false, transformFunction: null }, initialFocus: { classPropertyName: "initialFocus", publicName: "initialFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { listeners: { "click": "onHostClick($event)" } }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #dialog\n class=\"kf-modal\"\n [class.kf-modal--bounded]=\"!!maxHeight()\"\n [class.kf-modal--fullscreen-mobile]=\"fullscreenOnMobile()\"\n [class.kf-modal--dividers]=\"dividers()\"\n [attr.data-size]=\"size()\"\n [style.--kf-modal-width]=\"width()\"\n [style.--kf-modal-max-height]=\"maxHeight()\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n (cancel)=\"onCancel($event)\"\n (close)=\"open.set(false)\"\n>\n @if (open()) {\n <div #panel class=\"kf-modal__panel\">\n <div class=\"kf-modal__head\">\n <div class=\"kf-modal__heading\">\n @if (title()) {\n <h2 class=\"kf-modal__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\n <ng-content select=\"[kf-modal-meta]\" />\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-modal__close\"\n aria-label=\"Cerrar di\u00E1logo\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n <div class=\"kf-modal__toolbar\"><ng-content select=\"[kf-modal-toolbar]\" /></div>\n <div class=\"kf-modal__body\"><ng-content /></div>\n <div class=\"kf-modal__footer\"><ng-content select=\"[footer]\" /></div>\n </div>\n }\n</dialog>\n", styles: [".kf-modal{width:min(var(--kf-modal-width, 480px),calc(100vw - 2 * var(--kf-space-md)));max-height:calc(100vh - 2 * var(--kf-space-xl));padding:0;border:none;background:transparent;overflow:visible;font-family:var(--kf-font-body)}.kf-modal::backdrop{background:#171d2573}.kf-modal__panel{display:flex;flex-direction:column;gap:var(--kf-space-md);padding:var(--kf-space-lg);background:var(--kf-color-white);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg)}.kf-modal__head{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-modal__heading{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-sm);row-gap:var(--kf-space-xs)}.kf-modal__title{margin:0;font-family:var(--kf-font-title);font-size:1.375rem;font-weight:700;color:var(--kf-color-ink)}.kf-modal__close{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;margin:-4px -6px 0 0;padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer}.kf-modal__close:hover{color:var(--kf-color-ink);background:var(--kf-color-surface)}.kf-modal__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-modal__toolbar:empty{display:none}.kf-modal__body{color:var(--kf-color-text);overflow-y:auto}.kf-modal__footer:empty{display:none}.kf-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--kf-space-sm)}.kf-modal__footer-start{margin-right:auto}.kf-modal[data-size=sm]{--kf-modal-width: 480px}.kf-modal[data-size=md]{--kf-modal-width: 640px}.kf-modal[data-size=lg]{--kf-modal-width: 880px}.kf-modal[data-size=xl]{--kf-modal-width: 1120px}.kf-modal--dividers .kf-modal__head{padding-bottom:var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-modal--dividers .kf-modal__footer{padding-top:var(--kf-space-md);border-top:1px solid var(--kf-color-border)}.kf-modal--bounded{max-height:min(var(--kf-modal-max-height),calc(100dvh - 2 * var(--kf-space-md)))}.kf-modal--bounded .kf-modal__panel{box-sizing:border-box;max-height:inherit}.kf-modal--bounded .kf-modal__body{flex:1 1 auto;min-height:0;overscroll-behavior:contain}@media(max-width:640px){.kf-modal--fullscreen-mobile{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0}.kf-modal--fullscreen-mobile .kf-modal__panel{box-sizing:border-box;height:100%;max-height:100%;padding:var(--kf-space-md);gap:var(--kf-space-sm);border-radius:0;box-shadow:none}.kf-modal--fullscreen-mobile .kf-modal__body{flex:1 1 auto;min-height:0}.kf-modal--fullscreen-mobile .kf-modal__title{font-size:var(--kf-font-size-title-sm)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
7546
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Modal, isStandalone: true, selector: "kf-modal", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, dividers: { classPropertyName: "dividers", publicName: "dividers", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fullscreenOnMobile: { classPropertyName: "fullscreenOnMobile", publicName: "fullscreenOnMobile", isSignal: true, isRequired: false, transformFunction: null }, initialFocus: { classPropertyName: "initialFocus", publicName: "initialFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { listeners: { "click": "onHostClick($event)" } }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #dialog\n class=\"kf-modal\"\n [class.kf-modal--bounded]=\"!!maxHeight()\"\n [class.kf-modal--fullscreen-mobile]=\"fullscreenOnMobile()\"\n [class.kf-modal--dividers]=\"dividers()\"\n [attr.data-size]=\"size()\"\n [style.--kf-modal-width]=\"width()\"\n [style.--kf-modal-max-height]=\"maxHeight()\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n (cancel)=\"onCancel($event)\"\n (close)=\"open.set(false)\"\n>\n @if (open()) {\n <div #panel class=\"kf-modal__panel\">\n <div class=\"kf-modal__head\">\n <div class=\"kf-modal__heading\">\n @if (title()) {\n <h2 class=\"kf-modal__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\n <ng-content select=\"[kf-modal-meta]\" />\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-modal__close\"\n aria-label=\"Cerrar di\u00E1logo\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n <div class=\"kf-modal__toolbar\"><ng-content select=\"[kf-modal-toolbar]\" /></div>\n <div class=\"kf-modal__body\"><ng-content /></div>\n <div class=\"kf-modal__footer\"><ng-content select=\"[footer]\" /></div>\n </div>\n }\n</dialog>\n", styles: [".kf-modal{width:min(var(--kf-modal-width, 480px),calc(100vw - 2 * var(--kf-space-md)));max-height:calc(100vh - 2 * var(--kf-space-xl));padding:0;border:none;background:transparent;overflow:visible;font-family:var(--kf-font-body)}.kf-modal::backdrop{background:#171d2573}.kf-modal__panel{display:flex;flex-direction:column;gap:var(--kf-space-md);padding:var(--kf-space-lg);background:var(--kf-color-white);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg)}.kf-modal__head{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-modal__heading{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-sm);row-gap:var(--kf-space-xs)}.kf-modal__title{margin:0;font-family:var(--kf-font-title);font-size:1.375rem;font-weight:700;color:var(--kf-color-ink)}.kf-modal__close{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;margin:-4px -6px 0 0;padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer}.kf-modal__close:after{content:\"\";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}.kf-modal__close:hover{color:var(--kf-color-ink);background:var(--kf-color-surface)}.kf-modal__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-modal__toolbar:empty{display:none}.kf-modal__body{margin:calc(-1 * var(--kf-space-xs));padding:var(--kf-space-xs);color:var(--kf-color-text);overflow-y:auto}.kf-modal__footer:empty{display:none}.kf-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--kf-space-sm)}.kf-modal__footer-start{margin-right:auto}.kf-modal[data-size=sm]{--kf-modal-width: 480px}.kf-modal[data-size=md]{--kf-modal-width: 640px}.kf-modal[data-size=lg]{--kf-modal-width: 880px}.kf-modal[data-size=xl]{--kf-modal-width: 1120px}.kf-modal--dividers .kf-modal__head{padding-bottom:var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-modal--dividers .kf-modal__footer{padding-top:var(--kf-space-md);border-top:1px solid var(--kf-color-border)}.kf-modal--bounded{max-height:min(var(--kf-modal-max-height),calc(100dvh - 2 * var(--kf-space-md)))}.kf-modal--bounded .kf-modal__panel{box-sizing:border-box;max-height:inherit}.kf-modal--bounded .kf-modal__body{flex:1 1 auto;min-height:0;overscroll-behavior:contain}@media(max-width:640px){.kf-modal--fullscreen-mobile{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0}.kf-modal--fullscreen-mobile .kf-modal__panel{box-sizing:border-box;height:100%;max-height:100%;padding:var(--kf-space-md);gap:var(--kf-space-sm);border-radius:0;box-shadow:none}.kf-modal--fullscreen-mobile .kf-modal__body{flex:1 1 auto;min-height:0}.kf-modal--fullscreen-mobile .kf-modal__title{font-size:var(--kf-font-size-title-sm)}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }] });
7460
7547
  }
7461
7548
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Modal, decorators: [{
7462
7549
  type: Component,
7463
- args: [{ selector: 'kf-modal', imports: [Icon], template: "<dialog\n #dialog\n class=\"kf-modal\"\n [class.kf-modal--bounded]=\"!!maxHeight()\"\n [class.kf-modal--fullscreen-mobile]=\"fullscreenOnMobile()\"\n [class.kf-modal--dividers]=\"dividers()\"\n [attr.data-size]=\"size()\"\n [style.--kf-modal-width]=\"width()\"\n [style.--kf-modal-max-height]=\"maxHeight()\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n (cancel)=\"onCancel($event)\"\n (close)=\"open.set(false)\"\n>\n @if (open()) {\n <div #panel class=\"kf-modal__panel\">\n <div class=\"kf-modal__head\">\n <div class=\"kf-modal__heading\">\n @if (title()) {\n <h2 class=\"kf-modal__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\n <ng-content select=\"[kf-modal-meta]\" />\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-modal__close\"\n aria-label=\"Cerrar di\u00E1logo\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n <div class=\"kf-modal__toolbar\"><ng-content select=\"[kf-modal-toolbar]\" /></div>\n <div class=\"kf-modal__body\"><ng-content /></div>\n <div class=\"kf-modal__footer\"><ng-content select=\"[footer]\" /></div>\n </div>\n }\n</dialog>\n", styles: [".kf-modal{width:min(var(--kf-modal-width, 480px),calc(100vw - 2 * var(--kf-space-md)));max-height:calc(100vh - 2 * var(--kf-space-xl));padding:0;border:none;background:transparent;overflow:visible;font-family:var(--kf-font-body)}.kf-modal::backdrop{background:#171d2573}.kf-modal__panel{display:flex;flex-direction:column;gap:var(--kf-space-md);padding:var(--kf-space-lg);background:var(--kf-color-white);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg)}.kf-modal__head{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-modal__heading{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-sm);row-gap:var(--kf-space-xs)}.kf-modal__title{margin:0;font-family:var(--kf-font-title);font-size:1.375rem;font-weight:700;color:var(--kf-color-ink)}.kf-modal__close{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;margin:-4px -6px 0 0;padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer}.kf-modal__close:hover{color:var(--kf-color-ink);background:var(--kf-color-surface)}.kf-modal__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-modal__toolbar:empty{display:none}.kf-modal__body{color:var(--kf-color-text);overflow-y:auto}.kf-modal__footer:empty{display:none}.kf-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--kf-space-sm)}.kf-modal__footer-start{margin-right:auto}.kf-modal[data-size=sm]{--kf-modal-width: 480px}.kf-modal[data-size=md]{--kf-modal-width: 640px}.kf-modal[data-size=lg]{--kf-modal-width: 880px}.kf-modal[data-size=xl]{--kf-modal-width: 1120px}.kf-modal--dividers .kf-modal__head{padding-bottom:var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-modal--dividers .kf-modal__footer{padding-top:var(--kf-space-md);border-top:1px solid var(--kf-color-border)}.kf-modal--bounded{max-height:min(var(--kf-modal-max-height),calc(100dvh - 2 * var(--kf-space-md)))}.kf-modal--bounded .kf-modal__panel{box-sizing:border-box;max-height:inherit}.kf-modal--bounded .kf-modal__body{flex:1 1 auto;min-height:0;overscroll-behavior:contain}@media(max-width:640px){.kf-modal--fullscreen-mobile{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0}.kf-modal--fullscreen-mobile .kf-modal__panel{box-sizing:border-box;height:100%;max-height:100%;padding:var(--kf-space-md);gap:var(--kf-space-sm);border-radius:0;box-shadow:none}.kf-modal--fullscreen-mobile .kf-modal__body{flex:1 1 auto;min-height:0}.kf-modal--fullscreen-mobile .kf-modal__title{font-size:var(--kf-font-size-title-sm)}}\n"] }]
7550
+ args: [{ selector: 'kf-modal', imports: [Icon], template: "<dialog\n #dialog\n class=\"kf-modal\"\n [class.kf-modal--bounded]=\"!!maxHeight()\"\n [class.kf-modal--fullscreen-mobile]=\"fullscreenOnMobile()\"\n [class.kf-modal--dividers]=\"dividers()\"\n [attr.data-size]=\"size()\"\n [style.--kf-modal-width]=\"width()\"\n [style.--kf-modal-max-height]=\"maxHeight()\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n (cancel)=\"onCancel($event)\"\n (close)=\"open.set(false)\"\n>\n @if (open()) {\n <div #panel class=\"kf-modal__panel\">\n <div class=\"kf-modal__head\">\n <div class=\"kf-modal__heading\">\n @if (title()) {\n <h2 class=\"kf-modal__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\n <ng-content select=\"[kf-modal-meta]\" />\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"kf-modal__close\"\n aria-label=\"Cerrar di\u00E1logo\"\n (click)=\"open.set(false)\"\n >\n <kf-icon name=\"x\" size=\"sm\" />\n </button>\n }\n </div>\n <div class=\"kf-modal__toolbar\"><ng-content select=\"[kf-modal-toolbar]\" /></div>\n <div class=\"kf-modal__body\"><ng-content /></div>\n <div class=\"kf-modal__footer\"><ng-content select=\"[footer]\" /></div>\n </div>\n }\n</dialog>\n", styles: [".kf-modal{width:min(var(--kf-modal-width, 480px),calc(100vw - 2 * var(--kf-space-md)));max-height:calc(100vh - 2 * var(--kf-space-xl));padding:0;border:none;background:transparent;overflow:visible;font-family:var(--kf-font-body)}.kf-modal::backdrop{background:#171d2573}.kf-modal__panel{display:flex;flex-direction:column;gap:var(--kf-space-md);padding:var(--kf-space-lg);background:var(--kf-color-white);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg)}.kf-modal__head{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-modal__heading{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:var(--kf-space-sm);row-gap:var(--kf-space-xs)}.kf-modal__title{margin:0;font-family:var(--kf-font-title);font-size:1.375rem;font-weight:700;color:var(--kf-color-ink)}.kf-modal__close{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;margin:-4px -6px 0 0;padding:2px;border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer}.kf-modal__close:after{content:\"\";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}.kf-modal__close:hover{color:var(--kf-color-ink);background:var(--kf-color-surface)}.kf-modal__close:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-modal__toolbar:empty{display:none}.kf-modal__body{margin:calc(-1 * var(--kf-space-xs));padding:var(--kf-space-xs);color:var(--kf-color-text);overflow-y:auto}.kf-modal__footer:empty{display:none}.kf-modal__footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--kf-space-sm)}.kf-modal__footer-start{margin-right:auto}.kf-modal[data-size=sm]{--kf-modal-width: 480px}.kf-modal[data-size=md]{--kf-modal-width: 640px}.kf-modal[data-size=lg]{--kf-modal-width: 880px}.kf-modal[data-size=xl]{--kf-modal-width: 1120px}.kf-modal--dividers .kf-modal__head{padding-bottom:var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-modal--dividers .kf-modal__footer{padding-top:var(--kf-space-md);border-top:1px solid var(--kf-color-border)}.kf-modal--bounded{max-height:min(var(--kf-modal-max-height),calc(100dvh - 2 * var(--kf-space-md)))}.kf-modal--bounded .kf-modal__panel{box-sizing:border-box;max-height:inherit}.kf-modal--bounded .kf-modal__body{flex:1 1 auto;min-height:0;overscroll-behavior:contain}@media(max-width:640px){.kf-modal--fullscreen-mobile{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0}.kf-modal--fullscreen-mobile .kf-modal__panel{box-sizing:border-box;height:100%;max-height:100%;padding:var(--kf-space-md);gap:var(--kf-space-sm);border-radius:0;box-shadow:none}.kf-modal--fullscreen-mobile .kf-modal__body{flex:1 1 auto;min-height:0}.kf-modal--fullscreen-mobile .kf-modal__title{font-size:var(--kf-font-size-title-sm)}}\n"] }]
7464
7551
  }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], dividers: [{ type: i0.Input, args: [{ isSignal: true, alias: "dividers", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], fullscreenOnMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullscreenOnMobile", required: false }] }], initialFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialFocus", required: false }] }], dialog: [{ type: i0.ViewChild, args: ['dialog', { isSignal: true }] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], onHostClick: [{
7465
7552
  type: HostListener,
7466
7553
  args: ['click', ['$event']]
@@ -9009,8 +9096,16 @@ class SidebarShell {
9009
9096
  */
9010
9097
  itemsCollapsed = computed(() => this.collapsed() && !this.isMobileViewport(), /* @ts-ignore */
9011
9098
  ...(ngDevMode ? [{ debugName: "itemsCollapsed" }] : /* istanbul ignore next */ []));
9012
- /** Cierra el panel mobile con Escape — mismo criterio que `Dropdown`/`Modal`/`Drawer`. */
9013
- onEscape() {
9099
+ /**
9100
+ * Cierra el panel mobile con Escape — mismo criterio que `Drawer`: si un
9101
+ * panel flotante de adentro (`kf-dropdown`, `kf-select`) ya consumió la
9102
+ * tecla en captura (`defaultPrevented`), el panel mobile sigue abierto y
9103
+ * solo cierra la capa superior.
9104
+ */
9105
+ onEscape(event) {
9106
+ if (!this.mobileOpen() || event.defaultPrevented) {
9107
+ return;
9108
+ }
9014
9109
  this.mobileOpen.set(false);
9015
9110
  }
9016
9111
  onNavItemClick(event, item) {
@@ -9019,14 +9114,14 @@ class SidebarShell {
9019
9114
  this.navItemClick.emit(item);
9020
9115
  }
9021
9116
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SidebarShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
9022
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SidebarShell, isStandalone: true, selector: "kf-sidebar-shell", inputs: { navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, mobileOpen: { classPropertyName: "mobileOpen", publicName: "mobileOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange", mobileOpen: "mobileOpenChange", navItemClick: "navItemClick" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (mobileOpen()) {\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__backdrop\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n ></button>\n}\n\n<aside\n class=\"kf-sidebar-shell__rail\"\n [class.kf-sidebar-shell__rail--collapsed]=\"itemsCollapsed()\"\n [class.kf-sidebar-shell__rail--mobile-open]=\"mobileOpen()\"\n>\n <div class=\"kf-sidebar-shell__brand\">\n <div class=\"kf-sidebar-shell__brand-full\">\n <ng-content select=\"[kf-sidebar-brand]\" />\n </div>\n <div class=\"kf-sidebar-shell__brand-collapsed\">\n <ng-content select=\"[kf-sidebar-brand-collapsed]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__mobile-close\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n >\n <kf-icon name=\"x\" size=\"md\" />\n </button>\n </div>\n\n <nav class=\"kf-sidebar-shell__nav\">\n @for (entry of itemsWithGroupHeader(); track entry.item.href) {\n @if (entry.showGroupLabel && !itemsCollapsed()) {\n <div class=\"kf-sidebar-shell__group-label\">{{ entry.item.groupLabel }}</div>\n }\n <kf-sidebar-nav-item\n [icon]=\"entry.item.icon\"\n [label]=\"entry.item.label\"\n [href]=\"entry.item.href\"\n [active]=\"!!entry.item.active\"\n [collapsed]=\"itemsCollapsed()\"\n (click)=\"onNavItemClick($event, entry.item)\"\n />\n }\n </nav>\n\n <div class=\"kf-sidebar-shell__bottom\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__collapse-toggle\"\n [class.kf-sidebar-shell__collapse-toggle--collapsed]=\"itemsCollapsed()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA'\"\n [kfTooltip]=\"itemsCollapsed() ? (collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA') : ''\"\n (click)=\"collapsed.set(!collapsed())\"\n >\n <kf-icon [name]=\"collapsed() ? 'chevron-right' : 'chevron-left'\" size=\"sm\" />\n @if (!itemsCollapsed()) {\n <span class=\"kf-sidebar-shell__collapse-toggle-label\">\n {{ collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA' }}\n </span>\n }\n </button>\n\n <div class=\"kf-sidebar-shell__footer\">\n <ng-content select=\"[kf-sidebar-footer]\" />\n </div>\n </div>\n</aside>\n\n<div class=\"kf-sidebar-shell__topbar\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__menu-toggle\"\n aria-label=\"Abrir men\u00FA de navegaci\u00F3n\"\n (click)=\"mobileOpen.set(true)\"\n >\n <kf-icon name=\"menu\" size=\"md\" />\n </button>\n <div class=\"kf-sidebar-shell__topbar-brand\">\n <ng-content select=\"[kf-sidebar-brand-mobile]\" />\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:contents}.kf-sidebar-shell__backdrop{display:none}.kf-sidebar-shell__rail{box-sizing:border-box;display:flex;flex-direction:column;position:sticky;top:0;height:100dvh;width:268px;flex:none;padding:var(--kf-space-lg) var(--kf-space-md);background:linear-gradient(190deg,var(--kf-color-sidebar-gradient-from) 0%,var(--kf-color-sidebar-gradient-to) 60%);transition:width .18s ease,padding-inline .18s ease}.kf-sidebar-shell__rail--collapsed{width:56px;padding-inline:var(--kf-space-sm)}.kf-sidebar-shell__brand{display:flex;align-items:center;justify-content:center;margin-bottom:var(--kf-space-xl)}.kf-sidebar-shell__brand-full{display:flex;justify-content:center;min-width:0}.kf-sidebar-shell__brand-full ::ng-deep img{display:block;height:1.5rem}.kf-sidebar-shell__brand-collapsed{display:none;justify-content:center;min-width:0}.kf-sidebar-shell__brand-collapsed ::ng-deep img{display:block;height:1.75rem}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-full{display:none}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-collapsed{display:flex}.kf-sidebar-shell__mobile-close{display:none;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;border-radius:var(--kf-radius-sm);background:#ffffff14;color:#fffc;cursor:pointer}.kf-sidebar-shell__mobile-close:hover{background:#ffffff29;color:var(--kf-color-white)}.kf-sidebar-shell__nav{flex:1 1 auto;display:flex;flex-direction:column;gap:var(--kf-space-xs);overflow-y:auto}.kf-sidebar-shell__group-label{margin-top:var(--kf-space-sm);padding:0 var(--kf-space-md);font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#fff6;white-space:nowrap;overflow:hidden}.kf-sidebar-shell__nav>.kf-sidebar-shell__group-label:first-child{margin-top:0}.kf-sidebar-shell__bottom{display:flex;flex-direction:column;margin-top:var(--kf-space-sm);padding-top:var(--kf-space-sm);border-top:1px solid rgba(255,255,255,.12)}.kf-sidebar-shell__footer{margin-top:var(--kf-space-sm)}.kf-sidebar-shell__footer:empty{display:none}.kf-sidebar-shell__collapse-toggle{box-sizing:border-box;display:flex;align-items:center;gap:var(--kf-space-sm);width:100%;padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-radius:var(--kf-radius-sm);background:#ffffff0f;color:#ffffffb3;font-family:var(--kf-font-body);font-size:.8125rem;font-weight:600;cursor:pointer;transition:background .14s,color .14s}.kf-sidebar-shell__collapse-toggle:hover{background:#ffffff1f;color:var(--kf-color-white)}.kf-sidebar-shell__collapse-toggle--collapsed{justify-content:center;width:40px;height:40px;padding-inline:0}.kf-sidebar-shell__collapse-toggle-label{flex:1 1 auto;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-sidebar-shell__topbar{display:none}@media(max-width:900px){.kf-sidebar-shell__rail{position:fixed;inset:0 auto 0 0;z-index:100;width:284px;max-width:86vw;transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);box-shadow:none}.kf-sidebar-shell__rail--mobile-open{transform:translate(0);box-shadow:var(--kf-shadow-lg)}.kf-sidebar-shell__rail--collapsed{width:284px;max-width:86vw;padding-inline:var(--kf-space-md)}.kf-sidebar-shell__brand{display:grid;grid-template-columns:1fr 2rem;align-items:center}.kf-sidebar-shell__brand-full{grid-column:1;justify-content:flex-start}.kf-sidebar-shell__mobile-close{grid-column:2;display:flex}.kf-sidebar-shell__collapse-toggle{display:none}.kf-sidebar-shell__backdrop{display:block;position:fixed;inset:0;z-index:90;border:none;padding:0;cursor:pointer;background:#0a0e1480}.kf-sidebar-shell__topbar{display:flex;align-items:center;gap:var(--kf-space-md);padding:var(--kf-space-sm) var(--kf-space-lg);background:var(--kf-color-white);border-bottom:1px solid var(--kf-color-border)}.kf-sidebar-shell__menu-toggle{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;border-radius:var(--kf-radius-sm);background:transparent;color:var(--kf-color-ink);cursor:pointer;flex:none}.kf-sidebar-shell__menu-toggle:hover{background:var(--kf-color-surface)}.kf-sidebar-shell__topbar-brand ::ng-deep img{display:block;height:1.25rem}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: SidebarNavItem, selector: "kf-sidebar-nav-item", inputs: ["icon", "label", "href", "active", "collapsed"] }, { kind: "directive", type: TooltipDirective, selector: "[kfTooltip]", inputs: ["kfTooltip", "kfTooltipPosition"] }] });
9117
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SidebarShell, isStandalone: true, selector: "kf-sidebar-shell", inputs: { navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, mobileOpen: { classPropertyName: "mobileOpen", publicName: "mobileOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange", mobileOpen: "mobileOpenChange", navItemClick: "navItemClick" }, host: { listeners: { "document:keydown.escape": "onEscape($event)" } }, ngImport: i0, template: "@if (mobileOpen()) {\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__backdrop\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n ></button>\n}\n\n<aside\n class=\"kf-sidebar-shell__rail\"\n [class.kf-sidebar-shell__rail--collapsed]=\"itemsCollapsed()\"\n [class.kf-sidebar-shell__rail--mobile-open]=\"mobileOpen()\"\n>\n <div class=\"kf-sidebar-shell__brand\">\n <div class=\"kf-sidebar-shell__brand-full\">\n <ng-content select=\"[kf-sidebar-brand]\" />\n </div>\n <div class=\"kf-sidebar-shell__brand-collapsed\">\n <ng-content select=\"[kf-sidebar-brand-collapsed]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__mobile-close\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n >\n <kf-icon name=\"x\" size=\"md\" />\n </button>\n </div>\n\n <nav class=\"kf-sidebar-shell__nav\">\n @for (entry of itemsWithGroupHeader(); track entry.item.href) {\n @if (entry.showGroupLabel && !itemsCollapsed()) {\n <div class=\"kf-sidebar-shell__group-label\">{{ entry.item.groupLabel }}</div>\n }\n <kf-sidebar-nav-item\n [icon]=\"entry.item.icon\"\n [label]=\"entry.item.label\"\n [href]=\"entry.item.href\"\n [active]=\"!!entry.item.active\"\n [collapsed]=\"itemsCollapsed()\"\n (click)=\"onNavItemClick($event, entry.item)\"\n />\n }\n </nav>\n\n <div class=\"kf-sidebar-shell__bottom\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__collapse-toggle\"\n [class.kf-sidebar-shell__collapse-toggle--collapsed]=\"itemsCollapsed()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA'\"\n [kfTooltip]=\"itemsCollapsed() ? (collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA') : ''\"\n (click)=\"collapsed.set(!collapsed())\"\n >\n <kf-icon [name]=\"collapsed() ? 'chevron-right' : 'chevron-left'\" size=\"sm\" />\n @if (!itemsCollapsed()) {\n <span class=\"kf-sidebar-shell__collapse-toggle-label\">\n {{ collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA' }}\n </span>\n }\n </button>\n\n <div class=\"kf-sidebar-shell__footer\">\n <ng-content select=\"[kf-sidebar-footer]\" />\n </div>\n </div>\n</aside>\n\n<div class=\"kf-sidebar-shell__topbar\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__menu-toggle\"\n aria-label=\"Abrir men\u00FA de navegaci\u00F3n\"\n (click)=\"mobileOpen.set(true)\"\n >\n <kf-icon name=\"menu\" size=\"md\" />\n </button>\n <div class=\"kf-sidebar-shell__topbar-brand\">\n <ng-content select=\"[kf-sidebar-brand-mobile]\" />\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:contents}.kf-sidebar-shell__backdrop{display:none}.kf-sidebar-shell__rail{box-sizing:border-box;display:flex;flex-direction:column;position:sticky;top:0;height:100dvh;width:268px;flex:none;padding:var(--kf-space-lg) var(--kf-space-md);background:linear-gradient(190deg,var(--kf-color-sidebar-gradient-from) 0%,var(--kf-color-sidebar-gradient-to) 60%);transition:width .18s ease,padding-inline .18s ease}.kf-sidebar-shell__rail--collapsed{width:56px;padding-inline:var(--kf-space-sm)}.kf-sidebar-shell__brand{display:flex;align-items:center;justify-content:center;margin-bottom:var(--kf-space-xl)}.kf-sidebar-shell__brand-full{display:flex;justify-content:center;min-width:0}.kf-sidebar-shell__brand-full ::ng-deep img{display:block;height:1.5rem}.kf-sidebar-shell__brand-collapsed{display:none;justify-content:center;min-width:0}.kf-sidebar-shell__brand-collapsed ::ng-deep img{display:block;height:1.75rem}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-full{display:none}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-collapsed{display:flex}.kf-sidebar-shell__mobile-close{display:none;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;border-radius:var(--kf-radius-sm);background:#ffffff14;color:#fffc;cursor:pointer}.kf-sidebar-shell__mobile-close:hover{background:#ffffff29;color:var(--kf-color-white)}.kf-sidebar-shell__nav{flex:1 1 auto;display:flex;flex-direction:column;gap:var(--kf-space-xs);overflow-y:auto}.kf-sidebar-shell__group-label{margin-top:var(--kf-space-sm);padding:0 var(--kf-space-md);font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#fff6;white-space:nowrap;overflow:hidden}.kf-sidebar-shell__nav>.kf-sidebar-shell__group-label:first-child{margin-top:0}.kf-sidebar-shell__bottom{display:flex;flex-direction:column;margin-top:var(--kf-space-sm);padding-top:var(--kf-space-sm);border-top:1px solid rgba(255,255,255,.12)}.kf-sidebar-shell__footer{margin-top:var(--kf-space-sm)}.kf-sidebar-shell__footer:empty{display:none}.kf-sidebar-shell__collapse-toggle{box-sizing:border-box;display:flex;align-items:center;gap:var(--kf-space-sm);width:100%;padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-radius:var(--kf-radius-sm);background:#ffffff0f;color:#ffffffb3;font-family:var(--kf-font-body);font-size:.8125rem;font-weight:600;cursor:pointer;transition:background .14s,color .14s}.kf-sidebar-shell__collapse-toggle:hover{background:#ffffff1f;color:var(--kf-color-white)}.kf-sidebar-shell__collapse-toggle--collapsed{justify-content:center;width:40px;height:40px;padding-inline:0}.kf-sidebar-shell__collapse-toggle-label{flex:1 1 auto;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-sidebar-shell__topbar{display:none}@media(max-width:900px){.kf-sidebar-shell__rail{position:fixed;inset:0 auto 0 0;z-index:100;width:284px;max-width:86vw;transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);box-shadow:none}.kf-sidebar-shell__rail--mobile-open{transform:translate(0);box-shadow:var(--kf-shadow-lg)}.kf-sidebar-shell__rail--collapsed{width:284px;max-width:86vw;padding-inline:var(--kf-space-md)}.kf-sidebar-shell__brand{display:grid;grid-template-columns:1fr 2rem;align-items:center}.kf-sidebar-shell__brand-full{grid-column:1;justify-content:flex-start}.kf-sidebar-shell__mobile-close{grid-column:2;display:flex}.kf-sidebar-shell__collapse-toggle{display:none}.kf-sidebar-shell__backdrop{display:block;position:fixed;inset:0;z-index:90;border:none;padding:0;cursor:pointer;background:#0a0e1480}.kf-sidebar-shell__topbar{display:flex;align-items:center;gap:var(--kf-space-md);padding:var(--kf-space-sm) var(--kf-space-lg);background:var(--kf-color-white);border-bottom:1px solid var(--kf-color-border)}.kf-sidebar-shell__menu-toggle{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;border-radius:var(--kf-radius-sm);background:transparent;color:var(--kf-color-ink);cursor:pointer;flex:none}.kf-sidebar-shell__menu-toggle:hover{background:var(--kf-color-surface)}.kf-sidebar-shell__topbar-brand ::ng-deep img{display:block;height:1.25rem}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: SidebarNavItem, selector: "kf-sidebar-nav-item", inputs: ["icon", "label", "href", "active", "collapsed"] }, { kind: "directive", type: TooltipDirective, selector: "[kfTooltip]", inputs: ["kfTooltip", "kfTooltipPosition"] }] });
9023
9118
  }
9024
9119
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SidebarShell, decorators: [{
9025
9120
  type: Component,
9026
9121
  args: [{ selector: 'kf-sidebar-shell', imports: [Icon, SidebarNavItem, TooltipDirective], template: "@if (mobileOpen()) {\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__backdrop\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n ></button>\n}\n\n<aside\n class=\"kf-sidebar-shell__rail\"\n [class.kf-sidebar-shell__rail--collapsed]=\"itemsCollapsed()\"\n [class.kf-sidebar-shell__rail--mobile-open]=\"mobileOpen()\"\n>\n <div class=\"kf-sidebar-shell__brand\">\n <div class=\"kf-sidebar-shell__brand-full\">\n <ng-content select=\"[kf-sidebar-brand]\" />\n </div>\n <div class=\"kf-sidebar-shell__brand-collapsed\">\n <ng-content select=\"[kf-sidebar-brand-collapsed]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__mobile-close\"\n aria-label=\"Cerrar men\u00FA\"\n (click)=\"mobileOpen.set(false)\"\n >\n <kf-icon name=\"x\" size=\"md\" />\n </button>\n </div>\n\n <nav class=\"kf-sidebar-shell__nav\">\n @for (entry of itemsWithGroupHeader(); track entry.item.href) {\n @if (entry.showGroupLabel && !itemsCollapsed()) {\n <div class=\"kf-sidebar-shell__group-label\">{{ entry.item.groupLabel }}</div>\n }\n <kf-sidebar-nav-item\n [icon]=\"entry.item.icon\"\n [label]=\"entry.item.label\"\n [href]=\"entry.item.href\"\n [active]=\"!!entry.item.active\"\n [collapsed]=\"itemsCollapsed()\"\n (click)=\"onNavItemClick($event, entry.item)\"\n />\n }\n </nav>\n\n <div class=\"kf-sidebar-shell__bottom\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__collapse-toggle\"\n [class.kf-sidebar-shell__collapse-toggle--collapsed]=\"itemsCollapsed()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA'\"\n [kfTooltip]=\"itemsCollapsed() ? (collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA') : ''\"\n (click)=\"collapsed.set(!collapsed())\"\n >\n <kf-icon [name]=\"collapsed() ? 'chevron-right' : 'chevron-left'\" size=\"sm\" />\n @if (!itemsCollapsed()) {\n <span class=\"kf-sidebar-shell__collapse-toggle-label\">\n {{ collapsed() ? 'Expandir men\u00FA' : 'Colapsar men\u00FA' }}\n </span>\n }\n </button>\n\n <div class=\"kf-sidebar-shell__footer\">\n <ng-content select=\"[kf-sidebar-footer]\" />\n </div>\n </div>\n</aside>\n\n<div class=\"kf-sidebar-shell__topbar\">\n <button\n type=\"button\"\n class=\"kf-sidebar-shell__menu-toggle\"\n aria-label=\"Abrir men\u00FA de navegaci\u00F3n\"\n (click)=\"mobileOpen.set(true)\"\n >\n <kf-icon name=\"menu\" size=\"md\" />\n </button>\n <div class=\"kf-sidebar-shell__topbar-brand\">\n <ng-content select=\"[kf-sidebar-brand-mobile]\" />\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:contents}.kf-sidebar-shell__backdrop{display:none}.kf-sidebar-shell__rail{box-sizing:border-box;display:flex;flex-direction:column;position:sticky;top:0;height:100dvh;width:268px;flex:none;padding:var(--kf-space-lg) var(--kf-space-md);background:linear-gradient(190deg,var(--kf-color-sidebar-gradient-from) 0%,var(--kf-color-sidebar-gradient-to) 60%);transition:width .18s ease,padding-inline .18s ease}.kf-sidebar-shell__rail--collapsed{width:56px;padding-inline:var(--kf-space-sm)}.kf-sidebar-shell__brand{display:flex;align-items:center;justify-content:center;margin-bottom:var(--kf-space-xl)}.kf-sidebar-shell__brand-full{display:flex;justify-content:center;min-width:0}.kf-sidebar-shell__brand-full ::ng-deep img{display:block;height:1.5rem}.kf-sidebar-shell__brand-collapsed{display:none;justify-content:center;min-width:0}.kf-sidebar-shell__brand-collapsed ::ng-deep img{display:block;height:1.75rem}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-full{display:none}.kf-sidebar-shell__rail--collapsed .kf-sidebar-shell__brand-collapsed{display:flex}.kf-sidebar-shell__mobile-close{display:none;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;border-radius:var(--kf-radius-sm);background:#ffffff14;color:#fffc;cursor:pointer}.kf-sidebar-shell__mobile-close:hover{background:#ffffff29;color:var(--kf-color-white)}.kf-sidebar-shell__nav{flex:1 1 auto;display:flex;flex-direction:column;gap:var(--kf-space-xs);overflow-y:auto}.kf-sidebar-shell__group-label{margin-top:var(--kf-space-sm);padding:0 var(--kf-space-md);font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#fff6;white-space:nowrap;overflow:hidden}.kf-sidebar-shell__nav>.kf-sidebar-shell__group-label:first-child{margin-top:0}.kf-sidebar-shell__bottom{display:flex;flex-direction:column;margin-top:var(--kf-space-sm);padding-top:var(--kf-space-sm);border-top:1px solid rgba(255,255,255,.12)}.kf-sidebar-shell__footer{margin-top:var(--kf-space-sm)}.kf-sidebar-shell__footer:empty{display:none}.kf-sidebar-shell__collapse-toggle{box-sizing:border-box;display:flex;align-items:center;gap:var(--kf-space-sm);width:100%;padding:var(--kf-space-sm) var(--kf-space-md);border:none;border-radius:var(--kf-radius-sm);background:#ffffff0f;color:#ffffffb3;font-family:var(--kf-font-body);font-size:.8125rem;font-weight:600;cursor:pointer;transition:background .14s,color .14s}.kf-sidebar-shell__collapse-toggle:hover{background:#ffffff1f;color:var(--kf-color-white)}.kf-sidebar-shell__collapse-toggle--collapsed{justify-content:center;width:40px;height:40px;padding-inline:0}.kf-sidebar-shell__collapse-toggle-label{flex:1 1 auto;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-sidebar-shell__topbar{display:none}@media(max-width:900px){.kf-sidebar-shell__rail{position:fixed;inset:0 auto 0 0;z-index:100;width:284px;max-width:86vw;transform:translate(-100%);transition:transform .26s cubic-bezier(.4,0,.2,1),box-shadow .26s cubic-bezier(.4,0,.2,1);box-shadow:none}.kf-sidebar-shell__rail--mobile-open{transform:translate(0);box-shadow:var(--kf-shadow-lg)}.kf-sidebar-shell__rail--collapsed{width:284px;max-width:86vw;padding-inline:var(--kf-space-md)}.kf-sidebar-shell__brand{display:grid;grid-template-columns:1fr 2rem;align-items:center}.kf-sidebar-shell__brand-full{grid-column:1;justify-content:flex-start}.kf-sidebar-shell__mobile-close{grid-column:2;display:flex}.kf-sidebar-shell__collapse-toggle{display:none}.kf-sidebar-shell__backdrop{display:block;position:fixed;inset:0;z-index:90;border:none;padding:0;cursor:pointer;background:#0a0e1480}.kf-sidebar-shell__topbar{display:flex;align-items:center;gap:var(--kf-space-md);padding:var(--kf-space-sm) var(--kf-space-lg);background:var(--kf-color-white);border-bottom:1px solid var(--kf-color-border)}.kf-sidebar-shell__menu-toggle{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;border-radius:var(--kf-radius-sm);background:transparent;color:var(--kf-color-ink);cursor:pointer;flex:none}.kf-sidebar-shell__menu-toggle:hover{background:var(--kf-color-surface)}.kf-sidebar-shell__topbar-brand ::ng-deep img{display:block;height:1.25rem}}\n"] }]
9027
9122
  }], propDecorators: { navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], mobileOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileOpen", required: false }] }, { type: i0.Output, args: ["mobileOpenChange"] }], navItemClick: [{ type: i0.Output, args: ["navItemClick"] }], onEscape: [{
9028
9123
  type: HostListener,
9029
- args: ['document:keydown.escape']
9124
+ args: ['document:keydown.escape', ['$event']]
9030
9125
  }] } });
9031
9126
 
9032
9127
  const INTERACTIVE_CONTENT = 'a, button, input, select, textarea, label, [tabindex], ' +
@@ -9081,6 +9176,11 @@ class StatTile {
9081
9176
  /** Tercera línea bajo el valor. Vacía cae en `notePlaceholder`. */
9082
9177
  note = input(/* @ts-ignore */
9083
9178
  ...(ngDevMode ? [undefined, { debugName: "note" }] : /* istanbul ignore next */ []));
9179
+ /** Máximo de líneas visibles de la nota antes de la elipsis (`…`); el texto
9180
+ * completo sigue en el DOM y en el `title`. Default 2, como siempre. Un
9181
+ * valor menor a 1 o no numérico no limita la altura: la nota se muestra
9182
+ * entera. */
9183
+ noteLines = input(2, { ...(ngDevMode ? { debugName: "noteLines" } : /* istanbul ignore next */ {}), transform: numberAttribute });
9084
9184
  /** Qué dice la tercera línea cuando no hay nota. Cada consumidor debería
9085
9185
  * pasar el motivo real de SU dato ausente, no un texto genérico. */
9086
9186
  notePlaceholder = input(/* @ts-ignore */
@@ -9165,10 +9265,16 @@ class StatTile {
9165
9265
  this.tileClick.emit();
9166
9266
  }
9167
9267
  }
9268
+ /** Valor de `line-clamp`: entero ≥ 1, o `none` para mostrar la nota entera. */
9269
+ noteClamp = computed(() => {
9270
+ const lines = Math.floor(this.noteLines());
9271
+ return lines >= 1 ? String(lines) : 'none';
9272
+ }, /* @ts-ignore */
9273
+ ...(ngDevMode ? [{ debugName: "noteClamp" }] : /* istanbul ignore next */ []));
9168
9274
  noteIsPlaceholder = computed(() => !this.note() && !!this.notePlaceholder(), /* @ts-ignore */
9169
9275
  ...(ngDevMode ? [{ debugName: "noteIsPlaceholder" }] : /* istanbul ignore next */ []));
9170
9276
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
9171
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: StatTile, isStandalone: true, selector: "kf-stat-tile", inputs: { cta: { classPropertyName: "cta", publicName: "cta", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, notePlaceholder: { classPropertyName: "notePlaceholder", publicName: "notePlaceholder", isSignal: true, isRequired: false, transformFunction: null }, valueMissing: { classPropertyName: "valueMissing", publicName: "valueMissing", isSignal: true, isRequired: false, transformFunction: null }, hasProjectedValue: { classPropertyName: "hasProjectedValue", publicName: "hasProjectedValue", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, actionHref: { classPropertyName: "actionHref", publicName: "actionHref", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, pressed: { classPropertyName: "pressed", publicName: "pressed", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", tileClick: "tileClick" }, host: { listeners: { "click": "onActivate($event)", "keydown": "onKeydown($event)", "keyup": "onKeyup($event)" }, properties: { "class.kf-stat-tile--cta": "cta()", "class.kf-stat-tile--inline": "!cta() && variant() === \"inline\"", "class.kf-stat-tile--interactive": "isInteractive()", "attr.role": "isInteractive() ? \"button\" : null", "attr.tabindex": "isInteractive() ? 0 : null", "attr.aria-pressed": "isInteractive() ? pressed() : null", "attr.aria-expanded": "isInteractive() ? expanded() : null" } }, ngImport: i0, template: "@if (cta()) {\n <span class=\"kf-stat-tile__cta-title\">{{ title() }}</span>\n @if (description()) {\n <span class=\"kf-stat-tile__cta-description\">{{ description() }}</span>\n }\n @if (actionLabel()) {\n <kf-link\n class=\"kf-stat-tile__cta-action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n} @else {\n <div class=\"kf-stat-tile__head\">\n <!-- El label recibe la clase de tone adem\u00E1s del value: juntos forman\n una sola unidad de lectura, y pintar solo el n\u00FAmero la romper\u00EDa. -->\n <span\n class=\"kf-stat-tile__label\"\n [class.kf-stat-tile__label--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__label--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__label--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__label--info]=\"tone() === 'info'\"\n >{{ label() }}</span\n >\n @if (icon(); as iconName) {\n <span class=\"kf-stat-tile__icon\">\n <kf-icon [name]=\"iconName\" size=\"sm\" />\n </span>\n }\n </div>\n @if (hasProjectedValue()) {\n <!-- Slot para un valor que no es texto medido (ej. un `kf-badge` de\n estado) \u2014 mismo bloque `__value`, sin las clases de tono, que en ese\n caso las resuelve el propio contenido proyectado (el badge trae su\n tono). -->\n <span class=\"kf-stat-tile__value kf-stat-tile__value--projected\">\n <ng-content select=\"[valueContent]\" />\n </span>\n } @else {\n <span\n class=\"kf-stat-tile__value\"\n [class.kf-stat-tile__value--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__value--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__value--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__value--info]=\"tone() === 'info'\"\n [class.kf-stat-tile__value--missing]=\"valueMissing()\"\n >{{ value() }}</span\n >\n }\n\n <!-- La l\u00EDnea se reserva con o sin nota: un tile m\u00E1s corto desalinea la\n fila. El `title` deja disponible el texto completo, recortado a 2 l\u00EDneas. -->\n @if (noteText(); as note) {\n <span\n class=\"kf-stat-tile__note\"\n [class.kf-stat-tile__note--empty]=\"noteIsPlaceholder()\"\n [title]=\"note\"\n >{{ note }}</span\n >\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);padding:var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);height:100%;min-width:0}:host(.kf-stat-tile--cta){background:var(--kf-color-surface);gap:2px}:host(.kf-stat-tile--inline){flex-direction:row-reverse;align-items:baseline;height:auto;gap:6px;padding:0;border:none;border-radius:0;background:transparent}:host(.kf-stat-tile--inline) .kf-stat-tile__head{width:auto}.kf-stat-tile__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-xs)}.kf-stat-tile__label{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__icon{display:inline-flex;color:var(--kf-color-primary)}.kf-stat-tile__value{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__value--projected{display:flex;align-items:center;font-size:initial;font-weight:initial;color:initial}.kf-stat-tile__value--ok,.kf-stat-tile__label--ok{color:var(--kf-color-success-strong)}.kf-stat-tile__value--warn,.kf-stat-tile__label--warn{color:var(--kf-color-warning-strong)}.kf-stat-tile__value--error,.kf-stat-tile__label--error{color:var(--kf-color-error-strong)}.kf-stat-tile__value--info,.kf-stat-tile__label--info{color:var(--kf-color-info-strong)}.kf-stat-tile__value--missing{font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);font-style:italic;color:var(--kf-color-text-muted)}.kf-stat-tile__note{display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:var(--kf-font-size-caption);color:var(--kf-color-text-muted);margin-top:auto}.kf-stat-tile__note--empty{font-style:italic;opacity:.75}.kf-stat-tile__cta-title{font-family:var(--kf-font-title);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__cta-description{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:var(--kf-font-size-label);font-weight:600}:host(.kf-stat-tile--interactive){cursor:pointer;text-align:start;transition:border-color .14s,background-color .14s,box-shadow .14s}@media(hover:hover){:host(.kf-stat-tile--interactive:hover){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}}:host(.kf-stat-tile--interactive[aria-pressed=\"true\"]){border-color:var(--kf-color-primary);box-shadow:var(--kf-stat-tile-ring)}:host(.kf-stat-tile--interactive:focus-visible){outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){:host(.kf-stat-tile--interactive){transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: Link, selector: "kf-link", inputs: ["variant", "disabled", "href", "showArrow"] }] });
9277
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: StatTile, isStandalone: true, selector: "kf-stat-tile", inputs: { cta: { classPropertyName: "cta", publicName: "cta", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, noteLines: { classPropertyName: "noteLines", publicName: "noteLines", isSignal: true, isRequired: false, transformFunction: null }, notePlaceholder: { classPropertyName: "notePlaceholder", publicName: "notePlaceholder", isSignal: true, isRequired: false, transformFunction: null }, valueMissing: { classPropertyName: "valueMissing", publicName: "valueMissing", isSignal: true, isRequired: false, transformFunction: null }, hasProjectedValue: { classPropertyName: "hasProjectedValue", publicName: "hasProjectedValue", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, actionHref: { classPropertyName: "actionHref", publicName: "actionHref", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, pressed: { classPropertyName: "pressed", publicName: "pressed", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", tileClick: "tileClick" }, host: { listeners: { "click": "onActivate($event)", "keydown": "onKeydown($event)", "keyup": "onKeyup($event)" }, properties: { "class.kf-stat-tile--cta": "cta()", "class.kf-stat-tile--inline": "!cta() && variant() === \"inline\"", "class.kf-stat-tile--interactive": "isInteractive()", "attr.role": "isInteractive() ? \"button\" : null", "attr.tabindex": "isInteractive() ? 0 : null", "attr.aria-pressed": "isInteractive() ? pressed() : null", "attr.aria-expanded": "isInteractive() ? expanded() : null" } }, ngImport: i0, template: "@if (cta()) {\n <span class=\"kf-stat-tile__cta-title\">{{ title() }}</span>\n @if (description()) {\n <span class=\"kf-stat-tile__cta-description\">{{ description() }}</span>\n }\n @if (actionLabel()) {\n <kf-link\n class=\"kf-stat-tile__cta-action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n} @else {\n <div class=\"kf-stat-tile__head\">\n <!-- El label recibe la clase de tone adem\u00E1s del value: juntos forman\n una sola unidad de lectura, y pintar solo el n\u00FAmero la romper\u00EDa. -->\n <span\n class=\"kf-stat-tile__label\"\n [class.kf-stat-tile__label--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__label--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__label--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__label--info]=\"tone() === 'info'\"\n >{{ label() }}</span\n >\n @if (icon(); as iconName) {\n <span class=\"kf-stat-tile__icon\">\n <kf-icon [name]=\"iconName\" size=\"sm\" />\n </span>\n }\n </div>\n @if (hasProjectedValue()) {\n <!-- Slot para un valor que no es texto medido (ej. un `kf-badge` de\n estado) \u2014 mismo bloque `__value`, sin las clases de tono, que en ese\n caso las resuelve el propio contenido proyectado (el badge trae su\n tono). -->\n <span class=\"kf-stat-tile__value kf-stat-tile__value--projected\">\n <ng-content select=\"[valueContent]\" />\n </span>\n } @else {\n <span\n class=\"kf-stat-tile__value\"\n [class.kf-stat-tile__value--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__value--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__value--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__value--info]=\"tone() === 'info'\"\n [class.kf-stat-tile__value--missing]=\"valueMissing()\"\n >{{ value() }}</span\n >\n }\n\n <!-- La l\u00EDnea se reserva con o sin nota: un tile m\u00E1s corto desalinea la\n fila. El `title` deja disponible el texto completo, recortado a `noteLines`\n l\u00EDneas (2 por defecto). -->\n @if (noteText(); as note) {\n <span\n class=\"kf-stat-tile__note\"\n [class.kf-stat-tile__note--empty]=\"noteIsPlaceholder()\"\n [style.--kf-stat-tile-note-lines]=\"noteClamp()\"\n [title]=\"note\"\n >{{ note }}</span\n >\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);padding:var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);height:100%;min-width:0}:host(.kf-stat-tile--cta){background:var(--kf-color-surface);gap:2px}:host(.kf-stat-tile--inline){flex-direction:row-reverse;align-items:baseline;height:auto;gap:6px;padding:0;border:none;border-radius:0;background:transparent}:host(.kf-stat-tile--inline) .kf-stat-tile__head{width:auto}.kf-stat-tile__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-xs)}.kf-stat-tile__label{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__icon{display:inline-flex;color:var(--kf-color-primary)}.kf-stat-tile__value{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__value--projected{display:flex;align-items:center;font-size:initial;font-weight:initial;color:initial}.kf-stat-tile__value--ok,.kf-stat-tile__label--ok{color:var(--kf-color-success-strong)}.kf-stat-tile__value--warn,.kf-stat-tile__label--warn{color:var(--kf-color-warning-strong)}.kf-stat-tile__value--error,.kf-stat-tile__label--error{color:var(--kf-color-error-strong)}.kf-stat-tile__value--info,.kf-stat-tile__label--info{color:var(--kf-color-info-strong)}.kf-stat-tile__value--missing{font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);font-style:italic;color:var(--kf-color-text-muted)}.kf-stat-tile__note{display:-webkit-box;-webkit-line-clamp:var(--kf-stat-tile-note-lines, 2);line-clamp:var(--kf-stat-tile-note-lines, 2);-webkit-box-orient:vertical;overflow:hidden;font-size:var(--kf-font-size-caption);color:var(--kf-color-text-muted);margin-top:auto}.kf-stat-tile__note--empty{font-style:italic;opacity:.75}.kf-stat-tile__cta-title{font-family:var(--kf-font-title);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__cta-description{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:var(--kf-font-size-label);font-weight:600}:host(.kf-stat-tile--interactive){cursor:pointer;text-align:start;transition:border-color .14s,background-color .14s,box-shadow .14s}@media(hover:hover){:host(.kf-stat-tile--interactive:hover){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}}:host(.kf-stat-tile--interactive[aria-pressed=\"true\"]){border-color:var(--kf-color-primary);box-shadow:var(--kf-stat-tile-ring)}:host(.kf-stat-tile--interactive:focus-visible){outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){:host(.kf-stat-tile--interactive){transition:none}}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }, { kind: "component", type: Link, selector: "kf-link", inputs: ["variant", "disabled", "href", "showArrow"] }] });
9172
9278
  }
9173
9279
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatTile, decorators: [{
9174
9280
  type: Component,
@@ -9183,8 +9289,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
9183
9289
  '(click)': 'onActivate($event)',
9184
9290
  '(keydown)': 'onKeydown($event)',
9185
9291
  '(keyup)': 'onKeyup($event)',
9186
- }, template: "@if (cta()) {\n <span class=\"kf-stat-tile__cta-title\">{{ title() }}</span>\n @if (description()) {\n <span class=\"kf-stat-tile__cta-description\">{{ description() }}</span>\n }\n @if (actionLabel()) {\n <kf-link\n class=\"kf-stat-tile__cta-action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n} @else {\n <div class=\"kf-stat-tile__head\">\n <!-- El label recibe la clase de tone adem\u00E1s del value: juntos forman\n una sola unidad de lectura, y pintar solo el n\u00FAmero la romper\u00EDa. -->\n <span\n class=\"kf-stat-tile__label\"\n [class.kf-stat-tile__label--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__label--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__label--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__label--info]=\"tone() === 'info'\"\n >{{ label() }}</span\n >\n @if (icon(); as iconName) {\n <span class=\"kf-stat-tile__icon\">\n <kf-icon [name]=\"iconName\" size=\"sm\" />\n </span>\n }\n </div>\n @if (hasProjectedValue()) {\n <!-- Slot para un valor que no es texto medido (ej. un `kf-badge` de\n estado) \u2014 mismo bloque `__value`, sin las clases de tono, que en ese\n caso las resuelve el propio contenido proyectado (el badge trae su\n tono). -->\n <span class=\"kf-stat-tile__value kf-stat-tile__value--projected\">\n <ng-content select=\"[valueContent]\" />\n </span>\n } @else {\n <span\n class=\"kf-stat-tile__value\"\n [class.kf-stat-tile__value--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__value--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__value--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__value--info]=\"tone() === 'info'\"\n [class.kf-stat-tile__value--missing]=\"valueMissing()\"\n >{{ value() }}</span\n >\n }\n\n <!-- La l\u00EDnea se reserva con o sin nota: un tile m\u00E1s corto desalinea la\n fila. El `title` deja disponible el texto completo, recortado a 2 l\u00EDneas. -->\n @if (noteText(); as note) {\n <span\n class=\"kf-stat-tile__note\"\n [class.kf-stat-tile__note--empty]=\"noteIsPlaceholder()\"\n [title]=\"note\"\n >{{ note }}</span\n >\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);padding:var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);height:100%;min-width:0}:host(.kf-stat-tile--cta){background:var(--kf-color-surface);gap:2px}:host(.kf-stat-tile--inline){flex-direction:row-reverse;align-items:baseline;height:auto;gap:6px;padding:0;border:none;border-radius:0;background:transparent}:host(.kf-stat-tile--inline) .kf-stat-tile__head{width:auto}.kf-stat-tile__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-xs)}.kf-stat-tile__label{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__icon{display:inline-flex;color:var(--kf-color-primary)}.kf-stat-tile__value{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__value--projected{display:flex;align-items:center;font-size:initial;font-weight:initial;color:initial}.kf-stat-tile__value--ok,.kf-stat-tile__label--ok{color:var(--kf-color-success-strong)}.kf-stat-tile__value--warn,.kf-stat-tile__label--warn{color:var(--kf-color-warning-strong)}.kf-stat-tile__value--error,.kf-stat-tile__label--error{color:var(--kf-color-error-strong)}.kf-stat-tile__value--info,.kf-stat-tile__label--info{color:var(--kf-color-info-strong)}.kf-stat-tile__value--missing{font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);font-style:italic;color:var(--kf-color-text-muted)}.kf-stat-tile__note{display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:var(--kf-font-size-caption);color:var(--kf-color-text-muted);margin-top:auto}.kf-stat-tile__note--empty{font-style:italic;opacity:.75}.kf-stat-tile__cta-title{font-family:var(--kf-font-title);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__cta-description{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:var(--kf-font-size-label);font-weight:600}:host(.kf-stat-tile--interactive){cursor:pointer;text-align:start;transition:border-color .14s,background-color .14s,box-shadow .14s}@media(hover:hover){:host(.kf-stat-tile--interactive:hover){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}}:host(.kf-stat-tile--interactive[aria-pressed=\"true\"]){border-color:var(--kf-color-primary);box-shadow:var(--kf-stat-tile-ring)}:host(.kf-stat-tile--interactive:focus-visible){outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){:host(.kf-stat-tile--interactive){transition:none}}\n"] }]
9187
- }], propDecorators: { cta: [{ type: i0.Input, args: [{ isSignal: true, alias: "cta", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], notePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "notePlaceholder", required: false }] }], valueMissing: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueMissing", required: false }] }], hasProjectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasProjectedValue", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], actionHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionHref", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], tileClick: [{ type: i0.Output, args: ["tileClick"] }] } });
9292
+ }, template: "@if (cta()) {\n <span class=\"kf-stat-tile__cta-title\">{{ title() }}</span>\n @if (description()) {\n <span class=\"kf-stat-tile__cta-description\">{{ description() }}</span>\n }\n @if (actionLabel()) {\n <kf-link\n class=\"kf-stat-tile__cta-action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n} @else {\n <div class=\"kf-stat-tile__head\">\n <!-- El label recibe la clase de tone adem\u00E1s del value: juntos forman\n una sola unidad de lectura, y pintar solo el n\u00FAmero la romper\u00EDa. -->\n <span\n class=\"kf-stat-tile__label\"\n [class.kf-stat-tile__label--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__label--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__label--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__label--info]=\"tone() === 'info'\"\n >{{ label() }}</span\n >\n @if (icon(); as iconName) {\n <span class=\"kf-stat-tile__icon\">\n <kf-icon [name]=\"iconName\" size=\"sm\" />\n </span>\n }\n </div>\n @if (hasProjectedValue()) {\n <!-- Slot para un valor que no es texto medido (ej. un `kf-badge` de\n estado) \u2014 mismo bloque `__value`, sin las clases de tono, que en ese\n caso las resuelve el propio contenido proyectado (el badge trae su\n tono). -->\n <span class=\"kf-stat-tile__value kf-stat-tile__value--projected\">\n <ng-content select=\"[valueContent]\" />\n </span>\n } @else {\n <span\n class=\"kf-stat-tile__value\"\n [class.kf-stat-tile__value--ok]=\"tone() === 'ok'\"\n [class.kf-stat-tile__value--warn]=\"tone() === 'warn'\"\n [class.kf-stat-tile__value--error]=\"tone() === 'error'\"\n [class.kf-stat-tile__value--info]=\"tone() === 'info'\"\n [class.kf-stat-tile__value--missing]=\"valueMissing()\"\n >{{ value() }}</span\n >\n }\n\n <!-- La l\u00EDnea se reserva con o sin nota: un tile m\u00E1s corto desalinea la\n fila. El `title` deja disponible el texto completo, recortado a `noteLines`\n l\u00EDneas (2 por defecto). -->\n @if (noteText(); as note) {\n <span\n class=\"kf-stat-tile__note\"\n [class.kf-stat-tile__note--empty]=\"noteIsPlaceholder()\"\n [style.--kf-stat-tile-note-lines]=\"noteClamp()\"\n [title]=\"note\"\n >{{ note }}</span\n >\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);padding:var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);height:100%;min-width:0}:host(.kf-stat-tile--cta){background:var(--kf-color-surface);gap:2px}:host(.kf-stat-tile--inline){flex-direction:row-reverse;align-items:baseline;height:auto;gap:6px;padding:0;border:none;border-radius:0;background:transparent}:host(.kf-stat-tile--inline) .kf-stat-tile__head{width:auto}.kf-stat-tile__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-xs)}.kf-stat-tile__label{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__icon{display:inline-flex;color:var(--kf-color-primary)}.kf-stat-tile__value{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__value--projected{display:flex;align-items:center;font-size:initial;font-weight:initial;color:initial}.kf-stat-tile__value--ok,.kf-stat-tile__label--ok{color:var(--kf-color-success-strong)}.kf-stat-tile__value--warn,.kf-stat-tile__label--warn{color:var(--kf-color-warning-strong)}.kf-stat-tile__value--error,.kf-stat-tile__label--error{color:var(--kf-color-error-strong)}.kf-stat-tile__value--info,.kf-stat-tile__label--info{color:var(--kf-color-info-strong)}.kf-stat-tile__value--missing{font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);font-style:italic;color:var(--kf-color-text-muted)}.kf-stat-tile__note{display:-webkit-box;-webkit-line-clamp:var(--kf-stat-tile-note-lines, 2);line-clamp:var(--kf-stat-tile-note-lines, 2);-webkit-box-orient:vertical;overflow:hidden;font-size:var(--kf-font-size-caption);color:var(--kf-color-text-muted);margin-top:auto}.kf-stat-tile__note--empty{font-style:italic;opacity:.75}.kf-stat-tile__cta-title{font-family:var(--kf-font-title);font-weight:700;color:var(--kf-color-ink)}.kf-stat-tile__cta-description{font-size:var(--kf-font-size-label);color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:var(--kf-font-size-label);font-weight:600}:host(.kf-stat-tile--interactive){cursor:pointer;text-align:start;transition:border-color .14s,background-color .14s,box-shadow .14s}@media(hover:hover){:host(.kf-stat-tile--interactive:hover){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}}:host(.kf-stat-tile--interactive[aria-pressed=\"true\"]){border-color:var(--kf-color-primary);box-shadow:var(--kf-stat-tile-ring)}:host(.kf-stat-tile--interactive:focus-visible){outline:none;box-shadow:var(--kf-shadow-focus)}@media(prefers-reduced-motion:reduce){:host(.kf-stat-tile--interactive){transition:none}}\n"] }]
9293
+ }], propDecorators: { cta: [{ type: i0.Input, args: [{ isSignal: true, alias: "cta", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], noteLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "noteLines", required: false }] }], notePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "notePlaceholder", required: false }] }], valueMissing: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueMissing", required: false }] }], hasProjectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasProjectedValue", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], actionHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionHref", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], pressed: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressed", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], tileClick: [{ type: i0.Output, args: ["tileClick"] }] } });
9188
9294
 
9189
9295
  /**
9190
9296
  * Pill con borde, en mayúsculas y con letter-spacing, pensada para indicadores
@@ -9230,12 +9336,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
9230
9336
  * switch hace que el valor llegue dos veces al consumidor: usar una sola de
9231
9337
  * las dos vías, o ignorar en el handler el eco que no cambia el valor.
9232
9338
  *
9339
+ * `describedBy` recibe el `id` de un texto de ayuda externo (ej. el `<p>` de
9340
+ * una fila de preferencias) y lo enlaza con `aria-describedby` del botón, para
9341
+ * que el lector de pantalla lo anuncie junto al nombre y el estado. Sin valor,
9342
+ * el atributo no se renderiza.
9343
+ *
9233
9344
  * El color sale de roles (`--kf-color-primary` encendido,
9234
9345
  * `--kf-color-border-control` apagado) y el foco de `--kf-shadow-focus`; no
9235
9346
  * recibe colores.
9236
9347
  *
9237
9348
  * <kf-switch label="Fijar indicadores" [(checked)]="pinned" />
9238
9349
  * <kf-switch label="Mapa junto a la tabla" hideLabel size="sm" formControlName="splitMap" />
9350
+ * <kf-switch label="Alertas por correo" describedBy="mail-hint" [(checked)]="mail" />
9351
+ * <p id="mail-hint">Se envía un resumen cada hora.</p>
9239
9352
  */
9240
9353
  class Switch {
9241
9354
  /** Nombre accesible y texto visible (salvo con `hideLabel`). */
@@ -9246,6 +9359,9 @@ class Switch {
9246
9359
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9247
9360
  size = input('md', /* @ts-ignore */
9248
9361
  ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
9362
+ /** `id` del texto de ayuda que describe al interruptor (`aria-describedby`). */
9363
+ describedBy = input(null, /* @ts-ignore */
9364
+ ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
9249
9365
  /** Estado encendido, two-way: `[(checked)]="pinned"`. */
9250
9366
  checked = model(false, /* @ts-ignore */
9251
9367
  ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
@@ -9279,13 +9395,13 @@ class Switch {
9279
9395
  this.disabledByForm.set(isDisabled);
9280
9396
  }
9281
9397
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Switch, deps: [], target: i0.ɵɵFactoryTarget.Component });
9282
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Switch, isStandalone: true, selector: "kf-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, providers: [
9398
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Switch, isStandalone: true, selector: "kf-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, describedBy: { classPropertyName: "describedBy", publicName: "describedBy", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, providers: [
9283
9399
  {
9284
9400
  provide: NG_VALUE_ACCESSOR,
9285
9401
  useExisting: forwardRef(() => Switch),
9286
9402
  multi: true,
9287
9403
  },
9288
- ], ngImport: i0, template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"kf-switch\"\n [class.kf-switch--sm]=\"size() === 'sm'\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"hideLabel() ? label() : null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (blur)=\"onBlur()\"\n>\n <span class=\"kf-switch__track\" aria-hidden=\"true\">\n <span class=\"kf-switch__thumb\"></span>\n </span>\n @if (!hideLabel()) {\n <span class=\"kf-switch__label\">{{ label() }}</span>\n }\n</button>\n", styles: [":host{display:inline-flex}.kf-switch{--kf-switch-track-width: 36px;--kf-switch-track-height: 20px;--kf-switch-thumb-size: 16px;--kf-switch-gap: 2px;display:inline-flex;align-items:center;gap:var(--kf-space-sm);margin:0;padding:0;border:none;background:transparent;font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);color:var(--kf-color-text);text-align:start;cursor:pointer}.kf-switch--sm{--kf-switch-track-width: 28px;--kf-switch-track-height: 16px;--kf-switch-thumb-size: 12px;font-size:var(--kf-font-size-body-sm)}.kf-switch__track{position:relative;flex:none;box-sizing:border-box;width:var(--kf-switch-track-width);height:var(--kf-switch-track-height);border-radius:var(--kf-radius-pill);background:var(--kf-color-border-control);transition:background-color .14s}.kf-switch__thumb{position:absolute;top:var(--kf-switch-gap);left:var(--kf-switch-gap);width:var(--kf-switch-thumb-size);height:var(--kf-switch-thumb-size);border-radius:var(--kf-radius-pill);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);transition:transform .14s}.kf-switch[aria-checked=true] .kf-switch__track{background:var(--kf-color-primary)}.kf-switch[aria-checked=true] .kf-switch__thumb{transform:translate(calc(var(--kf-switch-track-width) - var(--kf-switch-thumb-size) - 2 * var(--kf-switch-gap)))}.kf-switch:focus-visible{outline:none}.kf-switch:focus-visible .kf-switch__track{box-shadow:var(--kf-shadow-focus)}.kf-switch:disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-switch:disabled .kf-switch__track{opacity:.5}.kf-switch__label{-webkit-user-select:none;user-select:none}@media(prefers-reduced-motion:reduce){.kf-switch__track,.kf-switch__thumb{transition:none}}@media(forced-colors:active){.kf-switch__track{background:ButtonText}.kf-switch[aria-checked=true] .kf-switch__track{background:Highlight}.kf-switch__thumb{background:ButtonFace;border:1px solid ButtonText}}\n"] });
9404
+ ], ngImport: i0, template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"kf-switch\"\n [class.kf-switch--sm]=\"size() === 'sm'\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"hideLabel() ? label() : null\"\n [attr.aria-describedby]=\"describedBy() || null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (blur)=\"onBlur()\"\n>\n <span class=\"kf-switch__track\" aria-hidden=\"true\">\n <span class=\"kf-switch__thumb\"></span>\n </span>\n @if (!hideLabel()) {\n <span class=\"kf-switch__label\">{{ label() }}</span>\n }\n</button>\n", styles: [":host{display:inline-flex}.kf-switch{--kf-switch-track-width: 36px;--kf-switch-track-height: 20px;--kf-switch-thumb-size: 16px;--kf-switch-gap: 2px;display:inline-flex;align-items:center;gap:var(--kf-space-sm);margin:0;padding:0;border:none;background:transparent;font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);color:var(--kf-color-text);text-align:start;cursor:pointer}.kf-switch--sm{--kf-switch-track-width: 28px;--kf-switch-track-height: 16px;--kf-switch-thumb-size: 12px;font-size:var(--kf-font-size-body-sm)}.kf-switch__track{position:relative;flex:none;box-sizing:border-box;width:var(--kf-switch-track-width);height:var(--kf-switch-track-height);border-radius:var(--kf-radius-pill);background:var(--kf-color-border-control);transition:background-color .14s}.kf-switch__thumb{position:absolute;top:var(--kf-switch-gap);left:var(--kf-switch-gap);width:var(--kf-switch-thumb-size);height:var(--kf-switch-thumb-size);border-radius:var(--kf-radius-pill);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);transition:transform .14s}.kf-switch[aria-checked=true] .kf-switch__track{background:var(--kf-color-primary)}.kf-switch[aria-checked=true] .kf-switch__thumb{transform:translate(calc(var(--kf-switch-track-width) - var(--kf-switch-thumb-size) - 2 * var(--kf-switch-gap)))}.kf-switch:focus-visible{outline:none}.kf-switch:focus-visible .kf-switch__track{box-shadow:var(--kf-shadow-focus)}.kf-switch:disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-switch:disabled .kf-switch__track{opacity:.5}.kf-switch__label{-webkit-user-select:none;user-select:none}@media(prefers-reduced-motion:reduce){.kf-switch__track,.kf-switch__thumb{transition:none}}@media(forced-colors:active){.kf-switch__track{background:ButtonText}.kf-switch[aria-checked=true] .kf-switch__track{background:Highlight}.kf-switch__thumb{background:ButtonFace;border:1px solid ButtonText}}\n"] });
9289
9405
  }
9290
9406
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Switch, decorators: [{
9291
9407
  type: Component,
@@ -9295,8 +9411,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
9295
9411
  useExisting: forwardRef(() => Switch),
9296
9412
  multi: true,
9297
9413
  },
9298
- ], template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"kf-switch\"\n [class.kf-switch--sm]=\"size() === 'sm'\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"hideLabel() ? label() : null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (blur)=\"onBlur()\"\n>\n <span class=\"kf-switch__track\" aria-hidden=\"true\">\n <span class=\"kf-switch__thumb\"></span>\n </span>\n @if (!hideLabel()) {\n <span class=\"kf-switch__label\">{{ label() }}</span>\n }\n</button>\n", styles: [":host{display:inline-flex}.kf-switch{--kf-switch-track-width: 36px;--kf-switch-track-height: 20px;--kf-switch-thumb-size: 16px;--kf-switch-gap: 2px;display:inline-flex;align-items:center;gap:var(--kf-space-sm);margin:0;padding:0;border:none;background:transparent;font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);color:var(--kf-color-text);text-align:start;cursor:pointer}.kf-switch--sm{--kf-switch-track-width: 28px;--kf-switch-track-height: 16px;--kf-switch-thumb-size: 12px;font-size:var(--kf-font-size-body-sm)}.kf-switch__track{position:relative;flex:none;box-sizing:border-box;width:var(--kf-switch-track-width);height:var(--kf-switch-track-height);border-radius:var(--kf-radius-pill);background:var(--kf-color-border-control);transition:background-color .14s}.kf-switch__thumb{position:absolute;top:var(--kf-switch-gap);left:var(--kf-switch-gap);width:var(--kf-switch-thumb-size);height:var(--kf-switch-thumb-size);border-radius:var(--kf-radius-pill);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);transition:transform .14s}.kf-switch[aria-checked=true] .kf-switch__track{background:var(--kf-color-primary)}.kf-switch[aria-checked=true] .kf-switch__thumb{transform:translate(calc(var(--kf-switch-track-width) - var(--kf-switch-thumb-size) - 2 * var(--kf-switch-gap)))}.kf-switch:focus-visible{outline:none}.kf-switch:focus-visible .kf-switch__track{box-shadow:var(--kf-shadow-focus)}.kf-switch:disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-switch:disabled .kf-switch__track{opacity:.5}.kf-switch__label{-webkit-user-select:none;user-select:none}@media(prefers-reduced-motion:reduce){.kf-switch__track,.kf-switch__thumb{transition:none}}@media(forced-colors:active){.kf-switch__track{background:ButtonText}.kf-switch[aria-checked=true] .kf-switch__track{background:Highlight}.kf-switch__thumb{background:ButtonFace;border:1px solid ButtonText}}\n"] }]
9299
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }] } });
9414
+ ], template: "<button\n type=\"button\"\n role=\"switch\"\n class=\"kf-switch\"\n [class.kf-switch--sm]=\"size() === 'sm'\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"hideLabel() ? label() : null\"\n [attr.aria-describedby]=\"describedBy() || null\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n (blur)=\"onBlur()\"\n>\n <span class=\"kf-switch__track\" aria-hidden=\"true\">\n <span class=\"kf-switch__thumb\"></span>\n </span>\n @if (!hideLabel()) {\n <span class=\"kf-switch__label\">{{ label() }}</span>\n }\n</button>\n", styles: [":host{display:inline-flex}.kf-switch{--kf-switch-track-width: 36px;--kf-switch-track-height: 20px;--kf-switch-thumb-size: 16px;--kf-switch-gap: 2px;display:inline-flex;align-items:center;gap:var(--kf-space-sm);margin:0;padding:0;border:none;background:transparent;font-family:var(--kf-font-body);font-size:var(--kf-font-size-body);color:var(--kf-color-text);text-align:start;cursor:pointer}.kf-switch--sm{--kf-switch-track-width: 28px;--kf-switch-track-height: 16px;--kf-switch-thumb-size: 12px;font-size:var(--kf-font-size-body-sm)}.kf-switch__track{position:relative;flex:none;box-sizing:border-box;width:var(--kf-switch-track-width);height:var(--kf-switch-track-height);border-radius:var(--kf-radius-pill);background:var(--kf-color-border-control);transition:background-color .14s}.kf-switch__thumb{position:absolute;top:var(--kf-switch-gap);left:var(--kf-switch-gap);width:var(--kf-switch-thumb-size);height:var(--kf-switch-thumb-size);border-radius:var(--kf-radius-pill);background:var(--kf-color-white);box-shadow:var(--kf-shadow-xs);transition:transform .14s}.kf-switch[aria-checked=true] .kf-switch__track{background:var(--kf-color-primary)}.kf-switch[aria-checked=true] .kf-switch__thumb{transform:translate(calc(var(--kf-switch-track-width) - var(--kf-switch-thumb-size) - 2 * var(--kf-switch-gap)))}.kf-switch:focus-visible{outline:none}.kf-switch:focus-visible .kf-switch__track{box-shadow:var(--kf-shadow-focus)}.kf-switch:disabled{cursor:not-allowed;color:var(--kf-color-text-muted)}.kf-switch:disabled .kf-switch__track{opacity:.5}.kf-switch__label{-webkit-user-select:none;user-select:none}@media(prefers-reduced-motion:reduce){.kf-switch__track,.kf-switch__thumb{transition:none}}@media(forced-colors:active){.kf-switch__track{background:ButtonText}.kf-switch[aria-checked=true] .kf-switch__track{background:Highlight}.kf-switch__thumb{background:ButtonFace;border:1px solid ButtonText}}\n"] }]
9415
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], describedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "describedBy", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }] } });
9300
9416
 
9301
9417
  /**
9302
9418
  * Barra de tabs subrayada: un indicador se desliza hasta la pestaña activa.
@@ -9428,6 +9544,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
9428
9544
  *
9429
9545
  * <kf-textarea label="Detalle" formControlName="detail" [maxRows]="12" />
9430
9546
  *
9547
+ * `maxlength` limita el texto (`maxlength` nativo, entero positivo) y
9548
+ * `showCounter` agrega el contador «0 / 500» pegado bajo el campo, en la misma
9549
+ * fila que el `hint`/`errorMessage`. Ambos son opt-in: sin ellos el campo no
9550
+ * cambia. El contador sin `maxlength` no se muestra (no hay tope que contar).
9551
+ * Visualmente pasa a rojo al llegar al tope; para lectores de pantalla solo
9552
+ * anuncia (`aria-live="polite"`) al cruzar el 90 % y al llegar al límite, no
9553
+ * en cada tecla.
9554
+ *
9555
+ * <kf-textarea label="Motivo" formControlName="reason" [maxlength]="500" showCounter />
9556
+ *
9431
9557
  * `invalid` + `errorMessage` y `readonly`/`disabled` siguen el mismo
9432
9558
  * contrato que `kf-input` — ver su JSDoc para la diferencia entre ambos
9433
9559
  * estados.
@@ -9461,9 +9587,14 @@ class Textarea {
9461
9587
  /** Filas máximas antes de que el contenido pase a scroll interno en vez de seguir creciendo. */
9462
9588
  maxRows = input(6, /* @ts-ignore */
9463
9589
  ...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
9590
+ /** Largo máximo del texto (`maxlength` nativo), entero positivo. */
9591
+ maxlength = input(null, { ...(ngDevMode ? { debugName: "maxlength" } : /* istanbul ignore next */ {}), transform: toMaxLength });
9592
+ /** Muestra el contador «n / maxlength» bajo el campo. Requiere `maxlength`. */
9593
+ showCounter = input(false, { ...(ngDevMode ? { debugName: "showCounter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9464
9594
  textareaId = `kf-textarea-${Textarea.nextId++}`;
9465
9595
  hintId = `${this.textareaId}-hint`;
9466
9596
  errorId = `${this.textareaId}-error`;
9597
+ counterId = `${this.textareaId}-counter`;
9467
9598
  value = signal('', /* @ts-ignore */
9468
9599
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
9469
9600
  focused = signal(false, /* @ts-ignore */
@@ -9474,6 +9605,38 @@ class Textarea {
9474
9605
  /** Disabled real: por input() directo o por el FormControl asociado. */
9475
9606
  isDisabled = computed(() => this.disabled() || this.disabledByForm(), /* @ts-ignore */
9476
9607
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
9608
+ counterVisible = computed(() => this.showCounter() && this.maxlength() !== null, /* @ts-ignore */
9609
+ ...(ngDevMode ? [{ debugName: "counterVisible" }] : /* istanbul ignore next */ []));
9610
+ atLimit = computed(() => {
9611
+ const max = this.maxlength();
9612
+ return max !== null && this.value().length >= max;
9613
+ }, /* @ts-ignore */
9614
+ ...(ngDevMode ? [{ debugName: "atLimit" }] : /* istanbul ignore next */ []));
9615
+ /**
9616
+ * Texto del `aria-live`: cambia solo al cruzar un umbral (90 % y tope), así
9617
+ * el lector no lee cada carácter escrito cerca del límite.
9618
+ */
9619
+ counterAnnouncement = computed(() => {
9620
+ const max = this.maxlength();
9621
+ if (max === null) {
9622
+ return '';
9623
+ }
9624
+ const length = this.value().length;
9625
+ if (length >= max) {
9626
+ return `Límite de ${max} caracteres alcanzado.`;
9627
+ }
9628
+ return length >= Math.ceil(max * 0.9) ? 'Queda menos del 10 % de caracteres disponibles.' : '';
9629
+ }, /* @ts-ignore */
9630
+ ...(ngDevMode ? [{ debugName: "counterAnnouncement" }] : /* istanbul ignore next */ []));
9631
+ /** Hint o error, más el contador cuando se muestra. */
9632
+ describedBy = computed(() => {
9633
+ const ids = [
9634
+ this.errorMessage() ? this.errorId : this.hint() ? this.hintId : null,
9635
+ this.counterVisible() ? this.counterId : null,
9636
+ ].filter((id) => id !== null);
9637
+ return ids.length ? ids.join(' ') : null;
9638
+ }, /* @ts-ignore */
9639
+ ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
9477
9640
  onChange = () => { };
9478
9641
  onTouched = () => { };
9479
9642
  ngAfterViewInit() {
@@ -9536,24 +9699,24 @@ class Textarea {
9536
9699
  el.style.overflowY = el.scrollHeight > maxHeight ? 'auto' : 'hidden';
9537
9700
  }
9538
9701
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Textarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
9539
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Textarea, isStandalone: true, selector: "kf-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minRows: { classPropertyName: "minRows", publicName: "minRows", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
9702
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Textarea, isStandalone: true, selector: "kf-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minRows: { classPropertyName: "minRows", publicName: "minRows", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, showCounter: { classPropertyName: "showCounter", publicName: "showCounter", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
9540
9703
  {
9541
9704
  provide: NG_VALUE_ACCESSOR,
9542
9705
  useExisting: forwardRef(() => Textarea),
9543
9706
  multi: true,
9544
9707
  },
9545
- ], viewQueries: [{ propertyName: "nativeTextarea", first: true, predicate: ["nativeTextarea"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"textareaId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<textarea\n #nativeTextarea\n [id]=\"textareaId\"\n class=\"kf-textarea__control\"\n [class.kf-textarea__control--focused]=\"focused()\"\n [class.kf-textarea__control--invalid]=\"invalid()\"\n [class.kf-textarea__control--readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.readonly]=\"readonly() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : hint() ? hintId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [value]=\"value()\"\n (input)=\"onInput(nativeTextarea.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n></textarea>\n@if (errorMessage(); as message) {\n <span class=\"kf-textarea__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-textarea__hint kf-field-hint\" [id]=\"hintId\">{{ hint() }}</span>\n}\n", styles: [".kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);font-family:var(--kf-font-body)}.kf-textarea__control{resize:none;width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);background:var(--kf-color-surface);color:var(--kf-color-text);font:inherit;padding:var(--kf-space-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-textarea__control::placeholder{color:var(--kf-color-text-muted)}.kf-textarea__control--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus);outline:none}.kf-textarea__control--invalid{border-color:var(--kf-color-error)}.kf-textarea__control--invalid.kf-textarea__control--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-textarea__control:disabled{opacity:.5;cursor:not-allowed}.kf-textarea__control--readonly{background:var(--kf-color-gray-100);cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required", "visuallyHidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9708
+ ], viewQueries: [{ propertyName: "nativeTextarea", first: true, predicate: ["nativeTextarea"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"textareaId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<textarea\n #nativeTextarea\n [id]=\"textareaId\"\n class=\"kf-textarea__control\"\n [class.kf-textarea__control--focused]=\"focused()\"\n [class.kf-textarea__control--invalid]=\"invalid()\"\n [class.kf-textarea__control--readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.readonly]=\"readonly() ? true : null\"\n [attr.maxlength]=\"maxlength()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [value]=\"value()\"\n (input)=\"onInput(nativeTextarea.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n></textarea>\n<ng-template #feedback>\n @if (errorMessage(); as message) {\n <span class=\"kf-textarea__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n } @else if (hint()) {\n <span class=\"kf-textarea__hint kf-field-hint\" [id]=\"hintId\">{{ hint() }}</span>\n }\n</ng-template>\n@if (counterVisible()) {\n <div class=\"kf-textarea__footer\">\n <ng-container [ngTemplateOutlet]=\"feedback\" />\n <span\n class=\"kf-textarea__counter kf-field-hint\"\n [class.kf-textarea__counter--limit]=\"atLimit()\"\n [id]=\"counterId\"\n >{{ value().length }} / {{ maxlength() }}</span\n >\n </div>\n <span class=\"kf-sr-only\" aria-live=\"polite\" aria-atomic=\"true\">{{ counterAnnouncement() }}</span>\n} @else {\n <ng-container [ngTemplateOutlet]=\"feedback\" />\n}\n", styles: [".kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);font-family:var(--kf-font-body)}.kf-textarea__control{resize:none;width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);background:var(--kf-color-surface);color:var(--kf-color-text);font:inherit;padding:var(--kf-space-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-textarea__control::placeholder{color:var(--kf-color-text-muted)}.kf-textarea__control--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus);outline:none}.kf-textarea__control--invalid{border-color:var(--kf-color-error)}.kf-textarea__control--invalid.kf-textarea__control--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-textarea__control:disabled{opacity:.5;cursor:not-allowed}.kf-textarea__control--readonly{background:var(--kf-color-gray-100);cursor:default}.kf-textarea__footer{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-textarea__footer>.kf-textarea__hint,.kf-textarea__footer>.kf-textarea__error{flex:1 1 auto;min-width:0}.kf-textarea__counter{flex:none;margin-inline-start:auto;white-space:nowrap;font-variant-numeric:tabular-nums}.kf-textarea__counter--limit{font-weight:600;color:var(--kf-color-error-strong)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required", "visuallyHidden"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9546
9709
  }
9547
9710
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Textarea, decorators: [{
9548
9711
  type: Component,
9549
- args: [{ selector: 'kf-textarea', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, FieldLabel], providers: [
9712
+ args: [{ selector: 'kf-textarea', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, FieldLabel, NgTemplateOutlet], providers: [
9550
9713
  {
9551
9714
  provide: NG_VALUE_ACCESSOR,
9552
9715
  useExisting: forwardRef(() => Textarea),
9553
9716
  multi: true,
9554
9717
  },
9555
- ], template: "@if (label()) {\n <kf-field-label [for]=\"textareaId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<textarea\n #nativeTextarea\n [id]=\"textareaId\"\n class=\"kf-textarea__control\"\n [class.kf-textarea__control--focused]=\"focused()\"\n [class.kf-textarea__control--invalid]=\"invalid()\"\n [class.kf-textarea__control--readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.readonly]=\"readonly() ? true : null\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : hint() ? hintId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [value]=\"value()\"\n (input)=\"onInput(nativeTextarea.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n></textarea>\n@if (errorMessage(); as message) {\n <span class=\"kf-textarea__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-textarea__hint kf-field-hint\" [id]=\"hintId\">{{ hint() }}</span>\n}\n", styles: [".kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);font-family:var(--kf-font-body)}.kf-textarea__control{resize:none;width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);background:var(--kf-color-surface);color:var(--kf-color-text);font:inherit;padding:var(--kf-space-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-textarea__control::placeholder{color:var(--kf-color-text-muted)}.kf-textarea__control--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus);outline:none}.kf-textarea__control--invalid{border-color:var(--kf-color-error)}.kf-textarea__control--invalid.kf-textarea__control--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-textarea__control:disabled{opacity:.5;cursor:not-allowed}.kf-textarea__control--readonly{background:var(--kf-color-gray-100);cursor:default}\n"] }]
9556
- }], propDecorators: { nativeTextarea: [{ type: i0.ViewChild, args: ['nativeTextarea', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRows", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }] } });
9718
+ ], template: "@if (label()) {\n <kf-field-label [for]=\"textareaId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<textarea\n #nativeTextarea\n [id]=\"textareaId\"\n class=\"kf-textarea__control\"\n [class.kf-textarea__control--focused]=\"focused()\"\n [class.kf-textarea__control--invalid]=\"invalid()\"\n [class.kf-textarea__control--readonly]=\"readonly()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.readonly]=\"readonly() ? true : null\"\n [attr.maxlength]=\"maxlength()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [value]=\"value()\"\n (input)=\"onInput(nativeTextarea.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n></textarea>\n<ng-template #feedback>\n @if (errorMessage(); as message) {\n <span class=\"kf-textarea__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n } @else if (hint()) {\n <span class=\"kf-textarea__hint kf-field-hint\" [id]=\"hintId\">{{ hint() }}</span>\n }\n</ng-template>\n@if (counterVisible()) {\n <div class=\"kf-textarea__footer\">\n <ng-container [ngTemplateOutlet]=\"feedback\" />\n <span\n class=\"kf-textarea__counter kf-field-hint\"\n [class.kf-textarea__counter--limit]=\"atLimit()\"\n [id]=\"counterId\"\n >{{ value().length }} / {{ maxlength() }}</span\n >\n </div>\n <span class=\"kf-sr-only\" aria-live=\"polite\" aria-atomic=\"true\">{{ counterAnnouncement() }}</span>\n} @else {\n <ng-container [ngTemplateOutlet]=\"feedback\" />\n}\n", styles: [".kf-field-hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-field-error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}.kf-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;gap:var(--kf-space-xs);font-family:var(--kf-font-body)}.kf-textarea__control{resize:none;width:100%;min-width:0;box-sizing:border-box;border:1px solid var(--kf-color-border-control);border-radius:var(--kf-radius-sm);background:var(--kf-color-surface);color:var(--kf-color-text);font:inherit;padding:var(--kf-space-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-textarea__control::placeholder{color:var(--kf-color-text-muted)}.kf-textarea__control--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus);outline:none}.kf-textarea__control--invalid{border-color:var(--kf-color-error)}.kf-textarea__control--invalid.kf-textarea__control--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-textarea__control:disabled{opacity:.5;cursor:not-allowed}.kf-textarea__control--readonly{background:var(--kf-color-gray-100);cursor:default}.kf-textarea__footer{display:flex;align-items:flex-start;gap:var(--kf-space-sm)}.kf-textarea__footer>.kf-textarea__hint,.kf-textarea__footer>.kf-textarea__error{flex:1 1 auto;min-width:0}.kf-textarea__counter{flex:none;margin-inline-start:auto;white-space:nowrap;font-variant-numeric:tabular-nums}.kf-textarea__counter--limit{font-weight:600;color:var(--kf-color-error-strong)}\n"] }]
9719
+ }], propDecorators: { nativeTextarea: [{ type: i0.ViewChild, args: ['nativeTextarea', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRows", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], showCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCounter", required: false }] }] } });
9557
9720
 
9558
9721
  /**
9559
9722
  * Da forma al valor de un campo MIENTRAS el usuario escribe — ej.