import type { Api, GridSizeUnit, GridSizeUnitStr, RendererConfig, RendererProps, Schema, SchemaBoolean, SchemaClassName, SchemaExpression, TestFunc } from 'jamis-core'; import type { BaseSchemaWithoutType, FormHorizontal, FormOptionsControl, FormSchemaBase, IFormItemStore, IFormStore, SchemaRemark } from '../types'; export interface FormBaseControl extends BaseSchemaWithoutType { /** * 表单项大小 */ size?: SizeUnit; sizeExpr?: SchemaExpression; /** * 描述标题 */ label?: string | false | Schema; /** * 描述标题 */ labelAlign?: LabelAlign; /** * label自定义宽度,默认单位为px */ labelWidth?: number | string; /** * 配置 label className * @deprecated 使用`slots.className`替代 */ labelClassName?: string; /** * 字段名,表单提交时的 key,支持多层级,用.连接,如: a.b.c */ name?: string; /** * 显示一个小图标, 鼠标放上去的时候显示提示内容 */ remark?: unknown; /** * 显示一个小图标, 鼠标放上去的时候显示提示内容, 这个小图标跟 label 在一起 */ labelRemark?: unknown; /** * 输入提示,聚焦的时候显示 */ hint?: string; /** * 当修改完的时候是否提交表单。 */ submitOnChange?: boolean; /** * 是否只读 */ readOnly?: boolean; /** * 只读条件 */ readOnlyOn?: string; /** * 不设置时,当表单提交过后表单项每次修改都会触发重新验证, * 如果设置了,则由此配置项来决定要不要每次修改都触发验证。 */ validateOnChange?: boolean; /** * 是否要开启校验, 默认会开启 * 这只是一个开关, 实际上要有设置校验规则时才真正做校验 */ validatable?: boolean; /** * 是否要开启校验表达式 */ validatableOn?: SchemaExpression; /** * 描述内容,支持 Html 片段。 */ description?: string; /** * @deprecated 用 description 代替 */ desc?: string; /** * 配置描述上的 className * @deprecated 使用`slots.className`替代 */ descriptionClassName?: SchemaClassName; /** * 配置当前表单项展示模式 */ mode?: 'normal' | 'inline' | 'horizontal'; modeExpr?: SchemaExpression; /** * 当配置为水平布局的时候,用来配置具体的左右分配。 */ horizontal?: FormHorizontal; /** * 表单 control 是否为 inline 模式。 */ inline?: boolean; /** * control元素的 className * @deprecated 使用`slots.className`替代 */ inputClassName?: SchemaClassName; /** * control元素的 style */ inputStyle?: React.CSSProperties; /** * control下子元素的样式类 * @deprecated 使用`slots.className`替代 */ controlBodyClassName?: SchemaClassName; /** * 占位符 */ placeholder?: string; placeholderExpr?: SchemaExpression; /** * 是否为必填 */ required?: boolean; /** * 动态判断是否为必填 */ requiredOn?: SchemaExpression; /** * 必填星号的样式类 * @deprecated 使用`slots.className`替代 */ requiredClassName?: SchemaClassName; changeImmediately?: boolean; /** * 验证失败的提示信息 */ validationErrors?: { [k in keyof FormValidation]: string; }; validations?: string | FormValidation; /** * 默认值,切记只能是静态值,不支持取变量,跟数据关联是通过设置 name 属性来实现的。 */ value?: any; /** * 默认值,支持表达式的语法 */ valueExpr?: SchemaExpression; /** * 表单项隐藏时,是否在当前 Form 中删除掉该表单项值。注意同名的未隐藏的表单项值也会删掉 */ clearValueOnHidden?: boolean; /** * 远端校验表单项接口 */ validateApi?: Api; /** 是否可清除 */ clearable?: boolean; /** 设置列占据的行宽, 1-12 */ columnRatio?: GridSizeUnit; columnRatioExpr?: GridSizeUnit | SchemaExpression | Record; /** * 是否静态展示 */ static?: boolean; /** * 是否静态展示表达式 */ staticOn?: SchemaExpression; /** * 静态展示空值占位 */ staticPlaceholder?: string; /** 兼容老用法,新用法直接在 Component 里面定义 validate 方法即可。 */ validate?: (values: any, value: any) => string | boolean; /** * 表单项值读取时的转换函数或者表达式字符串, 用于getValue */ pipeIn?: ((value: any, data: Record) => any) | SchemaExpression; /** * 每次值改变而写入时转换函数或者表达式字符串, 用于handleChange */ pipeOut?: ((value: any, originValue: any, data: Record) => any) | SchemaExpression; } export interface FormBaseControlSchema extends FormBaseControl { /** * 显示一个小图标, 鼠标放上去的时候显示提示内容 */ remark?: SchemaRemark; /** * 显示一个小图标, 鼠标放上去的时候显示提示内容, 这个小图标跟 label 在一起 */ labelRemark?: SchemaRemark; /** * 是否显示清除按钮 */ clearable?: boolean; } export interface FormOptionsSchema extends FormBaseControlSchema, Omit { } export interface FormItemBasicConfig extends Partial { type?: string; wrap?: boolean; renderLabel?: boolean; renderDescription?: boolean; test?: RegExp | TestFunc; storeType?: string; validations?: string; /** * 是否使用严格模式, 默认是true, 如果设置为false, 则任何属性变化都执行re-render */ strictMode?: boolean; /** * schema变化使视图更新的属性白名单 */ detectProps?: Array; descriptionClassName?: string; storeExtendsData?: boolean; sizeMutable?: boolean; weight?: number; extendsData?: boolean; showErrorMsg?: boolean; shouldComponentUpdate?: (props: any, prevProps: any) => boolean; validate?: (values: any, value: any) => string | boolean; } export interface FormItemProps extends RendererProps { name?: string; formStore?: IFormStore; formItem?: IFormItemStore; formInited: boolean; formMode: 'normal' | 'horizontal' | 'inline' | 'row' | 'default'; formHorizontal: FormHorizontal; horizontal?: FormHorizontal; formLabelAlign: LabelAlign; formLabelWidth?: number | string; defaultSize?: SizeUnit; size?: SizeUnit; labelAlign?: LabelAlign; labelWidth?: number | string; /** @deprecated 使用`classMap.Form-label`替代 */ labelClassName?: string; disabled?: boolean; btnDisabled: boolean; defaultValue: any; value?: any; prinstine: any; formItemValue: any; /** @deprecated 使用`slots.className`替代 */ inputClassName?: SchemaClassName; inputStyle?: React.CSSProperties; inputOnly?: boolean; renderLabel?: boolean; renderDescription?: boolean; sizeMutable?: boolean; wrap?: boolean; hint?: string; description?: string; /** @deprecated 使用`slots.className`替代 */ descriptionClassName?: SchemaClassName; errors?: { [propName: string]: string; }; error?: string; showErrorMsg?: boolean; /** @deprecated 使用`slots.className`替代 */ requiredClassName?: SchemaClassName; /** @deprecated 使用`slots.className`替代 */ valueClassName?: SchemaClassName; static?: boolean; setPrinstineValue: (value: any) => void; onChange: (value: any, submitOnChange?: boolean, changeImmediately?: boolean) => void; formItemDispatchEvent?: (type: string, data: any) => void; onBulkChange?: (values: { [propName: string]: any; }, submitOnChange?: boolean) => void; /** * 打开formitem 中的弹窗 */ onOpenDialog: (schema: Schema, data: any) => Promise; addHook: (fn: Function, mode: 'validate' | 'init' | 'flush') => () => void; removeHook: (fn: Function, mode?: 'validate' | 'init' | 'flush') => void; renderFormItems: (schema: Partial, region: string, props: any) => JSX.Element; onFocus: (e: any) => void; onBlur: (e: any) => void; getValue: () => any; setValue: (value: any, key: string) => void; renderControl?: (props: FormControlProps) => JSX.Element; } export type FormControlProps = RendererProps & { onOpenDialog: (schema: Schema, data: any) => Promise; } & Exclude; export type FormItemComponent = React.ComponentType; export type FormControlComponent = React.ComponentType; export interface FormItemConfig extends FormItemBasicConfig { component: FormControlComponent; } export interface FormItemStoreProp { required?: boolean; readOnly?: boolean; disabled?: boolean; unique?: boolean; value?: any; rules?: string | { [propName: string]: any; }; messages?: { [propName: string]: string; } | string | {}; multiple?: boolean; delimiter?: string; valueField?: string; labelField?: string; joinValues?: boolean; extractValue?: boolean; type?: string; id?: string; selectFirst?: boolean; autoFill?: any; clearValueOnHidden?: boolean; validateApi?: boolean | string; minLength?: number; maxLength?: number; validateOnChange?: boolean; label?: string; resetValue: string; isValueSchemaExp?: boolean; inputGroupControl?: { name: string; path: string; [propsName: string]: any; }; [key: string]: any; } export interface FormValidation { /** * 是否是字母 */ isAlpha?: boolean; /** * 是否为字母数字 */ isAlphanumeric?: boolean; /** * 是否为邮箱地址 */ isEmail?: boolean; /** * 是否为浮点型 */ isFloat?: boolean; /** * 是否为整型 */ isInt?: boolean; /** * 是否为 json */ isJson?: boolean; /** * 长度等于指定值 */ isLength?: number; /** * 是否为数字 */ isNumeric?: boolean; /** * 是否为必填 */ isRequired?: boolean; /** * 是否为 URL 地址 */ isUrl?: boolean | { schemes?: ('http' | 'https' | 'ftp' | 'sftp' | 'file')[]; allowLocal?: boolean; allowDataUrl?: boolean; }; /** * 内容命中指定正则 */ matchRegexp?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp1?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp2?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp3?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp4?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp5?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp6?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp7?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp8?: string | RegExp; /** * 内容命中指定正则 */ matchRegexp9?: string | RegExp; /** * 最大长度为指定值 */ maxLength?: number | string; /** * 最大值为指定值 */ maximum?: number | string; /** * 最小长度为指定值 */ minLength?: number | string; /** * 最小值为指定值 */ minimum?: number | string; /** * 和目标日期相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isDateTimeSame?: string | string[]; /** * 早于目标日期,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isDateTimeBefore?: string | string[]; /** * 晚于目标日期,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isDateTimeAfter?: string | string[]; /** * 早于目标日期或和目标日期相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isDateTimeSameOrBefore?: string | string[]; /** * 晚于目标日期或和目标日期相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isDateTimeSameOrAfter?: string | string[]; /** * 日期处于目标日期范围,支持指定粒度和区间的开闭形式,默认到毫秒, 左右开区间 * @version 2.2.0 */ isDateTimeBetween?: string | string[]; /** * 和目标时间相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isTimeSame?: string | string[]; /** * 早于目标时间,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isTimeBefore?: string | string[]; /** * 晚于目标时间,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isTimeAfter?: string | string[]; /** * 早于目标时间或和目标时间相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isTimeSameOrBefore?: string | string[]; /** * 晚于目标时间或和目标时间相同,支持指定粒度,默认到毫秒 * @version 2.2.0 */ isTimeSameOrAfter?: string | string[]; /** * 时间处于目标时间范围,支持指定粒度和区间的开闭形式,默认到毫秒, 左右开区间 * @version 2.2.0 */ isTimeBetween?: string | string[]; [propName: string]: any; } export type LabelAlign = 'right' | 'left'; export type SizeUnit = 'xs' | 'sm' | 'normal' | 'md' | 'lg' | 'xl' | 'full'; export interface IOption { value?: string | number | null; label?: string | null; children?: IOption[] | null; disabled?: boolean | null; visible?: boolean | null; hidden?: boolean | null; }