import { DoCheck, ElementRef, EventEmitter, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { DatePickerMetadata } from '../../molecules/date-picker/types'; import { TextareaInputMetadata } from '../../molecules/textarea-input/types'; import { UsernameInputMetadata } from '../../molecules/username-input/types'; import { AttachmentItem } from '../attachment-uploader/types'; import { ButtonMetadata, FormMetadata, FormSubmit, InputMetadata, InputType } from '../../types'; import * as i0 from "@angular/core"; export declare class FormComponent implements OnInit, OnChanges, DoCheck { private fb; private elementRef; props: FormMetadata; onSubmit: EventEmitter; onValueChange: EventEmitter>; onInvalid: EventEmitter; onSelectChange: EventEmitter<{ field: string; value: any; }>; form: FormGroup; types: typeof InputType; states: { ENABLED: "ENABLED"; DISABLED: "DISABLED"; WORKING: "WORKING"; ERROR: "ERROR"; }; /** * Valor actual del form (`form.getRawValue()`), actualizado en cada * `valueChanges`. Pensado para el modo `controlled`: el host lo lee vía * `@ViewChild(FormComponent)` sin tocar el FormGroup directo. En modo normal * también está disponible. */ readonly value: import("@angular/core").WritableSignal>; /** * Estado de validez del form, actualizado en cada `statusChanges`. Para que * el host (wizard) habilite/deshabilite su botón "Siguiente". */ readonly valid: import("@angular/core").WritableSignal; private subscriptions; private actionsCache; private fieldPropMemo; private usernamePropMemo; private textareaPropMemo; private selectPropMemo; private textInputPropMemo; private datePickerPropMemo; private fieldIdMemo; private fieldUid; private previousState; private previousUploadingCount; private uploadingFields; constructor(fb: FormBuilder, elementRef: ElementRef); /** Arma la definición de controles (valor inicial + validadores) desde `props`. */ private buildFormControlsDef; /** * Reconstruye el `FormGroup` desde cero, con los valores iniciales de `props` * actuales (no los que el usuario haya tecleado desde entonces). * * Existe para el caso en que Angular NO destruye el componente entre dos usos * — típicamente `IonicRouteStrategy`, que cachea la página ruteada al navegar * afuera y la reutiliza al volver sin correr `ngOnInit` de nuevo. Sin esto, * un form de login mantiene lo que el usuario anterior tecleó después de * cerrar sesión y volver a `/login`: el `FormGroup` se construyó UNA vez y * nadie lo tocó desde entonces. * * Reconstruye el `FormGroup` entero (no `.reset(values)`) porque la * definición trae `[valor, validators]` por control, no valores planos — * reusar `buildFormControlsDef()` tal cual evita mantener dos formas de * calcular "cuál es el valor inicial" que puedan desincronizarse. * * El caller (típicamente `val-login`, vía `ionViewWillEnter`) decide CUÁNDO * llamarlo — acá no hay heurística de "cuándo resetear", porque un form de * varios pasos sí podría querer conservar lo tecleado al volver a una * pestaña. */ resetForm(): void; ngOnInit(): void; ngOnChanges(changes: SimpleChanges): void; private patchInitialValuesFromProps; ngDoCheck(): void; /** * Synchronizes form control disabled/enabled state with field metadata. */ private syncFieldControlStates; /** * Actualiza el cache de actions basado en el estado actual del form. */ private updateActionsCache; ngOnDestroy(): void; trackSelectChanges(fieldName: string): void; submitHandler(token?: string): Promise; onAttachmentChange(fieldName: string, items: AttachmentItem[]): void; getControl(field: string): FormControl; /** * Ids estables (label + error) para un field. Memoizados por referencia para * que el wiring `aria-labelledby` / `aria-describedby` no cambie entre ciclos * de change detection. */ private fieldIds; /** Id del label visible del campo (consumido por el template + el input). */ labelId(field: InputMetadata): string; /** Id del contenedor de error (`val-hint`) del campo. */ errorId(field: InputMetadata): string; getFieldProp(field: InputMetadata): InputMetadata; /** * Adapter para los tipos colapsados en `val-text-input` (EMAIL/NUMBER/HOUR). * Reusa `getFieldProp` (con su control + wiring de ids) e inyecta el `inputType` * HTML nativo. Memoizado por referencia de field para no romper la identidad. */ getTextInputProp(field: InputMetadata, inputType: NonNullable): InputMetadata; /** * Adapter para SELECT — igual que `getFieldProp` pero limpia `label`. * val-form ya renderiza el título del campo con `` arriba del input; * si además pasáramos `label` al ``, este lo pinta DENTRO del pill * → redundancia visual ("Tipo" dos veces). Reusa el mismo memo (con la entrada * ya label-stripped) para no romper la identidad de referencia. */ getSelectProp(field: InputMetadata): InputMetadata; /** * Adapter — convierte un `InputMetadata` (con type=HANDLE) a `UsernameInputMetadata`. * El check de disponibilidad se resuelve dentro del component (AuthService inyectado); * el caller puede sobrescribirlo pasando `field.errors` o un `UsernameInputMetadata` * custom usando type=TEXT si necesita otra fuente de truth. */ getUsernameProp(field: InputMetadata): UsernameInputMetadata; /** * Adapter — convierte un `InputMetadata` (con type=DATE_PICKER) a `DatePickerMetadata`. * label/hint se omiten — val-form los renderiza vía .field-name/.field-description. */ getDatePickerProp(field: InputMetadata): DatePickerMetadata; /** * Adapter — convierte un `InputMetadata` (con type=TEXTAREA) a `TextareaInputMetadata`. * Defaults sensatos: autoGrow + counter habilitado, 4-12 rows. */ getTextareaProp(field: InputMetadata): TextareaInputMetadata; get isAtEndOfForm(): boolean; /** * Fuerza mostrar los errores de validación (marca todos los controles como * touched) y devuelve si el form es válido. Pensado para el modo `controlled`: * el host lo invoca en su "Siguiente" para gatear la navegación del wizard. */ validate(): boolean; /** * Marca todos los controles como touched (muestra errores) sin devolver nada. * Alias semántico de la primera mitad de `validate()`. */ markAllTouched(): void; get Form(): FormGroup; get FormState(): { form: FormGroup; data: FormMetadata; }; get actions(): ButtonMetadata[]; private readonly i18nSuggestion; /** Sugerencias descartadas por el usuario, para no volver a insistir. */ private readonly suggestionDismissed; /** * Devuelve el correo corregido a sugerir, o null. * * Solo sugiere cuando el campo NO tiene foco: mientras se escribe, todo * correo a medio teclear parece un typo y la sugerencia parpadearía. */ emailSuggestionFor(field: InputMetadata): string | null; /** * Busca el control sin explotar si el formulario todavía no se construyó. * `getControl` asume `Form` ya inicializado; acá se llama desde el template, * que puede evaluarse antes de `ngOnInit` en algunos ciclos. */ private controlPorNombre; emailSuggestionQuestion(sugerido: string): string; emailSuggestionApplyLabel(): string; /** * Traduce con respaldo real. * * `I18nService.t()` NO devuelve null cuando falta la clave: devuelve vacío o * un placeholder `[namespace.key]`. Con `??` el respaldo nunca entraba y el * renglón salía en blanco en cualquier app que no registrara la clave. Lo * encontró el spec del componente, no la revisión a ojo. */ private textoI18n; /** Aplica la corrección. Es la única vía: nada se reescribe sin este clic. */ applyEmailSuggestion(field: InputMetadata, sugerido: string): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; }