@fairys/valtio-form-basic 0.0.8 → 0.0.10

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.
@@ -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
- rules?: FairysValtioFormInstance<T>['rules'];
11
+ /**表单项规则(如果表单项没有指定规则,则使用全局规则,如果表单项指定规则,则使用表单项规则)*/
12
+ rules?: Record<PropertyKey, RuleItem[]>;
12
13
  /**表单初始值*/
13
14
  formData?: FairysValtioFormInstance<T>['state'];
14
15
  /**表单隐藏状态*/
@@ -54,7 +55,7 @@ export declare function useFairysValtioForm<T extends MObject<T> = object>(props
54
55
  boxShadow?: boolean;
55
56
  lastItemBordered?: boolean;
56
57
  colCount?: number;
57
- errorLayout?: "left-bottom" | "right-bottom" | "top-right" | "top-left";
58
+ errorLayout?: "bottom-left" | "bottom-right" | "top-right" | "top-left" | "left-border-top" | "right-border-top";
58
59
  labelMode?: "left" | "top" | "between";
59
60
  formItemClassName?: string;
60
61
  formItemStyle?: React.CSSProperties;
@@ -62,5 +63,9 @@ 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
- borderedType?: "bottom" | "body";
66
+ itemBorderType?: "bottom" | "body";
67
+ itemBorderColor?: React.CSSProperties["borderColor"];
68
+ isInvalidBorderRed?: boolean;
69
+ isInvalidTextRed?: boolean;
70
+ showColon?: boolean;
66
71
  };
@@ -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
- name: string;
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
  /**传递组件字段*/
@@ -26,9 +38,9 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
26
38
  bodyStyle?: React.CSSProperties;
27
39
  children?: React.ReactNode;
28
40
  /**规则校验失败错误提示位置*/
29
- errorLayout?: 'left-bottom' | 'right-bottom' | 'top-right' | 'top-left';
41
+ errorLayout?: FairysValtioFormLayoutContextOptions['errorLayout'];
30
42
  /**label显示模式*/
31
- labelMode?: 'left' | 'top' | 'between';
43
+ labelMode?: FairysValtioFormLayoutContextOptions['labelMode'];
32
44
  /**额外内容*/
33
45
  extra?: React.ReactNode;
34
46
  /**底部提示内容*/
@@ -48,9 +60,19 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
48
60
  /**是否显示冒号*/
49
61
  showColon?: boolean;
50
62
  /**底部显示边框*/
51
- borderedType?: FairysValtioFormLayoutContextOptions['borderedType'];
63
+ itemBorderType?: FairysValtioFormLayoutContextOptions['itemBorderType'];
64
+ /**边框颜色*/
65
+ itemBorderColor?: React.CSSProperties['borderColor'];
66
+ /**是否校验失败时显示红色边框*/
67
+ isInvalidBorderRed?: boolean;
68
+ /**是否校验失败时显示红色文本*/
69
+ isInvalidTextRed?: boolean;
52
70
  /**输入框属性*/
53
71
  attrs?: any;
72
+ /**是否拼接父级字段名*/
73
+ isJoinParentField?: boolean;
74
+ /**校验规则*/
75
+ rules?: RuleItem[];
54
76
  }
