@fairys/rn-valtio-form-basic 0.0.12

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.
@@ -0,0 +1,135 @@
1
+ /**表单项*/
2
+
3
+ import { View, Text } from 'react-native';
4
+ import type { ViewProps } from 'react-native';
5
+ import { Fragment } from 'react';
6
+ import type { MObject } from '@fairys/valtio-form-basic';
7
+ import {
8
+ useFairysValtioFormInstanceContextHideState,
9
+ FairysValtioFormParentAttrsContext,
10
+ } from '@fairys/valtio-form-basic/esm/common';
11
+ import { formItemStyles } from './styles/form.item';
12
+ import type { FairysValtioFormItemAttrsProps } from './hooks/form.item';
13
+ import { useFairysValtioFormItemAttrs, useFairysValtioFormItemNoStyleAttrs } from 'hooks/form.item';
14
+
15
+ export interface FairysRNValtioFormItemProps<T extends MObject<T> = object>
16
+ extends Omit<ViewProps, 'style'>,
17
+ FairysValtioFormItemAttrsProps {
18
+ /**是否使用控制隐藏的表单项*/
19
+ isHide?: boolean;
20
+ /**是否使用无样式表单项*/
21
+ noStyle?: boolean;
22
+ }
23
+
24
+ /**普通表单项*/
25
+ export function FairysRNValtioFormItemBase<T extends MObject<T> = object>(
26
+ props: Omit<FairysRNValtioFormItemProps<T>, 'isHide' | 'noStyle'>,
27
+ ) {
28
+ const { label, extra, helpText } = props;
29
+ const {
30
+ itemStyle,
31
+ itemContainerStyle,
32
+ itemLabelStyle,
33
+ itemLabelTextStyle,
34
+ itemLabelShowColonStyle,
35
+ itemExtraStyle,
36
+ itemInputStyle,
37
+ itemBodyStyle,
38
+ isInvalid,
39
+ isRequired,
40
+ showColon,
41
+ formAttrsNameInstance,
42
+ itemBorderType,
43
+ errorStyle,
44
+ helpStyle,
45
+ error,
46
+ children,
47
+ } = useFairysValtioFormItemAttrs(props);
48
+ return (
49
+ <View style={itemStyle}>
50
+ <View style={itemContainerStyle}>
51
+ {label ? (
52
+ <View style={itemLabelStyle}>
53
+ {isRequired ? (
54
+ <Text style={formItemStyles['fairys-valtio-form-item-label.required']}>*</Text>
55
+ ) : (
56
+ <Fragment />
57
+ )}
58
+ <Text style={itemLabelTextStyle}>{label}</Text>
59
+ {showColon ? <Text style={itemLabelShowColonStyle}>:</Text> : <Fragment />}
60
+ </View>
61
+ ) : (
62
+ <Fragment />
63
+ )}
64
+ <View style={itemBodyStyle}>
65
+ <FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
66
+ <View style={itemInputStyle}>{children}</View>
67
+ </FairysValtioFormParentAttrsContext.Provider>
68
+ {extra ? (
69
+ <View style={itemExtraStyle}>
70
+ <Text style={formItemStyles['fairys-valtio-form-item-body-extra-text']}>{extra}</Text>
71
+ </View>
72
+ ) : (
73
+ <Fragment />
74
+ )}
75
+ {itemBorderType === 'body' && isInvalid ? (
76
+ <View style={errorStyle}>
77
+ <Text style={formItemStyles['fairys-valtio-form-item-body-error-text']}>{error}</Text>
78
+ </View>
79
+ ) : (
80
+ <Fragment />
81
+ )}
82
+ </View>
83
+ </View>
84
+ {helpText ? (
85
+ <View style={helpStyle}>
86
+ <Text>{helpText}</Text>
87
+ </View>
88
+ ) : (
89
+ <Fragment />
90
+ )}
91
+ {isInvalid && itemBorderType !== 'body' ? (
92
+ <View style={errorStyle}>
93
+ <Text style={formItemStyles['fairys-valtio-form-item-body-error-text']}>{error}</Text>
94
+ </View>
95
+ ) : (
96
+ <Fragment />
97
+ )}
98
+ </View>
99
+ );
100
+ }
101
+ /**控制隐藏的表单项*/
102
+ export function FairysRNValtioFormHideItem<T extends MObject<T> = object>(
103
+ props: Omit<FairysRNValtioFormItemProps<T>, 'isHide' | 'noStyle'>,
104
+ ) {
105
+ const [state] = useFairysValtioFormInstanceContextHideState();
106
+ const isHide = state[props.name];
107
+ if (isHide) {
108
+ return <Fragment />;
109
+ }
110
+ return <FairysRNValtioFormItemBase<T> {...props} />;
111
+ }
112
+
113
+ /**无样式表单项*/
114
+ export function FairysRNValtioFormItemNoStyle<T extends MObject<T> = object>(
115
+ props: Omit<FairysRNValtioFormItemProps<T>, 'isHide' | 'noStyle'>,
116
+ ) {
117
+ const { children, formAttrsNameInstance } = useFairysValtioFormItemNoStyleAttrs(props);
118
+ return (
119
+ <FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
120
+ {children}
121
+ </FairysValtioFormParentAttrsContext.Provider>
122
+ );
123
+ }
124
+
125
+ /**表单项基础组件(根据isHide和noStyle判断是否使用控制隐藏的表单项和无样式表单项)*/
126
+ export function FairysRNValtioFormItem<T extends MObject<T> = object>(props: FairysRNValtioFormItemProps<T>) {
127
+ const { isHide, noStyle, ...rest } = props;
128
+ if (isHide) {
129
+ return <FairysRNValtioFormHideItem<T> {...rest} />;
130
+ }
131
+ if (noStyle) {
132
+ return <FairysRNValtioFormItemNoStyle<T> {...rest} />;
133
+ }
134
+ return <FairysRNValtioFormItemBase<T> {...rest} />;
135
+ }
package/src/form.tsx ADDED
@@ -0,0 +1,38 @@
1
+ import { FairysRNValtioFormLayout } from './layout';
2
+ import { FairysRNValtioFormItem, FairysRNValtioFormHideItem, FairysRNValtioFormItemBase } from './form.item';
3
+ import {
4
+ FairysValtioFormInstanceContext,
5
+ useFairysValtioFormInstance,
6
+ useFairysValtioFormInstanceContext,
7
+ useFairysValtioFormInstanceContextState,
8
+ useFairysValtioFormInstanceContextHideState,
9
+ } from '@fairys/valtio-form-basic/esm/common';
10
+
11
+ import type { MObject } from '@fairys/valtio-form-basic/esm/common';
12
+ import type { FairysValtioFormAttrsProps } from 'hooks/form';
13
+ import { useFairysValtioForm } from 'hooks/form';
14
+
15
+ export interface FairysRNValtioFormProps<T extends MObject<T> = object> extends FairysValtioFormAttrsProps<T> {}
16
+
17
+ export function FairysRNValtioForm<T extends MObject<T> = object>(props: FairysRNValtioFormProps<T>) {
18
+ const { formInstance, children, ...rest } = useFairysValtioForm(props);
19
+ return (
20
+ <FairysValtioFormInstanceContext.Provider value={formInstance}>
21
+ <FairysRNValtioFormLayout {...rest}>{children}</FairysRNValtioFormLayout>
22
+ </FairysValtioFormInstanceContext.Provider>
23
+ );
24
+ }
25
+ /**初始化实例*/
26
+ FairysRNValtioForm.useForm = useFairysValtioFormInstance;
27
+ /**获取状态*/
28
+ FairysRNValtioForm.useFormState = useFairysValtioFormInstanceContextState;
29
+ /**获取隐藏状态*/
30
+ FairysRNValtioForm.useFormHideState = useFairysValtioFormInstanceContextHideState;
31
+ /**获取上下文实例*/
32
+ FairysRNValtioForm.useFormInstance = useFairysValtioFormInstanceContext;
33
+ /**表单项基础组件*/
34
+ FairysRNValtioForm.FormItemBase = FairysRNValtioFormItemBase;
35
+ /**表单项*/
36
+ FairysRNValtioForm.FormItem = FairysRNValtioFormItem;
37
+ /**隐藏表单想*/
38
+ FairysRNValtioForm.FormHideItem = FairysRNValtioFormHideItem;
@@ -0,0 +1,492 @@
1
+ /**表单项*/
2
+ import React, { useEffect, useMemo } from 'react';
3
+ import { StyleSheet, ViewProps } from 'react-native';
4
+ import type {
5
+ MObject,
6
+ FairysValtioFormItemAttrsProps as _FairysValtioFormItemAttrsProps,
7
+ } from '@fairys/valtio-form-basic';
8
+ import {
9
+ useFairysValtioFormInstanceContextState,
10
+ FairysValtioFormInstance,
11
+ get,
12
+ formatePath,
13
+ FairysValtioFormParentAttrs,
14
+ useFairysValtioFormAttrsName,
15
+ useId,
16
+ } from '@fairys/valtio-form-basic/esm/common';
17
+ import { formItemStyles } from 'styles/form.item';
18
+ import { FairysValtioFormLayoutContextOptions, useFairysValtioFormLayoutContext } from './layout';
19
+
20
+ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object>
21
+ extends Omit<
22
+ _FairysValtioFormItemAttrsProps<T>,
23
+ 'style' | 'labelStyle' | 'bodyStyle' | 'rowSpan' | 'className' | 'labelClassName' | 'bodyClassName'
24
+ > {
25
+ style?: ViewProps['style'];
26
+ labelStyle?: ViewProps['style'];
27
+ bodyStyle?: ViewProps['style'];
28
+ }
29
+
30
+ /**
31
+ * 处理表单表单项属性
32
+ *
33
+ * @example
34
+ *
35
+ * ```tsx
36
+
37
+ * ```
38
+ *
39
+ */
40
+ export function useFairysValtioFormItemAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>) {
41
+ const [layoutAttrs] = useFairysValtioFormLayoutContext();
42
+ const colCount = layoutAttrs.colCount || 1;
43
+ const parent_borderedType = layoutAttrs.itemBorderType || 'bottom';
44
+ const parent_errorLayout = layoutAttrs.errorLayout || 'bottom-right';
45
+ const parent_formItemLabelStyle = layoutAttrs.formItemLabelStyle;
46
+ const parent_formItemStyle = layoutAttrs.formItemStyle;
47
+ const parent_formItemBodyStyle = layoutAttrs.formItemBodyStyle;
48
+ const parent_labelMode = layoutAttrs.labelMode || 'between';
49
+ const parent_itemBorderColor = layoutAttrs.itemBorderColor;
50
+ const parent_isInvalidBorderRed = layoutAttrs.isInvalidBorderRed;
51
+ const parent_isInvalidTextRed = layoutAttrs.isInvalidTextRed;
52
+ const parent_showColon = layoutAttrs.showColon;
53
+
54
+ const {
55
+ name,
56
+ valuePropName = 'value',
57
+ getValuePath = 'text',
58
+ getValueFromEvent,
59
+ formatValue,
60
+ onAfterUpdate,
61
+ trigger = 'onChange',
62
+ style,
63
+ labelStyle,
64
+ bodyStyle,
65
+ children,
66
+ labelMode = parent_labelMode,
67
+ errorLayout = parent_errorLayout,
68
+ colSpan = 1,
69
+ isRequired: _isRequired,
70
+ itemBorderType = parent_borderedType,
71
+ attrs = {},
72
+ showColon = parent_showColon,
73
+ itemBorderColor = parent_itemBorderColor,
74
+ isInvalidBorderRed = parent_isInvalidBorderRed,
75
+ isInvalidTextRed = parent_isInvalidTextRed,
76
+ isJoinParentField = true,
77
+ rules,
78
+ } = props;
79
+ const {
80
+ name: _name,
81
+ paths,
82
+ parentName,
83
+ formAttrsNameInstance,
84
+ } = useFairysValtioFormAttrsName({ name, isJoinParentField });
85
+
86
+ const widthStyles: ViewProps['style'] = useMemo(() => {
87
+ if (colCount >= colSpan) {
88
+ return {
89
+ width: `${(100 / colCount) * colSpan}%`,
90
+ };
91
+ }
92
+ return { width: `100%` };
93
+ }, [colSpan, colCount]);
94
+
95
+ const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState<T>();
96
+ const value = useMemo(() => get(state, paths), [state, paths]);
97
+
98
+ const error = errorState[_name];
99
+ // 使用从 Form 中设置的规则
100
+ const _formItemRules = formInstance.rules?.[_name];
101
+ const id = useId(_name);
102
+ formInstance.nameToPaths[_name] = paths;
103
+
104
+ useEffect(() => {
105
+ if (Array.isArray(rules) && rules.length) {
106
+ formInstance.mountRules[_name] = rules;
107
+ }
108
+ return () => {
109
+ formInstance.removeRules(_name);
110
+ };
111
+ }, [_name, rules]);
112
+
113
+ const onValueChange = (event: any) => {
114
+ let newValue = event;
115
+ const target = event?.nativeEvent;
116
+ if (typeof getValueFromEvent === 'function') {
117
+ newValue = getValueFromEvent(event, formInstance);
118
+ } else if (event && target && typeof target === 'object' && getValuePath in target) {
119
+ newValue = get(target, formatePath(getValuePath));
120
+ }
121
+ if (typeof formatValue === 'function') {
122
+ newValue = formatValue(newValue, formInstance, event);
123
+ }
124
+ if (newValue === value) return;
125
+ formInstance.updatedValueByPaths(_name, newValue);
126
+ if (typeof onAfterUpdate === 'function') {
127
+ onAfterUpdate(newValue, formInstance, event);
128
+ }
129
+ };
130
+
131
+ /**基础组件参数*/
132
+ const baseControl = {
133
+ ...attrs,
134
+ style: StyleSheet.flatten([attrs?.style || {}, labelMode === 'between' ? formItemStyles['input.between'] : {}]),
135
+ name,
136
+ id,
137
+ [valuePropName]: value,
138
+ [trigger]: onValueChange,
139
+ };
140
+
141
+ /**判断是否必填*/
142
+ const isRequired = useMemo(() => {
143
+ if (_isRequired) {
144
+ return _isRequired;
145
+ } else if (Array.isArray(rules) && rules.length) {
146
+ return rules.some((rule) => rule.required);
147
+ } else if (_formItemRules && Array.isArray(_formItemRules) && _formItemRules.length) {
148
+ return _formItemRules.some((rule) => rule.required);
149
+ }
150
+ return false;
151
+ }, [rules, formInstance, _formItemRules]);
152
+
153
+ /**校验是否存在错误信息*/
154
+ const isInvalid = useMemo(() => {
155
+ if (Array.isArray(error) && error.length) {
156
+ return true;
157
+ }
158
+ return false;
159
+ }, [error]);
160
+
161
+ const item_style = useMemo(() => {
162
+ return StyleSheet.flatten([
163
+ formItemStyles['fairys-valtio-form-item'],
164
+ itemBorderType === 'bottom' ? formItemStyles['fairys-valtio-form-item.border-bottom'] : {},
165
+ itemBorderColor && itemBorderType === 'bottom' ? { borderColor: itemBorderColor } : {},
166
+ isInvalid && isInvalidBorderRed && itemBorderType === 'bottom'
167
+ ? formItemStyles['fairys-valtio-form-item.border-bottom.red']
168
+ : {},
169
+ widthStyles,
170
+ parent_formItemStyle,
171
+ style,
172
+ ]);
173
+ }, [
174
+ style,
175
+ widthStyles,
176
+ parent_formItemStyle,
177
+ labelMode,
178
+ itemBorderType,
179
+ isInvalid,
180
+ isInvalidBorderRed,
181
+ ]) as ViewProps['style'];
182
+
183
+ const itemContainer_style = useMemo(() => {
184
+ return StyleSheet.flatten([
185
+ formItemStyles['fairys-valtio-form-item-container'],
186
+ labelMode === 'between' ? formItemStyles['fairys-valtio-form-item-container.between'] : {},
187
+ labelMode === 'top' ? formItemStyles['fairys-valtio-form-item-container.top'] : {},
188
+ labelMode === 'left' ? formItemStyles['fairys-valtio-form-item-container.left'] : {},
189
+ ]);
190
+ }, [labelMode]) as ViewProps['style'];
191
+
192
+ const itemLabel_style = useMemo(() => {
193
+ return StyleSheet.flatten([
194
+ formItemStyles['fairys-valtio-form-item-label'],
195
+ labelMode === 'left' ? formItemStyles['fairys-valtio-form-item-label.left'] : {},
196
+ parent_formItemLabelStyle,
197
+ labelStyle,
198
+ ]);
199
+ }, [labelMode, parent_formItemLabelStyle, labelStyle]) as ViewProps['style'];
200
+
201
+ const itemLabelShowColon_style = useMemo(() => {
202
+ return StyleSheet.flatten([
203
+ formItemStyles['fairys-valtio-form-item-label.show-colon'],
204
+ isInvalid && isInvalidTextRed ? formItemStyles['fairys-valtio-form-item-label.show-colon.red'] : {},
205
+ ]);
206
+ }, [isInvalid, isInvalidTextRed]) as ViewProps['style'];
207
+
208
+ const itemLabelText_style = useMemo(() => {
209
+ return StyleSheet.flatten([
210
+ formItemStyles['fairys-valtio-form-item-label-text'],
211
+ isInvalid && isInvalidTextRed ? formItemStyles['fairys-valtio-form-item-label-text.red'] : {},
212
+ ]);
213
+ }, [labelMode, isInvalid, isInvalidTextRed]) as ViewProps['style'];
214
+
215
+ const itemBody_style = useMemo(() => {
216
+ return StyleSheet.flatten([
217
+ formItemStyles['fairys-valtio-form-item-body'],
218
+ labelMode === 'left' ? formItemStyles['fairys-valtio-form-item-body.left'] : {},
219
+ labelMode === 'top' ? formItemStyles['fairys-valtio-form-item-body.top'] : {},
220
+ labelMode === 'between' ? formItemStyles['fairys-valtio-form-item-body.between'] : {},
221
+ itemBorderType === 'body' ? formItemStyles['fairys-valtio-form-item-body.border-bottom'] : {},
222
+ itemBorderColor && itemBorderType === 'body' ? { borderColor: itemBorderColor } : {},
223
+ isInvalid && isInvalidBorderRed && itemBorderType === 'body'
224
+ ? formItemStyles['fairys-valtio-form-item-body.border-bottom.red']
225
+ : {},
226
+ parent_formItemBodyStyle,
227
+ bodyStyle,
228
+ ]);
229
+ }, [bodyStyle, parent_formItemBodyStyle, labelMode, isInvalid]) as ViewProps['style'];
230
+
231
+ const itemBodyInput_style = useMemo(() => {
232
+ return StyleSheet.flatten([
233
+ formItemStyles['fairys-valtio-form-item-body-input'],
234
+ labelMode === 'between' ? formItemStyles['fairys-valtio-form-item-body-input.between'] : {},
235
+ labelMode !== 'between' ? formItemStyles['fairys-valtio-form-item-body-input.not.between'] : {},
236
+ ]);
237
+ }, [labelMode]) as ViewProps['style'];
238
+
239
+ const itemExtra_style = useMemo(() => {
240
+ return StyleSheet.flatten([formItemStyles['fairys-valtio-form-item-body-extra']]);
241
+ }, []) as ViewProps['style'];
242
+
243
+ const itemHelp_style = useMemo(() => {
244
+ return StyleSheet.flatten([formItemStyles['fairys-valtio-form-item-help']]);
245
+ }, []) as ViewProps['style'];
246
+
247
+ const itemError_style = useMemo(() => {
248
+ return StyleSheet.flatten([
249
+ formItemStyles['fairys-valtio-form-item-body-error'],
250
+ errorLayout ? formItemStyles['fairys-valtio-form-item-body-error.' + errorLayout] || {} : {},
251
+ ]);
252
+ }, [errorLayout]) as ViewProps['style'];
253
+
254
+ return {
255
+ value,
256
+ isInvalid,
257
+ itemBorderType,
258
+ onValueChange,
259
+ colSpan,
260
+ colCount,
261
+ labelMode,
262
+ errorLayout,
263
+ isRequired,
264
+ state,
265
+ errorState,
266
+ formInstance,
267
+ error,
268
+ _name,
269
+ name,
270
+ id,
271
+ paths,
272
+ parentName,
273
+ formAttrsNameInstance,
274
+ showColon,
275
+ // ================================================================================
276
+ itemStyle: item_style,
277
+ itemContainerStyle: itemContainer_style,
278
+ itemLabelStyle: itemLabel_style,
279
+ itemLabelTextStyle: itemLabelText_style,
280
+ itemLabelShowColonStyle: itemLabelShowColon_style,
281
+ itemBodyStyle: itemBody_style,
282
+ itemInputStyle: itemBodyInput_style,
283
+ itemExtraStyle: itemExtra_style,
284
+ errorStyle: itemError_style,
285
+ helpStyle: itemHelp_style,
286
+ children: React.isValidElement(children) ? React.cloneElement(children, { ...baseControl }) : children,
287
+ } as FairysValtioFormItemAttrsReturn<T>;
288
+ }
289
+
290
+ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object> {
291
+ /**表单项值*/
292
+ value?: any;
293
+ /**是否校验错误*/
294
+ isInvalid: boolean;
295
+ /**边框类型*/
296
+ itemBorderType: FairysValtioFormLayoutContextOptions['itemBorderType'];
297
+ /**值改变事件*/
298
+ onValueChange: (event: any) => void;
299
+ /**当前表单项占据列数*/
300
+ colSpan: number;
301
+ /**列数*/
302
+ colCount: number;
303
+ /**标签显示模式*/
304
+ labelMode: FairysValtioFormLayoutContextOptions['labelMode'];
305
+ /**错误提示位置*/
306
+ errorLayout: FairysValtioFormLayoutContextOptions['errorLayout'];
307
+ /**是否必填*/
308
+ isRequired: boolean;
309
+ /**表单状态*/
310
+ state: T;
311
+ /**错误状态*/
312
+ errorState: Record<PropertyKey, string[]>;
313
+ /**表单实例*/
314
+ formInstance: FairysValtioFormInstance<T>;
315
+ /**错误信息*/
316
+ error?: string[];
317
+ /**拼接父级字段名后得到的表单项名称*/
318
+ _name?: string;
319
+ /**表单项名称*/
320
+ name?: string;
321
+ /**表单项ID*/
322
+ id?: string;
323
+ /**表单项路径*/
324
+ paths?: (string | number)[];
325
+ /**父级字段名*/
326
+ parentName?: string;
327
+ /**表单属性名实例*/
328
+ formAttrsNameInstance: FairysValtioFormParentAttrs;
329
+ /**是否显示冒号*/
330
+ showColon: boolean;
331
+ // =========================================
332
+ itemStyle: ViewProps['style'];
333
+ itemContainerStyle: ViewProps['style'];
334
+ itemLabelStyle: ViewProps['style'];
335
+ itemLabelTextStyle: ViewProps['style'];
336
+ itemLabelShowColonStyle: ViewProps['style'];
337
+ itemBodyStyle: ViewProps['style'];
338
+ itemInputStyle: ViewProps['style'];
339
+ itemExtraStyle: ViewProps['style'];
340
+ errorStyle: ViewProps['style'];
341
+ helpStyle: ViewProps['style'];
342
+ /**子元素*/
343
+ children?: React.ReactNode;
344
+ }
345
+
346
+ /**
347
+ * 没有样式的表单项属性,仅返回基础输入组件参数
348
+ *
349
+ * @example
350
+ *
351
+ *```tsx
352
+
353
+ * ```
354
+ */
355
+ export function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T> = object>(
356
+ props: FairysValtioFormItemAttrsProps<T>,
357
+ ) {
358
+ const {
359
+ name,
360
+ valuePropName = 'value',
361
+ getValuePath = 'text',
362
+ getValueFromEvent,
363
+ formatValue,
364
+ onAfterUpdate,
365
+ trigger = 'onChange',
366
+ children,
367
+ attrs = {},
368
+ isJoinParentField = true,
369
+ rules,
370
+ isRequired: _isRequired,
371
+ } = props;
372
+ const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState<T>();
373
+ const {
374
+ name: _name,
375
+ paths,
376
+ parentName,
377
+ formAttrsNameInstance,
378
+ } = useFairysValtioFormAttrsName({ name, isJoinParentField });
379
+ const id = useId(_name);
380
+ const value = useMemo(() => get(state, paths), [state, paths]);
381
+ const error = errorState[_name];
382
+ formInstance.nameToPaths[_name] = paths;
383
+
384
+ // 使用从 Form 中设置的规则
385
+ const _formItemRules = formInstance.rules?.[_name];
386
+
387
+ useEffect(() => {
388
+ if (Array.isArray(rules) && rules.length) {
389
+ formInstance.mountRules[_name] = rules;
390
+ }
391
+ return () => {
392
+ formInstance.removeRules(_name);
393
+ };
394
+ }, [_name, rules]);
395
+
396
+ const onValueChange = (event: any) => {
397
+ let newValue = event;
398
+ const target = event?.nativeEvent;
399
+ if (typeof getValueFromEvent === 'function') {
400
+ newValue = getValueFromEvent(event, formInstance);
401
+ } else if (event && target && typeof target === 'object' && getValuePath in target) {
402
+ newValue = get(target, formatePath(getValuePath));
403
+ }
404
+ if (typeof formatValue === 'function') {
405
+ newValue = formatValue(newValue, formInstance, event);
406
+ }
407
+ if (newValue === value) return;
408
+ formInstance.updatedValueByPaths(_name, newValue);
409
+ if (typeof onAfterUpdate === 'function') {
410
+ onAfterUpdate(newValue, formInstance, event);
411
+ }
412
+ };
413
+ /**基础组件参数*/
414
+ const baseControl = {
415
+ ...attrs,
416
+ name,
417
+ id,
418
+ [valuePropName]: value,
419
+ [trigger]: onValueChange,
420
+ };
421
+
422
+ /**判断是否必填*/
423
+ const isRequired = useMemo(() => {
424
+ if (_isRequired) {
425
+ return _isRequired;
426
+ } else if (Array.isArray(rules) && rules.length) {
427
+ return rules.some((rule) => rule.required);
428
+ } else if (_formItemRules && Array.isArray(_formItemRules) && _formItemRules.length) {
429
+ return _formItemRules.some((rule) => rule.required);
430
+ }
431
+ return false;
432
+ }, [rules, formInstance, _formItemRules]);
433
+
434
+ /**校验是否存在错误信息*/
435
+ const isInvalid = useMemo(() => {
436
+ if (Array.isArray(error) && error.length) {
437
+ return true;
438
+ }
439
+ return false;
440
+ }, [error]);
441
+
442
+ return {
443
+ value,
444
+ isRequired,
445
+ isInvalid,
446
+ error,
447
+ onValueChange,
448
+ state,
449
+ errorState,
450
+ formInstance,
451
+ _name,
452
+ name,
453
+ id,
454
+ paths,
455
+ parentName,
456
+ formAttrsNameInstance,
457
+ children: React.isValidElement(children) ? React.cloneElement(children, { ...baseControl }) : children,
458
+ } as FairysValtioFormItemNoStyleAttrsReturn<T>;
459
+ }
460
+
461
+ export interface FairysValtioFormItemNoStyleAttrsReturn<T extends MObject<T> = object> {
462
+ /**表单项值*/
463
+ value?: any;
464
+ /**是否校验错误*/
465
+ isInvalid: boolean;
466
+ /**是否必填*/
467
+ isRequired: boolean;
468
+ /**错误信息*/
469
+ error?: string[];
470
+ /**值改变事件*/
471
+ onValueChange: (event: any) => void;
472
+ /**表单状态*/
473
+ state: T;
474
+ /**错误状态*/
475
+ errorState: Record<PropertyKey, string[]>;
476
+ /**表单实例*/
477
+ formInstance: FairysValtioFormInstance<T>;
478
+ /**拼接父级字段名后得到的表单项名称*/
479
+ _name?: string;
480
+ /**表单项名称*/
481
+ name?: string;
482
+ /**表单项ID*/
483
+ id?: string;
484
+ /**表单项路径*/
485
+ paths?: (string | number)[];
486
+ /**父级字段名*/
487
+ parentName?: string;
488
+ /**表单属性名实例*/
489
+ formAttrsNameInstance: FairysValtioFormParentAttrs;
490
+ /**子元素*/
491
+ children?: React.ReactNode;
492
+ }