@fairys/valtio-form-basic 0.0.8 → 0.0.9
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/esm/form/form.d.ts +6 -2
- package/esm/form/form.item.d.ts +84 -19
- package/esm/form/form.item.js +103 -18
- package/esm/form/hooks/index.d.ts +34 -0
- package/esm/form/hooks/index.js +57 -0
- package/esm/form/instance/index.d.ts +14 -6
- package/esm/form/instance/index.js +47 -23
- package/esm/form/layout.d.ts +12 -3
- package/esm/form/layout.js +17 -8
- package/esm/form/utils/index.d.ts +24 -0
- package/esm/form/utils/index.js +60 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/styles/index.css +9 -5
- package/lib/index.js +21 -12
- package/package.json +2 -2
- package/src/form/form.item.tsx +204 -36
- package/src/form/form.tsx +2 -17
- package/src/form/hooks/index.tsx +78 -0
- package/src/form/instance/index.ts +57 -35
- package/src/form/layout.tsx +28 -10
- package/src/form/utils/index.ts +108 -0
- package/src/index.tsx +1 -0
- package/src/styles/index.css +10 -4
package/esm/form/form.d.ts
CHANGED
|
@@ -2,13 +2,14 @@ import { MObject } from '../interface';
|
|
|
2
2
|
import { FairysValtioFormInstance } from './instance';
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
4
|
import { FairysValtioFormLayoutAttrsProps } from './layout';
|
|
5
|
+
import { RuleItem } from 'async-validator';
|
|
5
6
|
export interface FairysValtioFormAttrsProps<T extends MObject<T> = object> extends FairysValtioFormLayoutAttrsProps {
|
|
6
7
|
/**表单实例*/
|
|
7
8
|
form?: FairysValtioFormInstance<T>;
|
|
8
9
|
/**子元素*/
|
|
9
10
|
children: ReactNode;
|
|
10
11
|
/**表单项规则*/
|
|
11
|
-
rules?:
|
|
12
|
+
rules?: Record<PropertyKey, RuleItem[]>;
|
|
12
13
|
/**表单初始值*/
|
|
13
14
|
formData?: FairysValtioFormInstance<T>['state'];
|
|
14
15
|
/**表单隐藏状态*/
|
|
@@ -62,5 +63,8 @@ export declare function useFairysValtioForm<T extends MObject<T> = object>(props
|
|
|
62
63
|
formItemLabelStyle?: React.CSSProperties;
|
|
63
64
|
formItemBodyClassName?: string;
|
|
64
65
|
formItemBodyStyle?: React.CSSProperties;
|
|
65
|
-
|
|
66
|
+
itemBorderType?: "bottom" | "body";
|
|
67
|
+
itemBorderColor?: React.CSSProperties["borderColor"];
|
|
68
|
+
isInvalidBorderRed?: boolean;
|
|
69
|
+
showColon?: boolean;
|
|
66
70
|
};
|
package/esm/form/form.item.d.ts
CHANGED
|
@@ -3,9 +3,21 @@ import { MObject } from '../interface';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { FairysValtioFormInstance } from './instance';
|
|
5
5
|
import { FairysValtioFormLayoutContextOptions } from './layout';
|
|
6
|
+
import { FairysValtioFormParentAttrs } from './hooks';
|
|
7
|
+
import { RuleItem } from 'async-validator';
|
|
6
8
|
export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* 表单项名称 ,字段需要和存储的字段路径一致
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* 路径中的值为 number 类型时,会创建一个空数组。路径中的值为 string 类型时,会创建一个空对象。最后一个直接赋值
|
|
14
|
+
*
|
|
15
|
+
* 默认:"name"
|
|
16
|
+
* 嵌套字段:"name.a.doc" ===> { name: { a: { doc: undefined } } }
|
|
17
|
+
* 嵌套字段:"name[1].a.doc" ===> { name: [{}, { a: { doc: undefined } }] }
|
|
18
|
+
* 嵌套字段:"name.a[2].doc" ===> { name: { a: [{}, {}, { doc: undefined }] } }
|
|
19
|
+
*/
|
|
20
|
+
name?: string;
|
|
9
21
|
/**表单项标签*/
|
|
10
22
|
label?: string;
|
|
11
23
|
/**传递组件字段*/
|
|
@@ -48,9 +60,17 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
|
|
|
48
60
|
/**是否显示冒号*/
|
|
49
61
|
showColon?: boolean;
|
|
50
62
|
/**底部显示边框*/
|
|
51
|
-
|
|
63
|
+
itemBorderType?: FairysValtioFormLayoutContextOptions['itemBorderType'];
|
|
64
|
+
/**边框颜色*/
|
|
65
|
+
itemBorderColor?: React.CSSProperties['borderColor'];
|
|
66
|
+
/**是否校验失败时显示红色边框*/
|
|
67
|
+
isInvalidBorderRed?: boolean;
|
|
52
68
|
/**输入框属性*/
|
|
53
69
|
attrs?: any;
|
|
70
|
+
/**是否拼接父级字段名*/
|
|
71
|
+
isJoinParentField?: boolean;
|
|
72
|
+
/**校验规则*/
|
|
73
|
+
rules?: RuleItem[];
|
|
54
74
|
}
|
|
55
75
|
/**
|
|
56
76
|
* 处理表单表单项属性
|
|
@@ -59,7 +79,7 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
|
|
|
59
79
|
*
|
|
60
80
|
* ```tsx
|
|
61
81
|
import { Fragment } from 'react'
|
|
62
|
-
import { useFairysValtioFormItemAttrs } from "@fairys/valtio-form"
|
|
82
|
+
import { useFairysValtioFormItemAttrs , FairysValtioFormParentAttrsContext } from "@fairys/valtio-form"
|
|
63
83
|
import type { FairysValtioFormItemAttrsProps } from "@fairys/valtio-form"
|
|
64
84
|
export interface FormItemProps extends FairysValtioFormItemAttrsProps{}
|
|
65
85
|
|
|
@@ -68,10 +88,11 @@ export const FormItem = (props: FormItemProps) => {
|
|
|
68
88
|
const {
|
|
69
89
|
itemClassName, itemStyle, containerClassName, itemLabelClassName, itemLabelStyle,
|
|
70
90
|
itemBodyClassName, itemBodyStyle, itemInputClassName, itemExtraClassName, errorClassName, helpClassName,
|
|
71
|
-
isInvalid,
|
|
91
|
+
isInvalid, itemBorderType, children, error,formAttrsNameInstance
|
|
72
92
|
} = useFairysValtioFormItemAttrs(props)
|
|
73
93
|
|
|
74
94
|
return (
|
|
95
|
+
<FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
|
|
75
96
|
<View className={itemClassName} style={itemStyle}>
|
|
76
97
|
<View className={containerClassName}>
|
|
77
98
|
<View className={itemLabelClassName} style={itemLabelStyle}>
|
|
@@ -82,12 +103,13 @@ export const FormItem = (props: FormItemProps) => {
|
|
|
82
103
|
{children}
|
|
83
104
|
</View>
|
|
84
105
|
{extra ? <View className={itemExtraClassName}>{extra}</View> : <Fragment />}
|
|
85
|
-
{
|
|
106
|
+
{itemBorderType === 'body' && isInvalid ? <View className={errorClassName}>{error}</View> : <Fragment />}
|
|
86
107
|
</View>
|
|
87
108
|
</View>
|
|
88
109
|
{helpText ? <View className={helpClassName}>{helpText}</View> : <Fragment />}
|
|
89
|
-
{isInvalid &&
|
|
110
|
+
{isInvalid && itemBorderType !== 'body' ? <View className={errorClassName}>{error}</View> : <Fragment />}
|
|
90
111
|
</View>
|
|
112
|
+
</FairysValtioFormParentAttrsContext.Provider>
|
|
91
113
|
);
|
|
92
114
|
}
|
|
93
115
|
* ```
|
|
@@ -98,31 +120,41 @@ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object>
|
|
|
98
120
|
/**表单项值*/
|
|
99
121
|
value?: any;
|
|
100
122
|
/**是否校验错误*/
|
|
101
|
-
isInvalid
|
|
123
|
+
isInvalid: boolean;
|
|
102
124
|
/**边框类型*/
|
|
103
|
-
|
|
125
|
+
itemBorderType: FairysValtioFormLayoutContextOptions['itemBorderType'];
|
|
104
126
|
/**值改变事件*/
|
|
105
|
-
onValueChange
|
|
127
|
+
onValueChange: (event: any) => void;
|
|
106
128
|
/**当前表单项占据列数*/
|
|
107
|
-
colSpan
|
|
129
|
+
colSpan: number;
|
|
108
130
|
/**当前表单项占据行数*/
|
|
109
|
-
rowSpan
|
|
131
|
+
rowSpan: number;
|
|
110
132
|
/**列数*/
|
|
111
|
-
colCount
|
|
133
|
+
colCount: number;
|
|
112
134
|
/**标签显示模式*/
|
|
113
|
-
labelMode
|
|
135
|
+
labelMode: FairysValtioFormLayoutContextOptions['labelMode'];
|
|
114
136
|
/**错误提示位置*/
|
|
115
|
-
errorLayout
|
|
137
|
+
errorLayout: FairysValtioFormLayoutContextOptions['errorLayout'];
|
|
116
138
|
/**是否必填*/
|
|
117
|
-
isRequired
|
|
139
|
+
isRequired: boolean;
|
|
118
140
|
/**表单状态*/
|
|
119
|
-
state
|
|
141
|
+
state: T;
|
|
120
142
|
/**错误状态*/
|
|
121
|
-
errorState
|
|
143
|
+
errorState: Record<PropertyKey, string[]>;
|
|
122
144
|
/**表单实例*/
|
|
123
|
-
formInstance
|
|
145
|
+
formInstance: FairysValtioFormInstance<T>;
|
|
124
146
|
/**错误信息*/
|
|
125
147
|
error?: string[];
|
|
148
|
+
/**拼接父级字段名后得到的表单项名称*/
|
|
149
|
+
_name?: string;
|
|
150
|
+
/**表单项名称*/
|
|
151
|
+
name?: string;
|
|
152
|
+
/**表单项路径*/
|
|
153
|
+
paths?: (string | number)[];
|
|
154
|
+
/**父级字段名*/
|
|
155
|
+
parentName?: string;
|
|
156
|
+
/**表单属性名实例*/
|
|
157
|
+
formAttrsNameInstance: FairysValtioFormParentAttrs;
|
|
126
158
|
/**表单项类名*/
|
|
127
159
|
itemClassName: string;
|
|
128
160
|
/**表单项样式*/
|
|
@@ -148,3 +180,36 @@ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object>
|
|
|
148
180
|
/**子元素*/
|
|
149
181
|
children?: React.ReactNode;
|
|
150
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* 没有样式的表单项属性,仅返回基础输入组件参数
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
*
|
|
188
|
+
*```tsx
|
|
189
|
+
import { Fragment } from 'react'
|
|
190
|
+
import { useFairysValtioFormItemAttrs, FairysValtioFormParentAttrsContext } from "@fairys/valtio-form"
|
|
191
|
+
import type { FairysValtioFormItemAttrsProps } from "@fairys/valtio-form"
|
|
192
|
+
export interface FormItemProps extends FairysValtioFormItemAttrsProps{}
|
|
193
|
+
|
|
194
|
+
export const FormItem = (props: FormItemProps) => {
|
|
195
|
+
const { children , formAttrsNameInstance } = useFairysValtioFormItemNoStyleAttrs(props)
|
|
196
|
+
return <FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
|
|
197
|
+
{children}
|
|
198
|
+
</FairysValtioFormParentAttrsContext.Provider>
|
|
199
|
+
}
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
export declare function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>): {
|
|
203
|
+
value: unknown;
|
|
204
|
+
error: string[];
|
|
205
|
+
onValueChange: (event: any) => void;
|
|
206
|
+
state: T;
|
|
207
|
+
errorState: Record<PropertyKey, string[]>;
|
|
208
|
+
formInstance: FairysValtioFormInstance<T>;
|
|
209
|
+
_name: string;
|
|
210
|
+
name: string;
|
|
211
|
+
paths: (number | symbol)[] | (string | number)[];
|
|
212
|
+
parentName: string;
|
|
213
|
+
formAttrsNameInstance: FairysValtioFormParentAttrs;
|
|
214
|
+
children: string | number | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode>;
|
|
215
|
+
};
|
package/esm/form/form.item.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import react, { useMemo } from "react";
|
|
1
|
+
import react, { useEffect, useMemo } from "react";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { useFairysValtioFormInstanceContextState } from "./instance/index.js";
|
|
4
4
|
import { useFairysValtioFormLayoutContext } from "./layout.js";
|
|
5
|
+
import { useFairysValtioFormAttrsName } from "./hooks/index.js";
|
|
6
|
+
import { get } from "./utils/index.js";
|
|
5
7
|
function useFairysValtioFormItemAttrs(props) {
|
|
6
8
|
const [layoutAttrs] = useFairysValtioFormLayoutContext();
|
|
7
9
|
const colCount = layoutAttrs.colCount || 1;
|
|
8
|
-
const parent_borderedType = layoutAttrs.
|
|
10
|
+
const parent_borderedType = layoutAttrs.itemBorderType || 'bottom';
|
|
9
11
|
const parent_errorLayout = layoutAttrs.errorLayout || 'right-bottom';
|
|
10
12
|
const parent_formItemClassName = layoutAttrs.formItemClassName;
|
|
11
13
|
const parent_formItemLabelClassName = layoutAttrs.formItemLabelClassName;
|
|
@@ -14,20 +16,34 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
14
16
|
const parent_formItemBodyClassName = layoutAttrs.formItemBodyClassName;
|
|
15
17
|
const parent_formItemBodyStyle = layoutAttrs.formItemBodyStyle;
|
|
16
18
|
const parent_labelMode = layoutAttrs.labelMode || 'between';
|
|
17
|
-
const
|
|
19
|
+
const parent_itemBorderColor = layoutAttrs.itemBorderColor;
|
|
20
|
+
const parent_isInvalidBorderRed = layoutAttrs.isInvalidBorderRed;
|
|
21
|
+
const parent_showColon = layoutAttrs.showColon;
|
|
22
|
+
const { name, valuePropName = 'value', getValueFromEvent, formatValue, onAfterUpdate, trigger = 'onChange', className, style, labelClassName, labelStyle, bodyClassName, bodyStyle, children, labelMode = parent_labelMode, errorLayout = parent_errorLayout, colSpan = 1, rowSpan = 1, isRequired: _isRequired, itemBorderType = parent_borderedType, attrs = {}, showColon = parent_showColon, itemBorderColor = parent_itemBorderColor, isInvalidBorderRed = parent_isInvalidBorderRed, isJoinParentField = true, rules } = props;
|
|
23
|
+
const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
|
|
24
|
+
name,
|
|
25
|
+
isJoinParentField
|
|
26
|
+
});
|
|
18
27
|
const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
const value = useMemo(()=>get(state, paths), [
|
|
29
|
+
state,
|
|
30
|
+
paths
|
|
31
|
+
]);
|
|
32
|
+
const error = errorState[_name];
|
|
33
|
+
formInstance.nameToPaths[_name] = paths;
|
|
34
|
+
if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
|
|
35
|
+
useEffect(()=>()=>{
|
|
36
|
+
formInstance.removeRules(_name);
|
|
37
|
+
}, [
|
|
38
|
+
_name
|
|
39
|
+
]);
|
|
22
40
|
const onValueChange = (event)=>{
|
|
23
41
|
let value = event;
|
|
24
42
|
const target = event?.detail || event?.target;
|
|
25
43
|
if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
|
|
26
44
|
else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
|
|
27
45
|
if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
|
|
28
|
-
formInstance.
|
|
29
|
-
[name]: value
|
|
30
|
-
});
|
|
46
|
+
formInstance.updatedValueByPaths(_name, value);
|
|
31
47
|
if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
|
|
32
48
|
};
|
|
33
49
|
const baseControl = {
|
|
@@ -51,13 +67,17 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
51
67
|
error
|
|
52
68
|
]);
|
|
53
69
|
const item_cls = useMemo(()=>clsx('fairys-valtio-form-item fairystaroform__p-_zkh1_4px_zhk2_ fairystaroform__text-_zkh1_12px_zhk2_ fairystaroform__relative fairystaroform__flex fairystaroform__flex-col fairystaroform__box-border fairystaroform__break-all', {
|
|
54
|
-
'
|
|
70
|
+
'fairys-valtio-form-item-invalid': isInvalid,
|
|
71
|
+
'fairys-valtio-form-item-invalid-border-red': isInvalid && isInvalidBorderRed && 'bottom' === itemBorderType,
|
|
72
|
+
'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200': 'bottom' === itemBorderType,
|
|
55
73
|
[labelMode]: labelMode
|
|
56
|
-
},
|
|
74
|
+
}, parent_formItemClassName, className), [
|
|
57
75
|
className,
|
|
58
76
|
parent_formItemClassName,
|
|
59
77
|
labelMode,
|
|
60
|
-
|
|
78
|
+
itemBorderType,
|
|
79
|
+
isInvalid,
|
|
80
|
+
isInvalidBorderRed
|
|
61
81
|
]);
|
|
62
82
|
const itemContainer_cls = useMemo(()=>clsx('fairys-valtio-form-item-container fairystaroform__flex-1 fairystaroform__h-full fairystaroform__flex fairystaroform__box-border', {
|
|
63
83
|
'fairystaroform__flex-row fairystaroform__items-center fairystaroform__justify-between fairystaroform__gap-_zkh1_8px_zhk2_': 'between' === labelMode,
|
|
@@ -83,12 +103,15 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
83
103
|
'fairystaroform__flex-row fairystaroform__justify-start': 'left' === labelMode,
|
|
84
104
|
'fairystaroform__flex-row fairystaroform__justify-end': 'between' === labelMode || 'top' === labelMode,
|
|
85
105
|
'fairystaroform__flex-row': 'top' === labelMode,
|
|
86
|
-
'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' ===
|
|
87
|
-
|
|
106
|
+
'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' === itemBorderType,
|
|
107
|
+
'fairys-valtio-form-item-invalid-border-red': isInvalid && isInvalidBorderRed && 'body' === itemBorderType
|
|
108
|
+
}, parent_formItemBodyClassName, bodyClassName), [
|
|
88
109
|
bodyClassName,
|
|
89
110
|
labelMode,
|
|
90
|
-
|
|
91
|
-
parent_formItemBodyClassName
|
|
111
|
+
itemBorderType,
|
|
112
|
+
parent_formItemBodyClassName,
|
|
113
|
+
isInvalid,
|
|
114
|
+
isInvalidBorderRed
|
|
92
115
|
]);
|
|
93
116
|
const itemInput_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__flex fairystaroform__flex-row fairystaroform__flex-1 fairystaroform__box-border', {
|
|
94
117
|
'fairystaroform__justify-end fairystaroform__text-right': 'between' === labelMode,
|
|
@@ -122,7 +145,7 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
122
145
|
return {
|
|
123
146
|
value,
|
|
124
147
|
isInvalid,
|
|
125
|
-
|
|
148
|
+
itemBorderType,
|
|
126
149
|
onValueChange,
|
|
127
150
|
colSpan,
|
|
128
151
|
rowSpan,
|
|
@@ -134,8 +157,16 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
134
157
|
errorState,
|
|
135
158
|
formInstance,
|
|
136
159
|
error,
|
|
160
|
+
_name,
|
|
161
|
+
name,
|
|
162
|
+
paths,
|
|
163
|
+
parentName,
|
|
164
|
+
formAttrsNameInstance,
|
|
137
165
|
itemClassName: item_cls,
|
|
138
166
|
itemStyle: {
|
|
167
|
+
...itemBorderColor && 'bottom' === itemBorderType ? {
|
|
168
|
+
borderBottomColor: itemBorderColor
|
|
169
|
+
} : {},
|
|
139
170
|
...parent_formItemStyle || {},
|
|
140
171
|
...styleBase,
|
|
141
172
|
...style || {}
|
|
@@ -148,6 +179,9 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
148
179
|
},
|
|
149
180
|
itemBodyClassName: itemBody_cls,
|
|
150
181
|
itemBodyStyle: {
|
|
182
|
+
...itemBorderColor && 'body' === itemBorderType ? {
|
|
183
|
+
borderBottomColor: itemBorderColor
|
|
184
|
+
} : {},
|
|
151
185
|
...parent_formItemBodyStyle || {},
|
|
152
186
|
...bodyStyle || {}
|
|
153
187
|
},
|
|
@@ -160,4 +194,55 @@ function useFairysValtioFormItemAttrs(props) {
|
|
|
160
194
|
}) : children
|
|
161
195
|
};
|
|
162
196
|
}
|
|
163
|
-
|
|
197
|
+
function useFairysValtioFormItemNoStyleAttrs(props) {
|
|
198
|
+
const { name, valuePropName = 'value', getValueFromEvent, formatValue, onAfterUpdate, trigger = 'onChange', children, attrs = {}, isJoinParentField = true, rules } = props;
|
|
199
|
+
const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
|
|
200
|
+
const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
|
|
201
|
+
name,
|
|
202
|
+
isJoinParentField
|
|
203
|
+
});
|
|
204
|
+
const value = useMemo(()=>get(state, paths), [
|
|
205
|
+
state,
|
|
206
|
+
paths
|
|
207
|
+
]);
|
|
208
|
+
const error = errorState[_name];
|
|
209
|
+
formInstance.nameToPaths[_name] = paths;
|
|
210
|
+
if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
|
|
211
|
+
useEffect(()=>()=>{
|
|
212
|
+
formInstance.removeRules(_name);
|
|
213
|
+
}, [
|
|
214
|
+
_name
|
|
215
|
+
]);
|
|
216
|
+
const onValueChange = (event)=>{
|
|
217
|
+
let value = event;
|
|
218
|
+
const target = event?.detail || event?.target;
|
|
219
|
+
if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
|
|
220
|
+
else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
|
|
221
|
+
if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
|
|
222
|
+
formInstance.updatedValueByPaths(_name, value);
|
|
223
|
+
if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
|
|
224
|
+
};
|
|
225
|
+
const baseControl = {
|
|
226
|
+
...attrs,
|
|
227
|
+
name,
|
|
228
|
+
[valuePropName]: value,
|
|
229
|
+
[trigger]: onValueChange
|
|
230
|
+
};
|
|
231
|
+
return {
|
|
232
|
+
value,
|
|
233
|
+
error,
|
|
234
|
+
onValueChange,
|
|
235
|
+
state,
|
|
236
|
+
errorState,
|
|
237
|
+
formInstance,
|
|
238
|
+
_name,
|
|
239
|
+
name,
|
|
240
|
+
paths,
|
|
241
|
+
parentName,
|
|
242
|
+
formAttrsNameInstance,
|
|
243
|
+
children: /*#__PURE__*/ react.isValidElement(children) ? /*#__PURE__*/ react.cloneElement(children, {
|
|
244
|
+
...baseControl
|
|
245
|
+
}) : children
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
export { useFairysValtioFormItemAttrs, useFairysValtioFormItemNoStyleAttrs };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface FairysValtioFormParentAttrsState {
|
|
2
|
+
name?: string;
|
|
3
|
+
}
|
|
4
|
+
/***
|
|
5
|
+
* 父级属性
|
|
6
|
+
*/
|
|
7
|
+
export declare class FairysValtioFormParentAttrs {
|
|
8
|
+
state: FairysValtioFormParentAttrsState;
|
|
9
|
+
updated: (attrs: Record<string, any>) => void;
|
|
10
|
+
/***更新父级字段值*/
|
|
11
|
+
updatedName: (name?: string, parentName?: string) => void;
|
|
12
|
+
}
|
|
13
|
+
/**初始化父级属性*/
|
|
14
|
+
export declare const useFairysValtioFormParentAttrs: (instance?: FairysValtioFormParentAttrs) => FairysValtioFormParentAttrs;
|
|
15
|
+
/***父级属性上下文*/
|
|
16
|
+
export declare const FairysValtioFormParentAttrsContext: import("react").Context<FairysValtioFormParentAttrs>;
|
|
17
|
+
/***获取父级属性实例*/
|
|
18
|
+
export declare const useFairysValtioFormParentAttrsContext: () => FairysValtioFormParentAttrs;
|
|
19
|
+
/***获取父级属性状态*/
|
|
20
|
+
export declare const useFairysValtioFormParentAttrsState: () => readonly [{
|
|
21
|
+
readonly name?: string;
|
|
22
|
+
}, FairysValtioFormParentAttrs];
|
|
23
|
+
export interface FairysValtioFormAttrsNameOptions {
|
|
24
|
+
name?: string;
|
|
25
|
+
/**是否拼接父级字段名*/
|
|
26
|
+
isJoinParentField?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/***获取属性名和路径*/
|
|
29
|
+
export declare const useFairysValtioFormAttrsName: (options?: FairysValtioFormAttrsNameOptions) => {
|
|
30
|
+
formAttrsNameInstance: FairysValtioFormParentAttrs;
|
|
31
|
+
parentName: string;
|
|
32
|
+
name: string;
|
|
33
|
+
paths: (number | symbol)[] | (string | number)[];
|
|
34
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo, useRef } from "react";
|
|
2
|
+
import { proxy, useSnapshot } from "valtio";
|
|
3
|
+
import { formateName, formatePath } from "../utils/index.js";
|
|
4
|
+
class FairysValtioFormParentAttrs {
|
|
5
|
+
state = proxy({
|
|
6
|
+
name: ''
|
|
7
|
+
});
|
|
8
|
+
updated = (attrs)=>{
|
|
9
|
+
this.state = {
|
|
10
|
+
...this.state,
|
|
11
|
+
...attrs
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
updatedName = (name, parentName)=>{
|
|
15
|
+
this.state.name = formateName(name, parentName);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const useFairysValtioFormParentAttrs = (instance)=>{
|
|
19
|
+
const parentAttrs = useRef();
|
|
20
|
+
if (!parentAttrs.current) if (instance) parentAttrs.current = instance;
|
|
21
|
+
else parentAttrs.current = new FairysValtioFormParentAttrs();
|
|
22
|
+
return parentAttrs.current;
|
|
23
|
+
};
|
|
24
|
+
const FairysValtioFormParentAttrsContext = /*#__PURE__*/ createContext(new FairysValtioFormParentAttrs());
|
|
25
|
+
const useFairysValtioFormParentAttrsContext = ()=>useContext(FairysValtioFormParentAttrsContext);
|
|
26
|
+
const useFairysValtioFormParentAttrsState = ()=>{
|
|
27
|
+
const instance = useFairysValtioFormParentAttrsContext();
|
|
28
|
+
const state = useSnapshot(instance.state);
|
|
29
|
+
return [
|
|
30
|
+
state,
|
|
31
|
+
instance
|
|
32
|
+
];
|
|
33
|
+
};
|
|
34
|
+
const useFairysValtioFormAttrsName = (options = {})=>{
|
|
35
|
+
const { name, isJoinParentField = true } = options;
|
|
36
|
+
const formAttrsNameInstance = useFairysValtioFormParentAttrs();
|
|
37
|
+
const [state] = useFairysValtioFormParentAttrsState();
|
|
38
|
+
const parentName = state.name;
|
|
39
|
+
const _name = useMemo(()=>isJoinParentField ? formateName(name, parentName) : name, [
|
|
40
|
+
name,
|
|
41
|
+
parentName,
|
|
42
|
+
isJoinParentField
|
|
43
|
+
]);
|
|
44
|
+
const _paths = useMemo(()=>formatePath(_name), [
|
|
45
|
+
_name
|
|
46
|
+
]);
|
|
47
|
+
useMemo(()=>formAttrsNameInstance.updatedName(_name), [
|
|
48
|
+
_name
|
|
49
|
+
]);
|
|
50
|
+
return {
|
|
51
|
+
formAttrsNameInstance,
|
|
52
|
+
parentName,
|
|
53
|
+
name: _name,
|
|
54
|
+
paths: _paths
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export { FairysValtioFormParentAttrs, FairysValtioFormParentAttrsContext, useFairysValtioFormAttrsName, useFairysValtioFormParentAttrs, useFairysValtioFormParentAttrsContext, useFairysValtioFormParentAttrsState };
|
|
@@ -22,6 +22,11 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
|
|
|
22
22
|
* @param isValidate 是否验证(可选)
|
|
23
23
|
*/
|
|
24
24
|
updated: <M = T>(state: Partial<M>, isValidate?: boolean) => void;
|
|
25
|
+
/**根据路径设置值
|
|
26
|
+
* @param path 值路径
|
|
27
|
+
* @param value 值
|
|
28
|
+
*/
|
|
29
|
+
updatedValueByPaths: (path: PropertyKey, value: any) => void;
|
|
25
30
|
/**
|
|
26
31
|
* 更新行数据的隐藏信息
|
|
27
32
|
* @param objectHideInfo 行数据隐藏信息对象
|
|
@@ -44,12 +49,15 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
|
|
|
44
49
|
* 清理所有数据
|
|
45
50
|
*/
|
|
46
51
|
clear: () => void;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
/**由表单项挂载规则,(根据表单项的字段存储路径对应校验规则)*/
|
|
53
|
+
mountRules: Record<PropertyKey, RuleItem[]>;
|
|
54
|
+
/**移除表单项挂载规则*/
|
|
55
|
+
removeRules: (name: PropertyKey) => void;
|
|
56
|
+
/**表单项规则*/
|
|
57
|
+
rules: Record<PropertyKey, RuleItem[]>;
|
|
58
|
+
/**表单项名称到路径映射*/
|
|
59
|
+
nameToPaths: Record<PropertyKey, PropertyKey[]>;
|
|
60
|
+
/**验证表单项规则*/
|
|
53
61
|
validate: (fields?: PropertyKey[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
|
|
54
62
|
}
|
|
55
63
|
/**声明实例*/
|
|
@@ -2,6 +2,7 @@ import { createContext, useContext, useRef } from "react";
|
|
|
2
2
|
import { proxy, ref as external_valtio_ref, snapshot, useSnapshot } from "valtio";
|
|
3
3
|
import async_validator from "async-validator";
|
|
4
4
|
import { copy } from "fast-copy";
|
|
5
|
+
import { formatePath, get, set } from "../utils/index.js";
|
|
5
6
|
class FairysValtioFormInstance {
|
|
6
7
|
state = proxy({});
|
|
7
8
|
errorState = proxy({});
|
|
@@ -21,6 +22,12 @@ class FairysValtioFormInstance {
|
|
|
21
22
|
}
|
|
22
23
|
if (isValidate) this.validate(keys, false);
|
|
23
24
|
};
|
|
25
|
+
updatedValueByPaths = (path, value)=>{
|
|
26
|
+
set(this.state, formatePath(path), value);
|
|
27
|
+
this.validate([
|
|
28
|
+
path
|
|
29
|
+
], false);
|
|
30
|
+
};
|
|
24
31
|
updatedHideInfo = (objectHideInfo)=>{
|
|
25
32
|
const keys = Object.keys(objectHideInfo);
|
|
26
33
|
for(let index = 0; index < keys.length; index++){
|
|
@@ -60,36 +67,49 @@ class FairysValtioFormInstance {
|
|
|
60
67
|
this.errorState = proxy({});
|
|
61
68
|
this.hideState = proxy({});
|
|
62
69
|
};
|
|
70
|
+
mountRules = {};
|
|
71
|
+
removeRules = (name)=>{
|
|
72
|
+
delete this.mountRules[name];
|
|
73
|
+
};
|
|
63
74
|
rules = {};
|
|
75
|
+
nameToPaths = {};
|
|
64
76
|
validate = async (fields, isReturn = true)=>{
|
|
65
|
-
|
|
77
|
+
const rules = {
|
|
78
|
+
...this.rules,
|
|
79
|
+
...this.mountRules
|
|
80
|
+
};
|
|
66
81
|
const _formData = snapshot(this.state);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
...
|
|
86
|
-
}
|
|
82
|
+
const _values = {};
|
|
83
|
+
let _fields = Object.keys(rules);
|
|
84
|
+
let _lastRules = {};
|
|
85
|
+
let isPropsFields = false;
|
|
86
|
+
if (Array.isArray(fields) && fields.length) {
|
|
87
|
+
_fields = [
|
|
88
|
+
...fields
|
|
89
|
+
];
|
|
90
|
+
isPropsFields = true;
|
|
91
|
+
for(let index = 0; index < fields.length; index++){
|
|
92
|
+
const field = fields[index];
|
|
93
|
+
const paths = this.nameToPaths[field];
|
|
94
|
+
_lastRules[field] = rules[field];
|
|
95
|
+
_values[field] = get(_formData, paths ? paths : formatePath(field));
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
isPropsFields = false;
|
|
99
|
+
_lastRules = {
|
|
100
|
+
...rules
|
|
101
|
+
};
|
|
102
|
+
for(let index = 0; index < _fields.length; index++){
|
|
103
|
+
const field = _fields[index];
|
|
104
|
+
const paths = this.nameToPaths[field];
|
|
105
|
+
_values[field] = get(_formData, paths);
|
|
106
|
+
}
|
|
87
107
|
}
|
|
88
108
|
return new Promise((resolve, reject)=>{
|
|
89
109
|
new async_validator({
|
|
90
110
|
...rules
|
|
91
111
|
}).validate({
|
|
92
|
-
...
|
|
112
|
+
..._values
|
|
93
113
|
}, (errors, fields)=>{
|
|
94
114
|
for(let index = 0; index < _fields.length; index++){
|
|
95
115
|
const field = _fields[index];
|
|
@@ -101,7 +121,11 @@ class FairysValtioFormInstance {
|
|
|
101
121
|
errors,
|
|
102
122
|
fields
|
|
103
123
|
});
|
|
104
|
-
else resolve(
|
|
124
|
+
else isPropsFields ? resolve({
|
|
125
|
+
...fields
|
|
126
|
+
}) : resolve({
|
|
127
|
+
..._formData
|
|
128
|
+
});
|
|
105
129
|
});
|
|
106
130
|
});
|
|
107
131
|
};
|
package/esm/form/layout.d.ts
CHANGED
|
@@ -23,7 +23,13 @@ export interface FairysValtioFormLayoutContextOptions {
|
|
|
23
23
|
/**
|
|
24
24
|
* 底部边框类型
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
itemBorderType?: 'bottom' | 'body';
|
|
27
|
+
/**边框颜色*/
|
|
28
|
+
itemBorderColor?: React.CSSProperties['borderColor'];
|
|
29
|
+
/**是否校验失败时显示红色边框*/
|
|
30
|
+
isInvalidBorderRed?: boolean;
|
|
31
|
+
/**是否显示冒号*/
|
|
32
|
+
showColon?: boolean;
|
|
27
33
|
}
|
|
28
34
|
export interface FairysValtioFormLayoutAttrsProps extends FairysValtioFormLayoutContextOptions {
|
|
29
35
|
/**
|
|
@@ -2645,7 +2651,10 @@ export declare const useFairysValtioFormLayoutContext: () => readonly [{
|
|
|
2645
2651
|
readonly colorRendering?: import("csstype").Property.ColorRendering | undefined;
|
|
2646
2652
|
readonly glyphOrientationVertical?: import("csstype").Property.GlyphOrientationVertical | undefined;
|
|
2647
2653
|
};
|
|
2648
|
-
readonly
|
|
2654
|
+
readonly itemBorderType?: "bottom" | "body";
|
|
2655
|
+
readonly itemBorderColor?: React.CSSProperties["borderColor"];
|
|
2656
|
+
readonly isInvalidBorderRed?: boolean;
|
|
2657
|
+
readonly showColon?: boolean;
|
|
2649
2658
|
}, FairysValtioFormLayoutInstance];
|
|
2650
2659
|
/**
|
|
2651
2660
|
* 布局属性处理
|
|
@@ -2706,7 +2715,7 @@ export interface FairysValtioFormLayoutAttrsReturn {
|
|
|
2706
2715
|
/**
|
|
2707
2716
|
* 底部边框类型
|
|
2708
2717
|
*/
|
|
2709
|
-
|
|
2718
|
+
itemBorderType: string;
|
|
2710
2719
|
/**表单布局实例*/
|
|
2711
2720
|
formLayoutInstance: FairysValtioFormLayoutInstance;
|
|
2712
2721
|
/**布局ClassName*/
|