@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
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
import { a as _RhfUtilsContextProvider, c as FormRelayContextProvider, i as isEmptyObject, o as useRhfUtilsContext, r as getFlatFieldErrors, t as FormRelaySetter, u as createContext } from "./FormRelaySetter-BKO0Wodf.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Controller, FormProvider, useForm, useFormContext, useFormState, useWatch } from "react-hook-form";
|
|
5
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
6
|
+
//#region src/client/config/context/RhfUtilsClientConfigContext.tsx
|
|
7
|
+
const RhfUtilsClientConfigContext_Internal = React.createContext(void 0);
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/client/config/context/RhfUtilsClientConfigProvider.tsx
|
|
10
|
+
const RhfUtilsClientConfigProvider = ({ config, children }) => {
|
|
11
|
+
const [memoConfig] = React.useState(config ?? {});
|
|
12
|
+
return /* @__PURE__ */ jsx(RhfUtilsClientConfigContext_Internal.Provider, {
|
|
13
|
+
value: memoConfig,
|
|
14
|
+
children: /* @__PURE__ */ jsx(FormRelayContextProvider, { children })
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/errors/flat/context/useFlatFieldErrorsContext.ts
|
|
19
|
+
const { Provider: _FormErrorsFlatContextProvider, useRequired: useFlatFieldErrorsContext } = createContext();
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/errors/flat/context/useFlatFieldErrorsContextHasOnlyOrphans.ts
|
|
22
|
+
/**
|
|
23
|
+
* Returns `true` if all errors are orphans.
|
|
24
|
+
*
|
|
25
|
+
* You may want to treat this case specifically.
|
|
26
|
+
*/
|
|
27
|
+
const useFlatFieldErrorsContextHasOnlyOrphans = () => {
|
|
28
|
+
const errors = useFlatFieldErrorsContext();
|
|
29
|
+
return React.useMemo(() => {
|
|
30
|
+
if (!errors.hasErrors) return false;
|
|
31
|
+
if (!errors.hasOrphans) return false;
|
|
32
|
+
return Object.keys(errors.orphans).length === Object.keys(errors.all).length;
|
|
33
|
+
}, [errors]);
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/errors/nonfield/RhfUtilsNonFieldErrorMarkerHtmlAttribute.ts
|
|
37
|
+
/**
|
|
38
|
+
* HTML data attribute for {@link RhfUtilsNonFieldErrorMarker}.
|
|
39
|
+
*/
|
|
40
|
+
const RhfUtilsNonFieldErrorMarkerHtmlAttribute = "data-rhfutils-nonfield-error-marker-path";
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/errors/nonfield/RhfUtilsNonFieldErrorMarker.tsx
|
|
43
|
+
/**
|
|
44
|
+
* Empty, hidden marker to indicate a non-field/non-root error is being displayed to user.
|
|
45
|
+
*
|
|
46
|
+
* Example use case:
|
|
47
|
+
* Field array with minimum items.
|
|
48
|
+
* (When there are no items, the error is not associated with a field and is displayed separately.)
|
|
49
|
+
*/
|
|
50
|
+
const RhfUtilsNonFieldErrorMarker = ({ path }) => {
|
|
51
|
+
return /* @__PURE__ */ jsx("div", {
|
|
52
|
+
role: "alert",
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
style: { display: "none" },
|
|
55
|
+
[RhfUtilsNonFieldErrorMarkerHtmlAttribute]: path
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/form/utils/useFormRequestSubmit.ts
|
|
60
|
+
/**
|
|
61
|
+
* Get callback to trigger submit manually on form.
|
|
62
|
+
*
|
|
63
|
+
* Note: `submitter` is optional, but is required to be a submit button.
|
|
64
|
+
*
|
|
65
|
+
* @link https://developer.mozilla.org/docs/Web/API/HTMLFormElement/requestSubmit
|
|
66
|
+
*/
|
|
67
|
+
const useFormRequestSubmit = (ref) => React.useCallback((submitter) => {
|
|
68
|
+
if (!ref.current) throw new Error();
|
|
69
|
+
requestSubmitByForm(ref.current, submitter);
|
|
70
|
+
}, [ref]);
|
|
71
|
+
const requestSubmitByForm = (form, submitter) => {
|
|
72
|
+
form.requestSubmit(submitter);
|
|
73
|
+
};
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/submit/error/FormSubmitError.ts
|
|
76
|
+
var FormSubmitError = class extends Error {
|
|
77
|
+
errors;
|
|
78
|
+
constructor(errors, message) {
|
|
79
|
+
super(message);
|
|
80
|
+
this.errors = errors;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/submit/last-error/useLastSubmitErrorContext.ts
|
|
85
|
+
const { Provider: _LastSubmitErrorContextProvider, useRequired: _useLastSubmitErrorContext } = createContext();
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/submit/last-error/useLastSubmitError.ts
|
|
88
|
+
const useLastSubmitError = () => _useLastSubmitErrorContext().current;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/devtool/LazyDevTool.tsx
|
|
91
|
+
const LazyRhfDevTool = React.lazy(() => import("@hookform/devtools").then((res) => ({ default: res.DevTool })));
|
|
92
|
+
/**
|
|
93
|
+
* Lazy-loaded RHF DevTool.
|
|
94
|
+
*/
|
|
95
|
+
const LazyDevTool = ({ config }) => {
|
|
96
|
+
const [memoConfig] = React.useState(config);
|
|
97
|
+
if (!memoConfig) return null;
|
|
98
|
+
const props = typeof memoConfig === "object" ? memoConfig : void 0;
|
|
99
|
+
return /* @__PURE__ */ jsx(React.Suspense, { children: /* @__PURE__ */ jsx(LazyRhfDevTool, { ...props }) });
|
|
100
|
+
};
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/devtool/LazyDevToolViaProviders.tsx
|
|
103
|
+
const LazyDevToolViaProviders = () => {
|
|
104
|
+
return /* @__PURE__ */ jsx(LazyDevTool, { config: useRhfUtilsContext().options.devTool });
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/form/_Controller.tsx
|
|
108
|
+
const _Controller = (props) => /* @__PURE__ */ jsx(Controller, { ...props });
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/client/config/context/useRhfUtilsClientConfig.ts
|
|
111
|
+
const useRhfUtilsClientConfig = () => {
|
|
112
|
+
const ctx = React.useContext(RhfUtilsClientConfigContext_Internal);
|
|
113
|
+
if (ctx === void 0) throw new Error();
|
|
114
|
+
return ctx;
|
|
115
|
+
};
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/submit/useRhfUtilsFormOnSubmitContext.ts
|
|
118
|
+
const useRhfUtilsFormOnSubmitContext = () => {
|
|
119
|
+
return {
|
|
120
|
+
utils: useRhfUtilsContext(),
|
|
121
|
+
rhf: useFormContext(),
|
|
122
|
+
FormSubmitError
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/form/utils/useHandleCancelWithCheckIfCanBe.ts
|
|
127
|
+
const useHandleCancelWithCheckIfCanBe = (onCancel, useCanFormBeCancelled, formOnSubmitContext) => {
|
|
128
|
+
const canFormBeCancelled = useCanFormBeCancelled?.();
|
|
129
|
+
return async () => {
|
|
130
|
+
if (!onCancel) return;
|
|
131
|
+
if (await Promise.resolve(canFormBeCancelled?.(formOnSubmitContext)) === false) return;
|
|
132
|
+
return Promise.resolve(onCancel());
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/form/utils/useHandleCancelWithCheckIfCanBeViaProviders.ts
|
|
137
|
+
const useHandleCancelWithCheckIfCanBeViaProviders = (onCancel) => {
|
|
138
|
+
const { useCanFormBeCancelled } = useRhfUtilsClientConfig();
|
|
139
|
+
return useHandleCancelWithCheckIfCanBe(onCancel, useCanFormBeCancelled, useRhfUtilsFormOnSubmitContext());
|
|
140
|
+
};
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/form/with-handlers-and-children/_ChildrenViaProviders.tsx
|
|
143
|
+
const RhfUtilsFormChildrenViaProviders_Internal = ({ onCancel, Children }) => {
|
|
144
|
+
const rhf = useFormContext();
|
|
145
|
+
const utils = useRhfUtilsContext();
|
|
146
|
+
const onCancelWithCheck = useHandleCancelWithCheckIfCanBeViaProviders(onCancel);
|
|
147
|
+
return /* @__PURE__ */ jsx(Children, {
|
|
148
|
+
...utils,
|
|
149
|
+
rhf,
|
|
150
|
+
onCancel: onCancelWithCheck,
|
|
151
|
+
Controller: _Controller,
|
|
152
|
+
FormSubmitError
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/submit/error/setCtxErrorsByFormSubmitFieldErrors.ts
|
|
157
|
+
/**
|
|
158
|
+
* Handle thrown {@link FormSubmitError}.
|
|
159
|
+
* Add key/values as name/message to RHF context errors.
|
|
160
|
+
*/
|
|
161
|
+
const setCtxErrorsByFormSubmitFieldErrors = (ctx, errors) => {
|
|
162
|
+
Object.entries(errors).forEach(([name, fieldError]) => {
|
|
163
|
+
ctx.setError(name, {
|
|
164
|
+
type: "FormSubmitFieldError",
|
|
165
|
+
...fieldError
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/form/defaults/form/getRhfUtilsFormResolvedFormProps.ts
|
|
171
|
+
const getRhfUtilsFormResolvedFormProps = (global, instance, surfaced) => ({
|
|
172
|
+
...global,
|
|
173
|
+
...instance,
|
|
174
|
+
className: [
|
|
175
|
+
global?.className,
|
|
176
|
+
instance?.className,
|
|
177
|
+
surfaced?.className
|
|
178
|
+
].filter(Boolean).join(" ").trim() || void 0
|
|
179
|
+
});
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/form/defaults/form/useRhfUtilsFormResolvedFormProps.ts
|
|
182
|
+
const useRhfUtilsFormResolvedFormProps = (formProps, id, surfaced) => {
|
|
183
|
+
return {
|
|
184
|
+
id,
|
|
185
|
+
...getRhfUtilsFormResolvedFormProps(useRhfUtilsClientConfig().defaults?.form, formProps, surfaced)
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/submit/last-error/useLastSubmitErrorContextWith.ts
|
|
190
|
+
const useLastSubmitErrorContextWith = (handleSubmit) => {
|
|
191
|
+
const ctx = _useLastSubmitErrorContext();
|
|
192
|
+
return async function(event) {
|
|
193
|
+
try {
|
|
194
|
+
ctx.reset();
|
|
195
|
+
return await handleSubmit(event);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
ctx.set(error, event);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/form/with-handlers-and-children/_useHandleSubmit.ts
|
|
204
|
+
const useRhfUtilsFormHandleSubmit_Internal = ({ onValid, onInvalid, onError, onFinally }) => {
|
|
205
|
+
const rhfContext = useFormContext();
|
|
206
|
+
const { options, lastSubmitStateRef } = useRhfUtilsContext();
|
|
207
|
+
const handleSubmitWithLastSubmitError = useLastSubmitErrorContextWith(rhfContext.handleSubmit(onValid, onInvalid));
|
|
208
|
+
return (event) => {
|
|
209
|
+
lastSubmitStateRef.current = "submitting";
|
|
210
|
+
if (options.stopSubmitPropagation) event.stopPropagation();
|
|
211
|
+
Promise.resolve(handleSubmitWithLastSubmitError(event)).then(() => {
|
|
212
|
+
lastSubmitStateRef.current = "success";
|
|
213
|
+
}).catch((error) => {
|
|
214
|
+
lastSubmitStateRef.current = "error";
|
|
215
|
+
onError(error, event);
|
|
216
|
+
}).finally(() => {
|
|
217
|
+
onFinally?.();
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
//#endregion
|
|
222
|
+
//#region src/form/with-handlers-and-children/_FormWithSubmitHandler.tsx
|
|
223
|
+
const RhfUtilsFormWithSubmitHandler_Internal = ({ getApiData, onSubmitInvalid, onBeforeSubmitInvariants, onBeforeSubmit, onSubmit, onSubmitSuccess, onSubmitError, onSubmitFinally, form, className, children }) => {
|
|
224
|
+
const rhfContext = useFormContext();
|
|
225
|
+
const utils = useRhfUtilsContext();
|
|
226
|
+
const config = useRhfUtilsClientConfig();
|
|
227
|
+
const resolvedFormProps = useRhfUtilsFormResolvedFormProps(form, utils.formId, { className });
|
|
228
|
+
const handleSubmitValid = async (data, event) => {
|
|
229
|
+
const datas = {
|
|
230
|
+
input: rhfContext.getValues(),
|
|
231
|
+
output: data,
|
|
232
|
+
api: getApiData?.(data)
|
|
233
|
+
};
|
|
234
|
+
const context = {
|
|
235
|
+
utils,
|
|
236
|
+
rhf: rhfContext,
|
|
237
|
+
FormSubmitError
|
|
238
|
+
};
|
|
239
|
+
const submitEvent = event;
|
|
240
|
+
if (onBeforeSubmitInvariants) await handleOnSubmitInvariants(onBeforeSubmitInvariants, datas, context, submitEvent);
|
|
241
|
+
await Promise.resolve(onBeforeSubmit?.(datas, context, submitEvent));
|
|
242
|
+
const submitResponse = await Promise.resolve(onSubmit?.(datas, context, submitEvent));
|
|
243
|
+
utils.lastSubmitStateRef.current = "success";
|
|
244
|
+
await Promise.resolve(onSubmitSuccess?.(submitResponse, datas, context, submitEvent));
|
|
245
|
+
};
|
|
246
|
+
function handleSubmitError(error, event) {
|
|
247
|
+
const formSubmitErrors = error instanceof FormSubmitError ? error.errors : config.onSubmitErrorUnknown?.(error);
|
|
248
|
+
if (formSubmitErrors) setCtxErrorsByFormSubmitFieldErrors(rhfContext, formSubmitErrors);
|
|
249
|
+
onSubmitError?.(error, {
|
|
250
|
+
utils,
|
|
251
|
+
errors: formSubmitErrors,
|
|
252
|
+
rhf: rhfContext
|
|
253
|
+
}, event);
|
|
254
|
+
}
|
|
255
|
+
const handleSubmit = useRhfUtilsFormHandleSubmit_Internal({
|
|
256
|
+
onValid: handleSubmitValid,
|
|
257
|
+
onInvalid: onSubmitInvalid,
|
|
258
|
+
onError: handleSubmitError,
|
|
259
|
+
onFinally: onSubmitFinally
|
|
260
|
+
});
|
|
261
|
+
const Outlet = React.useCallback(() => children, []);
|
|
262
|
+
/** FormComponent props -- general, non-form-, non-schema-specific. */
|
|
263
|
+
const formInjectorProps = {
|
|
264
|
+
...utils,
|
|
265
|
+
rhf: rhfContext,
|
|
266
|
+
Controller: _Controller,
|
|
267
|
+
FormSubmitError,
|
|
268
|
+
Outlet
|
|
269
|
+
};
|
|
270
|
+
return /* @__PURE__ */ jsx(config.FormComponent ?? "form", {
|
|
271
|
+
...resolvedFormProps,
|
|
272
|
+
id: utils.formId,
|
|
273
|
+
ref: utils.formRef,
|
|
274
|
+
onSubmit: handleSubmit,
|
|
275
|
+
children: config.FormInjector ? /* @__PURE__ */ jsx(config.FormInjector, { ...formInjectorProps }) : children
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
const handleOnSubmitInvariants = async (onBeforeSubmitInvariants, data, context, event) => {
|
|
279
|
+
const falseyFieldsAndMessages = (await Promise.resolve(onBeforeSubmitInvariants(data, context, event))).filter(({ validate }) => !validate).map(({ field, message }) => [field, { message }]);
|
|
280
|
+
if (!falseyFieldsAndMessages.length) return;
|
|
281
|
+
throw new context.FormSubmitError(Object.fromEntries(falseyFieldsAndMessages));
|
|
282
|
+
};
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/form/with-handlers-and-children/RhfUtilsForm.tsx
|
|
285
|
+
const RhfUtilsForm = ({ getApiData, onCancel, onSubmitInvalid, onBeforeSubmitInvariants, onBeforeSubmit, onSubmit, onSubmitSuccess, onSubmitError, onSubmitFinally, Children, form, className }) => /* @__PURE__ */ jsxs(RhfUtilsFormWithSubmitHandler_Internal, {
|
|
286
|
+
getApiData,
|
|
287
|
+
onSubmitInvalid,
|
|
288
|
+
onBeforeSubmitInvariants,
|
|
289
|
+
onBeforeSubmit,
|
|
290
|
+
onSubmit,
|
|
291
|
+
onSubmitSuccess,
|
|
292
|
+
onSubmitError,
|
|
293
|
+
onSubmitFinally,
|
|
294
|
+
form,
|
|
295
|
+
className,
|
|
296
|
+
children: [/* @__PURE__ */ jsx(LazyDevToolViaProviders, {}), /* @__PURE__ */ jsx(RhfUtilsFormChildrenViaProviders_Internal, {
|
|
297
|
+
onCancel,
|
|
298
|
+
Children
|
|
299
|
+
})]
|
|
300
|
+
});
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/resolvers/zod/form/RhfUtilsZodForm.tsx
|
|
303
|
+
const RhfUtilsZodForm = (props) => /* @__PURE__ */ jsx(RhfUtilsForm, { ...props });
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/errors/flat/filterFlatFieldErrors.ts
|
|
306
|
+
/**
|
|
307
|
+
* Filter {@link FlatFieldErrors} by a predicate.
|
|
308
|
+
*
|
|
309
|
+
* (Encapsulates to and from Object entries.)
|
|
310
|
+
*/
|
|
311
|
+
const makeFlatFieldErrorsFilter = (predicate) => (errors) => Object.fromEntries(Object.entries(errors).filter(predicate));
|
|
312
|
+
//#endregion
|
|
313
|
+
//#region src/errors/isFieldErrorRefd.ts
|
|
314
|
+
/**
|
|
315
|
+
* Determine if {@link FieldError} is a `ref`'d field error.
|
|
316
|
+
*/
|
|
317
|
+
const isFieldErrorRefd = (error) => !!error.ref;
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/errors/isFlatFieldErrorEntryRefd.ts
|
|
320
|
+
/**
|
|
321
|
+
* Determine if {@link FieldError} is a `ref`'d field error.
|
|
322
|
+
*/
|
|
323
|
+
const isFlatFieldErrorEntryRefd = ([, error]) => isFieldErrorRefd(error);
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/errors/getRefdFromFlatFieldErrors.ts
|
|
326
|
+
const getRefdFromFlatFieldErrors = makeFlatFieldErrorsFilter(isFlatFieldErrorEntryRefd);
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/errors/nonfield/RhfUtilsNonFieldErrorMarker.utils.ts
|
|
329
|
+
/**
|
|
330
|
+
* Returns query selector for matching non-field error marker.
|
|
331
|
+
* By default includes nested field matching. (See `options.excludeNested`.)
|
|
332
|
+
*
|
|
333
|
+
* @returns One or more selectors in a comma-separated list.
|
|
334
|
+
*/
|
|
335
|
+
const getRhfUtilsNonFieldErrorMarkerQuerySelector = (path, options) => {
|
|
336
|
+
return [["", ""], ...options?.excludeNested ? [] : [["^", "."]]].map(([attrSuffix, pathSuffix]) => _getQuerySelector(RhfUtilsNonFieldErrorMarkerHtmlAttribute + attrSuffix, path + pathSuffix)).join(", ");
|
|
337
|
+
};
|
|
338
|
+
const _getQuerySelector = (attr, value) => `[role="alert"][${attr}="${value}"]`;
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/errors/nonfield/isNonFieldErrorMarkerInDOM.ts
|
|
341
|
+
/**
|
|
342
|
+
* Determine if a non-field error marker is in the DOM.
|
|
343
|
+
* Note: this will also look for nested markers to accommodate field arrays
|
|
344
|
+
*/
|
|
345
|
+
const isNonFieldErrorMarkerInDOM = (path, parentElement) => !!parentElement.querySelector(getRhfUtilsNonFieldErrorMarkerQuerySelector(path));
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/errors/root/isFormErrorPathRoot.ts
|
|
348
|
+
/**
|
|
349
|
+
* Determine if an error path is root. (e.g., `root` or `root.nested`)
|
|
350
|
+
*
|
|
351
|
+
* @param path Flat path. (e.g., 'root.nested')
|
|
352
|
+
*/
|
|
353
|
+
const isFormErrorPathRoot = (path) => path === "root" || path.startsWith("root.");
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/errors/orphan/isOrphanFormError.ts
|
|
356
|
+
const isOrphanFormError = (path, error, parentElement) => !isFieldErrorRefd(error) && !isFormErrorPathRoot(path) && !isNonFieldErrorMarkerInDOM(path, parentElement);
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/errors/orphan/getIsOrphanFormErrorWithParentElement.ts
|
|
359
|
+
/**
|
|
360
|
+
* Util wrapper for {@link isOrphanFormError} for usage with {@link FlatFieldErrorEntry}.
|
|
361
|
+
*/
|
|
362
|
+
const getIsFlatFieldErrorEntryOrphanByParentElement = (parentElement) => ([path, error]) => isOrphanFormError(path, error, parentElement);
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/errors/orphan/getOrphansFromFlatFieldErrors.ts
|
|
365
|
+
const getOrphansFromFlatFieldErrors = (errors, parentElement) => makeFlatFieldErrorsFilter(getIsFlatFieldErrorEntryOrphanByParentElement(parentElement))(errors);
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region src/errors/root/isFlatFieldErrorEntryPathRoot.ts
|
|
368
|
+
/**
|
|
369
|
+
* Util wrapper for {@link isFormErrorPathRoot} for usage with {@link FlatFieldErrorEntry}.
|
|
370
|
+
*/
|
|
371
|
+
const isFlatFieldErrorEntryPathRoot = ([path]) => isFormErrorPathRoot(path);
|
|
372
|
+
//#endregion
|
|
373
|
+
//#region src/errors/root/getRootsFromFlatFieldErrors.ts
|
|
374
|
+
const getRootsFromFlatFieldErrors = makeFlatFieldErrorsFilter(isFlatFieldErrorEntryPathRoot);
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/errors/flat/context/FlatFieldErrorsContextProvider.tsx
|
|
377
|
+
/**
|
|
378
|
+
* Provides a flattened version of the form errors.
|
|
379
|
+
* Allows flattening and filtering to happen once per errors change.
|
|
380
|
+
*/
|
|
381
|
+
const FlatFieldErrorsContextProvider = ({ formRef, children }) => {
|
|
382
|
+
const { errors } = useFormState();
|
|
383
|
+
const all = getFlatFieldErrors(errors);
|
|
384
|
+
const orphans = formRef.current ? getOrphansFromFlatFieldErrors(all, formRef.current) : {};
|
|
385
|
+
return /* @__PURE__ */ jsx(_FormErrorsFlatContextProvider, {
|
|
386
|
+
value: {
|
|
387
|
+
all,
|
|
388
|
+
fields: getRefdFromFlatFieldErrors(all),
|
|
389
|
+
roots: getRootsFromFlatFieldErrors(all),
|
|
390
|
+
orphans,
|
|
391
|
+
hasErrors: !isEmptyObject(errors),
|
|
392
|
+
hasOrphans: !isEmptyObject(orphans)
|
|
393
|
+
},
|
|
394
|
+
children
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region src/submit/last-error/LastSubmitErrorContextProvider.tsx
|
|
399
|
+
const LastSubmitErrorContextProvider = ({ children }) => {
|
|
400
|
+
const [lastSubmit, setLastSubmit] = React.useState(void 0);
|
|
401
|
+
return /* @__PURE__ */ jsx(_LastSubmitErrorContextProvider, {
|
|
402
|
+
value: {
|
|
403
|
+
current: lastSubmit,
|
|
404
|
+
reset: () => {
|
|
405
|
+
setLastSubmit(void 0);
|
|
406
|
+
},
|
|
407
|
+
set: (error, event) => {
|
|
408
|
+
setLastSubmit({
|
|
409
|
+
error,
|
|
410
|
+
event
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
children
|
|
415
|
+
});
|
|
416
|
+
};
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region src/errors/output/consoleErrors.ts
|
|
419
|
+
/**
|
|
420
|
+
* Output form values and errors to console.
|
|
421
|
+
*/
|
|
422
|
+
const consoleErrors = (message, values, errors, type = "debug") => {
|
|
423
|
+
console[type](message, {
|
|
424
|
+
values,
|
|
425
|
+
errors
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/errors/flat/context/useFlatFieldErrorsContextOutput.ts
|
|
430
|
+
/**
|
|
431
|
+
* Outputs (e.g., console, throw) errors based on config.
|
|
432
|
+
*/
|
|
433
|
+
const useFlatFieldErrorsContextOutput = (config) => {
|
|
434
|
+
const form = useFormContext();
|
|
435
|
+
const errors = useFlatFieldErrorsContext();
|
|
436
|
+
React.useEffect(() => {
|
|
437
|
+
if (!errors.hasErrors) return;
|
|
438
|
+
const console = config?.console?.(errors);
|
|
439
|
+
if (console) consoleErrors(console.message ?? defaultMessage, form.getValues(), errors, console.type);
|
|
440
|
+
const _throw = config?.throw?.(errors);
|
|
441
|
+
if (_throw) throw new Error(typeof _throw === "string" ? _throw : defaultMessage);
|
|
442
|
+
}, [errors]);
|
|
443
|
+
};
|
|
444
|
+
const defaultMessage = "Form errors";
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/utils/useRefIfValueWasTrue.ts
|
|
447
|
+
const useRefIfValueWasTrue = (value) => {
|
|
448
|
+
const hasBooleanChanged = React.useRef(false);
|
|
449
|
+
React.useEffect(() => {
|
|
450
|
+
if (!value) return;
|
|
451
|
+
hasBooleanChanged.current = true;
|
|
452
|
+
}, [value]);
|
|
453
|
+
const reset = () => {
|
|
454
|
+
hasBooleanChanged.current = false;
|
|
455
|
+
};
|
|
456
|
+
return [hasBooleanChanged, reset];
|
|
457
|
+
};
|
|
458
|
+
//#endregion
|
|
459
|
+
//#region src/submit/useFormOnSubmitted.ts
|
|
460
|
+
const useFormOnSubmitted = (callback, options) => {
|
|
461
|
+
const { isSubmitSuccessful, isSubmitting } = useFormState();
|
|
462
|
+
const [wasSubmitting, resetWasSubmitting] = useRefIfValueWasTrue(isSubmitting);
|
|
463
|
+
React.useEffect(() => {
|
|
464
|
+
if (!callback) return;
|
|
465
|
+
if (isSubmitting) return;
|
|
466
|
+
if (!wasSubmitting.current) return;
|
|
467
|
+
resetWasSubmitting();
|
|
468
|
+
if (options?.successful === void 0 || isSubmitSuccessful === options.successful) callback(isSubmitSuccessful);
|
|
469
|
+
}, [isSubmitting]);
|
|
470
|
+
};
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/submit/useResetFormOnSubmitted.ts
|
|
473
|
+
/**
|
|
474
|
+
* Control resetting of values and (some) state (e.g., `isDirty`) after form submitted.
|
|
475
|
+
*
|
|
476
|
+
* `isDirty` and other state is reset, but submit-related state is preserved, as well as errors.
|
|
477
|
+
*
|
|
478
|
+
* Use cases:
|
|
479
|
+
* - on success:
|
|
480
|
+
* - `defaults`: reset current values to defaults (e.g., clear form)
|
|
481
|
+
* - `current`: reset defaults to current values (e.g., keep values)
|
|
482
|
+
* - on error:
|
|
483
|
+
* - reset current values to default values (e.g., submitOnChange reset)
|
|
484
|
+
*
|
|
485
|
+
* See `Rules` section: https://react-hook-form.com/api/useform/reset/
|
|
486
|
+
* Specifically: "- It's recommended to reset inside useEffect after submission."
|
|
487
|
+
*/
|
|
488
|
+
const useResetFormOnSubmitted = (options) => {
|
|
489
|
+
const { getValues, reset } = useFormContext();
|
|
490
|
+
useFormOnSubmitted((success) => {
|
|
491
|
+
if (!options) return;
|
|
492
|
+
const whichValues = options[success ? "success" : "error"]?.values;
|
|
493
|
+
if (!whichValues) return;
|
|
494
|
+
const keepValues = whichValues === "current";
|
|
495
|
+
reset(keepValues ? getValues() : void 0, {
|
|
496
|
+
keepIsSubmitSuccessful: true,
|
|
497
|
+
keepIsSubmitted: true,
|
|
498
|
+
keepSubmitCount: true,
|
|
499
|
+
/**
|
|
500
|
+
* This is necessary when setting default values to current values (lest form stop updating).
|
|
501
|
+
*
|
|
502
|
+
* Technically, we are keeping values and resetting default values to same values.
|
|
503
|
+
*
|
|
504
|
+
* Steps to repro:
|
|
505
|
+
* - RhfUtilsClientConfig with resetOnSubmitted set to success values to current
|
|
506
|
+
* - remove `keepValues` prop from reset
|
|
507
|
+
* - create valid form, submit
|
|
508
|
+
* - form values should be unchanged
|
|
509
|
+
* - unexpectedly: can no longer type into input
|
|
510
|
+
*/
|
|
511
|
+
keepValues,
|
|
512
|
+
keepErrors: true
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
//#endregion
|
|
517
|
+
//#region src/utils/useIsFirstRender.ts
|
|
518
|
+
/**
|
|
519
|
+
* Use to determine if first render has run.
|
|
520
|
+
*
|
|
521
|
+
* (Supports strict mode.)
|
|
522
|
+
*/
|
|
523
|
+
const useIsFirstRender = () => {
|
|
524
|
+
const isFirstRender = React.useRef(DEFAULT_STATE);
|
|
525
|
+
React.useEffect(() => {
|
|
526
|
+
if (isFirstRender.current) isFirstRender.current = !DEFAULT_STATE;
|
|
527
|
+
return () => {
|
|
528
|
+
isFirstRender.current = DEFAULT_STATE;
|
|
529
|
+
};
|
|
530
|
+
}, []);
|
|
531
|
+
return isFirstRender;
|
|
532
|
+
};
|
|
533
|
+
const DEFAULT_STATE = true;
|
|
534
|
+
//#endregion
|
|
535
|
+
//#region src/utils/useDebouncedOnChangeValue.ts
|
|
536
|
+
/**
|
|
537
|
+
* React hook to debounce onChange event callback.
|
|
538
|
+
*
|
|
539
|
+
* Returns debounced state setter (uses ref internally).
|
|
540
|
+
*
|
|
541
|
+
* When debounce delay has elapsed after setting value,
|
|
542
|
+
* onChange callback is called with latest value.
|
|
543
|
+
*
|
|
544
|
+
* @returns `[setValueDebounced]`
|
|
545
|
+
*/
|
|
546
|
+
const useDebouncedOnChangeValue = ({ onChange, delay }) => {
|
|
547
|
+
/**
|
|
548
|
+
* State. (Via ref as it should not re-render.)
|
|
549
|
+
*/
|
|
550
|
+
const state = React.useRef(null);
|
|
551
|
+
/** Callback for `setTimeout`. */
|
|
552
|
+
const _onTimeout = () => {
|
|
553
|
+
if (!state.current) return;
|
|
554
|
+
onChange(state.current.value);
|
|
555
|
+
state.current = null;
|
|
556
|
+
};
|
|
557
|
+
const _clearTimeout = () => {
|
|
558
|
+
if (state.current) clearTimeout(state.current.timer);
|
|
559
|
+
};
|
|
560
|
+
React.useEffect(() => _clearTimeout, []);
|
|
561
|
+
const setValueDebounced = (value) => {
|
|
562
|
+
_clearTimeout();
|
|
563
|
+
state.current = {
|
|
564
|
+
value,
|
|
565
|
+
timer: setTimeout(_onTimeout, delay)
|
|
566
|
+
};
|
|
567
|
+
};
|
|
568
|
+
return [setValueDebounced];
|
|
569
|
+
};
|
|
570
|
+
//#endregion
|
|
571
|
+
//#region src/submit/useSubmitFormOnEvent.ts
|
|
572
|
+
/**
|
|
573
|
+
* Internal, shared hook to setup debounced callback for OnChange hooks.
|
|
574
|
+
*/
|
|
575
|
+
const useSubmitFormOnEventDebounced = (formRef, options) => {
|
|
576
|
+
const requestSubmit = useFormRequestSubmit(formRef);
|
|
577
|
+
const [setOnChangeDebounced] = useDebouncedOnChangeValue({
|
|
578
|
+
delay: options?.debounce ?? 0,
|
|
579
|
+
onChange: () => {
|
|
580
|
+
requestSubmit();
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
return setOnChangeDebounced;
|
|
584
|
+
};
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/submit/useSubmitFormOnWatch.ts
|
|
587
|
+
/**
|
|
588
|
+
* Watches for changes in form values.
|
|
589
|
+
*
|
|
590
|
+
* Caveats:
|
|
591
|
+
* - uses RHF's useWatch
|
|
592
|
+
* - triggers change immediately as user types, so use sensible debounce time
|
|
593
|
+
* - does not cover uncontrolled inputs
|
|
594
|
+
*/
|
|
595
|
+
const useSubmitFormOnWatch = (formRef, options) => {
|
|
596
|
+
const setOnChangeDebounced = useSubmitFormOnEventDebounced(formRef, { debounce: options?.debounce });
|
|
597
|
+
const watch = useWatch();
|
|
598
|
+
const { isValid, isDirty, isValidating, isSubmitting } = useFormState();
|
|
599
|
+
/**
|
|
600
|
+
* In some cases, {@link watch} reference object can change,
|
|
601
|
+
* even when no input has been made by user.
|
|
602
|
+
*/
|
|
603
|
+
const watchJson = React.useMemo(() => JSON.stringify(watch), [watch]);
|
|
604
|
+
const isFirstRender = useIsFirstRender();
|
|
605
|
+
React.useEffect(() => {
|
|
606
|
+
if (isFirstRender.current) return;
|
|
607
|
+
if (isValidating) return;
|
|
608
|
+
if (isSubmitting) return;
|
|
609
|
+
if (!isValid) return;
|
|
610
|
+
if (!isDirty) return;
|
|
611
|
+
setOnChangeDebounced(watch);
|
|
612
|
+
}, [
|
|
613
|
+
isValid,
|
|
614
|
+
isDirty,
|
|
615
|
+
watchJson,
|
|
616
|
+
isValidating
|
|
617
|
+
]);
|
|
618
|
+
};
|
|
619
|
+
//#endregion
|
|
620
|
+
//#region src/form/context/utils/RhfUtilsContextProvider.tsx
|
|
621
|
+
const RhfUtilsContextProvider = ({ formId, formRef, options, children }) => {
|
|
622
|
+
const [memoOptions] = React.useState(options);
|
|
623
|
+
useFlatFieldErrorsContextOutput(useRhfUtilsClientConfig().fieldErrors?.output);
|
|
624
|
+
(memoOptions.submitOnWatch ? useSubmitFormOnWatch : void 0)?.(formRef, memoOptions.submitOnWatch);
|
|
625
|
+
useResetFormOnSubmitted(memoOptions.resetOnSubmitted);
|
|
626
|
+
return /* @__PURE__ */ jsx(_RhfUtilsContextProvider, {
|
|
627
|
+
value: {
|
|
628
|
+
formId,
|
|
629
|
+
formRef,
|
|
630
|
+
options,
|
|
631
|
+
lastSubmitStateRef: React.useRef(null)
|
|
632
|
+
},
|
|
633
|
+
children
|
|
634
|
+
});
|
|
635
|
+
};
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/form/options/getRhfUtilsFormResolvedOptions.ts
|
|
638
|
+
const getRhfUtilsFormResolvedOptions = (global, instance) => ({
|
|
639
|
+
...global,
|
|
640
|
+
...instance,
|
|
641
|
+
...(global?.resetOnSubmitted || instance?.resetOnSubmitted) && { resetOnSubmitted: {
|
|
642
|
+
...global?.resetOnSubmitted,
|
|
643
|
+
...instance?.resetOnSubmitted
|
|
644
|
+
} }
|
|
645
|
+
});
|
|
646
|
+
//#endregion
|
|
647
|
+
//#region src/form/options/useRhfUtilsFormResolvedOptions.ts
|
|
648
|
+
const useRhfUtilsFormResolvedOptions = (config, options) => React.useMemo(() => getRhfUtilsFormResolvedOptions(config.defaults?.options, options), [JSON.stringify(options)]);
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/form/rhf/getRhfUtilsFormResolvedRhfProps.ts
|
|
651
|
+
const getRhfUtilsFormResolvedRhfProps = (global, instance) => ({
|
|
652
|
+
...global,
|
|
653
|
+
...instance
|
|
654
|
+
});
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/form/rhf/useRhfFormWithResolvedProps.ts
|
|
657
|
+
const useRhfFormWithResolvedProps = (props, config, defaultValues, resolver) => useForm({
|
|
658
|
+
...getRhfUtilsFormResolvedRhfProps(config.defaults?.rhf, props),
|
|
659
|
+
resolver,
|
|
660
|
+
defaultValues
|
|
661
|
+
});
|
|
662
|
+
//#endregion
|
|
663
|
+
//#region src/form/providers/RhfUtilsFormProviders.tsx
|
|
664
|
+
function RhfUtilsFormProviders({ formId, rhf, resolver, defaultValues, options, relay, children }) {
|
|
665
|
+
const config = useRhfUtilsClientConfig();
|
|
666
|
+
const reactId = React.useId();
|
|
667
|
+
const id = formId || reactId;
|
|
668
|
+
const formRef = React.useRef(null);
|
|
669
|
+
const resolvedRhf = useRhfFormWithResolvedProps(rhf, config, defaultValues, resolver);
|
|
670
|
+
const resolvedOptions = useRhfUtilsFormResolvedOptions(config, options);
|
|
671
|
+
return /* @__PURE__ */ jsx(FormProvider, {
|
|
672
|
+
...resolvedRhf,
|
|
673
|
+
children: /* @__PURE__ */ jsx(FlatFieldErrorsContextProvider, {
|
|
674
|
+
formRef,
|
|
675
|
+
children: /* @__PURE__ */ jsxs(RhfUtilsContextProvider, {
|
|
676
|
+
formId: id,
|
|
677
|
+
formRef,
|
|
678
|
+
options: resolvedOptions,
|
|
679
|
+
children: [/* @__PURE__ */ jsx(FormRelaySetter, { options: relay }), /* @__PURE__ */ jsx(LastSubmitErrorContextProvider, { children })]
|
|
680
|
+
})
|
|
681
|
+
})
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
//#endregion
|
|
685
|
+
//#region src/resolvers/zod/getZodResolver.ts
|
|
686
|
+
const getZodResolver = (schema) => zodResolver(schema);
|
|
687
|
+
//#endregion
|
|
688
|
+
//#region src/resolvers/zod/providers/RhfUtilsZodFormProviders.tsx
|
|
689
|
+
const RhfUtilsZodFormProviders = ({ schema, children, ...props }) => /* @__PURE__ */ jsx(RhfUtilsFormProviders, {
|
|
690
|
+
...props,
|
|
691
|
+
resolver: getZodResolver(schema),
|
|
692
|
+
children
|
|
693
|
+
});
|
|
694
|
+
//#endregion
|
|
695
|
+
//#region src/form/with-providers/RhfUtilsFormWithProviders.tsx
|
|
696
|
+
/**
|
|
697
|
+
* Form providers (with utils) with immediate descendent {@link RhfUtilsForm}.
|
|
698
|
+
* (Syntactic sugar for {@link useRhfUtilsForm}. Use this for most applications.)
|
|
699
|
+
*/
|
|
700
|
+
function RhfUtilsFormWithProviders({ getApiData, resolver, rhf, defaultValues, options, relay, onCancel, onSubmitInvalid, onBeforeSubmitInvariants, onBeforeSubmit, onSubmit, onSubmitSuccess, onSubmitError, onSubmitFinally, Children, form, formId, className }) {
|
|
701
|
+
const providerProps = {
|
|
702
|
+
formId,
|
|
703
|
+
resolver,
|
|
704
|
+
rhf,
|
|
705
|
+
defaultValues,
|
|
706
|
+
options,
|
|
707
|
+
relay
|
|
708
|
+
};
|
|
709
|
+
const formProps = {
|
|
710
|
+
getApiData,
|
|
711
|
+
onCancel,
|
|
712
|
+
onSubmitInvalid,
|
|
713
|
+
onBeforeSubmitInvariants,
|
|
714
|
+
onBeforeSubmit,
|
|
715
|
+
onSubmit,
|
|
716
|
+
onSubmitSuccess,
|
|
717
|
+
onSubmitError,
|
|
718
|
+
onSubmitFinally,
|
|
719
|
+
Children,
|
|
720
|
+
form,
|
|
721
|
+
className
|
|
722
|
+
};
|
|
723
|
+
return /* @__PURE__ */ jsx(RhfUtilsFormProviders, {
|
|
724
|
+
...providerProps,
|
|
725
|
+
children: /* @__PURE__ */ jsx(RhfUtilsForm, { ...formProps })
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
//#endregion
|
|
729
|
+
//#region src/resolvers/zod/with-providers/RhfUtilsZodFormWithProviders.tsx
|
|
730
|
+
const RhfUtilsZodFormWithProviders = ({ schema, ...props }) => /* @__PURE__ */ jsx(RhfUtilsFormWithProviders, {
|
|
731
|
+
...props,
|
|
732
|
+
resolver: getZodResolver(schema)
|
|
733
|
+
});
|
|
734
|
+
//#endregion
|
|
735
|
+
//#region src/_exports/index.ts
|
|
736
|
+
/**
|
|
737
|
+
* @license @paragrav/rhf-utils
|
|
738
|
+
*
|
|
739
|
+
* Copyright (c) 2024-present paragrav.dev
|
|
740
|
+
*
|
|
741
|
+
* This source code is licensed under the MIT license found in the
|
|
742
|
+
* LICENSE file in the root directory of this source tree.
|
|
743
|
+
*/
|
|
744
|
+
//#endregion
|
|
745
|
+
export { FormSubmitError, RhfUtilsClientConfigProvider, RhfUtilsNonFieldErrorMarker, RhfUtilsZodForm, RhfUtilsZodFormProviders, RhfUtilsZodFormWithProviders, useFlatFieldErrorsContext, useFlatFieldErrorsContextHasOnlyOrphans, useFormRequestSubmit, useLastSubmitError, useRhfUtilsContext };
|