@kaufmann-lab/ui 0.1.18 → 0.1.20
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.
- package/README.md +18 -1
- package/fesm2022/kaufmann-lab-ui-business.mjs +30 -3
- package/fesm2022/kaufmann-lab-ui-business.mjs.map +1 -1
- package/fesm2022/kaufmann-lab-ui-core.mjs +460 -20
- package/fesm2022/kaufmann-lab-ui-core.mjs.map +1 -1
- package/package.json +1 -1
- package/types/kaufmann-lab-ui-business.d.ts +42 -3
- package/types/kaufmann-lab-ui-core.d.ts +191 -11
- package/kaufmann-lab-ui-0.1.18.tgz +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, booleanAttribute, inject, computed, effect, Component, model, output,
|
|
2
|
+
import { input, booleanAttribute, inject, computed, effect, Component, model, output, ElementRef, Injector, signal, afterNextRender, ChangeDetectionStrategy, numberAttribute, contentChildren, DestroyRef, viewChild, forwardRef, TemplateRef, contentChild, ViewContainerRef, HostListener, afterRenderEffect, viewChildren, Input as Input$1, Directive, Injectable } from '@angular/core';
|
|
3
3
|
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule, NgControl } from '@angular/forms';
|
|
@@ -1385,6 +1385,304 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1385
1385
|
args: [{ selector: 'kf-bucket-progress', template: "<div class=\"kf-bucket-progress__head\">\n <span class=\"kf-bucket-progress__title\">{{ title() }}</span>\n @if (summary()) {\n <span class=\"kf-bucket-progress__summary\">{{ summary() }}</span>\n }\n</div>\n\n<div class=\"kf-bucket-progress__bar\" role=\"img\" [attr.aria-label]=\"ariaLabel()\">\n @for (item of visibleItems(); track item.key) {\n <span\n class=\"kf-bucket-progress__segment\"\n [style.flex-grow]=\"item.count\"\n [style.background]=\"item.color\"\n ></span>\n }\n</div>\n\n<div class=\"kf-bucket-progress__legend\">\n @for (item of visibleItems(); track item.key) {\n <span class=\"kf-bucket-progress__legend-item\">\n <span class=\"kf-bucket-progress__dot\" [style.background]=\"item.color\"></span>\n {{ item.count }} {{ item.label }}\n </span>\n }\n</div>\n", styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}.kf-bucket-progress__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);flex-wrap:wrap}.kf-bucket-progress__title{font-family:var(--kf-font-title);font-weight:700;color:var(--kf-color-ink);font-size:.95rem}.kf-bucket-progress__summary{font-size:.85rem;color:var(--kf-color-text-muted)}.kf-bucket-progress__bar{display:flex;gap:2px;height:8px}.kf-bucket-progress__segment{border-radius:2px;transition:flex-grow .3s ease}@media(prefers-reduced-motion:reduce){.kf-bucket-progress__segment{transition:none}}.kf-bucket-progress__legend{display:flex;flex-wrap:wrap;gap:var(--kf-space-md)}.kf-bucket-progress__legend-item{display:flex;align-items:center;gap:6px;font-size:.78rem;color:var(--kf-color-text-muted)}.kf-bucket-progress__dot{width:8px;height:8px;border-radius:2px;flex:none}\n"] }]
|
|
1386
1386
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], summary: [{ type: i0.Input, args: [{ isSignal: true, alias: "summary", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
|
|
1387
1387
|
|
|
1388
|
+
const DEFAULT_MONTH_NAMES = [
|
|
1389
|
+
'Enero',
|
|
1390
|
+
'Febrero',
|
|
1391
|
+
'Marzo',
|
|
1392
|
+
'Abril',
|
|
1393
|
+
'Mayo',
|
|
1394
|
+
'Junio',
|
|
1395
|
+
'Julio',
|
|
1396
|
+
'Agosto',
|
|
1397
|
+
'Septiembre',
|
|
1398
|
+
'Octubre',
|
|
1399
|
+
'Noviembre',
|
|
1400
|
+
'Diciembre',
|
|
1401
|
+
];
|
|
1402
|
+
const DEFAULT_WEEKDAY_LABELS = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
|
|
1403
|
+
const DEFAULT_WEEKDAY_NAMES = [
|
|
1404
|
+
'lunes',
|
|
1405
|
+
'martes',
|
|
1406
|
+
'miércoles',
|
|
1407
|
+
'jueves',
|
|
1408
|
+
'viernes',
|
|
1409
|
+
'sábado',
|
|
1410
|
+
'domingo',
|
|
1411
|
+
];
|
|
1412
|
+
/**
|
|
1413
|
+
* Selector de fecha de un solo mes, con grilla semanal que parte en lunes.
|
|
1414
|
+
*
|
|
1415
|
+
* Las fechas viajan como strings ISO (`YYYY-MM-DD`, y `YYYY-MM` para el mes
|
|
1416
|
+
* visible) y se calculan en UTC, así la zona horaria del navegador nunca
|
|
1417
|
+
* corre una fecha un día.
|
|
1418
|
+
*
|
|
1419
|
+
* `availableDates` en `null` deja seleccionable toda fecha dentro de
|
|
1420
|
+
* `min`/`max`; un arreglo deja seleccionables SOLO esas fechas (el resto se
|
|
1421
|
+
* rinde deshabilitado). `markedDates` es independiente: agrega un punto
|
|
1422
|
+
* marcador sin afectar si la fecha se puede elegir.
|
|
1423
|
+
*
|
|
1424
|
+
* Patrón WAI-ARIA `grid` con roving tabindex: las flechas mueven por
|
|
1425
|
+
* día/semana, Home/End van al inicio/fin de la semana y PageUp/PageDown
|
|
1426
|
+
* cambian de mes; el foco cruza los límites del mes.
|
|
1427
|
+
*
|
|
1428
|
+
* <kf-calendar
|
|
1429
|
+
* [(value)]="date"
|
|
1430
|
+
* [(month)]="month"
|
|
1431
|
+
* [min]="today"
|
|
1432
|
+
* [availableDates]="freeDates()"
|
|
1433
|
+
* [markedDates]="eventDates()"
|
|
1434
|
+
* [loading]="loadingAvailability()"
|
|
1435
|
+
* >
|
|
1436
|
+
* <p footer>Leyenda</p>
|
|
1437
|
+
* </kf-calendar>
|
|
1438
|
+
*/
|
|
1439
|
+
class Calendar {
|
|
1440
|
+
static nextId = 0;
|
|
1441
|
+
/** Fecha seleccionada, ISO `YYYY-MM-DD`. */
|
|
1442
|
+
value = model(null, /* @ts-ignore */
|
|
1443
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1444
|
+
/** Mes visible, `YYYY-MM`. En `null` se deriva de `value` y, si no hay, de hoy. */
|
|
1445
|
+
month = model(null, /* @ts-ignore */
|
|
1446
|
+
...(ngDevMode ? [{ debugName: "month" }] : /* istanbul ignore next */ []));
|
|
1447
|
+
/** Fecha mínima seleccionable (inclusive), ISO. */
|
|
1448
|
+
min = input(null, /* @ts-ignore */
|
|
1449
|
+
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
1450
|
+
/** Fecha máxima seleccionable (inclusive), ISO. */
|
|
1451
|
+
max = input(null, /* @ts-ignore */
|
|
1452
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
1453
|
+
/** `null`: toda fecha dentro de `min`/`max` es seleccionable. Arreglo: solo esas fechas. */
|
|
1454
|
+
availableDates = input(null, /* @ts-ignore */
|
|
1455
|
+
...(ngDevMode ? [{ debugName: "availableDates" }] : /* istanbul ignore next */ []));
|
|
1456
|
+
/** Fechas con punto marcador, independiente de si son seleccionables. */
|
|
1457
|
+
markedDates = input([], /* @ts-ignore */
|
|
1458
|
+
...(ngDevMode ? [{ debugName: "markedDates" }] : /* istanbul ignore next */ []));
|
|
1459
|
+
/** Reemplaza el "hoy" local (tests/SSR), ISO. */
|
|
1460
|
+
today = input(null, /* @ts-ignore */
|
|
1461
|
+
...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
|
|
1462
|
+
/** Atenúa la grilla y bloquea la selección mientras carga la disponibilidad. */
|
|
1463
|
+
loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1464
|
+
ariaLabel = input('Calendario', /* @ts-ignore */
|
|
1465
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
1466
|
+
/** Los 12 nombres de mes, partiendo en enero. */
|
|
1467
|
+
monthNames = input(DEFAULT_MONTH_NAMES, /* @ts-ignore */
|
|
1468
|
+
...(ngDevMode ? [{ debugName: "monthNames" }] : /* istanbul ignore next */ []));
|
|
1469
|
+
/** Las 7 iniciales visibles de los días, partiendo en lunes. */
|
|
1470
|
+
weekdayLabels = input(DEFAULT_WEEKDAY_LABELS, /* @ts-ignore */
|
|
1471
|
+
...(ngDevMode ? [{ debugName: "weekdayLabels" }] : /* istanbul ignore next */ []));
|
|
1472
|
+
/** Los 7 nombres completos de los días, partiendo en lunes — se usan en los nombres accesibles. */
|
|
1473
|
+
weekdayNames = input(DEFAULT_WEEKDAY_NAMES, /* @ts-ignore */
|
|
1474
|
+
...(ngDevMode ? [{ debugName: "weekdayNames" }] : /* istanbul ignore next */ []));
|
|
1475
|
+
/** Se agrega al nombre accesible de una fecha marcada. */
|
|
1476
|
+
markedLabel = input('marcado', /* @ts-ignore */
|
|
1477
|
+
...(ngDevMode ? [{ debugName: "markedLabel" }] : /* istanbul ignore next */ []));
|
|
1478
|
+
previousMonthLabel = input('Mes anterior', /* @ts-ignore */
|
|
1479
|
+
...(ngDevMode ? [{ debugName: "previousMonthLabel" }] : /* istanbul ignore next */ []));
|
|
1480
|
+
nextMonthLabel = input('Mes siguiente', /* @ts-ignore */
|
|
1481
|
+
...(ngDevMode ? [{ debugName: "nextMonthLabel" }] : /* istanbul ignore next */ []));
|
|
1482
|
+
host = inject(ElementRef);
|
|
1483
|
+
injector = inject(Injector);
|
|
1484
|
+
focusedDate = signal(null, /* @ts-ignore */
|
|
1485
|
+
...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
|
|
1486
|
+
titleId = `kf-calendar-title-${Calendar.nextId++}`;
|
|
1487
|
+
todayIso = computed(() => this.today() ?? localTodayIso(), /* @ts-ignore */
|
|
1488
|
+
...(ngDevMode ? [{ debugName: "todayIso" }] : /* istanbul ignore next */ []));
|
|
1489
|
+
displayedMonth = computed(() => this.month() ?? this.value()?.slice(0, 7) ?? this.todayIso().slice(0, 7), /* @ts-ignore */
|
|
1490
|
+
...(ngDevMode ? [{ debugName: "displayedMonth" }] : /* istanbul ignore next */ []));
|
|
1491
|
+
title = computed(() => {
|
|
1492
|
+
const [year, month] = parseParts(this.displayedMonth());
|
|
1493
|
+
return `${this.monthNames()[month - 1]} ${year}`;
|
|
1494
|
+
}, /* @ts-ignore */
|
|
1495
|
+
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
1496
|
+
minMonth = computed(() => this.min()?.slice(0, 7) ?? null, /* @ts-ignore */
|
|
1497
|
+
...(ngDevMode ? [{ debugName: "minMonth" }] : /* istanbul ignore next */ []));
|
|
1498
|
+
maxMonth = computed(() => this.max()?.slice(0, 7) ?? null, /* @ts-ignore */
|
|
1499
|
+
...(ngDevMode ? [{ debugName: "maxMonth" }] : /* istanbul ignore next */ []));
|
|
1500
|
+
canGoPrevious = computed(() => this.isMonthNavigable(shiftMonth(this.displayedMonth(), -1)), /* @ts-ignore */
|
|
1501
|
+
...(ngDevMode ? [{ debugName: "canGoPrevious" }] : /* istanbul ignore next */ []));
|
|
1502
|
+
canGoNext = computed(() => this.isMonthNavigable(shiftMonth(this.displayedMonth(), 1)), /* @ts-ignore */
|
|
1503
|
+
...(ngDevMode ? [{ debugName: "canGoNext" }] : /* istanbul ignore next */ []));
|
|
1504
|
+
availableSet = computed(() => {
|
|
1505
|
+
const dates = this.availableDates();
|
|
1506
|
+
return dates ? new Set(dates) : null;
|
|
1507
|
+
}, /* @ts-ignore */
|
|
1508
|
+
...(ngDevMode ? [{ debugName: "availableSet" }] : /* istanbul ignore next */ []));
|
|
1509
|
+
markedSet = computed(() => new Set(this.markedDates()), /* @ts-ignore */
|
|
1510
|
+
...(ngDevMode ? [{ debugName: "markedSet" }] : /* istanbul ignore next */ []));
|
|
1511
|
+
weeks = computed(() => {
|
|
1512
|
+
const month = this.displayedMonth();
|
|
1513
|
+
const firstDay = `${month}-01`;
|
|
1514
|
+
const lastDay = addDays(`${shiftMonth(month, 1)}-01`, -1);
|
|
1515
|
+
const start = addDays(firstDay, -weekdayIndex(firstDay));
|
|
1516
|
+
const end = addDays(lastDay, 6 - weekdayIndex(lastDay));
|
|
1517
|
+
const weeks = [];
|
|
1518
|
+
let week = [];
|
|
1519
|
+
for (let iso = start; iso <= end; iso = addDays(iso, 1)) {
|
|
1520
|
+
week.push(this.buildDay(iso, month));
|
|
1521
|
+
if (week.length === 7) {
|
|
1522
|
+
weeks.push(week);
|
|
1523
|
+
week = [];
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
return weeks;
|
|
1527
|
+
}, /* @ts-ignore */
|
|
1528
|
+
...(ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []));
|
|
1529
|
+
/** La única celda con `tabindex="0"` (roving tabindex). */
|
|
1530
|
+
activeDate = computed(() => {
|
|
1531
|
+
const month = this.displayedMonth();
|
|
1532
|
+
const inMonth = (iso) => iso?.slice(0, 7) === month;
|
|
1533
|
+
const focused = this.focusedDate();
|
|
1534
|
+
if (inMonth(focused)) {
|
|
1535
|
+
return focused;
|
|
1536
|
+
}
|
|
1537
|
+
const value = this.value();
|
|
1538
|
+
if (inMonth(value)) {
|
|
1539
|
+
return value;
|
|
1540
|
+
}
|
|
1541
|
+
const today = this.todayIso();
|
|
1542
|
+
if (inMonth(today)) {
|
|
1543
|
+
return today;
|
|
1544
|
+
}
|
|
1545
|
+
const firstSelectable = this.weeks()
|
|
1546
|
+
.flat()
|
|
1547
|
+
.find((day) => day.selectable);
|
|
1548
|
+
return firstSelectable?.iso ?? `${month}-01`;
|
|
1549
|
+
}, /* @ts-ignore */
|
|
1550
|
+
...(ngDevMode ? [{ debugName: "activeDate" }] : /* istanbul ignore next */ []));
|
|
1551
|
+
previousMonth() {
|
|
1552
|
+
if (this.canGoPrevious()) {
|
|
1553
|
+
this.month.set(shiftMonth(this.displayedMonth(), -1));
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
nextMonth() {
|
|
1557
|
+
if (this.canGoNext()) {
|
|
1558
|
+
this.month.set(shiftMonth(this.displayedMonth(), 1));
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
selectDay(day) {
|
|
1562
|
+
if (!day.selectable || this.loading()) {
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
this.focusedDate.set(day.iso);
|
|
1566
|
+
if (day.iso !== this.value()) {
|
|
1567
|
+
this.value.set(day.iso);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
onDayFocus(iso) {
|
|
1571
|
+
this.focusedDate.set(iso);
|
|
1572
|
+
}
|
|
1573
|
+
onDayKeydown(event, iso) {
|
|
1574
|
+
const target = keyboardTarget(event.key, iso);
|
|
1575
|
+
if (target === null) {
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
event.preventDefault();
|
|
1579
|
+
const targetMonth = target.slice(0, 7);
|
|
1580
|
+
if (!this.isMonthNavigable(targetMonth)) {
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
this.focusedDate.set(target);
|
|
1584
|
+
if (targetMonth !== this.displayedMonth()) {
|
|
1585
|
+
this.month.set(targetMonth);
|
|
1586
|
+
}
|
|
1587
|
+
// Si cambió el mes, la celda destino todavía no existe en el DOM.
|
|
1588
|
+
afterNextRender(() => this.focusDay(target), { injector: this.injector });
|
|
1589
|
+
}
|
|
1590
|
+
focusDay(iso) {
|
|
1591
|
+
this.host.nativeElement.querySelector(`[data-date="${iso}"]`)?.focus();
|
|
1592
|
+
}
|
|
1593
|
+
isMonthNavigable(month) {
|
|
1594
|
+
const min = this.minMonth();
|
|
1595
|
+
const max = this.maxMonth();
|
|
1596
|
+
return (min === null || month >= min) && (max === null || month <= max);
|
|
1597
|
+
}
|
|
1598
|
+
buildDay(iso, displayedMonth) {
|
|
1599
|
+
const [year, month, day] = parseParts(iso);
|
|
1600
|
+
const inMonth = iso.slice(0, 7) === displayedMonth;
|
|
1601
|
+
const min = this.min();
|
|
1602
|
+
const max = this.max();
|
|
1603
|
+
const available = this.availableSet();
|
|
1604
|
+
const marked = this.markedSet().has(iso);
|
|
1605
|
+
const weekdayName = this.weekdayNames()[weekdayIndex(iso)];
|
|
1606
|
+
const monthName = this.monthNames()[month - 1].toLowerCase();
|
|
1607
|
+
const baseLabel = `${weekdayName} ${day} de ${monthName} de ${year}`;
|
|
1608
|
+
return {
|
|
1609
|
+
iso,
|
|
1610
|
+
day,
|
|
1611
|
+
inMonth,
|
|
1612
|
+
selectable: inMonth &&
|
|
1613
|
+
(min === null || iso >= min) &&
|
|
1614
|
+
(max === null || iso <= max) &&
|
|
1615
|
+
(available === null || available.has(iso)),
|
|
1616
|
+
selected: iso === this.value(),
|
|
1617
|
+
marked,
|
|
1618
|
+
today: iso === this.todayIso(),
|
|
1619
|
+
ariaLabel: marked ? `${baseLabel}, ${this.markedLabel()}` : baseLabel,
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Calendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1623
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Calendar, isStandalone: true, selector: "kf-calendar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, month: { classPropertyName: "month", publicName: "month", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, availableDates: { classPropertyName: "availableDates", publicName: "availableDates", isSignal: true, isRequired: false, transformFunction: null }, markedDates: { classPropertyName: "markedDates", publicName: "markedDates", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, monthNames: { classPropertyName: "monthNames", publicName: "monthNames", isSignal: true, isRequired: false, transformFunction: null }, weekdayLabels: { classPropertyName: "weekdayLabels", publicName: "weekdayLabels", isSignal: true, isRequired: false, transformFunction: null }, weekdayNames: { classPropertyName: "weekdayNames", publicName: "weekdayNames", isSignal: true, isRequired: false, transformFunction: null }, markedLabel: { classPropertyName: "markedLabel", publicName: "markedLabel", isSignal: true, isRequired: false, transformFunction: null }, previousMonthLabel: { classPropertyName: "previousMonthLabel", publicName: "previousMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, nextMonthLabel: { classPropertyName: "nextMonthLabel", publicName: "nextMonthLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", month: "monthChange" }, ngImport: i0, template: "<div class=\"kf-calendar\" role=\"group\" [attr.aria-label]=\"ariaLabel()\">\n <div class=\"kf-calendar__header\">\n <kf-button\n variant=\"ghost\"\n shape=\"circle\"\n size=\"lg\"\n type=\"button\"\n icon=\"chevron-left\"\n [ariaLabel]=\"previousMonthLabel()\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousMonth()\"\n />\n <kf-text\n class=\"kf-calendar__title\"\n as=\"span\"\n variant=\"title-sm\"\n aria-live=\"polite\"\n [attr.id]=\"titleId\"\n >{{ title() }}</kf-text\n >\n <kf-button\n variant=\"ghost\"\n shape=\"circle\"\n size=\"lg\"\n type=\"button\"\n icon=\"chevron-right\"\n [ariaLabel]=\"nextMonthLabel()\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextMonth()\"\n />\n </div>\n\n <div\n class=\"kf-calendar__grid\"\n role=\"grid\"\n [class.kf-calendar__grid--loading]=\"loading()\"\n [attr.aria-labelledby]=\"titleId\"\n [attr.aria-busy]=\"loading() || null\"\n >\n <div class=\"kf-calendar__row\" role=\"row\">\n @for (label of weekdayLabels(); track $index) {\n <span\n class=\"kf-calendar__weekday kf-overline-text\"\n role=\"columnheader\"\n [attr.aria-label]=\"weekdayNames()[$index]\"\n >{{ label }}</span\n >\n }\n </div>\n\n @for (week of weeks(); track week[0].iso) {\n <div class=\"kf-calendar__row\" role=\"row\">\n @for (day of week; track day.iso) {\n @if (day.inMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"kf-calendar__day\"\n [class.kf-calendar__day--selectable]=\"day.selectable\"\n [class.kf-calendar__day--selected]=\"day.selected\"\n [class.kf-calendar__day--today]=\"day.today\"\n [class.kf-calendar__day--marked]=\"day.marked\"\n [attr.data-date]=\"day.iso\"\n [attr.aria-label]=\"day.ariaLabel\"\n [attr.aria-selected]=\"day.selected\"\n [attr.aria-disabled]=\"!day.selectable\"\n [attr.aria-current]=\"day.today ? 'date' : null\"\n [attr.tabindex]=\"day.iso === activeDate() ? 0 : -1\"\n (click)=\"selectDay(day)\"\n (focus)=\"onDayFocus(day.iso)\"\n (keydown)=\"onDayKeydown($event, day.iso)\"\n >\n {{ day.day }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"kf-calendar__day kf-calendar__day--outside\">\n <span aria-hidden=\"true\">{{ day.day }}</span>\n </span>\n }\n }\n </div>\n }\n </div>\n\n <ng-content select=\"[footer]\" />\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)}:host{display:block}.kf-calendar{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-calendar__header{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm)}.kf-calendar__title{flex:1;text-align:center}.kf-calendar__grid{display:flex;flex-direction:column;gap:2px;transition:opacity .2s ease}.kf-calendar__grid--loading{opacity:.5;cursor:progress}.kf-calendar__row{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.kf-calendar__weekday{display:flex;align-items:center;justify-content:center;min-height:32px}.kf-calendar__day{position:relative;display:flex;align-items:center;justify-content:center;min-width:0;min-height:44px;padding:0;box-sizing:border-box;border:none;border-radius:var(--kf-radius-sm);background:transparent;font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted);cursor:default;transition:background-color .14s,color .14s}.kf-calendar__day--selectable{font-weight:var(--kf-font-weight-medium);color:var(--kf-color-ink);cursor:pointer}.kf-calendar__grid--loading .kf-calendar__day--selectable{cursor:progress}.kf-calendar__day--selectable:hover:not(.kf-calendar__day--selected){background:var(--kf-color-primary-soft)}.kf-calendar__day:focus-visible{z-index:1;outline:2px solid var(--kf-color-primary);outline-offset:1px}.kf-calendar__day--today{box-shadow:inset 0 0 0 1.5px var(--kf-color-primary)}.kf-calendar__day--selected{background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-calendar__day--selected:hover{background:var(--kf-color-primary-hover)}.kf-calendar__day--outside{color:var(--kf-color-gray-400)}.kf-calendar__day--marked:after{content:\"\";position:absolute;bottom:6px;left:50%;width:4px;height:4px;margin-left:-2px;border-radius:var(--kf-radius-pill);background:var(--kf-color-primary)}.kf-calendar__day--selected.kf-calendar__day--marked:after{background:var(--kf-color-white)}@media(prefers-reduced-motion:reduce){.kf-calendar__grid,.kf-calendar__day{transition:none}}\n"], dependencies: [{ kind: "component", type: Button, selector: "kf-button", inputs: ["variant", "size", "shape", "disabled", "type", "icon", "block", "loading", "ariaLabel", "ariaExpanded", "ariaPressed"] }, { kind: "component", type: Text, selector: "kf-text", inputs: ["as", "variant", "tone"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1624
|
+
}
|
|
1625
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Calendar, decorators: [{
|
|
1626
|
+
type: Component,
|
|
1627
|
+
args: [{ selector: 'kf-calendar', changeDetection: ChangeDetectionStrategy.OnPush, imports: [Button, Text], template: "<div class=\"kf-calendar\" role=\"group\" [attr.aria-label]=\"ariaLabel()\">\n <div class=\"kf-calendar__header\">\n <kf-button\n variant=\"ghost\"\n shape=\"circle\"\n size=\"lg\"\n type=\"button\"\n icon=\"chevron-left\"\n [ariaLabel]=\"previousMonthLabel()\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousMonth()\"\n />\n <kf-text\n class=\"kf-calendar__title\"\n as=\"span\"\n variant=\"title-sm\"\n aria-live=\"polite\"\n [attr.id]=\"titleId\"\n >{{ title() }}</kf-text\n >\n <kf-button\n variant=\"ghost\"\n shape=\"circle\"\n size=\"lg\"\n type=\"button\"\n icon=\"chevron-right\"\n [ariaLabel]=\"nextMonthLabel()\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextMonth()\"\n />\n </div>\n\n <div\n class=\"kf-calendar__grid\"\n role=\"grid\"\n [class.kf-calendar__grid--loading]=\"loading()\"\n [attr.aria-labelledby]=\"titleId\"\n [attr.aria-busy]=\"loading() || null\"\n >\n <div class=\"kf-calendar__row\" role=\"row\">\n @for (label of weekdayLabels(); track $index) {\n <span\n class=\"kf-calendar__weekday kf-overline-text\"\n role=\"columnheader\"\n [attr.aria-label]=\"weekdayNames()[$index]\"\n >{{ label }}</span\n >\n }\n </div>\n\n @for (week of weeks(); track week[0].iso) {\n <div class=\"kf-calendar__row\" role=\"row\">\n @for (day of week; track day.iso) {\n @if (day.inMonth) {\n <button\n type=\"button\"\n role=\"gridcell\"\n class=\"kf-calendar__day\"\n [class.kf-calendar__day--selectable]=\"day.selectable\"\n [class.kf-calendar__day--selected]=\"day.selected\"\n [class.kf-calendar__day--today]=\"day.today\"\n [class.kf-calendar__day--marked]=\"day.marked\"\n [attr.data-date]=\"day.iso\"\n [attr.aria-label]=\"day.ariaLabel\"\n [attr.aria-selected]=\"day.selected\"\n [attr.aria-disabled]=\"!day.selectable\"\n [attr.aria-current]=\"day.today ? 'date' : null\"\n [attr.tabindex]=\"day.iso === activeDate() ? 0 : -1\"\n (click)=\"selectDay(day)\"\n (focus)=\"onDayFocus(day.iso)\"\n (keydown)=\"onDayKeydown($event, day.iso)\"\n >\n {{ day.day }}\n </button>\n } @else {\n <span role=\"gridcell\" class=\"kf-calendar__day kf-calendar__day--outside\">\n <span aria-hidden=\"true\">{{ day.day }}</span>\n </span>\n }\n }\n </div>\n }\n </div>\n\n <ng-content select=\"[footer]\" />\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)}:host{display:block}.kf-calendar{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-calendar__header{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm)}.kf-calendar__title{flex:1;text-align:center}.kf-calendar__grid{display:flex;flex-direction:column;gap:2px;transition:opacity .2s ease}.kf-calendar__grid--loading{opacity:.5;cursor:progress}.kf-calendar__row{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.kf-calendar__weekday{display:flex;align-items:center;justify-content:center;min-height:32px}.kf-calendar__day{position:relative;display:flex;align-items:center;justify-content:center;min-width:0;min-height:44px;padding:0;box-sizing:border-box;border:none;border-radius:var(--kf-radius-sm);background:transparent;font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted);cursor:default;transition:background-color .14s,color .14s}.kf-calendar__day--selectable{font-weight:var(--kf-font-weight-medium);color:var(--kf-color-ink);cursor:pointer}.kf-calendar__grid--loading .kf-calendar__day--selectable{cursor:progress}.kf-calendar__day--selectable:hover:not(.kf-calendar__day--selected){background:var(--kf-color-primary-soft)}.kf-calendar__day:focus-visible{z-index:1;outline:2px solid var(--kf-color-primary);outline-offset:1px}.kf-calendar__day--today{box-shadow:inset 0 0 0 1.5px var(--kf-color-primary)}.kf-calendar__day--selected{background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-calendar__day--selected:hover{background:var(--kf-color-primary-hover)}.kf-calendar__day--outside{color:var(--kf-color-gray-400)}.kf-calendar__day--marked:after{content:\"\";position:absolute;bottom:6px;left:50%;width:4px;height:4px;margin-left:-2px;border-radius:var(--kf-radius-pill);background:var(--kf-color-primary)}.kf-calendar__day--selected.kf-calendar__day--marked:after{background:var(--kf-color-white)}@media(prefers-reduced-motion:reduce){.kf-calendar__grid,.kf-calendar__day{transition:none}}\n"] }]
|
|
1628
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], month: [{ type: i0.Input, args: [{ isSignal: true, alias: "month", required: false }] }, { type: i0.Output, args: ["monthChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], availableDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableDates", required: false }] }], markedDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "markedDates", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], monthNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthNames", required: false }] }], weekdayLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekdayLabels", required: false }] }], weekdayNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekdayNames", required: false }] }], markedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "markedLabel", required: false }] }], previousMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthLabel", required: false }] }], nextMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthLabel", required: false }] }] } });
|
|
1629
|
+
function pad(value) {
|
|
1630
|
+
return String(value).padStart(2, '0');
|
|
1631
|
+
}
|
|
1632
|
+
function parseParts(iso) {
|
|
1633
|
+
return iso.split('-').map(Number);
|
|
1634
|
+
}
|
|
1635
|
+
function fromUtc(date) {
|
|
1636
|
+
return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}-${pad(date.getUTCDate())}`;
|
|
1637
|
+
}
|
|
1638
|
+
function localTodayIso() {
|
|
1639
|
+
const now = new Date();
|
|
1640
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
1641
|
+
}
|
|
1642
|
+
function addDays(iso, days) {
|
|
1643
|
+
const [year, month, day] = parseParts(iso);
|
|
1644
|
+
return fromUtc(new Date(Date.UTC(year, month - 1, day + days)));
|
|
1645
|
+
}
|
|
1646
|
+
/** 0 = lunes … 6 = domingo. */
|
|
1647
|
+
function weekdayIndex(iso) {
|
|
1648
|
+
const [year, month, day] = parseParts(iso);
|
|
1649
|
+
return (new Date(Date.UTC(year, month - 1, day)).getUTCDay() + 6) % 7;
|
|
1650
|
+
}
|
|
1651
|
+
function shiftMonth(yearMonth, delta) {
|
|
1652
|
+
const [year, month] = parseParts(yearMonth);
|
|
1653
|
+
const date = new Date(Date.UTC(year, month - 1 + delta, 1));
|
|
1654
|
+
return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}`;
|
|
1655
|
+
}
|
|
1656
|
+
/** Mismo día en otro mes, acotado al último día de ese mes. */
|
|
1657
|
+
function shiftDateByMonths(iso, delta) {
|
|
1658
|
+
const targetMonth = shiftMonth(iso.slice(0, 7), delta);
|
|
1659
|
+
const lastDay = parseParts(addDays(`${shiftMonth(targetMonth, 1)}-01`, -1))[2];
|
|
1660
|
+
const day = Math.min(parseParts(iso)[2], lastDay);
|
|
1661
|
+
return `${targetMonth}-${pad(day)}`;
|
|
1662
|
+
}
|
|
1663
|
+
function keyboardTarget(key, iso) {
|
|
1664
|
+
switch (key) {
|
|
1665
|
+
case 'ArrowLeft':
|
|
1666
|
+
return addDays(iso, -1);
|
|
1667
|
+
case 'ArrowRight':
|
|
1668
|
+
return addDays(iso, 1);
|
|
1669
|
+
case 'ArrowUp':
|
|
1670
|
+
return addDays(iso, -7);
|
|
1671
|
+
case 'ArrowDown':
|
|
1672
|
+
return addDays(iso, 7);
|
|
1673
|
+
case 'Home':
|
|
1674
|
+
return addDays(iso, -weekdayIndex(iso));
|
|
1675
|
+
case 'End':
|
|
1676
|
+
return addDays(iso, 6 - weekdayIndex(iso));
|
|
1677
|
+
case 'PageUp':
|
|
1678
|
+
return shiftDateByMonths(iso, -1);
|
|
1679
|
+
case 'PageDown':
|
|
1680
|
+
return shiftDateByMonths(iso, 1);
|
|
1681
|
+
default:
|
|
1682
|
+
return null;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1388
1686
|
/**
|
|
1389
1687
|
* Contenedor base con esquinas redondeadas y sombra sutil — la base visual
|
|
1390
1688
|
* de paneles, tarjetas de métrica, tablas y bloques de contenido de todo el
|
|
@@ -2351,6 +2649,7 @@ const COMPACT_PANEL_MIN_WIDTH = 72;
|
|
|
2351
2649
|
*
|
|
2352
2650
|
* <kf-select label="Sede" [options]="['Lima', 'Arequipa', 'Trujillo']" placeholder="Selecciona…" />
|
|
2353
2651
|
* <kf-select [options]="[{ value: 'pe', label: 'Perú' }]" (valueChange)="onCountry($event)" />
|
|
2652
|
+
* <kf-select [options]="[{ value: '1002099', label: 'BBVA', tag: 'Empresa', detail: 'RUC 20100130204' }]" />
|
|
2354
2653
|
*
|
|
2355
2654
|
* `variant="compact"` cambia el ancho de `240px` fijo a intrínseco con un
|
|
2356
2655
|
* techo de `160px` (se ajusta al contenido de la opción seleccionada hasta
|
|
@@ -2414,7 +2713,7 @@ class Select {
|
|
|
2414
2713
|
...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
|
|
2415
2714
|
activeIndex = signal(0, /* @ts-ignore */
|
|
2416
2715
|
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
2417
|
-
/** Resolves
|
|
2716
|
+
/** Resolves `string | SelectOption` entries into a single shape for the template. */
|
|
2418
2717
|
normalizedOptions = computed(() => this.options().map((option) => typeof option === 'string' ? { value: option, label: option } : option), /* @ts-ignore */
|
|
2419
2718
|
...(ngDevMode ? [{ debugName: "normalizedOptions" }] : /* istanbul ignore next */ []));
|
|
2420
2719
|
selectedOption = computed(() => this.normalizedOptions().find((option) => option.value === this.value()), /* @ts-ignore */
|
|
@@ -2427,7 +2726,7 @@ class Select {
|
|
|
2427
2726
|
if (!query) {
|
|
2428
2727
|
return this.normalizedOptions();
|
|
2429
2728
|
}
|
|
2430
|
-
return this.normalizedOptions().filter((option) =>
|
|
2729
|
+
return this.normalizedOptions().filter((option) => [option.label, option.tag, option.detail].some((text) => !!text && normalizeForSearch(text).includes(query)));
|
|
2431
2730
|
}, /* @ts-ignore */
|
|
2432
2731
|
...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
2433
2732
|
triggerRef = viewChild.required('trigger', /* @ts-ignore */
|
|
@@ -2474,6 +2773,13 @@ class Select {
|
|
|
2474
2773
|
}
|
|
2475
2774
|
this.isOpen.update((open) => !open);
|
|
2476
2775
|
}
|
|
2776
|
+
/** Nombre accesible explícito solo para opciones con `tag`/`detail`, para separar las partes al leerlas. */
|
|
2777
|
+
optionAriaLabel(option) {
|
|
2778
|
+
if (!option.tag && !option.detail) {
|
|
2779
|
+
return null;
|
|
2780
|
+
}
|
|
2781
|
+
return [option.label, option.tag, option.detail].filter(Boolean).join(', ');
|
|
2782
|
+
}
|
|
2477
2783
|
select(option) {
|
|
2478
2784
|
this.isOpen.set(false);
|
|
2479
2785
|
if (option.value !== this.value()) {
|
|
@@ -2505,16 +2811,16 @@ class Select {
|
|
|
2505
2811
|
}
|
|
2506
2812
|
}
|
|
2507
2813
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2508
|
-
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 }, 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 }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchThreshold: { classPropertyName: "searchThreshold", publicName: "searchThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" }, 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'" } }, 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 }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\">{{ 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 [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (click)=\"toggle()\"\n>\n <span class=\"kf-select__value\" [class.kf-select__value--placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\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 class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\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 />\n }\n <ul class=\"kf-select__list\" [id]=\"listboxId\" role=\"listbox\" [attr.aria-labelledby]=\"triggerId\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"0\"\n [attr.aria-selected]=\"option.value === value()\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown.enter)=\"select(option)\"\n (keydown.space)=\"$event.preventDefault(); select(option)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n >\n {{ option.label }}\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)}: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--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);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.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--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;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__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);color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.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__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"], dependencies: [{ kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required"] }] });
|
|
2814
|
+
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 }, 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 }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchThreshold: { classPropertyName: "searchThreshold", publicName: "searchThreshold", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" }, 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'" } }, 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 }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\">{{ 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 [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\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>\n <span class=\"kf-select__value\" [class.kf-select__value--placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n @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 class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\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 />\n }\n <ul class=\"kf-select__list\" [id]=\"listboxId\" role=\"listbox\" [attr.aria-labelledby]=\"triggerId\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"0\"\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.enter)=\"select(option)\"\n (keydown.space)=\"$event.preventDefault(); select(option)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\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)}: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--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);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.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__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;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__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);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__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"] }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required"] }] });
|
|
2509
2815
|
}
|
|
2510
2816
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, decorators: [{
|
|
2511
2817
|
type: Component,
|
|
2512
|
-
args: [{ selector: 'kf-select', imports: [FieldLabel], host: {
|
|
2818
|
+
args: [{ selector: 'kf-select', imports: [Badge, FieldLabel], host: {
|
|
2513
2819
|
'[class.kf-select--compact]': "variant() === 'compact'",
|
|
2514
2820
|
'[class.kf-select--width-sm]': "width() === 'sm'",
|
|
2515
2821
|
'[class.kf-select--width-lg]': "width() === 'lg'",
|
|
2516
2822
|
'[class.kf-select--width-full]': "width() === 'full'",
|
|
2517
|
-
}, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\">{{ 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 [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-describedby]=\"errorMessage() ? errorId : null\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n (click)=\"toggle()\"\n>\n <span class=\"kf-select__value\" [class.kf-select__value--placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\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 class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\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 />\n }\n <ul class=\"kf-select__list\" [id]=\"listboxId\" role=\"listbox\" [attr.aria-labelledby]=\"triggerId\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"0\"\n [attr.aria-selected]=\"option.value === value()\"\n (click)=\"select(option)\"\n (mouseenter)=\"activeIndex.set(i)\"\n (keydown.enter)=\"select(option)\"\n (keydown.space)=\"$event.preventDefault(); select(option)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\n >\n {{ option.label }}\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)}: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--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);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.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--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;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__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);color:var(--kf-color-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.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__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
|
|
2823
|
+
}, template: "@if (label()) {\n <kf-field-label [for]=\"triggerId\">{{ 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 [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\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>\n <span class=\"kf-select__value\" [class.kf-select__value--placeholder]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n @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 class=\"kf-select__panel\" [class.kf-select__panel--compact]=\"variant() === 'compact'\">\n @if (showSearch()) {\n <input\n #searchInput\n type=\"text\"\n class=\"kf-select__search\"\n placeholder=\"Buscar\u2026\"\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 />\n }\n <ul class=\"kf-select__list\" [id]=\"listboxId\" role=\"listbox\" [attr.aria-labelledby]=\"triggerId\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"kf-select__option\"\n [class.kf-select__option--selected]=\"option.value === value()\"\n [class.kf-select__option--active]=\"i === activeIndex()\"\n role=\"option\"\n tabindex=\"0\"\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.enter)=\"select(option)\"\n (keydown.space)=\"$event.preventDefault(); select(option)\"\n (keydown.arrowdown)=\"$event.preventDefault(); moveActive(1)\"\n (keydown.arrowup)=\"$event.preventDefault(); moveActive(-1)\"\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)}: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--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);border-radius:var(--kf-radius-sm);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.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__trigger--tagged .kf-select__value{flex:1 1 auto;min-width:0;text-align:start}.kf-select__tag{flex:none}.kf-select__trigger .kf-select__tag{margin-block:-2px}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__panel{box-sizing:border-box;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__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);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__empty{text-align:center;padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
|
|
2518
2824
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", 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 }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchThreshold", 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 }] }], onDocumentEscape: [{
|
|
2519
2825
|
type: HostListener,
|
|
2520
2826
|
args: ['document:keydown.escape']
|
|
@@ -3510,6 +3816,10 @@ class Input {
|
|
|
3510
3816
|
...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
3511
3817
|
placeholder = input('', /* @ts-ignore */
|
|
3512
3818
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
3819
|
+
/** Teclado virtual sugerido en mobile (ej. `"numeric"` para montos o
|
|
3820
|
+
* kilometraje) — sin valor, el navegador decide según `type`. */
|
|
3821
|
+
inputmode = input(/* @ts-ignore */
|
|
3822
|
+
...(ngDevMode ? [undefined, { debugName: "inputmode" }] : /* istanbul ignore next */ []));
|
|
3513
3823
|
/** Agrega el botón de mostrar/ocultar — sin efecto si `type` no es `"password"`. */
|
|
3514
3824
|
toggleable = input(false, { ...(ngDevMode ? { debugName: "toggleable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3515
3825
|
inputId = `kf-input-${Input.nextId++}`;
|
|
@@ -3587,13 +3897,13 @@ class Input {
|
|
|
3587
3897
|
this.passwordVisible.update((visible) => !visible);
|
|
3588
3898
|
}
|
|
3589
3899
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Input, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3590
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Input, isStandalone: true, selector: "kf-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", 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 }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, toggleable: { classPropertyName: "toggleable", publicName: "toggleable", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
3900
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Input, isStandalone: true, selector: "kf-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", 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 }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, inputmode: { classPropertyName: "inputmode", publicName: "inputmode", isSignal: true, isRequired: false, transformFunction: null }, toggleable: { classPropertyName: "toggleable", publicName: "toggleable", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
3591
3901
|
{
|
|
3592
3902
|
provide: NG_VALUE_ACCESSOR,
|
|
3593
3903
|
useExisting: forwardRef(() => Input),
|
|
3594
3904
|
multi: true,
|
|
3595
3905
|
},
|
|
3596
|
-
], viewQueries: [{ propertyName: "nativeInput", first: true, predicate: ["nativeInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"inputId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<div\n class=\"kf-input__field\"\n [class.kf-input__field--disabled]=\"isDisabled()\"\n [class.kf-input__field--readonly]=\"readonly()\"\n [class.kf-input__field--focused]=\"focused()\"\n [class.kf-input__field--invalid]=\"invalid()\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-input__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n <input\n #nativeInput\n [id]=\"inputId\"\n class=\"kf-input__control\"\n [type]=\"effectiveType()\"\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(nativeInput.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n />\n @if (showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"kf-input__toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"onTogglePasswordVisibility()\"\n >\n <kf-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" size=\"sm\" />\n </button>\n } @else if (suffix()) {\n <span class=\"kf-input__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (errorMessage(); as message) {\n <span class=\"kf-input__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-input__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-input__field{display:flex;align-items:center;gap:var(--kf-space-sm);padding:0 var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-input__field--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-input__field--invalid{border-color:var(--kf-color-error)}.kf-input__field--invalid.kf-input__field--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-input__field--disabled{opacity:.5}.kf-input__field--readonly{background:var(--kf-color-gray-100)}.kf-input__control:read-only{cursor:default}.kf-input__icon{color:var(--kf-color-text-muted)}.kf-input__field--invalid .kf-input__icon{color:var(--kf-color-error)}.kf-input__control{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) 0}.kf-input__control::placeholder{color:var(--kf-color-text-muted)}.kf-input__control:disabled{cursor:not-allowed}.kf-input__suffix{flex:none;color:var(--kf-color-text-muted);font-size:.875rem}.kf-input__toggle{flex:none;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;padding:var(--kf-space-xs);margin:0 calc(var(--kf-space-xs) * -1);color:var(--kf-color-text-muted);cursor:pointer;border-radius:var(--kf-radius-xs);transition:color .14s}.kf-input__toggle:hover{color:var(--kf-color-text)}.kf-input__toggle:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required"] }, { kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3906
|
+
], viewQueries: [{ propertyName: "nativeInput", first: true, predicate: ["nativeInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <kf-field-label [for]=\"inputId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<div\n class=\"kf-input__field\"\n [class.kf-input__field--disabled]=\"isDisabled()\"\n [class.kf-input__field--readonly]=\"readonly()\"\n [class.kf-input__field--focused]=\"focused()\"\n [class.kf-input__field--invalid]=\"invalid()\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-input__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n <input\n #nativeInput\n [id]=\"inputId\"\n class=\"kf-input__control\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [attr.inputmode]=\"inputmode() || null\"\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(nativeInput.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n />\n @if (showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"kf-input__toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"onTogglePasswordVisibility()\"\n >\n <kf-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" size=\"sm\" />\n </button>\n } @else if (suffix()) {\n <span class=\"kf-input__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (errorMessage(); as message) {\n <span class=\"kf-input__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-input__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-input__field{display:flex;align-items:center;gap:var(--kf-space-sm);padding:0 var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-input__field--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-input__field--invalid{border-color:var(--kf-color-error)}.kf-input__field--invalid.kf-input__field--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-input__field--disabled{opacity:.5}.kf-input__field--readonly{background:var(--kf-color-gray-100)}.kf-input__control:read-only{cursor:default}.kf-input__icon{color:var(--kf-color-text-muted)}.kf-input__field--invalid .kf-input__icon{color:var(--kf-color-error)}.kf-input__control{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) 0}.kf-input__control::placeholder{color:var(--kf-color-text-muted)}.kf-input__control:disabled{cursor:not-allowed}.kf-input__suffix{flex:none;color:var(--kf-color-text-muted);font-size:.875rem}.kf-input__toggle{flex:none;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;padding:var(--kf-space-xs);margin:0 calc(var(--kf-space-xs) * -1);color:var(--kf-color-text-muted);cursor:pointer;border-radius:var(--kf-radius-xs);transition:color .14s}.kf-input__toggle:hover{color:var(--kf-color-text)}.kf-input__toggle:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldLabel, selector: "kf-field-label", inputs: ["for", "required"] }, { kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size", "rotate", "filled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3597
3907
|
}
|
|
3598
3908
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Input, decorators: [{
|
|
3599
3909
|
type: Component,
|
|
@@ -3603,8 +3913,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3603
3913
|
useExisting: forwardRef(() => Input),
|
|
3604
3914
|
multi: true,
|
|
3605
3915
|
},
|
|
3606
|
-
], template: "@if (label()) {\n <kf-field-label [for]=\"inputId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<div\n class=\"kf-input__field\"\n [class.kf-input__field--disabled]=\"isDisabled()\"\n [class.kf-input__field--readonly]=\"readonly()\"\n [class.kf-input__field--focused]=\"focused()\"\n [class.kf-input__field--invalid]=\"invalid()\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-input__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n <input\n #nativeInput\n [id]=\"inputId\"\n class=\"kf-input__control\"\n [type]=\"effectiveType()\"\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(nativeInput.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n />\n @if (showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"kf-input__toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"onTogglePasswordVisibility()\"\n >\n <kf-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" size=\"sm\" />\n </button>\n } @else if (suffix()) {\n <span class=\"kf-input__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (errorMessage(); as message) {\n <span class=\"kf-input__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-input__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-input__field{display:flex;align-items:center;gap:var(--kf-space-sm);padding:0 var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-input__field--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-input__field--invalid{border-color:var(--kf-color-error)}.kf-input__field--invalid.kf-input__field--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-input__field--disabled{opacity:.5}.kf-input__field--readonly{background:var(--kf-color-gray-100)}.kf-input__control:read-only{cursor:default}.kf-input__icon{color:var(--kf-color-text-muted)}.kf-input__field--invalid .kf-input__icon{color:var(--kf-color-error)}.kf-input__control{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) 0}.kf-input__control::placeholder{color:var(--kf-color-text-muted)}.kf-input__control:disabled{cursor:not-allowed}.kf-input__suffix{flex:none;color:var(--kf-color-text-muted);font-size:.875rem}.kf-input__toggle{flex:none;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;padding:var(--kf-space-xs);margin:0 calc(var(--kf-space-xs) * -1);color:var(--kf-color-text-muted);cursor:pointer;border-radius:var(--kf-radius-xs);transition:color .14s}.kf-input__toggle:hover{color:var(--kf-color-text)}.kf-input__toggle:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}\n"] }]
|
|
3607
|
-
}], 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 }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", 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 }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], toggleable: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleable", required: false }] }] } });
|
|
3916
|
+
], template: "@if (label()) {\n <kf-field-label [for]=\"inputId\" [required]=\"required()\">{{ label() }}</kf-field-label>\n}\n<div\n class=\"kf-input__field\"\n [class.kf-input__field--disabled]=\"isDisabled()\"\n [class.kf-input__field--readonly]=\"readonly()\"\n [class.kf-input__field--focused]=\"focused()\"\n [class.kf-input__field--invalid]=\"invalid()\"\n>\n @if (icon(); as iconName) {\n <kf-icon class=\"kf-input__icon\" [name]=\"iconName\" size=\"sm\" />\n }\n <input\n #nativeInput\n [id]=\"inputId\"\n class=\"kf-input__control\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [attr.inputmode]=\"inputmode() || null\"\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(nativeInput.value)\"\n (blur)=\"onBlur()\"\n (focus)=\"focused.set(true)\"\n />\n @if (showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"kf-input__toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Ocultar contrase\u00F1a' : 'Mostrar contrase\u00F1a'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"onTogglePasswordVisibility()\"\n >\n <kf-icon [name]=\"passwordVisible() ? 'eye-off' : 'eye'\" size=\"sm\" />\n </button>\n } @else if (suffix()) {\n <span class=\"kf-input__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (errorMessage(); as message) {\n <span class=\"kf-input__error kf-field-error\" [id]=\"errorId\" role=\"alert\">{{ message }}</span>\n} @else if (hint()) {\n <span class=\"kf-input__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-input__field{display:flex;align-items:center;gap:var(--kf-space-sm);padding:0 var(--kf-space-sm);background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);transition:background .14s,border-color .14s,box-shadow .14s}.kf-input__field--focused{background:var(--kf-color-white);border-color:var(--kf-color-primary);box-shadow:var(--kf-shadow-focus)}.kf-input__field--invalid{border-color:var(--kf-color-error)}.kf-input__field--invalid.kf-input__field--focused{box-shadow:var(--kf-shadow-focus-error)}.kf-input__field--disabled{opacity:.5}.kf-input__field--readonly{background:var(--kf-color-gray-100)}.kf-input__control:read-only{cursor:default}.kf-input__icon{color:var(--kf-color-text-muted)}.kf-input__field--invalid .kf-input__icon{color:var(--kf-color-error)}.kf-input__control{flex:1;min-width:0;border:none;outline:none;background:transparent;font:inherit;color:var(--kf-color-text);padding:var(--kf-space-sm) 0}.kf-input__control::placeholder{color:var(--kf-color-text-muted)}.kf-input__control:disabled{cursor:not-allowed}.kf-input__suffix{flex:none;color:var(--kf-color-text-muted);font-size:.875rem}.kf-input__toggle{flex:none;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;padding:var(--kf-space-xs);margin:0 calc(var(--kf-space-xs) * -1);color:var(--kf-color-text-muted);cursor:pointer;border-radius:var(--kf-radius-xs);transition:color .14s}.kf-input__toggle:hover{color:var(--kf-color-text)}.kf-input__toggle:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}\n"] }]
|
|
3917
|
+
}], 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 }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", 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 }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inputmode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputmode", required: false }] }], toggleable: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleable", required: false }] }] } });
|
|
3608
3918
|
|
|
3609
3919
|
let nextId = 0;
|
|
3610
3920
|
/**
|
|
@@ -3860,7 +4170,7 @@ class Filter {
|
|
|
3860
4170
|
this.fieldChange.emit({ key, value });
|
|
3861
4171
|
}
|
|
3862
4172
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Filter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3863
|
-
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", "required", "icon", "suffix", "hint", "invalid", "errorMessage", "disabled", "readonly", "type", "placeholder", "toggleable"] }, { 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", "options", "value", "placeholder", "disabled", "invalid", "errorMessage", "variant", "width", "searchable", "searchThreshold"], outputs: ["valueChange"] }] });
|
|
4173
|
+
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", "required", "icon", "suffix", "hint", "invalid", "errorMessage", "disabled", "readonly", "type", "placeholder", "inputmode", "toggleable"] }, { 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", "options", "value", "placeholder", "disabled", "invalid", "errorMessage", "variant", "width", "searchable", "searchThreshold"], outputs: ["valueChange"] }] });
|
|
3864
4174
|
}
|
|
3865
4175
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Filter, decorators: [{
|
|
3866
4176
|
type: Component,
|
|
@@ -4374,6 +4684,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4374
4684
|
* <kf-action-tile-row icon="download" title="Pagos" description="Revisa tu estado de cuenta y realiza pagos." />
|
|
4375
4685
|
* </kf-panel>
|
|
4376
4686
|
*
|
|
4687
|
+
* Para apps con router: escuchar `actionClick` y llamar
|
|
4688
|
+
* `event.preventDefault()` antes de `router.navigateByUrl(...)`. El
|
|
4689
|
+
* `actionHref` se mantiene igual para que click-medio, "abrir en pestaña
|
|
4690
|
+
* nueva" y el hover de la barra de estado sigan funcionando.
|
|
4691
|
+
*
|
|
4692
|
+
* <kf-panel title="Mis documentos por pagar" actionLabel="Ir a pagos" actionHref="/pagos"
|
|
4693
|
+
* (actionClick)="$event.preventDefault(); router.navigateByUrl('/pagos')">
|
|
4694
|
+
* …
|
|
4695
|
+
* </kf-panel>
|
|
4696
|
+
*
|
|
4377
4697
|
* El host y el `kf-card` interno son flex column con `flex:1` de punta a
|
|
4378
4698
|
* punta — si un grid/flex externo estira `kf-panel` a la altura de un
|
|
4379
4699
|
* hermano más alto, el contenido proyectado hereda esa altura en vez de
|
|
@@ -4388,13 +4708,19 @@ class Panel {
|
|
|
4388
4708
|
...(ngDevMode ? [undefined, { debugName: "actionLabel" }] : /* istanbul ignore next */ []));
|
|
4389
4709
|
actionHref = input(/* @ts-ignore */
|
|
4390
4710
|
...(ngDevMode ? [undefined, { debugName: "actionHref" }] : /* istanbul ignore next */ []));
|
|
4711
|
+
/**
|
|
4712
|
+
* Click en el link de acción. Incluye el `MouseEvent` para que un
|
|
4713
|
+
* consumidor con router pueda cortar la navegación nativa — mismo patrón
|
|
4714
|
+
* que `itemClick` de `kf-breadcrumb`, sin depender de `@angular/router`.
|
|
4715
|
+
*/
|
|
4716
|
+
actionClick = output();
|
|
4391
4717
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Panel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4392
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Panel, isStandalone: true, selector: "kf-panel", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, actionHref: { classPropertyName: "actionHref", publicName: "actionHref", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<kf-card>\n <div class=\"kf-panel__head\">\n <span class=\"kf-panel__title\">{{ title() }}</span>\n @if (actionLabel()) {\n <kf-link
|
|
4718
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Panel, isStandalone: true, selector: "kf-panel", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, actionHref: { classPropertyName: "actionHref", publicName: "actionHref", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<kf-card>\n <div class=\"kf-panel__head\">\n <span class=\"kf-panel__title\">{{ title() }}</span>\n @if (actionLabel()) {\n <kf-link\n class=\"kf-panel__action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n </div>\n <kf-divider />\n <div class=\"kf-panel__body\">\n <ng-content />\n </div>\n</kf-card>\n", styles: [":host{display:flex;flex-direction:column}kf-card{flex:1}.kf-panel__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);margin-bottom:var(--kf-space-sm)}.kf-panel__title{font-family:var(--kf-font-title);font-size:1.05rem;font-weight:700;color:var(--kf-color-ink)}.kf-panel__action{flex:none;font-size:.8125rem;font-weight:600}.kf-panel__body{display:flex;flex:1;flex-direction:column;gap:var(--kf-space-sm);margin-top:var(--kf-space-sm)}\n"], dependencies: [{ kind: "component", type: Card, selector: "kf-card", inputs: ["flush", "gap"] }, { kind: "component", type: Divider, selector: "kf-divider", inputs: ["orientation"] }, { kind: "component", type: Link, selector: "kf-link", inputs: ["variant", "disabled", "href", "showArrow"] }] });
|
|
4393
4719
|
}
|
|
4394
4720
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Panel, decorators: [{
|
|
4395
4721
|
type: Component,
|
|
4396
|
-
args: [{ selector: 'kf-panel', imports: [Card, Divider, Link], template: "<kf-card>\n <div class=\"kf-panel__head\">\n <span class=\"kf-panel__title\">{{ title() }}</span>\n @if (actionLabel()) {\n <kf-link
|
|
4397
|
-
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], actionHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionHref", required: false }] }] } });
|
|
4722
|
+
args: [{ selector: 'kf-panel', imports: [Card, Divider, Link], template: "<kf-card>\n <div class=\"kf-panel__head\">\n <span class=\"kf-panel__title\">{{ title() }}</span>\n @if (actionLabel()) {\n <kf-link\n class=\"kf-panel__action\"\n [href]=\"actionHref() || '#'\"\n showArrow\n (click)=\"actionClick.emit($event)\"\n >\n {{ actionLabel() }}\n </kf-link>\n }\n </div>\n <kf-divider />\n <div class=\"kf-panel__body\">\n <ng-content />\n </div>\n</kf-card>\n", styles: [":host{display:flex;flex-direction:column}kf-card{flex:1}.kf-panel__head{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);margin-bottom:var(--kf-space-sm)}.kf-panel__title{font-family:var(--kf-font-title);font-size:1.05rem;font-weight:700;color:var(--kf-color-ink)}.kf-panel__action{flex:none;font-size:.8125rem;font-weight:600}.kf-panel__body{display:flex;flex:1;flex-direction:column;gap:var(--kf-space-sm);margin-top:var(--kf-space-sm)}\n"] }]
|
|
4723
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], 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"] }] } });
|
|
4398
4724
|
|
|
4399
4725
|
/**
|
|
4400
4726
|
* Cabecera completa del portal (página 31) — franja de administrador
|
|
@@ -4570,11 +4896,11 @@ class Progress {
|
|
|
4570
4896
|
clampedValue = computed(() => Math.min(Math.max(this.value(), 0), 100), /* @ts-ignore */
|
|
4571
4897
|
...(ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []));
|
|
4572
4898
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Progress, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4573
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Progress, isStandalone: true, selector: "kf-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"kf-progress\">\n @if (label(); as text) {\n <div class=\"kf-progress__top\">\n <span class=\"kf-progress__label kf-progress--{{ tone() }}\">{{ text }}</span>\n </div>\n }\n <div\n class=\"kf-progress__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"kf-progress__fill kf-progress--{{ tone() }}\" [style.width.%]=\"clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}.kf-progress{display:flex;flex-direction:column;min-width:0}.kf-progress__top{display:flex;justify-content:flex-end;margin-block-end:3px}.kf-progress__label{font-family:var(--kf-font-mono);font-size:var(--kf-font-size-caption);font-weight:700}.kf-progress__track{height:4px;border-radius:var(--kf-radius-pill);background:var(--kf-color-gray-200);overflow:hidden}.kf-progress__fill{height:100%;border-radius:var(--kf-radius-pill);transition:width .3s ease}@media(prefers-reduced-motion:reduce){.kf-progress__fill{transition:none}}.kf-progress--neutral{color:var(--kf-color-text-muted)}.kf-progress__fill.kf-progress--neutral{background:var(--kf-color-secondary)}.kf-progress--ok{color:var(--kf-color-success-strong)}.kf-progress__fill.kf-progress--ok{background:var(--kf-color-success)}.kf-progress--warn{color:var(--kf-color-warning-strong)}.kf-progress__fill.kf-progress--warn{background:var(--kf-color-warning)}.kf-progress--error{color:var(--kf-color-error-strong)}.kf-progress__fill.kf-progress--error{background:var(--kf-color-error)}\n"] });
|
|
4899
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Progress, isStandalone: true, selector: "kf-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"kf-progress\">\n @if (label(); as text) {\n <div class=\"kf-progress__top\">\n <span class=\"kf-progress__label kf-progress--{{ tone() }}\">{{ text }}</span>\n </div>\n }\n <div\n class=\"kf-progress__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"kf-progress__fill kf-progress--{{ tone() }}\" [style.width.%]=\"clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}.kf-progress{display:flex;flex-direction:column;min-width:0}.kf-progress__top{display:flex;justify-content:flex-end;margin-block-end:3px}.kf-progress__label{font-family:var(--kf-font-mono);font-size:var(--kf-font-size-caption);font-weight:700}.kf-progress__track{height:4px;border-radius:var(--kf-radius-pill);background:var(--kf-color-gray-200);overflow:hidden}.kf-progress__fill{height:100%;border-radius:var(--kf-radius-pill);transition:width .3s ease}@media(prefers-reduced-motion:reduce){.kf-progress__fill{transition:none}}.kf-progress--neutral{color:var(--kf-color-text-muted)}.kf-progress__fill.kf-progress--neutral{background:var(--kf-color-secondary)}.kf-progress--primary{color:var(--kf-color-primary)}.kf-progress__fill.kf-progress--primary{background:var(--kf-color-primary)}.kf-progress--ok{color:var(--kf-color-success-strong)}.kf-progress__fill.kf-progress--ok{background:var(--kf-color-success)}.kf-progress--warn{color:var(--kf-color-warning-strong)}.kf-progress__fill.kf-progress--warn{background:var(--kf-color-warning)}.kf-progress--error{color:var(--kf-color-error-strong)}.kf-progress__fill.kf-progress--error{background:var(--kf-color-error)}\n"] });
|
|
4574
4900
|
}
|
|
4575
4901
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Progress, decorators: [{
|
|
4576
4902
|
type: Component,
|
|
4577
|
-
args: [{ selector: 'kf-progress', template: "<div class=\"kf-progress\">\n @if (label(); as text) {\n <div class=\"kf-progress__top\">\n <span class=\"kf-progress__label kf-progress--{{ tone() }}\">{{ text }}</span>\n </div>\n }\n <div\n class=\"kf-progress__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"kf-progress__fill kf-progress--{{ tone() }}\" [style.width.%]=\"clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}.kf-progress{display:flex;flex-direction:column;min-width:0}.kf-progress__top{display:flex;justify-content:flex-end;margin-block-end:3px}.kf-progress__label{font-family:var(--kf-font-mono);font-size:var(--kf-font-size-caption);font-weight:700}.kf-progress__track{height:4px;border-radius:var(--kf-radius-pill);background:var(--kf-color-gray-200);overflow:hidden}.kf-progress__fill{height:100%;border-radius:var(--kf-radius-pill);transition:width .3s ease}@media(prefers-reduced-motion:reduce){.kf-progress__fill{transition:none}}.kf-progress--neutral{color:var(--kf-color-text-muted)}.kf-progress__fill.kf-progress--neutral{background:var(--kf-color-secondary)}.kf-progress--ok{color:var(--kf-color-success-strong)}.kf-progress__fill.kf-progress--ok{background:var(--kf-color-success)}.kf-progress--warn{color:var(--kf-color-warning-strong)}.kf-progress__fill.kf-progress--warn{background:var(--kf-color-warning)}.kf-progress--error{color:var(--kf-color-error-strong)}.kf-progress__fill.kf-progress--error{background:var(--kf-color-error)}\n"] }]
|
|
4903
|
+
args: [{ selector: 'kf-progress', template: "<div class=\"kf-progress\">\n @if (label(); as text) {\n <div class=\"kf-progress__top\">\n <span class=\"kf-progress__label kf-progress--{{ tone() }}\">{{ text }}</span>\n </div>\n }\n <div\n class=\"kf-progress__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"kf-progress__fill kf-progress--{{ tone() }}\" [style.width.%]=\"clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}.kf-progress{display:flex;flex-direction:column;min-width:0}.kf-progress__top{display:flex;justify-content:flex-end;margin-block-end:3px}.kf-progress__label{font-family:var(--kf-font-mono);font-size:var(--kf-font-size-caption);font-weight:700}.kf-progress__track{height:4px;border-radius:var(--kf-radius-pill);background:var(--kf-color-gray-200);overflow:hidden}.kf-progress__fill{height:100%;border-radius:var(--kf-radius-pill);transition:width .3s ease}@media(prefers-reduced-motion:reduce){.kf-progress__fill{transition:none}}.kf-progress--neutral{color:var(--kf-color-text-muted)}.kf-progress__fill.kf-progress--neutral{background:var(--kf-color-secondary)}.kf-progress--primary{color:var(--kf-color-primary)}.kf-progress__fill.kf-progress--primary{background:var(--kf-color-primary)}.kf-progress--ok{color:var(--kf-color-success-strong)}.kf-progress__fill.kf-progress--ok{background:var(--kf-color-success)}.kf-progress--warn{color:var(--kf-color-warning-strong)}.kf-progress__fill.kf-progress--warn{background:var(--kf-color-warning)}.kf-progress--error{color:var(--kf-color-error-strong)}.kf-progress__fill.kf-progress--error{background:var(--kf-color-error)}\n"] }]
|
|
4578
4904
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
4579
4905
|
|
|
4580
4906
|
/**
|
|
@@ -5314,6 +5640,12 @@ class StatTile {
|
|
|
5314
5640
|
...(ngDevMode ? [undefined, { debugName: "actionLabel" }] : /* istanbul ignore next */ []));
|
|
5315
5641
|
actionHref = input(/* @ts-ignore */
|
|
5316
5642
|
...(ngDevMode ? [undefined, { debugName: "actionHref" }] : /* istanbul ignore next */ []));
|
|
5643
|
+
/**
|
|
5644
|
+
* Click en el link de la variante CTA. Incluye el `MouseEvent` para que un
|
|
5645
|
+
* consumidor con router pueda cortar la navegación nativa — mismo patrón
|
|
5646
|
+
* que `actionClick` de `kf-panel`, sin depender de `@angular/router`.
|
|
5647
|
+
*/
|
|
5648
|
+
actionClick = output();
|
|
5317
5649
|
/** Texto real de la nota. `null` significa "no reservar la línea": pasa
|
|
5318
5650
|
* solo cuando el consumidor no declaró ni nota ni placeholder. */
|
|
5319
5651
|
noteText = computed(() => this.note() || this.notePlaceholder() || null, /* @ts-ignore */
|
|
@@ -5321,15 +5653,15 @@ class StatTile {
|
|
|
5321
5653
|
noteIsPlaceholder = computed(() => !this.note() && !!this.notePlaceholder(), /* @ts-ignore */
|
|
5322
5654
|
...(ngDevMode ? [{ debugName: "noteIsPlaceholder" }] : /* istanbul ignore next */ []));
|
|
5323
5655
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5324
|
-
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 } }, host: { properties: { "class.kf-stat-tile--cta": "cta()", "class.kf-stat-tile--inline": "!cta() && variant() === \"inline\"" } }, 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
|
|
5656
|
+
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 } }, outputs: { actionClick: "actionClick" }, host: { properties: { "class.kf-stat-tile--cta": "cta()", "class.kf-stat-tile--inline": "!cta() && variant() === \"inline\"" } }, 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:.8125rem;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:.8125rem;color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:.8125rem;font-weight:600}\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"] }] });
|
|
5325
5657
|
}
|
|
5326
5658
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: StatTile, decorators: [{
|
|
5327
5659
|
type: Component,
|
|
5328
5660
|
args: [{ selector: 'kf-stat-tile', imports: [Icon, Link], host: {
|
|
5329
5661
|
'[class.kf-stat-tile--cta]': 'cta()',
|
|
5330
5662
|
'[class.kf-stat-tile--inline]': '!cta() && variant() === "inline"',
|
|
5331
|
-
}, 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
|
|
5332
|
-
}], 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 }] }] } });
|
|
5663
|
+
}, 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:.8125rem;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:.8125rem;color:var(--kf-color-text-muted)}.kf-stat-tile__cta-action{margin-top:var(--kf-space-xs);font-size:.8125rem;font-weight:600}\n"] }]
|
|
5664
|
+
}], 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"] }] } });
|
|
5333
5665
|
|
|
5334
5666
|
/**
|
|
5335
5667
|
* Pill con borde, en mayúsculas y con letter-spacing, pensada para indicadores
|
|
@@ -5693,6 +6025,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
5693
6025
|
}, template: "<!--\n El grid vive en un div interno y no en el `:host`: el host es el CONTENEDOR\n de consulta (`container-type: inline-size`), y una `@container` dentro de\n su propia hoja medir\u00EDa el contenedor de m\u00E1s arriba, no a \u00E9l mismo.\n-->\n<div class=\"kf-tile-grid\">\n <ng-content />\n</div>\n", styles: [":host{display:block;container-type:inline-size;container-name:kf-tile-grid;min-width:0}.kf-tile-grid{display:grid;gap:var(--kf-space-sm);align-items:stretch}:host(.kf-tile-grid--1) .kf-tile-grid{grid-template-columns:minmax(0,1fr)}:host(.kf-tile-grid--2) .kf-tile-grid{grid-template-columns:repeat(2,minmax(0,1fr))}:host(.kf-tile-grid--3) .kf-tile-grid{grid-template-columns:repeat(3,minmax(0,1fr))}:host(.kf-tile-grid--4) .kf-tile-grid{grid-template-columns:repeat(4,minmax(0,1fr))}:host(.kf-tile-grid--5) .kf-tile-grid{grid-template-columns:repeat(5,minmax(0,1fr))}:host(.kf-tile-grid--6) .kf-tile-grid{grid-template-columns:repeat(6,minmax(0,1fr))}@container kf-tile-grid (max-width: 620px){:host(.kf-tile-grid--3) .kf-tile-grid,:host(.kf-tile-grid--4) .kf-tile-grid,:host(.kf-tile-grid--5) .kf-tile-grid,:host(.kf-tile-grid--6) .kf-tile-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@container kf-tile-grid (max-width: 380px){:host(.kf-tile-grid--2) .kf-tile-grid,:host(.kf-tile-grid--3) .kf-tile-grid,:host(.kf-tile-grid--4) .kf-tile-grid,:host(.kf-tile-grid--5) .kf-tile-grid,:host(.kf-tile-grid--6) .kf-tile-grid{grid-template-columns:minmax(0,1fr)}}\n"] }]
|
|
5694
6026
|
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
|
|
5695
6027
|
|
|
6028
|
+
const SKELETON_COUNT = 8;
|
|
6029
|
+
/**
|
|
6030
|
+
* Grilla de horarios seleccionables con semántica de radiogroup: un solo tab
|
|
6031
|
+
* stop, las flechas mueven y seleccionan (saltando los deshabilitados) y
|
|
6032
|
+
* Home/End van al primer/último horario habilitado.
|
|
6033
|
+
*
|
|
6034
|
+
* Si algún horario declara `group`, se rinde un subgrupo con etiqueta por
|
|
6035
|
+
* cada grupo distinto; si no, una sola grilla plana.
|
|
6036
|
+
*
|
|
6037
|
+
* <kf-time-slot-picker
|
|
6038
|
+
* ariaLabel="Horario"
|
|
6039
|
+
* [slots]="[{ value: '09:00', group: 'Mañana' }, { value: '15:30', group: 'Tarde', disabled: true }]"
|
|
6040
|
+
* [(value)]="time"
|
|
6041
|
+
* [loading]="loadingSlots()"
|
|
6042
|
+
* />
|
|
6043
|
+
*/
|
|
6044
|
+
class TimeSlotPicker {
|
|
6045
|
+
static nextId = 0;
|
|
6046
|
+
slots = input.required(/* @ts-ignore */
|
|
6047
|
+
...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
|
|
6048
|
+
value = model(null, /* @ts-ignore */
|
|
6049
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
6050
|
+
ariaLabel = input.required(/* @ts-ignore */
|
|
6051
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
6052
|
+
/** Muestra chips de carga en lugar de los horarios. */
|
|
6053
|
+
loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
6054
|
+
emptyLabel = input('No hay horarios disponibles', /* @ts-ignore */
|
|
6055
|
+
...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
|
|
6056
|
+
host = inject(ElementRef);
|
|
6057
|
+
idPrefix = `kf-time-slot-picker-${TimeSlotPicker.nextId++}`;
|
|
6058
|
+
skeletons = Array.from({ length: SKELETON_COUNT }, (_, index) => index);
|
|
6059
|
+
groups = computed(() => {
|
|
6060
|
+
const slots = this.slots();
|
|
6061
|
+
if (!slots.some((slot) => slot.group)) {
|
|
6062
|
+
return [{ id: `${this.idPrefix}-group-0`, label: null, slots }];
|
|
6063
|
+
}
|
|
6064
|
+
const byGroup = new Map();
|
|
6065
|
+
for (const slot of slots) {
|
|
6066
|
+
const key = slot.group ?? '';
|
|
6067
|
+
byGroup.set(key, [...(byGroup.get(key) ?? []), slot]);
|
|
6068
|
+
}
|
|
6069
|
+
return [...byGroup].map(([label, groupSlots], index) => ({
|
|
6070
|
+
id: `${this.idPrefix}-group-${index}`,
|
|
6071
|
+
label: label || null,
|
|
6072
|
+
slots: groupSlots,
|
|
6073
|
+
}));
|
|
6074
|
+
}, /* @ts-ignore */
|
|
6075
|
+
...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
6076
|
+
/** Valores habilitados en orden visual — la secuencia de navegación por teclado. */
|
|
6077
|
+
enabledValues = computed(() => this.groups()
|
|
6078
|
+
.flatMap((group) => group.slots)
|
|
6079
|
+
.filter((slot) => !slot.disabled)
|
|
6080
|
+
.map((slot) => slot.value), /* @ts-ignore */
|
|
6081
|
+
...(ngDevMode ? [{ debugName: "enabledValues" }] : /* istanbul ignore next */ []));
|
|
6082
|
+
/** El único chip con `tabindex="0"` (roving tabindex). */
|
|
6083
|
+
tabStop = computed(() => {
|
|
6084
|
+
const values = this.enabledValues();
|
|
6085
|
+
const value = this.value();
|
|
6086
|
+
return value !== null && values.includes(value) ? value : (values[0] ?? null);
|
|
6087
|
+
}, /* @ts-ignore */
|
|
6088
|
+
...(ngDevMode ? [{ debugName: "tabStop" }] : /* istanbul ignore next */ []));
|
|
6089
|
+
select(slot) {
|
|
6090
|
+
if (slot.disabled || this.loading() || slot.value === this.value()) {
|
|
6091
|
+
return;
|
|
6092
|
+
}
|
|
6093
|
+
this.value.set(slot.value);
|
|
6094
|
+
}
|
|
6095
|
+
onKeydown(event, current) {
|
|
6096
|
+
const values = this.enabledValues();
|
|
6097
|
+
const index = values.indexOf(current);
|
|
6098
|
+
if (index === -1) {
|
|
6099
|
+
return;
|
|
6100
|
+
}
|
|
6101
|
+
let nextIndex;
|
|
6102
|
+
switch (event.key) {
|
|
6103
|
+
case 'ArrowRight':
|
|
6104
|
+
case 'ArrowDown':
|
|
6105
|
+
nextIndex = (index + 1) % values.length;
|
|
6106
|
+
break;
|
|
6107
|
+
case 'ArrowLeft':
|
|
6108
|
+
case 'ArrowUp':
|
|
6109
|
+
nextIndex = (index - 1 + values.length) % values.length;
|
|
6110
|
+
break;
|
|
6111
|
+
case 'Home':
|
|
6112
|
+
nextIndex = 0;
|
|
6113
|
+
break;
|
|
6114
|
+
case 'End':
|
|
6115
|
+
nextIndex = values.length - 1;
|
|
6116
|
+
break;
|
|
6117
|
+
default:
|
|
6118
|
+
return;
|
|
6119
|
+
}
|
|
6120
|
+
event.preventDefault();
|
|
6121
|
+
const next = values[nextIndex];
|
|
6122
|
+
this.value.set(next);
|
|
6123
|
+
// Se busca por dataset, no por id ni selector: los valores de horario son strings arbitrarios.
|
|
6124
|
+
Array.from(this.host.nativeElement.querySelectorAll('[data-value]'))
|
|
6125
|
+
.find((element) => element.dataset['value'] === next)
|
|
6126
|
+
?.focus();
|
|
6127
|
+
}
|
|
6128
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: TimeSlotPicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6129
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: TimeSlotPicker, isStandalone: true, selector: "kf-time-slot-picker", inputs: { slots: { classPropertyName: "slots", publicName: "slots", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "<div class=\"kf-time-slot-picker\" [attr.aria-busy]=\"loading() || null\">\n @if (loading()) {\n <div class=\"kf-time-slot-picker__grid\" aria-hidden=\"true\">\n @for (item of skeletons; track item) {\n <kf-skeleton variant=\"rect\" height=\"44px\" />\n }\n </div>\n } @else if (slots().length === 0) {\n <kf-text as=\"p\" variant=\"body-muted\">{{ emptyLabel() }}</kf-text>\n } @else {\n <div class=\"kf-time-slot-picker__groups\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel()\">\n @for (group of groups(); track group.id) {\n <div\n class=\"kf-time-slot-picker__group\"\n [attr.role]=\"group.label ? 'group' : null\"\n [attr.aria-labelledby]=\"group.label ? group.id : null\"\n >\n @if (group.label) {\n <span class=\"kf-time-slot-picker__group-label kf-overline-text\" [id]=\"group.id\">{{\n group.label\n }}</span>\n }\n <div class=\"kf-time-slot-picker__grid\">\n @for (slot of group.slots; track slot.value) {\n <button\n type=\"button\"\n role=\"radio\"\n class=\"kf-time-slot-picker__slot\"\n [class.kf-time-slot-picker__slot--selected]=\"slot.value === value()\"\n [disabled]=\"slot.disabled\"\n [attr.aria-checked]=\"slot.value === value()\"\n [attr.tabindex]=\"slot.value === tabStop() ? 0 : -1\"\n [attr.data-value]=\"slot.value\"\n (click)=\"select(slot)\"\n (keydown)=\"onKeydown($event, slot.value)\"\n >\n {{ slot.label ?? slot.value }}\n </button>\n }\n </div>\n </div>\n }\n </div>\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)}:host{display:block}.kf-time-slot-picker__groups{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-time-slot-picker__group{display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-time-slot-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:var(--kf-space-sm)}.kf-time-slot-picker__slot{min-height:44px;padding:0 var(--kf-space-sm);box-sizing:border-box;border:1.5px solid var(--kf-color-border);border-radius:var(--kf-radius-md);background:var(--kf-color-white);font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);font-variant-numeric:tabular-nums;color:var(--kf-color-ink);cursor:pointer;transition:background-color .14s,border-color .14s,color .14s}.kf-time-slot-picker__slot:hover:not(:disabled):not(.kf-time-slot-picker__slot--selected){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}.kf-time-slot-picker__slot:focus-visible{outline:2px solid var(--kf-color-primary);outline-offset:2px}.kf-time-slot-picker__slot--selected{border-color:var(--kf-color-primary);background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-time-slot-picker__slot:disabled{background:var(--kf-color-surface);color:var(--kf-color-text-muted);font-weight:var(--kf-font-weight-body);text-decoration:line-through;cursor:not-allowed}@media(prefers-reduced-motion:reduce){.kf-time-slot-picker__slot{transition:none}}\n"], dependencies: [{ kind: "component", type: Skeleton, selector: "kf-skeleton", inputs: ["variant", "width", "height"] }, { kind: "component", type: Text, selector: "kf-text", inputs: ["as", "variant", "tone"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6130
|
+
}
|
|
6131
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: TimeSlotPicker, decorators: [{
|
|
6132
|
+
type: Component,
|
|
6133
|
+
args: [{ selector: 'kf-time-slot-picker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [Skeleton, Text], template: "<div class=\"kf-time-slot-picker\" [attr.aria-busy]=\"loading() || null\">\n @if (loading()) {\n <div class=\"kf-time-slot-picker__grid\" aria-hidden=\"true\">\n @for (item of skeletons; track item) {\n <kf-skeleton variant=\"rect\" height=\"44px\" />\n }\n </div>\n } @else if (slots().length === 0) {\n <kf-text as=\"p\" variant=\"body-muted\">{{ emptyLabel() }}</kf-text>\n } @else {\n <div class=\"kf-time-slot-picker__groups\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel()\">\n @for (group of groups(); track group.id) {\n <div\n class=\"kf-time-slot-picker__group\"\n [attr.role]=\"group.label ? 'group' : null\"\n [attr.aria-labelledby]=\"group.label ? group.id : null\"\n >\n @if (group.label) {\n <span class=\"kf-time-slot-picker__group-label kf-overline-text\" [id]=\"group.id\">{{\n group.label\n }}</span>\n }\n <div class=\"kf-time-slot-picker__grid\">\n @for (slot of group.slots; track slot.value) {\n <button\n type=\"button\"\n role=\"radio\"\n class=\"kf-time-slot-picker__slot\"\n [class.kf-time-slot-picker__slot--selected]=\"slot.value === value()\"\n [disabled]=\"slot.disabled\"\n [attr.aria-checked]=\"slot.value === value()\"\n [attr.tabindex]=\"slot.value === tabStop() ? 0 : -1\"\n [attr.data-value]=\"slot.value\"\n (click)=\"select(slot)\"\n (keydown)=\"onKeydown($event, slot.value)\"\n >\n {{ slot.label ?? slot.value }}\n </button>\n }\n </div>\n </div>\n }\n </div>\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)}:host{display:block}.kf-time-slot-picker__groups{display:flex;flex-direction:column;gap:var(--kf-space-md)}.kf-time-slot-picker__group{display:flex;flex-direction:column;gap:var(--kf-space-sm)}.kf-time-slot-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:var(--kf-space-sm)}.kf-time-slot-picker__slot{min-height:44px;padding:0 var(--kf-space-sm);box-sizing:border-box;border:1.5px solid var(--kf-color-border);border-radius:var(--kf-radius-md);background:var(--kf-color-white);font:inherit;font-size:var(--kf-font-size-body-sm);font-weight:var(--kf-font-weight-medium);font-variant-numeric:tabular-nums;color:var(--kf-color-ink);cursor:pointer;transition:background-color .14s,border-color .14s,color .14s}.kf-time-slot-picker__slot:hover:not(:disabled):not(.kf-time-slot-picker__slot--selected){border-color:var(--kf-color-border-strong);background:var(--kf-color-primary-soft)}.kf-time-slot-picker__slot:focus-visible{outline:2px solid var(--kf-color-primary);outline-offset:2px}.kf-time-slot-picker__slot--selected{border-color:var(--kf-color-primary);background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-time-slot-picker__slot:disabled{background:var(--kf-color-surface);color:var(--kf-color-text-muted);font-weight:var(--kf-font-weight-body);text-decoration:line-through;cursor:not-allowed}@media(prefers-reduced-motion:reduce){.kf-time-slot-picker__slot{transition:none}}\n"] }]
|
|
6134
|
+
}], propDecorators: { slots: [{ type: i0.Input, args: [{ isSignal: true, alias: "slots", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }] } });
|
|
6135
|
+
|
|
5696
6136
|
/** Fixed icon per tone (page 20 of the design system) — not configurable per call. */
|
|
5697
6137
|
const TOAST_ICON = {
|
|
5698
6138
|
success: 'check-circle',
|
|
@@ -5902,5 +6342,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
5902
6342
|
* Generated bundle index. Do not edit.
|
|
5903
6343
|
*/
|
|
5904
6344
|
|
|
5905
|
-
export { ActionTile, AdminBadge, Alert, AlertRow, Avatar, Badge, Breadcrumb, BucketProgress, Button, Card, Carousel, CarouselSlide, Checkbox, Chip, Collapsible, ContactPopover, ContentSlot, ContentState, ContentViewer, DEFAULT_PAGE_SIZE_OPTIONS, DataTable, Divider, DocumentRow, Drawer, Dropdown, DropdownItem, DropdownPanel, EmptyState, EventTimeline, FeatureCard, Field, FieldLabel, Filter, FilterChips, FolderTabs, FolderTabsPanel, Footer, FormatInputDirective, Icon, Input, JourneyStepper, Link, MetricCard, Modal, MultiSelect, NoteBlock, PageHeader, Pagination, Panel, PortalHeader, Progress, PulseDot, RowActions, SectionHeader, SectionNav, SectionNavItem, SectionNavSubsection, Segmented, Select, SelectableCardGroup, SidebarShell, Skeleton, Spinner, StatCard, StatTile, StatusPill, Tabs, Text, Textarea, TileGrid, ToastHost, ToastService, TooltipDirective, ViewToggle, dataTableViewSignal };
|
|
6345
|
+
export { ActionTile, AdminBadge, Alert, AlertRow, Avatar, Badge, Breadcrumb, BucketProgress, Button, Calendar, Card, Carousel, CarouselSlide, Checkbox, Chip, Collapsible, ContactPopover, ContentSlot, ContentState, ContentViewer, DEFAULT_PAGE_SIZE_OPTIONS, DataTable, Divider, DocumentRow, Drawer, Dropdown, DropdownItem, DropdownPanel, EmptyState, EventTimeline, FeatureCard, Field, FieldLabel, Filter, FilterChips, FolderTabs, FolderTabsPanel, Footer, FormatInputDirective, Icon, Input, JourneyStepper, Link, MetricCard, Modal, MultiSelect, NoteBlock, PageHeader, Pagination, Panel, PortalHeader, Progress, PulseDot, RowActions, SectionHeader, SectionNav, SectionNavItem, SectionNavSubsection, Segmented, Select, SelectableCardGroup, SidebarShell, Skeleton, Spinner, StatCard, StatTile, StatusPill, Tabs, Text, Textarea, TileGrid, TimeSlotPicker, ToastHost, ToastService, TooltipDirective, ViewToggle, dataTableViewSignal };
|
|
5906
6346
|
//# sourceMappingURL=kaufmann-lab-ui-core.mjs.map
|