55
77
  /**
56
78
  * 处理表单表单项属性
@@ -59,7 +81,7 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
59
81
  *
60
82
  * ```tsx
61
83
  import { Fragment } from 'react'
62
- import { useFairysValtioFormItemAttrs } from "@fairys/valtio-form"
84
+ import { useFairysValtioFormItemAttrs , FairysValtioFormParentAttrsContext } from "@fairys/valtio-form"
63
85
  import type { FairysValtioFormItemAttrsProps } from "@fairys/valtio-form"
64
86
  export interface FormItemProps extends FairysValtioFormItemAttrsProps{}
65
87
 
@@ -68,10 +90,11 @@ export const FormItem = (props: FormItemProps) => {
68
90
  const {
69
91
  itemClassName, itemStyle, containerClassName, itemLabelClassName, itemLabelStyle,
70
92
  itemBodyClassName, itemBodyStyle, itemInputClassName, itemExtraClassName, errorClassName, helpClassName,
71
- isInvalid, borderedType, children, error
93
+ isInvalid, itemBorderType, children, error,formAttrsNameInstance
72
94
  } = useFairysValtioFormItemAttrs(props)
73
95
 
74
96
  return (
97
+ <FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
75
98
  <View className={itemClassName} style={itemStyle}>
76
99
  <View className={containerClassName}>
77
100
  <View className={itemLabelClassName} style={itemLabelStyle}>
@@ -82,12 +105,13 @@ export const FormItem = (props: FormItemProps) => {
82
105
  {children}
83
106
  </View>
84
107
  {extra ? <View className={itemExtraClassName}>{extra}</View> : <Fragment />}
85
- {borderedType === 'body' && isInvalid ? <View className={errorClassName}>{error}</View> : <Fragment />}
108
+ {itemBorderType === 'body' && isInvalid ? <View className={errorClassName}>{error}</View> : <Fragment />}
86
109
  </View>
87
110
  </View>
88
111
  {helpText ? <View className={helpClassName}>{helpText}</View> : <Fragment />}
89
- {isInvalid && borderedType !== 'body' ? <View className={errorClassName}>{error}</View> : <Fragment />}
112
+ {isInvalid && itemBorderType !== 'body' ? <View className={errorClassName}>{error}</View> : <Fragment />}
90
113
  </View>
114
+ </FairysValtioFormParentAttrsContext.Provider>
91
115
  );
92
116
  }
93
117
  * ```
@@ -98,31 +122,41 @@ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object>
98
122
  /**表单项值*/
99
123
  value?: any;
100
124
  /**是否校验错误*/
101
- isInvalid?: boolean;
125
+ isInvalid: boolean;
102
126
  /**边框类型*/
103
- borderedType?: FairysValtioFormLayoutContextOptions['borderedType'];
127
+ itemBorderType: FairysValtioFormLayoutContextOptions['itemBorderType'];
104
128
  /**值改变事件*/
105
- onValueChange?: (event: any) => void;
129
+ onValueChange: (event: any) => void;
106
130
  /**当前表单项占据列数*/
107
- colSpan?: number;
131
+ colSpan: number;
108
132
  /**当前表单项占据行数*/
109
- rowSpan?: number;
133
+ rowSpan: number;
110
134
  /**列数*/
111
- colCount?: number;
135
+ colCount: number;
112
136
  /**标签显示模式*/
113
- labelMode?: FairysValtioFormLayoutContextOptions['labelMode'];
137
+ labelMode: FairysValtioFormLayoutContextOptions['labelMode'];
114
138
  /**错误提示位置*/
115
- errorLayout?: FairysValtioFormLayoutContextOptions['errorLayout'];
139
+ errorLayout: FairysValtioFormLayoutContextOptions['errorLayout'];
116
140
  /**是否必填*/
117
- isRequired?: boolean;
141
+ isRequired: boolean;
118
142
  /**表单状态*/
119
- state?: T;
143
+ state: T;
120
144
  /**错误状态*/
121
- errorState?: Record<PropertyKey, string[]>;
145
+ errorState: Record<PropertyKey, string[]>;
122
146
  /**表单实例*/
123
- formInstance?: FairysValtioFormInstance<T>;
147
+ formInstance: FairysValtioFormInstance<T>;
124
148
  /**错误信息*/
125
149
  error?: string[];
150
+ /**拼接父级字段名后得到的表单项名称*/
151
+ _name?: string;
152
+ /**表单项名称*/
153
+ name?: string;
154
+ /**表单项路径*/
155
+ paths?: (string | number)[];
156
+ /**父级字段名*/
157
+ parentName?: string;
158
+ /**表单属性名实例*/
159
+ formAttrsNameInstance: FairysValtioFormParentAttrs;
126
160
  /**表单项类名*/
127
161
  itemClassName: string;
128
162
  /**表单项样式*/
@@ -148,3 +182,36 @@ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object>
148
182
  /**子元素*/
