valtech-components 4.0.237 → 4.0.239

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.
@@ -14,13 +14,16 @@ export interface ChatComposerSendEvent {
14
14
  files: File[];
15
15
  }
16
16
  /**
17
- * val-chat-composer — barra de redacción de chat moderna (signal inputs).
17
+ * val-chat-composer — barra de redacción estilo Notion/Claude (full custom).
18
18
  *
19
- * Pill con: adjuntar (+), textarea auto-grow, y mic/enviar (mic cuando está vacío,
20
- * enviar cuando hay texto o adjuntos). Los adjuntos (botón + / pegar imagen) se
21
- * acumulan como PREVIEW (miniaturas) y se emiten por `(attach)` recién al ENVIAR
22
- * no se van solos al chat. Audio grabado se emite directo al parar.
23
- * No incluye picker de emoji: el teclado del sistema ya lo trae.
19
+ * El editor es un `contenteditable` (NO ion-textarea): crece hasta un max-height,
20
+ * soporta pegar texto plano e imágenes del portapapeles, Enter envía / Shift+Enter
21
+ * salta línea. Debajo, una fila de acciones propias: adjuntar (+), mic/enviar.
22
+ * Los adjuntos (botón / pegar / audio grabado) se acumulan como miniaturas de
23
+ * PREVIEW y se mandan en UN solo evento `send {text, files}` (caption + adjuntos).
24
+ *
25
+ * Pensado para vivir en un contenedor fijo al fondo del viewport (el consumer
26
+ * ancla la posición). No incluye emoji picker (el teclado del sistema lo trae).
24
27
  */
