@fairys/valtio-form-basic 0.0.8

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/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # valtio-form-basic
2
+
3
+ 使用 valtio 实现的表单基础库, 使其更加便捷,同时支持`PC`、`H5`、`Taro`,同时也更加灵活。
4
+
5
+
6
+ ## 安装
7
+
8
+ ```bash
9
+ npm install @fairys/valtio-form-basic # yarn add @fairys/valtio-form-basic # pnpm add @fairys/valtio-form-basic
10
+ ```
@@ -0,0 +1,66 @@
1
+ import { MObject } from '../interface';
2
+ import { FairysValtioFormInstance } from './instance';
3
+ import { type ReactNode } from 'react';
4
+ import { FairysValtioFormLayoutAttrsProps } from './layout';
5
+ export interface FairysValtioFormAttrsProps<T extends MObject<T> = object> extends FairysValtioFormLayoutAttrsProps {
6
+ /**表单实例*/
7
+ form?: FairysValtioFormInstance<T>;
8
+ /**子元素*/
9
+ children: ReactNode;
10
+ /**表单项规则*/
11
+ rules?: FairysValtioFormInstance<T>['rules'];
12
+ /**表单初始值*/
13
+ formData?: FairysValtioFormInstance<T>['state'];
14
+ /**表单隐藏状态*/
15
+ hideState?: FairysValtioFormInstance<T>['hideState'];
16
+ /**formData 是否进行深度拷贝,如果不是则直接把 formData 赋值到 state ,否则使用 copy 方法深度拷贝后赋值 */
17
+ isDeepCopy?: boolean;
18
+ }
19
+ /**
20
+ * 表单属性处理
21
+ *
22
+ * @example
23
+ *
24
+ * ```tsx
25
+ import { useFairysValtioForm } from "@fairys/valtio-form"
26
+ import type { FairysValtioFormAttrProps } from "@fairys/valtio-form"
27
+ export interface FormProps extends FairysValtioFormAttrProps{}
28
+
29
+ export const Form = (props: FormProps) => {
30
+ const { formInstance,children, ...rest } = useFairysValtioForm(props)
31
+ return (
32
+ <FairysValtioFormInstanceContext.Provider value={formInstance}>
33
+ <布局组件 {...rest}>{children}</布局组件>
34
+ </FairysValtioFormInstanceContext.Provider>
35
+ );
36
+ }
37
+ * ```
38
+ */
39
+ export declare function useFairysValtioForm<T extends MObject<T> = object>(props: FairysValtioFormAttrsProps<T>): {
40
+ formInstance: FairysValtioFormInstance<T>;
41
+ /**子元素*/
42
+ children: ReactNode;
43
+ gap?: string | number;
44
+ title?: React.ReactNode;
45
+ extra?: React.ReactNode;
46
+ isAllColSpan?: boolean;
47
+ className?: string;
48
+ style?: React.CSSProperties;
49
+ headerClassName?: string;
50
+ headerStyle?: React.CSSProperties;
51
+ bodyClassName?: string;
52
+ bodyStyle?: React.CSSProperties;
53
+ bordered?: boolean;
54
+ boxShadow?: boolean;
55
+ lastItemBordered?: boolean;
56
+ colCount?: number;
57
+ errorLayout?: "left-bottom" | "right-bottom" | "top-right" | "top-left";
58
+ labelMode?: "left" | "top" | "between";
59
+ formItemClassName?: string;
60
+ formItemStyle?: React.CSSProperties;
61
+ formItemLabelClassName?: string;
62
+ formItemLabelStyle?: React.CSSProperties;
63
+ formItemBodyClassName?: string;
64
+ formItemBodyStyle?: React.CSSProperties;
65
+ borderedType?: "bottom" | "body";
66
+ };
@@ -0,0 +1,150 @@
1
+ /**表单项*/
2
+ import { MObject } from '../interface';
3
+ import React from 'react';
4
+ import { FairysValtioFormInstance } from './instance';
5
+ import { FairysValtioFormLayoutContextOptions } from './layout';
6
+ export interface FairysValtioFormItemAttrsProps<T extends MObject<T> = object> {
7
+ /**表单项名称*/
8
+ name: string;
9
+ /**表单项标签*/
10
+ label?: string;
11
+ /**传递组件字段*/
12
+ valuePropName?: string;
13
+ /**自定义获取值*/
14
+ getValueFromEvent?: (event: any, form: FairysValtioFormInstance<T>) => any;
15
+ /**值格式化*/
16
+ formatValue?: (value: any, form: FairysValtioFormInstance<T>, event: any) => any;
17
+ /**触发数据更新之后触发(用于数据联动之类的)*/
18
+ onAfterUpdate?: (value: any, form: FairysValtioFormInstance<T>, event: any) => void;
19
+ /**事件名称*/
20
+ trigger?: string;
21
+ className?: string;
22
+ style?: React.CSSProperties;
23
+ labelClassName?: string;
24
+ labelStyle?: React.CSSProperties;
25
+ bodyClassName?: string;
26
+ bodyStyle?: React.CSSProperties;
27
+ children?: React.ReactNode;
28
+ /**规则校验失败错误提示位置*/
29
+ errorLayout?: 'left-bottom' | 'right-bottom' | 'top-right' | 'top-left';
30
+ /**label显示模式*/
31
+ labelMode?: 'left' | 'top' | 'between';
32
+ /**额外内容*/
33
+ extra?: React.ReactNode;
34
+ /**底部提示内容*/
35
+ helpText?: React.ReactNode;
36
+ /**
37
+ * 表单项占据列数
38
+ * @default 1
39
+ */
40
+ colSpan?: number;
41
+ /**
42
+ * 表单项占据行数
43
+ * @default 1
44
+ */
45
+ rowSpan?: number;
46
+ /**是否必填*/
47
+ isRequired?: boolean;
48
+ /**是否显示冒号*/
49
+ showColon?: boolean;
50
+ /**底部显示边框*/
51
+ borderedType?: FairysValtioFormLayoutContextOptions['borderedType'];
52
+ /**输入框属性*/
53
+ attrs?: any;
54
+ }
55
+ /**
56
+ * 处理表单表单项属性
57
+ *
58
+ * @example
59
+ *
60
+ * ```tsx
61
+ import { Fragment } from 'react'
62
+ import { useFairysValtioFormItemAttrs } from "@fairys/valtio-form"
63
+ import type { FairysValtioFormItemAttrsProps } from "@fairys/valtio-form"
64
+ export interface FormItemProps extends FairysValtioFormItemAttrsProps{}
65
+
66
+ export const FormItem = (props: FormItemProps) => {
67
+ const { label, extra, helpText } = props
68
+ const {
69
+ itemClassName, itemStyle, containerClassName, itemLabelClassName, itemLabelStyle,
70
+ itemBodyClassName, itemBodyStyle, itemInputClassName, itemExtraClassName, errorClassName, helpClassName,
71
+ isInvalid, borderedType, children, error
72
+ } = useFairysValtioFormItemAttrs(props)
73
+
74
+ return (
75
+ <View className={itemClassName} style={itemStyle}>
76
+ <View className={containerClassName}>
77
+ <View className={itemLabelClassName} style={itemLabelStyle}>
78
+ {label}
79
+ </View>
80
+ <View className={itemBodyClassName} style={itemBodyStyle}>
81
+ <View className={itemInputClassName}>
82
+ {children}
83
+ </View>
84
+ {extra ? <View className={itemExtraClassName}>{extra}</View> : <Fragment />}
85
+ {borderedType === 'body' && isInvalid ? <View className={errorClassName}>{error}</View> : <Fragment />}
86
+ </View>
87
+ </View>
88
+ {helpText ? <View className={helpClassName}>{helpText}</View> : <Fragment />}
89
+ {isInvalid && borderedType !== 'body' ? <View className={errorClassName}>{error}</View> : <Fragment />}
90
+ </View>
91
+ );
92
+ }
93
+ * ```
94
+ *
95
+ */
96
+ export declare function useFairysValtioFormItemAttrs<T extends MObject<T> = object>(props: FairysValtioFormItemAttrsProps<T>): FairysValtioFormItemAttrsReturn<T>;
97
+ export interface FairysValtioFormItemAttrsReturn<T extends MObject<T> = object> {
98
+ /**表单项值*/
99
+ value?: any;
100
+ /**是否校验错误*/
101
+ isInvalid?: boolean;
102
+ /**边框类型*/
103
+ borderedType?: FairysValtioFormLayoutContextOptions['borderedType'];
104
+ /**值改变事件*/
105
+ onValueChange?: (event: any) => void;
106
+ /**当前表单项占据列数*/
107
+ colSpan?: number;
108
+ /**当前表单项占据行数*/
109
+ rowSpan?: number;
110
+ /**列数*/
111
+ colCount?: number;
112
+ /**标签显示模式*/
113
+ labelMode?: FairysValtioFormLayoutContextOptions['labelMode'];
114
+ /**错误提示位置*/
115
+ errorLayout?: FairysValtioFormLayoutContextOptions['errorLayout'];
116
+ /**是否必填*/
117
+ isRequired?: boolean;
118
+ /**表单状态*/
119
+ state?: T;
120
+ /**错误状态*/
121
+ errorState?: Record<PropertyKey, string[]>;
122
+ /**表单实例*/
123
+ formInstance?: FairysValtioFormInstance<T>;
124
+ /**错误信息*/
125
+ error?: string[];
126
+ /**表单项类名*/
127
+ itemClassName: string;
128
+ /**表单项样式*/
129
+ itemStyle: React.CSSProperties;
130
+ /**容器类名*/
131
+ containerClassName: string;
132
+ /**标签类名*/
133
+ itemLabelClassName: string;
134
+ /**标签样式*/
135
+ itemLabelStyle: React.CSSProperties;
136
+ /**体类名*/
137
+ itemBodyClassName: string;
138
+ /**体样式*/
139
+ itemBodyStyle: React.CSSProperties;
140
+ /**输入框类名*/
141
+ itemInputClassName: string;
142
+ /**额外内容类名*/
143
+ itemExtraClassName: string;
144
+ /**错误提示类名*/
145
+ errorClassName: string;
146
+ /**帮助提示类名*/
147
+ helpClassName: string;
148
+ /**子元素*/
149
+ children?: React.ReactNode;
150
+ }
@@ -0,0 +1,163 @@
1
+ import react, { useMemo } from "react";
2
+ import clsx from "clsx";
3
+ import { useFairysValtioFormInstanceContextState } from "./instance/index.js";
4
+ import { useFairysValtioFormLayoutContext } from "./layout.js";
5
+ function useFairysValtioFormItemAttrs(props) {
6
+ const [layoutAttrs] = useFairysValtioFormLayoutContext();
7
+ const colCount = layoutAttrs.colCount || 1;
8
+ const parent_borderedType = layoutAttrs.borderedType || 'bottom';
9
+ const parent_errorLayout = layoutAttrs.errorLayout || 'right-bottom';
10
+ const parent_formItemClassName = layoutAttrs.formItemClassName;
11
+ const parent_formItemLabelClassName = layoutAttrs.formItemLabelClassName;
12
+ const parent_formItemLabelStyle = layoutAttrs.formItemLabelStyle;
13
+ const parent_formItemStyle = layoutAttrs.formItemStyle;
14
+ const parent_formItemBodyClassName = layoutAttrs.formItemBodyClassName;
15
+ const parent_formItemBodyStyle = layoutAttrs.formItemBodyStyle;
16
+ 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;
18
+ const [state, errorState, formInstance] = useFairysValtioFormInstanceContextState();
19
+ const rules = formInstance.rules?.[name];
20
+ const value = state[name];
21
+ const error = errorState[name];
22
+ const onValueChange = (event)=>{
23
+ let value = event;
24
+ const target = event?.detail || event?.target;
25
+ if ('function' == typeof getValueFromEvent) value = getValueFromEvent(event, formInstance);
26
+ else if (event && target && 'object' == typeof target && valuePropName in target) value = target.valuePropName;
27
+ if ('function' == typeof formatValue) value = formatValue(value, formInstance, event);
28
+ formInstance.updated({
29
+ [name]: value
30
+ });
31
+ if ('function' == typeof onAfterUpdate) onAfterUpdate(value, formInstance, event);
32
+ };
33
+ const baseControl = {
34
+ ...attrs,
35
+ name,
36
+ [valuePropName]: value,
37
+ [trigger]: onValueChange
38
+ };
39
+ const isRequired = useMemo(()=>{
40
+ if (_isRequired) return _isRequired;
41
+ if (Array.isArray(rules) && rules.length) return rules.some((rule)=>rule.required);
42
+ return false;
43
+ }, [
44
+ rules,
45
+ formInstance
46
+ ]);
47
+ const isInvalid = useMemo(()=>{
48
+ if (Array.isArray(error) && error.length) return true;
49
+ return false;
50
+ }, [
51
+ error
52
+ ]);
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,
55
+ [labelMode]: labelMode
56
+ }, className, parent_formItemClassName), [
57
+ className,
58
+ parent_formItemClassName,
59
+ labelMode,
60
+ borderedType
61
+ ]);
62
+ const itemContainer_cls = useMemo(()=>clsx('fairys-valtio-form-item-container fairystaroform__flex-1 fairystaroform__h-full fairystaroform__flex fairystaroform__box-border', {
63
+ 'fairystaroform__flex-row fairystaroform__items-center fairystaroform__justify-between fairystaroform__gap-_zkh1_8px_zhk2_': 'between' === labelMode,
64
+ 'fairystaroform__flex-col fairystaroform__gap-_zkh1_4px_zhk2_': 'top' === labelMode,
65
+ 'fairystaroform__flex-row fairystaroform__gap-_zkh1_8px_zhk2_': 'left' === labelMode
66
+ }, labelClassName), [
67
+ labelClassName,
68
+ labelMode
69
+ ]);
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', {
71
+ 'fairystaroform__justify-start': 'left' !== labelMode,
72
+ 'fairystaroform__justify-end': 'left' === labelMode,
73
+ required: isRequired,
74
+ 'show-colon': showColon
75
+ }, labelClassName, parent_formItemLabelClassName), [
76
+ labelClassName,
77
+ parent_formItemLabelClassName,
78
+ labelMode,
79
+ isRequired,
80
+ showColon
81
+ ]);
82
+ const itemBody_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__relative fairystaroform__flex-1 fairystaroform__flex fairystaroform__box-border', {
83
+ 'fairystaroform__flex-row fairystaroform__justify-start': 'left' === labelMode,
84
+ 'fairystaroform__flex-row fairystaroform__justify-end': 'between' === labelMode || 'top' === labelMode,
85
+ 'fairystaroform__flex-row': 'top' === labelMode,
86
+ 'fairystaroform__border-b fairystaroform__border-b-solid fairystaroform__border-b-gray-200 ': 'body' === borderedType
87
+ }, bodyClassName, parent_formItemBodyClassName), [
88
+ bodyClassName,
89
+ labelMode,
90
+ borderedType,
91
+ parent_formItemBodyClassName
92
+ ]);
93
+ const itemInput_cls = useMemo(()=>clsx('fairys-valtio-form-item-body fairystaroform__flex fairystaroform__flex-row fairystaroform__flex-1 fairystaroform__box-border', {
94
+ 'fairystaroform__justify-end fairystaroform__text-right': 'between' === labelMode,
95
+ 'fairystaroform__justify-start fairystaroform__text-left fairystaroform__items-center': 'between' !== labelMode
96
+ }), [
97
+ labelMode
98
+ ]);
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
106
+ }), [
107
+ errorLayout
108
+ ]);
109
+ const styleBase = useMemo(()=>{
110
+ const css = {};
111
+ if (colSpan) {
112
+ const end = colCount > colSpan ? colSpan : colCount;
113
+ css.gridColumnEnd = `span ${end}`;
114
+ }
115
+ if (rowSpan) css.gridRowEnd = `span ${rowSpan}`;
116
+ return css;
117
+ }, [
118
+ colSpan,
119
+ rowSpan,
120
+ colCount
121
+ ]);
122
+ return {
123
+ value,
124
+ isInvalid,
125
+ borderedType,
126
+ onValueChange,
127
+ colSpan,
128
+ rowSpan,
129
+ colCount,
130
+ labelMode,
131
+ errorLayout,
132
+ isRequired,
133
+ state,
134
+ errorState,
135
+ formInstance,
136
+ error,
137
+ itemClassName: item_cls,
138
+ itemStyle: {
139
+ ...parent_formItemStyle || {},
140
+ ...styleBase,
141
+ ...style || {}
142
+ },
143
+ containerClassName: itemContainer_cls,
144
+ itemLabelClassName: itemLabel_cls,
145
+ itemLabelStyle: {
146
+ ...parent_formItemLabelStyle || {},
147
+ ...labelStyle || {}
148
+ },
149
+ itemBodyClassName: itemBody_cls,
150
+ itemBodyStyle: {
151
+ ...parent_formItemBodyStyle || {},
152
+ ...bodyStyle || {}
153
+ },
154
+ itemInputClassName: itemInput_cls,
155
+ itemExtraClassName: itemExtra_cls,
156
+ errorClassName: itemError_cls,
157
+ helpClassName: itemHelp_cls,
158
+ children: /*#__PURE__*/ react.isValidElement(children) ? /*#__PURE__*/ react.cloneElement(children, {
159
+ ...baseControl
160
+ }) : children
161
+ };
162
+ }
163
+ export { useFairysValtioFormItemAttrs };
@@ -0,0 +1,17 @@
1
+ import { useFairysValtioFormInstance } from "./instance/index.js";
2
+ import { useMemo } from "react";
3
+ function useFairysValtioForm(props) {
4
+ const { form, rules, formData, hideState, isDeepCopy = true, ...rest } = props;
5
+ const formInstance = useFairysValtioFormInstance(form);
6
+ formInstance.rules = rules;
7
+ useMemo(()=>formInstance.ctor({
8
+ formData,
9
+ hideState,
10
+ isDeepCopy
11
+ }), []);
12
+ return {
13
+ ...rest,
14
+ formInstance
15
+ };
16
+ }
17
+ export { useFairysValtioForm };
@@ -0,0 +1,64 @@
1
+ import { MObject } from '../../interface';
2
+ import { RuleItem, ValidateFieldsError, Values } from 'async-validator';
3
+ /**表单实例*/
4
+ export declare class FairysValtioFormInstance<T extends MObject<T> = Record<string, any>> {
5
+ /**状态*/
6
+ state: T;
7
+ /**
8
+ * 错误信息
9
+ */
10
+ errorState: Record<PropertyKey, string[]>;
11
+ /**隐藏状态*/
12
+ hideState: Record<PropertyKey, boolean>;
13
+ /**初始化表单值*/
14
+ ctor: (options?: {
15
+ formData?: Partial<T>;
16
+ hideState?: Record<PropertyKey, boolean>;
17
+ isDeepCopy?: boolean;
18
+ }) => void;
19
+ /**
20
+ * 更新数据
21
+ * @param state 更新数据对象
22
+ * @param isValidate 是否验证(可选)
23
+ */
24
+ updated: <M = T>(state: Partial<M>, isValidate?: boolean) => void;
25
+ /**
26
+ * 更新行数据的隐藏信息
27
+ * @param objectHideInfo 行数据隐藏信息对象
28
+ */
29
+ updatedHideInfo: (objectHideInfo: Record<PropertyKey, boolean>) => this;
30
+ /**
31
+ * 清理隐藏信息
32
+ */
33
+ clearHideInfo: (fields?: PropertyKey[]) => this;
34
+ /**
35
+ * 更新行数据的错误信息
36
+ * @param objectErrorInfo 行数据错误信息对象
37
+ */
38
+ updatedErrorInfo: (objectErrorInfo: Record<PropertyKey, string[]>) => this;
39
+ /**
40
+ * 清理错误信息
41
+ */
42
+ clearErrorInfo: (fields?: PropertyKey[]) => this;
43
+ /**
44
+ * 清理所有数据
45
+ */
46
+ clear: () => void;
47
+ /**列规则 */
48
+ rules: Record<PropertyKey, ((formData: T, instance: FairysValtioFormInstance<T>) => RuleItem[] | Promise<RuleItem[]>) | RuleItem[]>;
49
+ /**规则验证
50
+ * @param fields 列字段数组(可选)
51
+ * @param isReturn 是否返回验证结果(可选)
52
+ */
53
+ validate: (fields?: PropertyKey[], isReturn?: boolean) => Promise<ValidateFieldsError | Values>;
54
+ }
55
+ /**声明实例*/
56
+ export declare function useFairysValtioFormInstance<T extends MObject<T> = object>(instance?: FairysValtioFormInstance<T>): FairysValtioFormInstance<T>;
57
+ /**表单实例上下文*/
58
+ export declare const FairysValtioFormInstanceContext: import("react").Context<FairysValtioFormInstance<any>>;
59
+ /**表单实例上下文*/
60
+ export declare function useFairysValtioFormInstanceContext<T extends MObject<T> = object>(): FairysValtioFormInstance<T>;
61
+ /**状态取值*/
62
+ export declare function useFairysValtioFormInstanceContextState<T extends MObject<T> = object>(): [T, Record<PropertyKey, string[]>, FairysValtioFormInstance<T>, any, any];
63
+ /**隐藏组件状态取值*/
64
+ export declare function useFairysValtioFormInstanceContextHideState<T extends MObject<T> = object>(): [Record<PropertyKey, boolean>, FairysValtioFormInstance<T>, any];
@@ -0,0 +1,140 @@
1
+ import { createContext, useContext, useRef } from "react";
2
+ import { proxy, ref as external_valtio_ref, snapshot, useSnapshot } from "valtio";
3
+ import async_validator from "async-validator";
4
+ import { copy } from "fast-copy";
5
+ class FairysValtioFormInstance {
6
+ state = proxy({});
7
+ errorState = proxy({});
8
+ hideState = proxy({});
9
+ ctor = (options)=>{
10
+ const { formData, hideState, isDeepCopy = true } = options || {};
11
+ this.errorState = proxy({});
12
+ this.hideState = proxy(hideState ? copy(hideState) : {});
13
+ if (isDeepCopy) this.state = proxy(formData ? copy(formData) : {});
14
+ else if (formData) this.state = proxy(formData);
15
+ };
16
+ updated = (state, isValidate = true)=>{
17
+ const keys = Object.keys(state);
18
+ for(let index = 0; index < keys.length; index++){
19
+ const key = keys[index];
20
+ this.state[key] = state[key];
21
+ }
22
+ if (isValidate) this.validate(keys, false);
23
+ };
24
+ updatedHideInfo = (objectHideInfo)=>{
25
+ const keys = Object.keys(objectHideInfo);
26
+ for(let index = 0; index < keys.length; index++){
27
+ const field = keys[index];
28
+ this.hideState[field] = objectHideInfo[field];
29
+ }
30
+ return this;
31
+ };
32
+ clearHideInfo = (fields)=>{
33
+ let _fields = fields;
34
+ if (!Array.isArray(fields)) _fields = Object.keys(this.hideState);
35
+ for(let index = 0; index < _fields.length; index++){
36
+ const field = _fields[index];
37
+ delete this.hideState[field];
38
+ }
39
+ return this;
40
+ };
41
+ updatedErrorInfo = (objectErrorInfo)=>{
42
+ const keys = Object.keys(objectErrorInfo);
43
+ for(let index = 0; index < keys.length; index++){
44
+ const field = keys[index];
45
+ this.errorState[field] = objectErrorInfo[field];
46
+ }
47
+ return this;
48
+ };
49
+ clearErrorInfo = (fields)=>{
50
+ let _fields = fields;
51
+ if (!Array.isArray(fields)) _fields = Object.keys(this.errorState);
52
+ for(let index = 0; index < _fields.length; index++){
53
+ const field = _fields[index];
54
+ delete this.errorState[field];
55
+ }
56
+ return this;
57
+ };
58
+ clear = ()=>{
59
+ this.state = proxy({});
60
+ this.errorState = proxy({});
61
+ this.hideState = proxy({});
62
+ };
63
+ rules = {};
64
+ validate = async (fields, isReturn = true)=>{
65
+ let _fields = fields;
66
+ const _formData = snapshot(this.state);
67
+ if (!this.rules) return Promise.resolve({
68
+ ..._formData
69
+ });
70
+ const rules = {};
71
+ let isNeedValidate = false;
72
+ if (!fields || Array.isArray(fields) && 0 === fields.length) _fields = Object.keys(this.rules);
73
+ for(let index = 0; index < _fields.length; index++){
74
+ isNeedValidate = true;
75
+ const element = _fields[index];
76
+ const rule = this.rules[element];
77
+ if ('function' == typeof rule) {
78
+ const _rules = await rule(_formData, this);
79
+ rules[element] = _rules;
80
+ } else if (Array.isArray(rule)) rules[element] = rule;
81
+ }
82
+ if (!isNeedValidate) {
83
+ console.warn('no rules to validate');
84
+ return Promise.resolve({
85
+ ..._formData
86
+ });
87
+ }
88
+ return new Promise((resolve, reject)=>{
89
+ new async_validator({
90
+ ...rules
91
+ }).validate({
92
+ ..._formData
93
+ }, (errors, fields)=>{
94
+ for(let index = 0; index < _fields.length; index++){
95
+ const field = _fields[index];
96
+ const fidError = Array.isArray(errors) ? errors.filter((item)=>item.field === field) : void 0;
97
+ if (fidError) this.errorState[field] = external_valtio_ref(fidError.map((item)=>item.message || ''));
98
+ else delete this.errorState[field];
99
+ }
100
+ if (isReturn) if (errors) reject({
101
+ errors,
102
+ fields
103
+ });
104
+ else resolve(fields);
105
+ });
106
+ });
107
+ };
108
+ }
109
+ function useFairysValtioFormInstance(instance) {
110
+ const ref = useRef();
111
+ if (!ref.current) if (instance) ref.current = instance;
112
+ else ref.current = new FairysValtioFormInstance();
113
+ return ref.current;
114
+ }
115
+ const FairysValtioFormInstanceContext = createContext(new FairysValtioFormInstance());
116
+ function useFairysValtioFormInstanceContext() {
117
+ return useContext(FairysValtioFormInstanceContext);
118
+ }
119
+ function useFairysValtioFormInstanceContextState() {
120
+ const instance = useFairysValtioFormInstanceContext();
121
+ const state = useSnapshot(instance.state);
122
+ const errorState = useSnapshot(instance.errorState);
123
+ return [
124
+ state,
125
+ errorState,
126
+ instance,
127
+ state.__defaultValue,
128
+ errorState.__defaultValue
129
+ ];
130
+ }
131
+ function useFairysValtioFormInstanceContextHideState() {
132
+ const instance = useFairysValtioFormInstanceContext();
133
+ const hideState = useSnapshot(instance.hideState);
134
+ return [
135
+ hideState,
136
+ instance,
137
+ hideState.__defaultValue
138
+ ];
139
+ }
140
+ export { FairysValtioFormInstance, FairysValtioFormInstanceContext, useFairysValtioFormInstance, useFairysValtioFormInstanceContext, useFairysValtioFormInstanceContextHideState, useFairysValtioFormInstanceContextState };