@kaufmann-lab/ui 0.1.3 → 0.1.8
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/fesm2022/kaufmann-lab-ui.mjs +622 -297
- package/fesm2022/kaufmann-lab-ui.mjs.map +1 -1
- package/package.json +2 -1
- package/src/tokens/base.css +20 -0
- package/types/kaufmann-lab-ui.d.ts +245 -72
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, inject, computed, effect, Component, booleanAttribute, model, output, numberAttribute, contentChildren, signal, DestroyRef, viewChild, forwardRef,
|
|
2
|
+
import { input, inject, computed, effect, Component, booleanAttribute, model, output, numberAttribute, contentChildren, signal, DestroyRef, viewChild, forwardRef, ViewContainerRef, HostListener, TemplateRef, contentChild, ElementRef, ChangeDetectionStrategy, afterRenderEffect, afterNextRender, Injectable } from '@angular/core';
|
|
3
3
|
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
5
|
+
import { Overlay } from '@angular/cdk/overlay';
|
|
6
|
+
import { TemplatePortal } from '@angular/cdk/portal';
|
|
5
7
|
|
|
6
8
|
/** Símbolo de trazo "activity" (grilla 24×24) — ver `icons/index.ts` para el registro completo. */
|
|
7
9
|
const activity = {
|
|
@@ -849,6 +851,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
849
851
|
}, styles: [":host{display:inline-flex;align-items:center;gap:var(--kf-space-xs);padding:var(--kf-space-xs) var(--kf-space-sm);border-radius:var(--kf-radius-pill);background:var(--kf-color-warning-soft);border:1px solid var(--kf-color-warning);color:var(--kf-color-warning-strong);font-size:.75rem;font-weight:700;letter-spacing:.02em;text-transform:uppercase;line-height:1}:host(.kf-admin-badge--inline){background:transparent;border-color:#e2b93b80;color:var(--kf-color-warning)}\n"] }]
|
|
850
852
|
}], propDecorators: { inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }] } });
|
|
851
853
|
|
|
854
|
+
/**
|
|
855
|
+
* Indicador de carga indeterminado: inline, dentro de un botón, o como único
|
|
856
|
+
* contenido de una sección mientras llega la data.
|
|
857
|
+
*
|
|
858
|
+
* Cuando se conoce la forma del contenido que viene, preferir `kf-skeleton`
|
|
859
|
+
* (dibuja la silueta). El spinner es para "algo está pasando" sin forma
|
|
860
|
+
* conocida — guardar, enviar, reintentar.
|
|
861
|
+
*
|
|
862
|
+
* Lleva `role="status"`, así que el lector de pantalla anuncia el `label`
|
|
863
|
+
* cuando aparece. Sin `label` cae en un texto accesible por defecto.
|
|
864
|
+
*
|
|
865
|
+
* <kf-spinner />
|
|
866
|
+
* <kf-spinner size="sm" label="Cargando…" />
|
|
867
|
+
* <kf-spinner onDark />
|
|
868
|
+
*/
|
|
869
|
+
class Spinner {
|
|
870
|
+
size = input('md', /* @ts-ignore */
|
|
871
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
872
|
+
/** Texto al lado del anillo. Vacío deja solo el anillo (y el texto para lectores). */
|
|
873
|
+
label = input('', /* @ts-ignore */
|
|
874
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
875
|
+
/** Invierte los colores para fondos oscuros. */
|
|
876
|
+
onDark = input(false, { ...(ngDevMode ? { debugName: "onDark" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
877
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Spinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
878
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Spinner, isStandalone: true, selector: "kf-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, onDark: { classPropertyName: "onDark", publicName: "onDark", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
879
|
+
<span class="kf-spinner" [class.kf-spinner--on-dark]="onDark()" role="status">
|
|
880
|
+
<span class="kf-spinner__ring" [class]="'kf-spinner__ring--' + size()"></span>
|
|
881
|
+
@if (label()) {
|
|
882
|
+
<span class="kf-spinner__label">{{ label() }}</span>
|
|
883
|
+
} @else {
|
|
884
|
+
<span class="kf-spinner__sr">Cargando</span>
|
|
885
|
+
}
|
|
886
|
+
</span>
|
|
887
|
+
`, isInline: true, styles: [":host{display:inline-block}.kf-spinner{display:inline-flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}.kf-spinner__ring{display:inline-block;flex:none;border-radius:var(--kf-radius-pill);border:2px solid var(--kf-color-border);border-top-color:var(--kf-color-primary);animation:kf-spinner-turn .7s linear infinite}.kf-spinner__ring--sm{width:16px;height:16px}.kf-spinner__ring--md{width:24px;height:24px;border-width:3px}.kf-spinner__ring--lg{width:32px;height:32px;border-width:3px}.kf-spinner__label{font-size:.875rem;color:var(--kf-color-text-muted)}.kf-spinner--on-dark .kf-spinner__ring{border-color:#ffffff47;border-top-color:var(--kf-color-white)}.kf-spinner--on-dark .kf-spinner__label{color:var(--kf-color-white)}@keyframes kf-spinner-turn{to{transform:rotate(360deg)}}.kf-spinner__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media(prefers-reduced-motion:reduce){.kf-spinner__ring{animation-duration:2s}}\n"] });
|
|
888
|
+
}
|
|
889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Spinner, decorators: [{
|
|
890
|
+
type: Component,
|
|
891
|
+
args: [{ selector: 'kf-spinner', template: `
|
|
892
|
+
<span class="kf-spinner" [class.kf-spinner--on-dark]="onDark()" role="status">
|
|
893
|
+
<span class="kf-spinner__ring" [class]="'kf-spinner__ring--' + size()"></span>
|
|
894
|
+
@if (label()) {
|
|
895
|
+
<span class="kf-spinner__label">{{ label() }}</span>
|
|
896
|
+
} @else {
|
|
897
|
+
<span class="kf-spinner__sr">Cargando</span>
|
|
898
|
+
}
|
|
899
|
+
</span>
|
|
900
|
+
`, styles: [":host{display:inline-block}.kf-spinner{display:inline-flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}.kf-spinner__ring{display:inline-block;flex:none;border-radius:var(--kf-radius-pill);border:2px solid var(--kf-color-border);border-top-color:var(--kf-color-primary);animation:kf-spinner-turn .7s linear infinite}.kf-spinner__ring--sm{width:16px;height:16px}.kf-spinner__ring--md{width:24px;height:24px;border-width:3px}.kf-spinner__ring--lg{width:32px;height:32px;border-width:3px}.kf-spinner__label{font-size:.875rem;color:var(--kf-color-text-muted)}.kf-spinner--on-dark .kf-spinner__ring{border-color:#ffffff47;border-top-color:var(--kf-color-white)}.kf-spinner--on-dark .kf-spinner__label{color:var(--kf-color-white)}@keyframes kf-spinner-turn{to{transform:rotate(360deg)}}.kf-spinner__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media(prefers-reduced-motion:reduce){.kf-spinner__ring{animation-duration:2s}}\n"] }]
|
|
901
|
+
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onDark: [{ type: i0.Input, args: [{ isSignal: true, alias: "onDark", required: false }] }] } });
|
|
902
|
+
|
|
852
903
|
/**
|
|
853
904
|
* Wraps a native `<button>`, so keyboard handling, focus and form submission
|
|
854
905
|
* keep working. The cost of the wrapper is forwarding `disabled` and `type` by
|
|
@@ -864,10 +915,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
864
915
|
*
|
|
865
916
|
* `(click)` is not forwarded — it bubbles from the inner button to the host.
|
|
866
917
|
*
|
|
918
|
+
* `loading` replaces the projected content with `kf-spinner` and forces
|
|
919
|
+
* `disabled` — for the common "Ingresando…"/"Enviando…" submit pattern,
|
|
920
|
+
* which before this prop existed as plain text swaps with no visual
|
|
921
|
+
* indicator (see `web-portal-latam-frontend`'s login submit buttons).
|
|
922
|
+
*
|
|
867
923
|
* <kf-button (click)="save()">Save</kf-button>
|
|
868
924
|
* <kf-button variant="ghost" disabled>Cancel</kf-button>
|
|
869
925
|
* <kf-button variant="danger" (click)="remove()">Delete</kf-button>
|
|
870
926
|
* <kf-button size="sm" icon="calendar" block>Reservar hora</kf-button>
|
|
927
|
+
* <kf-button type="submit" [loading]="submitting()">Ingresar</kf-button>
|
|
871
928
|
*/
|
|
872
929
|
class Button {
|
|
873
930
|
variant = input('primary', /* @ts-ignore */
|
|
@@ -883,11 +940,19 @@ class Button {
|
|
|
883
940
|
...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
884
941
|
/** Stretches the button to the full width of its container. */
|
|
885
942
|
block = input(false, { ...(ngDevMode ? { debugName: "block" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
943
|
+
/** Replaces the projected content with `kf-spinner` and forces `disabled`. */
|
|
944
|
+
loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
945
|
+
/** `ghost`/`outline` have no solid background — the default spinner ring already reads fine there. */
|
|
946
|
+
hasSolidFill = computed(() => {
|
|
947
|
+
const variant = this.variant();
|
|
948
|
+
return variant !== 'ghost' && variant !== 'outline';
|
|
949
|
+
}, /* @ts-ignore */
|
|
950
|
+
...(ngDevMode ? [{ debugName: "hasSolidFill" }] : /* istanbul ignore next */ []));
|
|
886
951
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
887
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Button, isStandalone: true, selector: "kf-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.block": "block() ? '' : null" } }, ngImport: i0, template: `
|
|
952
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Button, isStandalone: true, selector: "kf-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.block": "block() ? '' : null" } }, ngImport: i0, template: `
|
|
888
953
|
<button
|
|
889
954
|
[type]="type()"
|
|
890
|
-
[disabled]="disabled()"
|
|
955
|
+
[disabled]="disabled() || loading()"
|
|
891
956
|
[class.kf-button--secondary]="variant() === 'secondary'"
|
|
892
957
|
[class.kf-button--ghost]="variant() === 'ghost'"
|
|
893
958
|
[class.kf-button--outline]="variant() === 'outline'"
|
|
@@ -895,19 +960,27 @@ class Button {
|
|
|
895
960
|
[class.kf-button--sm]="size() === 'sm'"
|
|
896
961
|
[class.kf-button--lg]="size() === 'lg'"
|
|
897
962
|
>
|
|
898
|
-
@if (
|
|
899
|
-
<kf-
|
|
963
|
+
@if (loading()) {
|
|
964
|
+
<kf-spinner size="sm" [onDark]="hasSolidFill()" />
|
|
965
|
+
} @else {
|
|
966
|
+
@if (icon(); as iconName) {
|
|
967
|
+
<kf-icon
|
|
968
|
+
class="kf-button__icon"
|
|
969
|
+
[name]="iconName"
|
|
970
|
+
[size]="size() === 'lg' ? 'md' : 'sm'"
|
|
971
|
+
/>
|
|
972
|
+
}
|
|
973
|
+
<ng-content />
|
|
900
974
|
}
|
|
901
|
-
<ng-content />
|
|
902
975
|
</button>
|
|
903
|
-
`, isInline: true, styles: [":host{display:inline-block}:host([block]){display:block}button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);width:100%;font:inherit;font-weight:600;padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-primary);border-radius:var(--kf-radius-sm);background:var(--kf-color-primary);color:var(--kf-color-white);cursor:pointer;transition:background .14s,border-color .14s,color .14s}button:hover:not(:disabled){background:var(--kf-color-primary-hover);border-color:var(--kf-color-primary-hover)}button:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}button:disabled{opacity:.5;cursor:not-allowed}button.kf-button--secondary{border-color:var(--kf-color-secondary);background:var(--kf-color-secondary)}button.kf-button--secondary:hover:not(:disabled){background:var(--kf-color-secondary-hover);border-color:var(--kf-color-secondary-hover)}button.kf-button--ghost{background:transparent;border-color:transparent;color:var(--kf-color-primary)}button.kf-button--ghost:hover:not(:disabled){background:var(--kf-color-primary-soft)}button.kf-button--outline{background:transparent;border-color:var(--kf-color-border-strong);color:var(--kf-color-text)}button.kf-button--outline:hover:not(:disabled){background:var(--kf-color-surface);border-color:var(--kf-color-text-muted)}button.kf-button--danger{border-color:var(--kf-color-error);background:var(--kf-color-error)}button.kf-button--danger:hover:not(:disabled){background:var(--kf-color-error-hover);border-color:var(--kf-color-error-hover)}button.kf-button--sm{padding:6px var(--kf-space-sm);font-size:.85rem}button.kf-button--lg{padding:var(--kf-space-sm) var(--kf-space-lg);font-size:1.05rem}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size"] }] });
|
|
976
|
+
`, isInline: true, styles: [":host{display:inline-block}:host([block]){display:block}button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);width:100%;font:inherit;font-weight:600;padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-primary);border-radius:var(--kf-radius-sm);background:var(--kf-color-primary);color:var(--kf-color-white);cursor:pointer;transition:background .14s,border-color .14s,color .14s}button:hover:not(:disabled){background:var(--kf-color-primary-hover);border-color:var(--kf-color-primary-hover)}button:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}button:disabled{opacity:.5;cursor:not-allowed}button.kf-button--secondary{border-color:var(--kf-color-secondary);background:var(--kf-color-secondary)}button.kf-button--secondary:hover:not(:disabled){background:var(--kf-color-secondary-hover);border-color:var(--kf-color-secondary-hover)}button.kf-button--ghost{background:transparent;border-color:transparent;color:var(--kf-color-primary)}button.kf-button--ghost:hover:not(:disabled){background:var(--kf-color-primary-soft)}button.kf-button--outline{background:transparent;border-color:var(--kf-color-border-strong);color:var(--kf-color-text)}button.kf-button--outline:hover:not(:disabled){background:var(--kf-color-surface);border-color:var(--kf-color-text-muted)}button.kf-button--danger{border-color:var(--kf-color-error);background:var(--kf-color-error)}button.kf-button--danger:hover:not(:disabled){background:var(--kf-color-error-hover);border-color:var(--kf-color-error-hover)}button.kf-button--sm{padding:6px var(--kf-space-sm);font-size:.85rem}button.kf-button--lg{padding:var(--kf-space-sm) var(--kf-space-lg);font-size:1.05rem}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size"] }, { kind: "component", type: Spinner, selector: "kf-spinner", inputs: ["size", "label", "onDark"] }] });
|
|
904
977
|
}
|
|
905
978
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Button, decorators: [{
|
|
906
979
|
type: Component,
|
|
907
|
-
args: [{ selector: 'kf-button', imports: [Icon], template: `
|
|
980
|
+
args: [{ selector: 'kf-button', imports: [Icon, Spinner], template: `
|
|
908
981
|
<button
|
|
909
982
|
[type]="type()"
|
|
910
|
-
[disabled]="disabled()"
|
|
983
|
+
[disabled]="disabled() || loading()"
|
|
911
984
|
[class.kf-button--secondary]="variant() === 'secondary'"
|
|
912
985
|
[class.kf-button--ghost]="variant() === 'ghost'"
|
|
913
986
|
[class.kf-button--outline]="variant() === 'outline'"
|
|
@@ -915,15 +988,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
915
988
|
[class.kf-button--sm]="size() === 'sm'"
|
|
916
989
|
[class.kf-button--lg]="size() === 'lg'"
|
|
917
990
|
>
|
|
918
|
-
@if (
|
|
919
|
-
<kf-
|
|
991
|
+
@if (loading()) {
|
|
992
|
+
<kf-spinner size="sm" [onDark]="hasSolidFill()" />
|
|
993
|
+
} @else {
|
|
994
|
+
@if (icon(); as iconName) {
|
|
995
|
+
<kf-icon
|
|
996
|
+
class="kf-button__icon"
|
|
997
|
+
[name]="iconName"
|
|
998
|
+
[size]="size() === 'lg' ? 'md' : 'sm'"
|
|
999
|
+
/>
|
|
1000
|
+
}
|
|
1001
|
+
<ng-content />
|
|
920
1002
|
}
|
|
921
|
-
<ng-content />
|
|
922
1003
|
</button>
|
|
923
1004
|
`, host: {
|
|
924
1005
|
'[attr.block]': "block() ? '' : null",
|
|
925
1006
|
}, styles: [":host{display:inline-block}:host([block]){display:block}button{display:inline-flex;align-items:center;justify-content:center;gap:var(--kf-space-xs);width:100%;font:inherit;font-weight:600;padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-primary);border-radius:var(--kf-radius-sm);background:var(--kf-color-primary);color:var(--kf-color-white);cursor:pointer;transition:background .14s,border-color .14s,color .14s}button:hover:not(:disabled){background:var(--kf-color-primary-hover);border-color:var(--kf-color-primary-hover)}button:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}button:disabled{opacity:.5;cursor:not-allowed}button.kf-button--secondary{border-color:var(--kf-color-secondary);background:var(--kf-color-secondary)}button.kf-button--secondary:hover:not(:disabled){background:var(--kf-color-secondary-hover);border-color:var(--kf-color-secondary-hover)}button.kf-button--ghost{background:transparent;border-color:transparent;color:var(--kf-color-primary)}button.kf-button--ghost:hover:not(:disabled){background:var(--kf-color-primary-soft)}button.kf-button--outline{background:transparent;border-color:var(--kf-color-border-strong);color:var(--kf-color-text)}button.kf-button--outline:hover:not(:disabled){background:var(--kf-color-surface);border-color:var(--kf-color-text-muted)}button.kf-button--danger{border-color:var(--kf-color-error);background:var(--kf-color-error)}button.kf-button--danger:hover:not(:disabled){background:var(--kf-color-error-hover);border-color:var(--kf-color-error-hover)}button.kf-button--sm{padding:6px var(--kf-space-sm);font-size:.85rem}button.kf-button--lg{padding:var(--kf-space-sm) var(--kf-space-lg);font-size:1.05rem}\n"] }]
|
|
926
|
-
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }] } });
|
|
1007
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
927
1008
|
|
|
928
1009
|
/**
|
|
929
1010
|
* Banner contextual que vive dentro del flujo: validaciones, avisos de
|
|
@@ -1463,7 +1544,7 @@ class Carousel {
|
|
|
1463
1544
|
aria-label="Slide anterior"
|
|
1464
1545
|
(click)="previous()"
|
|
1465
1546
|
>
|
|
1466
|
-
|
|
1547
|
+
<kf-icon name="chevron-left" size="sm" />
|
|
1467
1548
|
</button>
|
|
1468
1549
|
<button
|
|
1469
1550
|
type="button"
|
|
@@ -1471,16 +1552,16 @@ class Carousel {
|
|
|
1471
1552
|
aria-label="Slide siguiente"
|
|
1472
1553
|
(click)="next()"
|
|
1473
1554
|
>
|
|
1474
|
-
|
|
1555
|
+
<kf-icon name="chevron-right" size="sm" />
|
|
1475
1556
|
</button>
|
|
1476
1557
|
</div>
|
|
1477
1558
|
}
|
|
1478
1559
|
</div>
|
|
1479
|
-
`, isInline: true, styles: [":host{display:block;height:100%;font-family:var(--kf-font-body)}.kf-carousel{position:relative;height:100%}.kf-carousel__viewport{height:100%;overflow:hidden;border-radius:var(--kf-radius-md)}.kf-carousel__track{display:flex;height:100%;transition:transform .32s ease}.kf-carousel__controls{position:absolute;z-index:2;right:var(--kf-space-sm);bottom:var(--kf-space-sm);display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-carousel__arrow{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:1px solid rgb(255 255 255 / 22%);border-radius:var(--kf-radius-pill);background:#ffffff1f;color:#fff;
|
|
1560
|
+
`, isInline: true, styles: [":host{display:block;height:100%;font-family:var(--kf-font-body)}.kf-carousel{position:relative;height:100%}.kf-carousel__viewport{height:100%;overflow:hidden;border-radius:var(--kf-radius-md)}.kf-carousel__track{display:flex;height:100%;transition:transform .32s ease}.kf-carousel__controls{position:absolute;z-index:2;right:var(--kf-space-sm);bottom:var(--kf-space-sm);display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-carousel__arrow{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:1px solid rgb(255 255 255 / 22%);border-radius:var(--kf-radius-pill);background:#ffffff1f;color:#fff;cursor:pointer;transition:background .14s}.kf-carousel__arrow:hover{background:#ffffff3d}.kf-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 2px #fff9}.kf-carousel__dots{display:flex;gap:var(--kf-space-xs)}.kf-carousel__dot{width:7px;height:7px;padding:0;border:none;border-radius:var(--kf-radius-pill);background:#ffffff59;cursor:pointer;transition:background .14s,width .14s}.kf-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 2px #fff9}.kf-carousel__dot--active{width:1.125rem;border-radius:var(--kf-radius-xs);background:#fff}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size"] }] });
|
|
1480
1561
|
}
|
|
1481
1562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Carousel, decorators: [{
|
|
1482
1563
|
type: Component,
|
|
1483
|
-
args: [{ selector: 'kf-carousel', template: `
|
|
1564
|
+
args: [{ selector: 'kf-carousel', imports: [Icon], template: `
|
|
1484
1565
|
<div
|
|
1485
1566
|
class="kf-carousel"
|
|
1486
1567
|
(mouseenter)="pauseAutoplay()"
|
|
@@ -1518,7 +1599,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1518
1599
|
aria-label="Slide anterior"
|
|
1519
1600
|
(click)="previous()"
|
|
1520
1601
|
>
|
|
1521
|
-
|
|
1602
|
+
<kf-icon name="chevron-left" size="sm" />
|
|
1522
1603
|
</button>
|
|
1523
1604
|
<button
|
|
1524
1605
|
type="button"
|
|
@@ -1526,12 +1607,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1526
1607
|
aria-label="Slide siguiente"
|
|
1527
1608
|
(click)="next()"
|
|
1528
1609
|
>
|
|
1529
|
-
|
|
1610
|
+
<kf-icon name="chevron-right" size="sm" />
|
|
1530
1611
|
</button>
|
|
1531
1612
|
</div>
|
|
1532
1613
|
}
|
|
1533
1614
|
</div>
|
|
1534
|
-
`, styles: [":host{display:block;height:100%;font-family:var(--kf-font-body)}.kf-carousel{position:relative;height:100%}.kf-carousel__viewport{height:100%;overflow:hidden;border-radius:var(--kf-radius-md)}.kf-carousel__track{display:flex;height:100%;transition:transform .32s ease}.kf-carousel__controls{position:absolute;z-index:2;right:var(--kf-space-sm);bottom:var(--kf-space-sm);display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-carousel__arrow{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:1px solid rgb(255 255 255 / 22%);border-radius:var(--kf-radius-pill);background:#ffffff1f;color:#fff;
|
|
1615
|
+
`, styles: [":host{display:block;height:100%;font-family:var(--kf-font-body)}.kf-carousel{position:relative;height:100%}.kf-carousel__viewport{height:100%;overflow:hidden;border-radius:var(--kf-radius-md)}.kf-carousel__track{display:flex;height:100%;transition:transform .32s ease}.kf-carousel__controls{position:absolute;z-index:2;right:var(--kf-space-sm);bottom:var(--kf-space-sm);display:flex;align-items:center;gap:var(--kf-space-sm)}.kf-carousel__arrow{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:1px solid rgb(255 255 255 / 22%);border-radius:var(--kf-radius-pill);background:#ffffff1f;color:#fff;cursor:pointer;transition:background .14s}.kf-carousel__arrow:hover{background:#ffffff3d}.kf-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 2px #fff9}.kf-carousel__dots{display:flex;gap:var(--kf-space-xs)}.kf-carousel__dot{width:7px;height:7px;padding:0;border:none;border-radius:var(--kf-radius-pill);background:#ffffff59;cursor:pointer;transition:background .14s,width .14s}.kf-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 2px #fff9}.kf-carousel__dot--active{width:1.125rem;border-radius:var(--kf-radius-xs);background:#fff}\n"] }]
|
|
1535
1616
|
}], propDecorators: { autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], indexChange: [{ type: i0.Output, args: ["indexChange"] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CarouselSlide), { isSignal: true }] }] } });
|
|
1536
1617
|
|
|
1537
1618
|
/**
|
|
@@ -1700,10 +1781,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1700
1781
|
}], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }] } });
|
|
1701
1782
|
|
|
1702
1783
|
/**
|
|
1703
|
-
*
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1706
|
-
*
|
|
1784
|
+
* Separador visual simple entre bloques de contenido. `orientation`
|
|
1785
|
+
* controla si es una línea horizontal (para separar secciones apiladas) o
|
|
1786
|
+
* vertical (para separar elementos en una fila, ej. acciones en una toolbar,
|
|
1787
|
+
* o las columnas de metadata en `kf-company-selector`).
|
|
1788
|
+
*
|
|
1789
|
+
* En `vertical`, el divisor necesita una altura del contexto donde vive —
|
|
1790
|
+
* `:host { align-self: stretch }` lo hace ocupar la altura del contenedor
|
|
1791
|
+
* flex/grid padre sin que el consumidor tenga que fijarla a mano. `flex:
|
|
1792
|
+
* none` evita que el propio divisor se achique a 0 dentro de ese contenedor
|
|
1793
|
+
* flex cuando hay contenido hermano compitiendo por espacio.
|
|
1707
1794
|
*
|
|
1708
1795
|
* <kf-divider />
|
|
1709
1796
|
* <kf-divider orientation="vertical" />
|
|
@@ -1712,15 +1799,15 @@ class Divider {
|
|
|
1712
1799
|
orientation = input('horizontal', /* @ts-ignore */
|
|
1713
1800
|
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
1714
1801
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Divider, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1715
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: Divider, isStandalone: true, selector: "kf-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "attr.
|
|
1802
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: Divider, isStandalone: true, selector: "kf-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "separator" }, properties: { "attr.orientation": "orientation()", "attr.aria-orientation": "orientation()" } }, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;flex:none;border:none;background:var(--kf-color-border)}:host,:host([orientation=\"horizontal\"]){width:100%;height:1px}:host([orientation=\"vertical\"]){align-self:stretch;width:1px;height:auto}\n"] });
|
|
1716
1803
|
}
|
|
1717
1804
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Divider, decorators: [{
|
|
1718
1805
|
type: Component,
|
|
1719
1806
|
args: [{ selector: 'kf-divider', template: '', host: {
|
|
1720
1807
|
role: 'separator',
|
|
1808
|
+
'[attr.orientation]': 'orientation()',
|
|
1721
1809
|
'[attr.aria-orientation]': 'orientation()',
|
|
1722
|
-
|
|
1723
|
-
}, styles: [":host{display:block;flex:none;background:var(--kf-color-border)}:host(.kf-divider--vertical){width:1px;align-self:stretch}:host(:not(.kf-divider--vertical)){width:100%;height:1px}\n"] }]
|
|
1810
|
+
}, styles: [":host{display:block;flex:none;border:none;background:var(--kf-color-border)}:host,:host([orientation=\"horizontal\"]){width:100%;height:1px}:host([orientation=\"vertical\"]){align-self:stretch;width:1px;height:auto}\n"] }]
|
|
1724
1811
|
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
|
|
1725
1812
|
|
|
1726
1813
|
/**
|
|
@@ -1771,23 +1858,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1771
1858
|
`, styles: [":host{display:contents}.kf-field-label{font-family:var(--kf-font-title);font-size:.75rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--kf-color-text-muted)}.kf-field-label__required{color:var(--kf-color-error);margin-inline-start:2px}\n"] }]
|
|
1772
1859
|
}], propDecorators: { for: [{ type: i0.Input, args: [{ isSignal: true, alias: "for", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }] } });
|
|
1773
1860
|
|
|
1774
|
-
let nextId$
|
|
1861
|
+
let nextId$1 = 0;
|
|
1775
1862
|
/**
|
|
1776
1863
|
* Dropdown de selección simple con panel propio — NUNCA usa el `<select>`
|
|
1777
1864
|
* nativo del navegador. Un `<select>` real siempre delega el popup de
|
|
1778
1865
|
* opciones al sistema operativo, y ningún CSS puede controlar cómo se ve
|
|
1779
|
-
* ese popup
|
|
1780
|
-
* este componente reutiliza el patrón completo: trigger + panel flotante
|
|
1781
|
-
* propio, cerrado con click-afuera y Escape).
|
|
1866
|
+
* ese popup.
|
|
1782
1867
|
*
|
|
1783
|
-
*
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1786
|
-
*
|
|
1787
|
-
* `
|
|
1868
|
+
* Hasta la `0.1.5` existía además `kf-select-menu`, un segundo componente
|
|
1869
|
+
* prácticamente idéntico (mismo trigger, mismo panel, mismo CSS) que solo
|
|
1870
|
+
* se diferenciaba en aceptar `options` únicamente como `{ value, label }[]`
|
|
1871
|
+
* (sin el atajo `string[]` que `Select` ya tenía). Se fusionaron en este
|
|
1872
|
+
* componente en la `0.2.0` — mantener dos componentes con la misma
|
|
1873
|
+
* interacción y el mismo aspecto visual, cuya única diferencia real era la
|
|
1874
|
+
* forma de un input, no se sostenía como dos piezas separadas del catálogo.
|
|
1875
|
+
*
|
|
1876
|
+
* El panel flotante se conecta al trigger vía `@angular/cdk/overlay` — el
|
|
1877
|
+
* mismo mecanismo que `Dropdown` (ver `../dropdown/Dropdown.ts`).
|
|
1788
1878
|
*
|
|
1789
1879
|
* <kf-select label="Sede" [options]="['Lima', 'Arequipa', 'Trujillo']" placeholder="Selecciona…" />
|
|
1790
1880
|
* <kf-select [options]="[{ value: 'pe', label: 'Perú' }]" (valueChange)="onCountry($event)" />
|
|
1881
|
+
*
|
|
1882
|
+
* Pendiente: el prop `icon` de otros componentes del design system requiere
|
|
1883
|
+
* un componente Icon / sprite SVG que esta librería todavía no tiene — este
|
|
1884
|
+
* componente no usa iconos, así que no aplica acá.
|
|
1791
1885
|
*/
|
|
1792
1886
|
class Select {
|
|
1793
1887
|
label = input(/* @ts-ignore */
|
|
@@ -1800,7 +1894,7 @@ class Select {
|
|
|
1800
1894
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1801
1895
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1802
1896
|
valueChange = output();
|
|
1803
|
-
instanceId = `kf-select-${nextId$
|
|
1897
|
+
instanceId = `kf-select-${nextId$1++}`;
|
|
1804
1898
|
triggerId = `${this.instanceId}-trigger`;
|
|
1805
1899
|
listboxId = `${this.instanceId}-listbox`;
|
|
1806
1900
|
isOpen = signal(false, /* @ts-ignore */
|
|
@@ -1810,7 +1904,34 @@ class Select {
|
|
|
1810
1904
|
...(ngDevMode ? [{ debugName: "normalizedOptions" }] : /* istanbul ignore next */ []));
|
|
1811
1905
|
selectedOption = computed(() => this.normalizedOptions().find((option) => option.value === this.value()), /* @ts-ignore */
|
|
1812
1906
|
...(ngDevMode ? [{ debugName: "selectedOption" }] : /* istanbul ignore next */ []));
|
|
1813
|
-
|
|
1907
|
+
triggerRef = viewChild.required('trigger', /* @ts-ignore */
|
|
1908
|
+
...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
|
|
1909
|
+
panelTemplate = viewChild.required('panelTemplate', /* @ts-ignore */
|
|
1910
|
+
...(ngDevMode ? [{ debugName: "panelTemplate" }] : /* istanbul ignore next */ []));
|
|
1911
|
+
overlayService = inject(Overlay);
|
|
1912
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
1913
|
+
destroyRef = inject(DestroyRef);
|
|
1914
|
+
overlayRef = null;
|
|
1915
|
+
constructor() {
|
|
1916
|
+
effect(() => {
|
|
1917
|
+
if (this.isOpen()) {
|
|
1918
|
+
this.attach();
|
|
1919
|
+
}
|
|
1920
|
+
else {
|
|
1921
|
+
this.detach();
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
this.destroyRef.onDestroy(() => this.overlayRef?.dispose());
|
|
1925
|
+
}
|
|
1926
|
+
/**
|
|
1927
|
+
* Respaldo de `overlayRef.keydownEvents()`: ese observable del CDK solo ve
|
|
1928
|
+
* teclas presionadas con el foco DENTRO del pane del overlay. Si el foco
|
|
1929
|
+
* sigue en el trigger (o en cualquier otro lado de la página) mientras el
|
|
1930
|
+
* panel está abierto, `keydownEvents()` nunca dispara.
|
|
1931
|
+
*/
|
|
1932
|
+
onDocumentEscape() {
|
|
1933
|
+
this.isOpen.set(false);
|
|
1934
|
+
}
|
|
1814
1935
|
toggle() {
|
|
1815
1936
|
if (this.disabled()) {
|
|
1816
1937
|
return;
|
|
@@ -1823,16 +1944,53 @@ class Select {
|
|
|
1823
1944
|
this.valueChange.emit(option.value);
|
|
1824
1945
|
}
|
|
1825
1946
|
}
|
|
1826
|
-
|
|
1827
|
-
if (this.
|
|
1828
|
-
|
|
1947
|
+
attach() {
|
|
1948
|
+
if (this.overlayRef?.hasAttached()) {
|
|
1949
|
+
return;
|
|
1829
1950
|
}
|
|
1951
|
+
const overlayRef = this.getOrCreateOverlayRef();
|
|
1952
|
+
// Se remide el ancho del trigger en cada apertura, no solo la primera —
|
|
1953
|
+
// ver la misma nota en SelectMenu: cachear el ancho en la creación del
|
|
1954
|
+
// overlay lo deja desincronizado si el trigger cambia de tamaño entre
|
|
1955
|
+
// una apertura y la siguiente.
|
|
1956
|
+
overlayRef.updateSize({ width: this.triggerRef().nativeElement.getBoundingClientRect().width });
|
|
1957
|
+
const portal = new TemplatePortal(this.panelTemplate(), this.viewContainerRef);
|
|
1958
|
+
overlayRef.attach(portal);
|
|
1959
|
+
overlayRef.outsidePointerEvents().subscribe(() => this.isOpen.set(false));
|
|
1960
|
+
overlayRef.keydownEvents().subscribe((event) => {
|
|
1961
|
+
if (event.key === 'Escape') {
|
|
1962
|
+
this.isOpen.set(false);
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1830
1965
|
}
|
|
1831
|
-
|
|
1832
|
-
this.
|
|
1966
|
+
detach() {
|
|
1967
|
+
this.overlayRef?.detach();
|
|
1968
|
+
}
|
|
1969
|
+
getOrCreateOverlayRef() {
|
|
1970
|
+
if (this.overlayRef) {
|
|
1971
|
+
return this.overlayRef;
|
|
1972
|
+
}
|
|
1973
|
+
const positionStrategy = this.overlayService
|
|
1974
|
+
.position()
|
|
1975
|
+
.flexibleConnectedTo(this.triggerRef())
|
|
1976
|
+
.withPositions([
|
|
1977
|
+
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
|
|
1978
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
|
|
1979
|
+
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
|
|
1980
|
+
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -4 },
|
|
1981
|
+
])
|
|
1982
|
+
.withViewportMargin(8)
|
|
1983
|
+
.withPush(true);
|
|
1984
|
+
this.overlayRef = this.overlayService.create({
|
|
1985
|
+
positionStrategy,
|
|
1986
|
+
scrollStrategy: this.overlayService.scrollStrategies.reposition(),
|
|
1987
|
+
width: this.triggerRef().nativeElement.getBoundingClientRect().width,
|
|
1988
|
+
maxWidth: '90vw',
|
|
1989
|
+
});
|
|
1990
|
+
return this.overlayRef;
|
|
1833
1991
|
}
|
|
1834
1992
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1835
|
-
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 } }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:
|
|
1993
|
+
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 } }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1836
1994
|
@if (label()) {
|
|
1837
1995
|
<kf-field-label [for]="triggerId">{{ label() }}</kf-field-label>
|
|
1838
1996
|
}
|
|
@@ -1857,7 +2015,7 @@ class Select {
|
|
|
1857
2015
|
aria-hidden="true"
|
|
1858
2016
|
></span>
|
|
1859
2017
|
</button>
|
|
1860
|
-
|
|
2018
|
+
<ng-template #panelTemplate>
|
|
1861
2019
|
<ul
|
|
1862
2020
|
class="kf-select__panel"
|
|
1863
2021
|
[id]="listboxId"
|
|
@@ -1881,8 +2039,8 @@ class Select {
|
|
|
1881
2039
|
<li class="kf-select__empty">Sin opciones disponibles</li>
|
|
1882
2040
|
}
|
|
1883
2041
|
</ul>
|
|
1884
|
-
|
|
1885
|
-
`, isInline: true, styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);
|
|
2042
|
+
</ng-template>
|
|
2043
|
+
`, isInline: true, styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:240px;font-family:var(--kf-font-body)}.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__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__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-select__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-select__panel{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.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: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__empty{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"] }] });
|
|
1886
2044
|
}
|
|
1887
2045
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Select, decorators: [{
|
|
1888
2046
|
type: Component,
|
|
@@ -1911,7 +2069,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1911
2069
|
aria-hidden="true"
|
|
1912
2070
|
></span>
|
|
1913
2071
|
</button>
|
|
1914
|
-
|
|
2072
|
+
<ng-template #panelTemplate>
|
|
1915
2073
|
<ul
|
|
1916
2074
|
class="kf-select__panel"
|
|
1917
2075
|
[id]="listboxId"
|
|
@@ -1935,12 +2093,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
1935
2093
|
<li class="kf-select__empty">Sin opciones disponibles</li>
|
|
1936
2094
|
}
|
|
1937
2095
|
</ul>
|
|
1938
|
-
|
|
1939
|
-
`, styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);
|
|
1940
|
-
}], 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 }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }],
|
|
1941
|
-
type: HostListener,
|
|
1942
|
-
args: ['document:click', ['$event']]
|
|
1943
|
-
}], onEscape: [{
|
|
2096
|
+
</ng-template>
|
|
2097
|
+
`, styles: [":host{display:flex;flex-direction:column;gap:var(--kf-space-xs);width:240px;font-family:var(--kf-font-body)}.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__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-select__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-select__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-select__panel{box-sizing:border-box;width:100%;margin:0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.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: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__empty{padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
|
|
2098
|
+
}], 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 }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], panelTemplate: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], onDocumentEscape: [{
|
|
1944
2099
|
type: HostListener,
|
|
1945
2100
|
args: ['document:keydown.escape']
|
|
1946
2101
|
}] } });
|
|
@@ -2179,55 +2334,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
2179
2334
|
`, styles: [":host{display:block}.kf-skeleton{display:block;background:linear-gradient(90deg,var(--kf-color-border) 25%,var(--kf-color-surface) 37%,var(--kf-color-border) 63%);background-size:400% 100%;animation:kf-skeleton-shimmer 1.4s ease infinite}.kf-skeleton--text{height:14px;border-radius:var(--kf-radius-xs)}.kf-skeleton--rect{height:80px;border-radius:var(--kf-radius-sm)}.kf-skeleton--circle{aspect-ratio:1 / 1;border-radius:var(--kf-radius-pill)}@keyframes kf-skeleton-shimmer{0%{background-position:100% 0}to{background-position:0 0}}@media(prefers-reduced-motion:reduce){.kf-skeleton{animation:none;background:var(--kf-color-border)}}\n"] }]
|
|
2180
2335
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
|
|
2181
2336
|
|
|
2182
|
-
/**
|
|
2183
|
-
* Indicador de carga indeterminado: inline, dentro de un botón, o como único
|
|
2184
|
-
* contenido de una sección mientras llega la data.
|
|
2185
|
-
*
|
|
2186
|
-
* Cuando se conoce la forma del contenido que viene, preferir `kf-skeleton`
|
|
2187
|
-
* (dibuja la silueta). El spinner es para "algo está pasando" sin forma
|
|
2188
|
-
* conocida — guardar, enviar, reintentar.
|
|
2189
|
-
*
|
|
2190
|
-
* Lleva `role="status"`, así que el lector de pantalla anuncia el `label`
|
|
2191
|
-
* cuando aparece. Sin `label` cae en un texto accesible por defecto.
|
|
2192
|
-
*
|
|
2193
|
-
* <kf-spinner />
|
|
2194
|
-
* <kf-spinner size="sm" label="Cargando…" />
|
|
2195
|
-
* <kf-spinner onDark />
|
|
2196
|
-
*/
|
|
2197
|
-
class Spinner {
|
|
2198
|
-
size = input('md', /* @ts-ignore */
|
|
2199
|
-
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2200
|
-
/** Texto al lado del anillo. Vacío deja solo el anillo (y el texto para lectores). */
|
|
2201
|
-
label = input('', /* @ts-ignore */
|
|
2202
|
-
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2203
|
-
/** Invierte los colores para fondos oscuros. */
|
|
2204
|
-
onDark = input(false, { ...(ngDevMode ? { debugName: "onDark" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2205
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Spinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2206
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Spinner, isStandalone: true, selector: "kf-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, onDark: { classPropertyName: "onDark", publicName: "onDark", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
2207
|
-
<span class="kf-spinner" [class.kf-spinner--on-dark]="onDark()" role="status">
|
|
2208
|
-
<span class="kf-spinner__ring" [class]="'kf-spinner__ring--' + size()"></span>
|
|
2209
|
-
@if (label()) {
|
|
2210
|
-
<span class="kf-spinner__label">{{ label() }}</span>
|
|
2211
|
-
} @else {
|
|
2212
|
-
<span class="kf-spinner__sr">Cargando</span>
|
|
2213
|
-
}
|
|
2214
|
-
</span>
|
|
2215
|
-
`, isInline: true, styles: [":host{display:inline-block}.kf-spinner{display:inline-flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}.kf-spinner__ring{display:inline-block;flex:none;border-radius:var(--kf-radius-pill);border:2px solid var(--kf-color-border);border-top-color:var(--kf-color-primary);animation:kf-spinner-turn .7s linear infinite}.kf-spinner__ring--sm{width:16px;height:16px}.kf-spinner__ring--md{width:24px;height:24px;border-width:3px}.kf-spinner__ring--lg{width:32px;height:32px;border-width:3px}.kf-spinner__label{font-size:.875rem;color:var(--kf-color-text-muted)}.kf-spinner--on-dark .kf-spinner__ring{border-color:#ffffff47;border-top-color:var(--kf-color-white)}.kf-spinner--on-dark .kf-spinner__label{color:var(--kf-color-white)}@keyframes kf-spinner-turn{to{transform:rotate(360deg)}}.kf-spinner__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media(prefers-reduced-motion:reduce){.kf-spinner__ring{animation-duration:2s}}\n"] });
|
|
2216
|
-
}
|
|
2217
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Spinner, decorators: [{
|
|
2218
|
-
type: Component,
|
|
2219
|
-
args: [{ selector: 'kf-spinner', template: `
|
|
2220
|
-
<span class="kf-spinner" [class.kf-spinner--on-dark]="onDark()" role="status">
|
|
2221
|
-
<span class="kf-spinner__ring" [class]="'kf-spinner__ring--' + size()"></span>
|
|
2222
|
-
@if (label()) {
|
|
2223
|
-
<span class="kf-spinner__label">{{ label() }}</span>
|
|
2224
|
-
} @else {
|
|
2225
|
-
<span class="kf-spinner__sr">Cargando</span>
|
|
2226
|
-
}
|
|
2227
|
-
</span>
|
|
2228
|
-
`, styles: [":host{display:inline-block}.kf-spinner{display:inline-flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}.kf-spinner__ring{display:inline-block;flex:none;border-radius:var(--kf-radius-pill);border:2px solid var(--kf-color-border);border-top-color:var(--kf-color-primary);animation:kf-spinner-turn .7s linear infinite}.kf-spinner__ring--sm{width:16px;height:16px}.kf-spinner__ring--md{width:24px;height:24px;border-width:3px}.kf-spinner__ring--lg{width:32px;height:32px;border-width:3px}.kf-spinner__label{font-size:.875rem;color:var(--kf-color-text-muted)}.kf-spinner--on-dark .kf-spinner__ring{border-color:#ffffff47;border-top-color:var(--kf-color-white)}.kf-spinner--on-dark .kf-spinner__label{color:var(--kf-color-white)}@keyframes kf-spinner-turn{to{transform:rotate(360deg)}}.kf-spinner__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media(prefers-reduced-motion:reduce){.kf-spinner__ring{animation-duration:2s}}\n"] }]
|
|
2229
|
-
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onDark: [{ type: i0.Input, args: [{ isSignal: true, alias: "onDark", required: false }] }] } });
|
|
2230
|
-
|
|
2231
2337
|
/**
|
|
2232
2338
|
* Wrapper de los cuatro estados que toda sección tiene: cargando, con datos,
|
|
2233
2339
|
* vacía y con error. Un componente en vez de tres `@if` sueltos, porque es
|
|
@@ -2788,6 +2894,229 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
2788
2894
|
`, styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-data-table{background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-sm);overflow:hidden}.kf-data-table--flush{border:none;box-shadow:none;border-radius:0}.kf-data-table__toolbar{display:flex;justify-content:flex-end;padding:var(--kf-space-sm) var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-data-table__view-toggle{display:inline-flex;gap:2px;padding:2px;background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm)}.kf-data-table__view-option{font:inherit;font-size:.875em;padding:var(--kf-space-xs) var(--kf-space-sm);border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-xs);cursor:pointer;transition:background .14s,color .14s}.kf-data-table__view-option:hover:not(.kf-data-table__view-option--active){color:var(--kf-color-text)}.kf-data-table__view-option--active{background:var(--kf-color-white);color:var(--kf-color-ink);box-shadow:var(--kf-shadow-xs)}.kf-data-table__view-option:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-data-table__scroll{overflow-x:auto}.kf-data-table__table{width:100%;border-collapse:collapse;text-align:left}.kf-data-table__table th,.kf-data-table__table td{padding:var(--kf-space-sm) var(--kf-space-md);border-bottom:1px solid var(--kf-color-border);white-space:nowrap}.kf-data-table__table th{font-family:var(--kf-font-title);font-size:.8125em;text-transform:uppercase;letter-spacing:.02em;color:var(--kf-color-text-muted);background:var(--kf-color-surface)}.kf-data-table__table td{color:var(--kf-color-text)}.kf-data-table__table tbody tr:last-child td{border-bottom:none}.kf-data-table__row{cursor:pointer;transition:background .14s}.kf-data-table__row:hover{background:var(--kf-color-primary-soft)}.kf-data-table__cell--right{text-align:right}.kf-data-table__empty{padding:var(--kf-space-md)}.kf-data-table__footer{padding:var(--kf-space-sm) var(--kf-space-md);border-top:1px solid var(--kf-color-border)}.kf-data-table__footer:empty{display:none}.kf-data-table__cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--kf-space-md);padding:var(--kf-space-md)}.kf-data-table__card{display:flex;flex-direction:column;border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);overflow:hidden;transition:border-color .14s,box-shadow .14s}.kf-data-table__card--interactive{cursor:pointer}.kf-data-table__card:hover{border-color:var(--kf-color-border-strong);box-shadow:var(--kf-shadow-xs)}.kf-data-table__card--interactive:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-data-table__card-header{display:flex;align-items:center;gap:var(--kf-space-sm);padding:var(--kf-space-md)}.kf-data-table__card-media{flex:none}.kf-data-table__card-media img,.kf-data-table__thumb{display:block;width:48px;height:48px;border-radius:var(--kf-radius-xs);object-fit:cover;background:var(--kf-color-surface)}.kf-data-table__card-heading{display:flex;flex-direction:column;gap:var(--kf-space-xs);min-width:0}.kf-data-table__card-title{font-family:var(--kf-font-title);font-weight:600;color:var(--kf-color-ink);overflow-wrap:anywhere}.kf-data-table__card-statuses,.kf-data-table__card-actions{display:flex;flex-wrap:wrap;gap:var(--kf-space-xs)}.kf-data-table__card-fields{display:flex;flex-direction:column;gap:var(--kf-space-xs);padding:var(--kf-space-md)}.kf-data-table__card-header+.kf-data-table__card-fields{padding-top:0}.kf-data-table__card-field{display:flex;justify-content:space-between;gap:var(--kf-space-sm)}.kf-data-table__card-actions{justify-content:flex-end;margin-top:auto;padding:var(--kf-space-sm) var(--kf-space-md);border-top:1px solid var(--kf-color-border);background:var(--kf-color-surface)}.kf-data-table__thumb{width:32px;height:32px}.kf-data-table__card-label{font-family:var(--kf-font-title);font-size:.8125em;text-transform:uppercase;letter-spacing:.02em;color:var(--kf-color-text-muted)}.kf-data-table__card-value{color:var(--kf-color-text);text-align:right}\n"] }]
|
|
2789
2895
|
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], cardable: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardable", required: false }] }], defaultView: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultView", required: false }] }], render: [{ type: i0.Input, args: [{ isSignal: true, alias: "render", required: false }] }], cellTemplates: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellTemplates", required: false }] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }] } });
|
|
2790
2896
|
|
|
2897
|
+
/**
|
|
2898
|
+
* Ítem de acción dentro de un `kf-dropdown-panel`. Es un `<button>` nativo
|
|
2899
|
+
* por dentro (no un `<a>`): las acciones de un menú de este tipo disparan
|
|
2900
|
+
* comportamiento en la pantalla actual (cerrar sesión, ejecutar un
|
|
2901
|
+
* comando), no navegan a otra URL.
|
|
2902
|
+
*
|
|
2903
|
+
* <kf-dropdown-item (click)="onLogout()" tone="error">Cerrar sesión</kf-dropdown-item>
|
|
2904
|
+
*/
|
|
2905
|
+
class DropdownItem {
|
|
2906
|
+
tone = input('neutral', /* @ts-ignore */
|
|
2907
|
+
...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
|
|
2908
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2909
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: DropdownItem, isStandalone: true, selector: "kf-dropdown-item", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
2910
|
+
<button
|
|
2911
|
+
type="button"
|
|
2912
|
+
class="kf-dropdown-item"
|
|
2913
|
+
[class.kf-dropdown-item--error]="tone() === 'error'"
|
|
2914
|
+
role="menuitem"
|
|
2915
|
+
>
|
|
2916
|
+
<ng-content />
|
|
2917
|
+
</button>
|
|
2918
|
+
`, isInline: true, styles: [":host{display:block}.kf-dropdown-item{display:block;width:100%;padding:var(--kf-space-sm) var(--kf-space-md);border:none;background:transparent;font:inherit;text-align:left;color:var(--kf-color-text);cursor:pointer}.kf-dropdown-item:hover{background:var(--kf-color-surface)}.kf-dropdown-item:focus-visible{outline:none;box-shadow:inset var(--kf-shadow-focus)}.kf-dropdown-item--error{color:var(--kf-color-error-strong)}.kf-dropdown-item--error:hover{background:var(--kf-color-error-soft)}\n"] });
|
|
2919
|
+
}
|
|
2920
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DropdownItem, decorators: [{
|
|
2921
|
+
type: Component,
|
|
2922
|
+
args: [{ selector: 'kf-dropdown-item', template: `
|
|
2923
|
+
<button
|
|
2924
|
+
type="button"
|
|
2925
|
+
class="kf-dropdown-item"
|
|
2926
|
+
[class.kf-dropdown-item--error]="tone() === 'error'"
|
|
2927
|
+
role="menuitem"
|
|
2928
|
+
>
|
|
2929
|
+
<ng-content />
|
|
2930
|
+
</button>
|
|
2931
|
+
`, styles: [":host{display:block}.kf-dropdown-item{display:block;width:100%;padding:var(--kf-space-sm) var(--kf-space-md);border:none;background:transparent;font:inherit;text-align:left;color:var(--kf-color-text);cursor:pointer}.kf-dropdown-item:hover{background:var(--kf-color-surface)}.kf-dropdown-item:focus-visible{outline:none;box-shadow:inset var(--kf-shadow-focus)}.kf-dropdown-item--error{color:var(--kf-color-error-strong)}.kf-dropdown-item--error:hover{background:var(--kf-color-error-soft)}\n"] }]
|
|
2932
|
+
}], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }] } });
|
|
2933
|
+
/**
|
|
2934
|
+
* Contenido del panel flotante de un `kf-dropdown`. Es solo una plantilla
|
|
2935
|
+
* (`<ng-template>` por dentro, capturada vía `TemplateRef`) — `Dropdown` la
|
|
2936
|
+
* conecta al overlay real cuando `open` pasa a `true`, no la renderiza en su
|
|
2937
|
+
* propio lugar del DOM. Esto es lo que permite que el panel aparezca pegado
|
|
2938
|
+
* al host de `Dropdown` sin importar dónde esté ese host en la página.
|
|
2939
|
+
*
|
|
2940
|
+
* <kf-dropdown [(open)]="menuOpen">
|
|
2941
|
+
* <kf-dropdown-panel>
|
|
2942
|
+
* <kf-dropdown-item (click)="onLogout()">Cerrar sesión</kf-dropdown-item>
|
|
2943
|
+
* </kf-dropdown-panel>
|
|
2944
|
+
* </kf-dropdown>
|
|
2945
|
+
*/
|
|
2946
|
+
class DropdownPanel {
|
|
2947
|
+
templateRef = viewChild.required(TemplateRef, /* @ts-ignore */
|
|
2948
|
+
...(ngDevMode ? [{ debugName: "templateRef" }] : /* istanbul ignore next */ []));
|
|
2949
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DropdownPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2950
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: DropdownPanel, isStandalone: true, selector: "kf-dropdown-panel", viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
2951
|
+
<ng-template>
|
|
2952
|
+
<div class="kf-dropdown-panel">
|
|
2953
|
+
<div class="kf-dropdown-panel__inner" role="menu">
|
|
2954
|
+
<ng-content />
|
|
2955
|
+
</div>
|
|
2956
|
+
</div>
|
|
2957
|
+
</ng-template>
|
|
2958
|
+
`, isInline: true, styles: [".kf-dropdown-panel{min-width:220px;max-width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg);font-family:var(--kf-font-body);animation:kf-dropdown-panel-enter .14s ease-out}.kf-dropdown-panel__inner{padding:var(--kf-space-xs) 0;overflow:hidden;border-radius:inherit}@media(prefers-reduced-motion:reduce){.kf-dropdown-panel{animation:none}}@keyframes kf-dropdown-panel-enter{0%{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] });
|
|
2959
|
+
}
|
|
2960
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: DropdownPanel, decorators: [{
|
|
2961
|
+
type: Component,
|
|
2962
|
+
args: [{ selector: 'kf-dropdown-panel', template: `
|
|
2963
|
+
<ng-template>
|
|
2964
|
+
<div class="kf-dropdown-panel">
|
|
2965
|
+
<div class="kf-dropdown-panel__inner" role="menu">
|
|
2966
|
+
<ng-content />
|
|
2967
|
+
</div>
|
|
2968
|
+
</div>
|
|
2969
|
+
</ng-template>
|
|
2970
|
+
`, styles: [".kf-dropdown-panel{min-width:220px;max-width:100%;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md);box-shadow:var(--kf-shadow-lg);font-family:var(--kf-font-body);animation:kf-dropdown-panel-enter .14s ease-out}.kf-dropdown-panel__inner{padding:var(--kf-space-xs) 0;overflow:hidden;border-radius:inherit}@media(prefers-reduced-motion:reduce){.kf-dropdown-panel{animation:none}}@keyframes kf-dropdown-panel-enter{0%{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
|
|
2971
|
+
}], propDecorators: { templateRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
|
|
2972
|
+
/**
|
|
2973
|
+
* Menú de acciones flotante, conectado a un elemento disparador vía
|
|
2974
|
+
* `@angular/cdk/overlay` — la misma pieza que usa Angular Material para
|
|
2975
|
+
* `mat-menu`/`mat-select`. Resuelve el patrón que antes se reimplementaba a
|
|
2976
|
+
* mano en cada consumidor (ver el session-menu de `web-portal-latam-frontend`,
|
|
2977
|
+
* ~80 líneas de HTML/TS/SCSS para toggle + click-afuera + Escape + animación
|
|
2978
|
+
* de entrada, acopladas a una clase interna no pública de `PortalHeader`).
|
|
2979
|
+
*
|
|
2980
|
+
* Se apoya en el CDK en vez de un `position: absolute` casero (como sí hace
|
|
2981
|
+
* `SelectMenu`, que puede permitírselo porque su trigger vive siempre dentro
|
|
2982
|
+
* del propio componente) porque acá el disparador real puede vivir en OTRO
|
|
2983
|
+
* componente por completo — ej. el avatar dentro de `kf-portal-header` — y
|
|
2984
|
+
* el panel tiene que aparecer pegado a ESE elemento sin importar dónde el
|
|
2985
|
+
* consumidor ubique al `Dropdown` en su HTML. El Overlay CDK calcula esa
|
|
2986
|
+
* posición (con fallback si no entra en pantalla) en vez de que cada
|
|
2987
|
+
* consumidor lo recalcule a mano.
|
|
2988
|
+
*
|
|
2989
|
+
* `open` es two-way, igual que `Alert`/`Modal`: el consumidor decide qué
|
|
2990
|
+
* dispara la apertura (puede ser un `(click)` en un botón propio, o un
|
|
2991
|
+
* evento de otro componente como `PortalHeader.sessionClick`) — `Dropdown`
|
|
2992
|
+
* en sí no renderiza ningún trigger, su propio host es el punto de anclaje
|
|
2993
|
+
* visual del panel.
|
|
2994
|
+
*
|
|
2995
|
+
* <kf-dropdown [(open)]="menuOpen">
|
|
2996
|
+
* <kf-dropdown-panel>
|
|
2997
|
+
* <div class="mi-header">Sesión iniciada como {{ email() }}</div>
|
|
2998
|
+
* <kf-dropdown-item (click)="onLogout()" tone="error">Cerrar sesión</kf-dropdown-item>
|
|
2999
|
+
* </kf-dropdown-panel>
|
|
3000
|
+
* </kf-dropdown>
|
|
3001
|
+
*/
|
|
3002
|
+
class Dropdown {
|
|
3003
|
+
/** Visibilidad del panel, two-way: `[(open)]="menuOpen"`. */
|
|
3004
|
+
open = model(false, /* @ts-ignore */
|
|
3005
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
3006
|
+
/**
|
|
3007
|
+
* Elemento al que se conecta el overlay, si es distinto del propio host
|
|
3008
|
+
* de `Dropdown`. Sin esto, `Dropdown` asume que ÉL MISMO es visualmente
|
|
3009
|
+
* el disparador (caso normal: el consumidor arma su propio botón como
|
|
3010
|
+
* contenido, y `Dropdown` envuelve ese contenido). Cuando el disparador
|
|
3011
|
+
* real vive dentro de OTRO componente que no se puede envolver sin
|
|
3012
|
+
* ensanchar el área de click a algo más grande que el botón (ej. el
|
|
3013
|
+
* avatar de sesión dentro de `PortalHeader`, que convive con logo y
|
|
3014
|
+
* navegación en el mismo host), `anchor` permite apuntar el overlay a la
|
|
3015
|
+
* referencia real de ese componente en vez de al host vacío de
|
|
3016
|
+
* `Dropdown`.
|
|
3017
|
+
*
|
|
3018
|
+
* <kf-dropdown [(open)]="menuOpen" [anchor]="headerRef()">
|
|
3019
|
+
*/
|
|
3020
|
+
anchor = input(/* @ts-ignore */
|
|
3021
|
+
...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
|
|
3022
|
+
panel = contentChild(DropdownPanel, /* @ts-ignore */
|
|
3023
|
+
...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
|
|
3024
|
+
overlayService = inject(Overlay);
|
|
3025
|
+
host = inject((ElementRef));
|
|
3026
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
3027
|
+
destroyRef = inject(DestroyRef);
|
|
3028
|
+
overlayRef = null;
|
|
3029
|
+
constructor() {
|
|
3030
|
+
effect(() => {
|
|
3031
|
+
if (this.open()) {
|
|
3032
|
+
this.attach();
|
|
3033
|
+
}
|
|
3034
|
+
else {
|
|
3035
|
+
this.detach();
|
|
3036
|
+
}
|
|
3037
|
+
});
|
|
3038
|
+
this.destroyRef.onDestroy(() => this.overlayRef?.dispose());
|
|
3039
|
+
}
|
|
3040
|
+
/**
|
|
3041
|
+
* Respaldo de `overlayRef.keydownEvents()`: ese observable del CDK solo
|
|
3042
|
+
* ve teclas presionadas con el foco DENTRO del pane del overlay. Si el
|
|
3043
|
+
* usuario abre el menú y presiona Escape con el foco en otro lado de la
|
|
3044
|
+
* página (caso común — el foco puede seguir en el botón disparador, que
|
|
3045
|
+
* vive fuera del overlay), `keydownEvents()` nunca dispara. Este listener
|
|
3046
|
+
* a nivel de documento cubre ese caso; el de `keydownEvents()` sigue
|
|
3047
|
+
* activo para cuando el foco sí está dentro del panel.
|
|
3048
|
+
*/
|
|
3049
|
+
onDocumentEscape() {
|
|
3050
|
+
this.open.set(false);
|
|
3051
|
+
}
|
|
3052
|
+
attach() {
|
|
3053
|
+
const panel = this.panel();
|
|
3054
|
+
if (!panel || this.overlayRef?.hasAttached()) {
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
const overlayRef = this.getOrCreateOverlayRef();
|
|
3058
|
+
const portal = new TemplatePortal(panel.templateRef(), this.viewContainerRef);
|
|
3059
|
+
overlayRef.attach(portal);
|
|
3060
|
+
overlayRef.outsidePointerEvents().subscribe(() => this.open.set(false));
|
|
3061
|
+
overlayRef.keydownEvents().subscribe((event) => {
|
|
3062
|
+
if (event.key === 'Escape') {
|
|
3063
|
+
this.open.set(false);
|
|
3064
|
+
}
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
3067
|
+
detach() {
|
|
3068
|
+
this.overlayRef?.detach();
|
|
3069
|
+
}
|
|
3070
|
+
getOrCreateOverlayRef() {
|
|
3071
|
+
if (this.overlayRef) {
|
|
3072
|
+
return this.overlayRef;
|
|
3073
|
+
}
|
|
3074
|
+
const positionStrategy = this.overlayService
|
|
3075
|
+
.position()
|
|
3076
|
+
.flexibleConnectedTo(this.anchor() ?? this.host)
|
|
3077
|
+
// 4 posiciones, no 2: además de abajo/arriba (alineado al borde
|
|
3078
|
+
// derecho del anchor, el caso común), agrega el mismo par alineado al
|
|
3079
|
+
// borde IZQUIERDO. Con solo el par "end" — como estaba antes — un
|
|
3080
|
+
// trigger cerca del borde derecho de la pantalla no tenía ningún
|
|
3081
|
+
// fallback horizontal: el panel se salía del viewport en vez de
|
|
3082
|
+
// reacomodarse hacia la izquierda. El CDK prueba cada posición en
|
|
3083
|
+
// orden y usa la primera que entra completa en el viewport.
|
|
3084
|
+
.withPositions([
|
|
3085
|
+
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
|
|
3086
|
+
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -4 },
|
|
3087
|
+
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
|
|
3088
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
|
|
3089
|
+
])
|
|
3090
|
+
// Margen de seguridad contra los bordes del viewport — sin esto, el
|
|
3091
|
+
// CDK puede considerar una posición "válida" aunque quede pegada al
|
|
3092
|
+
// borde con 0px de aire.
|
|
3093
|
+
.withViewportMargin(8)
|
|
3094
|
+
// Si ninguna de las 4 posiciones entra completa (viewport muy
|
|
3095
|
+
// angosto), la última se ajusta con push en vez de desbordarse fuera
|
|
3096
|
+
// de pantalla sin control.
|
|
3097
|
+
.withPush(true);
|
|
3098
|
+
this.overlayRef = this.overlayService.create({
|
|
3099
|
+
positionStrategy,
|
|
3100
|
+
scrollStrategy: this.overlayService.scrollStrategies.reposition(),
|
|
3101
|
+
// Sin esto, el panel puede quedar más angosto que su propio
|
|
3102
|
+
// `min-width` en pantallas chicas si el CDK decide recortar — fija un
|
|
3103
|
+
// techo razonable en vez de dejarlo crecer sin límite ni encogerse
|
|
3104
|
+
// por debajo de lo legible.
|
|
3105
|
+
maxWidth: '90vw',
|
|
3106
|
+
});
|
|
3107
|
+
return this.overlayRef;
|
|
3108
|
+
}
|
|
3109
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3110
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.0", type: Dropdown, isStandalone: true, selector: "kf-dropdown", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()" } }, queries: [{ propertyName: "panel", first: true, predicate: DropdownPanel, descendants: true, isSignal: true }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:inline-block}\n"] });
|
|
3111
|
+
}
|
|
3112
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Dropdown, decorators: [{
|
|
3113
|
+
type: Component,
|
|
3114
|
+
args: [{ selector: 'kf-dropdown', template: `<ng-content />`, styles: [":host{display:inline-block}\n"] }]
|
|
3115
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], panel: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownPanel), { isSignal: true }] }], onDocumentEscape: [{
|
|
3116
|
+
type: HostListener,
|
|
3117
|
+
args: ['document:keydown.escape']
|
|
3118
|
+
}] } });
|
|
3119
|
+
|
|
2791
3120
|
/**
|
|
2792
3121
|
* Bloque promocional sobre fondo oscuro de marca (página 37) — campañas,
|
|
2793
3122
|
* accesos directos o el portal de autoatención. Usa `--kf-color-tertiary-deep`
|
|
@@ -3369,6 +3698,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3369
3698
|
`, styles: [":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:0 0 0 3px #eb575738}.kf-input__field--disabled{opacity:.5}.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)}.kf-input__hint{font-size:.75rem;color:var(--kf-color-text-muted)}.kf-input__error{display:flex;align-items:center;gap:var(--kf-space-xs);font-size:.75rem;font-weight:600;color:var(--kf-color-error-strong)}\n"] }]
|
|
3370
3699
|
}], 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 }] }], 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 }] }] } });
|
|
3371
3700
|
|
|
3701
|
+
/**
|
|
3702
|
+
* Acción de bajo énfasis con apariencia de texto — "¿Olvidaste tu
|
|
3703
|
+
* contraseña?", "Volver a iniciar sesión". Antes de este componente,
|
|
3704
|
+
* `web-portal-latam-frontend` reimplementaba esto dos veces (`.login__forgot`
|
|
3705
|
+
* como `<a href="#">` con `preventDefault()`, `.login__back` como
|
|
3706
|
+
* `<button>`), cada una con su propio `:focus-visible` copiado literal.
|
|
3707
|
+
*
|
|
3708
|
+
* Es siempre un `<button type="button">` por dentro, nunca un `<a>`: ninguno
|
|
3709
|
+
* de los dos casos reales navega a otra URL, ambos disparan una acción en la
|
|
3710
|
+
* misma pantalla (cambiar de vista, someter un flujo). Si en el futuro un
|
|
3711
|
+
* consumidor necesita navegación real con href, esa es una discusión de API
|
|
3712
|
+
* distinta (`kf-link` con `[routerLink]`/`href`), no se fuerza acá sin caso
|
|
3713
|
+
* de uso confirmado.
|
|
3714
|
+
*
|
|
3715
|
+
* `variant="default"` (color primario, subrayado en hover) es para la
|
|
3716
|
+
* acción de mayor jerarquía relativa de la pantalla (ej. "¿Olvidaste tu
|
|
3717
|
+
* contraseña?"); `variant="muted"` (gris que pasa a primario en hover) es
|
|
3718
|
+
* para acciones de retroceso/salida (ej. "← Volver a iniciar sesión").
|
|
3719
|
+
*
|
|
3720
|
+
* <kf-link (click)="onForgotPassword()">¿Olvidaste tu contraseña?</kf-link>
|
|
3721
|
+
* <kf-link variant="muted" (click)="onBack()">← Volver a iniciar sesión</kf-link>
|
|
3722
|
+
*/
|
|
3723
|
+
class Link {
|
|
3724
|
+
variant = input('default', /* @ts-ignore */
|
|
3725
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3726
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3727
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Link, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3728
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: Link, isStandalone: true, selector: "kf-link", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
3729
|
+
<button
|
|
3730
|
+
type="button"
|
|
3731
|
+
class="kf-link"
|
|
3732
|
+
[class.kf-link--muted]="variant() === 'muted'"
|
|
3733
|
+
[disabled]="disabled()"
|
|
3734
|
+
>
|
|
3735
|
+
<ng-content />
|
|
3736
|
+
</button>
|
|
3737
|
+
`, isInline: true, styles: [":host{display:inline-block}.kf-link{padding:0;border:none;background:transparent;font:inherit;font-weight:500;color:var(--kf-color-primary);text-decoration:none;cursor:pointer}.kf-link:hover:not(:disabled){text-decoration:underline}.kf-link:focus-visible{outline:2px solid var(--kf-color-primary);outline-offset:2px;border-radius:var(--kf-radius-xs)}.kf-link:disabled{opacity:.5;cursor:not-allowed}.kf-link--muted{color:var(--kf-color-text-muted)}.kf-link--muted:hover:not(:disabled){color:var(--kf-color-primary);text-decoration:none}\n"] });
|
|
3738
|
+
}
|
|
3739
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Link, decorators: [{
|
|
3740
|
+
type: Component,
|
|
3741
|
+
args: [{ selector: 'kf-link', template: `
|
|
3742
|
+
<button
|
|
3743
|
+
type="button"
|
|
3744
|
+
class="kf-link"
|
|
3745
|
+
[class.kf-link--muted]="variant() === 'muted'"
|
|
3746
|
+
[disabled]="disabled()"
|
|
3747
|
+
>
|
|
3748
|
+
<ng-content />
|
|
3749
|
+
</button>
|
|
3750
|
+
`, styles: [":host{display:inline-block}.kf-link{padding:0;border:none;background:transparent;font:inherit;font-weight:500;color:var(--kf-color-primary);text-decoration:none;cursor:pointer}.kf-link:hover:not(:disabled){text-decoration:underline}.kf-link:focus-visible{outline:2px solid var(--kf-color-primary);outline-offset:2px;border-radius:var(--kf-radius-xs)}.kf-link:disabled{opacity:.5;cursor:not-allowed}.kf-link--muted{color:var(--kf-color-text-muted)}.kf-link--muted:hover:not(:disabled){color:var(--kf-color-primary);text-decoration:none}\n"] }]
|
|
3751
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
3752
|
+
|
|
3372
3753
|
/**
|
|
3373
3754
|
* Card de estadística/KPI: label, valor grande, ícono opcional en la esquina
|
|
3374
3755
|
* superior derecha, badge de esquina opcional (pegado al valor) y una nota
|
|
@@ -3620,7 +4001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3620
4001
|
args: ['click', ['$event']]
|
|
3621
4002
|
}] } });
|
|
3622
4003
|
|
|
3623
|
-
let nextId
|
|
4004
|
+
let nextId = 0;
|
|
3624
4005
|
/**
|
|
3625
4006
|
* Dropdown de selección múltiple con checkboxes internos, siguiendo el mismo
|
|
3626
4007
|
* patrón de panel flotante que `SelectMenu` (panel con `position: absolute`
|
|
@@ -3657,7 +4038,7 @@ class MultiSelect {
|
|
|
3657
4038
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
3658
4039
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3659
4040
|
valuesChange = output();
|
|
3660
|
-
instanceId = `kf-multi-select-${nextId
|
|
4041
|
+
instanceId = `kf-multi-select-${nextId++}`;
|
|
3661
4042
|
triggerId = `${this.instanceId}-trigger`;
|
|
3662
4043
|
listboxId = `${this.instanceId}-listbox`;
|
|
3663
4044
|
isOpen = signal(false, /* @ts-ignore */
|
|
@@ -3793,7 +4174,7 @@ class MultiSelect {
|
|
|
3793
4174
|
}
|
|
3794
4175
|
</ul>
|
|
3795
4176
|
}
|
|
3796
|
-
`, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;
|
|
4177
|
+
`, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;width:240px}.kf-multi-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;font-family:var(--kf-font-body);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);color:var(--kf-color-text);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-multi-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.kf-multi-select__trigger:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-multi-select__trigger:disabled{opacity:.5;cursor:not-allowed}.kf-multi-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;text-align:left}.kf-multi-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-multi-select__count{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 5px;border-radius:var(--kf-radius-pill);background:var(--kf-color-primary);color:var(--kf-color-white);font-size:.72rem;font-weight:700}.kf-multi-select__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-multi-select__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-multi-select__panel{position:absolute;top:100%;left:0;right:0;z-index:10;margin:var(--kf-space-xs) 0 0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.kf-multi-select__option{display:flex;align-items:center;gap:var(--kf-space-sm);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-multi-select__option:hover{background:var(--kf-color-primary-soft)}.kf-multi-select__option--selected{color:var(--kf-color-primary);font-weight:600}.kf-multi-select__checkbox{display:inline-flex;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-multi-select__checkbox--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-multi-select__checkbox--checked:after{content:\"\";position:absolute;left:4px;top:1px;width:4px;height:8px;border:solid var(--kf-color-white);border-width:0 2px 2px 0;transform:rotate(45deg)}.kf-multi-select__checkbox--indeterminate{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-multi-select__checkbox--indeterminate:after{content:\"\";position:absolute;left:3px;top:6px;width:8px;height:2px;background:var(--kf-color-white);border:none;transform:none}.kf-multi-select__option-label{overflow:hidden;text-overflow:ellipsis}.kf-multi-select__empty{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"] }] });
|
|
3797
4178
|
}
|
|
3798
4179
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: MultiSelect, decorators: [{
|
|
3799
4180
|
type: Component,
|
|
@@ -3875,7 +4256,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
3875
4256
|
}
|
|
3876
4257
|
</ul>
|
|
3877
4258
|
}
|
|
3878
|
-
`, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;
|
|
4259
|
+
`, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;width:240px}.kf-multi-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;font-family:var(--kf-font-body);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);color:var(--kf-color-text);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-multi-select__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.kf-multi-select__trigger:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-multi-select__trigger:disabled{opacity:.5;cursor:not-allowed}.kf-multi-select__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;text-align:left}.kf-multi-select__value--placeholder{color:var(--kf-color-text-muted)}.kf-multi-select__count{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 5px;border-radius:var(--kf-radius-pill);background:var(--kf-color-primary);color:var(--kf-color-white);font-size:.72rem;font-weight:700}.kf-multi-select__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-multi-select__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-multi-select__panel{position:absolute;top:100%;left:0;right:0;z-index:10;margin:var(--kf-space-xs) 0 0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.kf-multi-select__option{display:flex;align-items:center;gap:var(--kf-space-sm);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-multi-select__option:hover{background:var(--kf-color-primary-soft)}.kf-multi-select__option--selected{color:var(--kf-color-primary);font-weight:600}.kf-multi-select__checkbox{display:inline-flex;flex-shrink:0;width:var(--kf-space-md);height:var(--kf-space-md);border:1px solid var(--kf-color-border-strong);border-radius:var(--kf-radius-xs);background:var(--kf-color-white);transition:background .14s,border-color .14s;position:relative}.kf-multi-select__checkbox--checked{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-multi-select__checkbox--checked:after{content:\"\";position:absolute;left:4px;top:1px;width:4px;height:8px;border:solid var(--kf-color-white);border-width:0 2px 2px 0;transform:rotate(45deg)}.kf-multi-select__checkbox--indeterminate{background:var(--kf-color-primary);border-color:var(--kf-color-primary)}.kf-multi-select__checkbox--indeterminate:after{content:\"\";position:absolute;left:3px;top:6px;width:8px;height:2px;background:var(--kf-color-white);border:none;transform:none}.kf-multi-select__option-label{overflow:hidden;text-overflow:ellipsis}.kf-multi-select__empty{padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
|
|
3879
4260
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], valuesChange: [{ type: i0.Output, args: ["valuesChange"] }], onDocumentClick: [{
|
|
3880
4261
|
type: HostListener,
|
|
3881
4262
|
args: ['document:click', ['$event']]
|
|
@@ -4347,10 +4728,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4347
4728
|
* `<ng-content select="[actions]">` para no acoplar el componente a un set
|
|
4348
4729
|
* fijo de botones.
|
|
4349
4730
|
*
|
|
4350
|
-
* `size
|
|
4351
|
-
*
|
|
4352
|
-
*
|
|
4353
|
-
*
|
|
4731
|
+
* `size` sigue la misma escala `'sm'|'md'|'lg'` que `Button`/`Icon`/`Spinner`
|
|
4732
|
+
* (`md` es el default): `sm` reduce tipografía y espaciado para usarse
|
|
4733
|
+
* dentro de cards ya compactas, `lg` los agranda para encabezar un bloque
|
|
4734
|
+
* más prominente. Antes de la `0.2.0`, `size` solo aceptaba `'sm'` —
|
|
4735
|
+
* placeholder incompleto de esta misma escala; los valores de `lg` son una
|
|
4736
|
+
* extrapolación proporcional de la escala existente (sin un caso de uso
|
|
4737
|
+
* real todavía que los valide, a diferencia de `sm`, que sí viene de un
|
|
4738
|
+
* patrón real de uso dentro de cards). `solid` rellena el chip de ícono con
|
|
4739
|
+
* el color primario sólido en vez del tratamiento "soft" (fondo tenue) —
|
|
4740
|
+
* pensado para superficies que ya tienen un tinte de color propio, donde el
|
|
4741
|
+
* chip "soft" perdería contraste.
|
|
4354
4742
|
*
|
|
4355
4743
|
* <kf-section-header icon="settings" title="Preferencias"
|
|
4356
4744
|
* subtitle="Configuración general de la cuenta">
|
|
@@ -4358,6 +4746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4358
4746
|
* </kf-section-header>
|
|
4359
4747
|
*
|
|
4360
4748
|
* <kf-section-header title="Detalle" size="sm" [solid]="true" />
|
|
4749
|
+
* <kf-section-header title="Resumen de flota" size="lg" />
|
|
4361
4750
|
*/
|
|
4362
4751
|
class SectionHeader {
|
|
4363
4752
|
icon = input(/* @ts-ignore */
|
|
@@ -4366,14 +4755,24 @@ class SectionHeader {
|
|
|
4366
4755
|
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
4367
4756
|
subtitle = input(/* @ts-ignore */
|
|
4368
4757
|
...(ngDevMode ? [undefined, { debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
4369
|
-
size = input(/* @ts-ignore */
|
|
4370
|
-
...(ngDevMode ? [
|
|
4758
|
+
size = input('md', /* @ts-ignore */
|
|
4759
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
4371
4760
|
solid = input(false, { ...(ngDevMode ? { debugName: "solid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4761
|
+
iconSize = computed(() => {
|
|
4762
|
+
if (this.size() === 'sm') {
|
|
4763
|
+
return 'sm';
|
|
4764
|
+
}
|
|
4765
|
+
if (this.size() === 'lg') {
|
|
4766
|
+
return 'lg';
|
|
4767
|
+
}
|
|
4768
|
+
return 'md';
|
|
4769
|
+
}, /* @ts-ignore */
|
|
4770
|
+
...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
4372
4771
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SectionHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4373
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SectionHeader, isStandalone: true, selector: "kf-section-header", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.kf-section-header--sm": "size() === 'sm'" } }, ngImport: i0, template: `
|
|
4772
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SectionHeader, isStandalone: true, selector: "kf-section-header", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, solid: { classPropertyName: "solid", publicName: "solid", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.kf-section-header--sm": "size() === 'sm'", "class.kf-section-header--lg": "size() === 'lg'" } }, ngImport: i0, template: `
|
|
4374
4773
|
@if (icon(); as iconName) {
|
|
4375
4774
|
<span class="kf-section-header__icon" [class.kf-section-header__icon--solid]="solid()">
|
|
4376
|
-
<kf-icon [name]="iconName" [size]="
|
|
4775
|
+
<kf-icon [name]="iconName" [size]="iconSize()" />
|
|
4377
4776
|
</span>
|
|
4378
4777
|
}
|
|
4379
4778
|
|
|
@@ -4387,14 +4786,14 @@ class SectionHeader {
|
|
|
4387
4786
|
<span class="kf-section-header__actions">
|
|
4388
4787
|
<ng-content select="[actions]" />
|
|
4389
4788
|
</span>
|
|
4390
|
-
`, isInline: true, styles: [":host{display:flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}:host(.kf-section-header--sm){gap:var(--kf-space-xs)}.kf-section-header__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;inline-size:2.5rem;block-size:2.5rem;border-radius:var(--kf-radius-sm);background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}:host(.kf-section-header--sm) .kf-section-header__icon{inline-size:1.75rem;block-size:1.75rem;border-radius:var(--kf-radius-xs)}.kf-section-header__icon--solid{background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-section-header__text{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}.kf-section-header__title{font-family:var(--kf-font-title);font-size:1rem;font-weight:700;color:var(--kf-color-ink);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__title{font-size:.875rem}.kf-section-header__subtitle{font-size:.8125rem;color:var(--kf-color-text-muted);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__subtitle{font-size:.75rem}.kf-section-header__actions{flex:none;display:flex;align-items:center;gap:var(--kf-space-sm)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size"] }] });
|
|
4789
|
+
`, isInline: true, styles: [":host{display:flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}:host(.kf-section-header--sm){gap:var(--kf-space-xs)}:host(.kf-section-header--lg){gap:var(--kf-space-md)}.kf-section-header__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;inline-size:2.5rem;block-size:2.5rem;border-radius:var(--kf-radius-sm);background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}:host(.kf-section-header--sm) .kf-section-header__icon{inline-size:1.75rem;block-size:1.75rem;border-radius:var(--kf-radius-xs)}:host(.kf-section-header--lg) .kf-section-header__icon{inline-size:3.25rem;block-size:3.25rem;border-radius:var(--kf-radius-md)}.kf-section-header__icon--solid{background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-section-header__text{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}.kf-section-header__title{font-family:var(--kf-font-title);font-size:1rem;font-weight:700;color:var(--kf-color-ink);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__title{font-size:.875rem}:host(.kf-section-header--lg) .kf-section-header__title{font-size:1.25rem}.kf-section-header__subtitle{font-size:.8125rem;color:var(--kf-color-text-muted);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__subtitle{font-size:.75rem}:host(.kf-section-header--lg) .kf-section-header__subtitle{font-size:.9375rem}.kf-section-header__actions{flex:none;display:flex;align-items:center;gap:var(--kf-space-sm)}\n"], dependencies: [{ kind: "component", type: Icon, selector: "kf-icon", inputs: ["name", "size"] }] });
|
|
4391
4790
|
}
|
|
4392
4791
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SectionHeader, decorators: [{
|
|
4393
4792
|
type: Component,
|
|
4394
4793
|
args: [{ selector: 'kf-section-header', imports: [Icon], template: `
|
|
4395
4794
|
@if (icon(); as iconName) {
|
|
4396
4795
|
<span class="kf-section-header__icon" [class.kf-section-header__icon--solid]="solid()">
|
|
4397
|
-
<kf-icon [name]="iconName" [size]="
|
|
4796
|
+
<kf-icon [name]="iconName" [size]="iconSize()" />
|
|
4398
4797
|
</span>
|
|
4399
4798
|
}
|
|
4400
4799
|
|
|
@@ -4410,7 +4809,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4410
4809
|
</span>
|
|
4411
4810
|
`, host: {
|
|
4412
4811
|
'[class.kf-section-header--sm]': "size() === 'sm'",
|
|
4413
|
-
|
|
4812
|
+
'[class.kf-section-header--lg]': "size() === 'lg'",
|
|
4813
|
+
}, styles: [":host{display:flex;align-items:center;gap:var(--kf-space-sm);font-family:var(--kf-font-body)}:host(.kf-section-header--sm){gap:var(--kf-space-xs)}:host(.kf-section-header--lg){gap:var(--kf-space-md)}.kf-section-header__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;inline-size:2.5rem;block-size:2.5rem;border-radius:var(--kf-radius-sm);background:var(--kf-color-primary-soft);color:var(--kf-color-primary)}:host(.kf-section-header--sm) .kf-section-header__icon{inline-size:1.75rem;block-size:1.75rem;border-radius:var(--kf-radius-xs)}:host(.kf-section-header--lg) .kf-section-header__icon{inline-size:3.25rem;block-size:3.25rem;border-radius:var(--kf-radius-md)}.kf-section-header__icon--solid{background:var(--kf-color-primary);color:var(--kf-color-white)}.kf-section-header__text{display:flex;flex-direction:column;min-width:0;flex:1 1 auto}.kf-section-header__title{font-family:var(--kf-font-title);font-size:1rem;font-weight:700;color:var(--kf-color-ink);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__title{font-size:.875rem}:host(.kf-section-header--lg) .kf-section-header__title{font-size:1.25rem}.kf-section-header__subtitle{font-size:.8125rem;color:var(--kf-color-text-muted);line-height:1.3}:host(.kf-section-header--sm) .kf-section-header__subtitle{font-size:.75rem}:host(.kf-section-header--lg) .kf-section-header__subtitle{font-size:.9375rem}.kf-section-header__actions{flex:none;display:flex;align-items:center;gap:var(--kf-space-sm)}\n"] }]
|
|
4414
4814
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], solid: [{ type: i0.Input, args: [{ isSignal: true, alias: "solid", required: false }] }] } });
|
|
4415
4815
|
|
|
4416
4816
|
/**
|
|
@@ -4484,184 +4884,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4484
4884
|
`, styles: [":host{display:inline-block}.kf-segmented__track{position:relative;display:grid;grid-template-columns:repeat(var(--kf-segmented-count),1fr);gap:2px;padding:2px;background:var(--kf-color-surface);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-md)}.kf-segmented__thumb{position:absolute;top:2px;left:2px;width:calc((100% - 4px) / var(--kf-segmented-count));height:calc(100% - 4px);background:var(--kf-color-white);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-xs);transform:translate(calc(var(--kf-segmented-index, 0) * 100%));transition:transform .2s ease}.kf-segmented__option{position:relative;z-index:1;font:inherit;padding:var(--kf-space-xs) var(--kf-space-md);border:none;background:transparent;color:var(--kf-color-text-muted);border-radius:var(--kf-radius-sm);cursor:pointer;transition:color .14s}.kf-segmented__option:hover:not(.kf-segmented__option--active){color:var(--kf-color-text)}.kf-segmented__option--active{color:var(--kf-color-ink)}.kf-segmented__option:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}\n"] }]
|
|
4485
4885
|
}], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
4486
4886
|
|
|
4487
|
-
let nextId = 0;
|
|
4488
|
-
/**
|
|
4489
|
-
* Dropdown de selección simple pero con panel propio (no usa `<select>` nativo),
|
|
4490
|
-
* para cuando se necesita más control visual que un `<select>` estándar permite.
|
|
4491
|
-
*
|
|
4492
|
-
* El panel flotante se implementa con `position: absolute` sobre el host
|
|
4493
|
-
* (sin Angular CDK Overlay, que no es dependencia del proyecto). Se abre y
|
|
4494
|
-
* cierra por click en el disparador, y se cierra al hacer click afuera o al
|
|
4495
|
-
* presionar Escape.
|
|
4496
|
-
*
|
|
4497
|
-
* <kf-select-menu
|
|
4498
|
-
* label="País"
|
|
4499
|
-
* [options]="countries"
|
|
4500
|
-
* [value]="selectedCountry()"
|
|
4501
|
-
* (valueChange)="selectedCountry.set($event)"
|
|
4502
|
-
* />
|
|
4503
|
-
*
|
|
4504
|
-
* Pendiente: el prop `icon` de otros componentes del design system requiere
|
|
4505
|
-
* un componente Icon / sprite SVG que esta librería todavía no tiene — este
|
|
4506
|
-
* componente no usa iconos, así que no aplica acá.
|
|
4507
|
-
*/
|
|
4508
|
-
class SelectMenu {
|
|
4509
|
-
label = input(/* @ts-ignore */
|
|
4510
|
-
...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
4511
|
-
options = input([], /* @ts-ignore */
|
|
4512
|
-
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
4513
|
-
value = input(/* @ts-ignore */
|
|
4514
|
-
...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
|
|
4515
|
-
placeholder = input('Seleccionar', /* @ts-ignore */
|
|
4516
|
-
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
4517
|
-
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4518
|
-
valueChange = output();
|
|
4519
|
-
instanceId = `kf-select-menu-${nextId++}`;
|
|
4520
|
-
triggerId = `${this.instanceId}-trigger`;
|
|
4521
|
-
listboxId = `${this.instanceId}-listbox`;
|
|
4522
|
-
isOpen = signal(false, /* @ts-ignore */
|
|
4523
|
-
...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
4524
|
-
selectedOption = computed(() => this.options().find((option) => option.value === this.value()), /* @ts-ignore */
|
|
4525
|
-
...(ngDevMode ? [{ debugName: "selectedOption" }] : /* istanbul ignore next */ []));
|
|
4526
|
-
host = inject((ElementRef));
|
|
4527
|
-
toggle() {
|
|
4528
|
-
if (this.disabled()) {
|
|
4529
|
-
return;
|
|
4530
|
-
}
|
|
4531
|
-
this.isOpen.update((open) => !open);
|
|
4532
|
-
}
|
|
4533
|
-
select(option) {
|
|
4534
|
-
this.isOpen.set(false);
|
|
4535
|
-
if (option.value !== this.value()) {
|
|
4536
|
-
this.valueChange.emit(option.value);
|
|
4537
|
-
}
|
|
4538
|
-
}
|
|
4539
|
-
onDocumentClick(event) {
|
|
4540
|
-
if (this.isOpen() && !this.host.nativeElement.contains(event.target)) {
|
|
4541
|
-
this.isOpen.set(false);
|
|
4542
|
-
}
|
|
4543
|
-
}
|
|
4544
|
-
onEscape() {
|
|
4545
|
-
this.isOpen.set(false);
|
|
4546
|
-
}
|
|
4547
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4548
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: SelectMenu, isStandalone: true, selector: "kf-select-menu", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, 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 } }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: `
|
|
4549
|
-
@if (label()) {
|
|
4550
|
-
<kf-field-label [for]="triggerId">{{ label() }}</kf-field-label>
|
|
4551
|
-
}
|
|
4552
|
-
<button
|
|
4553
|
-
#trigger
|
|
4554
|
-
type="button"
|
|
4555
|
-
[id]="triggerId"
|
|
4556
|
-
class="kf-select-menu__trigger"
|
|
4557
|
-
[disabled]="disabled()"
|
|
4558
|
-
[attr.aria-haspopup]="'listbox'"
|
|
4559
|
-
[attr.aria-expanded]="isOpen()"
|
|
4560
|
-
[attr.aria-controls]="isOpen() ? listboxId : null"
|
|
4561
|
-
(click)="toggle()"
|
|
4562
|
-
>
|
|
4563
|
-
<span
|
|
4564
|
-
class="kf-select-menu__value"
|
|
4565
|
-
[class.kf-select-menu__value--placeholder]="!selectedOption()"
|
|
4566
|
-
>
|
|
4567
|
-
{{ selectedOption()?.label ?? placeholder() }}
|
|
4568
|
-
</span>
|
|
4569
|
-
<span
|
|
4570
|
-
class="kf-select-menu__caret"
|
|
4571
|
-
[class.kf-select-menu__caret--open]="isOpen()"
|
|
4572
|
-
aria-hidden="true"
|
|
4573
|
-
></span>
|
|
4574
|
-
</button>
|
|
4575
|
-
@if (isOpen()) {
|
|
4576
|
-
<ul
|
|
4577
|
-
class="kf-select-menu__panel"
|
|
4578
|
-
[id]="listboxId"
|
|
4579
|
-
role="listbox"
|
|
4580
|
-
[attr.aria-labelledby]="triggerId"
|
|
4581
|
-
>
|
|
4582
|
-
@for (option of options(); track option.value) {
|
|
4583
|
-
<li
|
|
4584
|
-
class="kf-select-menu__option"
|
|
4585
|
-
[class.kf-select-menu__option--selected]="option.value === value()"
|
|
4586
|
-
role="option"
|
|
4587
|
-
tabindex="0"
|
|
4588
|
-
[attr.aria-selected]="option.value === value()"
|
|
4589
|
-
(click)="select(option)"
|
|
4590
|
-
(keydown.enter)="select(option)"
|
|
4591
|
-
(keydown.space)="$event.preventDefault(); select(option)"
|
|
4592
|
-
>
|
|
4593
|
-
{{ option.label }}
|
|
4594
|
-
</li>
|
|
4595
|
-
} @empty {
|
|
4596
|
-
<li class="kf-select-menu__empty">Sin opciones disponibles</li>
|
|
4597
|
-
}
|
|
4598
|
-
</ul>
|
|
4599
|
-
}
|
|
4600
|
-
`, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;min-width:200px}.kf-select-menu__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;font-family:var(--kf-font-body);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);color:var(--kf-color-text);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select-menu__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.kf-select-menu__trigger:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-select-menu__trigger:disabled{opacity:.5;cursor:not-allowed}.kf-select-menu__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select-menu__value--placeholder{color:var(--kf-color-text-muted)}.kf-select-menu__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-select-menu__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-select-menu__panel{position:absolute;top:100%;left:0;right:0;z-index:10;margin:var(--kf-space-xs) 0 0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.kf-select-menu__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-menu__option:hover{background:var(--kf-color-primary-soft)}.kf-select-menu__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select-menu__empty{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"] }] });
|
|
4601
|
-
}
|
|
4602
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: SelectMenu, decorators: [{
|
|
4603
|
-
type: Component,
|
|
4604
|
-
args: [{ selector: 'kf-select-menu', imports: [FieldLabel], template: `
|
|
4605
|
-
@if (label()) {
|
|
4606
|
-
<kf-field-label [for]="triggerId">{{ label() }}</kf-field-label>
|
|
4607
|
-
}
|
|
4608
|
-
<button
|
|
4609
|
-
#trigger
|
|
4610
|
-
type="button"
|
|
4611
|
-
[id]="triggerId"
|
|
4612
|
-
class="kf-select-menu__trigger"
|
|
4613
|
-
[disabled]="disabled()"
|
|
4614
|
-
[attr.aria-haspopup]="'listbox'"
|
|
4615
|
-
[attr.aria-expanded]="isOpen()"
|
|
4616
|
-
[attr.aria-controls]="isOpen() ? listboxId : null"
|
|
4617
|
-
(click)="toggle()"
|
|
4618
|
-
>
|
|
4619
|
-
<span
|
|
4620
|
-
class="kf-select-menu__value"
|
|
4621
|
-
[class.kf-select-menu__value--placeholder]="!selectedOption()"
|
|
4622
|
-
>
|
|
4623
|
-
{{ selectedOption()?.label ?? placeholder() }}
|
|
4624
|
-
</span>
|
|
4625
|
-
<span
|
|
4626
|
-
class="kf-select-menu__caret"
|
|
4627
|
-
[class.kf-select-menu__caret--open]="isOpen()"
|
|
4628
|
-
aria-hidden="true"
|
|
4629
|
-
></span>
|
|
4630
|
-
</button>
|
|
4631
|
-
@if (isOpen()) {
|
|
4632
|
-
<ul
|
|
4633
|
-
class="kf-select-menu__panel"
|
|
4634
|
-
[id]="listboxId"
|
|
4635
|
-
role="listbox"
|
|
4636
|
-
[attr.aria-labelledby]="triggerId"
|
|
4637
|
-
>
|
|
4638
|
-
@for (option of options(); track option.value) {
|
|
4639
|
-
<li
|
|
4640
|
-
class="kf-select-menu__option"
|
|
4641
|
-
[class.kf-select-menu__option--selected]="option.value === value()"
|
|
4642
|
-
role="option"
|
|
4643
|
-
tabindex="0"
|
|
4644
|
-
[attr.aria-selected]="option.value === value()"
|
|
4645
|
-
(click)="select(option)"
|
|
4646
|
-
(keydown.enter)="select(option)"
|
|
4647
|
-
(keydown.space)="$event.preventDefault(); select(option)"
|
|
4648
|
-
>
|
|
4649
|
-
{{ option.label }}
|
|
4650
|
-
</li>
|
|
4651
|
-
} @empty {
|
|
4652
|
-
<li class="kf-select-menu__empty">Sin opciones disponibles</li>
|
|
4653
|
-
}
|
|
4654
|
-
</ul>
|
|
4655
|
-
}
|
|
4656
|
-
`, styles: [":host{display:inline-flex;flex-direction:column;gap:var(--kf-space-xs);position:relative;font:inherit;min-width:200px}.kf-select-menu__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--kf-space-sm);width:100%;font:inherit;font-family:var(--kf-font-body);padding:var(--kf-space-sm) var(--kf-space-md);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);background:var(--kf-color-white);color:var(--kf-color-text);cursor:pointer;transition:border-color .14s,box-shadow .14s}.kf-select-menu__trigger:hover:not(:disabled){border-color:var(--kf-color-border-strong)}.kf-select-menu__trigger:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus)}.kf-select-menu__trigger:disabled{opacity:.5;cursor:not-allowed}.kf-select-menu__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kf-select-menu__value--placeholder{color:var(--kf-color-text-muted)}.kf-select-menu__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-select-menu__caret--open{transform:rotate(-135deg);margin-top:4px}.kf-select-menu__panel{position:absolute;top:100%;left:0;right:0;z-index:10;margin:var(--kf-space-xs) 0 0;padding:var(--kf-space-xs) 0;list-style:none;max-height:240px;overflow-y:auto;background:var(--kf-color-white);border:1px solid var(--kf-color-border);border-radius:var(--kf-radius-sm);box-shadow:var(--kf-shadow-md)}.kf-select-menu__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-menu__option:hover{background:var(--kf-color-primary-soft)}.kf-select-menu__option--selected{background:var(--kf-color-primary-soft);color:var(--kf-color-primary);font-weight:600}.kf-select-menu__empty{padding:var(--kf-space-sm) var(--kf-space-md);color:var(--kf-color-text-muted)}\n"] }]
|
|
4657
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], 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 }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], onDocumentClick: [{
|
|
4658
|
-
type: HostListener,
|
|
4659
|
-
args: ['document:click', ['$event']]
|
|
4660
|
-
}], onEscape: [{
|
|
4661
|
-
type: HostListener,
|
|
4662
|
-
args: ['document:keydown.escape']
|
|
4663
|
-
}] } });
|
|
4664
|
-
|
|
4665
4887
|
/**
|
|
4666
4888
|
* Indicador numérico compacto (página 34): label + valor grande, con un
|
|
4667
4889
|
* ícono a la derecha del label — más chico y sin badge de esquina que
|
|
@@ -4930,6 +5152,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
4930
5152
|
`, styles: [":host{display:block;font-family:var(--kf-font-body)}.kf-tabs{position:relative;display:flex;align-items:stretch;gap:var(--kf-space-md);border-bottom:1px solid var(--kf-color-border)}.kf-tabs__tab{display:inline-flex;align-items:center;gap:var(--kf-space-xs);font:inherit;font-size:.9rem;color:var(--kf-color-text-muted);background:transparent;border:none;padding:var(--kf-space-sm) 0;cursor:pointer;transition:color .14s}.kf-tabs__tab:hover:not(.kf-tabs__tab--active){color:var(--kf-color-text)}.kf-tabs__tab:focus-visible{outline:none;box-shadow:var(--kf-shadow-focus);border-radius:var(--kf-radius-xs)}.kf-tabs__tab--active{color:var(--kf-color-primary);font-size:1rem;font-weight:700}.kf-tabs__indicator{position:absolute;bottom:-1px;left:0;height:2px;background:var(--kf-color-primary);border-radius:2px 2px 0 0;pointer-events:none;transition:transform .28s cubic-bezier(.32,.72,0,1),width .28s cubic-bezier(.32,.72,0,1),opacity .14s}@media(prefers-reduced-motion:reduce){.kf-tabs__indicator{transition:opacity .14s}}\n"] }]
|
|
4931
5153
|
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], track: [{ type: i0.ViewChild, args: ['track', { isSignal: true }] }] } });
|
|
4932
5154
|
|
|
5155
|
+
/**
|
|
5156
|
+
* Tipografía unificada — separa la etiqueta semántica (`as`, qué es el
|
|
5157
|
+
* texto para el DOM/accesibilidad) del estilo visual (`variant`, cómo se
|
|
5158
|
+
* ve). Antes de este componente, cada pantalla que consume la librería
|
|
5159
|
+
* definía su propio `h1`/`p` con `font-size` suelto para el mismo rol
|
|
5160
|
+
* (título de página, subtítulo, texto secundario) — auditoría sobre
|
|
5161
|
+
* `web-portal-latam-frontend` encontró 9 tamaños distintos entre login y
|
|
5162
|
+
* home sin ningún paso de escala en común. `variant` resuelve eso contra
|
|
5163
|
+
* la escala de `tokens/base.css` (`--kf-font-size-*`).
|
|
5164
|
+
*
|
|
5165
|
+
* `tone` sigue la misma convención cerrada que `Alert`/`Badge`/`Chip`: sin
|
|
5166
|
+
* escape hatch de color libre. Si un caso necesita un color que `tone` no
|
|
5167
|
+
* cubre, es una discusión de design system, no una prop nueva acá.
|
|
5168
|
+
*
|
|
5169
|
+
* <kf-text as="h1" variant="title-lg">Bienvenido de nuevo</kf-text>
|
|
5170
|
+
* <kf-text as="p" variant="body-muted">Ingresá con tu cuenta corporativa.</kf-text>
|
|
5171
|
+
* <kf-text as="span" variant="caption" tone="error">Campo obligatorio</kf-text>
|
|
5172
|
+
*/
|
|
5173
|
+
class Text {
|
|
5174
|
+
/** Etiqueta semántica real que se renderiza — nunca es solo un `div`. */
|
|
5175
|
+
as = input('p', /* @ts-ignore */
|
|
5176
|
+
...(ngDevMode ? [{ debugName: "as" }] : /* istanbul ignore next */ []));
|
|
5177
|
+
variant = input('body', /* @ts-ignore */
|
|
5178
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
5179
|
+
tone = input('neutral', /* @ts-ignore */
|
|
5180
|
+
...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
|
|
5181
|
+
/**
|
|
5182
|
+
* Copia de `as` para uso dentro del template: `as` es palabra reservada
|
|
5183
|
+
* en las expresiones de Angular (`@if (x; as y)`), así que `@switch (as())`
|
|
5184
|
+
* no parsea — NG5002. La prop pública sigue llamándose `as` (es solo un
|
|
5185
|
+
* atributo HTML ahí, `<kf-text as="h1">`, no una expresión).
|
|
5186
|
+
*/
|
|
5187
|
+
tag = computed(() => this.as(), /* @ts-ignore */
|
|
5188
|
+
...(ngDevMode ? [{ debugName: "tag" }] : /* istanbul ignore next */ []));
|
|
5189
|
+
hostClass() {
|
|
5190
|
+
const classes = [`kf-text--${this.variant()}`];
|
|
5191
|
+
if (this.tone() !== 'neutral') {
|
|
5192
|
+
classes.push(`kf-text--${this.tone()}`);
|
|
5193
|
+
}
|
|
5194
|
+
return classes.join(' ');
|
|
5195
|
+
}
|
|
5196
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Text, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5197
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: Text, isStandalone: true, selector: "kf-text", inputs: { as: { classPropertyName: "as", publicName: "as", 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 } }, ngImport: i0, template: `
|
|
5198
|
+
<!--
|
|
5199
|
+
Una sola proyección compartida (ng-template + ngTemplateOutlet) en vez
|
|
5200
|
+
de un <ng-content> por cada rama del @switch: Angular solo conecta la
|
|
5201
|
+
proyección real del consumidor a la PRIMERA instancia de <ng-content>
|
|
5202
|
+
que encuentra en el árbol de compilación — con un <ng-content> por
|
|
5203
|
+
rama, todas menos una quedan vacías en runtime (bug detectado por
|
|
5204
|
+
Text.spec.ts, no algo documentado a simple vista en los docs de Angular).
|
|
5205
|
+
-->
|
|
5206
|
+
<ng-template #projected><ng-content /></ng-template>
|
|
5207
|
+
@switch (tag()) {
|
|
5208
|
+
@case ('h1') {
|
|
5209
|
+
<h1 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h1>
|
|
5210
|
+
}
|
|
5211
|
+
@case ('h2') {
|
|
5212
|
+
<h2 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h2>
|
|
5213
|
+
}
|
|
5214
|
+
@case ('h3') {
|
|
5215
|
+
<h3 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h3>
|
|
5216
|
+
}
|
|
5217
|
+
@case ('span') {
|
|
5218
|
+
<span [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></span>
|
|
5219
|
+
}
|
|
5220
|
+
@default {
|
|
5221
|
+
<p [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></p>
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
5224
|
+
`, isInline: true, styles: [":host{display:contents}h1,h2,h3,p,span{margin:0;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-text--title-lg{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-lg);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--title-md{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--title-sm{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-sm);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--body{font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body)}.kf-text--body-muted{font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}.kf-text--caption{font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}.kf-text--ok{color:var(--kf-color-success-strong)}.kf-text--warn{color:var(--kf-color-warning-strong)}.kf-text--error{color:var(--kf-color-error-strong)}.kf-text--info{color:var(--kf-color-info-strong)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
5225
|
+
}
|
|
5226
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: Text, decorators: [{
|
|
5227
|
+
type: Component,
|
|
5228
|
+
args: [{ selector: 'kf-text', imports: [NgTemplateOutlet], template: `
|
|
5229
|
+
<!--
|
|
5230
|
+
Una sola proyección compartida (ng-template + ngTemplateOutlet) en vez
|
|
5231
|
+
de un <ng-content> por cada rama del @switch: Angular solo conecta la
|
|
5232
|
+
proyección real del consumidor a la PRIMERA instancia de <ng-content>
|
|
5233
|
+
que encuentra en el árbol de compilación — con un <ng-content> por
|
|
5234
|
+
rama, todas menos una quedan vacías en runtime (bug detectado por
|
|
5235
|
+
Text.spec.ts, no algo documentado a simple vista en los docs de Angular).
|
|
5236
|
+
-->
|
|
5237
|
+
<ng-template #projected><ng-content /></ng-template>
|
|
5238
|
+
@switch (tag()) {
|
|
5239
|
+
@case ('h1') {
|
|
5240
|
+
<h1 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h1>
|
|
5241
|
+
}
|
|
5242
|
+
@case ('h2') {
|
|
5243
|
+
<h2 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h2>
|
|
5244
|
+
}
|
|
5245
|
+
@case ('h3') {
|
|
5246
|
+
<h3 [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></h3>
|
|
5247
|
+
}
|
|
5248
|
+
@case ('span') {
|
|
5249
|
+
<span [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></span>
|
|
5250
|
+
}
|
|
5251
|
+
@default {
|
|
5252
|
+
<p [class]="hostClass()"><ng-container [ngTemplateOutlet]="projected" /></p>
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
`, styles: [":host{display:contents}h1,h2,h3,p,span{margin:0;font-family:var(--kf-font-body);color:var(--kf-color-text)}.kf-text--title-lg{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-lg);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--title-md{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-md);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--title-sm{font-family:var(--kf-font-title);font-size:var(--kf-font-size-title-sm);font-weight:var(--kf-font-weight-title);color:var(--kf-color-ink)}.kf-text--body{font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body)}.kf-text--body-muted{font-size:var(--kf-font-size-body);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}.kf-text--caption{font-size:var(--kf-font-size-caption);font-weight:var(--kf-font-weight-body);color:var(--kf-color-text-muted)}.kf-text--ok{color:var(--kf-color-success-strong)}.kf-text--warn{color:var(--kf-color-warning-strong)}.kf-text--error{color:var(--kf-color-error-strong)}.kf-text--info{color:var(--kf-color-info-strong)}\n"] }]
|
|
5256
|
+
}], propDecorators: { as: [{ type: i0.Input, args: [{ isSignal: true, alias: "as", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }] } });
|
|
5257
|
+
|
|
4933
5258
|
/** Fixed icon per tone (page 20 of the design system) — not configurable per call. */
|
|
4934
5259
|
const TOAST_ICON = {
|
|
4935
5260
|
success: 'check-circle',
|
|
@@ -5279,5 +5604,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
|
|
|
5279
5604
|
* Generated bundle index. Do not edit.
|
|
5280
5605
|
*/
|
|
5281
5606
|
|
|
5282
|
-
export { ActionTile, AdminBadge, Alert, Avatar, Badge, Breadcrumb, Button, Card, Carousel, CarouselSlide, Checkbox, Chip, CompanySelector, ContentSlot, ContentState, DataTable, Divider, EmptyState, FeatureCard, Field, FieldLabel, FilterChips, FolderTabs, Icon, Input, MetricCard, Modal, MultiSelect, PageHeader, Pagination, Panel, PortalHeader, ReserveBlock, SectionHeader, Segmented, Select,
|
|
5607
|
+
export { ActionTile, AdminBadge, Alert, Avatar, Badge, Breadcrumb, Button, Card, Carousel, CarouselSlide, Checkbox, Chip, CompanySelector, ContentSlot, ContentState, DataTable, Divider, Dropdown, DropdownItem, DropdownPanel, EmptyState, FeatureCard, Field, FieldLabel, FilterChips, FolderTabs, Icon, Input, Link, MetricCard, Modal, MultiSelect, PageHeader, Pagination, Panel, PortalHeader, ReserveBlock, SectionHeader, Segmented, Select, Skeleton, Spinner, StatTile, StatusPill, Tabs, Text, ToastHost, ToastService, VehicleHeader, ViewToggle };
|
|
5283
5608
|
//# sourceMappingURL=kaufmann-lab-ui.mjs.map
|