25
28
  export declare class ChatComposerComponent implements OnDestroy {
26
29
  private i18n;
@@ -34,6 +37,7 @@ export declare class ChatComposerComponent implements OnDestroy {
34
37
  readonly typing: import("@angular/core").OutputEmitterRef<void>;
35
38
  readonly voice: import("@angular/core").OutputEmitterRef<void>;
36
39
  readonly cancelReply: import("@angular/core").OutputEmitterRef<void>;
40
+ private readonly editableRef;
37
41
  protected readonly body: import("@angular/core").WritableSignal<string>;
38
42
  protected readonly pending: import("@angular/core").WritableSignal<PendingAttachment[]>;
39
43
  private pendingId;
@@ -48,19 +52,17 @@ export declare class ChatComposerComponent implements OnDestroy {
48
52
  constructor();
49
53
  protected readonly canSend: import("@angular/core").Signal<boolean>;
50
54
  protected readonly placeholderText: import("@angular/core").Signal<string>;
51
- protected onInput(event: Event): void;
55
+ /** Lee el texto del contenteditable a la signal `body`. */
56
+ protected syncBody(): void;
52
57
  protected onKeydown(event: KeyboardEvent): void;
58
+ /** Pegar: texto plano (sin formato) + imágenes del portapapeles. */
59
+ protected onPaste(event: ClipboardEvent): void;
53
60
  protected onSend(): void;
61
+ private clearEditable;
54
62
  protected onFile(event: Event): void;
55
- /** Pegar imagen desde el portapapeles (captura de pantalla, copiar imagen). */
56
- protected onPaste(event: ClipboardEvent): void;
57
63
  private addPending;
58
64
  protected removePending(id: number): void;
59
- /**
60
- * Emite typing como máximo 1 vez cada 2s. performance.now es seguro en runtime.
61
- */
62
65
  private emitTypingDebounced;
63
- /** Selecciona un mimeType de audio soportado por el navegador. */
64
66
  private pickAudioMime;
65
67
  protected startRecording(): Promise<void>;
66
68
  /** Para la grabación y la stagea como adjunto pendiente (con preview de audio). */
@@ -0,0 +1,57 @@
1
+ import { AvatarUploadError, AvatarUploadMetadata, AvatarUploadResult } from '../avatar-upload/types';
2
+ import { ShareProfileModalMetadata } from '../share-profile-modal/types';
3
+ import { CtaCardMetadata } from '../../molecules/cta-card/types';
4
+ import { EmptyStateMetadata } from '../../molecules/empty-state/types';
5
+ import { FormMetadata, FormSubmit } from '../../types';
6
+ import { GetProfileResponse } from '../../../services/auth/types';
7
+ import { ProfileViewConfig } from './types';
8
+ import * as i0 from "@angular/core";
9
+ /**
10
+ * `val-profile-content` — CONTENIDO del perfil (avatar + handle + nombre + teléfono
11
+ * en un form con un botón). Presentacional + lógica de datos, SIN cromática de
12
+ * página: NO toca `NavigationService` ni el header del shell.
13
+ *
14
+ * Lo reutilizan tanto la vista ruteada (`val-profile-view`, que sí setea el header)
15
+ * como el modal (`val-profile-modal`). Así el modal no contamina el header del shell.
16
+ *
17
+ * Toda la lógica (lectura reactiva del mirror Firestore /users/{uid} + fallback REST,
18
+ * submit con diff handle→profile, avatar upload, estados, i18n) vive aquí.
19
+ */
20
+ export declare class ProfileContentComponent {
21
+ private auth;
22
+ private i18n;
23
+ private toast;
24
+ private errors;
25
+ private firebase;
26
+ private collections;
27
+ private route;
28
+ config?: ProfileViewConfig;
29
+ readonly resolvedConfig: import("@angular/core").Signal<Required<Omit<ProfileViewConfig, "onSaved" | "onAvatarUploaded" | "profileBaseUrl">> & Pick<ProfileViewConfig, "onSaved" | "onAvatarUploaded" | "profileBaseUrl">>;
30
+ /** Namespace i18n resuelto (público para que la vista ruteada arme el header). */
31
+ get ns(): string;
32
+ private usersCol;
33
+ private formCmp;
34
+ readonly profile: import("@angular/core").WritableSignal<GetProfileResponse>;
35
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
36
+ readonly saving: import("@angular/core").WritableSignal<boolean>;
37
+ readonly loadError: import("@angular/core").WritableSignal<unknown>;
38
+ readonly shareOpen: import("@angular/core").WritableSignal<boolean>;
39
+ readonly shareCta: import("@angular/core").Signal<CtaCardMetadata>;
40
+ readonly shareModal: import("@angular/core").Signal<ShareProfileModalMetadata>;
41
+ private readonly _userId;
42
+ readonly errorState: import("@angular/core").Signal<EmptyStateMetadata>;
43
+ readonly avatarProps: import("@angular/core").Signal<AvatarUploadMetadata>;
44
+ formMeta: FormMetadata;
45
+ constructor();
46
+ private buildFormMeta;
47
+ private applyI18nLabels;
48
+ private loadFromApi;
49
+ private mapMirrorToProfile;
50
+ onSubmit(event: FormSubmit): Promise<void>;
51
+ onAvatarUploaded(result: AvatarUploadResult): void;
52
+ onAvatarError(_err: AvatarUploadError): void;
53
+ protected t(key: string): string;
54
+ private initialsFromName;
55
+ static ɵfac: i0.ɵɵFactoryDeclaration<ProfileContentComponent, never>;
56
+ static ɵcmp: i0.ɵɵComponentDeclaration<ProfileContentComponent, "val-profile-content", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
57
+ }
@@ -1,89 +1,23 @@
1
- import { AvatarUploadError, AvatarUploadMetadata, AvatarUploadResult } from '../avatar-upload/types';
2
- import { ShareProfileModalMetadata } from '../share-profile-modal/types';
3
- import { CtaCardMetadata } from '../../molecules/cta-card/types';
4
- import { EmptyStateMetadata } from '../../molecules/empty-state/types';
5
- import { FormMetadata, FormSubmit } from '../../types';
6
- import { GetProfileResponse } from '../../../services/auth/types';
7
1
  import { ProfileViewConfig } from './types';
8
2
  import * as i0 from "@angular/core";
9
3
  /**
10
- * `val-profile-view` — vista Perfil full-feature autocontenida (organism).
4
+ * `val-profile-view` — vista Perfil ruteada (organism). Wrapper delgado:
5
+ * configura el header del shell (`NavigationService.setBackHeader`) y delega TODO
6
+ * el contenido/lógica a `val-profile-content`.
11
7
  *
12
- * Edita los campos públicos del usuario en UN solo formulario con UN solo botón
13
- * "Guardar". Wireup:
14
- * - Avatar — val-avatar-upload (Firebase Storage + backend sync). Separado del
15
- * form porque es upload sync independiente.
16
- * - Handle (@usuario) — InputType.HANDLE (val-username-input con check de
17
- * disponibilidad async resuelto vía AuthService inyectado).
18
- * - Nombre — InputType.TEXT.
19
- * - Teléfono — InputType.PHONE.
8
+ * El contenido vive en `val-profile-content` (sin cromática de página) para poder
9
+ * reutilizarse también desde `val-profile-modal` sin contaminar el header.
20
10
  *
21
- * Submit handler dispatcha:
22
- * 1. Si handle cambió updateHandle PRIMERO (uniqueness).
23
- * 2. Si name o phone cambió → updateProfile con ambos.
24
- *
25
- * Lectura del perfil: suscribe al doc Firestore /users/{uid} (mirror que mantiene
26
- * el backend). Reactivo cross-tab + auto-refresca tras save. Fallback REST
27
- * (auth.getProfile) si el doc no existe o el listener falla.
28
- *
29
- * NO renderiza ion-content — vive dentro de val-page-wrapper.
30
- *
31
- * Auto-registra sus defaults i18n (es/en) en el constructor si el consumer no
32
- * proveyó el namespace configurado (default `Settings.Profile`).
11
+ * Consumo: igual que antes (ruta vía `provideValtechProfileRoutes` o embebida con
12
+ * `[config]`). La config se pasa tal cual al contenido.
33
13
  */
34
14
  export declare class ProfileViewComponent {
35
15
  private nav;
36
- private auth;
37
16
  private i18n;
38
- private toast;
39
- private errors;
40
- private firebase;
41
- private collections;
42
17
  private route;
43
- /**
44
- * Config vía @Input (object-first). Si no se pasa, se cae al route data
45
- * `profileConfig` (poblado por `provideValtechProfileRoutes`). `resolvedConfig`
46
- * mergea con los defaults.
47
- */
48
18
  config?: ProfileViewConfig;
49
- /** Config mergeada con defaults. @Input gana sobre route data. */
50
- readonly resolvedConfig: import("@angular/core").Signal<Required<Omit<ProfileViewConfig, "onSaved" | "onAvatarUploaded" | "profileBaseUrl">> & Pick<ProfileViewConfig, "onSaved" | "onAvatarUploaded" | "profileBaseUrl">>;
51
- /** Namespace i18n resuelto (capturado una vez para llamadas no-reactivas). */
52
- private get ns();
53
- /**
54
- * Colección global /users/{uid} (skipAppPrefix: true — el doc vive fuera de
55
- * apps/{appId}/... porque es cross-app, ver firestore.rules).
56
- */
57
- private usersCol;
58
- private formCmp;
59
- readonly profile: import("@angular/core").WritableSignal<GetProfileResponse>;
60
- readonly loading: import("@angular/core").WritableSignal<boolean>;
61
- readonly saving: import("@angular/core").WritableSignal<boolean>;
62
- readonly loadError: import("@angular/core").WritableSignal<unknown>;
63
- readonly shareOpen: import("@angular/core").WritableSignal<boolean>;
64
- readonly shareCta: import("@angular/core").Signal<CtaCardMetadata>;
65
- readonly shareModal: import("@angular/core").Signal<ShareProfileModalMetadata>;
66
- private readonly _userId;
67
- readonly errorState: import("@angular/core").Signal<EmptyStateMetadata>;
68
- readonly avatarProps: import("@angular/core").Signal<AvatarUploadMetadata>;
69
- formMeta: FormMetadata;
19
+ private readonly ns;
70
20
  constructor();
71
- /** Construcción inicial — UNA vez. Gatea handle/phone según config. */
72
- private buildFormMeta;
73
- /** Re-aplica labels/hints/placeholders en cambio de idioma. */
74
- private applyI18nLabels;
75
- /**
76
- * Fallback REST. Capa 4 (UI declarativa): NO toasteamos acá — el
77
- * val-empty-state ES la UI del error.
78
- */
79
- private loadFromApi;
80
- private mapMirrorToProfile;
81
- onSubmit(event: FormSubmit): Promise<void>;
82
- onAvatarUploaded(result: AvatarUploadResult): void;
83
- onAvatarError(_err: AvatarUploadError): void;
84
- /** Lee del namespace configurado. */
85
- protected t(key: string): string;
86
- private initialsFromName;
87
21
  static ɵfac: i0.ɵɵFactoryDeclaration<ProfileViewComponent, never>;
88
22
  static ɵcmp: i0.ɵɵComponentDeclaration<ProfileViewComponent, "val-profile-view", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
89
23
  }
@@ -32,7 +32,6 @@ export interface HeaderActionsConfig {
32
32
  export declare class HeaderActionsService {
33
33
  private modal;
34
34
  private router;
35
- private nav;
36
35
  handle(token: string, config?: HeaderActionsConfig): Promise<boolean>;
37
36
  static ɵfac: i0.ɵɵFactoryDeclaration<HeaderActionsService, never>;
38
37
  static ɵprov: i0.ɵɵInjectableDeclaration<HeaderActionsService>;
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 = "4.0.237";
5
+ export declare const VERSION = "4.0.239";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "4.0.237",
3
+ "version": "4.0.239",
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
@@ -277,6 +277,7 @@ export * from './lib/components/organisms/bottom-nav/types';
277
277
  export * from './lib/components/organisms/avatar-upload/avatar-upload.component';
278
278
  export * from './lib/components/organisms/avatar-upload/types';
279
279
  export * from './lib/components/organisms/profile-view/profile-view.component';
280
+ export * from './lib/components/organisms/profile-view/profile-content.component';
280
281
  export * from './lib/components/organisms/profile-view/types';
281
282
  export * from './lib/components/organisms/profile-view/profile.routes';
282
283
  export * from './lib/components/organisms/preferences-view/preferences-view.component';