valtech-components 2.0.779 → 2.0.780

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.
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Configuración del componente `val-user-avatar`.
3
+ *
4
+ * Avatar smart con cadena de fallback:
5
+ * foto (`avatarUrl`) → iniciales (de `name`/`email`) → icono persona.
6
+ *
7
+ * Diseñado para headers, perfiles, listas de usuarios y dropdowns.
8
+ *
9
+ * @example Con user completo (greeting hero):
10
+ * ```html
11
+ * <val-user-avatar [props]="{ user: auth.user(), size: 'medium' }" />
12
+ * ```
13
+ *
14
+ * @example Standalone fields:
15
+ * ```html
16
+ * <val-user-avatar [props]="{ name: 'Juan Pérez', avatarUrl: '/a.jpg', size: 'small' }" />
17
+ * ```
18
+ *
19
+ * @example Header avatar clickable (link a /profile):
20
+ * ```html
21
+ * <val-user-avatar [props]="{ user: auth.user() }" (onClick)="goToProfile()" />
22
+ * ```
23
+ */
24
+ export interface UserAvatarMetadata {
25
+ /**
26
+ * User shape — pasa el resultado de `auth.user()` directamente. Cualquier
27
+ * combinación de `name`/`avatarUrl`/`email` se acepta. Tienen precedencia
28
+ * sobre los props sueltos (`name`, `email`, `avatarUrl`) abajo.
29
+ */
30
+ user?: {
31
+ name?: string;
32
+ avatarUrl?: string;
33
+ email?: string;
34
+ handle?: string;
35
+ } | null;
36
+ /** Nombre directo — usado si no hay `user` o si `user.name` está vacío. */
37
+ name?: string;
38
+ /** Email directo — usado si no hay `user` o si `user.email` está vacío. */
39
+ email?: string;
40
+ /** URL de avatar directa — usado si no hay `user` o si `user.avatarUrl` está vacío. */
41
+ avatarUrl?: string;
42
+ /**
43
+ * Tamaño:
44
+ * - `'xsmall'` 24px
45
+ * - `'small'` (default) 32px
46
+ * - `'medium'` 48px
47
+ * - `'large'` 72px
48
+ * - `'xlarge'` 96px
49
+ */
50
+ size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
51
+ /**
52
+ * Forma:
53
+ * - `'circle'` (default) — redondo completo
54
+ * - `'square'` — bordes redondeados pero cuadrado
55
+ */
56
+ shape?: 'circle' | 'square';
57
+ /**
58
+ * Color de fondo para el modo iniciales/icono. Cuando no se provee, se
59
+ * derive deterministicamente del `name`/`email` (mismo input → mismo color)
60
+ * para que el mismo user tenga siempre el mismo color.
61
+ */
62
+ background?: string;
63
+ /** Color del texto/icono cuando no hay foto. Default `'#fff'`. */
64
+ foreground?: string;
65
+ /**
66
+ * Mostrar border. Útil para overlays sobre fotos o backgrounds dark.
67
+ * Default: `false`.
68
+ */
69
+ bordered?: boolean;
70
+ /** Habilita grayscale (e.g., user desactivado). Default: `false`. */
71
+ grayscale?: boolean;
72
+ /** Clase CSS extra. */
73
+ cssClass?: string;
74
+ }
@@ -0,0 +1,50 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { UserAvatarMetadata } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * `val-user-avatar`
6
+ *
7
+ * Avatar **smart** con cadena de fallback automática:
8
+ *
9
+ * foto (`avatarUrl`) → iniciales (de `name`/`email`) → icono persona.
10
+ *
11
+ * Si la imagen falla en cargar (404, CORS, etc.), automáticamente cae a las
12
+ * iniciales sin que el caller tenga que hacer nada. Color de fondo derivado
13
+ * deterministicamente del user para que el mismo user tenga siempre el mismo
14
+ * color (a menos que `background` se sobrescriba).
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <val-user-avatar [props]="{ user: auth.user() }" (onClick)="goProfile()" />
19
+ * ```
20
+ */
21
+ export declare class UserAvatarComponent {
22
+ private readonly props_;
23
+ private readonly imageFailed;
24
+ set props(value: UserAvatarMetadata | undefined);
25
+ onClick: EventEmitter<void>;
26
+ /** Subscribers — usado para condicionar cursor/aria. */
27
+ get hasClick(): boolean;
28
+ readonly resolvedProps: import("@angular/core").Signal<UserAvatarMetadata>;
29
+ /** Resuelve los campos del user (user prop > campos sueltos). */
30
+ private readonly resolvedUser;
31
+ /** URL de imagen — empty si no hay o si la carga falló. */
32
+ readonly imageUrl: import("@angular/core").Signal<string>;
33
+ readonly showImage: import("@angular/core").Signal<boolean>;
34
+ /** Iniciales — 1-2 chars derivados de name (preferred) o email prefix. */
35
+ readonly initials: import("@angular/core").Signal<string>;
36
+ readonly sizeClass: import("@angular/core").Signal<"small" | "medium" | "large" | "xlarge" | "xsmall">;
37
+ readonly shapeClass: import("@angular/core").Signal<"circle" | "square">;
38
+ /** Background — explicito o derivado deterministicamente del user. */
39
+ readonly bgColor: import("@angular/core").Signal<string>;
40
+ readonly ariaLabel: import("@angular/core").Signal<string>;
41
+ onImageError(): void;
42
+ onImageLoad(): void;
43
+ /**
44
+ * Hash determinista string → HSL color del rango Valtech (purples/blues).
45
+ * Mismo seed → mismo color (consistencia entre sessions).
46
+ */
47
+ private colorFromSeed;
48
+ static ɵfac: i0.ɵɵFactoryDeclaration<UserAvatarComponent, never>;
49
+ static ɵcmp: i0.ɵɵComponentDeclaration<UserAvatarComponent, "val-user-avatar", never, { "props": { "alias": "props"; "required": false; }; }, { "onClick": "onClick"; }, never, never, true, never>;
50
+ }
@@ -1,21 +1,33 @@
1
- import { OnInit } from '@angular/core';
2
1
  import { NotesBoxMetadata } from './types';
3
2
  import * as i0 from "@angular/core";
4
- export declare class NotesBoxComponent implements OnInit {
5
- /**
6
- * Notes box configuration object.
7
- * @type {NotesBoxMetadata}
8
- * @property text - The main text content.
9
- * @property prefix - Optional prefix text (bold).
10
- * @property color - The background color of the box.
11
- * @property textColor - The color of the text.
12
- * @property size - The size of the text and box.
13
- * @property rounded - Whether the box has rounded corners.
14
- * @property padding - Custom padding for the box.
15
- */
3
+ /**
4
+ * `val-notes-box` — callout / admonition para resaltar información dentro de un
5
+ * flujo de texto.
6
+ *
7
+ * Diseño tipo GitHub/Docusaurus: fondo tintado suave, accent en el borde
8
+ * izquierdo, prefijo en mayúsculas pequeñas. Funciona en light & dark.
9
+ *
10
+ * El color es un Ionic Color (primary, success, warning, danger, tertiary, …).
11
+ * No usa `ion-card` ni `ion-color="X"` como background sino una mezcla
12
+ * `rgba(--ion-color-X-rgb, 0.08)` para no asfixiar el contenido.
13
+ *
14
+ * Renderiza inline HTML (`<strong>`, links via `processLinks`) cuando los
15
+ * flags están activos.
16
+ *
17
+ * @example
18
+ * <val-notes-box [props]="{
19
+ * text: 'Recordá guardar tus cambios antes de salir.',
20
+ * prefix: 'Tip',
21
+ * color: 'tertiary',
22
+ * textColor: 'dark',
23
+ * size: 'medium',
24
+ * rounded: true,
25
+ * allowPartialBold: true,
26
+ * }"></val-notes-box>
27
+ */
28
+ export declare class NotesBoxComponent {
29
+ /** Notes box configuration object. */
16
30
  props: NotesBoxMetadata;
17
- constructor();
18
- ngOnInit(): void;
19
31
  static ɵfac: i0.ɵɵFactoryDeclaration<NotesBoxComponent, never>;
20
32
  static ɵcmp: i0.ɵɵComponentDeclaration<NotesBoxComponent, "val-notes-box", never, { "props": { "alias": "props"; "required": false; }; }, {}, never, never, true, never>;
21
33
  }
@@ -213,6 +213,17 @@ export type ToolbarAction = {
213
213
  description?: string;
214
214
  /** Associated image (if any) */
215
215
  image?: ImageMetadata;
216
+ /**
217
+ * User shape para el modo `AVATAR` — habilita fallback inteligente:
218
+ * foto → iniciales (de `name`/`email`) → icono persona. Si se omite, el
219
+ * toolbar solo muestra la imagen pasada en `description`.
220
+ */
221
+ user?: {
222
+ name?: string;
223
+ email?: string;
224
+ avatarUrl?: string;
225
+ handle?: string;
226
+ } | null;
216
227
  };
217
228
  /**
218
229
  * Metadata for an icon.
@@ -87,6 +87,20 @@ export declare class AuthStateService {
87
87
  * Actualiza el userId y email (después de parsear el token).
88
88
  */
89
89
  updateUserInfo(userId: string, email: string): void;
90
+ /**
91
+ * Hidrata el state con campos del profile (nombre, handle, avatar, phone).
92
+ * Invocado tras `getProfile()` o `updateProfile()` para que consumers de
93
+ * `auth.user()` vean los campos enriched automáticamente.
94
+ *
95
+ * Cualquier campo `undefined` se ignora (no sobrescribe con null). Campos
96
+ * `null` explícitos se persisten (signal de "limpiado").
97
+ */
98
+ updateProfileFields(fields: {
99
+ name?: string | null;
100
+ handle?: string | null;
101
+ avatarUrl?: string | null;
102
+ phone?: string | null;
103
+ }): void;
90
104
  static ɵfac: i0.ɵɵFactoryDeclaration<AuthStateService, never>;
91
105
  static ɵprov: i0.ɵɵInjectableDeclaration<AuthStateService>;
92
106
  }
@@ -256,16 +256,20 @@ export declare class AuthService implements OnDestroy {
256
256
  switchOrg(organizationId: string): Observable<SwitchOrgResponse>;
257
257
  /**
258
258
  * Obtiene el perfil del usuario autenticado.
259
- * Incluye información de MFA y teléfono.
259
+ * Incluye información de MFA y teléfono. Hidrata el state automáticamente
260
+ * con `name/handle/avatarUrl/phone` para que `auth.user()` los retorne.
260
261
  */
261
262
  getProfile(): Observable<GetProfileResponse>;
262
263
  /**
263
- * Actualiza el perfil del usuario.
264
+ * Actualiza el perfil del usuario. Sincroniza state con los nuevos values
265
+ * (name/phone) — el backend response no los echo'a pero el caller ya tiene
266
+ * los valores que mandó.
264
267
  */
265
268
  updateProfile(request: UpdateProfileRequest): Observable<UpdateProfileResponse>;
266
269
  /**
267
- * Actualiza el avatar del usuario en el backend.
268
- * Nota: El estado local del avatar se maneja a través de getProfile().
270
+ * Actualiza el avatar del usuario en el backend. Sincroniza state con el
271
+ * `avatarUrl` retornado para que el header / dashboard se refresquen sin
272
+ * necesidad de un getProfile adicional.
269
273
  */
270
274
  updateAvatar(request: UpdateAvatarRequest): Observable<UpdateAvatarResponse>;
271
275
  /**
@@ -55,6 +55,14 @@ export interface AuthState {
55
55
  userId: string | null;
56
56
  /** Email del usuario */
57
57
  email: string | null;
58
+ /** Nombre completo del usuario (poblado tras `getProfile()`) */
59
+ name?: string | null;
60
+ /** Username/handle (poblado tras `getProfile()`) */
61
+ handle?: string | null;
62
+ /** URL del avatar (poblado tras `getProfile()`) */
63
+ avatarUrl?: string | null;
64
+ /** Teléfono (poblado tras `getProfile()`) */
65
+ phone?: string | null;
58
66
  /** Roles del usuario */
59
67
  roles: string[];
60
68
  /** Permisos del usuario (formato 'resource:action') */
package/lib/version.d.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * Current version of valtech-components.
3
3
  * This is automatically updated during the publish process.
4
4
  */
5
- export declare const VERSION = "2.0.779";
5
+ export declare const VERSION = "2.0.780";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "2.0.779",
3
+ "version": "2.0.780",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "valtech-firebase-config": "./src/lib/services/firebase/scripts/generate-sw-config.js"
package/public-api.d.ts CHANGED
@@ -46,6 +46,8 @@ export * from './lib/components/atoms/pattern/types';
46
46
  export * from './lib/components/atoms/pattern/motifs';
47
47
  export * from './lib/components/atoms/glass/glass.component';
48
48
  export { GlassMetadata } from './lib/components/atoms/glass/types';
49
+ export * from './lib/components/atoms/user-avatar/user-avatar.component';
50
+ export { UserAvatarMetadata } from './lib/components/atoms/user-avatar/types';
49
51
  export * from './lib/components/molecules/alert-box/alert-box.component';
50
52
  export * from './lib/components/molecules/alert-box/types';
51
53
  export * from './lib/components/molecules/button-group/button-group.component';