@kaufmann-lab/ui 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/fesm2022/kaufmann-lab-ui-auth.mjs +322 -0
- package/fesm2022/kaufmann-lab-ui-auth.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-business.mjs +468 -0
- package/fesm2022/kaufmann-lab-ui-business.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-core.mjs +6338 -0
- package/fesm2022/kaufmann-lab-ui-core.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-map.mjs +1637 -0
- package/fesm2022/kaufmann-lab-ui-map.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-mobile.mjs +92 -0
- package/fesm2022/kaufmann-lab-ui-mobile.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-shared.mjs +269 -0
- package/fesm2022/kaufmann-lab-ui-shared.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui.mjs +23 -8472
- package/fesm2022/kaufmann-lab-ui.mjs.map +1 -1
- package/package.json +25 -1
- package/types/kaufmann-lab-ui-auth.d.ts +240 -0
- package/types/kaufmann-lab-ui-business.d.ts +313 -0
- package/types/kaufmann-lab-ui-core.d.ts +3459 -0
- package/types/kaufmann-lab-ui-map.d.ts +631 -0
- package/types/kaufmann-lab-ui-mobile.d.ts +53 -0
- package/types/kaufmann-lab-ui-shared.d.ts +154 -0
- package/types/kaufmann-lab-ui.d.ts +5 -4631
- package/fesm2022/mapbox-gl-csp.worker.js +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaufmann-lab/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Shared Angular component library for the Kaufmann frontends",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kaufmann Lab",
|
|
@@ -26,6 +26,30 @@
|
|
|
26
26
|
".": {
|
|
27
27
|
"types": "./types/kaufmann-lab-ui.d.ts",
|
|
28
28
|
"default": "./fesm2022/kaufmann-lab-ui.mjs"
|
|
29
|
+
},
|
|
30
|
+
"./auth": {
|
|
31
|
+
"types": "./types/kaufmann-lab-ui-auth.d.ts",
|
|
32
|
+
"default": "./fesm2022/kaufmann-lab-ui-auth.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./business": {
|
|
35
|
+
"types": "./types/kaufmann-lab-ui-business.d.ts",
|
|
36
|
+
"default": "./fesm2022/kaufmann-lab-ui-business.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./core": {
|
|
39
|
+
"types": "./types/kaufmann-lab-ui-core.d.ts",
|
|
40
|
+
"default": "./fesm2022/kaufmann-lab-ui-core.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./map": {
|
|
43
|
+
"types": "./types/kaufmann-lab-ui-map.d.ts",
|
|
44
|
+
"default": "./fesm2022/kaufmann-lab-ui-map.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./mobile": {
|
|
47
|
+
"types": "./types/kaufmann-lab-ui-mobile.d.ts",
|
|
48
|
+
"default": "./fesm2022/kaufmann-lab-ui-mobile.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./shared": {
|
|
51
|
+
"types": "./types/kaufmann-lab-ui-shared.d.ts",
|
|
52
|
+
"default": "./fesm2022/kaufmann-lab-ui-shared.mjs"
|
|
29
53
|
}
|
|
30
54
|
},
|
|
31
55
|
"type": "module"
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Marca el contenido que va en el slot de SSO de `kf-auth-layout` (típico:
|
|
5
|
+
* un `kf-sso-button`, o varios si el ecosistema suma más de un proveedor).
|
|
6
|
+
* `AuthLayout` la detecta vía `contentChild` para decidir si renderiza el
|
|
7
|
+
* separador "o" entre el bloque de SSO y el formulario tradicional
|
|
8
|
+
* proyectado en el slot por defecto — sin este marcador, `AuthLayout`
|
|
9
|
+
* tendría que adivinar si hubo proyección leyendo el DOM a mano.
|
|
10
|
+
*
|
|
11
|
+
* <kf-auth-layout brand="Mi Portal">
|
|
12
|
+
* <div kfAuthLayoutSso>
|
|
13
|
+
* <kf-sso-button provider="microsoft" (click)="loginWithMicrosoft()" />
|
|
14
|
+
* </div>
|
|
15
|
+
* <form ...>...</form>
|
|
16
|
+
* </kf-auth-layout>
|
|
17
|
+
*/
|
|
18
|
+
declare class AuthLayoutSso {
|
|
19
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthLayoutSso, never>;
|
|
20
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AuthLayoutSso, "[kfAuthLayoutSso]", never, {}, {}, never, never, true, never>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type AuthLayoutBackground = 'plain' | 'gradient' | 'pattern';
|
|
24
|
+
/**
|
|
25
|
+
* Layout a pantalla completa para pantallas de autenticación (login,
|
|
26
|
+
* recuperar contraseña, confirmación de envío) — panel de marca a la
|
|
27
|
+
* izquierda, contenido libre a la derecha en desktop; en mobile el panel de
|
|
28
|
+
* marca se oculta y un logo compacto queda visible arriba del formulario.
|
|
29
|
+
*
|
|
30
|
+
* Resuelve solo el "cascarón": cada portal arma su propio `<form>` con los
|
|
31
|
+
* componentes de la librería y lo proyecta en el slot por defecto.
|
|
32
|
+
*
|
|
33
|
+
* <kf-auth-layout
|
|
34
|
+
* brand="Mi Portal"
|
|
35
|
+
* brandLogoSrc="images/mi-portal-logo-white.png"
|
|
36
|
+
* brandLogoMobileSrc="images/mi-portal-logo-black.png"
|
|
37
|
+
* brandTagline="Frase corta de marca, propia de cada portal."
|
|
38
|
+
* >
|
|
39
|
+
* <form (ngSubmit)="onSubmit()">
|
|
40
|
+
* <kf-input label="Correo" type="email" />
|
|
41
|
+
* <kf-input label="Contraseña" type="password" toggleable />
|
|
42
|
+
* <kf-button type="submit">Ingresar</kf-button>
|
|
43
|
+
* </form>
|
|
44
|
+
* </kf-auth-layout>
|
|
45
|
+
*
|
|
46
|
+
* `backgroundVariant` controla la superficie del panel derecho:
|
|
47
|
+
* `'plain'` (fondo liso, comportamiento histórico), `'gradient'` (default —
|
|
48
|
+
* degradé sutil derivado de `--kf-color-primary`/`--kf-color-surface` vía
|
|
49
|
+
* `color-mix()`, ningún color hardcodeado) o `'pattern'` (el mismo degradé
|
|
50
|
+
* más una textura de puntos, también resuelta con tokens). Los tres se
|
|
51
|
+
* resuelven contra los tokens de tema ACTIVOS — cambiar de tema
|
|
52
|
+
* (`andes-maq`, `divemotor-star`, `kaufmann-ar`, futuros) no requiere tocar
|
|
53
|
+
* este componente ni pasarle un color a mano.
|
|
54
|
+
*
|
|
55
|
+
* `card`, en `false` por defecto (comportamiento histórico: el contenido
|
|
56
|
+
* proyectado flota sin superficie propia), envuelve el slot por defecto con
|
|
57
|
+
* la misma superficie de `kf-card` (fondo, borde, sombra, radio) para que
|
|
58
|
+
* el formulario deje de verse suelto sobre el fondo del panel.
|
|
59
|
+
*
|
|
60
|
+
* `title`/`subtitle` renderizan un encabezado de bienvenida DENTRO de la
|
|
61
|
+
* card, antes que cualquier otro contenido (jerarquía ya resuelta:
|
|
62
|
+
* `title-lg` + `body-muted`, ver `Text.ts`) — así ningún consumidor tiene
|
|
63
|
+
* que adivinar la variante de `kf-text` correcta ni terminar con un
|
|
64
|
+
* "Iniciar sesión" repetido y suelto dentro de su propio `<form>`. Sin
|
|
65
|
+
* `title`, no se renderiza ningún encabezado (comportamiento histórico).
|
|
66
|
+
*
|
|
67
|
+
* El slot `[kfAuthLayoutSso]` (ver `AuthLayoutSso`) es para el patrón
|
|
68
|
+
* "SSO primero, credenciales como alternativa secundaria" — típicamente un
|
|
69
|
+
* `kf-sso-button`. Cuando hay contenido ahí, `AuthLayout` resuelve el
|
|
70
|
+
* separador "o" automáticamente entre ese bloque y el contenido por
|
|
71
|
+
* defecto; sin ese slot, nada cambia frente al comportamiento actual.
|
|
72
|
+
*
|
|
73
|
+
* <kf-auth-layout
|
|
74
|
+
* brand="Mi Portal"
|
|
75
|
+
* backgroundVariant="pattern"
|
|
76
|
+
* card
|
|
77
|
+
* title="Iniciar sesión"
|
|
78
|
+
* subtitle="Usa tu cuenta corporativa o ingresa con contraseña"
|
|
79
|
+
* >
|
|
80
|
+
* <div kfAuthLayoutSso>
|
|
81
|
+
* <kf-sso-button provider="microsoft" (click)="loginWithMicrosoft()" />
|
|
82
|
+
* </div>
|
|
83
|
+
* <form (ngSubmit)="onSubmit()">
|
|
84
|
+
* <kf-input label="Correo" type="email" />
|
|
85
|
+
* <kf-input label="Contraseña" type="password" toggleable />
|
|
86
|
+
* <kf-button type="submit">Ingresar</kf-button>
|
|
87
|
+
* </form>
|
|
88
|
+
* </kf-auth-layout>
|
|
89
|
+
*/
|
|
90
|
+
declare class AuthLayout {
|
|
91
|
+
/** Nombre de marca/portal — wordmark de respaldo si no hay logo, y `alt` de ambos logos. */
|
|
92
|
+
readonly brand: _angular_core.InputSignal<string>;
|
|
93
|
+
/** Logo en blanco para el panel oscuro de desktop. Sin esto, se muestra `brand()` como wordmark. */
|
|
94
|
+
readonly brandLogoSrc: _angular_core.InputSignal<string | undefined>;
|
|
95
|
+
/** Frase corta bajo el logo. */
|
|
96
|
+
readonly brandTagline: _angular_core.InputSignal<string | undefined>;
|
|
97
|
+
/** Logo compacto para mobile, sobre fondo claro. Sin esto, reutiliza `brandLogoSrc`. */
|
|
98
|
+
readonly brandLogoMobileSrc: _angular_core.InputSignal<string | undefined>;
|
|
99
|
+
/** Superficie del panel derecho. Default `'gradient'`; `'plain'` preserva el fondo liso histórico. */
|
|
100
|
+
readonly backgroundVariant: _angular_core.InputSignal<AuthLayoutBackground>;
|
|
101
|
+
/** Envuelve el contenido proyectado con la superficie de `kf-card` (fondo, borde, sombra). Default `false` — preserva el comportamiento histórico. */
|
|
102
|
+
readonly card: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
103
|
+
/** Título del encabezado dentro de la card (`title-lg`). Sin este input, no se renderiza ningún encabezado. */
|
|
104
|
+
readonly title: _angular_core.InputSignal<string | undefined>;
|
|
105
|
+
/** Subtítulo del encabezado (`body-muted`), debajo de `title`. Sin efecto si `title` no está presente. */
|
|
106
|
+
readonly subtitle: _angular_core.InputSignal<string | undefined>;
|
|
107
|
+
/** Presencia de contenido en el slot `[kfAuthLayoutSso]` — controla si se renderiza el separador "o". */
|
|
108
|
+
protected readonly ssoContent: _angular_core.Signal<AuthLayoutSso | undefined>;
|
|
109
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthLayout, never>;
|
|
110
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<AuthLayout, "kf-auth-layout", never, { "brand": { "alias": "brand"; "required": true; "isSignal": true; }; "brandLogoSrc": { "alias": "brandLogoSrc"; "required": false; "isSignal": true; }; "brandTagline": { "alias": "brandTagline"; "required": false; "isSignal": true; }; "brandLogoMobileSrc": { "alias": "brandLogoMobileSrc"; "required": false; "isSignal": true; }; "backgroundVariant": { "alias": "backgroundVariant"; "required": false; "isSignal": true; }; "card": { "alias": "card"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; }, {}, ["ssoContent"], ["[kfAuthLayoutSso]", "*"], true, never>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Botón de cerrar sesión, pensado para proyectarse dentro de
|
|
115
|
+
* `[kf-drawer-footer]` de `kf-drawer`, o junto a `kf-drawer-session` dentro
|
|
116
|
+
* de `[kf-sidebar-footer]` de `kf-sidebar-shell` — separado de
|
|
117
|
+
* `kf-drawer-session` (que solo muestra identidad: brand, avatar, nombre,
|
|
118
|
+
* email), no anidado dentro de ella.
|
|
119
|
+
*
|
|
120
|
+
* Ícono `log-out` + label, color `--kf-color-error` con hover en
|
|
121
|
+
* `--kf-color-error-soft` y foco visible con `--kf-shadow-focus`. Separado
|
|
122
|
+
* de `kf-drawer-session` (solo identidad) por responsabilidad única.
|
|
123
|
+
*
|
|
124
|
+
* No sabe nada de autenticación real — solo emite `logoutClick` cuando el
|
|
125
|
+
* consumidor debe cerrar la sesión real.
|
|
126
|
+
*
|
|
127
|
+
* `collapsed` oculta el label y centra el ícono, exponiéndolo vía `title`
|
|
128
|
+
* — mismo criterio que `SidebarNavItem.collapsed` y
|
|
129
|
+
* `DrawerSession.collapsed`, para cuando este botón vive dentro de un
|
|
130
|
+
* `kf-sidebar-shell` colapsado.
|
|
131
|
+
*
|
|
132
|
+
* <kf-drawer-logout kf-portal-header-footer (logoutClick)="onLogout()" />
|
|
133
|
+
*/
|
|
134
|
+
declare class DrawerLogout {
|
|
135
|
+
/** Label del botón, en español neutro por defecto. Input opcional por si
|
|
136
|
+
* algún consumidor futuro necesita otro texto. */
|
|
137
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
138
|
+
/** Oculta el label y centra el ícono — ver comentario de la clase. */
|
|
139
|
+
readonly collapsed: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
140
|
+
readonly logoutClick: _angular_core.OutputEmitterRef<void>;
|
|
141
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DrawerLogout, never>;
|
|
142
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerLogout, "kf-drawer-logout", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; }, { "logoutClick": "logoutClick"; }, never, never, true, never>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Bloque de identidad para `[kf-drawer-header]` de `kf-drawer` o
|
|
147
|
+
* `[kf-sidebar-footer]` de `kf-sidebar-shell`: avatar + nombre + email,
|
|
148
|
+
* brand opcional arriba. Solo identidad — el logout vive aparte, en
|
|
149
|
+
* `kf-drawer-logout`.
|
|
150
|
+
*
|
|
151
|
+
* `collapsed` oculta brand/nombre/email y deja solo el avatar (para un
|
|
152
|
+
* `kf-sidebar-shell` colapsado). `interactive` convierte la tarjeta en un
|
|
153
|
+
* botón real que emite `cardClick`, para cuando la identidad es el
|
|
154
|
+
* disparador de un menú de acciones (ej. envuelta en `kf-dropdown`).
|
|
155
|
+
*
|
|
156
|
+
* <kf-dropdown [(open)]="menuOpen">
|
|
157
|
+
* <kf-drawer-session interactive name="Juan Pérez" email="juan@empresa.com" (cardClick)="menuOpen.set(!menuOpen())" />
|
|
158
|
+
* <kf-dropdown-panel variant="dark">
|
|
159
|
+
* <kf-dropdown-item icon="log-out" tone="error" (click)="onLogout()">Cerrar sesión</kf-dropdown-item>
|
|
160
|
+
* </kf-dropdown-panel>
|
|
161
|
+
* </kf-dropdown>
|
|
162
|
+
*/
|
|
163
|
+
declare class DrawerSession {
|
|
164
|
+
readonly name: _angular_core.InputSignal<string>;
|
|
165
|
+
readonly email: _angular_core.InputSignal<string>;
|
|
166
|
+
/**
|
|
167
|
+
* Etiqueta de rol o función del usuario dentro de la sesión (ej.
|
|
168
|
+
* "Coordinador", "Supervisor"). Se muestra como badge dentro de la
|
|
169
|
+
* identidad, debajo del email — distinto de `brand`, que es la marca o
|
|
170
|
+
* cliente mostrada como encabezado de todo el bloque, no un atributo de
|
|
171
|
+
* la persona.
|
|
172
|
+
*/
|
|
173
|
+
readonly role: _angular_core.InputSignal<string>;
|
|
174
|
+
readonly initials: _angular_core.InputSignal<string>;
|
|
175
|
+
readonly avatarUrl: _angular_core.InputSignal<string>;
|
|
176
|
+
/** Label superior opcional, ej. "Portal Kaufmann LATAM". */
|
|
177
|
+
readonly brand: _angular_core.InputSignal<string>;
|
|
178
|
+
/** Oculta brand/nombre/email y centra el avatar — ver comentario de la clase. */
|
|
179
|
+
readonly collapsed: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
180
|
+
/** Convierte la tarjeta en un botón real con ícono de kebab — ver comentario de la clase. */
|
|
181
|
+
readonly interactive: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
182
|
+
/** Se emite al clickear la tarjeta, solo cuando `interactive` es `true`. */
|
|
183
|
+
readonly cardClick: _angular_core.OutputEmitterRef<void>;
|
|
184
|
+
/** Si no se pasa `initials`, se derivan de `name`: primera letra de cada
|
|
185
|
+
* una de las primeras 2 palabras, en mayúscula. */
|
|
186
|
+
protected readonly displayInitials: _angular_core.Signal<string>;
|
|
187
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DrawerSession, never>;
|
|
188
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DrawerSession, "kf-drawer-session", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "email": { "alias": "email"; "required": false; "isSignal": true; }; "role": { "alias": "role"; "required": false; "isSignal": true; }; "initials": { "alias": "initials"; "required": false; "isSignal": true; }; "avatarUrl": { "alias": "avatarUrl"; "required": false; "isSignal": true; }; "brand": { "alias": "brand"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "cardClick": "cardClick"; }, never, never, true, never>;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
type SsoProvider = 'microsoft';
|
|
192
|
+
/** Copy y glyph por proveedor — agregar una entrada acá es todo lo que hace
|
|
193
|
+
* falta para soportar un proveedor nuevo (ej. `google`), sin tocar el
|
|
194
|
+
* template ni los estilos del componente. */
|
|
195
|
+
interface SsoProviderConfig {
|
|
196
|
+
readonly label: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Botón de inicio de sesión vía SSO corporativo — pensado como pieza suelta,
|
|
200
|
+
* no acoplada a `kf-auth-layout`: cualquier consumidor puede usarlo solo,
|
|
201
|
+
* dentro o fuera del slot `[sso]` de `AuthLayout`.
|
|
202
|
+
*
|
|
203
|
+
* `provider` resuelve copy y glyph — hoy solo `'microsoft'` (el método
|
|
204
|
+
* principal de acceso del ecosistema, cuenta corporativa de Grupo Kaufmann),
|
|
205
|
+
* con la puerta abierta a sumar otros a futuro sin romper la API existente.
|
|
206
|
+
*
|
|
207
|
+
* El glyph es el ícono GENÉRICO de 4 cuadrados de colores que Microsoft
|
|
208
|
+
* publica en sus propias guías de marca para botones de terceros ("Sign in
|
|
209
|
+
* with Microsoft") — nunca el logotipo/wordmark oficial completo. No vive en
|
|
210
|
+
* el sprite de `kf-icon` (`icon-sprite.ts`) a propósito: ese catálogo es
|
|
211
|
+
* monocromático (`currentColor`, ver `Icon.ts`), pensado para trazos de un
|
|
212
|
+
* solo color — este glyph necesita sus 4 colores fijos tal como los define
|
|
213
|
+
* la guía de marca, así que un SVG inline propio es la opción correcta, no
|
|
214
|
+
* un glyph nuevo forzado al sprite compartido.
|
|
215
|
+
*
|
|
216
|
+
* El label por defecto viene de `provider` — pasar contenido propio via
|
|
217
|
+
* `<ng-content>` lo reemplaza (ej. un texto más corto en un lugar angosto).
|
|
218
|
+
*
|
|
219
|
+
* <kf-sso-button provider="microsoft" (ssoClick)="loginWithMicrosoft()" />
|
|
220
|
+
* <kf-sso-button provider="microsoft" [loading]="loggingIn()">
|
|
221
|
+
* Ingresar con cuenta corporativa
|
|
222
|
+
* </kf-sso-button>
|
|
223
|
+
*/
|
|
224
|
+
declare class SsoButton {
|
|
225
|
+
readonly provider: _angular_core.InputSignal<"microsoft">;
|
|
226
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
227
|
+
/** Reemplaza el glyph + label por `kf-spinner` y fuerza `disabled` — mismo
|
|
228
|
+
* patrón que `kf-button[loading]`. */
|
|
229
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
230
|
+
/** Igual que `kf-button`: por defecto `submit` dentro de un `<form>`, pero
|
|
231
|
+
* este botón normalmente vive fuera de cualquier form (dispara un
|
|
232
|
+
* redirect a Microsoft Entra ID), así que casi siempre conviene `button`. */
|
|
233
|
+
readonly type: _angular_core.InputSignal<"button" | "submit">;
|
|
234
|
+
protected readonly config: _angular_core.Signal<SsoProviderConfig>;
|
|
235
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SsoButton, never>;
|
|
236
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SsoButton, "kf-sso-button", never, { "provider": { "alias": "provider"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export { AuthLayout, AuthLayoutSso, DrawerLogout, DrawerSession, SsoButton };
|
|
240
|
+
export type { AuthLayoutBackground, SsoProvider };
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { TemplateRef } from '@angular/core';
|
|
3
|
+
import { DataTableColumn, IconName } from '@kaufmann-lab/ui/core';
|
|
4
|
+
export { DataTableColumn } from '@kaufmann-lab/ui/core';
|
|
5
|
+
|
|
6
|
+
/** Metadato clave mostrado junto al selector (RUC, identificación, sucursal). */
|
|
7
|
+
interface CompanySelectorMeta {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Conmutador de empresa activa con metadatos clave (página 32) — encabeza
|
|
13
|
+
* la pantalla de inicio del portal. Compone `kf-select` para el propio
|
|
14
|
+
* selector (mismo panel propio, sin `<select>` nativo) y proyecta hasta 3
|
|
15
|
+
* pares label/valor (RUC, Identificación, Sucursal en el ejemplo del PDF).
|
|
16
|
+
*
|
|
17
|
+
* <kf-company-selector
|
|
18
|
+
* label="Selecciona empresa"
|
|
19
|
+
* [companies]="['TRANSPORTES DEL SUR S.A.C.', 'ANDES MAQ LTDA.']"
|
|
20
|
+
* [value]="activeCompany()"
|
|
21
|
+
* (valueChange)="activeCompany.set($event)"
|
|
22
|
+
* [meta]="[
|
|
23
|
+
* { label: 'RUC', value: '20448712359' },
|
|
24
|
+
* { label: 'Identificación', value: '0004002232' },
|
|
25
|
+
* { label: 'Sucursal', value: 'Sucursal Norte' },
|
|
26
|
+
* ]"
|
|
27
|
+
* />
|
|
28
|
+
*/
|
|
29
|
+
declare class CompanySelector {
|
|
30
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
31
|
+
readonly companies: _angular_core.InputSignal<string[]>;
|
|
32
|
+
readonly value: _angular_core.InputSignal<string | undefined>;
|
|
33
|
+
readonly meta: _angular_core.InputSignal<CompanySelectorMeta[]>;
|
|
34
|
+
readonly valueChange: _angular_core.OutputEmitterRef<string>;
|
|
35
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<CompanySelector, never>;
|
|
36
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<CompanySelector, "kf-company-selector", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "companies": { "alias": "companies"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Chip de filtro genérico con contador — nunca hardcodeado a un dominio
|
|
40
|
+
* concreto (ej. estado de una cotización); el consumidor decide qué
|
|
41
|
+
* representa cada `value` y cómo mapea sus items contra él vía `predicate`.
|
|
42
|
+
*
|
|
43
|
+
* Bug real corregido: la primera versión leía `item.status`/`item.chip` por
|
|
44
|
+
* nombre de campo mágico en vez de un `predicate` — colisionaba con
|
|
45
|
+
* dominios donde `status` ya significa otra cosa (ej. `Quote.status` en
|
|
46
|
+
* `web-otd-frontend` es 'ok'|'error'|'warn' de aprobación, no "tiene saldo
|
|
47
|
+
* pendiente"). Un chip "Con saldo pendiente" sobre cotizaciones terminaba
|
|
48
|
+
* filtrando por un campo que no tenía nada que ver, mostrando 0 resultados
|
|
49
|
+
* siempre. `predicate` es explícito y no depende de convenciones de nombre. */
|
|
50
|
+
interface QuotePickerChip<T = unknown> {
|
|
51
|
+
value: string;
|
|
52
|
+
label: string;
|
|
53
|
+
count: number;
|
|
54
|
+
predicate: (item: T) => boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Una opción del dropdown "Ordenar por", visible solo en `variant="modal"`. */
|
|
57
|
+
interface QuotePickerSortOption {
|
|
58
|
+
value: string;
|
|
59
|
+
label: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Selector de un ítem "rico" de una lista buscable/filtrable — generalización
|
|
63
|
+
* del patrón "elegir una cotización" de Pagos y Facturas de OTD, pero sin
|
|
64
|
+
* ningún acoplamiento a `Quote`: todo el contenido de cada fila/card llega
|
|
65
|
+
* por `columns` (mismo `DataTableColumn` de `kf-data-table`, reexportado acá
|
|
66
|
+
* en vez de duplicar el concepto) + `cellTemplates` para contenido custom
|
|
67
|
+
* (thumbnail, monto formateado, etc. — mismo mecanismo `TemplateRef` +
|
|
68
|
+
* `ngTemplateOutlet` que ya usa `kf-data-table`).
|
|
69
|
+
*
|
|
70
|
+
* Un solo componente, dos contenedores (`variant: 'inline' | 'modal'`), UNA
|
|
71
|
+
* sola lógica de búsqueda/filtro/orden interna. Nunca dos implementaciones
|
|
72
|
+
* paralelas: el riesgo real de eso es que un fix de filtro se aplique en un
|
|
73
|
+
* modo y se olvide en el otro. Los `computed()` de más abajo
|
|
74
|
+
* (`filteredItems`, `sortedItems`) son la ÚNICA fuente de verdad para ambos
|
|
75
|
+
* `variant`; lo que cambia entre inline y modal es solo qué contenedor
|
|
76
|
+
* envuelve esos datos ya resueltos.
|
|
77
|
+
*
|
|
78
|
+
* ## Modo `inline` (default)
|
|
79
|
+
* Trigger a ANCHO COMPLETO (nunca una caja angosta de ancho fijo) que
|
|
80
|
+
* muestra el ítem activo colapsado — thumbnail, id + modelo, unidades +
|
|
81
|
+
* fecha + monto, CTA "Cambiar cotización" con chevron-down. Al click, el
|
|
82
|
+
* panel se expande INLINE (empuja el contenido de abajo, nunca flota
|
|
83
|
+
* encima) con buscador propio + chips de filtro + un grid de 2 columnas (1
|
|
84
|
+
* en mobile, breakpoint `max-width: 900px` vía `matchMediaSignal` — mismo
|
|
85
|
+
* mecanismo que ya usa el resto de la librería para decisiones de layout en
|
|
86
|
+
* TypeScript, no solo CSS). Por encima de `expandThreshold` resultados
|
|
87
|
+
* visibles, el panel recorta a un preview de `PREVIEW_ROWS` filas con un
|
|
88
|
+
* fade inferior y un botón dashed "Ver las N en pantalla completa" que
|
|
89
|
+
* emite `expandToModal` — el picker no decide qué pasa después (típicamente
|
|
90
|
+
* el consumidor pone `variant` en `'modal'` y `open` en `true`).
|
|
91
|
+
*
|
|
92
|
+
* ## Modo `modal`
|
|
93
|
+
* Mismo buscador, mismos chips, misma lógica de filtrado — compone
|
|
94
|
+
* `kf-modal` (proyectando el contenido) en vez de reimplementar un
|
|
95
|
+
* `<dialog>` a mano: la API de `Modal` (`[(open)]`, cierre con
|
|
96
|
+
* Escape/backdrop/botón vía `<dialog>` nativo) ya cubre exactamente lo que
|
|
97
|
+
* este modo necesita. Compone también `kf-data-table` para la tabla
|
|
98
|
+
* completa (columnas configurables, fade de overflow horizontal ya
|
|
99
|
+
* resuelto ahí) y `kf-pagination` para paginar — ninguno de los tres se
|
|
100
|
+
* reimplementa. Agrega un dropdown propio de "Ordenar por" (calibrado
|
|
101
|
+
* visualmente contra el trigger de `kf-select`, pero compacto: `kf-select`
|
|
102
|
+
* fuerza un ancho fijo de 240px pensado para formularios, no para una
|
|
103
|
+
* barra de herramientas de tabla — ver JSDoc de `sortOpen` más abajo).
|
|
104
|
+
*
|
|
105
|
+
* En mobile, `kf-data-table[cardable]` con `defaultView` forzado a
|
|
106
|
+
* `'cards'` decide la vista (mismo criterio que `matchMediaSignal` ya
|
|
107
|
+
* resolvió en otros consumidores): dentro de un modal a pantalla completa
|
|
108
|
+
* no tiene sentido ofrecer un toggle tabla/cards que en mobile daría una
|
|
109
|
+
* tabla angosta con scroll horizontal.
|
|
110
|
+
*
|
|
111
|
+
* DEUDA TÉCNICA CONOCIDA (confirmada con el usuario, ver CHANGELOG.md): el
|
|
112
|
+
* diseño validado con mockups pedía que en mobile el modal ocupe el 100%
|
|
113
|
+
* de la pantalla (botón "atrás", sin overlay centrado) — `kf-modal` no
|
|
114
|
+
* tiene ese modo, así que hoy en mobile se ve como un diálogo centrado
|
|
115
|
+
* angosto (`width: min(480px, ...)`). Es funcional (cards legibles,
|
|
116
|
+
* búsqueda, chips, paginación), solo visualmente distinto del mockup.
|
|
117
|
+
*
|
|
118
|
+
* <kf-quote-picker
|
|
119
|
+
* [items]="quotes()"
|
|
120
|
+
* [columns]="columns"
|
|
121
|
+
* [selectedId]="selectedQuoteId()"
|
|
122
|
+
* [idKey]="(q) => q.id"
|
|
123
|
+
* [chips]="statusChips()"
|
|
124
|
+
* [cellTemplates]="{ photo: photoCell(), amount: amountCell() }"
|
|
125
|
+
* (selectedIdChange)="selectedQuoteId.set($event)"
|
|
126
|
+
* (expandToModal)="variant.set('modal'); open.set(true)"
|
|
127
|
+
* />
|
|
128
|
+
*/
|
|
129
|
+
declare class QuotePicker<T = unknown> {
|
|
130
|
+
readonly items: _angular_core.InputSignal<T[]>;
|
|
131
|
+
readonly columns: _angular_core.InputSignal<DataTableColumn[]>;
|
|
132
|
+
readonly selectedId: _angular_core.InputSignal<string | null>;
|
|
133
|
+
readonly idKey: _angular_core.InputSignal<(item: T) => string>;
|
|
134
|
+
/**
|
|
135
|
+
* Mapa `columnKey -> TemplateRef`, mismo mecanismo que `kf-data-table`
|
|
136
|
+
* (`ngTemplateOutlet` + contexto `{ $implicit: item, index }`) — se
|
|
137
|
+
* reenvía tal cual a la tabla interna del modo `modal`, y se usa
|
|
138
|
+
* directamente en el grid de cards del modo `inline`. Un solo mapa para
|
|
139
|
+
* ambos modos, consistente con la regla de "una sola lógica interna".
|
|
140
|
+
*/
|
|
141
|
+
readonly cellTemplates: _angular_core.InputSignal<Record<string, TemplateRef<{
|
|
142
|
+
$implicit: T;
|
|
143
|
+
index: number;
|
|
144
|
+
}>> | undefined>;
|
|
145
|
+
readonly chips: _angular_core.InputSignal<QuotePickerChip<T>[]>;
|
|
146
|
+
readonly sortOptions: _angular_core.InputSignal<QuotePickerSortOption[]>;
|
|
147
|
+
readonly sort: _angular_core.ModelSignal<string | null>;
|
|
148
|
+
/**
|
|
149
|
+
* Umbral de volumen alto — el consumidor decide el número exacto, nunca
|
|
150
|
+
* hardcodeado a "cotizaciones" ni a ningún caso de uso puntual. Default
|
|
151
|
+
* 15 según el diseño validado con mockups.
|
|
152
|
+
*/
|
|
153
|
+
readonly expandThreshold: _angular_core.InputSignal<number>;
|
|
154
|
+
readonly variant: _angular_core.InputSignal<"inline" | "modal">;
|
|
155
|
+
/** Visibilidad del modo `modal`, two-way — mismo patrón que `[(open)]` de `kf-modal`. */
|
|
156
|
+
readonly open: _angular_core.ModelSignal<boolean>;
|
|
157
|
+
readonly title: _angular_core.InputSignal<string>;
|
|
158
|
+
readonly searchPlaceholder: _angular_core.InputSignal<string>;
|
|
159
|
+
/** Ícono de placeholder cuando ninguna columna `cardRole: 'media'` resuelve
|
|
160
|
+
* un thumbnail real vía `cellTemplates` — el picker no asume qué dominio
|
|
161
|
+
* consume (cotización, vehículo, cliente...), así que no hardcodea un
|
|
162
|
+
* ícono fijo. Default `'file'` solo por no dejar el input sin valor. */
|
|
163
|
+
readonly placeholderIcon: _angular_core.InputSignal<IconName>;
|
|
164
|
+
readonly selectedIdChange: _angular_core.OutputEmitterRef<string>;
|
|
165
|
+
/** Disparado al superar `expandThreshold` en modo inline; el consumidor decide pasar a `modal`. */
|
|
166
|
+
readonly expandToModal: _angular_core.OutputEmitterRef<void>;
|
|
167
|
+
protected readonly searchQuery: _angular_core.WritableSignal<string>;
|
|
168
|
+
protected readonly activeChip: _angular_core.WritableSignal<string | null>;
|
|
169
|
+
protected readonly expanded: _angular_core.WritableSignal<boolean>;
|
|
170
|
+
protected readonly page: _angular_core.WritableSignal<number>;
|
|
171
|
+
protected readonly sortOpen: _angular_core.WritableSignal<boolean>;
|
|
172
|
+
/**
|
|
173
|
+
* Mismo breakpoint (`max-width: 900px`) que el resto de la librería usa
|
|
174
|
+
* para decisiones de layout en TypeScript (no solo CSS) — ver
|
|
175
|
+
* `matchMediaSignal`. Decide 1 vs. 2 columnas en el grid inline, y tabla
|
|
176
|
+
* vs. cards apiladas dentro del modal.
|
|
177
|
+
*/
|
|
178
|
+
protected readonly isMobile: _angular_core.Signal<boolean>;
|
|
179
|
+
private readonly destroyRef;
|
|
180
|
+
private readonly previewScrollEl;
|
|
181
|
+
/** Mismo mecanismo de fade que `kf-data-table` — ver comentario en QuotePicker.css. */
|
|
182
|
+
protected readonly canFadeBottom: _angular_core.WritableSignal<boolean>;
|
|
183
|
+
readonly selectedItem: _angular_core.Signal<T | undefined>;
|
|
184
|
+
/** Filtro por texto (buscador propio) + filtro por chip activo, en ese orden. */
|
|
185
|
+
protected readonly filteredItems: _angular_core.Signal<T[]>;
|
|
186
|
+
/**
|
|
187
|
+
* Orden solo tiene efecto visible en modo `modal` (el diseño validado no
|
|
188
|
+
* pide dropdown de orden en inline) — se calcula igual en ambos casos
|
|
189
|
+
* porque es la MISMA lógica interna; en inline `sort()` simplemente se
|
|
190
|
+
* queda en `null` salvo que el consumidor lo setee explícitamente.
|
|
191
|
+
*/
|
|
192
|
+
protected readonly sortedItems: _angular_core.Signal<T[]>;
|
|
193
|
+
/** Por encima del umbral, el preview inline se recorta salvo que el usuario ya haya expandido. */
|
|
194
|
+
protected readonly isHighVolume: _angular_core.Signal<boolean>;
|
|
195
|
+
protected readonly previewItems: _angular_core.Signal<T[]>;
|
|
196
|
+
protected readonly pages: _angular_core.Signal<number>;
|
|
197
|
+
protected readonly pagedItems: _angular_core.Signal<T[]>;
|
|
198
|
+
protected readonly sortLabel: _angular_core.Signal<string>;
|
|
199
|
+
constructor();
|
|
200
|
+
private updateFadeState;
|
|
201
|
+
private cellText;
|
|
202
|
+
toggleExpandedPanel(): void;
|
|
203
|
+
onSearchInput(event: Event): void;
|
|
204
|
+
selectChip(value: string): void;
|
|
205
|
+
select(item: T): void;
|
|
206
|
+
onItemKeydown(event: KeyboardEvent, item: T): void;
|
|
207
|
+
onSeeAll(): void;
|
|
208
|
+
onTableRowClick(event: {
|
|
209
|
+
row: T;
|
|
210
|
+
index: number;
|
|
211
|
+
}): void;
|
|
212
|
+
toggleSort(): void;
|
|
213
|
+
setSort(value: string): void;
|
|
214
|
+
trackItem(item: T, index: number): string | number;
|
|
215
|
+
/** Arrow function como campo (no un método) para que `[rowKey]` reciba
|
|
216
|
+
* una referencia ESTABLE entre change detections — `trackItem.bind(this)`
|
|
217
|
+
* en el template recrearía una función nueva en cada ciclo, invalidando
|
|
218
|
+
* cualquier optimización de `kf-data-table` que dependa de identidad. */
|
|
219
|
+
protected readonly rowKeyFn: (item: T, index: number) => string | number;
|
|
220
|
+
protected cellValue(item: T, column: DataTableColumn): string;
|
|
221
|
+
protected readonly mediaColumn: _angular_core.Signal<DataTableColumn | undefined>;
|
|
222
|
+
protected readonly titleColumn: _angular_core.Signal<DataTableColumn | undefined>;
|
|
223
|
+
protected readonly fieldColumns: _angular_core.Signal<DataTableColumn[]>;
|
|
224
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<QuotePicker<any>, never>;
|
|
225
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<QuotePicker<any>, "kf-quote-picker", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "selectedId": { "alias": "selectedId"; "required": false; "isSignal": true; }; "idKey": { "alias": "idKey"; "required": true; "isSignal": true; }; "cellTemplates": { "alias": "cellTemplates"; "required": false; "isSignal": true; }; "chips": { "alias": "chips"; "required": false; "isSignal": true; }; "sortOptions": { "alias": "sortOptions"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "expandThreshold": { "alias": "expandThreshold"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "placeholderIcon": { "alias": "placeholderIcon"; "required": false; "isSignal": true; }; }, { "sort": "sortChange"; "open": "openChange"; "selectedIdChange": "selectedIdChange"; "expandToModal": "expandToModal"; }, never, never, true, never>;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Estado vacío de reservas en taller con llamada a agendar (página 36):
|
|
230
|
+
* barra de estado vacío arriba ("No tienes reservas de taller"), panel de
|
|
231
|
+
* invitación al medio (ícono en círculo azul, título, descripción, link) y
|
|
232
|
+
* una fila de dos acciones al pie — un slot `[actions]` proyectado, para no
|
|
233
|
+
* acoplar el componente a botones fijos.
|
|
234
|
+
*
|
|
235
|
+
* Distinto de `kf-empty-state` genérico: este combina la barra + la
|
|
236
|
+
* invitación + las acciones como un bloque compuesto propio del dominio
|
|
237
|
+
* "taller", no un placeholder de una sola pieza.
|
|
238
|
+
*
|
|
239
|
+
* `grow` estira el panel de invitación para llenar el espacio vertical
|
|
240
|
+
* disponible — solo cuando el consumidor comparte fila con una tarjeta más
|
|
241
|
+
* alta (ej. junto a "Total de vehículos"); en un lugar sin esa presión
|
|
242
|
+
* (home, debajo del carousel) se deja en su alto natural.
|
|
243
|
+
*
|
|
244
|
+
* <kf-reserve-block emptyLabel="No tienes reservas de taller" grow
|
|
245
|
+
* title="¿Necesitas mantención?" description="Tenemos la mejor red de talleres."
|
|
246
|
+
* actionLabel="Agenda tu reserva aquí" actionHref="/taller/agendar">
|
|
247
|
+
* <kf-button actions icon="calendar">Reservar hora</kf-button>
|
|
248
|
+
* <kf-button actions variant="outline" icon="list">Ver agenda</kf-button>
|
|
249
|
+
* </kf-reserve-block>
|
|
250
|
+
*
|
|
251
|
+
* Para apps con router: escuchar `actionClick` y llamar
|
|
252
|
+
* `event.preventDefault()` antes de `router.navigateByUrl(...)`. El
|
|
253
|
+
* `actionHref` se mantiene igual para que click-medio, "abrir en pestaña
|
|
254
|
+
* nueva" y el hover de la barra de estado sigan funcionando.
|
|
255
|
+
*
|
|
256
|
+
* <kf-reserve-block title="¿Necesitas mantención?" actionLabel="Agenda tu reserva aquí"
|
|
257
|
+
* actionHref="/taller/agendar"
|
|
258
|
+
* (actionClick)="$event.preventDefault(); router.navigateByUrl('/taller/agendar')" />
|
|
259
|
+
*/
|
|
260
|
+
declare class ReserveBlock {
|
|
261
|
+
readonly emptyLabel: _angular_core.InputSignal<string>;
|
|
262
|
+
readonly title: _angular_core.InputSignal<string>;
|
|
263
|
+
readonly description: _angular_core.InputSignal<string | undefined>;
|
|
264
|
+
readonly actionLabel: _angular_core.InputSignal<string | undefined>;
|
|
265
|
+
readonly actionHref: _angular_core.InputSignal<string | undefined>;
|
|
266
|
+
/** La invitación se estira para llenar la tarjeta (ej. junto a "Total de vehículos"). */
|
|
267
|
+
readonly grow: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
268
|
+
/**
|
|
269
|
+
* Click en el link de la invitación. Incluye el `MouseEvent` para que un
|
|
270
|
+
* consumidor con router pueda cortar la navegación nativa — mismo patrón
|
|
271
|
+
* que `itemClick` de `kf-breadcrumb`, sin depender de `@angular/router`.
|
|
272
|
+
*/
|
|
273
|
+
readonly actionClick: _angular_core.OutputEmitterRef<MouseEvent>;
|
|
274
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ReserveBlock, never>;
|
|
275
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ReserveBlock, "kf-reserve-block", never, { "emptyLabel": { "alias": "emptyLabel"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; "actionHref": { "alias": "actionHref"; "required": false; "isSignal": true; }; "grow": { "alias": "grow"; "required": false; "isSignal": true; }; }, { "actionClick": "actionClick"; }, never, ["[actions]"], true, never>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Estado puntual mostrado junto a la identidad del vehículo (ej. "En ruta",
|
|
280
|
+
* "Mantenimiento", "Fuera de servicio"). `tone` define el color semántico:
|
|
281
|
+
* "crit" no tiene token propio en base.css, se mapea a var(--kf-color-error).
|
|
282
|
+
*/
|
|
283
|
+
interface VehicleHeaderStatus {
|
|
284
|
+
label: string;
|
|
285
|
+
tone?: 'ok' | 'warn' | 'crit';
|
|
286
|
+
icon?: IconName;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Header de identidad de un vehículo de flota: unidad (patente/id), modelo
|
|
290
|
+
* (como badge, no texto plano — página 24: "ABC-123" junto a un badge
|
|
291
|
+
* "TITAN 4X2"), VIN en fuente mono y un estado opcional. Un área de acciones
|
|
292
|
+
* opcional se proyecta vía `<ng-content select="[actions]">` para no acoplar
|
|
293
|
+
* el componente a un set fijo de botones — el patrón real de la spec es
|
|
294
|
+
* `kf-button variant="outline"` (ej. "Llamar", con ícono) + un `primary`
|
|
295
|
+
* (ej. "Crear Ticket", con ícono "+"):
|
|
296
|
+
*
|
|
297
|
+
* <kf-vehicle-header unit="AB123CD" model="Sprinter 415" vin="9BW..."
|
|
298
|
+
* [status]="{ label: 'En ruta', tone: 'ok' }">
|
|
299
|
+
* <kf-button actions variant="outline" icon="phone">Llamar</kf-button>
|
|
300
|
+
* <kf-button actions icon="plus">Crear Ticket</kf-button>
|
|
301
|
+
* </kf-vehicle-header>
|
|
302
|
+
*/
|
|
303
|
+
declare class VehicleHeader {
|
|
304
|
+
readonly unit: _angular_core.InputSignal<string>;
|
|
305
|
+
readonly model: _angular_core.InputSignal<string | undefined>;
|
|
306
|
+
readonly vin: _angular_core.InputSignal<string | undefined>;
|
|
307
|
+
readonly status: _angular_core.InputSignal<VehicleHeaderStatus | undefined>;
|
|
308
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<VehicleHeader, never>;
|
|
309
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<VehicleHeader, "kf-vehicle-header", never, { "unit": { "alias": "unit"; "required": true; "isSignal": true; }; "model": { "alias": "model"; "required": false; "isSignal": true; }; "vin": { "alias": "vin"; "required": false; "isSignal": true; }; "status": { "alias": "status"; "required": false; "isSignal": true; }; }, {}, never, ["[actions]"], true, never>;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export { CompanySelector, QuotePicker, ReserveBlock, VehicleHeader };
|
|
313
|
+
export type { CompanySelectorMeta, QuotePickerChip, QuotePickerSortOption, VehicleHeaderStatus };
|