import {
AbstractType,
InjectionToken,
StaticProvider,
Type,
} from '@angular/core';
import {
AbstractControlOptions,
AsyncValidatorFn,
ValidatorFn,
} from '@angular/forms';
import { BaseDefinitionMetadata } from '@rxap/definition';
import {
Constructor,
NonEmpty,
} from '@rxap/utilities';
import { RxapFormArray } from './form-array';
import { RxapFormControl } from './form-control';
import type { RxapFormGroup } from './form-group';
import {
AbstractControl,
ControlOptions,
} from './types';
export interface InjectableValidator {
validate?: ValidatorFn;
asyncValidate?: AsyncValidatorFn;
}
/**
* @internal
*/
export interface _RxapAbstractControlOptions extends AbstractControlOptions {
state?: any | (() => any);
injectValidators?: Array<
| Type<InjectableValidator>
| InjectionToken<InjectableValidator>
| AbstractType<InjectableValidator>
>;
controlType?: Constructor<RxapFormControl>;
disabled?: boolean;
readonly?: boolean;
}
export type RxapAbstractControlOptions<
T extends Record<string, any> = Record<string, any>
> = _RxapAbstractControlOptions & T;
export interface RxapAbstractControlOptionsWithDefinition
extends RxapAbstractControlOptions {
definition: Constructor;
}
export interface FormDefinition<T = any,
E extends object = any,
JSON extends Record<string, any> = any,
> {
rxapFormGroup: RxapFormGroup<T, E>;
/**
* used to access the form definition metadata type save
*/
rxapMetadata: FormDefinitionMetadata;
/**
* The Reuse hook is called when the instance is reused.
* And can be used to reset or alter the local state of the instance.
*/
rxapReuse?(): void;
/**
* Called to get the value that should be submitted. If not defined
* the value property of the root RxapFormGroup instance will be used
*/
getSubmitValue?(): JSON;
/**
* Called to get the value that should be submitted. If not defined
* the value property of the root RxapFormGroup instance will be used
*/
toJSON?(): JSON;
}
export interface FormDefinitionArray<T> extends Array<T> {
rxapFormArray: RxapFormArray;
}
export type FormType<T> = Partial<
FormDefinition<T>
> &
{
[K in keyof T]: T[K] extends (infer U)[]
? FormDefinitionArray<FormType<U>> | FormDefinitionArray<RxapFormControl<U>> | RxapFormControl<T[K]> | RxapFormArray<U>
: T[K] extends Record<string, any>
? (FormType<T[K]> & Partial<FormDefinition<T[K]>>) | RxapFormControl<T[K]>
: RxapFormControl<NonEmpty<T[K]>>;
};
export interface FormOptions extends RxapAbstractControlOptions {
id: string;
}
export interface FormDefinitionMetadata
extends BaseDefinitionMetadata,
FormOptions {
providers?: StaticProvider[];
/**
* true - after 5000ms the form is automatically submitted if valid
* number - after the set ms the is automatically submitted if valid
*/
autoSubmit?: boolean | number;
}
export type ChangeFn<T = any> = (
value: T,
emitViewToModelChange: boolean,
) => void;
export type SetValueFn<T = any> = (value: T, options?: ControlOptions) => void;
export type FormBuilderFn<T extends (FormDefinition<Data> | FormType<Data>) = FormDefinition, Data = Record<string, any>> = (
state: any,
options: { controlId: string },
) => T | RxapFormControl;
export type ControlInsertedFn = (
index: number,
controlOrDefinition: AbstractControl | FormDefinition,
) => void;
export type ControlRemovedFn = (index: number) => void;
export interface FormArrayOptions extends RxapAbstractControlOptions {
builder: FormBuilderFn;
controlId: string;
controlInsertedFn: ControlInsertedFn;
controlRemovedFn: ControlRemovedFn;
}
export interface FormGroupOptions extends RxapAbstractControlOptions {
controlId: string;
}