@flatbiz/antd
Version:
402 lines (399 loc) • 12.8 kB
TypeScript
import { TAny, TPlainObject } from '@flatbiz/utils';
import { FormItemProps, FormListFieldData, FormListOperation, FormProps } from 'antd';
import { FormListProps } from 'antd/es/form/FormList.js';
import { CSSProperties, ReactElement, ReactNode } from 'react';
declare const PresetDefaultGrid: {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
xxl: number;
};
export type TBoxBreakpoint = "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
export type Gutter = number | undefined | Partial<Record<TBoxBreakpoint, number>>;
export type GutterParams = Gutter | [
Gutter,
Gutter
];
export interface BoxRowProps {
/**
* 在不同响应尺寸下的元素占位格数
* 应用到所有Col子元素上
*/
defaultGrid?: Partial<typeof PresetDefaultGrid>;
/** 间距 */
gutter?: GutterParams;
/** flex 布局的垂直对齐方式 */
align?: "top" | "middle" | "bottom" | "stretch";
/** flex 布局的水平排列方式 */
justify?: "start" | "end" | "center" | "space-around" | "space-between" | "space-evenly";
/** 尺寸变化回调 */
onBoxBreakpointChange?: (breakpoint: TBoxBreakpoint) => void;
}
export type TFormLayoutPreClassNameProps = {
/**
* label宽度,Form内部所有FormItem label都生效
* ```
* 1. 可设置数值
* 2. 可设置`auto`自适应
* ```
*/
labelWidth?: "auto" | "70" | "80" | "90" | "100" | "110" | "120" | "130" | "140" | "150" | "160" | "170" | "180" | "190" | "200";
/** labelItem 竖直布局 */
labelItemVertical?: boolean;
/** label 对齐方式 */
labelAlign?: "left" | "right";
/** formItem之间竖直间距,默认值:24 */
formItemGap?: "24" | "15" | "8" | "5" | "0";
/**
* className 中可能会包含 preDefinedClassName.form.xx,优先级大于 labelWidth、labelItemVertical、labelAlign、formItemGap
*/
className?: string;
};
export type TFormItemLayoutPreClassNameProps = {
/**
* label宽度,Form内部所有FormItem label都生效
* ```
* 1. 可设置数值
* 2. 可设置`auto`自适应
* ```
*/
labelWidth?: "auto" | "70" | "80" | "90" | "100" | "110" | "120" | "130" | "140" | "150" | "160" | "170" | "180" | "190" | "200";
/** labelItem 竖直布局 */
labelItemVertical?: boolean;
/** label 对齐方式 */
labelAlign?: "left" | "right";
/**
* className 中可能会包含 preDefinedClassName.formItem.xx,优先级大于 labelWidth、labelItemVertical、labelAlign
*/
className?: string;
};
export type FormWrapperProps<Values = any> = TFormLayoutPreClassNameProps & FormProps<Values> & {
children: ReactNode;
};
export type EasyFormProps = Omit<FormWrapperProps, "children"> & {
/**
* 定义一行显示几列(当外层宽度尺寸大于 992px(lg) 时,一行显示几列), 默认值:3
* ```
* 1. 当外层宽度尺寸小于992px(lg),为xs、sm、md情况下不受column值影响(column=1除外)
* 2. 宽度尺寸定义
* xs: 宽度 < 576px
* sm: 宽度 ≥ 576px
* md: 宽度 ≥ 768px
* lg: 宽度 ≥ 992px
* xl: 宽度 ≥ 1200px
* xxl: 宽度 ≥ 1600px
* 3. 列数尺寸定义
* {
* 1: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
* 2: { xs: 24, sm: 12, md: 12, lg: 12, xl: 12, xxl: 12 },
* 3: { xs: 24, sm: 12, md: 12, lg: 8, xl: 8, xxl: 8 },
* 4: { xs: 24, sm: 12, md: 12, lg: 6, xl: 6, xxl: 6 },
* };
* ```
*/
column?: 1 | 2 | 3 | 4;
/**
* 强制定义一行显示几列,不考虑响应式
* ```
* 1. 优先级大于column
* 2. 建议优先使用column配置
* ```
*/
forceColumn?: 1 | 2 | 3 | 4;
/**
* Form显示宽度,可数值、可百分比;在小屏幕尺寸(xs、sm)上无效
*/
width?: number | string;
/** 网格间距 */
gridGutter?: BoxRowProps["gutter"];
children: ReactNode;
/**
* 是否为纯净模式,对EasyForm的子节点不做任何包装处理
*/
isPure?: boolean;
/**
* true: 当前EasyForm组件不使用Antd Form包裹,可在Form、EasyForm、FormWrapper内部使用
*/
nonuseFormWrapper?: boolean;
/**
* 栅格占位格数,最大值:24
* ```
* 1. 当前EasyForm处在 EasyForm 直接子节点中有效,即当前EasyForm在EasyForm栅格中的占位格数;
* 2. 父节点使用属性值,当前节点不使用属性值
* ```
*/
span?: number;
};
export type FormItemWrapperProps = Omit<FormItemProps, "hidden" | "children" | "noStyle"> & TFormItemLayoutPreClassNameProps & {
wrapper?: (children: ReactNode) => ReactElement;
/** 设置wrapper后,before、after失效 */
before?: ReactNode;
/** 设置wrapper后,before、after失效 */
after?: ReactNode;
/** 设置 before、after 属性的包装结构style */
beforeAfterStyle?: CSSProperties;
/** value 序列化处理 */
inputNormalize?: (value?: TAny) => TAny;
/**
* onChange 参数序列化处理
* 如果设置 normalize 属性,outputNormalize将失效
*/
outputNormalize?: (value?: TAny) => TAny;
/**
* 隐藏 Form.Item,同时清除 Form.Item 值
* ```
* 1.与 dependencies 属性配合使用,可实现当前FormItemWrapper的显示隐藏
* 2.提交不校验rules
* ```
*/
isClear?: boolean | ((formValues: TPlainObject) => boolean);
/**
* 隐藏 Form.Item,不会清除 Form.Item 值
* ```
* 1.与 dependencies 属性配合使用,可实现当前FormItemWrapper的显示隐藏
* 2.提交会校验rules
* ```
*/
hidden?: boolean | ((formValues: TPlainObject) => boolean);
/**
* 栅格占位格数,最大值:24
* ```
* 1. 当前FormItemWrapper处在 EasyForm 直接子节点中有效,即FormItemWrapper在EasyForm栅格中的占位格数;
* 2. 父节点使用属性值,当前节点不使用属性值
* ```
*/
span?: number;
/** 不支持函数式写法,如果需要使用dependencies获取表单值,可使用FormItemWrapperDependencies 组件 */
children?: ReactNode;
/**
* ```
* 1. 设置noStyle后,可能会导致 FromItemWrapper 在 EasyFrom 内部渲染网格布局时出现异常
* 2. 在FormItemWrapper中使用 dependencies 逻辑不需要设置 noStyle
* ```
*/
noStyle?: boolean;
};
export type EditableCardDataIndex = string | string[];
export interface EditableCardOperation {
index: number;
add: (defaultValue: TPlainObject, insertIndex?: number) => void;
remove: (index: number) => void;
/** 同一级内移动 */
move: (fromIndex: number, toIndex: number) => void;
/** 是否可编辑 */
editable: boolean;
/**
* 设置当前卡片指定字段值
*/
setCurrentRowField: (dataIndexConfigs: {
name: EditableCardDataIndex;
value?: TAny;
}[]) => void;
/** 获取当前卡片表单数据 */
getCurrentRowData: () => TPlainObject;
/**
* 当前卡片表单 name
* ```
* 值为 field.name
* ```
*/
rowFormItemName: string | number;
/**
* 当前卡片表单完整 name
* ```
* 例如:['dataList', 0]
* ```
*/
rowFormItemCompleteName: Array<string | number>;
/** 当前卡片表单验证,需要自行指定nameList(dataIndex数组) */
validateRowFields: (nameList: EditableCardDataIndex[]) => Promise<void>;
forceUpdate: () => void;
}
/** 卡片内字段配置 */
export type EditableCardColumnItem = {
/**
* 字段key值
* ```
* 例如:
* dataIndex: 'abc'
* dataIndex: ['abc', 'xyz']
* ```
*/
dataIndex: EditableCardDataIndex;
/** 是否可编辑 */
editable: boolean | ((operation: Pick<EditableCardOperation, "index" | "getCurrentRowData">, index: number) => boolean);
/**
* 布局占用网格数目(最大数值24)
* ```
* 1. 一行总共等分24份
* ```
*/
gridNumber?: number;
/** 标题 */
title?: ReactElement | string;
/**
* Form.Item props
*/
formItemProps?: Omit<FormItemWrapperProps, "children" | "name"> | ((operation: EditableCardOperation) => Omit<FormItemWrapperProps, "children" | "name">);
/**
* 通过 operation.editable 来判断渲染结构,其中render返回的根节点会作为 Form.Item 的children
* ```
* 例如
* render: (operation) => {
* if (operation.editable) {
* return <Input placeholder="请输入" />;
* }
* return <Tag>{value}</Tag>;
* }
*
* 如果需要额外布局,可通过 formItemProps.wrapper 实现
* formItemProps: (operation) => {
* return {
* wrapper: (children) => {
* return (
* <FlexLayout fullIndex={[0]} direction="horizontal" gap={10}>
* <div>{children}</div>
* <div>额外布局</div>
* </FlexLayout>
* );
* },
* };
* },
* render: (operation) => {
* if (operation.editable) {
* return <Input placeholder="请输入" />;
* }
* return <Tag>{value}</Tag>;
* }
* ```
*/
render?: (operation: EditableCardOperation) => ReactElement;
/**
* 会在 title 之后展示一个 icon
*/
tips?: string;
/** 为表格header中的字段添加必填标识,如果未配置 formItemProps.rules,内部会新增一条required rule */
required?: boolean;
/**
* 隐藏域设置
* ```
* 如果是动态隐藏,并且在逻辑切换后无效果,可尝试执行 operation.forceUpdate()
* ```
*/
hidden?: (operation: EditableCardOperation, index: number) => boolean;
/** 移除设置,优先级高于 hidden */
remove?: (operation: EditableCardOperation, index: number) => boolean;
formItemContainer?: (formItem: ReactElement) => ReactElement | null;
};
export type EditableCardProps = {
className?: string;
style?: CSSProperties;
/** 卡片内字段配置 */
columns: EditableCardColumnItem[];
/**
* 当前Edittable处在formList内部时(必填),完整formItem的name
* ```
* 例如 处在formList内部
* 1. formListName=[0,dataList]
* 2. formListCompleteName=[xxxList, 0, dataList]
* ```
*/
formListCompleteName?: Array<string | number>;
/** Form.List name */
formListName: Array<string | number> | string;
/** 初始化值 */
initialValue?: TPlainObject[];
/**
* Form.List rules
* ```
rules={[
{
validator: async (_, names) => {
if (!names || names.length < 2) {
return Promise.reject(new Error('At least 2 passengers'));
}
},
},
]}
* ```
*/
rules?: FormListProps["rules"];
/**`默认新增按钮`新增行默认值,hiddenFooterBtn != true 有效 */
addRowDefaultValues?: () => TPlainObject;
/** 自定义新增按钮名称 */
addRowBtnName?: ReactNode;
/** 隐藏底部`新增`按钮 */
hiddenFooterBtn?: boolean;
/** 隐藏默认删除按钮 */
hiddenDeleteBtn?: boolean;
/** 顶部区域渲染 */
contentBeforeRender?: (formListOperation: FormListOperation, nextRowIndex: number) => ReactElement | null;
/** 底部区域渲染 */
contentAfterRender?: (formListOperation: FormListOperation, nextRowIndex: number) => ReactElement | null;
/** 设置默认卡片名称,设置 onCustomWrapper 后失效 */
onCustomGroupName?: (index: number) => string | ReactElement;
/** 自定义卡片包裹,同时可自定义删除按钮、新增按钮 */
onCustomWrapper?: (children: ReactElement, extraData: {
operation: FormListOperation;
fields: FormListFieldData[];
fieldItem: FormListFieldData;
index: number;
required?: boolean;
key: string;
}) => ReactElement;
/** 设置必填,但只有一条数据时,隐藏默认删除按钮 */
required?: boolean;
/** 默认卡片样式 */
cardClassName?: string;
/** 默认卡片样式 */
cardStyle?: CSSProperties;
/**
* 每个卡片内容都使用了 EasyForm 包裹,此处可设置 EasyFormProps
* ```
* 可使用 EasyForm 中 FormItem布局
* ```
*/
cardEasyFormProps?: Omit<EasyFormProps, "nonuseFormWrapper" | "isPure" | "children">;
/**
* 默认卡片右侧布局,设置 onCustomWrapper 后失效
* ```
* 1. 通过before 、after自定义删除按钮左右布局
* cardExtraRender={(extraData)=>{
* return {
* before: [<div>1</div>, <div>2</div>],
* after: [<div>3</div>, <div>4</div>],
* }
* }}
* 2. 返回ReactElement,可自定义右侧布局
* cardExtraRender={(extraData)=>{
* return <div>111</div>
* }}
* ```
*/
cardExtraRender?: (extraData: {
operation: FormListOperation;
fields: FormListFieldData[];
fieldItem: FormListFieldData;
index: number;
required?: boolean;
key: string;
}) => {
before?: ReactElement[];
after?: ReactElement[];
} | ReactElement;
};
/**
* 使用FormList实现可编辑卡片
* ```
* 1. 必须在外部包裹Form组件或者EasyForm组件
* 2. 行内需要联动逻辑可使用 column.render.operation.setCurrentRowField 方法
* 3. 可使用DragEditableCard组件实现拖拽排序
*
* demo
* https://fex.qa.tcshuke.com/docs/admin/main/form/grid
* ```
*/
export declare const EditableCard: (props: EditableCardProps) => import("react").JSX.Element;
export {};