/* eslint-disable @typescript-eslint/no-explicit-any */ import type { DeepKeys, DeepValue, FieldApi, FieldAsyncValidateOrFn, FieldState, FieldValidateOrFn, FormApi, FormAsyncValidateOrFn, FormOptions, FormState, FormValidateOrFn, StandardSchemaV1, VueFormApi } from "@tanstack/vue-form" import type * as Effect from "effect-app/Effect" import type * as S from "effect-app/Schema" import type { UnionToTuples } from "effect-app/utils" import type { Fiber as EffectFiber } from "effect/Fiber" import type * as Order from "effect/Order" import type { Redacted } from "effect/Redacted" import type { AllowedComponentProps, ComponentCustomProps, ComputedRef, PublicProps, ShallowUnwrapRef, VNode, VNodeProps } from "vue" import type { MergedInputProps, OmegaFieldInternalApi, TaggedUnionOptionsArray } from "./InputProps" import type { MetaRecord, NestedKeyOf } from "./meta/types" import type { defaultValuesPriorityUnion as PersistencyPriority, Policies as PersistencyPolicies } from "./persistency" import type { FormErrors } from "./submit" export type FieldPath = unknown extends T ? string // technically we cannot have primitive at the root : T extends string | boolean | number | null | undefined | symbol | bigint | Redacted ? "" // technically we cannot have array at the root : T extends ReadonlyArray ? FieldPath_ : { [K in keyof T]: FieldPath_ }[keyof T] export type FieldPath_ = unknown extends T ? string : T extends string | boolean | number | null | undefined | symbol | bigint | Redacted ? Path : T extends ReadonlyArray ? FieldPath_ | Path : { [K in keyof T]: FieldPath_ }[keyof T] export type BaseProps> = { /** * Will fallback to i18n when not specified. * Can also be provided via #label slot for custom HTML labels. * When using the slot, it receives bindings: { required, id, label } */ label?: string validators?: FieldValidators // Use FlexibleArrayPath: if name contains [], just use TName; otherwise intersect with Leaves name: TName /** * Optional class to apply to the input element. * - If a string is provided, it will be used instead of the general class * - If null is provided, no class will be applied (neither inputClass nor general class) * - If undefined (not provided), the general class will be used */ inputClass?: string | null } export type TypesWithOptions = "radio" | "select" | "multiple" | "autocomplete" | "autocompletemultiple" export type DefaultTypeProps = { type?: TypeOverride options?: undefined } | { type?: TypesWithOptions // TODO: options should depend on `type`, but since there is auto-type, we can't currently enforce it. // hence we allow it also for type? (undefined) atm options?: { title: string value: unknown }[] } export type OmegaInputPropsBase< From extends Record, To extends Record, Name extends DeepKeys > = { form: OF & { meta: MetaRecord i18nNamespace?: string } } & BaseProps export type OmegaInputProps< From extends Record, To extends Record, Name extends DeepKeys, TypeProps = DefaultTypeProps > = { form: OmegaFormReturn & { meta: MetaRecord i18nNamespace?: string } } & BaseProps export type OmegaArrayProps< From extends Record, To extends Record, Name extends DeepKeys > = & Omit< OmegaInputProps, "validators" | "options" | "label" | "type" | "items" | "name" > & { name: DeepKeys defaultItems?: DeepValue> // deprecated items, caused bugs in state update, use defaultItems instead. It's not a simple Never, because Volar explodes items?: "please use `defaultItems` instead" } export type TypeOverride = | "string" | "text" | "number" | "select" | "multiple" | "boolean" | "radio" | "autocomplete" | "autocompletemultiple" | "switch" | "range" | "password" | "email" | "date" export interface OmegaError { label: string inputId: string errors: readonly string[] } export type FormProps = & Omit< FormOptions< From, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, Record | undefined // TODO >, | "onSubmit" | "defaultValues" > & { // when defaultValues are allowed to be undefined, then they should also be allowed to be partial // this fixes validator issues where a defaultValue of "" leads to "requires at least 1 character", while manually emptying the field changes it to "is required" defaultValues?: Partial onSubmit?: (props: { formApi: OmegaFormParams meta: any value: To }) => Promise | EffectFiber | Effect.Effect } export type OmegaFormParams = FormApi< From, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, Record | undefined > export type OmegaFormState = FormState< From, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined > // TODO: stitch TSubmitMeta somehow export type OmegaFormApi | undefined> = & OmegaFormParams & VueFormApi< From, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, TSubmitMeta > export type FormComponent = VueFormApi< T, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, Record | undefined > export type FormType< From extends Record, To extends Record, Name extends DeepKeys > = OmegaFormApi & { Field: OmegaFieldInternalApi } export type PrefixFromDepth< K extends string | number, _TDepth extends any[] > = K export type FieldValidators = { onChangeAsync?: FieldAsyncValidateOrFn onChange?: FieldValidateOrFn onBlur?: FieldValidateOrFn onBlurAsync?: FieldAsyncValidateOrFn } export type OmegaAutoGenMeta< From extends Record, To extends Record, Name extends DeepKeys > = Omit, "form"> type keysRule = | { keys?: NestedKeyOf[] banKeys?: "You should only use one of banKeys or keys, not both, moron" } | { keys?: "You should only use one of banKeys or keys, not both, moron" banKeys?: NestedKeyOf[] } export type Policies = PersistencyPolicies export type defaultValuesPriorityUnion = PersistencyPriority export type OmegaConfig = { i18nNamespace?: string persistency?: { /** Order of importance: * - "querystring": Highest priority when persisting * - "local" and then "session": Lower priority storage options */ policies?: UnionToTuples overrideDefaultValues?: "deprecated: use defaultValuesPriority" id?: string } & keysRule ignorePreventCloseEvents?: boolean /** * Prevents browser window/tab exit when form has unsaved changes. * Shows native browser "Leave site?" dialog. * * @remarks * - Opt-in only: Must explicitly enable * - Independent from data persistence feature */ preventWindowExit?: "prevent" | "prevent-and-reset" | "nope" input?: any /** * Default values order is: Tanstack default values passed as second parameter to useOmegaForm, then persistency * default values from querystring or local/session storage, then defaults from schema * You can customize the order and with omegaConfig.defaultValuesPriority * default value = ['tanstack', 'persistency', 'schema'] */ defaultValuesPriority?: UnionToTuples defaultFromSchema?: "deprecated: use defaultValuesPriority" } export interface OF extends OmegaFormApi { meta: MetaRecord unionMeta: Record> clear: () => void /** * Backfills the untouched children of any materialised nullable struct with * their schema default (or `null`), so the live `values` matches what * validation and decoding see. Called after a field change. */ normalizeNullableStructs: () => void i18nNamespace?: string ignorePreventCloseEvents?: boolean registerField: ( field: ComputedRef<{ name: string label: string id: string }> ) => void /** @experimental */ handleSubmitEffect: { /** * when `checkErrors` is true, the Effect will fail with `FormErrors` when there are validation errors * @experimental */ (options: { checkErrors: true; meta?: Record }): Effect.Effect> /** @experimental */ (options?: { meta?: Record }): Effect.Effect } } type __VLS_PrettifyLocal = & { [K in keyof T]: T[K] } & {} // Type aliases for Array component slots - using cached types for performance // eslint-disable-next-line @typescript-eslint/no-explicit-any type CachedFieldApi< From extends Record, To extends Record, TypeProps = DefaultTypeProps > = FieldApi< From, OmegaFormReturn["_keys"], DeepValue["_keys"]>, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, Record | undefined > // eslint-disable-next-line @typescript-eslint/no-explicit-any type CachedFieldState< From extends Record, To extends Record, TypeProps = DefaultTypeProps > = FieldState< From, OmegaFormReturn["_keys"], DeepValue["_keys"]>, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, | FieldAsyncValidateOrFn< From, OmegaFormReturn["_keys"], DeepValue["_keys"]> > | undefined, FormValidateOrFn | undefined, FormValidateOrFn | undefined, StandardSchemaV1, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined, FormValidateOrFn | undefined, FormAsyncValidateOrFn | undefined > export interface OmegaFormReturn< From extends Record, To extends Record, TypeProps = DefaultTypeProps > extends OF { // Pre-computed type aliases - computed ONCE for performance _paths: FieldPath _keys: NestedKeyOf _schema: S.Codec // this crazy thing here is copied from the OmegaFormInput.vue.d.ts, with `From` removed as Generic, instead closed over from the From generic above.. Input: ["_paths"]>( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< & Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & TypeProps & Partial<{}> > & BaseProps & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: { default?(props: MergedInputProps): void label?: (props: { required: boolean; id: string; label: string }) => void } emit: {} }> ) => VNode & { __ctx?: Awaited } Errors: ( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< & Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & Partial<{}> > & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: { default: (props: { errors: readonly OmegaError[]; showedGeneralErrors: string[] }) => void } emit: {} }> ) => VNode & { __ctx?: Awaited } TaggedUnion: ["_keys"]>( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< & Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & { name?: Name type?: "select" | "radio" options: TaggedUnionOptionsArray _debugName?: [NoInfer] label?: string } & {} > & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: Record< string, (props: { field: FieldApi< From, Name, DeepValue, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any > state: FieldState< From, Name, DeepValue, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any > }) => any > emit: {} }> ) => VNode & { __ctx?: Awaited } Array: ["_keys"]>( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< & Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & (Omit, "form">) & {} > & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: { "pre-array"?: (props: { field: CachedFieldApi state: CachedFieldState }) => any } & { default?: (props: { subField: CachedFieldApi subState: CachedFieldState index: number field: CachedFieldApi }) => any } & { "post-array"?: (props: { field: CachedFieldApi state: CachedFieldState }) => any } & { field?: (props: { field: CachedFieldApi }) => any } emit: {} }> ) => VNode & { __ctx?: Awaited } AutoGen: ["_keys"]>( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & { // form: OmegaInputProps["form"] pick?: OmegaFormReturn["_keys"][] omit?: OmegaFormReturn["_keys"][] labelMap?: (key: OmegaFormReturn["_keys"]) => string | undefined filterMap?: >( key: OmegaFormReturn["_keys"], meta: M ) => boolean | M order?: OmegaFormReturn["_keys"][] sort?: Order.Order> } & {} > & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: { default(props: { child: OmegaAutoGenMeta }): void } emit: {} }> ) => VNode & { __ctx?: Awaited } Form: >( __VLS_props: NonNullable>["props"], __VLS_ctx?: __VLS_PrettifyLocal>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable>["expose"], __VLS_setup?: Promise<{ props: & __VLS_PrettifyLocal< Pick< & Partial<{}> & Omit< {} & VNodeProps & AllowedComponentProps & ComponentCustomProps, never >, never > & { // form: OmegaFormReturn disabled?: boolean subscribe?: K[] } & {} > & PublicProps expose(exposed: ShallowUnwrapRef<{}>): void attrs: any slots: { default(props: { subscribedValues: K[] extends undefined[] ? Record : Pick, K> }): void } emit: {} }> ) => VNode & { __ctx?: Awaited } }