149
183
  children?: React.ReactNode;
150
184
  }
185
+ /**
186
+ * 没有样式的表单项属性,仅返回基础输入组件参数
187
+ *
188
+ * @example
189
+ *
190
+ *```tsx
191
+ import { Fragment } from 'react'
192
+ import { useFairysValtioFormItemAttrs, FairysValtioFormParentAttrsContext } from "@fairys/valtio-form"
193
+ import type { FairysValtioFormItemAttrsProps } from "@fairys/valtio-form"
194
+ export interface FormItemProps extends FairysValtioFormItemAttrsProps{}
195
+
196
+ export const FormItem = (props: FormItemProps) => {
197
+ const { children , formAttrsNameInstance } = useFairysValtioFormItemNoStyleAttrs(props)
198
+ return <FairysValtioFormParentAttrsContext.Provider value={formAttrsNameInstance}>
199
+ {children}
200
+ </FairysValtioFormParentAttrsContext.Provider>
201
+ }
202
+ * ```
203
+ */
204
+ export declare function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>): {
205
+ value: unknown;
206
+ error: string[];
207
+ onValueChange: (event: any) => void;
208
+ state: T;
209
+ errorState: Record<PropertyKey, string[]>;
210
+ formInstance: FairysValtioFormInstance<T>;
211
+ _name: string;
212
+ name: string;
213
+ paths: (number | symbol)[] | (string | number)[];
214
+ parentName: string;
215
+ formAttrsNameInstance: FairysValtioFormParentAttrs;
216
+ children: string | number | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode>;
217
+ };
@@ -1,12 +1,14 @@
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.borderedType || 'bottom';
9
- const parent_errorLayout = layoutAttrs.errorLayout || 'right-bottom';
10
+ const parent_borderedType = layoutAttrs.itemBorderType || 'bottom';
11
+ const parent_errorLayout = layoutAttrs.errorLayout || 'bottom-right';
10
12
  const parent_formItemClassName = layoutAttrs.formItemClassName;
11
13
  const parent_formItemLabelClassName = layoutAttrs.formItemLabelClassName;
12
14
  const parent_formItemLabelStyle = layoutAttrs.formItemLabelStyle;
@@ -14,20 +16,36 @@ 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 { 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, borderedType = parent_borderedType, attrs = {}, showColon = false } = props;
19
+ const parent_itemBorderColor = layoutAttrs.itemBorderColor;
20
+ const parent_isInvalidBorderRed = layoutAttrs.isInvalidBorderRed;
21
+ const parent_isInvalidTextRed = layoutAttrs.isInvalidTextRed;
22
+ const parent_showColon = layoutAttrs.showColon;
23
+ 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, isInvalidTextRed = parent_isInvalidTextRed, isJoinParentField = true, rules } = props;
24
+ const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
25
+ name,
26
+ isJoinParentField
27
+ });
18
28
  const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
19
- const rules = formInstance.rules?.[name];
20
- const value = state[name];
21
- const error = errorState[name];
29
+ const value = useMemo(()=>get(state, paths), [
30
+ state,
31
+ paths
32
+ ]);
33
+ const error = errorState[_name];
34
+ const _formItemRules = formInstance.rules?.[_name];
35
+ formInstance.nameToPaths[_name] = paths;
36
+ if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
37
+ useEffect(()=>()=>{
38
+ formInstance.removeRules(_name);
39
+ }, [
40
+ _name
41
+ ]);
22
42
  const onValueChange = (event)=>{
23
43
  let value = event;
24
44
  const target = event?.detail || event?.target;
25
45
  if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
26
46
  else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
27
47
  if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
28
- formInstance.updated({
29
- [name]: value
30
- });
48
+ formInstance.updatedValueByPaths(_name, value);
31
49
  if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
32
50
  };
