@paragrav/rhf-utils 0.65.0 → 0.67.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/README.md +3 -2
- package/dist/tsdown/FormRelayOptions-mBqiP41Z.d.ts +29 -0
- package/dist/tsdown/FormRelaySetter-BKO0Wodf.js +192 -0
- package/dist/tsdown/RhfUtilsClientConfigType-CeOJzNAc.d.ts +212 -0
- package/dist/tsdown/RhfUtilsContextType-BFmDtONY.d.ts +81 -0
- package/dist/tsdown/index.d.ts +207 -0
- package/dist/tsdown/index.js +745 -0
- package/dist/tsdown/relay.d.ts +56 -0
- package/dist/tsdown/relay.js +71 -0
- package/dist/tsdown/trpc.d.ts +36 -0
- package/dist/tsdown/trpc.js +47 -0
- package/package.json +8 -24
- package/dist/dts/Register.d.ts +0 -16
- package/dist/dts/_exports/config.d.ts +0 -2
- package/dist/dts/_exports/errors.d.ts +0 -3
- package/dist/dts/_exports/form.d.ts +0 -7
- package/dist/dts/_exports/index.d.ts +0 -14
- package/dist/dts/_exports/relay.d.ts +0 -7
- package/dist/dts/_exports/submit.d.ts +0 -4
- package/dist/dts/_exports/trpc.d.ts +0 -2
- package/dist/dts/_exports/types.d.ts +0 -7
- package/dist/dts/_exports/zod.d.ts +0 -6
- package/dist/dts/client/config/RhfUtilsClientConfigType.d.ts +0 -71
- package/dist/dts/client/config/context/RhfUtilsClientConfigContext.d.ts +0 -3
- package/dist/dts/client/config/context/RhfUtilsClientConfigProvider.d.ts +0 -7
- package/dist/dts/client/config/context/useRhfUtilsClientConfig.d.ts +0 -1
- package/dist/dts/devtool/LazyDevTool.d.ts +0 -10
- package/dist/dts/devtool/LazyDevToolViaProviders.d.ts +0 -1
- package/dist/dts/errors/flat/FlatFieldErrorsList.d.ts +0 -6
- package/dist/dts/errors/flat/context/FlatFieldErrorsContextProvider.d.ts +0 -10
- package/dist/dts/errors/flat/context/FlatFieldErrorsOutputConfig.d.ts +0 -19
- package/dist/dts/errors/flat/context/useFlatFieldErrorsContext.d.ts +0 -11
- package/dist/dts/errors/flat/context/useFlatFieldErrorsContextHasOnlyOrphans.d.ts +0 -6
- package/dist/dts/errors/flat/context/useFlatFieldErrorsContextOutput.d.ts +0 -5
- package/dist/dts/errors/flat/filterFlatFieldErrors.d.ts +0 -7
- package/dist/dts/errors/flat/flattenFieldErrors.d.ts +0 -14
- package/dist/dts/errors/flat/getFlatFieldErrors.d.ts +0 -35
- package/dist/dts/errors/flat/types.d.ts +0 -16
- package/dist/dts/errors/getRefdFromFlatFieldErrors.d.ts +0 -1
- package/dist/dts/errors/isFieldErrorRefd.d.ts +0 -5
- package/dist/dts/errors/isFlatFieldErrorEntryRefd.d.ts +0 -5
- package/dist/dts/errors/message/FormErrorMessage.d.ts +0 -7
- package/dist/dts/errors/message/RhfUtilsFieldErrorMessage.d.ts +0 -10
- package/dist/dts/errors/nonfield/RhfUtilsNonFieldErrorMarker.d.ts +0 -13
- package/dist/dts/errors/nonfield/RhfUtilsNonFieldErrorMarker.spec.d.ts +0 -1
- package/dist/dts/errors/nonfield/RhfUtilsNonFieldErrorMarker.utils.d.ts +0 -18
- package/dist/dts/errors/nonfield/RhfUtilsNonFieldErrorMarkerHtmlAttribute.d.ts +0 -4
- package/dist/dts/errors/nonfield/isNonFieldError.d.ts +0 -17
- package/dist/dts/errors/nonfield/isNonFieldErrorMarkerInDOM.d.ts +0 -5
- package/dist/dts/errors/orphan/getIsOrphanFormErrorWithParentElement.d.ts +0 -5
- package/dist/dts/errors/orphan/getOrphansFromFlatFieldErrors.d.ts +0 -2
- package/dist/dts/errors/orphan/isOrphanFormError.d.ts +0 -2
- package/dist/dts/errors/output/consoleErrors.d.ts +0 -5
- package/dist/dts/errors/output/types.d.ts +0 -7
- package/dist/dts/errors/root/RootErrorsListFromFlatFieldErrorsContext.d.ts +0 -1
- package/dist/dts/errors/root/consts.d.ts +0 -1
- package/dist/dts/errors/root/getRootsFromFlatFieldErrors.d.ts +0 -1
- package/dist/dts/errors/root/isFlatFieldErrorEntryPathRoot.d.ts +0 -5
- package/dist/dts/errors/root/isFormErrorPathRoot.d.ts +0 -6
- package/dist/dts/errors/trpc/makeOnSubmitTrpcClientErrorHandler.d.ts +0 -9
- package/dist/dts/errors/trpc/trpcClientErrorMessageSchema.d.ts +0 -19
- package/dist/dts/errors/trpc/trpcClientErrorToFormSubmitFieldErrorsSchemaTransformer.d.ts +0 -23
- package/dist/dts/form/RHF_UseFormReturnWithoutProxiesType.d.ts +0 -15
- package/dist/dts/form/RhfUtilsFormInjectorProps.d.ts +0 -17
- package/dist/dts/form/UseRhfUtilsFormChildrenPropsType.d.ts +0 -25
- package/dist/dts/form/_Controller.d.ts +0 -4
- package/dist/dts/form/context/utils/LastSubmitStateType.d.ts +0 -1
- package/dist/dts/form/context/utils/RhfUtilsContextProvider.d.ts +0 -9
- package/dist/dts/form/context/utils/RhfUtilsContextType.d.ts +0 -12
- package/dist/dts/form/context/utils/useRhfUtilsContext.d.ts +0 -5
- package/dist/dts/form/context/utils/useRhfUtilsContextRequestSubmit.d.ts +0 -4
- package/dist/dts/form/defaults/UseRhfUtilsFormGlobalDefaults.d.ts +0 -24
- package/dist/dts/form/defaults/UseRhfUtilsFormInstanceDefaults.d.ts +0 -18
- package/dist/dts/form/defaults/UseRhfUtilsFormResolvedDefaultsType.d.ts +0 -12
- package/dist/dts/form/defaults/form/UseRhfUtilsFormInstanceFormProps.d.ts +0 -6
- package/dist/dts/form/defaults/form/getRhfUtilsFormResolvedFormProps.d.ts +0 -2
- package/dist/dts/form/defaults/form/useRhfUtilsFormResolvedFormProps.d.ts +0 -293
- package/dist/dts/form/options/RhfUtilsFormOptionsType.d.ts +0 -27
- package/dist/dts/form/options/getRhfUtilsFormResolvedOptions.d.ts +0 -2
- package/dist/dts/form/options/useRhfUtilsFormResolvedOptions.d.ts +0 -8
- package/dist/dts/form/providers/RhfUtilsFormProviders.d.ts +0 -6
- package/dist/dts/form/providers/RhfUtilsFormProvidersPropsType.d.ts +0 -17
- package/dist/dts/form/relay/FormRelayOptions.d.ts +0 -16
- package/dist/dts/form/relay/context/FormRelayContextProvider.d.ts +0 -4
- package/dist/dts/form/relay/context/useFormRelayContext.d.ts +0 -12
- package/dist/dts/form/relay/context/utils.d.ts +0 -4
- package/dist/dts/form/relay/get/FormRelayGroupType.d.ts +0 -16
- package/dist/dts/form/relay/get/grouper/context/hooks.d.ts +0 -8
- package/dist/dts/form/relay/get/grouper/context/index.d.ts +0 -5
- package/dist/dts/form/relay/get/grouper/context/provider.d.ts +0 -9
- package/dist/dts/form/relay/get/grouper/useFirstFormStateGroup.d.ts +0 -9
- package/dist/dts/form/relay/get/useFormRelay.d.ts +0 -13
- package/dist/dts/form/relay/set/FormRelaySetter.d.ts +0 -6
- package/dist/dts/form/relay/set/useFormRelaySet.d.ts +0 -2
- package/dist/dts/form/relay/types.d.ts +0 -12
- package/dist/dts/form/rhf/SafeFieldValuesType.d.ts +0 -4
- package/dist/dts/form/rhf/UseFormPropsType.d.ts +0 -4
- package/dist/dts/form/rhf/getRhfUtilsFormResolvedRhfProps.d.ts +0 -4
- package/dist/dts/form/rhf/useRhfFormWithResolvedProps.d.ts +0 -5
- package/dist/dts/form/utils/getSubmitterButtonData.d.ts +0 -6
- package/dist/dts/form/utils/useFormRequestSubmit.d.ts +0 -9
- package/dist/dts/form/utils/useHandleCancelWithCheckIfCanBe.d.ts +0 -4
- package/dist/dts/form/utils/useHandleCancelWithCheckIfCanBeViaProviders.d.ts +0 -2
- package/dist/dts/form/utils/useShouldFormBlockNavigation.d.ts +0 -24
- package/dist/dts/form/with-handlers-and-children/RhfUtilsForm.d.ts +0 -3
- package/dist/dts/form/with-handlers-and-children/RhfUtilsFormProps.d.ts +0 -42
- package/dist/dts/form/with-handlers-and-children/RhfUtilsFormPropsOnBeforeSubmitInvariants.d.ts +0 -12
- package/dist/dts/form/with-handlers-and-children/_ChildrenViaProviders.d.ts +0 -3
- package/dist/dts/form/with-handlers-and-children/_FormWithSubmitHandler.d.ts +0 -4
- package/dist/dts/form/with-handlers-and-children/_useHandleSubmit.d.ts +0 -11
- package/dist/dts/form/with-providers/RhfUtilsFormWithProviders.d.ts +0 -8
- package/dist/dts/form/with-providers/RhfUtilsFormWithProvidersProps.d.ts +0 -8
- package/dist/dts/main.d.ts +0 -1
- package/dist/dts/playwright/index.d.ts +0 -0
- package/dist/dts/playwright-ct.config.d.ts +0 -5
- package/dist/dts/resolvers/ObjectSchema.d.ts +0 -7
- package/dist/dts/resolvers/zod/RhfUtilsUseZodFormChildrenFCType.d.ts +0 -7
- package/dist/dts/resolvers/zod/RhfUtilsUseZodFormChildrenPropsType.d.ts +0 -4
- package/dist/dts/resolvers/zod/ZodTypeSafeFieldValuesType.d.ts +0 -5
- package/dist/dts/resolvers/zod/consts.d.ts +0 -4
- package/dist/dts/resolvers/zod/form/RhfUtilsZodForm.d.ts +0 -7
- package/dist/dts/resolvers/zod/getZodResolver.d.ts +0 -4
- package/dist/dts/resolvers/zod/providers/RhfUtilsZodFormProviders.d.ts +0 -8
- package/dist/dts/resolvers/zod/with-providers/RhfUtilsZodFormWithProviders.d.ts +0 -10
- package/dist/dts/submit/UseRhfUtilsFormOnSubmitContextType.d.ts +0 -23
- package/dist/dts/submit/error/FormSubmitError.d.ts +0 -6
- package/dist/dts/submit/error/FormSubmitFieldErrors.d.ts +0 -14
- package/dist/dts/submit/error/setCtxErrorsByFormSubmitFieldErrors.d.ts +0 -8
- package/dist/dts/submit/last-error/LastSubmitErrorContextProvider.d.ts +0 -4
- package/dist/dts/submit/last-error/LastSubmitErrorContextType.d.ts +0 -8
- package/dist/dts/submit/last-error/useLastSubmitError.d.ts +0 -4
- package/dist/dts/submit/last-error/useLastSubmitErrorContext.d.ts +0 -3
- package/dist/dts/submit/last-error/useLastSubmitErrorContextWith.d.ts +0 -2
- package/dist/dts/submit/useFormOnSubmitSuccessfulAndReset.d.ts +0 -13
- package/dist/dts/submit/useFormOnSubmitted.d.ts +0 -4
- package/dist/dts/submit/useResetFormOnSubmitted.d.ts +0 -35
- package/dist/dts/submit/useRhfUtilsFormOnSubmitContext.d.ts +0 -3
- package/dist/dts/submit/useSubmitFormOnChange.d.ts +0 -15
- package/dist/dts/submit/useSubmitFormOnEvent.d.ts +0 -9
- package/dist/dts/submit/useSubmitFormOnWatch.d.ts +0 -14
- package/dist/dts/utils/PassthroughChildren.d.ts +0 -7
- package/dist/dts/utils/createContext.d.ts +0 -10
- package/dist/dts/utils/fixedForwardRef.d.ts +0 -5
- package/dist/dts/utils/isEmptyObject.d.ts +0 -1
- package/dist/dts/utils/timeoutAsync.d.ts +0 -6
- package/dist/dts/utils/types.d.ts +0 -3
- package/dist/dts/utils/useDebouncedOnChangeValue.d.ts +0 -14
- package/dist/dts/utils/useImperativeForwardedRef.d.ts +0 -9
- package/dist/dts/utils/useIsFirstRender.d.ts +0 -7
- package/dist/dts/utils/useRefIfValueWasTrue.d.ts +0 -2
- package/dist/dts/utils/useToggle.d.ts +0 -2
- package/dist/dts/vite-env.d.ts +0 -1
- package/dist/esm/FormRelaySetter.mjs +0 -89
- package/dist/esm/index.mjs +0 -351
- package/dist/esm/relay.mjs +0 -49
- package/dist/esm/trpc.mjs +0 -24
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Integration and utility library for [react-hook-form](https://www.react-hook-for
|
|
|
9
9
|
- TypeScript-first
|
|
10
10
|
- global configuration (🔗 [`RhfUtilsClientConfig`](#config) section)
|
|
11
11
|
- RHF (`UseFormProps`) and utilities (`RhfUtilsFormOptions`) options defaults
|
|
12
|
-
- inject your own hooks and UI (`
|
|
12
|
+
- inject your own hooks and UI (`FormInjector`)
|
|
13
13
|
- server error transformation (`onSubmitErrorUnknown`) ✨
|
|
14
14
|
- handle cancel prompt (`useCanFormBeCancelled`) ✨
|
|
15
15
|
- RHF `FormState.errors` logging/throwing (`RhfUtilsClientConfig.fieldErrors`) ✨
|
|
@@ -76,7 +76,7 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
76
76
|
|
|
77
77
|
// inject your own hooks and components
|
|
78
78
|
// into all RhfUtilsZodForm instances
|
|
79
|
-
|
|
79
|
+
FormInjector: (
|
|
80
80
|
// RhfUtilsFormInjectorProps
|
|
81
81
|
{
|
|
82
82
|
Outlet, // Form instance (RhfUtilsZodForm.Children) "outlet"
|
|
@@ -116,6 +116,7 @@ export const rhfUtilsClientConfig: RhfUtilsClientConfig = {
|
|
|
116
116
|
// (i.e., calling your own hook in `FormComponent`)
|
|
117
117
|
useCanFormBeCancelled: () => {
|
|
118
118
|
const { isDirty } = useFormState();
|
|
119
|
+
const myPrompter = useMyPrompter();
|
|
119
120
|
|
|
120
121
|
// return callback to be called at event-time
|
|
121
122
|
return ({ options }) =>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { i as SafeFieldValues, t as RhfUtilsContext } from "./RhfUtilsContextType-BFmDtONY.js";
|
|
2
|
+
import { FormState } from "react-hook-form";
|
|
3
|
+
|
|
4
|
+
//#region src/form/relay/types.d.ts
|
|
5
|
+
type FormRelay<TFieldValues extends SafeFieldValues = SafeFieldValues> = {
|
|
6
|
+
state: FormRelayStateSelected<TFieldValues>;
|
|
7
|
+
options: FormRelayOptions;
|
|
8
|
+
utils: RhfUtilsContext;
|
|
9
|
+
};
|
|
10
|
+
type FormRelayStateSelected<TFieldValues extends SafeFieldValues = SafeFieldValues> = Partial<FormState<TFieldValues> & {
|
|
11
|
+
isMounted: true;
|
|
12
|
+
}>;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/form/relay/FormRelayOptions.d.ts
|
|
15
|
+
type FormRelayOptions = {
|
|
16
|
+
/**
|
|
17
|
+
* Determines what part of RHF's form state is relayed.
|
|
18
|
+
* Also acts to activate RHF proxy values.
|
|
19
|
+
*/
|
|
20
|
+
select: (formState: FormState<SafeFieldValues>) => FormRelayStateSelected;
|
|
21
|
+
/**
|
|
22
|
+
* Arbitrary group name(s) for this form.
|
|
23
|
+
* Think of it like class or category names.
|
|
24
|
+
* (e.g., "parent" or "children")
|
|
25
|
+
*/
|
|
26
|
+
groups?: string[];
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { FormRelay as n, FormRelayStateSelected as r, FormRelayOptions as t };
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { get, useFormState } from "react-hook-form";
|
|
4
|
+
import { flatten } from "flat";
|
|
5
|
+
//#region src/utils/createContext.ts
|
|
6
|
+
/**
|
|
7
|
+
* Create a strictly-typed context that throws error if no provider is found.
|
|
8
|
+
* @returns A tuple with a function to get the context and the context provider.
|
|
9
|
+
*/
|
|
10
|
+
function createContext() {
|
|
11
|
+
const context = React.createContext(void 0);
|
|
12
|
+
const useMaybe = () => React.useContext(context);
|
|
13
|
+
const useRequired = () => {
|
|
14
|
+
const c = useMaybe();
|
|
15
|
+
if (c === void 0) throw new Error();
|
|
16
|
+
return c;
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
Provider: context.Provider,
|
|
20
|
+
useMaybe,
|
|
21
|
+
useRequired
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/form/relay/context/useFormRelayContext.ts
|
|
26
|
+
const { Provider: _FormRelayContextProvider, useRequired: useFormRelayContext } = createContext();
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/form/relay/context/FormRelayContextProvider.tsx
|
|
29
|
+
const FormRelayContextProvider = ({ children }) => {
|
|
30
|
+
const [state, setState] = React.useState({});
|
|
31
|
+
return /* @__PURE__ */ jsx(_FormRelayContextProvider, {
|
|
32
|
+
value: {
|
|
33
|
+
add: React.useCallback((formState, utils, options) => {
|
|
34
|
+
if (state[utils.formId]) throw new Error("Form id already exists.");
|
|
35
|
+
setState((forms) => ({
|
|
36
|
+
...forms,
|
|
37
|
+
[utils.formId]: {
|
|
38
|
+
state: formState,
|
|
39
|
+
utils,
|
|
40
|
+
options
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
}, [state]),
|
|
44
|
+
update: React.useCallback((id, state) => {
|
|
45
|
+
setState((forms) => {
|
|
46
|
+
const current = forms[id];
|
|
47
|
+
if (!current) throw new Error("Form id doesn't exist");
|
|
48
|
+
return {
|
|
49
|
+
...forms,
|
|
50
|
+
[id]: {
|
|
51
|
+
...current,
|
|
52
|
+
state
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}, []),
|
|
57
|
+
remove: React.useCallback((id) => {
|
|
58
|
+
setState((forms) => Object.fromEntries(Object.entries(forms).filter(([entryId]) => entryId !== id)));
|
|
59
|
+
}, []),
|
|
60
|
+
state
|
|
61
|
+
},
|
|
62
|
+
children
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/form/context/utils/useRhfUtilsContext.tsx
|
|
67
|
+
const { Provider: _RhfUtilsContextProvider, useRequired: useRhfUtilsContext, useMaybe: useRhfUtilsMaybeContext } = createContext();
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/utils/isEmptyObject.ts
|
|
70
|
+
const isEmptyObject = (obj) => Object.keys(obj).length === 0;
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/errors/flat/flattenFieldErrors.ts
|
|
73
|
+
/**
|
|
74
|
+
* Flatten a {@link FieldErrors} object.
|
|
75
|
+
*
|
|
76
|
+
* @returns e.g.,
|
|
77
|
+
* ```ts
|
|
78
|
+
* {
|
|
79
|
+
* "address.street.type": "too_short",
|
|
80
|
+
* "address.street.ref.value": "123",
|
|
81
|
+
* "address.street.message": "Required."
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
const flattenFieldErrors = (errors) => flatten(errors);
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/errors/flat/getFlatFieldErrors.ts
|
|
88
|
+
/**
|
|
89
|
+
* Get {@link FlatFieldErrors} from {@link FieldErrors}.
|
|
90
|
+
* This makes it easy to work with potentially deeply-nested {@link FieldErrors}.
|
|
91
|
+
*
|
|
92
|
+
* @param errors {@link FieldErrors} object.
|
|
93
|
+
*
|
|
94
|
+
* @returns `FlatFieldErrors` object.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```
|
|
98
|
+
* {
|
|
99
|
+
* "address.street": {
|
|
100
|
+
* type: "too_short",
|
|
101
|
+
* ref: { value: "123" },
|
|
102
|
+
* message: "Required." }
|
|
103
|
+
* }
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
const getFlatFieldErrors = (errors) => {
|
|
108
|
+
const flattened = flattenFieldErrors(errors);
|
|
109
|
+
return Object.fromEntries(Object.keys(flattened).reduce((entriesAccumulator, flattenedKey) => {
|
|
110
|
+
/**
|
|
111
|
+
* Maybe path.
|
|
112
|
+
*
|
|
113
|
+
* Derived from flattened key by removing leaf node suffix (if present).
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* path: `address.street.message` -> `address.street`
|
|
117
|
+
* @example
|
|
118
|
+
* not path: `address.street.ref` -> `address.street.ref` (no suffix match to replace)
|
|
119
|
+
*/
|
|
120
|
+
const maybePath = flattenedKey.replace(regexMaybeFieldErrorLeafNodeSuffix, "");
|
|
121
|
+
if (maybePath === flattenedKey) return entriesAccumulator;
|
|
122
|
+
const fieldError = get(errors, maybePath, void 0);
|
|
123
|
+
if (!fieldError) return entriesAccumulator;
|
|
124
|
+
/**
|
|
125
|
+
* Add entry to accumulator.
|
|
126
|
+
*
|
|
127
|
+
* (If it's a duplicate (e.g., `.type` leaf node matched before `.message`),
|
|
128
|
+
* it doesn't matter because `Object.fromEntries` will just overwrite
|
|
129
|
+
* first entry with second matching key/value.)
|
|
130
|
+
*/
|
|
131
|
+
entriesAccumulator.push([maybePath, fieldError]);
|
|
132
|
+
return entriesAccumulator;
|
|
133
|
+
}, []));
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Regular expression to maybe match the end of a leaf node path.
|
|
137
|
+
*
|
|
138
|
+
* i.e., `name.type`, `address.street.message`
|
|
139
|
+
*
|
|
140
|
+
* iow: dot [?: non-capturing]("type" | "message")[\b word boundary][$ end of string]
|
|
141
|
+
*/
|
|
142
|
+
const regexMaybeFieldErrorLeafNodeSuffix = /\.(?:type|message)\b$/;
|
|
143
|
+
const getFlatFieldErrorsSansRef = (errors) => Object.fromEntries(Object.entries(getFlatFieldErrors(errors)).map(([name, error]) => [name, {
|
|
144
|
+
type: error.type,
|
|
145
|
+
message: error.message,
|
|
146
|
+
hasRef: !!error.ref
|
|
147
|
+
}]));
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/form/relay/set/useFormRelaySet.ts
|
|
150
|
+
const useFormRelaySet = (options) => {
|
|
151
|
+
if (!options) return;
|
|
152
|
+
const [memoOptions] = React.useState(options);
|
|
153
|
+
useFormRelayOnMount(memoOptions);
|
|
154
|
+
useFormRelayOnChange(memoOptions);
|
|
155
|
+
};
|
|
156
|
+
const useFormRelayOnMount = (options) => {
|
|
157
|
+
const utils = useRhfUtilsContext();
|
|
158
|
+
const relay = useFormRelayContext();
|
|
159
|
+
const formStateForRelay = useFormStateForRelay(options);
|
|
160
|
+
React.useEffect(() => {
|
|
161
|
+
relay.add(formStateForRelay, utils, options);
|
|
162
|
+
return () => {
|
|
163
|
+
relay.remove(utils.formId);
|
|
164
|
+
};
|
|
165
|
+
}, []);
|
|
166
|
+
};
|
|
167
|
+
const useFormRelayOnChange = (options) => {
|
|
168
|
+
const utils = useRhfUtilsContext();
|
|
169
|
+
const relay = useFormRelayContext();
|
|
170
|
+
const formStateForRelay = useFormStateForRelay(options);
|
|
171
|
+
React.useEffect(() => {
|
|
172
|
+
relay.update(utils.formId, formStateForRelay);
|
|
173
|
+
}, [formStateForRelay]);
|
|
174
|
+
};
|
|
175
|
+
/** Transform, memo-ize {@link useFormState}'s return to {@link FormRelayed} */
|
|
176
|
+
const useFormStateForRelay = (options) => {
|
|
177
|
+
const formState = useFormState();
|
|
178
|
+
const formStateSelected = options.select(formState);
|
|
179
|
+
const formStateSelectedJson = JSON.stringify({
|
|
180
|
+
...formStateSelected,
|
|
181
|
+
errors: formStateSelected.errors && getFlatFieldErrorsSansRef(formStateSelected.errors)
|
|
182
|
+
});
|
|
183
|
+
return React.useMemo(() => formStateSelected, [formStateSelectedJson]);
|
|
184
|
+
};
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/form/relay/set/FormRelaySetter.tsx
|
|
187
|
+
const FormRelaySetter = ({ options }) => {
|
|
188
|
+
useFormRelaySet(options);
|
|
189
|
+
return null;
|
|
190
|
+
};
|
|
191
|
+
//#endregion
|
|
192
|
+
export { _RhfUtilsContextProvider as a, FormRelayContextProvider as c, isEmptyObject as i, useFormRelayContext as l, useFormRelaySet as n, useRhfUtilsContext as o, getFlatFieldErrors as r, useRhfUtilsMaybeContext as s, FormRelaySetter as t, createContext as u };
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { a as RhfUtilsFormOptions, i as SafeFieldValues, t as RhfUtilsContext } from "./RhfUtilsContextType-BFmDtONY.js";
|
|
2
|
+
import React$1 from "react";
|
|
3
|
+
import { ControllerProps, FieldError, FieldPath, UseFormProps, UseFormReturn } from "react-hook-form";
|
|
4
|
+
|
|
5
|
+
//#region src/errors/output/types.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Config object for error output.
|
|
8
|
+
*/
|
|
9
|
+
type RhfUtilsErrorsOutputConsoleConfig = {
|
|
10
|
+
type?: 'debug' | 'error';
|
|
11
|
+
message?: string;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/errors/flat/types.d.ts
|
|
15
|
+
/**
|
|
16
|
+
* Flattened field errors object.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* {
|
|
21
|
+
* 'address.street': FieldError
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
type FlatFieldErrors = Record<string, FieldError>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/errors/flat/context/useFlatFieldErrorsContext.d.ts
|
|
28
|
+
type FlatFieldErrorsContext = {
|
|
29
|
+
all: FlatFieldErrors;
|
|
30
|
+
fields: FlatFieldErrors;
|
|
31
|
+
roots: FlatFieldErrors;
|
|
32
|
+
orphans: FlatFieldErrors;
|
|
33
|
+
hasErrors: boolean;
|
|
34
|
+
hasOrphans: boolean;
|
|
35
|
+
};
|
|
36
|
+
declare const _FormErrorsFlatContextProvider: import("react").Provider<FlatFieldErrorsContext | undefined>, useFlatFieldErrorsContext: () => FlatFieldErrorsContext;
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/errors/flat/context/FlatFieldErrorsOutputConfig.d.ts
|
|
39
|
+
type FlatFieldErrorsOutputConfig = {
|
|
40
|
+
/**
|
|
41
|
+
* Configure how/if errors should be outputted to console.
|
|
42
|
+
*
|
|
43
|
+
* Example use cases:
|
|
44
|
+
* - console.debug errors in development environment.
|
|
45
|
+
* - console.error certain errors in production environment.
|
|
46
|
+
*/
|
|
47
|
+
console?: (context: FlatFieldErrorsContext) => RhfUtilsErrorsOutputConsoleConfig | null | false | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Configure how/if errors should be thrown.
|
|
50
|
+
*
|
|
51
|
+
* Example use case:
|
|
52
|
+
* - bring attention to certain errors in development environment.
|
|
53
|
+
*/
|
|
54
|
+
throw?: (context: FlatFieldErrorsContext) => true | string | false | undefined;
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/form/rhf/UseFormPropsType.d.ts
|
|
58
|
+
type RhfUseFormGlobalProps = Pick<UseFormProps, 'mode' | 'reValidateMode' | 'resetOptions' | 'context' | 'shouldFocusError' | 'shouldUnregister' | 'shouldUseNativeValidation' | 'progressive' | 'criteriaMode' | 'delayError'>;
|
|
59
|
+
type RhfUseFormInstanceProps<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = Omit<UseFormProps<TFieldValues, unknown, TTransformedValues>, 'defaultValues' | 'resolver'>;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/form/defaults/UseRhfUtilsFormGlobalDefaults.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* Globally-relevant subset of defaults.
|
|
64
|
+
*/
|
|
65
|
+
type UseRhfUtilsFormGlobalDefaults = {
|
|
66
|
+
/**
|
|
67
|
+
* Default RHF `useForm` settings.
|
|
68
|
+
*
|
|
69
|
+
* (Exposes only non-local props.)
|
|
70
|
+
*/
|
|
71
|
+
rhf?: RhfUseFormGlobalProps;
|
|
72
|
+
/**
|
|
73
|
+
* Global settings and defaults.
|
|
74
|
+
*
|
|
75
|
+
* (Extend this type via `Register` type to inject custom options/functionality via `Children` component.)
|
|
76
|
+
*/
|
|
77
|
+
options?: RhfUtilsFormOptions;
|
|
78
|
+
/**
|
|
79
|
+
* Default props for form element.
|
|
80
|
+
*/
|
|
81
|
+
form?: Pick<React$1.PropsWithoutRef<React$1.JSX.IntrinsicElements['form']>, 'className' | 'noValidate' | 'role'>;
|
|
82
|
+
};
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/submit/error/FormSubmitFieldErrors.d.ts
|
|
85
|
+
/**
|
|
86
|
+
* Field errors structure based on RHF's `FieldErrors`.
|
|
87
|
+
*
|
|
88
|
+
* - Uses {@link SafeFieldValues} instead of more permissive `FieldValues`.
|
|
89
|
+
* - `root.<string>` keys allowed.
|
|
90
|
+
* - `root` is reserved for special use cases.
|
|
91
|
+
* - simplified `ErrorOption` value.
|
|
92
|
+
*/
|
|
93
|
+
type FormSubmitFieldErrors<TFieldValues extends SafeFieldValues = SafeFieldValues> = Record<FieldPath<TFieldValues> | `root.${string}`, {
|
|
94
|
+
message: string;
|
|
95
|
+
type?: string;
|
|
96
|
+
}>;
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/submit/error/FormSubmitError.d.ts
|
|
99
|
+
declare class FormSubmitError<TFieldValues extends SafeFieldValues = SafeFieldValues, TApiValues extends undefined | SafeFieldValues = undefined, TAllValues extends SafeFieldValues = (TApiValues extends undefined ? TFieldValues : TFieldValues | TApiValues)> extends Error {
|
|
100
|
+
errors: FormSubmitFieldErrors<TAllValues>;
|
|
101
|
+
constructor(errors: FormSubmitFieldErrors<TAllValues>, message?: string);
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/submit/UseRhfUtilsFormOnSubmitContextType.d.ts
|
|
105
|
+
/**
|
|
106
|
+
* Props for onSubmit other than `data` and `event`.
|
|
107
|
+
*
|
|
108
|
+
* Consider keeping shape in line with `UseRhfUtilsFormChildrenProps` and `UseRhfUtilsFormReturn`.
|
|
109
|
+
*/
|
|
110
|
+
type UseRhfUtilsFormOnSubmitContext<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues, TApiValues extends undefined | SafeFieldValues = undefined> = {
|
|
111
|
+
utils: RhfUtilsContext;
|
|
112
|
+
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
113
|
+
FormSubmitError: typeof FormSubmitError<TFieldValues, TApiValues>;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Props for onSubmitError other than `error` and `event`.
|
|
117
|
+
*/
|
|
118
|
+
type UseRhfUtilsFormOnSubmitErrorContext<TFieldValues extends SafeFieldValues, TTransformedValues extends SafeFieldValues> = {
|
|
119
|
+
utils: RhfUtilsContext;
|
|
120
|
+
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
121
|
+
errors?: FormSubmitFieldErrors;
|
|
122
|
+
};
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/utils/types.d.ts
|
|
125
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
126
|
+
/** Merge {@link C} into {@link B} into {@link A} (last taking highest precedence). */
|
|
127
|
+
type Merge<A, B, C = unknown, D = unknown> = D & Omit<C, keyof D> & Omit<Omit<B, keyof C>, keyof D> & Omit<Omit<Omit<A, keyof B>, keyof C>, keyof D>;
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/form/_Controller.d.ts
|
|
130
|
+
type _ControllerProps<TFieldValues extends SafeFieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> = Omit<ControllerProps<TFieldValues, TName>, 'control'>;
|
|
131
|
+
declare const _Controller: <TFieldValues extends SafeFieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: _ControllerProps<TFieldValues, TName>) => import("react").JSX.Element;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/client/config/RhfUtilsFormInjectorProps.d.ts
|
|
134
|
+
/**
|
|
135
|
+
* RhfUtilsClientConfig's FormComponent props.
|
|
136
|
+
*/
|
|
137
|
+
type RhfUtilsFormInjectorProps<TFieldValues extends SafeFieldValues = SafeFieldValues, TTransformedValues extends SafeFieldValues = TFieldValues> = Merge<{
|
|
138
|
+
/** Form instance children (`RhfUtilsZodForm.Children`) to output amid globally-injected code. */Outlet: React.FC;
|
|
139
|
+
}, RhfUtilsContext, {
|
|
140
|
+
rhf: UseFormReturn<TFieldValues, unknown, TTransformedValues>;
|
|
141
|
+
Controller: typeof _Controller<TFieldValues>;
|
|
142
|
+
FormSubmitError: typeof FormSubmitError<TFieldValues>;
|
|
143
|
+
}>;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/client/config/RhfUtilsClientConfigType.d.ts
|
|
146
|
+
/**
|
|
147
|
+
* Client configuration object.
|
|
148
|
+
*
|
|
149
|
+
* Options under `defaults` can be overridden at form level.
|
|
150
|
+
*/
|
|
151
|
+
type RhfUtilsClientConfig = {
|
|
152
|
+
/**
|
|
153
|
+
* Default options for all forms. (Are overridden by form-specific options.)
|
|
154
|
+
*/
|
|
155
|
+
defaults?: UseRhfUtilsFormGlobalDefaults;
|
|
156
|
+
/**
|
|
157
|
+
* Supply your own `<form>` component.
|
|
158
|
+
*
|
|
159
|
+
* (By default, a native {@link HTMLFormElement} is used.)
|
|
160
|
+
*/
|
|
161
|
+
FormComponent?: React.FC<React.PropsWithChildren<React.HTMLAttributes<HTMLFormElement>>>;
|
|
162
|
+
/**
|
|
163
|
+
* Inject your own hooks, components, etc., into every form instance.
|
|
164
|
+
*
|
|
165
|
+
* @description
|
|
166
|
+
*
|
|
167
|
+
* (NOTE: context params are not schema-typed as not possible at this level.)
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
*
|
|
171
|
+
* See README.
|
|
172
|
+
*/
|
|
173
|
+
FormInjector?: React.FC<RhfUtilsFormInjectorProps>;
|
|
174
|
+
/**
|
|
175
|
+
* A hook that returns a callback that determines whether form can be cancelled at event-time.
|
|
176
|
+
*
|
|
177
|
+
* @description
|
|
178
|
+
*
|
|
179
|
+
* Cancellation of forms often doesn't involve navigation, making it more challenging to centrally handle.
|
|
180
|
+
* Your hook's returned callback should internally prompt user and return response as `boolean`
|
|
181
|
+
* indicating whether cancellation should be blocked. See `README.md` for example.
|
|
182
|
+
*
|
|
183
|
+
* @returns Callback that, given {@link RhfUtilsFormContext} at event-time, returns `boolean` value indicating whether form can be cancelled.
|
|
184
|
+
*
|
|
185
|
+
* Callback should return:
|
|
186
|
+
* `true`: if form can be cancelled (e.g., form not dirty or user confirmed via prompt); {@link UseRhfUtilsFormProps.onCancel} is called.
|
|
187
|
+
* `false`: form cannot be cancelled (e.g., user denied); {@link UseRhfUtilsFormProps.onCancel} is not called.
|
|
188
|
+
*/
|
|
189
|
+
useCanFormBeCancelled?: () => (props: UseRhfUtilsFormOnSubmitContext) => MaybePromise<boolean>;
|
|
190
|
+
/**
|
|
191
|
+
* Global submit error handler when/if submit handler throws an error other than {@link FormSubmitError}.
|
|
192
|
+
*
|
|
193
|
+
* Example use case:
|
|
194
|
+
* - transform API errors to {@link FormSubmitFieldErrors}.
|
|
195
|
+
*
|
|
196
|
+
* @returns
|
|
197
|
+
* - if {@link FormSubmitFieldErrors}: merge into context errors.
|
|
198
|
+
* - if `undefined`: do nothing.
|
|
199
|
+
*/
|
|
200
|
+
onSubmitErrorUnknown?: (error: unknown) => FormSubmitFieldErrors | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Configuration regarding RHF form state errors (`useFormContext().formState.errors`).
|
|
203
|
+
*/
|
|
204
|
+
fieldErrors?: {
|
|
205
|
+
/**
|
|
206
|
+
* Configure how/if errors should be outputted for debugging/reporting (i.e., console and/or throwing).
|
|
207
|
+
*/
|
|
208
|
+
output?: FlatFieldErrorsOutputConfig;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
//#endregion
|
|
212
|
+
export { UseRhfUtilsFormOnSubmitContext as a, FormSubmitFieldErrors as c, MaybePromise as i, RhfUseFormInstanceProps as l, RhfUtilsFormInjectorProps as n, UseRhfUtilsFormOnSubmitErrorContext as o, _Controller as r, FormSubmitError as s, RhfUtilsClientConfig as t, useFlatFieldErrorsContext as u };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { RefObject } from "react";
|
|
2
|
+
import { DevtoolUIProps } from "@hookform/devtools/dist/devToolUI";
|
|
3
|
+
import { Register } from "@/Register";
|
|
4
|
+
|
|
5
|
+
//#region src/submit/useResetFormOnSubmitted.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for {@link useResetFormOnSubmitted}.
|
|
8
|
+
*/
|
|
9
|
+
type UseResetFormOnSubmittedOptions = undefined | {
|
|
10
|
+
/**
|
|
11
|
+
* Reset values on successful submit.
|
|
12
|
+
* - `defaults`: reset current values to defaults
|
|
13
|
+
* - `current`: reset defaults to current values
|
|
14
|
+
*/
|
|
15
|
+
success?: {
|
|
16
|
+
values: 'defaults' | 'current';
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Reset values to defaults on submit error.
|
|
20
|
+
*/
|
|
21
|
+
error?: {
|
|
22
|
+
values: 'defaults';
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/submit/useSubmitFormOnWatch.d.ts
|
|
27
|
+
type UseSubmitFormOnWatchOptions = {
|
|
28
|
+
/** Milliseconds to debounce form submission. (Default is none.) */debounce: number;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/form/options/RhfUtilsFormOptionsType.d.ts
|
|
32
|
+
/**
|
|
33
|
+
* Options for enabling utils functionality provided by this library.
|
|
34
|
+
*
|
|
35
|
+
* Can be extended via {@link Register}.
|
|
36
|
+
*/
|
|
37
|
+
type RhfUtilsFormOptions = {
|
|
38
|
+
/** Stop propagation of submit event. */stopSubmitPropagation?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Request submit when user changes form values.
|
|
41
|
+
*/
|
|
42
|
+
submitOnWatch?: UseSubmitFormOnWatchOptions; /** Reset form values and state (e.g., `isDirty`) after submit -- on success and/or error. */
|
|
43
|
+
resetOnSubmitted?: UseResetFormOnSubmittedOptions;
|
|
44
|
+
/**
|
|
45
|
+
* Control dev tool options.
|
|
46
|
+
* (Lazy-loaded when truthy value supplied.
|
|
47
|
+
* For zero bundle size in prod, be sure to check for dev environment.)
|
|
48
|
+
*/
|
|
49
|
+
devTool?: boolean | Pick<DevtoolUIProps, 'placement' | 'styles'>;
|
|
50
|
+
} & (Register extends {
|
|
51
|
+
RhfUtilsFormOptions: infer _RhfUtilsFormOptions;
|
|
52
|
+
} ? _RhfUtilsFormOptions : {});
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/form/rhf/SafeFieldValuesType.d.ts
|
|
55
|
+
/**
|
|
56
|
+
* Equivalent to RHF's `FieldValues` except for `unknown` (instead of `any`) value.
|
|
57
|
+
*/
|
|
58
|
+
type SafeFieldValues = Record<string, unknown>;
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/form/context/utils/LastSubmitStateType.d.ts
|
|
61
|
+
type LastSubmitState = null | 'submitting' | 'success' | 'error';
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/form/context/utils/RhfUtilsContextProvider.d.ts
|
|
64
|
+
type RhfUtilsContextProviderProps = {
|
|
65
|
+
formId: string;
|
|
66
|
+
formRef: React.RefObject<HTMLFormElement | null>; /** Consumer-supplied options and values. */
|
|
67
|
+
options: RhfUtilsFormOptions;
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/form/context/utils/RhfUtilsContextType.d.ts
|
|
71
|
+
type RhfUtilsContext = RhfUtilsContextProviderProps & {
|
|
72
|
+
/**
|
|
73
|
+
* Current form submit state.
|
|
74
|
+
*
|
|
75
|
+
* e.g., can be used to determine whether safe to redirect (navigate) without prompter.
|
|
76
|
+
* Unlike RHF's `isSubmitSuccessful`, is computed/set immediately after `onSubmit` succeeds/fails.
|
|
77
|
+
*/
|
|
78
|
+
lastSubmitStateRef: RefObject<LastSubmitState>;
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { RhfUtilsFormOptions as a, SafeFieldValues as i, RhfUtilsContextProviderProps as n, LastSubmitState as r, RhfUtilsContext as t };
|