/* eslint-disable @typescript-eslint/no-explicit-any -- TanStack Form / Vue render-fn slot interop */ import type { DeepKeys } from "@tanstack/vue-form" import { type Component, h } from "vue" import type { MergedInputProps } from "./InputProps" import OmegaInput from "./OmegaInput.vue" import { type DefaultTypeProps } from "./types" import { useOmegaForm } from "./useOmegaForm" export const createUseFormWithCustomInput = < TypeProps = DefaultTypeProps >(CustomInputComponent: Component) => { return < From extends Record, To extends Record >( ...args: Parameters> ) => { const [schema, tanstackFormOptions, omegaConfig] = args // Create a wrapper that extends OmegaInput and overrides its default slot const WrappedInput = { name: "WrappedInput", inheritAttrs: false, setup(props: any, { attrs, slots }: any) { return () => h(OmegaInput, { ...props, ...attrs }, { // Override the default slot that OmegaInternalInput provides default: >({ field, state, ...inputProps }: MergedInputProps) => { // Filter out attrs that are already in inputProps or are special like 'form' const filteredAttrs = Object.fromEntries( Object.entries(attrs).filter(([key]) => !Object.prototype.hasOwnProperty.call(inputProps, key) && key !== "form" ) ) return h(CustomInputComponent, { ...filteredAttrs, field, state, inputProps }, { // Pass through label slot if it exists ...(slots.label && { label: (labelProps: any) => slots.label(labelProps) }), // Pass through default slot if it exists ...(slots.default && { default: (slotProps: any) => slots.default(slotProps) }) }) }, // Pass through label slot to OmegaInput ...(slots.label && { label: (labelProps: any) => slots.label(labelProps) }) }) } } const form = useOmegaForm( schema, tanstackFormOptions, { ...omegaConfig, input: WrappedInput } ) return form } }