react-form-manage 1.0.8-beta.2 → 1.0.8-beta.21

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 (46) hide show
  1. package/CHANGELOG.md +85 -5
  2. package/README.md +8 -4
  3. package/dist/components/Form/FormCleanUp.js +3 -3
  4. package/dist/components/Form/FormItem.d.ts +4 -2
  5. package/dist/components/Form/FormItem.js +7 -5
  6. package/dist/components/Form/FormList.d.ts +2 -2
  7. package/dist/components/Form/FormList.js +2 -2
  8. package/dist/hooks/useFormItemControl.d.ts +1 -0
  9. package/dist/hooks/useFormItemControl.js +60 -23
  10. package/dist/hooks/useFormListControl.d.ts +2 -1
  11. package/dist/hooks/useFormListControl.js +60 -10
  12. package/dist/index.cjs.d.ts +1 -0
  13. package/dist/index.d.ts +4 -3
  14. package/dist/index.esm.d.ts +1 -0
  15. package/dist/index.js +4 -2
  16. package/dist/providers/Form.d.ts +4 -2
  17. package/dist/providers/Form.js +98 -28
  18. package/dist/stores/formStore.d.ts +27 -2
  19. package/dist/stores/formStore.js +25 -9
  20. package/dist/test/TestDialog.d.ts +3 -0
  21. package/dist/test/TestDialog.js +21 -0
  22. package/dist/test/TestListener.d.ts +3 -0
  23. package/dist/test/TestListener.js +17 -0
  24. package/dist/test/TestSelect.d.ts +6 -0
  25. package/dist/test/TestSelect.js +24 -0
  26. package/dist/types/index.d.ts +1 -1
  27. package/dist/types/public.d.ts +6 -1
  28. package/dist/utils/obj.util.d.ts +1 -1
  29. package/dist/utils/obj.util.js +16 -5
  30. package/package.json +3 -1
  31. package/src/App.tsx +98 -4
  32. package/src/components/Form/FormCleanUp.tsx +3 -7
  33. package/src/components/Form/FormItem.tsx +56 -31
  34. package/src/components/Form/FormList.tsx +17 -4
  35. package/src/components/Form/InputWrapper.tsx +5 -0
  36. package/src/hooks/useFormItemControl.ts +70 -29
  37. package/src/hooks/useFormListControl.ts +104 -26
  38. package/src/index.ts +27 -13
  39. package/src/providers/Form.tsx +126 -17
  40. package/src/stores/formStore.ts +319 -288
  41. package/src/test/TestDialog.tsx +52 -0
  42. package/src/test/TestListener.tsx +21 -0
  43. package/src/test/TestSelect.tsx +38 -0
  44. package/src/types/index.ts +1 -1
  45. package/src/types/public.ts +7 -1
  46. package/src/utils/obj.util.ts +44 -13
@@ -0,0 +1,52 @@
1
+ import {
2
+ Button,
3
+ Dialog,
4
+ DialogContent,
5
+ DialogContentText,
6
+ DialogTitle,
7
+ TextField,
8
+ } from "@mui/material";
9
+ import { Box } from "@mui/system";
10
+ import { useToggle } from "minh-custom-hooks-release";
11
+ import FormItem from "../components/Form/FormItem";
12
+ import TestSelect from "./TestSelect";
13
+
14
+ type Props = {};
15
+
16
+ function TestDialog({}: Props) {
17
+ const { state: open, toggle } = useToggle();
18
+ return (
19
+ <Box>
20
+ <Dialog open={open} onClose={toggle}>
21
+ <DialogTitle>Test Dialog</DialogTitle>
22
+ <DialogContent>
23
+ <DialogContentText>This is a test dialog.</DialogContentText>
24
+ <FormItem
25
+ rules={[
26
+ {
27
+ handler(value) {
28
+ console.log("Validating in dialog: ", value);
29
+ return Boolean(value);
30
+ },
31
+ message: "Testt",
32
+ },
33
+ ]}
34
+ controlAfterInit
35
+ initialValue={null}
36
+ name="testSelectInsideDialog"
37
+ >
38
+ <TestSelect />
39
+ </FormItem>
40
+ <FormItem controlAfterInit initialValue={""} name="anotherField">
41
+ <TextField />
42
+ </FormItem>
43
+ </DialogContent>
44
+ </Dialog>
45
+ <Button variant="contained" onClick={toggle}>
46
+ Open Test Dialog
47
+ </Button>
48
+ </Box>
49
+ );
50
+ }
51
+
52
+ export default TestDialog;
@@ -0,0 +1,21 @@
1
+ import { cloneDeep } from "lodash";
2
+ import { useEffect } from "react";
3
+ import { useShallow } from "zustand/react/shallow";
4
+ import { useFormStore } from "../stores/formStore";
5
+
6
+ type Props = {};
7
+
8
+ function TestListener({}: Props) {
9
+ const { listeners } = useFormStore(
10
+ useShallow((state) => ({
11
+ listeners: state.listeners,
12
+ })),
13
+ );
14
+
15
+ useEffect(() => {
16
+ console.log("Listeners updated: ", cloneDeep(listeners));
17
+ }, [listeners]);
18
+ return <div>TestListener</div>;
19
+ }
20
+
21
+ export default TestListener;
@@ -0,0 +1,38 @@
1
+ import { Autocomplete, TextField } from "@mui/material";
2
+
3
+ type Props = {
4
+ value?: any;
5
+ onChange?: (value: any) => void;
6
+ };
7
+
8
+ function TestSelect({ value = null, onChange }: Props) {
9
+ return (
10
+ <Autocomplete
11
+ value={value}
12
+ onChange={(_, newValue) => {
13
+ onChange?.(newValue);
14
+ }}
15
+ renderInput={(params) => <TextField {...params} />}
16
+ options={[
17
+ {
18
+ value: "option1",
19
+ label: "Option 1",
20
+ },
21
+ {
22
+ value: "option2",
23
+ label: "Option 2",
24
+ },
25
+ ]}
26
+ getOptionKey={(o) => {
27
+ // console.log("Option get key: ", o);
28
+ return o?.value;
29
+ }}
30
+ getOptionLabel={(o) => {
31
+ // console.log("Option get label: ", o);
32
+ return o?.label;
33
+ }}
34
+ />
35
+ );
36
+ }
37
+
38
+ export default TestSelect;
@@ -1 +1 @@
1
- export * from './public';
1
+ export * from "./public";
@@ -1,5 +1,5 @@
1
- import type { GetConstantType } from "./util";
2
1
  import type { SUBMIT_STATE } from "../constants/form";
