@fairys/valtio-form-basic 0.0.12 → 1.0.0

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.
Files changed (49) hide show
  1. package/README.md +935 -2
  2. package/esm/{form → common}/hooks/index.d.ts +1 -0
  3. package/esm/{form → common}/hooks/index.js +9 -1
  4. package/esm/common/index.d.ts +4 -0
  5. package/esm/common/index.js +4 -0
  6. package/esm/{form → common}/instance/index.d.ts +34 -7
  7. package/esm/{form → common}/instance/index.js +45 -11
  8. package/esm/{form → common}/utils/index.d.ts +7 -0
  9. package/esm/{form → common}/utils/index.js +11 -1
  10. package/esm/form/form.d.ts +14 -8
  11. package/esm/form/form.item.d.ts +18 -7
  12. package/esm/form/form.item.js +56 -32
  13. package/esm/form/form.js +7 -4
  14. package/esm/form/layout.d.ts +4 -2591
  15. package/esm/form/layout.js +7 -4
  16. package/esm/index.d.ts +1 -2
  17. package/esm/index.js +1 -2
  18. package/esm/styles/index.css +20 -4
  19. package/lib/common/hooks/index.d.ts +35 -0
  20. package/lib/common/hooks/index.js +117 -0
  21. package/lib/common/index.d.ts +4 -0
  22. package/lib/common/index.js +87 -0
  23. package/lib/common/instance/index.d.ts +108 -0
  24. package/lib/common/instance/index.js +269 -0
  25. package/lib/common/interface.d.ts +4 -0
  26. package/lib/common/interface.js +18 -0
  27. package/lib/common/utils/index.d.ts +31 -0
  28. package/lib/common/utils/index.js +119 -0
  29. package/lib/form/form.d.ts +82 -0
  30. package/lib/form/form.item.d.ts +228 -0
  31. package/lib/form/form.item.js +327 -0
  32. package/lib/form/form.js +54 -0
  33. package/lib/form/layout.d.ts +153 -0
  34. package/lib/form/layout.js +196 -0
  35. package/lib/index.d.ts +4 -0
  36. package/lib/index.js +18 -27
  37. package/lib/styles/index.css +308 -0
  38. package/package.json +5 -5
  39. package/src/{form → common}/hooks/index.tsx +9 -1
  40. package/src/common/index.ts +4 -0
  41. package/src/{form → common}/instance/index.ts +110 -21
  42. package/src/{form → common}/utils/index.ts +21 -0
  43. package/src/form/form.item.tsx +87 -40
  44. package/src/form/form.tsx +23 -9
  45. package/src/form/layout.tsx +9 -3
  46. package/src/index.tsx +4 -5
  47. /package/esm/{interface.d.ts → common/interface.d.ts} +0 -0
  48. /package/esm/{interface.js → common/interface.js} +0 -0
  49. /package/src/{interface.ts → common/interface.ts} +0 -0
@@ -32,3 +32,4 @@ export declare const useFairysValtioFormAttrsName: (options?: FairysValtioFormAt
32
32
  name: string;
33
33
  paths: (number | symbol)[] | (string | number)[];
34
34
  };
35
+ export declare const useId: (suffix?: string) => string;
@@ -54,4 +54,12 @@ const useFairysValtioFormAttrsName = (options = {})=>{
54
54
  paths: _paths
55
55
  };
56
56
  };
57
- export { FairysValtioFormParentAttrs, FairysValtioFormParentAttrsContext, useFairysValtioFormAttrsName, useFairysValtioFormParentAttrs, useFairysValtioFormParentAttrsContext, useFairysValtioFormParentAttrsState };
57
+ let localId = 0;
58
+ const useId = (suffix = 'form-item-input')=>{
59
+ const count = useRef(localId++);
60
+ return useMemo(()=>`fairys-valtio-form_${count.current.toString(32)}_${suffix}`, [
61
+ count.current,
62
+ suffix
63
+ ]);
64
+ };
65
+ export { FairysValtioFormParentAttrs, FairysValtioFormParentAttrsContext, useFairysValtioFormAttrsName, useFairysValtioFormParentAttrs, useFairysValtioFormParentAttrsContext, useFairysValtioFormParentAttrsState, useId };
@@ -0,0 +1,4 @@
1
+ export * from './hooks';
2
+ export * from './instance';
3
+ export * from './utils';
4
+ export * from './interface';
@@ -0,0 +1,4 @@
1
+ export * from "./hooks/index.js";
2
+ export * from "./instance/index.js";
3
+ export * from "./utils/index.js";
4
+ export * from "./interface.js";
@@ -1,7 +1,20 @@
1
- import { MObject } from '../../interface';
1
+ import { MObject } from '../interface';
2
2
  import { RuleItem, ValidateFieldsError, Values } from 'async-validator';
