react-form-manage 1.0.8-beta.11 → 1.0.8-beta.13
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/dist/components/Form/FormCleanUp.js +3 -3
- package/dist/hooks/useFormItemControl.js +3 -3
- package/dist/hooks/useFormListControl.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -0
- package/dist/providers/Form.d.ts +6 -0
- package/dist/providers/Form.js +16 -4
- package/dist/stores/formStore.d.ts +25 -3
- package/dist/stores/formStore.js +13 -6
- package/package.json +1 -1
- package/src/App.tsx +34 -2
- package/src/components/Form/FormCleanUp.tsx +3 -7
- package/src/hooks/useFormItemControl.ts +3 -7
- package/src/hooks/useFormListControl.ts +2 -2
- package/src/index.ts +11 -0
- package/src/providers/Form.tsx +27 -3
- package/src/stores/formStore.ts +38 -23
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect } from "react";
|
|
3
3
|
import { useShallow } from "zustand/react/shallow";
|
|
4
|
-
import {
|
|
4
|
+
import { useFormStore } from "../../stores/formStore";
|
|
5
5
|
const FormCleanUp = () => {
|
|
6
|
-
const { cleanUpStack, clearCleanUpStack } =
|
|
6
|
+
const { cleanUpStack, clearCleanUpStack } = useFormStore(useShallow((state) => ({
|
|
7
7
|
cleanUpStack: state.cleanUpStack,
|
|
8
8
|
clearCleanUpStack: state.clearCleanUpStack
|
|
9
9
|
})));
|
|
10
|
-
const { revokeListener } =
|
|
10
|
+
const { revokeListener } = useFormStore(useShallow((state) => ({
|
|
11
11
|
revokeListener: state.revokeListener
|
|
12
12
|
})));
|
|
13
13
|
const { clearObjKeyItem, clearArrItem } = useFormStore(useShallow((state) => {
|
|
@@ -4,7 +4,7 @@ import { useEffect, useMemo } from "react";
|
|
|
4
4
|
import { useShallow } from "zustand/react/shallow";
|
|
5
5
|
import { IS_ALPHABET_STRING_AND_NUMBER_REGEX, IS_EMAIL_REGEX, IS_NAME_REGEX, IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX, IS_NO_SPACE_ALPHABET_STRING_REGEX, IS_NOSPACE_STRING_AND_NUMBER_REGEX, IS_PASSWORD_REGEX, IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX, IS_POSITIVE_STRING_NUMBER_REGEX, IS_STRING_AND_NUMBER_REGEX, IS_STRING_NUMBER_REGEX, IS_USERNAME_REGEX, IS_VIETNAMESE_PHONE_NUMBER_REGEX } from "../constants/validation";
|
|
6
6
|
import { useFormContext } from "../providers/Form";
|
|
7
|
-
import {
|
|
7
|
+
import { useFormStore } from "../stores/formStore";
|
|
8
8
|
const VALID_PREMITIVE_TYPE = ["string", "number", "undefined"];
|
|
9
9
|
function useFormItemControl({ formName, form, name, initialValue, formItemId, rules, elementRef }) {
|
|
10
10
|
const contextForm = useFormContext();
|
|
@@ -20,7 +20,7 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
20
20
|
submitState: (_d = (_c = state2.formStates) == null ? void 0 : _c[formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName)]) == null ? void 0 : _d.submitState
|
|
21
21
|
};
|
|
22
22
|
}));
|
|
23
|
-
const { setCleanUpStack } =
|
|
23
|
+
const { setCleanUpStack } = useFormStore(useShallow((state2) => ({
|
|
24
24
|
setCleanUpStack: state2.setCleanUpStack
|
|
25
25
|
})));
|
|
26
26
|
const { initValue: internalInitValue, setInitData, getInitData } = useFormStore(useShallow((state2) => {
|
|
@@ -30,7 +30,7 @@ function useFormItemControl({ formName, form, name, initialValue, formItemId, ru
|
|
|
30
30
|
getInitData: state2.getInitData
|
|
31
31
|
};
|
|
32
32
|
}));
|
|
33
|
-
const { listener, setListener } =
|
|
33
|
+
const { listener, setListener } = useFormStore(useShallow((state2) => {
|
|
34
34
|
return {
|
|
35
35
|
listener: state2.listeners.find((l) => l.formItemId === formItemId),
|
|
36
36
|
setListener: state2.setListener
|
|
@@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { v4 } from "uuid";
|
|
4
4
|
import { useShallow } from "zustand/react/shallow";
|
|
5
5
|
import { useFormContext } from "../providers/Form";
|
|
6
|
-
import {
|
|
6
|
+
import { useFormStore } from "../stores/formStore";
|
|
7
7
|
function useFormListControl({ name, form, initialValues, formName }) {
|
|
8
8
|
const contextForm = useFormContext();
|
|
9
9
|
const getFormValues = useFormStore((state) => state.getFormValues);
|
|
@@ -13,7 +13,7 @@ function useFormListControl({ name, form, initialValues, formName }) {
|
|
|
13
13
|
clearCacheData: state.clearCacheData,
|
|
14
14
|
setCacheData: state.setCacheData
|
|
15
15
|
})));
|
|
16
|
-
const { setCleanUpStack } =
|
|
16
|
+
const { setCleanUpStack } = useFormStore(useShallow((state) => ({
|
|
17
17
|
setCleanUpStack: state.setCleanUpStack
|
|
18
18
|
})));
|
|
19
19
|
const { initValue: internalInitValue, formState } = useFormStore(useShallow((state) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ import Input from "./components/Input";
|
|
|
6
6
|
import InputWrapper, { type InputWrapperProps } from "./components/Form/InputWrapper";
|
|
7
7
|
import useFormItemControl from "./hooks/useFormItemControl";
|
|
8
8
|
import useFormListControl from "./hooks/useFormListControl";
|
|
9
|
-
|
|
9
|
+
import { useFormStore, type FormInstance, type ListenerItem, type CleanUpItem } from "./stores/formStore";
|
|
10
|
+
export { Form, FormItem, FormList, Input, InputWrapper, useFormItemControl, useFormListControl, useForm, useWatch, useSubmitDataWatch, useFormStateWatch, useFormStore, type FormProps, type FormItemProps, type FormListProps, type InputWrapperProps, type ValidationRule, type FormFieldError, type SubmitState, type UseFormItemStateWatchReturn, type FormInstance, type ListenerItem, type CleanUpItem, SUBMIT_STATE, };
|
|
10
11
|
export default Form;
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import Input from "./components/Input";
|
|
|
6
6
|
import InputWrapper from "./components/Form/InputWrapper";
|
|
7
7
|
import useFormItemControl from "./hooks/useFormItemControl";
|
|
8
8
|
import useFormListControl from "./hooks/useFormListControl";
|
|
9
|
+
import { useFormStore } from "./stores/formStore";
|
|
9
10
|
var stdin_default = Form;
|
|
10
11
|
export {
|
|
11
12
|
Form,
|
|
@@ -19,6 +20,7 @@ export {
|
|
|
19
20
|
useFormItemControl,
|
|
20
21
|
useFormListControl,
|
|
21
22
|
useFormStateWatch,
|
|
23
|
+
useFormStore,
|
|
22
24
|
useSubmitDataWatch,
|
|
23
25
|
useWatch
|
|
24
26
|
};
|
package/dist/providers/Form.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ declare namespace Form {
|
|
|
22
22
|
var useSubmitDataWatch: typeof import("./Form").useSubmitDataWatch;
|
|
23
23
|
var useFormStateWatch: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => any;
|
|
24
24
|
var useFormItemStateWatch: <T = any>(nameOrFormItemId: string, formNameOrFormInstance?: string | PublicFormInstance<T>) => UseFormItemStateWatchReturn;
|
|
25
|
+
var useWatchFormListeners: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => {
|
|
26
|
+
listeners: import("../stores/formStore").ListenerItem[];
|
|
27
|
+
};
|
|
25
28
|
}
|
|
26
29
|
export default Form;
|
|
27
30
|
export declare function useFormContext(): any;
|
|
@@ -34,3 +37,6 @@ export declare function useSubmitDataWatch<T = any>({ formNameOrFormInstance, tr
|
|
|
34
37
|
}): T | undefined;
|
|
35
38
|
export declare const useFormStateWatch: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => any;
|
|
36
39
|
export declare const useFormItemStateWatch: <T = any>(nameOrFormItemId: string, formNameOrFormInstance?: string | PublicFormInstance<T>) => UseFormItemStateWatchReturn;
|
|
40
|
+
export declare const useWatchFormListeners: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => {
|
|
41
|
+
listeners: import("../stores/formStore").ListenerItem[];
|
|
42
|
+
};
|
package/dist/providers/Form.js
CHANGED
|
@@ -6,7 +6,7 @@ import { flushSync } from "react-dom";
|
|
|
6
6
|
import { useShallow } from "zustand/react/shallow";
|
|
7
7
|
import FormCleanUp from "../components/Form/FormCleanUp";
|
|
8
8
|
import { SUBMIT_STATE } from "../constants/form";
|
|
9
|
-
import {
|
|
9
|
+
import { useFormStore } from "../stores/formStore";
|
|
10
10
|
import { getAllNoneObjStringPath } from "../utils/obj.util";
|
|
11
11
|
const FormContext = createContext(null);
|
|
12
12
|
function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, ...props }) {
|
|
@@ -39,7 +39,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
|
|
|
39
39
|
// Test, nhớ xóa sau khi xong
|
|
40
40
|
// formStates: state.formStates?.[formName],
|
|
41
41
|
})));
|
|
42
|
-
const { getListeners } =
|
|
42
|
+
const { getListeners } = useFormStore(useShallow((state) => {
|
|
43
43
|
return {
|
|
44
44
|
getListeners: state.getListeners
|
|
45
45
|
};
|
|
@@ -267,7 +267,7 @@ function useForm(formNameOrFormInstance) {
|
|
|
267
267
|
const formContext = useContext(FormContext);
|
|
268
268
|
const targetFormName = isNil(formNameOrFormInstance) ? formContext == null ? void 0 : formContext.formName : typeof formNameOrFormInstance === "object" && formNameOrFormInstance !== null ? formNameOrFormInstance.formName : formNameOrFormInstance;
|
|
269
269
|
const formInstance = useFormStore((state) => {
|
|
270
|
-
return state.formInstances.find((i) => i.formName === targetFormName);
|
|
270
|
+
return Object.values(state.formInstances).find((i) => i.formName === targetFormName);
|
|
271
271
|
});
|
|
272
272
|
return [formInstance];
|
|
273
273
|
}
|
|
@@ -311,11 +311,22 @@ const useFormItemStateWatch = (nameOrFormItemId, formNameOrFormInstance) => {
|
|
|
311
311
|
errors: (listener == null ? void 0 : listener.internalErrors) || []
|
|
312
312
|
};
|
|
313
313
|
};
|
|
314
|
+
const useWatchFormListeners = (formNameOrFormInstance) => {
|
|
315
|
+
const [formInstance] = useForm(formNameOrFormInstance);
|
|
316
|
+
const listeners = useFormStore(useShallow((state) => {
|
|
317
|
+
const allListeners = state.listeners;
|
|
318
|
+
return {
|
|
319
|
+
listeners: allListeners.filter((l) => !isNil(formNameOrFormInstance) ? true : l.formName === (formInstance == null ? void 0 : formInstance.formName))
|
|
320
|
+
};
|
|
321
|
+
}));
|
|
322
|
+
return listeners;
|
|
323
|
+
};
|
|
314
324
|
Form.useForm = useForm;
|
|
315
325
|
Form.useWatch = useWatch;
|
|
316
326
|
Form.useSubmitDataWatch = useSubmitDataWatch;
|
|
317
327
|
Form.useFormStateWatch = useFormStateWatch;
|
|
318
328
|
Form.useFormItemStateWatch = useFormItemStateWatch;
|
|
329
|
+
Form.useWatchFormListeners = useWatchFormListeners;
|
|
319
330
|
export {
|
|
320
331
|
FormContext,
|
|
321
332
|
Form as default,
|
|
@@ -324,5 +335,6 @@ export {
|
|
|
324
335
|
useFormItemStateWatch,
|
|
325
336
|
useFormStateWatch,
|
|
326
337
|
useSubmitDataWatch,
|
|
327
|
-
useWatch
|
|
338
|
+
useWatch,
|
|
339
|
+
useWatchFormListeners
|
|
328
340
|
};
|
|
@@ -13,16 +13,38 @@ export interface FormInstance {
|
|
|
13
13
|
getFieldErrors: () => Record<string, any>;
|
|
14
14
|
setFieldFocus: (name: string) => void;
|
|
15
15
|
}
|
|
16
|
+
export interface ListenerItem {
|
|
17
|
+
name?: string;
|
|
18
|
+
formName?: string;
|
|
19
|
+
isTouched?: boolean;
|
|
20
|
+
isDirty?: boolean;
|
|
21
|
+
formItemId?: string;
|
|
22
|
+
internalErrors?: any;
|
|
23
|
+
onChange?: any;
|
|
24
|
+
onReset?: any;
|
|
25
|
+
onFocus?: any;
|
|
26
|
+
emitFocus?: any;
|
|
27
|
+
isInitied?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface CleanUpItem {
|
|
30
|
+
name?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
key: string;
|
|
33
|
+
itemKey?: string;
|
|
34
|
+
formName?: string;
|
|
35
|
+
}
|
|
16
36
|
interface FormStoreState {
|
|
17
37
|
forms: Record<string, any>;
|
|
18
38
|
initialValues: Record<string, any>;
|
|
19
39
|
formStates: Record<string, any>;
|
|
20
40
|
cacheData: Record<string, any>;
|
|
21
|
-
formInstances: FormInstance
|
|
41
|
+
formInstances: Record<string, FormInstance>;
|
|
22
42
|
submitHistory: Record<string, any[]>;
|
|
43
|
+
listeners: ListenerItem[];
|
|
44
|
+
cleanUpStack: CleanUpItem[];
|
|
23
45
|
[key: string]: any;
|
|
24
46
|
}
|
|
25
47
|
export declare const useFormStore: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
|
|
26
|
-
export declare const useFormListeners: import("zustand").UseBoundStore<import("zustand").StoreApi<
|
|
27
|
-
export declare const useFormCleanUp: import("zustand").UseBoundStore<import("zustand").StoreApi<
|
|
48
|
+
export declare const useFormListeners: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
|
|
49
|
+
export declare const useFormCleanUp: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
|
|
28
50
|
export {};
|
package/dist/stores/formStore.js
CHANGED
|
@@ -3,12 +3,12 @@ import { cloneDeep, get, isNil, isNumber, last, set, unset } from "lodash";
|
|
|
3
3
|
import { v4 } from "uuid";
|
|
4
4
|
import { create } from "zustand";
|
|
5
5
|
import { getAllNoneObjStringPath } from "../utils/obj.util";
|
|
6
|
-
const
|
|
6
|
+
const createFormStoreSlice = (storeSet, storeGet, api) => ({
|
|
7
7
|
forms: {},
|
|
8
8
|
initialValues: {},
|
|
9
9
|
formStates: {},
|
|
10
10
|
cacheData: {},
|
|
11
|
-
formInstances:
|
|
11
|
+
formInstances: {},
|
|
12
12
|
submitHistory: {},
|
|
13
13
|
setData(formName, name, value) {
|
|
14
14
|
return storeSet(produce((state) => {
|
|
@@ -191,8 +191,8 @@ const useFormStore = create((storeSet, storeGet) => ({
|
|
|
191
191
|
}
|
|
192
192
|
}));
|
|
193
193
|
}
|
|
194
|
-
})
|
|
195
|
-
const
|
|
194
|
+
});
|
|
195
|
+
const createListenersSlice = (storeSet, storeGet, api) => ({
|
|
196
196
|
listeners: [],
|
|
197
197
|
getListener(formItemId) {
|
|
198
198
|
return storeGet().listeners.find((l) => l.formItemId === formItemId);
|
|
@@ -261,8 +261,8 @@ const useFormListeners = create((storeSet, storeGet) => ({
|
|
|
261
261
|
}
|
|
262
262
|
}));
|
|
263
263
|
}
|
|
264
|
-
})
|
|
265
|
-
const
|
|
264
|
+
});
|
|
265
|
+
const createCleanUpSlice = (storeSet, storeGet, api) => ({
|
|
266
266
|
cleanUpStack: [],
|
|
267
267
|
setCleanUpStack({ name, type, itemKey, formName }) {
|
|
268
268
|
return storeSet(produce((state) => {
|
|
@@ -276,7 +276,14 @@ const useFormCleanUp = create((storeSet) => ({
|
|
|
276
276
|
state.cleanUpStack = [];
|
|
277
277
|
}));
|
|
278
278
|
}
|
|
279
|
+
});
|
|
280
|
+
const useFormStore = create((...a) => ({
|
|
281
|
+
...createFormStoreSlice(...a),
|
|
282
|
+
...createListenersSlice(...a),
|
|
283
|
+
...createCleanUpSlice(...a)
|
|
279
284
|
}));
|
|
285
|
+
const useFormListeners = useFormStore;
|
|
286
|
+
const useFormCleanUp = useFormStore;
|
|
280
287
|
export {
|
|
281
288
|
useFormCleanUp,
|
|
282
289
|
useFormListeners,
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Checkbox } from "@mui/material";
|
|
1
|
+
import { Checkbox, Dialog, DialogContent, TextField } from "@mui/material";
|
|
2
2
|
import { Button, Input } from "antd";
|
|
3
3
|
import { motion } from "framer-motion";
|
|
4
4
|
import { useEffect } from "react";
|
|
@@ -8,6 +8,7 @@ import InputWrapper from "./components/Form/InputWrapper";
|
|
|
8
8
|
import Form, { useForm } from "./providers/Form";
|
|
9
9
|
|
|
10
10
|
import { Form as AntdForm } from "antd";
|
|
11
|
+
import { useToggle } from "minh-custom-hooks-release";
|
|
11
12
|
|
|
12
13
|
function TestFormWatch() {
|
|
13
14
|
const watchValue = Form.useWatch("numericCode");
|
|
@@ -15,9 +16,37 @@ function TestFormWatch() {
|
|
|
15
16
|
return <div>TestFormWatch</div>;
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
function TestMuiDialog({
|
|
20
|
+
open,
|
|
21
|
+
onClose,
|
|
22
|
+
}: {
|
|
23
|
+
open: boolean;
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
}) {
|
|
26
|
+
return (
|
|
27
|
+
<Dialog open={open} onClose={onClose}>
|
|
28
|
+
<DialogContent>
|
|
29
|
+
{" "}
|
|
30
|
+
<Form
|
|
31
|
+
onFinish={(values) => {
|
|
32
|
+
console.log("Mui Dialog Form Values: ", values);
|
|
33
|
+
}}
|
|
34
|
+
formName="ADD_FORM"
|
|
35
|
+
>
|
|
36
|
+
<FormItem name="oooo">
|
|
37
|
+
<TextField />
|
|
38
|
+
</FormItem>
|
|
39
|
+
|
|
40
|
+
<Button htmlType="submit">Submit</Button>
|
|
41
|
+
</Form>
|
|
42
|
+
</DialogContent>
|
|
43
|
+
</Dialog>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
18
47
|
const App = () => {
|
|
19
48
|
const [form] = useForm("form1");
|
|
20
|
-
|
|
49
|
+
const { state: open, toggle } = useToggle(false);
|
|
21
50
|
const watchCheckBox = Form.useWatch("checkControlledAfterInit", "form1");
|
|
22
51
|
|
|
23
52
|
useEffect(() => {
|
|
@@ -180,6 +209,9 @@ const App = () => {
|
|
|
180
209
|
Reset
|
|
181
210
|
</Button>
|
|
182
211
|
</Form>
|
|
212
|
+
|
|
213
|
+
<Button onClick={toggle}>Toggle Dialog</Button>
|
|
214
|
+
<TestMuiDialog onClose={toggle} open={open} />
|
|
183
215
|
</div>
|
|
184
216
|
);
|
|
185
217
|
};
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { useEffect } from "react";
|
|
2
2
|
import { useShallow } from "zustand/react/shallow";
|
|
3
|
-
import {
|
|
4
|
-
useFormCleanUp,
|
|
5
|
-
useFormListeners,
|
|
6
|
-
useFormStore,
|
|
7
|
-
} from "../../stores/formStore";
|
|
3
|
+
import { useFormStore } from "../../stores/formStore";
|
|
8
4
|
|
|
9
5
|
const FormCleanUp = () => {
|
|
10
|
-
const { cleanUpStack, clearCleanUpStack } =
|
|
6
|
+
const { cleanUpStack, clearCleanUpStack } = useFormStore(
|
|
11
7
|
useShallow((state) => ({
|
|
12
8
|
cleanUpStack: state.cleanUpStack,
|
|
13
9
|
clearCleanUpStack: state.clearCleanUpStack,
|
|
14
10
|
})),
|
|
15
11
|
);
|
|
16
12
|
|
|
17
|
-
const { revokeListener } =
|
|
13
|
+
const { revokeListener } = useFormStore(
|
|
18
14
|
useShallow((state) => ({
|
|
19
15
|
revokeListener: state.revokeListener,
|
|
20
16
|
})),
|
|
@@ -18,11 +18,7 @@ import {
|
|
|
18
18
|
IS_VIETNAMESE_PHONE_NUMBER_REGEX,
|
|
19
19
|
} from "../constants/validation";
|
|
20
20
|
import { useFormContext } from "../providers/Form";
|
|
21
|
-
import {
|
|
22
|
-
useFormCleanUp,
|
|
23
|
-
useFormListeners,
|
|
24
|
-
useFormStore,
|
|
25
|
-
} from "../stores/formStore";
|
|
21
|
+
import { useFormStore } from "../stores/formStore";
|
|
26
22
|
|
|
27
23
|
import type { FormInstance } from "../stores/formStore";
|
|
28
24
|
import type {
|
|
@@ -98,7 +94,7 @@ export default function useFormItemControl<T = any>({
|
|
|
98
94
|
}),
|
|
99
95
|
);
|
|
100
96
|
|
|
101
|
-
const { setCleanUpStack } =
|
|
97
|
+
const { setCleanUpStack } = useFormStore(
|
|
102
98
|
useShallow((state) => ({
|
|
103
99
|
setCleanUpStack: state.setCleanUpStack,
|
|
104
100
|
})),
|
|
@@ -130,7 +126,7 @@ export default function useFormItemControl<T = any>({
|
|
|
130
126
|
}),
|
|
131
127
|
);
|
|
132
128
|
|
|
133
|
-
const { listener, setListener } =
|
|
129
|
+
const { listener, setListener } = useFormStore(
|
|
134
130
|
useShallow((state) => {
|
|
135
131
|
// console.log(
|
|
136
132
|
// "Get listener from store: ",
|
|
@@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import { v4 } from "uuid";
|
|
4
4
|
import { useShallow } from "zustand/react/shallow";
|
|
5
5
|
import { useFormContext } from "../providers/Form";
|
|
6
|
-
import {
|
|
6
|
+
import { useFormStore } from "../stores/formStore";
|
|
7
7
|
|
|
8
8
|
import type { FormInstance } from "../stores/formStore";
|
|
9
9
|
|
|
@@ -41,7 +41,7 @@ export default function useFormListControl<T = any>({
|
|
|
41
41
|
setCacheData: state.setCacheData,
|
|
42
42
|
})),
|
|
43
43
|
);
|
|
44
|
-
const { setCleanUpStack } =
|
|
44
|
+
const { setCleanUpStack } = useFormStore(
|
|
45
45
|
useShallow((state) => ({
|
|
46
46
|
setCleanUpStack: state.setCleanUpStack,
|
|
47
47
|
})),
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,13 @@ import InputWrapper, { type InputWrapperProps } from "./components/Form/InputWra
|
|
|
19
19
|
import useFormItemControl from "./hooks/useFormItemControl";
|
|
20
20
|
import useFormListControl from "./hooks/useFormListControl";
|
|
21
21
|
|
|
22
|
+
import {
|
|
23
|
+
useFormStore,
|
|
24
|
+
type FormInstance,
|
|
25
|
+
type ListenerItem,
|
|
26
|
+
type CleanUpItem
|
|
27
|
+
} from "./stores/formStore";
|
|
28
|
+
|
|
22
29
|
export {
|
|
23
30
|
Form,
|
|
24
31
|
FormItem,
|
|
@@ -31,6 +38,7 @@ export {
|
|
|
31
38
|
useWatch,
|
|
32
39
|
useSubmitDataWatch,
|
|
33
40
|
useFormStateWatch,
|
|
41
|
+
useFormStore,
|
|
34
42
|
type FormProps,
|
|
35
43
|
type FormItemProps,
|
|
36
44
|
type FormListProps,
|
|
@@ -39,6 +47,9 @@ export {
|
|
|
39
47
|
type FormFieldError,
|
|
40
48
|
type SubmitState,
|
|
41
49
|
type UseFormItemStateWatchReturn,
|
|
50
|
+
type FormInstance,
|
|
51
|
+
type ListenerItem,
|
|
52
|
+
type CleanUpItem,
|
|
42
53
|
SUBMIT_STATE,
|
|
43
54
|
};
|
|
44
55
|
|
package/src/providers/Form.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { flushSync } from "react-dom";
|
|
|
6
6
|
import { useShallow } from "zustand/react/shallow"; // Import useShallow
|
|
7
7
|
import FormCleanUp from "../components/Form/FormCleanUp";
|
|
8
8
|
import { SUBMIT_STATE } from "../constants/form";
|
|
9
|
-
import {
|
|
9
|
+
import { useFormStore } from "../stores/formStore";
|
|
10
10
|
import type {
|
|
11
11
|
PublicFormInstance,
|
|
12
12
|
UseFormItemStateWatchReturn,
|
|
@@ -81,7 +81,7 @@ export default function Form<T = any>({
|
|
|
81
81
|
})),
|
|
82
82
|
);
|
|
83
83
|
|
|
84
|
-
const { getListeners } =
|
|
84
|
+
const { getListeners } = useFormStore(
|
|
85
85
|
useShallow((state) => {
|
|
86
86
|
return {
|
|
87
87
|
getListeners: state.getListeners,
|
|
@@ -422,7 +422,9 @@ export function useForm<T = any>(
|
|
|
422
422
|
: (formNameOrFormInstance as string | undefined);
|
|
423
423
|
|
|
424
424
|
const formInstance = useFormStore((state) => {
|
|
425
|
-
return state.formInstances.find(
|
|
425
|
+
return Object.values(state.formInstances).find(
|
|
426
|
+
(i) => i.formName === targetFormName,
|
|
427
|
+
);
|
|
426
428
|
}) as PublicFormInstance<T> | undefined;
|
|
427
429
|
|
|
428
430
|
return [formInstance];
|
|
@@ -509,8 +511,30 @@ export const useFormItemStateWatch = <T = any,>(
|
|
|
509
511
|
};
|
|
510
512
|
};
|
|
511
513
|
|
|
514
|
+
export const useWatchFormListeners = <T = any,>(
|
|
515
|
+
formNameOrFormInstance?: string | PublicFormInstance<T>,
|
|
516
|
+
) => {
|
|
517
|
+
const [formInstance] = useForm<T>(formNameOrFormInstance as any);
|
|
518
|
+
|
|
519
|
+
const listeners = useFormStore(
|
|
520
|
+
useShallow((state) => {
|
|
521
|
+
const allListeners = state.listeners;
|
|
522
|
+
return {
|
|
523
|
+
listeners: allListeners.filter((l) =>
|
|
524
|
+
!isNil(formNameOrFormInstance)
|
|
525
|
+
? true
|
|
526
|
+
: l.formName === formInstance?.formName,
|
|
527
|
+
),
|
|
528
|
+
};
|
|
529
|
+
}),
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
return listeners;
|
|
533
|
+
};
|
|
534
|
+
|
|
512
535
|
Form.useForm = useForm;
|
|
513
536
|
Form.useWatch = useWatch;
|
|
514
537
|
Form.useSubmitDataWatch = useSubmitDataWatch;
|
|
515
538
|
Form.useFormStateWatch = useFormStateWatch;
|
|
516
539
|
Form.useFormItemStateWatch = useFormItemStateWatch;
|
|
540
|
+
Form.useWatchFormListeners = useWatchFormListeners;
|
package/src/stores/formStore.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface FormInstance {
|
|
|
17
17
|
setFieldFocus: (name: string) => void;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
interface ListenerItem {
|
|
20
|
+
export interface ListenerItem {
|
|
21
21
|
name?: string;
|
|
22
22
|
formName?: string;
|
|
23
23
|
isTouched?: boolean;
|
|
@@ -28,9 +28,10 @@ interface ListenerItem {
|
|
|
28
28
|
onReset?: any;
|
|
29
29
|
onFocus?: any;
|
|
30
30
|
emitFocus?: any;
|
|
31
|
+
isInitied?: boolean;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
interface CleanUpItem {
|
|
34
|
+
export interface CleanUpItem {
|
|
34
35
|
name?: string;
|
|
35
36
|
type?: string;
|
|
36
37
|
key: string;
|
|
@@ -43,19 +44,23 @@ interface FormStoreState {
|
|
|
43
44
|
initialValues: Record<string, any>;
|
|
44
45
|
formStates: Record<string, any>;
|
|
45
46
|
cacheData: Record<string, any>;
|
|
46
|
-
formInstances: FormInstance
|
|
47
|
+
formInstances: Record<string, FormInstance>;
|
|
47
48
|
submitHistory: Record<string, any[]>;
|
|
49
|
+
listeners: ListenerItem[];
|
|
50
|
+
cleanUpStack: CleanUpItem[];
|
|
48
51
|
// methods (loose typed for incremental migration)
|
|
49
52
|
[key: string]: any;
|
|
50
53
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
|
|
55
|
+
// Combined store containing all form-related state
|
|
56
|
+
// Form Store Slice
|
|
57
|
+
const createFormStoreSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
58
|
+
forms: {},
|
|
59
|
+
initialValues: {},
|
|
60
|
+
formStates: {},
|
|
61
|
+
cacheData: {},
|
|
62
|
+
formInstances: {},
|
|
63
|
+
submitHistory: {},
|
|
59
64
|
setData(formName, name, value) {
|
|
60
65
|
return storeSet(
|
|
61
66
|
produce<any>((state: any) => {
|
|
@@ -353,13 +358,13 @@ export const useFormStore = create<FormStoreState>(
|
|
|
353
358
|
}),
|
|
354
359
|
);
|
|
355
360
|
},
|
|
356
|
-
|
|
357
|
-
);
|
|
361
|
+
});
|
|
358
362
|
|
|
359
|
-
|
|
363
|
+
// Listeners Slice
|
|
364
|
+
const createListenersSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
360
365
|
listeners: [],
|
|
361
|
-
getListener(formItemId) {
|
|
362
|
-
return storeGet().listeners.find((l) => l.formItemId === formItemId);
|
|
366
|
+
getListener(formItemId: string) {
|
|
367
|
+
return storeGet().listeners.find((l: any) => l.formItemId === formItemId);
|
|
363
368
|
},
|
|
364
369
|
getListeners() {
|
|
365
370
|
return storeGet().listeners;
|
|
@@ -376,7 +381,7 @@ export const useFormListeners = create<any>((storeSet: any, storeGet: any) => ({
|
|
|
376
381
|
onFocus,
|
|
377
382
|
emitFocus,
|
|
378
383
|
isInitied,
|
|
379
|
-
}) {
|
|
384
|
+
}: any) {
|
|
380
385
|
return storeSet(
|
|
381
386
|
produce<any>((state: any) => {
|
|
382
387
|
const storeListeners = state.listeners;
|
|
@@ -433,7 +438,7 @@ export const useFormListeners = create<any>((storeSet: any, storeGet: any) => ({
|
|
|
433
438
|
}),
|
|
434
439
|
);
|
|
435
440
|
},
|
|
436
|
-
revokeListener(formItemId, onAfterRevoke) {
|
|
441
|
+
revokeListener(formItemId: string, onAfterRevoke: any) {
|
|
437
442
|
return storeSet(
|
|
438
443
|
produce<any>((state: any) => {
|
|
439
444
|
const storeListeners = state.listeners;
|
|
@@ -442,8 +447,6 @@ export const useFormListeners = create<any>((storeSet: any, storeGet: any) => ({
|
|
|
442
447
|
(l: any) => l.formItemId == formItemId,
|
|
443
448
|
);
|
|
444
449
|
|
|
445
|
-
// console.log("Find item for revoke: ", findListenerIndex, formItemId);
|
|
446
|
-
|
|
447
450
|
if (findListenerIndex > -1) {
|
|
448
451
|
const listenersInfo = cloneDeep(storeListeners[findListenerIndex]);
|
|
449
452
|
|
|
@@ -462,11 +465,12 @@ export const useFormListeners = create<any>((storeSet: any, storeGet: any) => ({
|
|
|
462
465
|
}),
|
|
463
466
|
);
|
|
464
467
|
},
|
|
465
|
-
})
|
|
468
|
+
});
|
|
466
469
|
|
|
467
|
-
|
|
470
|
+
// CleanUp Slice
|
|
471
|
+
const createCleanUpSlice = (storeSet: any, storeGet: any, api: any) => ({
|
|
468
472
|
cleanUpStack: [],
|
|
469
|
-
setCleanUpStack({ name, type, itemKey, formName }) {
|
|
473
|
+
setCleanUpStack({ name, type, itemKey, formName }: any) {
|
|
470
474
|
return storeSet(
|
|
471
475
|
produce<any>((state: any) => {
|
|
472
476
|
const oldValues = state.cleanUpStack;
|
|
@@ -482,4 +486,15 @@ export const useFormCleanUp = create<any>((storeSet: any) => ({
|
|
|
482
486
|
}),
|
|
483
487
|
);
|
|
484
488
|
},
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Combined Store
|
|
492
|
+
export const useFormStore = create<FormStoreState>((...a) => ({
|
|
493
|
+
...createFormStoreSlice(...a),
|
|
494
|
+
...createListenersSlice(...a),
|
|
495
|
+
...createCleanUpSlice(...a),
|
|
485
496
|
}));
|
|
497
|
+
|
|
498
|
+
// Deprecated exports - use useFormStore instead
|
|
499
|
+
export const useFormListeners = useFormStore;
|
|
500
|
+
export const useFormCleanUp = useFormStore;
|