@rainbow-oh/yee-c 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Form/demo/async-validate.js +2 -2
- package/dist/cjs/Form/demo/validate.js +2 -2
- package/dist/cjs/Form/form-store.js +19 -6
- package/dist/cjs/Form/index.d.ts +1 -1
- package/dist/cjs/Form/interface.d.ts +9 -2
- package/dist/cjs/Form/utils/path.js +1 -1
- package/dist/cjs/TreeSelect/tree-select.js +14 -4
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Form/demo/async-validate.js +2 -2
- package/dist/esm/Form/demo/validate.js +2 -2
- package/dist/esm/Form/form-store.js +33 -10
- package/dist/esm/Form/hooks/useForm.js +0 -175
- package/dist/esm/Form/index.d.ts +1 -1
- package/dist/esm/Form/interface.d.ts +9 -2
- package/dist/esm/Form/utils/path.js +2 -1
- package/dist/esm/TreeSelect/tree-select.js +20 -6
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Form/demo/async-validate.tsx +3 -2
- package/src/Form/demo/validate.tsx +3 -2
- package/src/Form/form-store.test.ts +156 -0
- package/src/Form/form-store.ts +28 -9
- package/src/Form/hooks/useForm.ts +0 -175
- package/src/Form/index.en-US.md +92 -92
- package/src/Form/index.ts +1 -0
- package/src/Form/index.zh-CN.md +55 -55
- package/src/Form/interface.ts +9 -2
- package/src/Form/utils/path.ts +2 -1
- package/src/TreeSelect/tree-select.tsx +21 -4
- package/src/version.ts +1 -1
package/src/Form/index.en-US.md
CHANGED
|
@@ -30,113 +30,113 @@ High performance form component with data scope management.
|
|
|
30
30
|
|
|
31
31
|
### FormProps
|
|
32
32
|
|
|
33
|
-
| Property | Type
|
|
34
|
-
| -------------------- |
|
|
35
|
-
| prefixCls | `string`
|
|
36
|
-
| className | `string`
|
|
37
|
-
| style | `React.CSSProperties`
|
|
38
|
-
| children | `React.ReactNode`
|
|
39
|
-
| name | `string`
|
|
40
|
-
| form | [FormInstance](#forminstance)
|
|
41
|
-
| disabled | `boolean`
|
|
42
|
-
| initialValues | `Store`
|
|
43
|
-
| layout | `'vertical' \| 'horizontal'`
|
|
44
|
-
| onFinish | `(values: Values) => void`
|
|
45
|
-
| onFinishFailed | `(
|
|
46
|
-
| onValuesChange | `(changedValues: Record<string, any>, values: Values) => void`
|
|
47
|
-
| onValuesBeforeChange | `(changedValues: Record<string, any>, values: Values) => void \| any` | Field value change before event callback | -
|
|
48
|
-
| onReset | `() => void`
|
|
49
|
-
| data
|
|
33
|
+
| Property | Type | Description | Default |
|
|
34
|
+
| -------------------- | --------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------- |
|
|
35
|
+
| prefixCls | `string` | Custom class name prefix | - |
|
|
36
|
+
| className | `string` | Custom root class name | - |
|
|
37
|
+
| style | `React.CSSProperties` | Custom root style | - |
|
|
38
|
+
| children | `React.ReactNode` | Fields | - |
|
|
39
|
+
| name | `string` | Form name | - |
|
|
40
|
+
| form | [FormInstance](#forminstance) | Form instance | - |
|
|
41
|
+
| disabled | `boolean` | Whether disabled | - |
|
|
42
|
+
| initialValues | `Store` | Initial values keyed by field name; nested fields use nested objects, e.g. `{ user: { name: 'tom' } }` | - |
|
|
43
|
+
| layout | `'vertical' \| 'horizontal'` | Layout | - |
|
|
44
|
+
| onFinish | `(values: Values) => void` | Submit event callback | - |
|
|
45
|
+
| onFinishFailed | `(errors: ValidateMessage[]) => void` | Submit error event callback | - |
|
|
46
|
+
| onValuesChange | `(changedValues: Record<string, any>, values: Values) => void` | Field value change event callback | - |
|
|
47
|
+
| onValuesBeforeChange | `(changedValues: Record<string, any>, values: Values) => void \| any` | Field value change before event callback | - |
|
|
48
|
+
| onReset | `() => void` | Reset event callback | - |
|
|
49
|
+
| data-\* | `string` | - | Supports all data-\* attributes, forwarded to root DOM element |
|
|
50
50
|
|
|
51
51
|
### FormInstance
|
|
52
52
|
|
|
53
|
-
| Property | Type | Description
|
|
54
|
-
| --------------------- | ------------------------------------------------------------------------------------------ |
|
|
55
|
-
| getFieldValidate | `(name: Name) => ValidateMessage \| null`
|
|
56
|
-
| getFieldStatus | `(name: NamePath) => FieldStatusData \| null`
|
|
57
|
-
| setFieldStatus | `(name: NamePath, status: FieldStatusData \| null) => void`
|
|
58
|
-
| getFieldValue | `(name: Name) => StoreValue`
|
|
59
|
-
| submit | `() => Promise<ValidateMessage[]>`
|
|
60
|
-
| getFieldsValue | `() => Values` | Get all field values
|
|
61
|
-
| setFieldsValue | `(newStore: Store, trigger?: TRIGGER) => void`
|
|
62
|
-
| setCallbacks | `(callbacks: Callbacks) => void` | Set callbacks
|
|
63
|
-
| resetFields | `(name?: Name[]) => void`
|
|
64
|
-
| clearFields | `(name?: Name[]) => void`
|
|
65
|
-
| validateField | `(name: Name, trigger?: 'onChange' \| 'onBlur') => Promise<ValidateMessage[]>`
|
|
66
|
-
| validateFields | `(names?: Name[], trigger?: TRIGGER) => Promise<ValidateMessage[]>`
|
|
67
|
-
| getCallbacks | `() => Callbacks`
|
|
68
|
-
| registerFieldEntities | `(entity: FieldEntity) => void` | Register field entities
|
|
69
|
-
| initialize | `({ initialValues, callbacks }: { initialValues?: Store; callbacks?: Callbacks }) => void` | Initialize form
|
|
70
|
-
| getListFields | `(name: NamePath) => FormListField[]` | Get list fields
|
|
71
|
-
| getListOperations | `(name: NamePath) => FormListOperation` | Get list operations
|
|
72
|
-
| subscribe | `(namePath?: NamePath, callback?: () => void) => () => void`
|
|
53
|
+
| Property | Type | Description |
|
|
54
|
+
| --------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
55
|
+
| getFieldValidate | `(name: Name) => ValidateMessage \| null` | Get field validation (may lag before async validation completes; updates via onStoreChange) |
|
|
56
|
+
| getFieldStatus | `(name: NamePath) => FieldStatusData \| null` | Get the displayed field status; rule validation errors take display precedence, otherwise a manually set status overrides validation |
|
|
57
|
+
| setFieldStatus | `(name: NamePath, status: FieldStatusData \| null) => void` | Set field status and message dynamically, or pass `null` to clear it; only blocking errors prevent submission |
|
|
58
|
+
| getFieldValue | `(name: Name) => StoreValue` | Get field value |
|
|
59
|
+
| submit | `() => Promise<ValidateMessage[]>` | Submit form (async, triggers onFinish only after validation completes) |
|
|
60
|
+
| getFieldsValue | `() => Values` | Get all field values |
|
|
61
|
+
| setFieldsValue | `(newStore: Store, trigger?: TRIGGER) => void` | Set field values |
|
|
62
|
+
| setCallbacks | `(callbacks: Callbacks) => void` | Set callbacks |
|
|
63
|
+
| resetFields | `(name?: Name[]) => void` | Reset fields (values and validation state; passing name only affects related fields) |
|
|
64
|
+
| clearFields | `(name?: Name[]) => void` | Clear fields (values and validation state; passing name only affects related fields) |
|
|
65
|
+
| validateField | `(name: Name, trigger?: 'onChange' \| 'onBlur') => Promise<ValidateMessage[]>` | Validate single field |
|
|
66
|
+
| validateFields | `(names?: Name[], trigger?: TRIGGER) => Promise<ValidateMessage[]>` | Validate multiple fields |
|
|
67
|
+
| getCallbacks | `() => Callbacks` | Get callbacks |
|
|
68
|
+
| registerFieldEntities | `(entity: FieldEntity) => void` | Register field entities |
|
|
69
|
+
| initialize | `({ initialValues, callbacks }: { initialValues?: Store; callbacks?: Callbacks }) => void` | Initialize form |
|
|
70
|
+
| getListFields | `(name: NamePath) => FormListField[]` | Get list fields |
|
|
71
|
+
| getListOperations | `(name: NamePath) => FormListOperation` | Get list operations |
|
|
72
|
+
| subscribe | `(namePath?: NamePath, callback?: () => void) => () => void` | Subscribe to field value changes, omit namePath to watch all fields |
|
|
73
73
|
|
|
74
74
|
### Form Static Methods
|
|
75
75
|
|
|
76
|
-
| Method
|
|
77
|
-
|
|
|
78
|
-
| Form.useForm
|
|
79
|
-
| Form.useWatch
|
|
80
|
-
| Form.useFormInstance | `() => FormInstance`
|
|
76
|
+
| Method | Type | Description |
|
|
77
|
+
| -------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
78
|
+
| Form.useForm | `(form?: FormInstance) => [FormInstance]` | Create a Form instance; pass an external form for controlled usage |
|
|
79
|
+
| Form.useWatch | `(namePath?: NamePath, form?: FormInstance) => T \| undefined` | Watch form field value changes, omit namePath to get all values |
|
|
80
|
+
| Form.useFormInstance | `() => FormInstance` | Get the nearest Form instance from context, must be used inside a `<Form>` |
|
|
81
81
|
|
|
82
82
|
### Field.GroupProps
|
|
83
83
|
|
|
84
|
-
| Property
|
|
85
|
-
|
|
|
86
|
-
| children
|
|
87
|
-
| label
|
|
88
|
-
| required
|
|
89
|
-
| rules
|
|
90
|
-
| cols
|
|
91
|
-
| style
|
|
92
|
-
| className | `string`
|
|
84
|
+
| Property | Type | Description | Default |
|
|
85
|
+
| --------- | --------------------- | -------------------------------------------------------------------------------- | ------- |
|
|
86
|
+
| children | `React.ReactNode` | Child elements, typically multiple Form.Field | - |
|
|
87
|
+
| label | `React.ReactNode` | Group label | - |
|
|
88
|
+
| required | `boolean` | Whether required (shows required indicator) | - |
|
|
89
|
+
| rules | [Rule\[\]](#rule) | Group-level validation rules, validator receives an object of child field values | - |
|
|
90
|
+
| cols | `number` | Number of columns for child fields | - |
|
|
91
|
+
| style | `React.CSSProperties` | Custom style | - |
|
|
92
|
+
| className | `string` | Custom class name | - |
|
|
93
93
|
|
|
94
94
|
### FieldProps
|
|
95
95
|
|
|
96
|
-
| Property
|
|
97
|
-
|
|
|
98
|
-
| className
|
|
99
|
-
| style
|
|
100
|
-
| classNames
|
|
101
|
-
| styles
|
|
102
|
-
| children
|
|
103
|
-
| name
|
|
104
|
-
| rules
|
|
105
|
-
| label
|
|
106
|
-
| tooltip
|
|
107
|
-
| required
|
|
108
|
-
| disabled
|
|
109
|
-
| initialValue
|
|
110
|
-
| valuePropName | `string`
|
|
96
|
+
| Property | Type | Description | Default |
|
|
97
|
+
| ------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
|
|
98
|
+
| className | `string` | Custom field root class name | - |
|
|
99
|
+
| style | `React.CSSProperties` | Custom field root style | - |
|
|
100
|
+
| classNames | `Partial<Record<'label' \| 'control', string>>` | Semantic structure class names | - |
|
|
101
|
+
| styles | `Partial<Record<'label' \| 'control', React.CSSProperties>>` | Semantic structure styles | - |
|
|
102
|
+
| children | `React.ReactElement` | Child element | - |
|
|
103
|
+
| name | `NamePath` | Field name | - |
|
|
104
|
+
| rules | [Rule\[\]](#rule) | Validation rules | - |
|
|
105
|
+
| label | `React.ReactNode` | Label | - |
|
|
106
|
+
| tooltip | `ReactNode \| (Omit<TooltipProps, 'children'> & { icon?: ReactNode })` | Help tooltip next to the label. Pass a string/node to use the default icon; pass an object to customize `icon` — all other props (`title`, `color`, `placement`, ...) are forwarded to Tooltip | - |
|
|
107
|
+
| required | `boolean` | Whether required | - |
|
|
108
|
+
| disabled | `boolean` | Whether disabled | - |
|
|
109
|
+
| initialValue | `unknown` | Initial value | - |
|
|
110
|
+
| valuePropName | `string` | Property name for child component value | `'value'` |
|
|
111
111
|
|
|
112
112
|
### Rule
|
|
113
113
|
|
|
114
|
-
| Property | Type
|
|
115
|
-
| --------------- |
|
|
116
|
-
| required | `boolean`
|
|
117
|
-
| type | `string`
|
|
118
|
-
| min | `number`
|
|
119
|
-
| max | `number`
|
|
120
|
-
| minLength | `number`
|
|
121
|
-
| maxLength | `number`
|
|
122
|
-
| regexp | `RegExp`
|
|
123
|
-
| message | `string`
|
|
124
|
-
| validator | `(value: unknown) => boolean \| void \| Promise<boolean \| void>`
|
|
125
|
-
| validateTrigger | `'onBlur' \| 'onChange' \| 'onSubmit' \| Array<'onBlur' \| 'onChange' \| 'onSubmit'>` | Validation trigger
|
|
114
|
+
| Property | Type | Description |
|
|
115
|
+
| --------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
+
| required | `boolean` | Whether required |
|
|
117
|
+
| type | `string` | Type |
|
|
118
|
+
| min | `number` | Minimum value |
|
|
119
|
+
| max | `number` | Maximum value |
|
|
120
|
+
| minLength | `number` | Minimum length |
|
|
121
|
+
| maxLength | `number` | Maximum length |
|
|
122
|
+
| regexp | `RegExp` | Regular expression |
|
|
123
|
+
| message | `string` | Error message |
|
|
124
|
+
| validator | `(value: unknown) => boolean \| void \| Promise<boolean \| void>` | Custom validator. Supports sync and async: sync `return false`/`throw` fails; async `resolve(false)`/`reject`/`throw` fails. When throwing/rejecting with an Error, `error.message` overrides `message` |
|
|
125
|
+
| validateTrigger | `'onBlur' \| 'onChange' \| 'onSubmit' \| Array<'onBlur' \| 'onChange' \| 'onSubmit'>` | Validation trigger |
|
|
126
126
|
|
|
127
127
|
### Types
|
|
128
128
|
|
|
129
|
-
| Type
|
|
130
|
-
|
|
|
131
|
-
| StoreValue
|
|
132
|
-
| Store
|
|
133
|
-
| Name
|
|
134
|
-
| NamePath
|
|
135
|
-
| FieldStatus
|
|
136
|
-
| FieldStatusData
|
|
137
|
-
| ValidateMessage
|
|
138
|
-
| FieldEntity
|
|
139
|
-
| TRIGGER
|
|
140
|
-
| FormListField
|
|
141
|
-
| FormListOperation | `{ add: (defaultValue?: any, insertIndex?: number) => void; remove: (index: number \| number[]) => void; move: (from: number, to: number) => void }`
|
|
142
|
-
| FormListProps
|
|
129
|
+
| Type | Description |
|
|
130
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| StoreValue | `any` |
|
|
132
|
+
| Store | `Record<string, StoreValue>` |
|
|
133
|
+
| Name | `string` |
|
|
134
|
+
| NamePath | `string \| string[] \| number \| (string \| number)[]` |
|
|
135
|
+
| FieldStatus | `'error' \| 'success' \| 'warning' \| 'info'` |
|
|
136
|
+
| FieldStatusData | `{ status: FieldStatus; message?: string; blocking?: boolean }` |
|
|
137
|
+
| ValidateMessage | `{ name: NamePath \| NamePath[] \| undefined; message: string; value: unknown; status: 'error' \| 'success' \| 'warning' \| 'info' }` |
|
|
138
|
+
| FieldEntity | `{ props: fieldProps & { name?: NamePath }; onStoreChange: () => void }` |
|
|
139
|
+
| TRIGGER | `'onChange' \| 'onBlur' \| 'onSubmit' \| 'reset' \| 'clear' \| 'update'` |
|
|
140
|
+
| FormListField | `{ key: React.Key; name: number; isListField?: boolean }` |
|
|
141
|
+
| FormListOperation | `{ add: (defaultValue?: any, insertIndex?: number) => void; remove: (index: number \| number[]) => void; move: (from: number, to: number) => void }` |
|
|
142
|
+
| FormListProps | `{ name: NamePath; children: (fields: FormListField[], operation: FormListOperation, meta: { errors: React.ReactNode[] }) => React.ReactNode; initialValue?: any[]; rules?: Rule[] }` |
|
package/src/Form/index.ts
CHANGED
package/src/Form/index.zh-CN.md
CHANGED
|
@@ -38,10 +38,10 @@ toc: 'content'
|
|
|
38
38
|
| name | `string` | 表单名 | - |
|
|
39
39
|
| form | [FormInstance](#forminstance) | 表单实例 | - |
|
|
40
40
|
| disabled | `boolean` | 是否禁用 | - |
|
|
41
|
-
| initialValues | `Store` |
|
|
41
|
+
| initialValues | `Store` | 初始值,键为字段 name;嵌套字段用嵌套对象表示,如 `{ user: { name: 'tom' } }` | - |
|
|
42
42
|
| layout | `'vertical' \| 'horizontal'` | 布局 | - |
|
|
43
43
|
| onFinish | `(values: Values) => void` | submit提交时触发事件 | - |
|
|
44
|
-
| onFinishFailed | `(
|
|
44
|
+
| onFinishFailed | `(errors: ValidateMessage[]) => void` | submit提交报错时触发事件 | - |
|
|
45
45
|
| onValuesChange | `(changedValues: Record<string, any>, values: Values) => void` | 表单字段值改变时触发事件 | - |
|
|
46
46
|
| onValuesBeforeChange | `(changedValues: Record<string, any>, values: Values) => void \| any` | 表单字段值改变前触发事件 | - |
|
|
47
47
|
| onReset | `() => void` | 表单重置时触发的事件 | - |
|
|
@@ -49,34 +49,34 @@ toc: 'content'
|
|
|
49
49
|
|
|
50
50
|
### FormInstance
|
|
51
51
|
|
|
52
|
-
| 属性名 | 类型 | 描述
|
|
53
|
-
| --------------------- | ------------------------------------------------------------------------------------------ |
|
|
54
|
-
| getFieldValidate | `(name: Name) => ValidateMessage \| null`
|
|
55
|
-
| getFieldStatus | `(name: NamePath) => FieldStatusData \| null`
|
|
56
|
-
| setFieldStatus | `(name: NamePath, status: FieldStatusData \| null) => void`
|
|
57
|
-
| getFieldValue | `(name: Name) => StoreValue` | 获取字段值
|
|
58
|
-
| submit | `() => Promise<ValidateMessage[]>`
|
|
59
|
-
| getFieldsValue | `() => Values` | 获取所有字段值
|
|
60
|
-
| setFieldsValue | `(newStore: Store, trigger?: TRIGGER) => void` | 设置字段值
|
|
61
|
-
| setCallbacks | `(callbacks: Callbacks) => void` | 设置回调
|
|
62
|
-
| resetFields | `(name?: Name[]) => void` | 重置字段(值与校验状态;指定 name 时只影响相关字段)
|
|
63
|
-
| clearFields | `(name?: Name[]) => void` |
|
|
64
|
-
| validateField | `(name: Name, trigger?: 'onChange' \| 'onBlur') => Promise<ValidateMessage[]>`
|
|
65
|
-
| validateFields | `(names?: Name[], trigger?: TRIGGER) => Promise<ValidateMessage[]>`
|
|
66
|
-
| getCallbacks | `() => Callbacks` | 获取回调
|
|
67
|
-
| registerFieldEntities | `(entity: FieldEntity) => void` | 注册字段实体
|
|
68
|
-
| initialize | `({ initialValues, callbacks }: { initialValues?: Store; callbacks?: Callbacks }) => void` | 初始化表单
|
|
69
|
-
| getListFields | `(name: NamePath) => FormListField[]` | 获取列表字段
|
|
70
|
-
| getListOperations | `(name: NamePath) => FormListOperation` | 获取列表操作
|
|
71
|
-
| subscribe | `(namePath?: NamePath, callback?: () => void) => () => void` | 订阅字段值变化,不传 namePath 监听所有字段
|
|
52
|
+
| 属性名 | 类型 | 描述 |
|
|
53
|
+
| --------------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
|
|
54
|
+
| getFieldValidate | `(name: Name) => ValidateMessage \| null` | 获取字段验证(异步校验未完成时可能读到旧值,最终会随 onStoreChange 更新) |
|
|
55
|
+
| getFieldStatus | `(name: NamePath) => FieldStatusData \| null` | 获取字段当前展示状态;规则校验错误优先展示,其余情况手动设置的状态优先于校验结果 |
|
|
56
|
+
| setFieldStatus | `(name: NamePath, status: FieldStatusData \| null) => void` | 动态设置字段状态和提示,传入 `null` 清除;仅 `blocking: true` 的 error 会阻止提交 |
|
|
57
|
+
| getFieldValue | `(name: Name) => StoreValue` | 获取字段值 |
|
|
58
|
+
| submit | `() => Promise<ValidateMessage[]>` | 提交表单(异步,校验完成后才触发 onFinish) |
|
|
59
|
+
| getFieldsValue | `() => Values` | 获取所有字段值 |
|
|
60
|
+
| setFieldsValue | `(newStore: Store, trigger?: TRIGGER) => void` | 设置字段值 |
|
|
61
|
+
| setCallbacks | `(callbacks: Callbacks) => void` | 设置回调 |
|
|
62
|
+
| resetFields | `(name?: Name[]) => void` | 重置字段(值与校验状态;指定 name 时只影响相关字段) |
|
|
63
|
+
| clearFields | `(name?: Name[]) => void` | 清空字段(值与校验状态;指定 name 时只影响相关字段) |
|
|
64
|
+
| validateField | `(name: Name, trigger?: 'onChange' \| 'onBlur') => Promise<ValidateMessage[]>` | 校验单个字段 |
|
|
65
|
+
| validateFields | `(names?: Name[], trigger?: TRIGGER) => Promise<ValidateMessage[]>` | 校验多个字段 |
|
|
66
|
+
| getCallbacks | `() => Callbacks` | 获取回调 |
|
|
67
|
+
| registerFieldEntities | `(entity: FieldEntity) => void` | 注册字段实体 |
|
|
68
|
+
| initialize | `({ initialValues, callbacks }: { initialValues?: Store; callbacks?: Callbacks }) => void` | 初始化表单 |
|
|
69
|
+
| getListFields | `(name: NamePath) => FormListField[]` | 获取列表字段 |
|
|
70
|
+
| getListOperations | `(name: NamePath) => FormListOperation` | 获取列表操作 |
|
|
71
|
+
| subscribe | `(namePath?: NamePath, callback?: () => void) => () => void` | 订阅字段值变化,不传 namePath 监听所有字段 |
|
|
72
72
|
|
|
73
73
|
### Form 静态方法
|
|
74
74
|
|
|
75
|
-
| 方法名
|
|
76
|
-
|
|
|
77
|
-
| Form.useForm
|
|
78
|
-
| Form.useWatch
|
|
79
|
-
| Form.useFormInstance | `() => FormInstance`
|
|
75
|
+
| 方法名 | 类型 | 描述 |
|
|
76
|
+
| -------------------- | -------------------------------------------------------------- | ------------------------------------------------------ |
|
|
77
|
+
| Form.useForm | `(form?: FormInstance) => [FormInstance]` | 创建 Form 实例,传入外部 form 可受控使用 |
|
|
78
|
+
| Form.useWatch | `(namePath?: NamePath, form?: FormInstance) => T \| undefined` | 监听表单字段值变化,不传 namePath 返回所有值 |
|
|
79
|
+
| Form.useFormInstance | `() => FormInstance` | 获取当前上下文中最近的 Form 实例,须在 `<Form>` 内调用 |
|
|
80
80
|
|
|
81
81
|
### Field.GroupProps
|
|
82
82
|
|
|
@@ -92,36 +92,36 @@ toc: 'content'
|
|
|
92
92
|
|
|
93
93
|
### FieldProps
|
|
94
94
|
|
|
95
|
-
| 属性名 | 类型
|
|
96
|
-
| ------------- |
|
|
97
|
-
| className | `string`
|
|
98
|
-
| style | `React.CSSProperties`
|
|
99
|
-
| classNames | `Partial<Record<'label' \| 'control', string>>`
|
|
100
|
-
| styles | `Partial<Record<'label' \| 'control', React.CSSProperties>>`
|
|
101
|
-
| children | `React.ReactElement`
|
|
102
|
-
| name | `NamePath`
|
|
103
|
-
| rules | [Rule\[\]](#rule)
|
|
104
|
-
| label | `React.ReactNode`
|
|
95
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
96
|
+
| ------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | --------- |
|
|
97
|
+
| className | `string` | 自定义字段根类名 | - |
|
|
98
|
+
| style | `React.CSSProperties` | 自定义字段根样式 | - |
|
|
99
|
+
| classNames | `Partial<Record<'label' \| 'control', string>>` | 语义化结构类名 | - |
|
|
100
|
+
| styles | `Partial<Record<'label' \| 'control', React.CSSProperties>>` | 语义化结构样式 | - |
|
|
101
|
+
| children | `React.ReactElement` | 子元素 | - |
|
|
102
|
+
| name | `NamePath` | 字段名 | - |
|
|
103
|
+
| rules | [Rule\[\]](#rule) | 校验规则 | - |
|
|
104
|
+
| label | `React.ReactNode` | 标签 | - |
|
|
105
105
|
| tooltip | `ReactNode \| (Omit<TooltipProps, 'children'> & { icon?: ReactNode })` | 标签旁的帮助提示。传字符串/节点使用默认图标;传对象时可自定义 `icon`,其余属性透传给 Tooltip(`title`、`color`、`placement` 等) | - |
|
|
106
|
-
| required | `boolean`
|
|
107
|
-
| disabled | `boolean`
|
|
108
|
-
| initialValue | `unknown`
|
|
109
|
-
| valuePropName | `string`
|
|
106
|
+
| required | `boolean` | 是否必填 | - |
|
|
107
|
+
| disabled | `boolean` | 是否禁用 | - |
|
|
108
|
+
| initialValue | `unknown` | 初始值 | - |
|
|
109
|
+
| valuePropName | `string` | 设置子组件值的属性名 | `'value'` |
|
|
110
110
|
|
|
111
111
|
### Rule
|
|
112
112
|
|
|
113
|
-
| 属性名 | 类型 | 描述
|
|
114
|
-
| --------------- | ------------------------------------------------------------------------------------- |
|
|
115
|
-
| required | `boolean` | 是否必填
|
|
116
|
-
| type | `string` | 类型
|
|
117
|
-
| min | `number` | 最小值
|
|
118
|
-
| max | `number` | 最大值
|
|
119
|
-
| minLength | `number` | 最小长度
|
|
120
|
-
| maxLength | `number` | 最大长度
|
|
121
|
-
| regexp | `RegExp` | 正则表达式
|
|
122
|
-
| message | `string` | 错误信息
|
|
123
|
-
| validator | `(value: unknown) => boolean \| void \| Promise<boolean \| void>`
|
|
124
|
-
| validateTrigger | `'onBlur' \| 'onChange' \| 'onSubmit' \| Array<'onBlur' \| 'onChange' \| 'onSubmit'>` | 校验触发时机
|
|
113
|
+
| 属性名 | 类型 | 描述 |
|
|
114
|
+
| --------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
115
|
+
| required | `boolean` | 是否必填 |
|
|
116
|
+
| type | `string` | 类型 |
|
|
117
|
+
| min | `number` | 最小值 |
|
|
118
|
+
| max | `number` | 最大值 |
|
|
119
|
+
| minLength | `number` | 最小长度 |
|
|
120
|
+
| maxLength | `number` | 最大长度 |
|
|
121
|
+
| regexp | `RegExp` | 正则表达式 |
|
|
122
|
+
| message | `string` | 错误信息 |
|
|
123
|
+
| validator | `(value: unknown) => boolean \| void \| Promise<boolean \| void>` | 自定义校验函数,支持同步与异步。同步返回 `false` 或 `throw` 表示失败;异步 `resolve(false)`/`reject`/`throw` 表示失败。`throw`/`reject` 时 `error.message` 覆盖 `message` |
|
|
124
|
+
| validateTrigger | `'onBlur' \| 'onChange' \| 'onSubmit' \| Array<'onBlur' \| 'onChange' \| 'onSubmit'>` | 校验触发时机 |
|
|
125
125
|
|
|
126
126
|
### Types
|
|
127
127
|
|
|
@@ -131,8 +131,8 @@ toc: 'content'
|
|
|
131
131
|
| Store | `Record<string, StoreValue>` |
|
|
132
132
|
| Name | `string` |
|
|
133
133
|
| NamePath | `string \| string[] \| number \| (string \| number)[]` |
|
|
134
|
-
| FieldStatus | `'error' \| 'success' \| 'warning' \| 'info'`
|
|
135
|
-
| FieldStatusData | `{ status: FieldStatus; message?: string; blocking?: boolean }`
|
|
134
|
+
| FieldStatus | `'error' \| 'success' \| 'warning' \| 'info'` |
|
|
135
|
+
| FieldStatusData | `{ status: FieldStatus; message?: string; blocking?: boolean }` |
|
|
136
136
|
| ValidateMessage | `{ name: NamePath \| NamePath[] \| undefined; message: string; value: unknown; status: 'error' \| 'success' \| 'warning' \| 'info' }` |
|
|
137
137
|
| FieldEntity | `{ props: fieldProps & { name?: NamePath }; onStoreChange: () => void }` |
|
|
138
138
|
| TRIGGER | `'onChange' \| 'onBlur' \| 'onSubmit' \| 'reset' \| 'clear' \| 'update'` |
|
package/src/Form/interface.ts
CHANGED
|
@@ -2,6 +2,11 @@ import type { TooltipProps } from '../Tooltip';
|
|
|
2
2
|
import type { DataAttributeProps } from '../utils/types';
|
|
3
3
|
|
|
4
4
|
export type StoreValue = any;
|
|
5
|
+
/**
|
|
6
|
+
* Form values keyed by field name. Nested-path fields (e.g.
|
|
7
|
+
* name="user.name") hold their values in nested objects:
|
|
8
|
+
* `{ user: { name: 'tom' } }`
|
|
9
|
+
*/
|
|
5
10
|
export type Store = Record<string, StoreValue>;
|
|
6
11
|
export type Name = string;
|
|
7
12
|
export type NamePath = string | string[] | number | (string | number)[];
|
|
@@ -41,7 +46,9 @@ export interface FormProps<Values = any> extends DataAttributeProps {
|
|
|
41
46
|
*/
|
|
42
47
|
disabled?: boolean;
|
|
43
48
|
/**
|
|
44
|
-
* Initial values
|
|
49
|
+
* Initial values, keyed by field name. Nested-path fields (e.g.
|
|
50
|
+
* name="user.name") take their values from nested objects:
|
|
51
|
+
* `{ user: { name: 'tom' } }`
|
|
45
52
|
*/
|
|
46
53
|
initialValues?: Store;
|
|
47
54
|
/**
|
|
@@ -90,7 +97,7 @@ export interface Callbacks<Values = any> {
|
|
|
90
97
|
/**
|
|
91
98
|
* Triggered on failed form submit
|
|
92
99
|
* */
|
|
93
|
-
onFinishFailed?: (
|
|
100
|
+
onFinishFailed?: (errors: ValidateMessage[]) => void;
|
|
94
101
|
/**
|
|
95
102
|
* Triggered on form reset
|
|
96
103
|
* */
|
package/src/Form/utils/path.ts
CHANGED
|
@@ -62,7 +62,8 @@ export function setValueByPath(
|
|
|
62
62
|
|
|
63
63
|
for (let i = 0; i < path.length - 1; i++) {
|
|
64
64
|
const key = String(path[i]);
|
|
65
|
-
|
|
65
|
+
// eslint-disable-next-line eqeqeq
|
|
66
|
+
if (current[key] == null) {
|
|
66
67
|
// 根据下一个键的类型创建容器
|
|
67
68
|
current[key] = typeof path[i + 1] === 'number' ? [] : {};
|
|
68
69
|
}
|
|
@@ -78,6 +78,23 @@ const TreeSelect = <T extends Record<string, unknown> = any>(
|
|
|
78
78
|
[dataSource, mergedFieldNames],
|
|
79
79
|
);
|
|
80
80
|
|
|
81
|
+
// itemMap 以 uid(Tree 内部的路径键)为键,仅根节点 uid === key。
|
|
82
|
+
// 选中项展示 / getNodes 需要按外部 value(raw key)查找,否则嵌套节点
|
|
83
|
+
// 查不到会走 Selector 的孤儿值回退,直接显示 value 本身
|
|
84
|
+
const keyItemMap = useMemo(() => {
|
|
85
|
+
const map = new Map<
|
|
86
|
+
string,
|
|
87
|
+
{ key: string | number; label: string; original: T }
|
|
88
|
+
>();
|
|
89
|
+
itemMap.forEach((item) => {
|
|
90
|
+
const k = String(item.key);
|
|
91
|
+
if (!map.has(k)) {
|
|
92
|
+
map.set(k, item);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return map;
|
|
96
|
+
}, [itemMap]);
|
|
97
|
+
|
|
81
98
|
// Filter data source for searching
|
|
82
99
|
const filteredDataSource = useMemo(() => {
|
|
83
100
|
const sourceArray = Array.isArray(dataSource) ? dataSource : [dataSource];
|
|
@@ -125,7 +142,7 @@ const TreeSelect = <T extends Record<string, unknown> = any>(
|
|
|
125
142
|
const selectedOptions = useMemo(() => {
|
|
126
143
|
return mergedValue
|
|
127
144
|
.map((key: string | number) => {
|
|
128
|
-
const item =
|
|
145
|
+
const item = keyItemMap.get(String(key));
|
|
129
146
|
if (!item) return null;
|
|
130
147
|
|
|
131
148
|
const label =
|
|
@@ -140,7 +157,7 @@ const TreeSelect = <T extends Record<string, unknown> = any>(
|
|
|
140
157
|
};
|
|
141
158
|
})
|
|
142
159
|
.filter(Boolean);
|
|
143
|
-
}, [mergedValue,
|
|
160
|
+
}, [mergedValue, keyItemMap, optionLabelProp]);
|
|
144
161
|
|
|
145
162
|
const getNodes = (keys: string | number | Array<string | number>) => {
|
|
146
163
|
if (keys === '' || keys === null) {
|
|
@@ -151,10 +168,10 @@ const TreeSelect = <T extends Record<string, unknown> = any>(
|
|
|
151
168
|
return [];
|
|
152
169
|
}
|
|
153
170
|
return keys
|
|
154
|
-
.map((key) =>
|
|
171
|
+
.map((key) => keyItemMap.get(String(key))?.original)
|
|
155
172
|
.filter((node): node is T => node !== undefined);
|
|
156
173
|
}
|
|
157
|
-
return
|
|
174
|
+
return keyItemMap.get(String(keys))?.original;
|
|
158
175
|
};
|
|
159
176
|
|
|
160
177
|
const handleSelect = (selectedKeys: Array<string | number>) => {
|