2
+ import type { GetConstantType } from "./util";
3
3
 
4
4
  export type FormValues<T = any> = T;
5
5
 
@@ -67,6 +67,12 @@ export interface UseFormItemReturn<T = any> {
67
67
  submitState?: SubmitState;
68
68
  }
69
69
 
70
+ export interface UseFormItemStateWatchReturn {
71
+ isTouched?: boolean;
72
+ isDirty?: boolean;
73
+ errors: FormFieldError[];
74
+ }
75
+
70
76
  export interface UseFormListProps<T = any> {
71
77
  name?: string;
72
78
  form?: PublicFormInstance<T>;
@@ -1,22 +1,53 @@
1
- import { filter, isNil, join } from "lodash";
1
+ import { filter, isNil, isPlainObject, join } from "lodash";
2
2
 
3
- export function getAllNoneObjStringPath(value: any, prevPath: string = "") {
4
- if (typeof value === "object") {
5
- return Object.keys(value).reduce((prev, cur) => {
3
+ export function getAllNoneObjStringPath(
4
+ value: any,
5
+ prevPath: string = "",
6
+ ): string[] {
7
+ // primitive / function / null / undefined => dừng
8
+ if (
9
+ value === null ||
10
+ value === undefined ||
11
+ typeof value !== "object" ||
12
+ typeof value === "function"
13
+ ) {
14
+ return [prevPath];
15
+ }
16
+
17
+ // array thì đi sâu
18
+ if (Array.isArray(value)) {
19
+ return value.reduce((prev: string[], item, index) => {
6
20
  return [
7
21
  ...prev,
8
-
9
22
  ...getAllNoneObjStringPath(
10
- value[cur],
23
+ item,
11
24
  join(
12
- filter([prevPath, cur], (v) => !isNil(v) && v !== ""),
13
- "."
14
- )
25
+ filter([prevPath, String(index)], (v) => !isNil(v) && v !== ""),
26
+ ".",
27
+ ),
15
28
  ),
16
29
  ];
17
30
  }, []);
18
31
  }
19
- return [prevPath];
32
+
33
+ // class instance (non-plain object) => dừng
34
+ if (!isPlainObject(value)) {
35
+ return [prevPath];
36
+ }
37
+
38
+ // plain object => đi sâu
39
+ return Object.keys(value).reduce((prev: string[], cur) => {
40
+ return [
41
+ ...prev,
42
+ ...getAllNoneObjStringPath(
43
+ value[cur],
44
+ join(
45
+ filter([prevPath, cur], (v) => !isNil(v) && v !== ""),
46
+ ".",
47
+ ),
48
+ ),
49
+ ];
50
+ }, []);
20
51
  }
21
52
 
22
53
  export function getAllStringPath(value: any, prevPath: string = "") {
@@ -26,14 +57,14 @@ export function getAllStringPath(value: any, prevPath: string = "") {
26
57
  ...prev,
27
58
  join(
28
59
  filter([prevPath, cur], (v) => !isNil(v) && v !== ""),
29
- "."
60
+ ".",
30
61
  ),
31
62
  ...getAllStringPath(
32
63
  value[cur],
33
64
  join(
34
65
  filter([prevPath, cur], (v) => !isNil(v) && v !== ""),
35
- "."
36
- )
66
+ ".",
67
+ ),
37
68
  ),
38
69
  ];
39
70
  }, []);