jamis
Version:
一种支持通过JSON配置方式生成页面的组件库
500 lines (499 loc) • 14.5 kB
TypeScript
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<GridSizeUnitStr, boolean | SchemaBoolean>;
/**
* 是否静态展示
*/
static?: boolean;
/**
* 是否静态展示表达式
*/
staticOn?: SchemaExpression;
/**
* 静态展示空值占位
*/
staticPlaceholder?: string;
/** 兼容老用法,新用法直接在 Component 里面定义 validate 方法即可。 */
validate?: (values: any, value: any) => string | boolean;
/**
* 表单项值读取时的转换函数或者表达式字符串, 用于getValue
*/
pipeIn?: ((value: any, data: Record<string, any>) => any) | SchemaExpression;
/**
* 每次值改变而写入时转换函数或者表达式字符串, 用于handleChange
*/
pipeOut?: ((value: any, originValue: any, data: Record<string, any>) => any) | SchemaExpression;
}
export interface FormBaseControlSchema extends FormBaseControl {
/**
* 显示一个小图标, 鼠标放上去的时候显示提示内容
*/
remark?: SchemaRemark;
/**
* 显示一个小图标, 鼠标放上去的时候显示提示内容, 这个小图标跟 label 在一起
*/
labelRemark?: SchemaRemark;
/**
* 是否显示清除按钮
*/
clearable?: boolean;
}
export interface FormOptionsSchema extends FormBaseControlSchema, Omit<FormOptionsControl, 'remark' | 'labelRemark'> {
}
export interface FormItemBasicConfig extends Partial<RendererConfig> {
type?: string;
wrap?: boolean;
renderLabel?: boolean;
renderDescription?: boolean;
test?: RegExp | TestFunc;
storeType?: string;
validations?: string;
/**
* 是否使用严格模式, 默认是true, 如果设置为false, 则任何属性变化都执行re-render
*/
strictMode?: boolean;
/**
* schema变化使视图更新的属性白名单
*/
detectProps?: Array<string>;
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<any>;
addHook: (fn: Function, mode: 'validate' | 'init' | 'flush') => () => void;
removeHook: (fn: Function, mode?: 'validate' | 'init' | 'flush') => void;
renderFormItems: (schema: Partial<FormSchemaBase>, 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<any>;
} & Exclude<FormItemProps, 'inputClassName' | 'renderControl' | 'defaultSize' | 'size' | 'error' | 'errors' | 'hint' | 'descriptionClassName' | 'inputOnly' | 'renderLabel' | 'renderDescription' | 'sizeMutable' | 'wrap'>;
export type FormItemComponent = React.ComponentType<FormItemProps>;
export type FormControlComponent = React.ComponentType<FormControlProps>;
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;
}