diff --git a/packages/antd/src/components/layout.tsx b/packages/antd/src/components/layout.tsx index 3a22ef2f55f..0996df4cc06 100644 --- a/packages/antd/src/components/layout.tsx +++ b/packages/antd/src/components/layout.tsx @@ -27,9 +27,7 @@ const normalizeCol = ( } } -export const FormLayoutItem: React.FC> = function( - props -) { +export const FormLayoutItem: React.FC = function(props) { return React.createElement( FormLayoutConsumer, {}, @@ -119,9 +117,13 @@ export const FormItemGrid = createVirtualBox( const { children: rawChildren, cols: rawCols, + // eslint-disable-next-line @typescript-eslint/no-unused-vars title, + // eslint-disable-next-line @typescript-eslint/no-unused-vars description, + // eslint-disable-next-line @typescript-eslint/no-unused-vars help, + // eslint-disable-next-line @typescript-eslint/no-unused-vars extra, ...props } = this.props diff --git a/packages/antd/src/fields/array.tsx b/packages/antd/src/fields/array.tsx index 66a9a96b388..52feca6fd41 100644 --- a/packages/antd/src/fields/array.tsx +++ b/packages/antd/src/fields/array.tsx @@ -8,8 +8,8 @@ export const CircleButton = styled['div'].attrs({ className: 'cricle-btn' })` margin-right:10px; border-radius: ${props => (!props.hasText ? '100px' : 'none')}; border: ${props => (!props.hasText ? '1px solid #eee' : 'none')}; - margin-bottom:20px; - cursor:pointer; + margin-bottom: 20px; + cursor: pointer; display: flex; align-items: center; justify-content: center; @@ -19,10 +19,9 @@ export const CircleButton = styled['div'].attrs({ className: 'cricle-btn' })` background:#f7f4f4; }` : ''} - .op-name{ - margin-left:3px; + .op-name { + margin-left: 3px; } -} ` export const TextButton = styled['div'].attrs({ diff --git a/packages/antd/src/fields/password.tsx b/packages/antd/src/fields/password.tsx index c8191d56bd4..926ae0e1ffe 100644 --- a/packages/antd/src/fields/password.tsx +++ b/packages/antd/src/fields/password.tsx @@ -158,24 +158,22 @@ interface IStrengthProps { } // 校验强度 UI -const StrengthFC = styled( - ({ strength, className }: IStrengthProps) => ( -
-
-
-
-
-
-
-
+const StrengthFC = styled(({ strength, className }: IStrengthProps) => ( +
+
+
+
+
+
+
- ) -)` +
+))` .password-strength-wrapper { background: #e0e0e0; margin-bottom: 3px; @@ -248,6 +246,6 @@ const PasswordFC = (props: Partial) => { registerFormField( 'password', connect({ - getProps: mapStyledProps, + getProps: mapStyledProps })(PasswordFC) ) diff --git a/packages/antd/src/fields/upload.tsx b/packages/antd/src/fields/upload.tsx index 1f072252d4e..d3ec524d0b7 100644 --- a/packages/antd/src/fields/upload.tsx +++ b/packages/antd/src/fields/upload.tsx @@ -184,7 +184,7 @@ registerFormField( this.props.onChange(fileList) } - public onChangeHandler = ({ fileList, file }) => { + public onChangeHandler = ({ fileList }) => { const { onChange } = this.props fileList = toArr(fileList) if ( @@ -235,6 +235,7 @@ registerFormField( } public render() { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { listType, locale, onChange, value, ...others } = this.props if (listType.indexOf('card') > -1) { diff --git a/packages/antd/src/index.tsx b/packages/antd/src/index.tsx index bb2d19ecc88..8534b7ef68b 100644 --- a/packages/antd/src/index.tsx +++ b/packages/antd/src/index.tsx @@ -20,15 +20,25 @@ export * from '@uform/react' export * from './components/formButtonGroup' export * from './components/button' export * from './components/layout' +import React from 'react' +import { + SchemaForm as InternalSchemaForm, + Field as InternalField +} from '@uform/react' +import { SchemaFormProps, FieldProps } from './type' -import { SchemaForm as ReactSchemaForm } from '@uform/react' -import { mapStyledProps, mapTextComponent } from './utils' -import { ISchemaFormProps, ISchemaFormExpandProps } from './type' +export { mapStyledProps, mapTextComponent } from './utils' -export { mapStyledProps, mapTextComponent } +export default class SchemaForm extends React.Component> { + render() { + return + } +} -export const SchemaForm: React.ComponentClass< - ISchemaFormProps & ISchemaFormExpandProps -> = ReactSchemaForm - -export default SchemaForm +export class Field extends React.Component< + FieldProps +> { + render() { + return + } +} diff --git a/packages/antd/src/type.tsx b/packages/antd/src/type.tsx index a1a2c80dcde..65c8d2677f6 100644 --- a/packages/antd/src/type.tsx +++ b/packages/antd/src/type.tsx @@ -1,13 +1,37 @@ import { ColProps } from 'antd/es/col' import { CardProps } from 'antd/es/card' import { BaseButtonProps } from 'antd/es/button/button' -import { IFormActions, ISchema, IEffects, IFieldError } from '@uform/types' - -export type TTextAlign = 'left' | 'right' -export type TSize = 'small' | 'medium' | 'large' -export type TLayout = 'horizontal' | 'vertical' | 'inline' -export type TTextEl = string | JSX.Element | null -export type TLabelAlign = 'left' | 'top' | 'inset' +import { + IFormActions, + ISchema, + IEffects, + IFieldError, + TextAlign, + Size, + Layout, + TextEl, + LabelAlign, + IAsyncFormActions +} from '@uform/types' +import { SwitchProps } from 'antd/lib/switch' +import { CheckboxGroupProps } from 'antd/lib/checkbox' +import { + DatePickerProps, + RangePickerProps, + MonthPickerProps, + WeekPickerProps +} from 'antd/lib/date-picker/interface' +import { InputNumberProps } from 'antd/lib/input-number' +import { IPasswordProps } from './fields/password' +import { RadioGroupProps } from 'antd/lib/radio' +import { ISliderProps } from './fields/range' +import { RateProps } from 'antd/lib/rate' +import { InputProps } from 'antd/lib/input' +import { TextAreaProps } from 'antd/es/input' +import { TimePickerProps } from 'antd/lib/time-picker' +import { TransferProps } from 'antd/lib/transfer' +import { IUploaderProps } from './fields/upload' +import { SelectProps } from 'antd/lib/select' type ColSpanType = number | string @@ -16,56 +40,26 @@ export interface ColSize { offset?: ColSpanType } -export interface ISchemaFormExpandProps { - autoAddColon?: boolean - className?: string - inline?: boolean - layout?: TLayout - maxTipsNum?: number - labelAlign?: TLabelAlign - labelTextAlign?: TTextAlign - labelCol?: ColSize | number - wrapperCol?: ColSize | number - size?: TSize - style?: React.CSSProperties - prefix?: string -} - export interface ILocaleMessages { [key: string]: string | ILocaleMessages } -export interface ISchemaFormProps { - actions?: IFormActions - initialValues?: V - defaultValue?: V - value?: V - editable?: boolean | ((name: string) => boolean) - effects?: IEffects - locale?: ILocaleMessages - schema?: ISchema - onChange?: (values: V) => void - onReset?: (values: V) => void - onSubmit?: (values: V) => void - onValidateFailed?: (fieldErrors: IFieldError[]) => void -} - export interface IFormLayoutProps { className?: string inline?: boolean - labelAlign?: TLabelAlign - wrapperCol?: number - labelCol?: number - labelTextAlign?: TTextAlign - size?: TSize + labelAlign?: LabelAlign + wrapperCol?: ColProps | number + labelCol?: ColProps | number + labelTextAlign?: TextAlign + size?: Size style?: React.CSSProperties } export interface IFormItemGridProps { cols?: Array - description?: TTextEl + description?: TextEl gutter?: number - title?: TTextEl + title?: TextEl } export interface IRowProps { @@ -85,7 +79,7 @@ export interface IRowProps { } export interface IColProps extends ColProps { - prefix: string + prefix?: string pure?: boolean className?: string fixedSpan?: string | number @@ -114,9 +108,11 @@ export type TFormCardOrFormBlockProps = Omit export interface IFormTextBox { text?: string - title?: TTextEl - description?: TTextEl + name?: string + title?: TextEl + description?: TextEl gutter?: number + required?: boolean } export interface IFormButtonGroupProps { @@ -134,3 +130,57 @@ export interface IFormButtonGroupProps { export interface ISubmitProps extends Omit { showLoading?: boolean } + +export interface SchemaFormProps { + actions?: IFormActions | IAsyncFormActions + initialValues?: V + defaultValue?: V + value?: V + editable?: boolean | ((name: string) => boolean) + effects?: IEffects + locale?: ILocaleMessages + schema?: ISchema + onChange?: (values: V) => void + onReset?: (values: V) => void + onSubmit?: (values: V) => void + onValidateFailed?: (fieldErrors: IFieldError[]) => void + autoAddColon?: boolean + className?: string + inline?: boolean + layout?: Layout + maxTipsNum?: number + labelAlign?: LabelAlign + labelTextAlign?: TextAlign + labelCol?: ColSize | number + wrapperCol?: ColSize | number + size?: Size + style?: React.CSSProperties + prefix?: string +} + +interface InternalFieldTypes { + boolean: SwitchProps | SelectProps + checkbox: CheckboxGroupProps + date: DatePickerProps + daterange: RangePickerProps + month: MonthPickerProps + week: WeekPickerProps + year: DatePickerProps + number: InputNumberProps | SelectProps + password: IPasswordProps + radio: RadioGroupProps + range: ISliderProps + rating: RateProps + string: InputProps | SelectProps + textarea: TextAreaProps | SelectProps + time: TimePickerProps + transfer: TransferProps + upload: IUploaderProps +} + +export interface FieldProps extends ISchema { + type?: T + name?: string + editable?: boolean + ['x-props']?: T extends keyof InternalFieldTypes ? InternalFieldTypes[T] : any +} diff --git a/packages/core/src/form.ts b/packages/core/src/form.ts index 598f3867a4c..45f64be56f4 100644 --- a/packages/core/src/form.ts +++ b/packages/core/src/form.ts @@ -44,8 +44,8 @@ const defaults = (opts: T): T => ({ initialValues: {}, values: {}, - onSubmit: (values: any) => {}, - effects: ($: any) => {}, + onSubmit: () => {}, + effects: () => {}, ...opts } as T) @@ -85,6 +85,8 @@ export class Form { private traverse: (schema: ISchema) => ISchema constructor(opts: IFormOptions) { + this.getFieldState = this.getFieldState.bind(this) + this.getFormState = this.getFormState.bind(this) this.options = defaults(opts) this.publisher = new Broadcast() this.initialized = false @@ -117,7 +119,7 @@ export class Form { public changeEditable(editable: Editable) { this.editable = editable - each(this.fields, (field, name) => { + each(this.fields, field => { field.changeEditable(editable) }) } @@ -128,7 +130,7 @@ export class Form { public setFieldState = ( path: Path | IFormPathMatcher, - callback?: (fieldState: IFieldState) => void + callback: (fieldState: IFieldState) => void ): Promise => { if (this.destructed) { return @@ -156,10 +158,16 @@ export class Form { }) } - public getFieldState = ( + public getFieldState( path: Path | IFormPathMatcher, - callback: (fieldState: IFieldState) => any - ) => { + callback: (fieldState: IFieldState) => void + ): void + public getFieldState(path: Path | IFormPathMatcher): IFieldState + + public getFieldState( + path: Path | IFormPathMatcher, + callback?: (fieldState: IFieldState) => void + ): any { let field: IField each(this.fields, innerField => { if (innerField.match(path)) { @@ -175,19 +183,21 @@ export class Form { } } - public getFormState = (callback: any) => { + public getFormState(callback: (formState: IFormState) => void): void + public getFormState(): IFormState + public getFormState(callback?: any): any { return isFn(callback) ? callback(this.publishState()) : this.publishState() } - public setFormState = reducer => { + public setFormState = (callback: (formState: IFormState) => void) => { if (this.destructed) { return } - if (!isFn(reducer)) { + if (!isFn(callback)) { return } const published = this.publishState() - reducer(published, reducer) + callback(published) return Promise.resolve(this.checkState(published)) } @@ -519,7 +529,7 @@ export class Form { return formState } - public validate(): Promise { + public validate(): Promise { return this.internalValidate(this.state.values, true).then(() => { return new Promise((resolve, reject) => { this.formNotify() diff --git a/packages/next/src/components/layout.tsx b/packages/next/src/components/layout.tsx index c746a19c375..e6760316594 100644 --- a/packages/next/src/components/layout.tsx +++ b/packages/next/src/components/layout.tsx @@ -59,7 +59,7 @@ export const FormLayout = createVirtualBox( } ) -export const FormLayoutItem: React.FC> = props => +export const FormLayoutItem: React.FC = props => React.createElement( FormLayoutConsumer, {}, @@ -110,9 +110,13 @@ export const FormItemGrid = createVirtualBox( const { children: rawChildren, cols: rawCols, + // eslint-disable-next-line @typescript-eslint/no-unused-vars title, + // eslint-disable-next-line @typescript-eslint/no-unused-vars description, + // eslint-disable-next-line @typescript-eslint/no-unused-vars help, + // eslint-disable-next-line @typescript-eslint/no-unused-vars extra, ...props } = this.props diff --git a/packages/next/src/index.ts b/packages/next/src/index.tsx similarity index 51% rename from packages/next/src/index.ts rename to packages/next/src/index.tsx index fa1907ed3c9..b47f2e0a123 100644 --- a/packages/next/src/index.ts +++ b/packages/next/src/index.tsx @@ -21,14 +21,25 @@ export * from './components/formButtonGroup' export * from './components/button' export * from './components/layout' -import { SchemaForm as ReactSchemaForm } from '@uform/react' -import { mapStyledProps, mapTextComponent } from './utils' -import { ISchemaFormProps, ISchemaFormExpandProps } from './type' +import React from 'react' +import { + SchemaForm as InternalSchemaForm, + Field as InternalField +} from '@uform/react' +import { SchemaFormProps, FieldProps } from './type' -export { mapStyledProps, mapTextComponent } +export { mapStyledProps, mapTextComponent } from './utils' -export const SchemaForm: React.ComponentClass< - ISchemaFormProps & ISchemaFormExpandProps -> = ReactSchemaForm +export default class SchemaForm extends React.Component> { + render() { + return + } +} -export default SchemaForm +export class Field extends React.Component< + FieldProps +> { + render() { + return + } +} diff --git a/packages/next/src/type.tsx b/packages/next/src/type.tsx index 3e070d4bbc2..fe6441ccdcf 100644 --- a/packages/next/src/type.tsx +++ b/packages/next/src/type.tsx @@ -1,13 +1,35 @@ import { ButtonProps } from '@alifd/next/types/button' import { CardProps } from '@alifd/next/types/card' import { RowProps, ColProps } from '@alifd/next/types/grid' -import { IFormActions, ISchema, IEffects, IFieldError } from '@uform/types' - -export type TTextAlign = 'left' | 'right' -export type TSize = 'small' | 'medium' | 'large' -export type TLayout = 'horizontal' | 'vertical' | 'inline' -export type TTextEl = string | JSX.Element | null -export type TLabelAlign = 'left' | 'top' | 'inset' +import { + IFormActions, + ISchema, + IEffects, + IFieldError, + Size, + TextAlign, + Layout, + TextEl, + LabelAlign +} from '@uform/types' +import { SwitchProps } from '@alifd/next/types/switch' +import { GroupProps as CheckboxGroupProps } from '@alifd/next/types/checkbox' +import { GroupProps as RadioGroupProps } from '@alifd/next/types/radio' +import { + DatePickerProps, + RangePickerProps, + MonthPickerProps, + YearPickerProps +} from '@alifd/next/types/date-picker' +import { NumberPickerProps } from '@alifd/next/types/number-picker' +import { IPasswordProps } from './fields/password' +import { RangeProps } from '@alifd/next/types/range' +import { RatingProps } from '@alifd/next/types/rating' +import { InputProps, TextAreaProps } from '@alifd/next/types/input' +import { TimePickerProps } from '@alifd/next/types/time-picker' +import { TransferProps } from '@alifd/next/types/transfer' +import { IUploaderProps } from './fields/upload' +import { SelectProps } from '@alifd/next/types/select' type ColSpanType = number | string @@ -16,64 +38,34 @@ export interface ColSize { offset?: ColSpanType } -export interface ISchemaFormExpandProps { - autoAddColon?: boolean - className?: string - inline?: boolean - layout?: TLayout - maxTipsNum?: number - labelAlign?: TLabelAlign - labelTextAlign?: TTextAlign - labelCol?: ColSize | number - wrapperCol?: ColSize | number - size?: TSize - style?: React.CSSProperties - prefix?: string -} - export interface ILocaleMessages { [key: string]: string | ILocaleMessages } -export interface ISchemaFormProps { - actions?: IFormActions - initialValues?: V - defaultValue?: V - value?: V - editable?: boolean | ((name: string) => boolean) - effects?: IEffects - locale?: ILocaleMessages - schema?: ISchema - onChange?: (values: V) => void - onReset?: (values: V) => void - onSubmit?: (values: V) => void - onValidateFailed?: (fieldErrors: IFieldError[]) => void -} - export interface IFormLayoutProps { className?: string inline?: boolean - labelAlign?: TLabelAlign + labelAlign?: LabelAlign wrapperCol?: number labelCol?: number - labelTextAlign?: TTextAlign - size?: TSize + labelTextAlign?: TextAlign + size?: Size style?: React.CSSProperties } export interface IFormItemGridProps { cols?: Array - description?: TTextEl + description?: TextEl gutter?: number - title?: TTextEl + title?: TextEl } export type TFormCardOrFormBlockProps = Omit export interface IFormTextBox { text?: string - title?: TTextEl - description?: TTextEl + title?: TextEl + description?: TextEl gutter?: number } @@ -85,7 +77,7 @@ export interface IRowProps extends RowProps { } export interface IColProps extends ColProps { - prefix: string + prefix?: string pure?: boolean className?: string } @@ -113,3 +105,56 @@ export interface IFormButtonGroupProps { span?: number offset?: number } + +export interface SchemaFormProps { + actions?: IFormActions + initialValues?: V + defaultValue?: V + value?: V + editable?: boolean | ((name: string) => boolean) + effects?: IEffects + locale?: ILocaleMessages + schema?: ISchema + onChange?: (values: V) => void + onReset?: (values: V) => void + onSubmit?: (values: V) => void + onValidateFailed?: (fieldErrors: IFieldError[]) => void + autoAddColon?: boolean + className?: string + inline?: boolean + layout?: Layout + maxTipsNum?: number + labelAlign?: LabelAlign + labelTextAlign?: TextAlign + labelCol?: ColSize | number + wrapperCol?: ColSize | number + size?: Size + style?: React.CSSProperties + prefix?: string +} + +interface InternalFieldTypes { + boolean: SwitchProps | SelectProps + checkbox: CheckboxGroupProps + date: DatePickerProps + daterange: RangePickerProps + month: MonthPickerProps + // week: WeekPickerProps + year: YearPickerProps + number: NumberPickerProps | SelectProps + password: IPasswordProps + radio: RadioGroupProps + range: RangeProps + rating: RatingProps + string: InputProps | SelectProps + textarea: TextAreaProps | SelectProps + time: TimePickerProps + transfer: TransferProps + upload: IUploaderProps +} +export interface FieldProps extends ISchema { + type?: T + name?: string + editable?: boolean + ['x-props']?: T extends keyof InternalFieldTypes ? InternalFieldTypes[T] : any +} diff --git a/packages/react/src/type.ts b/packages/react/src/type.ts index 667daeb93a1..572efd5c194 100644 --- a/packages/react/src/type.ts +++ b/packages/react/src/type.ts @@ -47,10 +47,10 @@ export interface IStateFieldState { required?: boolean } -export interface ISchemaFormProps extends IFormOptions { +export interface ISchemaFormProps extends IFormOptions { className?: string children?: React.ReactNode - value?: any + value?: V onChange?: (payload: IFormPayload) => void } diff --git a/packages/types/package.json b/packages/types/package.json index 8065a66e4ce..db452bc7f97 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -3,6 +3,7 @@ "version": "0.3.11", "license": "MIT", "main": "lib", + "module": "src", "types": "lib/index.d.ts", "repository": { "type": "git", diff --git a/packages/types/src/effects.ts b/packages/types/src/effects.ts index 3725d1faf80..c8f2288ee71 100644 --- a/packages/types/src/effects.ts +++ b/packages/types/src/effects.ts @@ -1,9 +1,9 @@ -import { Subject } from 'rxjs/internal/Subject' import { IFormActions, IFormPathMatcher } from './form' +import { Observable } from 'rxjs/internal/Observable' export type Dispatcher = (eventName: string, payload: any) => void export type IEffects = (selector: ISelector, actions: IFormActions) => void export type ISelector = ( eventName: string, formPathPattern: string | IFormPathMatcher -) => Subject +) => Observable diff --git a/packages/types/src/field.ts b/packages/types/src/field.ts index 528bf36ec20..7741058ac89 100644 --- a/packages/types/src/field.ts +++ b/packages/types/src/field.ts @@ -3,8 +3,8 @@ import { ISchema } from './schema' import { Path } from './path' import { IFormPathMatcher } from './form' -export interface IField { - value: any +export interface IField { + value: V valid: boolean dirty: boolean invalid: boolean @@ -18,13 +18,13 @@ export interface IField { errors: string[] effectErrors: string[] pristine: boolean - initialValue: any + initialValue: V name: string path: string[] props: ISchema rules: IRuleDescription[] dirtyType: string - lastValidateValue: any + lastValidateValue: V notify: (forceUpdate?: boolean) => void changeEditable: (editable: boolean | ((name: string) => boolean)) => void match: (path: Path | IFormPathMatcher) => boolean diff --git a/packages/types/src/form.ts b/packages/types/src/form.ts index 782e00b807a..40057cc6425 100644 --- a/packages/types/src/form.ts +++ b/packages/types/src/form.ts @@ -18,9 +18,9 @@ export interface IFieldError { errors: string[] } -export interface IFormState { - values: any // 表单数据 - initialValues: any // 初始化数据 +export interface IFormState { + values: V // 表单数据 + initialValues: V // 初始化数据 valid: boolean // 是否合法 invalid: boolean // 是否不合法 errors: IFieldError[] // 错误提示集合 @@ -32,13 +32,13 @@ export interface ISubscribers { [eventName: string]: Subject } -export interface IFormOptions { - editable: boolean | ((nam: string) => boolean) +export interface IFormOptions { + editable: boolean | ((name: string) => boolean) effects: IEffects - defaultValue?: object - values?: object - initialValues?: object - schema: ISchema | {} + defaultValue?: V + values?: V + initialValues?: V + schema: ISchema subscribes: ISubscribers onFormChange: (payload: IFormPayload) => void onFieldChange: (payload: IFieldPayload) => void @@ -49,44 +49,57 @@ export interface IFormOptions { traverse?: (schema: ISchema) => ISchema } -type TUnionType = T | Promise - -// 通过 createActions 或者 createAsyncActions 创建出来的 actions 接口 +// 通过 createActions 创建出来的 actions 接口 export interface IFormActions { setFieldState: ( name: Path | IFormPathMatcher, - callback?: (fieldState: IFieldState) => void - ) => TUnionType - getFieldState: ( - name: Path | IFormPathMatcher, - callback?: (fieldState: IFieldState) => void - ) => TUnionType - getFormState: ( - callback?: (fieldState: IFormState) => void - ) => TUnionType - setFormState: (callback: (fieldState: IFormState) => void) => TUnionType - getSchema: (path: Path) => TUnionType + callback: (fieldState: IFieldState) => void + ) => Promise + + getFieldState: { + ( + name: Path | IFormPathMatcher, + callback: (fieldState: IFieldState) => void + ): void + (name: Path | IFormPathMatcher): IFieldState + } + + getFormState: { + (): IFormState + (callback: (formState: IFormState) => void): void + } + + setFormState: (callback: (formState: IFormState) => void) => Promise + getSchema: (path: Path) => ISchema reset: ( forceClear?: boolean | { forceClear?: boolean; validate?: boolean }, validate?: boolean - ) => TUnionType - submit: () => TUnionType - validate: () => TUnionType - dispatch: (type: string, payload: T) => TUnionType + ) => void + submit: () => Promise + validate: () => Promise // error will be IFormState['errors'] + dispatch: (type: string, payload: T) => void } +// 通过 createAsyncActions 创建出来的 actions 接口 export interface IAsyncFormActions { setFieldState: ( name: Path | IFormPathMatcher, - callback?: (fieldState: IFieldState) => void + callback: (fieldState: IFieldState) => void ) => Promise - getFieldState: ( - name: Path | IFormPathMatcher, - callback?: (fieldState: IFieldState) => void - ) => Promise - getFormState: ( - callback?: (fieldState: IFormState) => void - ) => Promise + + getFieldState: { + ( + name: Path | IFormPathMatcher, + callback: (fieldState: IFieldState) => void + ): Promise + (name: Path | IFormPathMatcher): Promise + } + + getFormState: { + (): Promise + (callback: (formState: IFormState) => void): Promise + } + setFormState: (callback: (fieldState: IFormState) => void) => Promise getSchema: (path: Path) => Promise reset: ( @@ -94,7 +107,7 @@ export interface IAsyncFormActions { validate?: boolean ) => Promise submit: () => Promise - validate: () => Promise + validate: () => Promise //reject err will be IFormState['errors'] dispatch: (type: string, payload: T) => Promise } @@ -104,23 +117,36 @@ export interface IFormPathMatcher { pattern: string } -// next & antd 需要用到的 -export enum LabelAlign { - TOP = 'top', - INSET = 'inset', - LEFT = 'left' -} - -export enum LabelTextAlign { - LEFT = 'left', - RIGHT = 'right' -} - -export enum Size { - LARGE = 'large', - MEDIUM = 'medium', - SMALL = 'small' -} +export type TextAlign = 'left' | 'right' +export type Size = 'small' | 'medium' | 'large' +export type Layout = 'horizontal' | 'vertical' | 'inline' +export type TextEl = string | JSX.Element | null +export type LabelAlign = 'left' | 'top' | 'inset' + +type ColSpanType = number | string +export interface ColSize { + span?: ColSpanType + order?: ColSpanType + offset?: ColSpanType + push?: ColSpanType + pull?: ColSpanType +} + +export interface ColProps extends React.HTMLAttributes { + span?: ColSpanType + order?: ColSpanType + offset?: ColSpanType + push?: ColSpanType + pull?: ColSpanType + xs?: ColSpanType | ColSize + sm?: ColSpanType | ColSize + md?: ColSpanType | ColSize + lg?: ColSpanType | ColSize + xl?: ColSpanType | ColSize + xxl?: ColSpanType | ColSize + prefixCls?: string +} +// export type ColProps = { span: number; offset?: number } | number export interface IFormItemGridProps { name?: string @@ -131,37 +157,37 @@ export interface IFormItemGridProps { cols?: any } -export interface IFormSharedProps { - labelCol: object | number - wrapperCol: object | number - autoAddColon: boolean - size: Size - inline: boolean - labelAlign: LabelAlign - labelTextAlign: LabelTextAlign - className: string - style: React.CSSProperties - prefix: string - maxTipsNum: number +interface IFormSharedProps { + labelCol?: ColProps | number + wrapperCol?: ColProps | number + autoAddColon?: boolean + size?: Size + inline?: boolean + labelAlign?: LabelAlign + labelTextAlign?: TextAlign + className?: string + style?: React.CSSProperties + prefix?: string + maxTipsNum?: number } export interface IFormProps extends IFormSharedProps { - layout: string - children: React.ReactNode - component: string - onValidateFailed: () => void + layout?: string + children?: React.ReactNode + component?: string + onValidateFailed?: () => void } export interface IFormItemProps extends IFormSharedProps { - id: string - required: boolean - label: React.ReactNode - extra: React.ReactNode - validateState: any - isTableColItem: boolean - help: React.ReactNode - noMinHeight: boolean - children: React.ReactElement - type: string - schema: ISchema + id?: string + required?: boolean + label?: React.ReactNode + extra?: React.ReactNode + validateState?: any + isTableColItem?: boolean + help?: React.ReactNode + noMinHeight?: boolean + children?: React.ReactElement + type?: string + schema?: ISchema } diff --git a/packages/types/src/schema.ts b/packages/types/src/schema.ts index e21aacfa5fb..a6c37500a3a 100644 --- a/packages/types/src/schema.ts +++ b/packages/types/src/schema.ts @@ -1,13 +1,15 @@ import { Rule } from './rule' import { Dispatcher } from './effects' -export interface ISchema { +type MayBeArray = V | (V[]) + +export interface ISchema { type?: string title?: string description?: string - default?: unknown + default?: MayBeArray required?: boolean - enum?: Array<{ label: string; value: unknown } | string | number> + enum?: Array<{ label: string; value: V } | string | number> enumNames?: string[] properties?: { [key: string]: ISchema diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index 5a764856bf3..828bb72ee5b 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -1,6 +1,7 @@ const isType = (type: string) => (obj: unknown): obj is T => obj != null && Object.prototype.toString.call(obj) === `[object ${type}]` -export const isFn = isType<(...args: any[]) => void>('Function') +// FIXME: isFn, isArr is incorrect +export const isFn = isType<(...args: any[]) => any>('Function') export const isArr = Array.isArray || isType('Array') export const isPlainObj = isType('Object') export const isStr = isType('String')