UNPKG

@flatbiz/antd

Version:
431 lines (428 loc) 13.4 kB
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; }; export type DragEditableCardProps = Omit<EditableCardProps, "onCustomWrapper"> & { /** * 拖拽图标自定义,默认使用 DragOutlined 图标 */ dragIcon?: ReactElement; /** 禁用拖拽 */ disabledDrag?: boolean; /** * 表格数据唯一值字段Key * ``` * ``` */ uidFieldKey: string; /** * 拖拽结束事件 * ``` * dataSource: 拖拽完成后的数据源 * dragData * 1. activeId 拖拽ID * 2. activeIndex 拖拽起始表格数组索引值 * 3. overIndex 拖拽结束表格数组索引值 * ``` */ onDragChange?: (dataSource: TPlainObject[], dragData: { activeId: string | number; overId?: string | number; activeIndex: number; overIndex: number; }) => void; /** * 拖拽触发位置,默认在左侧 */ dragTriggerPosition?: "left" | "right"; }; /** * 可拖拽编辑卡片 * ``` * 1. 卡片数组必须有唯一值字段,通过参数 uidFieldKey 告诉组件 * ``` */ export declare const DragEditableCard: (props: DragEditableCardProps) => import("react").JSX.Element; export {};