import React from 'react'; import { FieldValues } from 'react-hook-form'; import FormItem, { FormItemProps } from './Item'; import { separatePropsByDestruct } from './propsSeparator'; // 类型工具:获取组件的 ref 类型 type ComponentRef> = React.ElementRef; // 类型工具:获取组件的 props 类型,避免与React.ComponentProps冲突 type InferComponentProps> = React.ComponentProps; // 需要从组件props中排除的属性(避免冲突) export type ExcludedProps = 'style' | 'error' | 'errorMessage'; // 表单项基础props(排除children) export type BaseFormItemProps = Omit, 'children'>; // 通用的表单组件props组合类型 export type FormComponentProps< TFieldValues extends FieldValues, TComponentProps > = BaseFormItemProps & Omit; /** * 高阶组件:将任意组件包装为表单组件 * 自动处理FormItem的逻辑,简化表单组件的创建 * * @template TComponent - 被包装的组件类型 * @template TFieldValues - 表单数据类型 * @param Component - 要包装的组件 * @param displayName - 组件显示名称 * @returns 包装后的表单组件 */ export function withFormItem< // eslint-disable-next-line @typescript-eslint/no-explicit-any TComponent extends React.ComponentType, TFieldValues extends FieldValues = FieldValues >( Component: TComponent, displayName: string, componentDefaultProps?: Partial>, formItemDefaultProps?: Partial> ) { type InnerComponentProps = InferComponentProps; // 需要从组件props中排除的属性(避免冲突) type ExcludedProps = | 'style' // style由FormItem控制,避免冲突 | 'error' // error由FormItem控制 | 'errorMessage'; // errorMessage由FormItem控制 type FormWrappedProps = Omit, 'children'> & Omit & { // 冲突属性 selectConfirmButtonText?: string; checkboxLabel?: string; }; const FormWrappedComponent = React.forwardRef< ComponentRef, FormWrappedProps >((props, ref) => { // 使用工具函数分离FormItem属性和组件属性 const { formItemProps, componentProps } = separatePropsByDestruct( props, componentDefaultProps, formItemDefaultProps ); return ( {React.createElement(Component, { ...componentProps, ...(ref ? { ref } : {}), })} ); }); FormWrappedComponent.displayName = displayName; return FormWrappedComponent; } /** * 便捷函数:创建表单组件 * 为常用组件提供更简洁的创建方式 * * @template TComponent - 被包装的组件类型 * @template TFieldValues - 表单数据类型 * @param Component - 要包装的组件 * @param displayName - 组件显示名称 * @returns 包装后的表单组件 */ export function createFormComponent< TComponent extends React.ComponentType, TFieldValues extends FieldValues = FieldValues >(Component: TComponent, displayName: string) { return withFormItem(Component, displayName); } /** * 批量创建表单组件的工具函数 * * @template T - 组件映射类型 * @param components - 组件映射对象 * @returns 包装后的表单组件映射对象 */ export function createFormComponents< // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends Record> >( components: T ): { [K in keyof T]: ReturnType>; } { const result = {} as { [K in keyof T]: ReturnType>; }; for (const [key, Component] of Object.entries(components)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (result as any)[key] = withFormItem(Component, `Form${key}`); } return result; } export default withFormItem;