UNPKG

@qundus/qform

Version:

The only form library you'll ever need :)

487 lines (475 loc) 20.8 kB
import { _QSTATE } from '@qundus/qstate'; import { deriveAddon, updateAddon } from '@qundus/qstate/addons'; import { OptionHooksIn } from '@qundus/qstate/hooks'; declare function createProcessors<F extends Field, O extends Options<any>>(props: ProcessorProps<F, O>): { readonly checkbox: (checked: any, value: any) => any; readonly file: (value: any) => any; readonly select: (value: any) => any; readonly number: (value: any) => number | null; }; type FieldStoreObject<F extends Field> = { value: F["value"] | undefined; condition: FieldCondition; errors?: string[]; extras?: FieldExtras<F["type"]>; }; type FieldStore<F extends Field, O extends Options<any>> = _QSTATE.StoreDerived<FieldStoreObject<F>, { hooks: O["hooks"]; }>; type FormState<F extends Fields> = _QSTATE.NanoMap<FormObject<F>>; type FormStore<F extends Fields, O extends Options<any>> = _QSTATE.Store<FormState<F>, { hooks: O["hooks"]; addons: { derive: typeof deriveAddon; update: typeof updateAddon; }; }>; type FormButtonObject = { status: FormStatus; disabled: boolean; canSubmit: boolean; submitting: boolean; }; type FormButtonStore<F extends Fields, O extends Options<F>> = _QSTATE.StoreDerived<FormButtonObject, { hooks: O["hooks"]; }>; type FormButton<F extends Fields, O extends Options<F>, S extends FormButtonStore<F, O> = FormButtonStore<F, O>> = { $store: S; }; declare const PLACEHOLDERS: { readonly select: { value: string; disabled: boolean; selected: boolean; }; readonly selectButton: { value: string; }; }; type ElementCustomProps<D extends ElementDomType, K extends ElementKeysType> = { dType?: D; kType?: K; }; interface Props<F extends Field, O extends Options<any>> { derived: FieldStore<F, O>; } type FieldElement<F extends Field, O extends Options<any>> = ReturnType<typeof prepareFieldElement<F, O>>; declare function prepareFieldElement<F extends Field, O extends Options<any>>(props: Props<F, O> & ElementProps<F, O>): { readonly dom: <D extends ElementDomType, K extends ElementKeysType>(props?: ElementCustomProps<D, K>) => { name: string; value: any; } & { required: boolean; disabled: boolean; } & { onfocus: (event: FocusEvent) => void; onblur: (event: FocusEvent) => void; autocomplete?: "on" | "off"; } & { oninput: (event: Event) => void; }; readonly preact: <D extends ElementDomType, K extends ElementKeysType>(props?: ElementCustomProps<D, K>) => { name: string; value: any; } & { required: boolean; disabled: boolean; } & { onfocus: (event: FocusEvent) => void; onblur: (event: FocusEvent) => void; autocomplete?: "on" | "off"; } & { oninput: (event: Event) => void; }; readonly react: <D extends ElementDomType, K extends ElementKeysType>(props?: ElementCustomProps<D, K>) => { name: string; value: any; } & { required: boolean; disabled: boolean; } & { onfocus: (event: FocusEvent) => void; onblur: (event: FocusEvent) => void; autocomplete?: "on" | "off"; } & { oninput: (event: Event) => void; }; readonly solid: <D extends ElementDomType, K extends ElementKeysType>(props?: ElementCustomProps<D, K>) => { name: string; value: any; } & { required: boolean; disabled: boolean; } & { onfocus: (event: FocusEvent) => void; onblur: (event: FocusEvent) => void; autocomplete?: "on" | "off"; } & { oninput: (event: Event) => void; }; readonly svelte: { name: string; value: any; } & { required: boolean; disabled: boolean; } & { onfocus: (event: FocusEvent) => void; onblur: (event: FocusEvent) => void; autocomplete?: "on" | "off"; } & { oninput: (event: Event) => void; }; ref: <K extends ElementKeysType>(ref: any, props?: ElementCustomProps<"dom", K>) => void; }; type FieldAtom<F extends Field, O extends Options<any>> = F extends Field<infer type, infer value> ? { $store: FieldStore<F, O>; key: string; type: type; label: string; getOptions?: F["options"]; get element(): FieldElement<F, O>; placeholders: typeof PLACEHOLDERS; get addValidation(): (func: FieldValidate) => (() => void) | null; updateValue: (value: value | ((prev: value) => void), configs?: { preprocessValue?: boolean; }) => void; clearValue: () => void; updateCondition: (value: Partial<FieldCondition> | ((prev: Partial<FieldCondition>) => Partial<FieldCondition>)) => void; } : unknown; type Atoms<S extends Fields, O extends Options<S>> = { [K in keyof S]: FieldAtom<S[K], O>; }; type AtomsPrepared<S extends Fields, O extends Options<S>> = ReturnType<typeof prepareFormAtoms<S, O>>; declare function prepareFormAtoms<F extends Fields, O extends Options<F>>(props: { fields: F; options: O; $store: FormStore<F, O>; }): { readonly atoms: <G extends keyof F>(key: G) => Atoms<F, O>[G]; readonly elements: <G extends keyof F>(key: G) => FieldElement<Field<FieldType, string>, O>; }; type _Processors<F extends Field, O extends Options<any>> = ReturnType<typeof createProcessors<F, O>>; type IsUnknown<T> = unknown extends T ? true : false; type IsUndefined<T> = unknown extends T ? never : undefined extends T ? true : false; type IsNull<T> = unknown extends T ? never : null extends T ? true : false; type IsEmpty<T> = unknown extends T ? never : {} extends T ? true : false; type ElementDomType = "dom" | "vdom"; /** * when element props is accessed, usually the returned keys are * all that support for html element, this gives user the option * to choose which ones are wanted. * @default "all"; */ type ElementKeysType = "base" | "special" | "all"; type ElementReturns<T extends ElementDomType, Base, Dom, VDom> = Base & ("dom" extends T ? Dom : VDom) extends infer G ? G : never; type FieldType = "checkbox" | "color" | "date" | "datetime-local" | "email" | "file" | "image" | "month" | "number" | "password" | "radio" | "range" | "reset" | "search" | "tel" | "text" | "time" | "url" | "week" | "select"; type FieldValue<T extends FieldType, D> = true extends IsUnknown<D> | IsUndefined<D> | IsNull<D> ? T extends "select" ? string[] : T extends "file" ? FileList : T extends "checkbox" ? boolean : T extends "radio" ? string : T extends "tel" ? number | string : string : D; /** * sometimes some field types require additional information beyond the * the standard field "value", this offers that through value processing * and places it under FieldState or State */ type FieldExtras<T extends FieldType> = T extends "file" ? { buffer: string | ArrayBuffer | null | undefined; file: File; placeholder: string; name: string; }[] : never; type FieldCondition = { valid: boolean; hidden: boolean; value: { updated: boolean; lastUpdate: false | "user" | "manual"; error: false | "validation" | "incomplete" | "optional"; }; element: { state: false | "focus" | "blur"; visited: boolean; disabled: boolean; required: boolean; }; }; type FieldErrors = string[] | null | undefined; type FieldValidate = (value: any, helpers: { $values: FormObject<any>["values"]; }) => string | string[] | undefined | null; /** * processor used in case of complex data values * need to be extracted from field element and the basic * element.value processor isn't accurate enough. * some processors run when events like onfocus and onblur fire, * this gives the chance to modify field state like required, * disabled..etc, according to specific needs or logic. */ type FieldProcess<F extends Field, Returns> = (props: Omit<ProcessorProps<F>, "$form"> & { value: any; getValueOf: (key: string) => any; getConditionOf: (key: string) => any; $condition: FieldCondition; processors: _Processors<F, Options<any>>; }) => Returns; type FieldProcessElement<D extends ElementDomType = ElementDomType> = (props: { key: string; element: Record<string, any>; value: FieldStoreObject<any>; isVdom: D extends "vdom" ? true : false; kType: ElementKeysType; }) => void; /** * Value Manual Change Mechanism (VMCM), happens when values are updated from api * fetch data or just manual programmatic interferrence. * this affects whether the updated values go through the proper * channels of validation, proccessing and affects on form status or just * updates values without affecting anything else. * @option normal: value updates go through the proper channeels of validation, proccessing, error handling and condition report. * @option bypass: value updates are not validated so no proccessing or error handling, condition is changed though. * @option force-valid: value updates defaults fields value condition to valid. * @default "normal" */ type FieldVMCM = "normal" | "bypass" | "force-valid"; type FieldValidateOn = "input" | "change"; type FieldOptions = (<G>(props?: G) => { label: string; value: string; }[]) | null | undefined; type Field<T extends FieldType = FieldType, V = any> = { type: T; /** initial value */ value?: V; hidden?: boolean; label?: string; processValue?: FieldProcess<Field<any>, any> | FieldProcess<Field<any>, any>[]; /** validate value */ validate?: FieldValidate | FieldValidate[] | null; validateOn?: FieldValidateOn; processCondition?: FieldProcess<Field<any>, void>; onChange?: (props: { $value: FieldStoreObject<Field<any>>; form: FormObject<Fields>; }) => void; required?: boolean; disabled?: boolean; /** supercedes global options */ vmcm?: FieldVMCM; /** * html bare element props passed, this is so preliminary right * now and requires extra work for vdom, expect breaking changes here. */ processElement?: FieldProcessElement; /** * all values go through preprocessing phase, use this to prevent that * @default true */ preprocessValue?: boolean; /** * checks for missing/required value and mark condition.value.error as * incomplete. * @default true */ incompleteStatus?: boolean; /** * allowing the field value to be null */ valueNullable?: boolean; options?: T extends "select" | "radio" ? FieldOptions : null; multiple?: T extends "select" ? boolean : false; /** * for when a checkbox is mandatory daah */ mandatory?: T extends "checkbox" ? boolean : false; }; type Basic = null | undefined | Field | FieldType; type Basics = Record<string, Basic>; type BasicToField<T extends Basic> = true extends IsUnknown<T> | IsUndefined<T> | IsNull<T> | IsEmpty<T> ? Field<FieldType, string> : T extends FieldType ? Field<T, FieldValue<T, undefined>> : T extends Field ? Field<T["type"], FieldValue<T["type"], T["value"]>> : never; type Fields<B extends Basics = Basics> = { [K in keyof B]: BasicToField<B[K]>; } extends infer G ? { [K in keyof G]: G[K]; } : never; type FormStatus = "idle" | "incomplete" | "error" | "valid" | "submit"; type FormValues<T extends Fields> = { [K in keyof T]: T[K]["value"]; }; type FormErrors<T extends Fields> = undefined | null | { [K in keyof T]?: string[]; }; type FormConditions<T extends Fields> = { [K in keyof T]: FieldCondition; }; type FormExtras<T extends Fields> = { [K in keyof T as FieldExtras<T[K]["type"]> extends never ? never : K]: FieldExtras<T[K]["type"]>; }; type FormObject<F extends Fields> = { values: FormValues<F>; conditions: FormConditions<F>; errors: FormErrors<F>; extras: FormExtras<F>; incomplete: string[]; status: FormStatus; } extends infer G ? { [K in keyof G]: G[K]; } : never; type Options<F extends Fields> = { hooks?: OptionHooksIn; onMount?: (props: { init: FormObject<F>; update: (values: any) => void | Promise<void>; }) => Promise<void> | void; onChange?: (props: { newValue: FormObject<F>; abort: () => void; }) => void; vmcm?: FieldVMCM; /** * usually all values are immediatly updated in the state, * by setting this to true, only valid values will be commited. * @default false */ preventErroredValues?: boolean; /** * normal behavior of form is to consider all fields required * and mark optional ones through "require" setting, * this alters that behavior and forces all fields to be optional. * the user then has the ability to make required fields through * setting "required" to true * @default true */ allFieldsRequired?: boolean; allFieldsDisabled?: boolean; /** * global options to optin or out of values preprocessing based on field type. * this option precedes individual ones */ preprocessValues?: boolean; /** * how should the form react to updating values using form.actions.update * @default "silent" */ onUpdateKeyNotFound?: "silent" | "warn"; /** * the last step of checking for form validity is to check for * required fields' values and add them to the incompleteList, * this option allows for choosing how big or small this list goes. * @option true collect all incomplete fields * @option false don't collect any incomplete fields * @option number collect this many of incomplete fields * @default false */ incompleteListCount?: boolean | number; /** * wheather the preferred method of checking values * is ran oninput or onchange, oninput checks for validation * for every change happens, onchange checks once there's a * state change like blur or focus. * field specific validateOn takes precedence here. * @default input */ validateOn?: FieldValidateOn; /** * global element processor, gets called before or after field's specific processElement * based on processElementOrder option. */ processElement?: FieldProcessElement; /** * determines wheather global processElement is going to take place before or after * field's specific processElement * @default "after" */ processElementOrder?: "before" | "after"; /** * if the desired data extracted from the form is in the * shape of a nested object, then this splitter is used * to determine which keys are nested, for now only * the dot is supported. * @default '.' */ flatObjectKeysChar?: "."; /** * when no label is provided, the key is used as fallback but sometimes * the key is meant to be unflattened later on when fetching the form data, * so this offers a way to replace the key flatObjectKeysChar with any * character. * @default ' ' or empty spcace */ flatLabelJoinChar?: string; }; type OptionsMerged<G extends Options<any>, D extends Options<any>> = D & G; type InteractionProps<F extends Field, O extends Options<any>> = { key: string; field: F; options: O; event: Event | undefined | null; value: any; preprocessValue?: boolean; $form: FormObject<any>; }; type ProcessorProps<F extends Field, O extends Options<any> = Options<any>> = { key: string; field: F; event: Event | undefined | null; manualUpdate: boolean; $form: FormObject<any>; }; type PluginProps<F extends Fields, O extends Options<F>> = { fields: F; options: O; $store: FormStore<F, O>; }; type ElementProps<F extends Field, O extends Options<any>> = { key: string; field: F; options: O; $store: FormStore<any, O>; }; type _model_Atoms<S extends Fields, O extends Options<S>> = Atoms<S, O>; type _model_AtomsPrepared<S extends Fields, O extends Options<S>> = AtomsPrepared<S, O>; type _model_Basic = Basic; type _model_BasicToField<T extends Basic> = BasicToField<T>; type _model_Basics = Basics; type _model_ElementDomType = ElementDomType; type _model_ElementKeysType = ElementKeysType; type _model_ElementProps<F extends Field, O extends Options<any>> = ElementProps<F, O>; type _model_ElementReturns<T extends ElementDomType, Base, Dom, VDom> = ElementReturns<T, Base, Dom, VDom>; type _model_Field<T extends FieldType = FieldType, V = any> = Field<T, V>; type _model_FieldAtom<F extends Field, O extends Options<any>> = FieldAtom<F, O>; type _model_FieldCondition = FieldCondition; type _model_FieldErrors = FieldErrors; type _model_FieldExtras<T extends FieldType> = FieldExtras<T>; type _model_FieldOptions = FieldOptions; type _model_FieldProcess<F extends Field, Returns> = FieldProcess<F, Returns>; type _model_FieldProcessElement<D extends ElementDomType = ElementDomType> = FieldProcessElement<D>; type _model_FieldStore<F extends Field, O extends Options<any>> = FieldStore<F, O>; type _model_FieldStoreObject<F extends Field> = FieldStoreObject<F>; type _model_FieldType = FieldType; type _model_FieldVMCM = FieldVMCM; type _model_FieldValidate = FieldValidate; type _model_FieldValidateOn = FieldValidateOn; type _model_FieldValue<T extends FieldType, D> = FieldValue<T, D>; type _model_Fields<B extends Basics = Basics> = Fields<B>; type _model_FormButton<F extends Fields, O extends Options<F>, S extends FormButtonStore<F, O> = FormButtonStore<F, O>> = FormButton<F, O, S>; type _model_FormButtonObject = FormButtonObject; type _model_FormButtonStore<F extends Fields, O extends Options<F>> = FormButtonStore<F, O>; type _model_FormConditions<T extends Fields> = FormConditions<T>; type _model_FormErrors<T extends Fields> = FormErrors<T>; type _model_FormExtras<T extends Fields> = FormExtras<T>; type _model_FormObject<F extends Fields> = FormObject<F>; type _model_FormState<F extends Fields> = FormState<F>; type _model_FormStatus = FormStatus; type _model_FormStore<F extends Fields, O extends Options<any>> = FormStore<F, O>; type _model_FormValues<T extends Fields> = FormValues<T>; type _model_InteractionProps<F extends Field, O extends Options<any>> = InteractionProps<F, O>; type _model_IsEmpty<T> = IsEmpty<T>; type _model_IsNull<T> = IsNull<T>; type _model_IsUndefined<T> = IsUndefined<T>; type _model_IsUnknown<T> = IsUnknown<T>; type _model_Options<F extends Fields> = Options<F>; type _model_OptionsMerged<G extends Options<any>, D extends Options<any>> = OptionsMerged<G, D>; type _model_PluginProps<F extends Fields, O extends Options<F>> = PluginProps<F, O>; type _model_ProcessorProps<F extends Field, O extends Options<any> = Options<any>> = ProcessorProps<F, O>; type _model__Processors<F extends Field, O extends Options<any>> = _Processors<F, O>; declare namespace _model { export type { _model_Atoms as Atoms, _model_AtomsPrepared as AtomsPrepared, _model_Basic as Basic, _model_BasicToField as BasicToField, _model_Basics as Basics, _model_ElementDomType as ElementDomType, _model_ElementKeysType as ElementKeysType, _model_ElementProps as ElementProps, _model_ElementReturns as ElementReturns, _model_Field as Field, _model_FieldAtom as FieldAtom, _model_FieldCondition as FieldCondition, _model_FieldErrors as FieldErrors, _model_FieldExtras as FieldExtras, _model_FieldOptions as FieldOptions, _model_FieldProcess as FieldProcess, _model_FieldProcessElement as FieldProcessElement, _model_FieldStore as FieldStore, _model_FieldStoreObject as FieldStoreObject, _model_FieldType as FieldType, _model_FieldVMCM as FieldVMCM, _model_FieldValidate as FieldValidate, _model_FieldValidateOn as FieldValidateOn, _model_FieldValue as FieldValue, _model_Fields as Fields, _model_FormButton as FormButton, _model_FormButtonObject as FormButtonObject, _model_FormButtonStore as FormButtonStore, _model_FormConditions as FormConditions, _model_FormErrors as FormErrors, _model_FormExtras as FormExtras, _model_FormObject as FormObject, _model_FormState as FormState, _model_FormStatus as FormStatus, _model_FormStore as FormStore, _model_FormValues as FormValues, _model_InteractionProps as InteractionProps, _model_IsEmpty as IsEmpty, _model_IsNull as IsNull, _model_IsUndefined as IsUndefined, _model_IsUnknown as IsUnknown, _model_Options as Options, _model_OptionsMerged as OptionsMerged, _model_PluginProps as PluginProps, _model_ProcessorProps as ProcessorProps, _model__Processors as _Processors }; } export { type AtomsPrepared as A, type Basics as B, type Fields as F, type Options as O, type PluginProps as P, _model as _, type FieldCondition as a, type FormButton as b, PLACEHOLDERS as c, type FormObject as d, type OptionsMerged as e, type FieldType as f, type Field as g };