UNPKG

@fastkit/vue-form-control

Version:

Basic form implementation library for Vue applications.

1,376 lines 160 kB
import { AppendFlags, FactoryOpts, InputMask, InputMask as IMaskInstance, Masked, MaskedDynamic, MaskedDynamicOptions, MaskedEnum, MaskedFunction, MaskedRange, MaskedRegExp, PIPE_TYPE } from "imask"; import { Mixin, RecursiveArray } from "@fastkit/helpers"; import { App, ComponentInternalInstance, ComputedRef, DirectiveBinding, ExtractPropTypes, InjectionKey, InputHTMLAttributes, ObjectDirective, Prop, PropType, Ref, SetupContext, Slot, TextareaHTMLAttributes, VNode, VNodeArrayChildren, VNodeChild, WritableComputedRef } from "vue"; import { Rule, ValidationError, VerifiableRule, VerifiableRuleOrFn } from "@fastkit/rules"; import { DefineSlotsType, TypedSlot, VNodeChildOrSlot } from "@fastkit/vue-utils"; export * from "imask"; //#region src/schemes/autocapitalize.d.ts type FormAutoCapitalize = 'off' | 'on' | 'words' | 'characters'; //#endregion //#region src/schemes/autocomplete.d.ts declare const FORM_AUTO_COMPLETES: readonly ["off", "on", "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "email", "username", "new-password", "current-password", "one-time-code", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-extension", "impp", "url", "photo"]; type FormAutoComplete = (typeof FORM_AUTO_COMPLETES)[number]; //#endregion //#region src/schemes/textinput.d.ts declare const TEXT_INPUT_TYPES: readonly ["color", "date", "datetime-local", "email", "month", "number", "password", "search", "tel", "text", "time", "url"]; type TextInputType = (typeof TEXT_INPUT_TYPES)[number]; declare const TEXT_INPUT_MODES: readonly ["decimal", "email", "none", "numeric", "search", "tel", "text", "url"]; type TextInputMode = (typeof TEXT_INPUT_MODES)[number]; type TextFinalizer = (value?: string | null) => string | Promise<string>; declare const BUILTIN_TEXT_FINALIZERS: Record<"trim" | "removeSpace" | "upper" | "lower" | "halfWidth" | "singleSpace", TextFinalizer>; type BuiltinTextFinalizerName = keyof typeof BUILTIN_TEXT_FINALIZERS; //#endregion //#region src/schemes/imask.d.ts type IMaskEventType = 'accept' | 'complete'; type AnyMaskedOptions = FactoryOpts; type IMaskEvent = CustomEvent<InputMask>; declare function createIMaskEvent(type: IMaskEventType, eventInitDict?: CustomEventInit<InputMask>): IMaskEvent; type IMaskTypedValue = string | number | Date; type IMaskRawInput = RegExp | Function | string; type DynamicMaskedMeta = { /** Metadata assigned to dynamic mask options. */ meta?: any; }; type AnyMaskedOptionsWithMeta = AnyMaskedOptions & DynamicMaskedMeta; type AnyMaskedWithMeta = Masked & DynamicMaskedMeta; type MaskedDynamicWithMeta = Omit<MaskedDynamic, 'currentMask' | 'compiledMasks'> & { currentMask?: AnyMaskedWithMeta; compiledMasks: AnyMaskedWithMeta[]; }; type MaskedDynamicOptionsWithMeta = Omit<MaskedDynamicOptions, 'mask' | 'dispatch'> & { mask: AnyMaskedOptionsWithMeta[]; dispatch?: (value: string, masked: MaskedDynamicWithMeta, flags: AppendFlags) => Masked; }; type IMaskInput = Exclude<AnyMaskedOptions, MaskedDynamicOptions> | IMaskRawInput | Masked<any> | MaskedFunction | MaskedRegExp | MaskedEnum | MaskedRange | MaskedDynamicOptionsWithMeta | false | null | undefined | void; declare function resolveIMaskInput(source?: IMaskInput): AnyMaskedOptions | undefined; //#endregion //#region src/composables/group.d.ts declare function createFormGroupProps(): { /** * Collect the error messages of all nodes belonging to this node * * By default, a node attempts to render error messages on its own, but enabling this setting allows the parent group to manage the rendering of error messages. * If you want to exclude a specific node from this configuration, enable the `showOwnErrors` setting for that node. */ collectErrorMessages: BooleanConstructor; /** * Auto scroll to the location of the form when invalid input is detected in the validation on submission */ disableAutoScroll: BooleanConstructor; name: StringConstructor; tag: StringConstructor; modelValue: import("vue").Prop<unknown, unknown>; tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; autofocus: BooleanConstructor; disabled: BooleanConstructor; readonly: BooleanConstructor; viewonly: BooleanConstructor; spellcheck: BooleanConstructor; required: BooleanConstructor | import("vue").PropType<boolean>; clearable: BooleanConstructor; validateTiming: { type: import("vue").PropType<ValidateTiming>; default: ValidateTiming; }; rules: { type: import("vue").PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; validationDeps: import("vue").PropType<(nodeControl: FormNodeControl) => any>; error: BooleanConstructor; errorMessages: import("vue").PropType<string | string[]>; showOwnErrors: { type: BooleanConstructor; default: undefined; }; detach: BooleanConstructor; }; type FormGroupProps = ExtractPropTypes<ReturnType<typeof createFormGroupProps>>; declare function createFormGroupEmits(): { 'update:modelValue': (value: unknown) => boolean; 'update:errors': (errors: FormNodeError[]) => boolean; change: (value: unknown) => boolean; focus: (ev: FocusEvent) => boolean; blur: (ev: FocusEvent) => boolean; }; declare function createFormGroupSettings(): { props: { /** * Collect the error messages of all nodes belonging to this node * * By default, a node attempts to render error messages on its own, but enabling this setting allows the parent group to manage the rendering of error messages. * If you want to exclude a specific node from this configuration, enable the `showOwnErrors` setting for that node. */ collectErrorMessages: BooleanConstructor; /** * Auto scroll to the location of the form when invalid input is detected in the validation on submission */ disableAutoScroll: BooleanConstructor; name: StringConstructor; tag: StringConstructor; modelValue: import("vue").Prop<unknown, unknown>; tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; autofocus: BooleanConstructor; disabled: BooleanConstructor; readonly: BooleanConstructor; viewonly: BooleanConstructor; spellcheck: BooleanConstructor; required: BooleanConstructor | import("vue").PropType<boolean>; clearable: BooleanConstructor; validateTiming: { type: import("vue").PropType<ValidateTiming>; default: ValidateTiming; }; rules: { type: import("vue").PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; validationDeps: import("vue").PropType<(nodeControl: FormNodeControl) => any>; error: BooleanConstructor; errorMessages: import("vue").PropType<string | string[]>; showOwnErrors: { type: BooleanConstructor; default: undefined; }; detach: BooleanConstructor; }; emits: { 'update:modelValue': (value: unknown) => boolean; 'update:errors': (errors: FormNodeError[]) => boolean; change: (value: unknown) => boolean; focus: (ev: FocusEvent) => boolean; blur: (ev: FocusEvent) => boolean; }; }; interface FormGroupEmitOptions extends ReturnType<typeof createFormGroupEmits> {} type FormGroupContext = SetupContext<FormGroupEmitOptions>; interface FormGroupOptions extends FormNodeControlBaseOptions {} declare class FormGroupControl extends FormNodeControl { readonly _props: FormGroupProps; protected _allNodes: Ref<FormNodeControl[]>; protected _allInvalidNodes: ComputedRef<FormNodeControl[]>; /** * All nodes in an error state belonging recursively to this group */ get allInvalidNodes(): FormNodeControl<any, any, BooleanConstructor>[]; /** * Collect the error messages of all nodes belonging to this node */ get collectErrorMessages(): boolean; /** * Auto scroll to the location of the form when invalid input is detected in the validation on submission */ get disableAutoScroll(): boolean; /** * List of all nodes belonging to this group * * This list is a reactive list, and depending on usage, it may contain a large number of nodes. * Please be aware that complex operations using this list can lead to performance issues. */ get allNodes(): FormNodeControl<any, any, BooleanConstructor>[]; constructor(props: FormGroupProps, ctx: FormGroupContext, options?: FormGroupOptions); /** @internal */ __joinFromNode(node: FormNodeControl): void; /** @internal */ __leaveFromNode(node: FormNodeControl): void; /** * Recursively retrieve the leading node in an error state within this group */ findFirstInvalidNode(): FormNodeControl<any, any, BooleanConstructor> | undefined; /** * Scroll to the position of the leading node in an error state within this group */ scrollToFirstInvalidNode(): void; protected dispatchAutoScroll(): void; protected _forceFinalize(): boolean; /** * Validate the values of this group and all descendant nodes. If there is one or more errors, scroll to the top error node * * If `disableAutoScroll` is set, scrolling will not be performed. */ validateAndScroll(): Promise<boolean>; } declare function useFormGroup(props: FormGroupProps, ctx: FormGroupContext, options?: FormGroupOptions): FormGroupControl; //#endregion //#region src/composables/form.d.ts /** * Form action context */ interface FormActionContext { /** Control for form element */ form: VueForm; /** Action has been canceled */ get canceled(): boolean; /** Submit event object */ get event(): Event; /** * Cancel the action * * Currently, this method simply sets the `canceled` property of the context to `false`. * This specification is subject to change in the future. */ cancel: () => void; } type FormActionHandler = (ctx: FormActionContext) => any; /** * @deprecated * This type has been changed to {@link FormActionHandler}. It will be deprecated in future releases. */ type FormFunctionableAction = FormActionHandler; type FormAction = string | FormActionHandler; interface FormInvalidSubmissionAcceptorContext { /** Form control */ readonly form: VueForm; /** * Accepted */ get accepted(): boolean; /** * Accept submission */ accept(): void; } type FormInvalidSubmissionAcceptor = (payload: FormInvalidSubmissionAcceptorContext) => void; type FormAcceptInvalidSubmissionSpec = boolean | FormInvalidSubmissionAcceptor; interface FormOptions extends FormGroupOptions {} declare function createFormProps(options?: FormOptions): { /** * Do not perform default HTML validation when submitting the form * * @default true */ novalidate: { type: BooleanConstructor; default: boolean; }; /** * Action settings for form submission * * Set the destination URL or callback handler */ action: PropType<FormAction>; /** * Automatic validation on transmission * * If this setting is enabled, all validation will be done before transmission and the transmission process will be canceled if there are invalid entries * * @default true */ autoValidate: { type: BooleanConstructor; default: boolean; }; /** * Form is sending */ sending: BooleanConstructor; /** * Accept invalid values during form submission * * @default false */ acceptInvalidSubmission: { type: PropType<FormAcceptInvalidSubmissionSpec>; default: boolean; }; collectErrorMessages: BooleanConstructor; disableAutoScroll: BooleanConstructor; name: StringConstructor; tag: StringConstructor; modelValue: import("vue").Prop<unknown, unknown>; tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; autofocus: BooleanConstructor; disabled: BooleanConstructor; readonly: BooleanConstructor; viewonly: BooleanConstructor; spellcheck: BooleanConstructor; required: BooleanConstructor | PropType<boolean>; clearable: BooleanConstructor; validateTiming: { type: PropType<ValidateTiming>; default: ValidateTiming; }; rules: { type: PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; validationDeps: PropType<(nodeControl: FormNodeControl) => any>; error: BooleanConstructor; errorMessages: PropType<string | string[]>; showOwnErrors: { type: BooleanConstructor; default: undefined; }; detach: BooleanConstructor; }; type FormProps = ExtractPropTypes<ReturnType<typeof createFormProps>>; declare function createFormEmits(): { /** * Form Submission * * This event is notified when the validation is complete and before the action is called * * @param form - VueForm instance * @param ev - Event */ submit: (form: VueForm, ev: Event) => boolean; /** * Updating sending status * * @param sending - sending status * @param form - VueForm instance */ 'update:sending': (sending: boolean, form: VueForm) => boolean; /** * The form action has been finished * * @param actionContext - Form action context */ finishAction: (actionContext: FormActionContext) => boolean; /** * Failed automatic validation * * @param form - VueForm instance */ autoValidationFailed: (form: VueForm) => boolean; 'update:modelValue': (value: unknown) => boolean; 'update:errors': (errors: FormNodeError[]) => boolean; change: (value: unknown) => boolean; focus: (ev: FocusEvent) => boolean; blur: (ev: FocusEvent) => boolean; }; type FormEmits = ReturnType<typeof createFormEmits>; declare function createFormSettings(options?: FormOptions): { props: { /** * Do not perform default HTML validation when submitting the form * * @default true */ novalidate: { type: BooleanConstructor; default: boolean; }; /** * Action settings for form submission * * Set the destination URL or callback handler */ action: PropType<FormAction>; /** * Automatic validation on transmission * * If this setting is enabled, all validation will be done before transmission and the transmission process will be canceled if there are invalid entries * * @default true */ autoValidate: { type: BooleanConstructor; default: boolean; }; /** * Form is sending */ sending: BooleanConstructor; /** * Accept invalid values during form submission * * @default false */ acceptInvalidSubmission: { type: PropType<FormAcceptInvalidSubmissionSpec>; default: boolean; }; collectErrorMessages: BooleanConstructor; disableAutoScroll: BooleanConstructor; name: StringConstructor; tag: StringConstructor; modelValue: import("vue").Prop<unknown, unknown>; tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; autofocus: BooleanConstructor; disabled: BooleanConstructor; readonly: BooleanConstructor; viewonly: BooleanConstructor; spellcheck: BooleanConstructor; required: BooleanConstructor | PropType<boolean>; clearable: BooleanConstructor; validateTiming: { type: PropType<ValidateTiming>; default: ValidateTiming; }; rules: { type: PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; validationDeps: PropType<(nodeControl: FormNodeControl) => any>; error: BooleanConstructor; errorMessages: PropType<string | string[]>; showOwnErrors: { type: BooleanConstructor; default: undefined; }; detach: BooleanConstructor; }; emits: { /** * Form Submission * * This event is notified when the validation is complete and before the action is called * * @param form - VueForm instance * @param ev - Event */ submit: (form: VueForm, ev: Event) => boolean; /** * Updating sending status * * @param sending - sending status * @param form - VueForm instance */ 'update:sending': (sending: boolean, form: VueForm) => boolean; /** * The form action has been finished * * @param actionContext - Form action context */ finishAction: (actionContext: FormActionContext) => boolean; /** * Failed automatic validation * * @param form - VueForm instance */ autoValidationFailed: (form: VueForm) => boolean; 'update:modelValue': (value: unknown) => boolean; 'update:errors': (errors: FormNodeError[]) => boolean; change: (value: unknown) => boolean; focus: (ev: FocusEvent) => boolean; blur: (ev: FocusEvent) => boolean; }; }; interface FormEmitOptions extends ReturnType<typeof createFormEmits> {} type FormContext = SetupContext<FormEmitOptions>; /** * Option to check the submittability of the form */ interface PrepareFormSubmissionOptions { /** Skip operability check */ skipOperationCheck?: boolean; /** Skip in-progress check during submission */ skipSendingCheck?: boolean; /** Skip validation */ skipValidation?: boolean; } /** * Dispatch option for form action */ interface DispatchFormActionOptions extends PrepareFormSubmissionOptions { /** Submit event object */ event?: Event; } interface ComputedFormAttributes { ref: Ref<HTMLFormElement | null>; action: string | undefined; spellcheck: boolean; onSubmit: (ev: Event) => void; novalidate: boolean; 'aria-disabled': boolean; } /** * Control for form element */ declare class VueForm extends FormGroupControl { readonly _props: FormProps; protected _formContext: FormContext; protected _nativeAction: ComputedRef<string | undefined>; protected _fnAction: ComputedRef<FormActionHandler | undefined>; protected _formRef: Ref<HTMLFormElement | null, HTMLFormElement | null>; protected _actionPromise: Ref<{ then: <TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>; catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<any>; finally: (onfinally?: (() => void) | null | undefined) => Promise<any>; readonly [Symbol.toStringTag]: string; } | null, Promise<any> | { then: <TResult1 = any, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<TResult1 | TResult2>; catch: <TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<any>; finally: (onfinally?: (() => void) | null | undefined) => Promise<any>; readonly [Symbol.toStringTag]: string; } | null>; protected _sending: ComputedRef<boolean>; protected _formAttrs: ComputedRef<ComputedFormAttributes>; /** * Do not perform default HTML validation when submitting the form */ get novalidate(): boolean; get nativeAction(): string | undefined; /** * Executing asynchronous submission action */ get sending(): boolean; /** * Automatic validation on transmission * * If this setting is enabled, all validation will be done before transmission and the transmission process will be canceled if there are invalid entries * * @default true */ get autoValidate(): boolean; /** * Attributes to apply to the form element */ get formAttrs(): ComputedFormAttributes; constructor(props: FormProps, ctx: FormContext, options?: FormOptions); /** * Generates SubmitEvent and dispatches it to the form element * * - If `preventDefault()` is called by the event handler, the sending process is canceled */ submit(): void; /** * Returns `true` if the form is in a submittable state after performing state checks and validation * * @param options - PrepareFormSubmissionOptions * @returns `true` if submission is possible */ prepareFormSubmission(options?: PrepareFormSubmissionOptions): Promise<boolean>; protected _dispatchAction(options?: DispatchFormActionOptions): Promise<void>; /** * Dispatch the specified action function * * @param options - Dispatch option for form action */ dispatchAction(options?: DispatchFormActionOptions): Promise<void>; /** * Handler for form element submission * * @param ev - Submit event object */ handleSubmit(ev: Event): void; } declare function useForm(props: FormProps, ctx: FormContext, options?: FormOptions): VueForm; //#endregion //#region src/service.d.ts type FormErrorMessageResolver = (error: FormNodeError, node?: FormNodeControl) => string | void; /** * Scroll option for the form element */ interface VueFormScrollOptions { /** * Default scroll option * * @see {@link ScrollIntoViewOptions} */ options?: ScrollIntoViewOptions; /** * Scroll handler function * * @param element - Scroll target element * @param options - Scroll option * @returns When canceling the default scroll and implementing custom scrolling within the application, return a truthy value. */ fn?: (element: HTMLElement, options?: ScrollIntoViewOptions) => void; } interface VueFormServiceOptions { errorMessageResolvers?: FormErrorMessageResolver[]; /** * Scroll option for the form element * * @see {@link VueFormScrollOptions} */ scroll?: VueFormScrollOptions; /** * Default value for text input autocomplete. * * @see {@link FormAutoComplete} */ defaultAutocomplete?: FormAutoComplete | boolean | undefined; } /** * Root service of `vue-form-control` */ declare class VueFormService { readonly errorMessageResolvers: FormErrorMessageResolver[]; /** * Scroll option for the form element * * @see {@link VueFormScrollOptions} */ readonly scroll?: VueFormScrollOptions; constructor(options?: VueFormServiceOptions); addMessageResolver(resolvers: FormErrorMessageResolver | FormErrorMessageResolver[]): void; resolveErrorMessage(error: FormNodeError, node?: FormNodeControl): string | void; scrollToElement(element: HTMLElement, options?: ScrollIntoViewOptions): void; } //#endregion //#region src/composables/wrapper.d.ts type RequiredChipSource = (() => VNodeChild) | string | boolean; type FormNodeWrapperHinttip = boolean | string | (() => VNodeChild); type FormNodeWrapperHinttipDelay = 'click' | number; type FormNodeWrapperSlots = DefineSlotsType<{ /** label */ label?: (wrapper: FormNodeWrapper) => any; /** hint message */ hint?: (wrapper: FormNodeWrapper) => any; /** Elements to be added to the information message */ infoAppends?: (wrapper: FormNodeWrapper) => any; } & FormNodeErrorSlots>; declare function createFormNodeWrapperProps(): { /** * Instance of FormNodeControl * * When this setting is applied, the state and error messages will always refer to the state of this node. If not set, it will attempt to compute them from descendant nodes. */ nodeControl: PropType<FormNodeControl>; /** label */ label: PropType<VNodeChildOrSlot>; /** hint message */ hint: PropType<VNodeChildOrSlot>; /** Settings for displaying hint as tips */ hinttip: PropType<FormNodeWrapperHinttip>; /** hint tip Display Delay */ hinttipDelay: PropType<FormNodeWrapperHinttipDelay>; /** Elements to be added to the information message */ infoAppends: PropType<VNodeChildOrSlot>; /** Hide information */ hiddenInfo: BooleanConstructor; /** Chip(required) display settings */ requiredChip: PropType<RequiredChipSource>; /** * Collect the error messages of all nodes belonging to this node * * By default, a node attempts to render error messages on its own, but enabling this setting allows the parent wrapper to manage the rendering of error messages. * If you want to exclude a specific node from this configuration, enable the `showOwnErrors` setting for that node. * * @default true */ collectErrorMessages: { type: BooleanConstructor; default: boolean; }; }; type FormNodeWrapperProps = ExtractPropTypes<ReturnType<typeof createFormNodeWrapperProps>>; declare function createFormNodeWrapperEmits(): { clickLabel: (ev: PointerEvent, wrapper: FormNodeWrapper) => boolean; }; type FormNodeWrapperEmitOptions = ReturnType<typeof createFormNodeWrapperEmits>; declare function createFormNodeWrapperSettings(): { props: { /** * Instance of FormNodeControl * * When this setting is applied, the state and error messages will always refer to the state of this node. If not set, it will attempt to compute them from descendant nodes. */ nodeControl: PropType<FormNodeControl>; /** label */ label: PropType<VNodeChildOrSlot>; /** hint message */ hint: PropType<VNodeChildOrSlot>; /** Settings for displaying hint as tips */ hinttip: PropType<FormNodeWrapperHinttip>; /** hint tip Display Delay */ hinttipDelay: PropType<FormNodeWrapperHinttipDelay>; /** Elements to be added to the information message */ infoAppends: PropType<VNodeChildOrSlot>; /** Hide information */ hiddenInfo: BooleanConstructor; /** Chip(required) display settings */ requiredChip: PropType<RequiredChipSource>; /** * Collect the error messages of all nodes belonging to this node * * By default, a node attempts to render error messages on its own, but enabling this setting allows the parent wrapper to manage the rendering of error messages. * If you want to exclude a specific node from this configuration, enable the `showOwnErrors` setting for that node. * * @default true */ collectErrorMessages: { type: BooleanConstructor; default: boolean; }; }; emits: { clickLabel: (ev: PointerEvent, wrapper: FormNodeWrapper) => boolean; }; }; type FormNodeWrapperContext = SetupContext<FormNodeWrapperEmitOptions>; interface FormNodeWrapperOptions { hinttipPrepend?: () => VNodeChild; } /** * Form node wrapper */ declare class FormNodeWrapper { readonly _props: FormNodeWrapperProps; readonly _service: VueFormService; protected _ctx: FormNodeWrapperContext | undefined; protected _allNodes: Ref<FormNodeControl[]>; protected _labelSlot: ComputedRef<TypedSlot<FormNodeWrapper> | undefined>; protected _hintSlot: ComputedRef<TypedSlot<FormNodeWrapper> | undefined>; protected _hinttip: ComputedRef<VNodeChild>; protected _hinttipDelay: ComputedRef<FormNodeWrapperHinttipDelay | undefined>; protected _hinttipPrepend?: () => VNodeChild; protected _infoAppendsSlot: ComputedRef<TypedSlot<FormNodeWrapper> | undefined>; protected _validating: ComputedRef<boolean>; protected _pending: ComputedRef<boolean>; protected _focused: ComputedRef<boolean>; protected _dirty: ComputedRef<boolean>; protected _disabled: ComputedRef<boolean>; protected _readonly: ComputedRef<boolean>; protected _viewonly: ComputedRef<boolean>; protected _touched: ComputedRef<boolean>; protected _required: ComputedRef<boolean>; protected _invalid: ComputedRef<boolean>; protected _resolvedErrorMessages: ComputedRef<FormNodeErrorMessageSource[]>; /** * Root service of `vue-form-control` * * @see {@link VueFormService} */ get service(): VueFormService; /** * Instance of FormNodeControl * * When this setting is applied, the state and error messages will always refer to the state of this node. If not set, it will attempt to compute them from descendant nodes. */ get nodeControl(): FormNodeControl | undefined; /** * List of all nodes belonging to this wrapper * * This list is a reactive list, and depending on usage, it may contain a large number of nodes. * Please be aware that complex operations using this list can lead to performance issues. */ get allNodes(): FormNodeControl<any, any, BooleanConstructor>[]; /** * At least one of the associated nodes is validating the value */ get validating(): boolean; /** * Pending processing * * This is marked as `true` during the validation and finalization process of the value */ get pending(): boolean; /** * One of the associated nodes is currently focused */ get focused(): boolean; /** * The changes to the input value have not been committed yet * * @see {@link FormNodeControl.initialValue initialValue} */ get dirty(): boolean; /** * The input value has not been changed from its initial value */ get pristine(): boolean; /** * All associated nodes are disabled */ get isDisabled(): boolean; /** * All associated nodes are read-only */ get isReadonly(): boolean; /** * All associated nodes are view-only */ get isViewonly(): boolean; /** * All associated nodes are operable */ get canOperation(): boolean; /** * One of the associated nodes has already been touched */ get touched(): boolean; /** * None of the associated nodes has been touched yet */ get untouched(): boolean; /** * One of the associated nodes requires input */ get isRequired(): boolean; /** * There is an error in the input value of one of the associated nodes */ get invalid(): boolean; /** * No errors in the input values of all associated nodes */ get valid(): boolean; /** * Collect the error messages of all nodes belonging to this node */ get collectErrorMessages(): boolean; /** * Source code for all collected error messages * * This list is generated based on the setting of {@link FormNodeControl.showOwnErrors showOwnErrors}. * * @see {@link FormNodeErrorMessageSource} */ get errorMessages(): FormNodeErrorMessageSource[]; /** * Source code for the first error message among all collected messages * * This list is generated based on the setting of {@link FormNodeControl.showOwnErrors showOwnErrors}. * * @see {@link FormNodeErrorMessageSource} */ get firstErrorMessage(): FormNodeErrorMessageSource | undefined; get labelSlot(): TypedSlot<FormNodeWrapper> | undefined; get hintSlot(): TypedSlot<FormNodeWrapper> | undefined; get infoAppendsSlot(): TypedSlot<FormNodeWrapper> | undefined; get hinttipDelay(): FormNodeWrapperHinttipDelay | undefined; constructor(props: FormNodeWrapperProps, ctx: FormNodeWrapperContext, options?: FormNodeWrapperOptions); renderLabel(): import("vue").VNodeArrayChildren | undefined; renderHint(allowNotFocused?: boolean): import("vue").VNodeArrayChildren | undefined; renderInfoAppends(): import("vue").VNodeArrayChildren | undefined; protected _getContextOrDie(): { attrs: import("vue").Attrs; slots: Readonly<{ [name: string]: import("vue").Slot<any> | undefined; }>; emit: (event: "clickLabel", ev: PointerEvent, wrapper: FormNodeWrapper) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed) => void; }; renderFirstError(slotsOverrides?: FormNodeErrorSlotsSource): import("vue").VNodeArrayChildren | undefined; renderMessage(allowNotFocused?: boolean): import("vue").VNodeArrayChildren | " "; renderHinttip(): { tip: VNodeChild; hint: VNodeChild; } | undefined; /** @internal */ __joinFromNode(node: FormNodeControl): void; /** @internal */ __leaveFromNode(node: FormNodeControl): void; /** * Generate a Proxy instance that extends the interface for this wrapper. * * @param trait - trait object * @returns Mixed-in Proxy */ extend<U extends object>(trait: U): Mixin<this, U>; } declare function useFormNodeWrapper(props: FormNodeWrapperProps, ctx: FormNodeWrapperContext, options?: FormNodeWrapperOptions): FormNodeWrapper; //#endregion //#region src/composables/node.d.ts type RecursiveVerifiableRuleOrFn = RecursiveArray<VerifiableRuleOrFn>; type RecursiveVerifiableRuleOrFnArray = Exclude<RecursiveVerifiableRuleOrFn, VerifiableRuleOrFn>; /** * Merge two specified recursive rule specifications into a single array and return it. * * @param baseRules - Base rules * @param mergeRules - Merge rules * @returns Array of merged rules */ declare function mergeFormNodeRules(baseRules: RecursiveVerifiableRuleOrFn | undefined, mergeRules: RecursiveVerifiableRuleOrFn | undefined): RecursiveVerifiableRuleOrFnArray; type FormNodeType = string | number | symbol; interface FormNodeError extends Omit<ValidationError, '$$symbol'> {} type FormNodeErrors = FormNodeError[]; declare function toFormNodeError(source: string | ValidationError | FormNodeError): FormNodeError; /** * Validation Timing * * - `always` Always validate * - `touch` Once touched, always validated thereafter. * - `blur` Once the focus is removed from the element at least once, subsequent validations will always be performed. * - `change` Once the value is changed at least once, subsequent validations will always be performed. * - `manual` Validation is not performed automatically. Only manual validation through programming is possible. * */ type ValidateTiming = 'always' | 'touch' | 'blur' | 'change' | 'manual'; type ValidationResult = ValidationError[] | null; type ValidateResolver = (result: ValidationResult) => void; type FormNodeStateExtension = (nodeControl: FormNodeControl, computedValue: boolean) => boolean; interface FormNodeStateExtensions { disabled?: FormNodeStateExtension; readonly?: FormNodeStateExtension; viewonly?: FormNodeStateExtension; canOperation?: FormNodeStateExtension; } interface FormNodeControlBaseOptions { nodeType?: FormNodeType; requiredFactory?: () => Rule<any> | undefined; defaultValidateTiming?: ValidateTiming; validationValue?: () => any; stateExtensions?: FormNodeStateExtensions; /** Add a custom error message */ errorMessages?: () => string | string[] | undefined; } interface FormNodeControlOptions<T = any, D = T, Required extends Prop<any> = BooleanConstructor> extends FormNodeControlBaseOptions { modelValue?: Prop<T, D>; required?: Required; shallow?: boolean; } type FormNodeErrorSlotsSource = { /** Error message */ error?: (error: FormNodeError) => any; } & { [K in `error:${string}`]: (error: FormNodeError) => any; }; type FormNodeErrorSlots = DefineSlotsType<FormNodeErrorSlotsSource>; declare function createFormNodeProps<T, D = T, Required extends Prop<any> = PropType<boolean>>(options?: FormNodeControlOptions<T, D, Required>): { /** * form node name * * This is set as is for input elements. */ name: StringConstructor; /** * Tag string for node searching */ tag: StringConstructor; /** model value */ modelValue: Prop<T, D>; /** * Tab index * * @default 0 * * @see https://developer.mozilla.org/docs/Web/HTML/Global_attributes/tabindex */ tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; /** Automatic focus */ autofocus: BooleanConstructor; /** disabled state */ disabled: BooleanConstructor; /** read-only state */ readonly: BooleanConstructor; /** view-only state */ viewonly: BooleanConstructor; /** * Spell Check Settings * * @see https://developer.mozilla.org/docs/Web/HTML/Global_attributes/spellcheck */ spellcheck: BooleanConstructor; /** required */ required: BooleanConstructor | Required; /** clearable */ clearable: BooleanConstructor; /** * Validation Timing * * - `always` Always validate * - `touch` Once touched, always validated thereafter. * - `blur` Once the focus is removed from the element at least once, subsequent validations will always be performed. * - `change` Once the value is changed at least once, subsequent validations will always be performed. * - `manual` Validation is not performed automatically. Only manual validation through programming is possible. * * @see {@link ValidateTiming} */ validateTiming: { type: PropType<ValidateTiming>; default: ValidateTiming; }; /** * List of validation rules */ rules: { type: PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; /** * Validation dependencies * * In vue-form-control, validation is performed again whenever the input value or related values change. However, if the validation condition references values from other nodes or external reactive values that are not included in the node, those changes cannot be detected. * By registering a function that returns such external reactive values, validation can be automatically triggered. */ validationDeps: PropType<(nodeControl: FormNodeControl) => any>; /** Force an error state. */ error: BooleanConstructor; /** List of error messages. */ errorMessages: PropType<string | string[]>; /** * Display error messages on this node itself * * If `true`, attempts to render errors for this node itself; if `false`, delegates error message display to the associated form group or wrapper. * * @default `false` if a parent group or wrapper exists and the `collectErrorMessages` setting is enabled; otherwise, `true`. */ showOwnErrors: { type: BooleanConstructor; default: undefined; }; /** * Detach and become independent from the parent node * * By default, the form node inherits the state of the form node existing in the parent tree and notifies the parent node of its own validation status, among other things. This option disables that behavior, allowing this node and its descendants to be detached from the parent node. */ detach: BooleanConstructor; }; type FormNodeProps = ExtractPropTypes<ReturnType<typeof createFormNodeProps>>; declare function createFormNodeEmits<T, D = T>(options?: FormNodeControlOptions<T, D>): { /** * Update Model Values */ 'update:modelValue': (value: T | D) => boolean; /** * Updating error content. * @param errors - List of error contents. */ 'update:errors': (errors: FormNodeError[]) => boolean; /** * Update Model Values */ change: (value: T | D) => boolean; /** * Focus on an element. * @param ev - FocusEvent */ focus: (ev: FocusEvent) => boolean; /** * The focus is removed from an element. * @param ev - FocusEvent */ blur: (ev: FocusEvent) => boolean; }; declare class Wrapper<T, D = T> { wrapped(options: FormNodeControlOptions<T, D>): { /** * Update Model Values */ 'update:modelValue': (value: T | D) => boolean; /** * Updating error content. * @param errors - List of error contents. */ 'update:errors': (errors: FormNodeError[]) => boolean; /** * Update Model Values */ change: (value: T | D) => boolean; /** * Focus on an element. * @param ev - FocusEvent */ focus: (ev: FocusEvent) => boolean; /** * The focus is removed from an element. * @param ev - FocusEvent */ blur: (ev: FocusEvent) => boolean; }; } interface FormNodeEmitOptions<T, D = T> extends ReturnType<Wrapper<T, D>['wrapped']> {} declare function createFormNodeSettings<T, D = T>(options: FormNodeControlOptions<T, D>): { options: FormNodeControlOptions<T, D, BooleanConstructor>; props: { /** * form node name * * This is set as is for input elements. */ name: StringConstructor; /** * Tag string for node searching */ tag: StringConstructor; /** model value */ modelValue: Prop<T, D>; /** * Tab index * * @default 0 * * @see https://developer.mozilla.org/docs/Web/HTML/Global_attributes/tabindex */ tabindex: { type: (StringConstructor | NumberConstructor)[]; default: number; }; /** Automatic focus */ autofocus: BooleanConstructor; /** disabled state */ disabled: BooleanConstructor; /** read-only state */ readonly: BooleanConstructor; /** view-only state */ viewonly: BooleanConstructor; /** * Spell Check Settings * * @see https://developer.mozilla.org/docs/Web/HTML/Global_attributes/spellcheck */ spellcheck: BooleanConstructor; /** required */ required: BooleanConstructor | PropType<boolean>; /** clearable */ clearable: BooleanConstructor; /** * Validation Timing * * - `always` Always validate * - `touch` Once touched, always validated thereafter. * - `blur` Once the focus is removed from the element at least once, subsequent validations will always be performed. * - `change` Once the value is changed at least once, subsequent validations will always be performed. * - `manual` Validation is not performed automatically. Only manual validation through programming is possible. * * @see {@link ValidateTiming} */ validateTiming: { type: PropType<ValidateTiming>; default: ValidateTiming; }; /** * List of validation rules */ rules: { type: PropType<RecursiveVerifiableRuleOrFn>; default: () => never[]; }; /** * Validation dependencies * * In vue-form-control, validation is performed again whenever the input value or related values change. However, if the validation condition references values from other nodes or external reactive values that are not included in the node, those changes cannot be detected. * By registering a function that returns such external reactive values, validation can be automatically triggered. */ validationDeps: PropType<(nodeControl: FormNodeControl) => any>; /** Force an error state. */ error: BooleanConstructor; /** List of error messages. */ errorMessages: PropType<string | string[]>; /** * Display error messages on this node itself * * If `true`, attempts to render errors for this node itself; if `false`, delegates error message display to the associated form group or wrapper. * * @default `false` if a parent group or wrapper exists and the `collectErrorMessages` setting is enabled; otherwise, `true`. */ showOwnErrors: { type: BooleanConstructor; default: undefined; }; /** * Detach and become independent from the parent node * * By default, the form node inherits the state of the form node existing in the parent tree and notifies the parent node of its own validation status, among other things. This option disables that behavior, allowing this node and its descendants to be detached from the parent node. */ detach: BooleanConstructor; }; emits: { /** * Update Model Values */ 'update:modelValue': (value: T | D) => boolean; /** * Updating error content. * @param errors - List of error contents. */ 'update:errors': (errors: FormNodeError[]) => boolean; /** * Update Model Values */ change: (value: T | D) => boolean; /** * Focus on an element. * @param ev - FocusEvent */ focus: (ev: FocusEvent) => boolean; /** * The focus is removed from an element. * @param ev - FocusEvent */ blur: (ev: FocusEvent) => boolean; }; }; type FormNodeContext<T, D = T> = SetupContext<FormNodeEmitOptions<T, D>>; /** * Source code for rendering error messages of form nodes */ interface FormNodeErrorMessageSource { /** Render error message */ render: (slotsOverrides?: FormNodeErrorSlotsSource) => VNodeArrayChildren; /** * Error object * * @see {@link FormNodeError} */ error: FormNodeError; /** * Node holding the error * * @see {@link FormNodeControl} */ node: FormNodeControl; /** * Automatically generated key * * Can be safely used as the key for the vnode when rendering in lists, etc. */ key: string; } /** * Base class for all form nodes */ declare class FormNodeControl<T = any, D = T, Required extends Prop<any> = BooleanConstructor> { readonly _props: FormNodeProps; readonly _service: VueFormService; readonly nodeType?: FormNodeType; readonly __multiple: boolean; protected _isMounted: Ref<boolean, boolean>; protected _mountedId: Ref<number | undefined, number | undefined>; protected _ctx: FormNodeContext<T, D>; protected _parentNode: FormNodeControl | null; protected _parentForm: VueForm | null; protected _parentFormGroup: FormGroupControl | null; protected _parentFormNodeWrapper: FormNodeWrapper | null; protected _booted: Ref<boolean, boolean>; protected _name: ComputedRef<string | undefined>; protected _value: Ref<T | D>; protected _initialValue: Ref<T | D>; protected _focused: Ref<boolean, boolean>; protected _children: Ref<FormNodeControl[]>; protected _invalidChildren: ComputedRef<FormNodeControl[]>; protected _finalizePromise: Ref<(() => Promise<void>) | null>; protected _validationErrors: Ref<ValidationError[]>; protected _validateResolvers: ValidateResolver[]; protected _lastValidateValueChanged: boolean; protected _validating: Ref<boolean, boolean>; protected _validateRequestId: number; protected _isDestroyed: boolean; protected _dirty: ComputedRef<boolean>; protected _touched: Ref<boolean, boolean>; protected _shouldValidate: Ref<boolean, boolean>; protected _currentValue: WritableComputedRef<T | D>; protected _errorMessages: ComputedRef<string[]>; protected _errors: ComputedRef<FormNodeError[]>; protected _resolvedErrorMessages: ComputedRef<FormNodeErrorMessageSource[]>; protected _errorCount: ComputedRef<number>; protected _isDisabled: ComputedRef<boolean>; protected _isReadonly: ComputedRef<boolean>; protected _isViewonly: ComputedRef<boolean>; protected _canOperation: ComputedRef<boolean>; protected _rules: ComputedRef<VerifiableRule[]>; protected _hasRequired: ComputedRef<boolean>; protected _tabindex: ComputedRef<number>; protected _cii: ComponentInternalInstance | null; protected _validationValueGetter?: () => any; protected _shouldSkipValidation: boolean; protected _stateExtensions: FormNodeStateExtensions; protected _requiredFactory: () => Rule<any> | undefined; /** * Root service of `vue-form-control` * * @see {@link VueFormService} */ get service(): VueFormService; /** * form node name * * This is set as is for input elements. */ get name(): string | undefined; /** * Tag string for node searching */ get tag(): string | undefined; /** Parent node */ get parentNode(): FormNodeControl | null; /** Parent form group */ get parentFormGroup(): FormGroupControl | null; /** Parent form node wrapper */ get parentFormNodeWrapper(): FormNodeWrapper | null; /** Parent form */ get parentForm(): VueForm | null; /** Automatic focus */ get autofocus(): boolean; /** * Detached and independent from the parent node */ get detached(): boolean; /** * Component created * * @remarks * Please be aware that it may not have been mounted yet. */ get booted(): boolean; /** Component mounted */ get isMounted(): boolean; /** If already mounted, its unique ID. */ get mountedId(): number | undefined; /** If already mounted, its unique ID. */ get mountedNodeId(): string | undefined; /** Finalizing the value adjustment process */ get isFinalizing(): boolean; /** Validating the value */ get validating(): boolean; /** * Pending processing * * This is marked as `true` during the validation and finalization process of the value */ get pending(): boolean; /** Current input value */ get value(): T | D; set value(value: T | D); /** Value used for validation */ get validationValue(): any; /** In focus */ get focused(): boolean; /** * Initial value before commit * * This value, once initialized with the value passed when the FormNode is instantiated, will not be modified from within the vue-form-control package internals. * Calling the commit series of methods from the application side updates the value to its state at that moment. * * @see {@link FormNodeControl.commitSelfValue commitSelfValue} * @see {@link FormNodeControl.commitValue commitValue} * @see {@link FormNodeControl.commitSelf commitSelf} * @see {@link FormNodeControl.commit commit} */ get initialValue(): T | D; /** * The changes to the input value have not been committed yet * * @see {@link FormNodeControl.initialValue initialValue} */ get dirty(): boolean; /** * The input value has not been changed from its initial value */ get pristine(): boolean; /** * Touched the elements of this node at least once */ get touched(): boolean; set touched(touched: boolean); /** * Not touched the elements of this node yet. */ get untouched(): boolean; /** * The list of FormNode instances directly belonging to this node as children */ get children(): FormNodeControl[]; /** * The list of FormNode instances directly belonging to itself, and possessing one or more errors */ get invalidChildren(): FormNodeControl[]; /** * The list of validation errors for the value within itself */ get validationErrors(): ValidationError[]; /** * The list of all errors within itself * * This is a merged list of error messages injected through properties and its own `validationErrors`. * * @remarks * This list does not include error information specified with the `erro