33
51
  const baseControl = {
@@ -39,10 +57,12 @@ function useFairysValtioFormItemAttrs(props) {
39
57
  const isRequired = useMemo(()=>{
40
58
  if (_isRequired) return _isRequired;
41
59
  if (Array.isArray(rules) && rules.length) return rules.some((rule)=>rule.required);
60
+ if (_formItemRules && Array.isArray(_formItemRules) && _formItemRules.length) return _formItemRules.some((rule)=>rule.required);
42
61
  return false;
43
62
  }, [
44
63
  rules,
45
- formInstance
64
+ formInstance,
65
+ _formItemRules
46
66
  ]);
47
67
  const isInvalid = useMemo(()=>{
48
68
  if (Array.isArray(error) && error.length) return true;
@@ -50,16 +70,21 @@ function useFairysValtioFormItemAttrs(props) {
50
70
  }, [
51
71
  error
52
72
  ]);
53
- 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
- 'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200': 'bottom' === borderedType,
73
+ const item_cls = useMemo(()=>clsx('fairys-valtio-form-item fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__p-_zkh1_4px_zhk2_ fairystaroform__text-_zkh1_12px_zhk2_ fairystaroform__relative fairystaroform__flex fairystaroform__flex-col fairystaroform__box-border fairystaroform__break-all', {
74
+ 'fairys-valtio-form-item-invalid': isInvalid,
75
+ 'fairys-valtio-form-item-invalid-text-red': isInvalid && isInvalidTextRed,
76
+ 'fairys-valtio-form-item-invalid-border-red': isInvalid && isInvalidBorderRed && 'bottom' === itemBorderType,
77
+ 'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200': 'bottom' === itemBorderType,
55
78
  [labelMode]: labelMode
56
- }, className, parent_formItemClassName), [
79
+ }, parent_formItemClassName, className), [
57
80
  className,
58
81
  parent_formItemClassName,
59
82
  labelMode,
60
- borderedType
83
+ itemBorderType,
84
+ isInvalid,
85
+ isInvalidBorderRed
61
86
  ]);
62
- const itemContainer_cls = useMemo(()=>clsx('fairys-valtio-form-item-container fairystaroform__flex-1 fairystaroform__h-full fairystaroform__flex fairystaroform__box-border', {
87
+ const itemContainer_cls = useMemo(()=>clsx('fairys-valtio-form-item-container fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__flex-1 fairystaroform__h-full fairystaroform__flex fairystaroform__box-border', {
63
88
  'fairystaroform__flex-row fairystaroform__items-center fairystaroform__justify-between fairystaroform__gap-_zkh1_8px_zhk2_': 'between' === labelMode,
64
89
  'fairystaroform__flex-col fairystaroform__gap-_zkh1_4px_zhk2_': 'top' === labelMode,
65
90
  'fairystaroform__flex-row fairystaroform__gap-_zkh1_8px_zhk2_': 'left' === labelMode
@@ -67,7 +92,7 @@ function useFairysValtioFormItemAttrs(props) {
67
92
  labelClassName,
68
93
  labelMode
69
94
  ]);
70
- const itemLabel_cls = useMemo(()=>clsx('fairys-valtio-form-item-label fairystaroform__text-gray-800 fairystaroform__flex fairystaroform__items-center fairystaroform__relative fairystaroform__box-border', {
95
+ const itemLabel_cls = useMemo(()=>clsx('fairys-valtio-form-item-label fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__text-gray-800 fairystaroform__flex fairystaroform__items-center fairystaroform__relative fairystaroform__box-border', {
71
96
  'fairystaroform__justify-start': 'left' !== labelMode,
72
97
  'fairystaroform__justify-end': 'left' === labelMode,
73
98
  required: isRequired,
@@ -79,30 +104,35 @@ function useFairysValtioFormItemAttrs(props) {
79
104
  isRequired,
80
105
  showColon
81
106
  ]);
82
- const itemBody_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__relative fairystaroform__flex-1 fairystaroform__flex fairystaroform__box-border', {
107
+ const itemBody_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__relative fairystaroform__flex-1 fairystaroform__flex fairystaroform__box-border', {
83
108
  'fairystaroform__flex-row fairystaroform__justify-start': 'left' === labelMode,
84
109
  'fairystaroform__flex-row fairystaroform__justify-end': 'between' === labelMode || 'top' === labelMode,
85
110
  'fairystaroform__flex-row': 'top' === labelMode,
86
- 'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' === borderedType
87
- }, bodyClassName, parent_formItemBodyClassName), [
111
+ 'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' === itemBorderType,
112
+ 'fairys-valtio-form-item-invalid-border-red': isInvalid && isInvalidBorderRed && 'body' === itemBorderType
113
+ }, parent_formItemBodyClassName, bodyClassName), [
88
114
  bodyClassName,
89
115
  labelMode,
90
- borderedType,
91
- parent_formItemBodyClassName
116
+ itemBorderType,
117
+ parent_formItemBodyClassName,
118
+ isInvalid,
119
+ isInvalidBorderRed
92
120
  ]);
93
- const itemInput_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__flex fairystaroform__flex-row fairystaroform__flex-1 fairystaroform__box-border', {
121
+ const itemInput_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-input fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__min-h-_zkh1_32px_zhk2_ fairystaroform__flex fairystaroform__flex-row fairystaroform__items-center fairystaroform__flex-1 fairystaroform__box-border', {
94
122
  'fairystaroform__justify-end fairystaroform__text-right': 'between' === labelMode,
95
123
  'fairystaroform__justify-start fairystaroform__text-left fairystaroform__items-center': 'between' !== labelMode
96
124
  }), [
97
125
  labelMode
98
126
  ]);
99
- const itemExtra_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-extra fairystaroform__box-border fairystaroform__flex fairystaroform__items-center fairystaroform__justify-center'), []);
100
- const itemHelp_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-help fairystaroform__text-_zkh1_10px_zhk2_ fairystaroform__w-full fairystaroform__box-border'), []);
101
- const itemError_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-error fairystaroform__px-_zkh1_4px_zhk2_ fairystaroform__w-full fairystaroform__flex fairystaroform__flex-row fairystaroform__box-border fairystaroform__text-red fairystaroform__absolute fairystaroform__text-_zkh1_10px_zhk2_ fairystaroform__z-10', {
102
- 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'left-bottom' === errorLayout,
103
- 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'right-bottom' === errorLayout,
104
- 'fairystaroform__top-_zkh1_-14px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'top-right' === errorLayout,
105
- 'fairystaroform__top-_zkh1_-14px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'top-left' === errorLayout
127
+ const itemExtra_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-extra fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__box-border fairystaroform__flex fairystaroform__items-center fairystaroform__justify-center'), []);
128
+ const itemHelp_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-help fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__text-_zkh1_10px_zhk2_ fairystaroform__w-full fairystaroform__box-border'), []);
129
+ const itemError_cls = useMemo(()=>clsx('fairys-valtio-form-item-body-error fairystaroform__transition-all fairystaroform__duration-300 fairystaroform__w-full fairystaroform__flex fairystaroform__flex-row fairystaroform__box-border fairystaroform__text-red fairystaroform__absolute fairystaroform__text-_zkh1_10px_zhk2_ fairystaroform__z-10', {
130
+ 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'bottom-left' === errorLayout,
131
+ 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'bottom-right' === errorLayout,
132
+ 'fairystaroform__top-_zkh1_-4px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'top-right' === errorLayout,
133
+ 'fairystaroform__top-_zkh1_-4px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'top-left' === errorLayout,
134
+ 'fairystaroform__left-0 fairystaroform__bottom-_zkh1_-2px_zhk2_ fairystaroform__justify-start': 'left-border-top' === errorLayout,
135
+ 'fairystaroform__right-0 fairystaroform__bottom-_zkh1_-2px_zhk2_ fairystaroform__justify-end': 'right-border-top' === errorLayout
106
136
  }), [
107
137
  errorLayout
108
138
  ]);
@@ -122,7 +152,7 @@ function useFairysValtioFormItemAttrs(props) {
122
152
  return {
123
153
  value,
124
154
  isInvalid,
125
- borderedType,
155
+ itemBorderType,
126
156
  onValueChange,
127
157
  colSpan,
128
158
  rowSpan,
@@ -134,8 +164,16 @@ function useFairysValtioFormItemAttrs(props) {
134
164
  errorState,
135
165
  formInstance,
136
166
  error,
167
+ _name,
168
+ name,
169
+ paths,
170
+ parentName,
171
+ formAttrsNameInstance,
137
172
  itemClassName: item_cls,
138
173
  itemStyle: {
174
+ ...itemBorderColor && 'bottom' === itemBorderType ? {
175
+ borderBottomColor: itemBorderColor
176
+ } : {},
139
177
  ...parent_formItemStyle || {},
140
178
  ...styleBase,
141
179
  ...style || {}
@@ -148,6 +186,9 @@ function useFairysValtioFormItemAttrs(props) {
148
186
  },
149
187
  itemBodyClassName: itemBody_cls,
150
188
  itemBodyStyle: {
189
+ ...itemBorderColor && 'body' === itemBorderType ? {
190
+ borderBottomColor: itemBorderColor
191
+ } : {},
151
192
  ...parent_formItemBodyStyle || {},
152
193
  ...bodyStyle || {}
153
194
  },
@@ -160,4 +201,55 @@ function useFairysValtioFormItemAttrs(props) {
160
201
  }) : children
161
202
  };
162
203
  }
163
- export { useFairysValtioFormItemAttrs };
204
+ function useFairysValtioFormItemNoStyleAttrs(props) {
205
+ const { name, valuePropName = 'value', getValueFromEvent, formatValue, onAfterUpdate, trigger = 'onChange', children, attrs = {}, isJoinParentField = true, rules } = props;
206
+ const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
207
+ const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
208
+ name,
209
+ isJoinParentField
210
+ });
211
+ const value = useMemo(()=>get(state, paths), [
212
+ state,
213
+ paths
214
+ ]);
215
+ const error = errorState[_name];
216
+ formInstance.nameToPaths[_name] = paths;
217
+ if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
218
+ useEffect(()=>()=>{
219
+ formInstance.removeRules(_name);
220
+ }, [
221
+ _name
222
+ ]);
223
+ const onValueChange = (event)=>{
224
+ let value = event;
225
+ const target = event?.detail || event?.target;
226
+ if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
227
+ else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
228
+ if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
229
+ formInstance.updatedValueByPaths(_name, value);
230
+ if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
231
+ };
232
+ const baseControl = {
233
+ ...attrs,
234
+ name,
235
+ [valuePropName]: value,
236
+ [trigger]: onValueChange
237
+ };
238
+ return {
239
+ value,
240
+ error,
241
+ onValueChange,
242
+ state,
243
+ errorState,
244
+ formInstance,
245
+ _name,
246
+ name,
247
+ paths,
248
+ parentName,
249
+ formAttrsNameInstance,
250
+ children: /*#__PURE__*/ react.isValidElement(children) ? /*#__PURE__*/ react.cloneElement(children, {
251
+ ...baseControl
252
+ }) : children
253
+ };
254
+ }
255
+ 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,13 +49,25 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
44
49
  * 清理所有数据
45
50
  */
46
51
  clear: () => void;
47
- /**列规则 */
48
- rules: Record<PropertyKey, ((formData: T, instance: FairysValtioFormInstance<T>) => RuleItem[] | Promise<RuleItem[]>) | RuleItem[]>;
49
- /**规则验证
50
- * @param fields 列字段数组(可选)
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
+ /**验证表单项规则
61
+ * @param fields 要验证的字段(可选)
51
62
  * @param isReturn 是否返回验证结果(可选)
52
63
  */
53
64
  validate: (fields?: PropertyKey[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
65
+ /**
66
+ * 验证某些前缀的字段
67
+ * @param prefix 前缀字段数组
68
+ * @param isReturn 是否返回验证结果(可选)
69
+ */
70
+ validatePrefixFields: (prefix: string[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
54
71
  }
55
72
  /**声明实例*/
56
73
  export declare function useFairysValtioFormInstance<T extends MObject<T> = object>(instance?: FairysValtioFormInstance<T>): FairysValtioFormInstance<T>;