react-form-manage 1.0.7-beta.2 → 1.0.8-beta.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.
- package/CHANGELOG.md +7 -1
- package/dist/components/Form/FormCleanUp.js +37 -40
- package/dist/components/Form/FormItem.js +42 -43
- package/dist/components/Form/FormList.js +11 -8
- package/dist/components/Form/InputWrapper.js +6 -3
- package/dist/components/Input.js +7 -4
- package/dist/constants/form.d.ts +7 -0
- package/dist/constants/form.js +9 -0
- package/dist/constants/validation.js +64 -33
- package/dist/contexts/FormContext.js +4 -1
- package/dist/hooks/useFormItemControl.d.ts +2 -1
- package/dist/hooks/useFormItemControl.js +303 -380
- package/dist/hooks/useFormListControl.js +213 -268
- package/dist/index.d.ts +3 -2
- package/dist/index.js +18 -3
- package/dist/providers/Form.d.ts +1 -1
- package/dist/providers/Form.js +275 -312
- package/dist/stores/formStore.js +272 -296
- package/dist/types/index.js +1 -1
- package/dist/types/public.d.ts +4 -0
- package/dist/types/public.js +0 -1
- package/dist/types/util.d.ts +3 -0
- package/dist/types/util.js +0 -0
- package/dist/utils/obj.util.js +25 -21
- package/package.json +3 -2
- package/src/components/Form/FormItem.tsx +2 -1
- package/src/components/Form/InputWrapper.tsx +8 -3
- package/src/constants/form.ts +8 -0
- package/src/hooks/useFormItemControl.ts +12 -1
- package/src/index.ts +4 -0
- package/src/providers/Form.tsx +1 -1
- package/src/types/public.ts +6 -0
- package/src/types/util.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,10 +8,16 @@ All notable changes to this project will be documented in this file.
|
|
|
8
8
|
- Improve `getValueFromEvent` in FormItem for custom event handler support
|
|
9
9
|
- Type `errors` as `FormFieldError[]` for better IDE support
|
|
10
10
|
|
|
11
|
-
## [1.0.7
|
|
11
|
+
## [1.0.7] - 2026-01-22
|
|
12
12
|
|
|
13
13
|
- Fix FormItem initial value propagation so cleaned-up items rehydrate correctly
|
|
14
14
|
- Keep `getValueFromEvent` custom extraction while preserving default `target.value` fallback
|
|
15
|
+
- Promote FormFieldError export and error typing improvements from beta to stable
|
|
16
|
+
|
|
17
|
+
## [1.0.8-beta.0] - 2026-01-22
|
|
18
|
+
|
|
19
|
+
- Add typed submit state (`SubmitState`) and export submit state constants
|
|
20
|
+
- Add build-time console stripping so published dist has no console logs
|
|
15
21
|
|
|
16
22
|
## [1.0.6] - 2026-01-22
|
|
17
23
|
|
|
@@ -1,46 +1,43 @@
|
|
|
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 { useFormCleanUp, useFormListeners, useFormStore
|
|
4
|
+
import { useFormCleanUp, useFormListeners, useFormStore } from "../../stores/formStore";
|
|
5
5
|
const FormCleanUp = () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (c.type === "array") {
|
|
34
|
-
console.log(c);
|
|
35
|
-
clearArrItem(c.formName, c.name);
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
clearCleanUpStack();
|
|
6
|
+
const { cleanUpStack, clearCleanUpStack } = useFormCleanUp(useShallow((state) => ({
|
|
7
|
+
cleanUpStack: state.cleanUpStack,
|
|
8
|
+
clearCleanUpStack: state.clearCleanUpStack
|
|
9
|
+
})));
|
|
10
|
+
const { revokeListener } = useFormListeners(useShallow((state) => ({
|
|
11
|
+
revokeListener: state.revokeListener
|
|
12
|
+
})));
|
|
13
|
+
const { clearObjKeyItem, clearArrItem } = useFormStore(useShallow((state) => {
|
|
14
|
+
return {
|
|
15
|
+
clearObjKeyItem: state.clearObjKeyItem,
|
|
16
|
+
clearArrItem: state.clearArrItem
|
|
17
|
+
};
|
|
18
|
+
}));
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (Array.isArray(cleanUpStack) && (cleanUpStack == null ? void 0 : cleanUpStack.length)) {
|
|
21
|
+
cleanUpStack.forEach((c) => {
|
|
22
|
+
if (c.itemKey) {
|
|
23
|
+
revokeListener(c.itemKey, (listener, same) => {
|
|
24
|
+
if (!same.length) {
|
|
25
|
+
clearObjKeyItem(listener.formName, listener.name);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
if (c.type === "array") {
|
|
30
|
+
clearArrItem(c.formName, c.name);
|
|
31
|
+
} else {
|
|
32
|
+
}
|
|
42
33
|
}
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
});
|
|
35
|
+
clearCleanUpStack();
|
|
36
|
+
}
|
|
37
|
+
}, [cleanUpStack]);
|
|
38
|
+
return _jsx(_Fragment, {});
|
|
39
|
+
};
|
|
40
|
+
var stdin_default = FormCleanUp;
|
|
41
|
+
export {
|
|
42
|
+
stdin_default as default
|
|
45
43
|
};
|
|
46
|
-
export default FormCleanUp;
|
|
@@ -1,47 +1,46 @@
|
|
|
1
1
|
import { cloneElement, useRef, useState } from "react";
|
|
2
2
|
import { v4 } from "uuid";
|
|
3
3
|
import useFormItemControl from "../../hooks/useFormItemControl";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
onFocus,
|
|
44
|
-
validateState: state,
|
|
45
|
-
ref: elRef,
|
|
46
|
-
});
|
|
4
|
+
function FormItem({ children, name, formName, initialValue, formItemId: externalFormItemId, rules, valuePropName = "value", getValueFromEvent }) {
|
|
5
|
+
const elRef = useRef(null);
|
|
6
|
+
const [formItemId] = useState(externalFormItemId != null ? externalFormItemId : v4());
|
|
7
|
+
const { value, onChange, errors, state, onFocus, isDirty, submitState } = useFormItemControl({
|
|
8
|
+
formName,
|
|
9
|
+
name,
|
|
10
|
+
initialValue,
|
|
11
|
+
formItemId,
|
|
12
|
+
rules,
|
|
13
|
+
elementRef: elRef
|
|
14
|
+
});
|
|
15
|
+
return cloneElement(children, {
|
|
16
|
+
// ref: inputRef,
|
|
17
|
+
[valuePropName]: value,
|
|
18
|
+
onChange: (...args) => {
|
|
19
|
+
let val = args[0];
|
|
20
|
+
if (getValueFromEvent && typeof getValueFromEvent === "function") {
|
|
21
|
+
val = getValueFromEvent(...args);
|
|
22
|
+
} else {
|
|
23
|
+
const e = args[0];
|
|
24
|
+
if (e && e.target) {
|
|
25
|
+
val = e.target.value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
onChange(val);
|
|
29
|
+
},
|
|
30
|
+
// onFocus: () => {
|
|
31
|
+
// setIsTouched(true);
|
|
32
|
+
// },
|
|
33
|
+
// isTouched: isTouched,
|
|
34
|
+
isDirty,
|
|
35
|
+
// errors: errors,
|
|
36
|
+
// formState,
|
|
37
|
+
errors,
|
|
38
|
+
onFocus,
|
|
39
|
+
validateState: state,
|
|
40
|
+
ref: elRef,
|
|
41
|
+
submitState
|
|
42
|
+
});
|
|
47
43
|
}
|
|
44
|
+
export {
|
|
45
|
+
FormItem as default
|
|
46
|
+
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import useTestRrenderListControl from "../../hooks/useFormListControl";
|
|
2
2
|
const FormList = ({ name, initialValues, form, formName, children }) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
const { listFields, ...actions } = useTestRrenderListControl({
|
|
4
|
+
name,
|
|
5
|
+
initialValues,
|
|
6
|
+
form,
|
|
7
|
+
formName
|
|
8
|
+
});
|
|
9
|
+
return children(listFields, { ...actions });
|
|
10
|
+
};
|
|
11
|
+
var stdin_default = FormList;
|
|
12
|
+
export {
|
|
13
|
+
stdin_default as default
|
|
10
14
|
};
|
|
11
|
-
export default FormList;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { cloneElement } from "react";
|
|
3
|
+
import { SUBMIT_STATE } from "../../constants/form";
|
|
3
4
|
const InputWrapper = ({ children, errors = [], ...props }) => {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
return _jsxs("div", { children: [cloneElement(children, props), (props.isDirty || props.submitState === SUBMIT_STATE.REJECTED) && (errors == null ? void 0 : errors.map((r) => _jsx("div", { children: r == null ? void 0 : r.message }, `${props.name}-${props.formItemId}-${r.ruleName}`)))] });
|
|
6
|
+
};
|
|
7
|
+
var stdin_default = InputWrapper;
|
|
8
|
+
export {
|
|
9
|
+
stdin_default as default
|
|
6
10
|
};
|
|
7
|
-
export default InputWrapper;
|
package/dist/components/Input.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from "react";
|
|
3
3
|
const Input = forwardRef(({ onChange, ...props }, ref) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
return _jsx("input", { ref, onChange: (e) => {
|
|
5
|
+
onChange == null ? void 0 : onChange(e.target.value);
|
|
6
|
+
}, ...props });
|
|
7
7
|
});
|
|
8
|
-
|
|
8
|
+
var stdin_default = Input;
|
|
9
|
+
export {
|
|
10
|
+
stdin_default as default
|
|
11
|
+
};
|
|
@@ -1,33 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export
|
|
33
|
-
|
|
1
|
+
const IS_STRING_NUMBER_REGEX = /^\d+$/;
|
|
2
|
+
const IS_USERNAME_REGEX = /^[a-zA-Z0-9._]{3,16}$/;
|
|
3
|
+
const IS_PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
|
|
4
|
+
const IS_POSITIVE_STRING_NUMBER_REGEX = /^[1-9]\d*$/;
|
|
5
|
+
const IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX = /^(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
6
|
+
const IS_VIETNAMESE_PHONE_NUMBER_REGEX = /^(?:\+84|0)[\s\-\.]?(?:3[2-9]|5[6|8|9]|7[06-9]|8[1-5]|9[0-9])[\s\-\.]?\d[\d\s\-\.]{6,8}$/;
|
|
7
|
+
const IS_EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
8
|
+
const IS_NAME_REGEX = /^[A-Za-zÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚĂĐĨŨƠàáâãèéêìíòóôõùúăđĩũơƯĂÂÊÔƠƯăâêôơưÇçÝýỳỵỷỹ\s]{2,50}$/;
|
|
9
|
+
const IS_NOSPACE_STRING_AND_NUMBER_REGEX = /^[A-Za-zÀ-ỹ0-9]+$/;
|
|
10
|
+
const IS_STRING_AND_NUMBER_REGEX = /^[A-Za-zÀ-ỹ0-9][A-Za-zÀ-ỹ0-9\s]*$/;
|
|
11
|
+
const IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX = /^[A-Za-z0-9]+$/;
|
|
12
|
+
const IS_ALPHABET_STRING_AND_NUMBER_REGEX = /^[A-Za-z0-9]+(?:\s[A-Za-z0-9]+)*$/;
|
|
13
|
+
const IS_NO_SPACE_ALPHABET_STRING_REGEX = /^[A-Za-z]+$/;
|
|
14
|
+
const HANDLER_INVALID_MESSAGE = "Invalid value!";
|
|
15
|
+
const MIN_INVALID_MESSAGE = "Min value invalid!";
|
|
16
|
+
const MAX_INVALID_MESSAGE = "Max value invalid!";
|
|
17
|
+
const MIN_INVALID_LENGTH_MESSAGE = "Max length invalid!";
|
|
18
|
+
const MAX_INVALID_LENGTH_MESSAGE = "Max length invalid!";
|
|
19
|
+
const IS_STRING_NUMBER_INVALID_MESSAGE = "Must be number!";
|
|
20
|
+
const IS_USERNAME_INVALID_MESSAGE = `Username must be containes string, number, '.' or '_'!`;
|
|
21
|
+
const IS_PASSWORD_INVALID_MESSAGE = "Password must be contains Minimum 8 characters, with uppercase, lowercase, number, special character!";
|
|
22
|
+
const IS_POSITIVE_STRING_NUMBER_INVALID_MESSAGE = "Must be positive number!";
|
|
23
|
+
const IS_POSITIVE_INTEGER_STRING_NUMBER_INVALID_MESSAGE = "Must be positive integer number!";
|
|
24
|
+
const IS_VIETNAMESE_PHONE_NUMBER_INVALID_MESSAGE = "Invalid phone number format!";
|
|
25
|
+
const IS_EMAIL_INVALID_MESSAGE = "Invalid email format!";
|
|
26
|
+
const IS_NAME_INVALID_MESSAGE = "Invalid name format!";
|
|
27
|
+
const IS_NOSPACE_STRING_AND_NUMBER_MESSAGE = "String must only includes string and number without whitespace!";
|
|
28
|
+
const IS_STRING_AND_NUMBER_MESSAGE = "String must only includes string, number and whitespace!";
|
|
29
|
+
const IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_MESSAGE = "String must only includes alphabet characters and numbers!";
|
|
30
|
+
const IS_ALPHABET_STRING_AND_NUMBER_MESSAGE = "String must only includes alphabet charaters, numbers and whitespace";
|
|
31
|
+
const IS_NO_SPACE_ALPHABET_STRING_MESSAGE = "String must only includes alphabet";
|
|
32
|
+
export {
|
|
33
|
+
HANDLER_INVALID_MESSAGE,
|
|
34
|
+
IS_ALPHABET_STRING_AND_NUMBER_MESSAGE,
|
|
35
|
+
IS_ALPHABET_STRING_AND_NUMBER_REGEX,
|
|
36
|
+
IS_EMAIL_INVALID_MESSAGE,
|
|
37
|
+
IS_EMAIL_REGEX,
|
|
38
|
+
IS_NAME_INVALID_MESSAGE,
|
|
39
|
+
IS_NAME_REGEX,
|
|
40
|
+
IS_NOSPACE_STRING_AND_NUMBER_MESSAGE,
|
|
41
|
+
IS_NOSPACE_STRING_AND_NUMBER_REGEX,
|
|
42
|
+
IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_MESSAGE,
|
|
43
|
+
IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX,
|
|
44
|
+
IS_NO_SPACE_ALPHABET_STRING_MESSAGE,
|
|
45
|
+
IS_NO_SPACE_ALPHABET_STRING_REGEX,
|
|
46
|
+
IS_PASSWORD_INVALID_MESSAGE,
|
|
47
|
+
IS_PASSWORD_REGEX,
|
|
48
|
+
IS_POSITIVE_INTEGER_STRING_NUMBER_INVALID_MESSAGE,
|
|
49
|
+
IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX,
|
|
50
|
+
IS_POSITIVE_STRING_NUMBER_INVALID_MESSAGE,
|
|
51
|
+
IS_POSITIVE_STRING_NUMBER_REGEX,
|
|
52
|
+
IS_STRING_AND_NUMBER_MESSAGE,
|
|
53
|
+
IS_STRING_AND_NUMBER_REGEX,
|
|
54
|
+
IS_STRING_NUMBER_INVALID_MESSAGE,
|
|
55
|
+
IS_STRING_NUMBER_REGEX,
|
|
56
|
+
IS_USERNAME_INVALID_MESSAGE,
|
|
57
|
+
IS_USERNAME_REGEX,
|
|
58
|
+
IS_VIETNAMESE_PHONE_NUMBER_INVALID_MESSAGE,
|
|
59
|
+
IS_VIETNAMESE_PHONE_NUMBER_REGEX,
|
|
60
|
+
MAX_INVALID_LENGTH_MESSAGE,
|
|
61
|
+
MAX_INVALID_MESSAGE,
|
|
62
|
+
MIN_INVALID_LENGTH_MESSAGE,
|
|
63
|
+
MIN_INVALID_MESSAGE
|
|
64
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type RefObject } from "react";
|
|
2
2
|
import type { FormInstance } from "../stores/formStore";
|
|
3
|
-
import type { ValidationRule } from "../types/public";
|
|
3
|
+
import type { SubmitState, ValidationRule } from "../types/public";
|
|
4
4
|
type AnyObject = Record<string, any>;
|
|
5
5
|
interface UseFormItemControlProps {
|
|
6
6
|
formName?: string;
|
|
@@ -18,6 +18,7 @@ interface UseFormItemControlReturn {
|
|
|
18
18
|
errors: any;
|
|
19
19
|
onFocus: () => void;
|
|
20
20
|
isDirty?: boolean;
|
|
21
|
+
submitState?: SubmitState;
|
|
21
22
|
}
|
|
22
23
|
export default function useFormItemControl<T = any>({ formName, form, name, initialValue, formItemId, rules, elementRef, }: UseFormItemControlProps): UseFormItemControlReturn;
|
|
23
24
|
export {};
|