3
+ import { FairysValtioFormAttrsProps } from '../../form/form';
3
4
  /**表单实例*/
4
5
  export declare class FairysValtioFormInstance<T extends MObject<T> = Record<string, any>> {
6
+ /**
7
+ * 表单值改变时回调
8
+ * @param path 表单项路径
9
+ * @param value 表单项值
10
+ */
11
+ onValuesChange?: (path: PropertyKey, value: any) => void;
12
+ /***
13
+ * 判断值是否为代理对象
14
+ * @param value 值
15
+ * @returns 是否为代理对象
16
+ */
17
+ isValtioProxy: (value: any) => boolean;
5
18
  /**状态*/
6
19
  state: T;
7
20
  /**
@@ -14,7 +27,7 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
14
27
  ctor: (options?: {
15
28
  formData?: Partial<T>;
16
29
  hideState?: Record<PropertyKey, boolean>;
17
- initFormDataType?: "deepCopy" | "proxy" | "immutable";
30
+ initFormDataType?: FairysValtioFormAttrsProps["initFormDataType"];
18
31
  }) => void;
19
32
  /**
20
33
  * 更新数据
@@ -27,6 +40,12 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
27
40
  * @param value 值
28
41
  */
29
42
  updatedValueByPaths: (path: PropertyKey, value: any) => void;
43
+ /**表单项卸载移除保存值*/
44
+ removeValueByPaths: (path: PropertyKey) => void;
45
+ /**
46
+ * 清理值
47
+ */
48
+ clearValue: (fields?: PropertyKey[]) => this;
30
49
  /**
31
50
  * 更新行数据的隐藏信息
32
51
  * @param objectHideInfo 行数据隐藏信息对象
@@ -61,7 +80,7 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
61
80
  * @param fields 要验证的字段(可选)
62
81
  * @param isReturn 是否返回验证结果(可选)
63
82
  */
64
- validate: (fields?: PropertyKey[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
83
+ validate: (fields?: PropertyKey[], isReturn?: boolean) => Promise<ValidateFieldsError | Values | Partial<T>>;
65
84
  /**
66
85
  * 验证某些前缀的字段
67
86
  * @param prefix 前缀字段数组
@@ -70,12 +89,20 @@ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<stri
70
89
  validatePrefixFields: (prefix: string[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
71
90
  }
72
91
  /**声明实例*/
73
- export declare function useFairysValtioFormInstance<T extends MObject<T> = object>(instance?: FairysValtioFormInstance<T>): FairysValtioFormInstance<T>;
92
+ export declare function useFairysValtioFormInstance<T extends MObject<T> = Record<string, any>>(instance?: FairysValtioFormInstance<T>): FairysValtioFormInstance<T>;
74
93
  /**表单实例上下文*/
75
94
  export declare const FairysValtioFormInstanceContext: import("react").Context<FairysValtioFormInstance<any>>;
76
95
  /**表单实例上下文*/
77
- export declare function useFairysValtioFormInstanceContext<T extends MObject<T> = object>(): FairysValtioFormInstance<T>;
96
+ export declare function useFairysValtioFormInstanceContext<T extends MObject<T> = Record<string, any>>(): FairysValtioFormInstance<T>;
78
97
  /**状态取值*/
79
- export declare function useFairysValtioFormInstanceContextState<T extends MObject<T> = object>(): [T, Record<PropertyKey, string[]>, FairysValtioFormInstance<T>, any, any];
98
+ export declare function useFairysValtioFormInstanceContextState<T extends MObject<T> = Record<string, any>>(): [T, Record<PropertyKey, string[]>, FairysValtioFormInstance<T>, any, any];
80
99
  /**隐藏组件状态取值*/
81
- export declare function useFairysValtioFormInstanceContextHideState<T extends MObject<T> = object>(): [Record<PropertyKey, boolean>, FairysValtioFormInstance<T>, any];
100
+ export declare function useFairysValtioFormInstanceContextHideState<T extends MObject<T> = Record<string, any>>(): [Record<PropertyKey, boolean>, FairysValtioFormInstance<T>, any];
101
+ /**
102
+ * 传递表单实例获取状态
103
+ */
104
+ export declare function useFairysValtioFormInstanceToState<T extends MObject<T> = Record<string, any>>(formInstance: FairysValtioFormInstance<T>): T;
105
+ /**
106
+ * 传递表单实例获取隐藏状态
107
+ */
108
+ export declare function useFairysValtioFormInstanceToHideState<T extends MObject<T> = Record<string, any>>(formInstance: FairysValtioFormInstance<T>): Record<PropertyKey, boolean>;
@@ -1,19 +1,29 @@
1
1
  import { createContext, useContext, useRef } from "react";
2
- import { proxy, ref as external_valtio_ref, snapshot, useSnapshot } from "valtio";
2
+ import { proxy, ref as external_valtio_ref, snapshot, unstable_getInternalStates, 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
+ import { formatePath, get, isObject, removeValueByPaths, set } from "../utils/index.js";
6
6
  class FairysValtioFormInstance {
7
+ onValuesChange;
8
+ isValtioProxy = (value)=>{
9
+ const { refSet } = unstable_getInternalStates();
10
+ const canProxyDefault = (x)=>isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise);
11
+ return canProxyDefault(value);
12
+ };
7
13
  state = proxy({});
8
14
  errorState = proxy({});
9
15
  hideState = proxy({});
10
16
  ctor = (options)=>{
11
17
  const { formData, hideState, initFormDataType = 'deepCopy' } = options || {};
12
- this.errorState = proxy({});
13
- this.hideState = proxy(hideState ? copy(hideState) : {});
14
- if ('deepCopy' === initFormDataType) this.state = proxy(formData ? copy(formData) : {});
15
- else if ('proxy' === initFormDataType) this.state = proxy(formData);
16
- else if ('immutable' === initFormDataType) this.state = formData;
18
+ this.clear();
19
+ this.updatedHideInfo(hideState ? copy(hideState) : {});
20
+ const isValtioProxy = this.isValtioProxy(formData);
21
+ if (isValtioProxy) if ('deepCopy' === initFormDataType) this.updated(copy(snapshot(formData)), false);
22
+ else this.updated(formData, false);
23
+ else {
24
+ if ('deepCopy' === initFormDataType) this.updated(copy(formData || {}), false);
25
+ this.updated(formData || {}, false);
26
+ }
17
27
  };
18
28
  updated = (state, isValidate = true)=>{
19
29
  const keys = Object.keys(state);
@@ -28,6 +38,19 @@ class FairysValtioFormInstance {
28
38
  this.validate([
29
39
  path
30
40
  ], false);
41
+ this.onValuesChange?.(path, value);
42
+ };
43
+ removeValueByPaths = (path)=>{
44
+ removeValueByPaths(this.state, formatePath(path));
45
+ };
46
+ clearValue = (fields)=>{
47
+ let _fields = fields;
48
+ if (!Array.isArray(fields)) _fields = Object.keys(this.state);
49
+ for(let index = 0; index < _fields.length; index++){
50
+ const field = _fields[index];
51
+ delete this.state[field];
52
+ }
53
+ return this;
31
54
  };
32
55
  updatedHideInfo = (objectHideInfo)=>{
33
56
  const keys = Object.keys(objectHideInfo);
@@ -64,9 +87,12 @@ class FairysValtioFormInstance {
64
87
  return this;
65
88
  };
66
89
  clear = ()=>{
67
- this.state = proxy({});
68
- this.errorState = proxy({});
69
- this.hideState = proxy({});
90
+ this.clearValue();
91
+ this.clearHideInfo();
92
+ this.clearErrorInfo();
93
+ this.mountRules = {};
94
+ this.rules = {};
95
+ this.nameToPaths = {};
70
96
  };
71
97
  mountRules = {};
72
98
  removeRules = (name)=>{
@@ -167,4 +193,12 @@ function useFairysValtioFormInstanceContextHideState() {
167
193
  hideState.__defaultValue
168
194
  ];
169
195
  }
170
- export { FairysValtioFormInstance, FairysValtioFormInstanceContext, useFairysValtioFormInstance, useFairysValtioFormInstanceContext, useFairysValtioFormInstanceContextHideState, useFairysValtioFormInstanceContextState };
196
+ function useFairysValtioFormInstanceToState(formInstance) {
197
+ const state = useSnapshot(formInstance.state);
198
+ return state;
199
+ }
200
+ function useFairysValtioFormInstanceToHideState(formInstance) {
201
+ const hideState = useSnapshot(formInstance.hideState);
202
+ return hideState;
203
+ }
204
+ export { FairysValtioFormInstance, FairysValtioFormInstanceContext, useFairysValtioFormInstance, useFairysValtioFormInstanceContext, useFairysValtioFormInstanceContextHideState, useFairysValtioFormInstanceContextState, useFairysValtioFormInstanceToHideState, useFairysValtioFormInstanceToState };
@@ -14,6 +14,12 @@ export declare function set<T>(state: any, paths: PropertyKey[], nextValue: T):
14
14
  * @param segments 键路径
15
15
  */
16
16
  export declare function get<TDefault = unknown>(value: any, segments: PropertyKey[]): TDefault;
17
+ /***
18
+ * 移除值
19
+ * @param value 任意值
20
+ * @param segments 键路径
21
+ */
22
+ export declare function removeValueByPaths(value: any, segments: PropertyKey[]): void;
17
23
  /***
18
24
  * 格式化路径,将路径中的数组索引转换为数字
19
25
  * @param path 路径
@@ -22,3 +28,4 @@ export declare function get<TDefault = unknown>(value: any, segments: PropertyKe
22
28
  export declare function formatePath(path: PropertyKey): (number | symbol)[] | (string | number)[];
23
29
  /**格式化属性名*/
24
30
  export declare function formateName(name?: string, parentName?: string): string;
31
+ export declare const isObject: (x: unknown) => x is object;
@@ -20,6 +20,15 @@ function get(value, segments) {
20
20
  for (const key of segments)current = current?.[key];
21
21
  return current;
22
22
  }
23
+ function removeValueByPaths(value, segments) {
24
+ let current = value;
25
+ const lg = segments.length;
26
+ for(let index = 0; index < lg; index++){
27
+ const key = segments[index];
28
+ if (index === lg - 1) delete current[key];
29
+ else current = current?.[key];
30
+ }
31
+ }
23
32
  function formatePath(path) {
24
33
  if ('string' != typeof path) return [
25
34
  path
@@ -57,4 +66,5 @@ function formateName(name, parentName) {
57
66
  if (name) return name;
58
67
  return '';
59
68
  }
60
- export { formateName, formatePath, get, set };
69
+ const isObject = (x)=>'object' == typeof x && null !== x;
70
+ export { formateName, formatePath, get, isObject, removeValueByPaths, set };
@@ -1,9 +1,9 @@
1
- import { MObject } from '../interface';
2
- import { FairysValtioFormInstance } from './instance';
1
+ import { MObject } from '../common/interface';
2
+ import { FairysValtioFormInstance } from '../common/instance';
3
3
  import { type ReactNode } from 'react';
4
4
  import { FairysValtioFormLayoutAttrsProps } from './layout';
5
5
  import { RuleItem } from 'async-validator';
6
- export interface FairysValtioFormAttrsProps<T extends MObject<T> = object> extends FairysValtioFormLayoutAttrsProps {
6
+ export interface FairysValtioFormAttrsProps<T extends MObject<T> = Record<string, any>> extends FairysValtioFormLayoutAttrsProps {
7
7
  /**表单实例*/
8
8
  form?: FairysValtioFormInstance<T>;
9
9
  /**子元素*/
@@ -17,10 +17,15 @@ export interface FairysValtioFormAttrsProps<T extends MObject<T> = object> exten
17
17
  /**
18
18
  * 初始化表单数据类型,默认值为 deepCopy
19
19
  * - deepCopy:使用深度拷贝初始化表单数据
20
- * - proxy:使用代理对象初始化表单数据
21
- * - immutable:直接使用对象,不进行任何处理,注意,这个使用必须是`valtio`中的`proxy`声明的对象数据,否则表单项更新数据不会同步
20
+ * - immutable:直接使用对象(注意:当传递的不是`valtio`的`proxy`对象时,会使用`valtio`中的`proxy`声明)
22
21
  */
23
- initFormDataType?: 'deepCopy' | 'proxy' | 'immutable';
22
+ initFormDataType?: 'deepCopy' | 'immutable';
23
+ /**
24
+ * 表单值改变时回调
25
+ * @param path 表单项路径
26
+ * @param value 表单项值
27
+ */
28
+ onValuesChange?: (path: PropertyKey, value: any) => void;
24
29
  }
25
30
  /**
26
31
  * 表单属性处理
@@ -42,7 +47,7 @@ export const Form = (props: FormProps) => {
42
47
  }
43
48
  * ```
44
49
  */
45
- export declare function useFairysValtioForm<T extends MObject<T> = object>(props: FairysValtioFormAttrsProps<T>): {
50
+ export declare function useFairysValtioForm<T extends MObject<T> = Record<string, any>>(props: FairysValtioFormAttrsProps<T>, ref: React.Ref<FairysValtioFormInstance<T>>): {
46
51
  formInstance: FairysValtioFormInstance<T>;
47
52
  /**子元素*/
48
53
  children: ReactNode;
@@ -59,6 +64,7 @@ export declare function useFairysValtioForm<T extends MObject<T> = object>(props
59
64
  bordered?: boolean;
60
65
  boxShadow?: boolean;
61
66
  lastItemBordered?: boolean;
67
+ platform?: "pc" | "rn" | "taro";
62
68
  colCount?: number;
63
69
  errorLayout?: "bottom-left" | "bottom-right" | "top-right" | "top-left" | "left-border-top" | "right-border-top";
64
70
  labelMode?: "left" | "top" | "between";
@@ -68,7 +74,7 @@ export declare function useFairysValtioForm<T extends MObject<T> = object>(props
68
74
  formItemLabelStyle?: React.CSSProperties;
69
75
  formItemBodyClassName?: string;
70
76
  formItemBodyStyle?: React.CSSProperties;
71
- itemBorderType?: "bottom" | "body";
77
+ itemBorderType?: "bottom" | "body" | "none";
72
78
  itemBorderColor?: React.CSSProperties["borderColor"];
73
79
  isInvalidBorderRed?: boolean;
74
80
  isInvalidTextRed?: boolean;
@@ -1,11 +1,13 @@
1
1
  /**表单项*/
2
- import { MObject } from '../interface';
2
+ import { MObject } from '../common/interface';
3
3
  import React from 'react';
4
- import { FairysValtioFormInstance } from './instance';
4
+ import { FairysValtioFormInstance } from '../common/instance';
5
5
  import { FairysValtioFormLayoutContextOptions } from './layout';
6
- import { FairysValtioFormParentAttrs } from './hooks';
6
+ import { FairysValtioFormParentAttrs } from '../common/hooks';
7
7
  import { RuleItem } from 'async-validator';
8
- export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
8
+ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = Record<string, any>> {
9
+ /**平台*/
10
+ platform?: 'pc' | 'rn' | 'taro';
9
11
  /**
10
12
  * 表单项名称 ,字段需要和存储的字段路径一致
11
13
  *
@@ -22,6 +24,8 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
22
24
  label?: string;
23
25
  /**传递组件字段*/
24
26
  valuePropName?: string;
27
+ /**取值字段(默认 valuePropName字段值)*/
28
+ getValuePath?: string;
25
29
  /**自定义获取值*/
26
30
  getValueFromEvent?: (event: any, form: FairysValtioFormInstance<T>) => any;
27
31
  /**值格式化*/
@@ -73,6 +77,10 @@ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
73
77
  isJoinParentField?: boolean;
74
78
  /**校验规则*/
75
79
  rules?: RuleItem[];
80
+ /**卸载移除数据值
81
+ * @default true
82
+ */
83
+ isRemoveValueOnUnmount?: boolean;
76
84
  }
77
85
  /**
78
86
  * 处理表单表单项属性
@@ -117,8 +125,8 @@ export const FormItem = (props: FormItemProps) => {
117
125
  * ```
118
126
  *
119
127
  */
120
- export declare function useFairysValtioFormItemAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>): FairysValtioFormItemAttrsReturn<T>;
121
- export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object> {
128
+ export declare function useFairysValtioFormItemAttrs<T extends MObject<T> = Record<string, any>>(props: FairysValtioFormItemAttrsProps<T>): FairysValtioFormItemAttrsReturn<T>;
129
+ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = Record<string, any>> {
122
130
  /**表单项值*/
123
131
  value?: any;
124
132
  /**是否校验错误*/
@@ -151,6 +159,8 @@ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object>
151
159
  _name?: string;
152
160
  /**表单项名称*/
153
161
  name?: string;
162
+ /**表单项ID*/
163
+ id?: string;
154
164
  /**表单项路径*/
155
165
  paths?: (string | number)[];
156
166
  /**父级字段名*/
@@ -201,7 +211,7 @@ export const FormItem = (props: FormItemProps) => {
201
211
  }
202
212
  * ```
203
213
  */
204
- export declare function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>): {
214
+ export declare function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T> = Record<string, any>>(props: FairysValtioFormItemAttrsProps<T>): {
205
215
  value: unknown;
206
216
  error: string[];
207
217
  onValueChange: (event: any) => void;
@@ -210,6 +220,7 @@ export declare function useFairysValtioFormItemNoStyleAttrs<T extends MObject<T>
210
220
  formInstance: FairysValtioFormInstance<T>;
211
221
  _name: string;
212
222
  name: string;
223
+ id: string;
213
224
  paths: (number | symbol)[] | (string | number)[];
214
225
  parentName: string;
215
226
  formAttrsNameInstance: FairysValtioFormParentAttrs;
@@ -1,9 +1,9 @@
1
1
  import react, { useEffect, useMemo } from "react";
2
2
  import clsx from "clsx";
3
- import { useFairysValtioFormInstanceContextState } from "./instance/index.js";
3
+ import { useFairysValtioFormInstanceContextState } from "../common/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
+ import { useFairysValtioFormAttrsName, useId } from "../common/hooks/index.js";
6
+ import { formatePath, get } from "../common/utils/index.js";
7
7
  function useFairysValtioFormItemAttrs(props) {
8
8
  const [layoutAttrs] = useFairysValtioFormLayoutContext();
9
9
  const colCount = layoutAttrs.colCount || 1;
@@ -20,7 +20,8 @@ function useFairysValtioFormItemAttrs(props) {
20
20
  const parent_isInvalidBorderRed = layoutAttrs.isInvalidBorderRed;
21
21
  const parent_isInvalidTextRed = layoutAttrs.isInvalidTextRed;
22
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;
23
+ const parent_platform = layoutAttrs.platform;
24
+ const { name, valuePropName = 'value', getValuePath = valuePropName, 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, platform = parent_platform, isRemoveValueOnUnmount = true } = props;
24
25
  const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
25
26
  name,
26
27
  isJoinParentField
@@ -32,25 +33,34 @@ function useFairysValtioFormItemAttrs(props) {
32
33
  ]);
33
34
  const error = errorState[_name];
34
35
  const _formItemRules = formInstance.rules?.[_name];
36
+ const id = useId(_name);
35
37
  formInstance.nameToPaths[_name] = paths;
36
- if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
37
- useEffect(()=>()=>{
38
+ useEffect(()=>{
39
+ if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
40
+ return ()=>{
38
41
  formInstance.removeRules(_name);
39
- }, [
40
- _name
42
+ };
43
+ }, [
44
+ _name,
45
+ rules
41
46
  ]);
42
47
  const onValueChange = (event)=>{
43
- let value = event;
48
+ let _value = event;
44
49
  const target = event?.detail || event?.target;
45
- if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
46
- else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
47
- if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
48
- formInstance.updatedValueByPaths(_name, value);
49
- if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
50
+ if ('function' == typeof getValueFromEvent) _value = getValueFromEvent(event, formInstance);
51
+ else if (event && target && 'object' == typeof target && getValuePath in target) _value = get(target, formatePath(getValuePath));
52
+ if ('function' == typeof formatValue) _value = formatValue(_value, formInstance, event);
53
+ if (value === _value) return;
54
+ formInstance.updatedValueByPaths(_name, _value);
55
+ if ('function' == typeof onAfterUpdate) onAfterUpdate(_value, formInstance, event);
50
56
  };
57
+ useEffect(()=>()=>{
58
+ if (isRemoveValueOnUnmount) formInstance.removeValueByPaths(_name);
59
+ }, []);
51
60
  const baseControl = {
52
61
  ...attrs,
53
62
  name,
63
+ id,
54
64
  [valuePropName]: value,
55
65
  [trigger]: onValueChange
56
66
  };
@@ -104,10 +114,9 @@ function useFairysValtioFormItemAttrs(props) {
104
114
  isRequired,
105
115
  showColon
106
116
  ]);
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', {
117
+ 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 fairystaroform__items-start', {
108
118
  'fairystaroform__flex-row fairystaroform__justify-start': 'left' === labelMode,
109
119
  'fairystaroform__flex-row fairystaroform__justify-end': 'between' === labelMode || 'top' === labelMode,
110
- 'fairystaroform__flex-row': 'top' === labelMode,
111
120
  'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' === itemBorderType,
112
121
  'fairys-valtio-form-item-invalid-border-red': isInvalid && isInvalidBorderRed && 'body' === itemBorderType
113
122
  }, parent_formItemBodyClassName, bodyClassName), [
@@ -127,14 +136,18 @@ function useFairysValtioFormItemAttrs(props) {
127
136
  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
137
  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
138
  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,
139
+ 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'bottom-left' === errorLayout && 'pc' !== platform,
140
+ 'fairystaroform__bottom-_zkh1_-10px_zhk2_ fairystaroform__left-0 fairystaroform__justify-start': 'bottom-left' === errorLayout && 'pc' === platform,
141
+ 'fairystaroform__bottom-_zkh1_-14px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'bottom-right' === errorLayout && 'pc' !== platform,
142
+ 'fairystaroform__bottom-_zkh1_-10px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'bottom-right' === errorLayout && 'pc' === platform,
132
143
  'fairystaroform__top-_zkh1_-4px_zhk2_ fairystaroform__right-0 fairystaroform__justify-end': 'top-right' === errorLayout,
133
144
  '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
145
+ 'fairystaroform__left-0 fairystaroform__bottom-_zkh1_-2px_zhk2_ fairystaroform__justify-start': 'left-border-top' === errorLayout,
146
+ 'fairystaroform__right-0 fairystaroform__bottom-_zkh1_-2px_zhk2_ fairystaroform__justify-end': 'right-border-top' === errorLayout,
147
+ 'fairystaroform__px-_zkh1_4px_zhk2_': 'pc' === platform
136
148
  }), [
137
- errorLayout
149
+ errorLayout,
150
+ platform
138
151
  ]);
139
152
  const styleBase = useMemo(()=>{
140
153
  const css = {};
@@ -166,6 +179,7 @@ function useFairysValtioFormItemAttrs(props) {
166
179
  error,
167
180
  _name,
168
181
  name,
182
+ id,
169
183
  paths,
170
184
  parentName,
171
185
  formAttrsNameInstance,
@@ -202,36 +216,45 @@ function useFairysValtioFormItemAttrs(props) {
202
216
  };
203
217
  }
204
218
  function useFairysValtioFormItemNoStyleAttrs(props) {
205
- const { name, valuePropName = 'value', getValueFromEvent, formatValue, onAfterUpdate, trigger = 'onChange', children, attrs = {}, isJoinParentField = true, rules } = props;
219
+ const { name, valuePropName = 'value', getValuePath = valuePropName, getValueFromEvent, formatValue, onAfterUpdate, trigger = 'onChange', children, attrs = {}, isJoinParentField = true, rules, isRemoveValueOnUnmount = true } = props;
206
220
  const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
207
221
  const { name: _name, paths, parentName, formAttrsNameInstance } = useFairysValtioFormAttrsName({
208
222
  name,
209
223
  isJoinParentField
210
224
  });
225
+ const id = useId(_name);
211
226
  const value = useMemo(()=>get(state, paths), [
212
227
  state,
213
228
  paths
214
229
  ]);
215
230
  const error = errorState[_name];
216
231
  formInstance.nameToPaths[_name] = paths;
217
- if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
218
- useEffect(()=>()=>{
232
+ useEffect(()=>{
233
+ if (Array.isArray(rules) && rules.length) formInstance.mountRules[_name] = rules;
234
+ return ()=>{
219
235
  formInstance.removeRules(_name);
220
- }, [
221
- _name
236
+ };
237
+ }, [
238
+ _name,
239
+ rules
222
240
  ]);
223
241
  const onValueChange = (event)=>{
224
- let value = event;
242
+ let _value = event;
225
243
  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);
244
+ if ('function' == typeof getValueFromEvent) _value = getValueFromEvent(event, formInstance);
245
+ else if (event && target && 'object' == typeof target && getValuePath in target) _value = get(target, formatePath(getValuePath));
246
+ if ('function' == typeof formatValue) _value = formatValue(_value, formInstance, event);
247
+ if (value === _value) return;
248
+ formInstance.updatedValueByPaths(_name, _value);
249
+ if ('function' == typeof onAfterUpdate) onAfterUpdate(_value, formInstance, event);
231
250
  };
251
+ useEffect(()=>()=>{
252
+ if (isRemoveValueOnUnmount) formInstance.removeValueByPaths(_name);
253
+ }, []);
232
254
  const baseControl = {
233
255
  ...attrs,
234
256
  name,
257
+ id,
235
258
  [valuePropName]: value,
236
259
  [trigger]: onValueChange
237
260
  };
@@ -244,6 +267,7 @@ function useFairysValtioFormItemNoStyleAttrs(props) {
244
267
  formInstance,
245
268
  _name,
246
269
  name,
270
+ id,
247
271
  paths,
248
272
  parentName,
249
273
  formAttrsNameInstance,
package/esm/form/form.js CHANGED
@@ -1,14 +1,17 @@
1
- import { useFairysValtioFormInstance } from "./instance/index.js";
2
- import { useMemo } from "react";
3
- function useFairysValtioForm(props) {
4
- const { form, rules, formData, hideState, initFormDataType = 'deepCopy', ...rest } = props;
1
+ import { useFairysValtioFormInstance } from "../common/instance/index.js";
2
+ import { useEffect, useImperativeHandle, useMemo } from "react";
3
+ function useFairysValtioForm(props, ref) {
4
+ const { form, rules, formData, hideState, initFormDataType = 'deepCopy', onValuesChange, ...rest } = props;
5
5
  const formInstance = useFairysValtioFormInstance(form);
6
6
  formInstance.rules = rules;
7
+ formInstance.onValuesChange = onValuesChange;
7
8
  useMemo(()=>formInstance.ctor({
8
9
  formData,
9
10
  hideState,
10
11
  initFormDataType
11
12
  }), []);
13
+ useImperativeHandle(ref, ()=>formInstance);
14
+ useEffect(()=>()=>formInstance.clear(), []);
12
15
  return {
13
16
  ...rest,
14
17
  formInstance