import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { FormField } from "@/components/ui/form"; import { useForm, useFormContext } from "react-hook-form"; import * as z from "zod"; import { DEFAULT_ZOD_HANDLERS, INPUT_COMPONENTS } from "../config"; import { Dependency, FieldConfig, FieldConfigItem } from "../types"; import { beautifyObjectName, getBaseSchema, getBaseType, zodToHtmlInputProps, } from "../utils"; import AutoFormArray from "./array"; import resolveDependencies from "../dependencies"; function DefaultParent({ children }: { children: React.ReactNode }) { return <>{children}; } export default function AutoFormObject< SchemaType extends z.ZodObject, >({ schema, form, fieldConfig, path = [], dependencies = [], }: { schema: SchemaType | z.ZodEffects; form: ReturnType; fieldConfig?: FieldConfig>; path?: string[]; dependencies?: Dependency>[]; }) { const { watch } = useFormContext(); // Use useFormContext to access the watch function if (!schema) { return null; } const { shape } = getBaseSchema(schema) || {}; if (!shape) { return null; } const handleIfZodNumber = (item: z.ZodAny) => { const isZodNumber = (item as any)._def.typeName === "ZodNumber"; const isInnerZodNumber = (item._def as any).innerType?._def?.typeName === "ZodNumber"; if (isZodNumber) { (item as any)._def.coerce = true; } else if (isInnerZodNumber) { (item._def as any).innerType._def.coerce = true; } return item; }; return ( {Object.keys(shape).map((name) => { let item = shape[name] as z.ZodAny; item = handleIfZodNumber(item) as z.ZodAny; const zodBaseType = getBaseType(item); const itemName = item._def.description ?? beautifyObjectName(name); const key = [...path, name].join("."); const { isHidden, isDisabled, isRequired: isRequiredByDependency, overrideOptions, } = resolveDependencies(dependencies, name, watch); if (isHidden) { return null; } if (zodBaseType === "ZodObject") { return ( {itemName} } form={form} fieldConfig={ (fieldConfig?.[name] ?? {}) as FieldConfig< z.infer > } path={[...path, name]} /> ); } if (zodBaseType === "ZodArray") { return ( } form={form} fieldConfig={fieldConfig?.[name] ?? {}} path={[...path, name]} /> ); } const fieldConfigItem: FieldConfigItem = fieldConfig?.[name] ?? {}; const zodInputProps = zodToHtmlInputProps(item); const isRequired = isRequiredByDependency || zodInputProps.required || fieldConfigItem.inputProps?.required || false; if (overrideOptions) { item = z.enum(overrideOptions) as unknown as z.ZodAny; } return ( { const inputType = fieldConfigItem.fieldType ?? DEFAULT_ZOD_HANDLERS[zodBaseType] ?? "fallback"; const InputComponent = typeof inputType === "function" ? inputType : INPUT_COMPONENTS[inputType]; const ParentElement = fieldConfigItem.renderParent ?? DefaultParent; const defaultValue = fieldConfigItem.inputProps?.defaultValue; const value = field.value ?? defaultValue ?? ""; const fieldProps = { ...zodToHtmlInputProps(item), ...field, ...fieldConfigItem.inputProps, disabled: fieldConfigItem.inputProps?.disabled || isDisabled, ref: undefined, value: value, }; if (InputComponent === undefined) { return <>; } return ( ); }} /> ); })} ); }