@octanejs/hook-form 0.1.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.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/package.json +46 -0
  4. package/src/FormProvider.tsrx +76 -0
  5. package/src/FormProvider.tsrx.d.ts +10 -0
  6. package/src/constants.ts +31 -0
  7. package/src/controller.tsrx +8 -0
  8. package/src/controller.tsrx.d.ts +52 -0
  9. package/src/form.tsrx +119 -0
  10. package/src/form.tsrx.d.ts +6 -0
  11. package/src/formStateSubscribe.tsrx +10 -0
  12. package/src/formStateSubscribe.tsrx.d.ts +16 -0
  13. package/src/index.ts +19 -0
  14. package/src/logic/appendErrors.ts +19 -0
  15. package/src/logic/createFormControl.ts +1841 -0
  16. package/src/logic/generateId.ts +14 -0
  17. package/src/logic/generateWatchOutput.ts +27 -0
  18. package/src/logic/getCheckboxValue.ts +36 -0
  19. package/src/logic/getDirtyFields.ts +120 -0
  20. package/src/logic/getEventValue.ts +12 -0
  21. package/src/logic/getFieldValue.ts +33 -0
  22. package/src/logic/getFieldValueAs.ts +22 -0
  23. package/src/logic/getFocusFieldName.ts +13 -0
  24. package/src/logic/getNodeParentName.ts +4 -0
  25. package/src/logic/getProxyFormState.ts +33 -0
  26. package/src/logic/getRadioValue.ts +24 -0
  27. package/src/logic/getResolverOptions.ts +33 -0
  28. package/src/logic/getRuleValue.ts +16 -0
  29. package/src/logic/getValidateError.ts +22 -0
  30. package/src/logic/getValidationModes.ts +11 -0
  31. package/src/logic/getValueAndMessage.ts +12 -0
  32. package/src/logic/hasPromiseValidation.ts +27 -0
  33. package/src/logic/hasValidation.ts +12 -0
  34. package/src/logic/index.ts +3 -0
  35. package/src/logic/isNameInFieldArray.ts +7 -0
  36. package/src/logic/isWatched.ts +11 -0
  37. package/src/logic/iterateFieldsByAction.ts +37 -0
  38. package/src/logic/schemaErrorLookup.ts +54 -0
  39. package/src/logic/shouldRenderFormState.ts +25 -0
  40. package/src/logic/shouldSubscribeByName.ts +18 -0
  41. package/src/logic/skipValidation.ts +21 -0
  42. package/src/logic/unsetEmptyArray.ts +6 -0
  43. package/src/logic/updateFieldArrayRootError.ts +17 -0
  44. package/src/logic/validateField.ts +273 -0
  45. package/src/types/controller.ts +98 -0
  46. package/src/types/errors.ts +56 -0
  47. package/src/types/events.ts +26 -0
  48. package/src/types/fieldArray.ts +288 -0
  49. package/src/types/fields.ts +46 -0
  50. package/src/types/form.ts +961 -0
  51. package/src/types/index.ts +12 -0
  52. package/src/types/path/common.ts +391 -0
  53. package/src/types/path/eager.ts +224 -0
  54. package/src/types/path/index.ts +16 -0
  55. package/src/types/resolvers.ts +38 -0
  56. package/src/types/utils.ts +125 -0
  57. package/src/types/validator.ts +94 -0
  58. package/src/types/watch.ts +66 -0
  59. package/src/useController.ts +268 -0
  60. package/src/useFieldArray.ts +490 -0
  61. package/src/useForm.ts +182 -0
  62. package/src/useFormContext.ts +47 -0
  63. package/src/useFormControlContext.ts +25 -0
  64. package/src/useFormState.ts +86 -0
  65. package/src/useIsomorphicLayoutEffect.ts +6 -0
  66. package/src/useWatch.ts +356 -0
  67. package/src/utils/append.ts +4 -0
  68. package/src/utils/cloneObject.ts +32 -0
  69. package/src/utils/compact.ts +2 -0
  70. package/src/utils/convertToArrayPayload.ts +2 -0
  71. package/src/utils/createSubject.ts +48 -0
  72. package/src/utils/deepEqual.ts +81 -0
  73. package/src/utils/deepMerge.ts +27 -0
  74. package/src/utils/extractFormValues.ts +28 -0
  75. package/src/utils/fillEmptyArray.ts +3 -0
  76. package/src/utils/flatten.ts +23 -0
  77. package/src/utils/get.ts +29 -0
  78. package/src/utils/index.ts +3 -0
  79. package/src/utils/insert.ts +8 -0
  80. package/src/utils/isBoolean.ts +2 -0
  81. package/src/utils/isCheckBoxInput.ts +4 -0
  82. package/src/utils/isDateObject.ts +2 -0
  83. package/src/utils/isEmptyObject.ts +7 -0
  84. package/src/utils/isFileInput.ts +4 -0
  85. package/src/utils/isFunction.ts +2 -0
  86. package/src/utils/isHTMLElement.ts +13 -0
  87. package/src/utils/isKey.ts +4 -0
  88. package/src/utils/isMultipleSelect.ts +5 -0
  89. package/src/utils/isNullOrUndefined.ts +2 -0
  90. package/src/utils/isObject.ts +8 -0
  91. package/src/utils/isPlainObject.ts +8 -0
  92. package/src/utils/isPrimitive.ts +8 -0
  93. package/src/utils/isRadioInput.ts +4 -0
  94. package/src/utils/isRadioOrCheckbox.ts +8 -0
  95. package/src/utils/isRegex.ts +2 -0
  96. package/src/utils/isString.ts +2 -0
  97. package/src/utils/isUndefined.ts +2 -0
  98. package/src/utils/isWeb.ts +4 -0
  99. package/src/utils/live.ts +6 -0
  100. package/src/utils/move.ts +15 -0
  101. package/src/utils/noop.ts +2 -0
  102. package/src/utils/objectHasFunction.ts +11 -0
  103. package/src/utils/prepend.ts +7 -0
  104. package/src/utils/remove.ts +24 -0
  105. package/src/utils/set.ts +36 -0
  106. package/src/utils/sleep.ts +2 -0
  107. package/src/utils/stringToPath.ts +4 -0
  108. package/src/utils/swap.ts +4 -0
  109. package/src/utils/unset.ts +65 -0
  110. package/src/utils/update.ts +5 -0
  111. package/src/watch.tsrx +7 -0
  112. package/src/watch.tsrx.d.ts +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dominic Gannaway
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @octanejs/hook-form
2
+
3
+ React Hook Form for the [octane](https://github.com/octanejs/octane) renderer —
4
+ the complete react-hook-form 7.81.0 source ported onto octane's hooks:
5
+ performant, flexible forms with native-event validation, field arrays, schema
6
+ resolvers, `Controller`/`FormProvider`, and SSR.
7
+
8
+ ```tsx
9
+ import { useForm } from '@octanejs/hook-form';
10
+
11
+ export function App() @{
12
+ const {
13
+ register,
14
+ handleSubmit,
15
+ formState: { errors },
16
+ } = useForm({ mode: 'onChange' });
17
+
18
+ <form onSubmit={handleSubmit((data) => console.log(data))}>
19
+ <input {...register('email', { required: 'required' })} />
20
+ @if (errors.email) {
21
+ <span role="alert">{errors.email.message as string}</span>
22
+ }
23
+ <button>{'Submit'}</button>
24
+ </form>
25
+ }
26
+ ```
27
+
28
+ ## The one API difference: `onInput`
29
+
30
+ Octane has **native, delegated events** — no synthetic event layer. The
31
+ per-keystroke text event on the platform is `input` (native `change` fires on
32
+ blur/commit), so the handler upstream calls `onChange` is exposed as
33
+ **`onInput`**:
34
+
35
+ - `register(name)` returns `{ name, ref, onInput, onBlur }` (upstream:
36
+ `onChange`). `{...register('x')}` spreads work unchanged.
37
+ - `useController`'s `field` is `{ value, name, ref, onInput, onBlur, … }`.
38
+ `field.onInput` doubles as the programmatic setter (accepts an event or a
39
+ raw value), exactly like upstream's `field.onChange`.
40
+ - `mode: 'onChange'` / `reValidateMode: 'onChange'` option VALUES are
41
+ unchanged — validation still runs per keystroke (driven by native `input`).
42
+ - Register OPTIONS keep their upstream names: `register('x', { onChange, onBlur })`
43
+ callbacks are invoked as before.
44
+
45
+ Everything else — validation modes, `formState` proxy subscriptions,
46
+ `useFieldArray`, `useWatch`/`Watch`, `FormStateSubscribe`, `reset`/`setValue`/
47
+ `trigger` semantics, SSR via `octane/server` — matches upstream behavior; the
48
+ port runs react-hook-form's own ~1,200-test suite (see
49
+ `packages/hook-form/tests/`) plus differential tests asserting byte-identical
50
+ DOM against the real react-hook-form.
51
+
52
+ ## License
53
+
54
+ MIT — contains source derived from
55
+ [react-hook-form](https://github.com/react-hook-form/react-hook-form)
56
+ (MIT, © Beier (Bill) Luo), adapted for octane.
57
+
58
+ ## Status
59
+
60
+ Current scope, known divergences, and verification status are tracked in the
61
+ generated [bindings status table](../../docs/bindings-status.md), sourced from
62
+ this package's [`status.json`](./status.json).
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@octanejs/hook-form",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "description": "React Hook Form for the octane renderer — the full react-hook-form 7.81.0 source ported onto octane's hooks: performant, flexible forms with native-event validation (onInput), field arrays, and schema resolvers.",
7
+ "author": {
8
+ "name": "Dominic Gannaway",
9
+ "email": "dg@domgan.com"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/octanejs/octane.git",
17
+ "directory": "packages/hook-form"
18
+ },
19
+ "main": "src/index.ts",
20
+ "module": "src/index.ts",
21
+ "types": "src/index.ts",
22
+ "files": [
23
+ "src",
24
+ "README.md"
25
+ ],
26
+ "exports": {
27
+ ".": "./src/index.ts"
28
+ },
29
+ "dependencies": {
30
+ "octane": "0.1.3"
31
+ },
32
+ "devDependencies": {
33
+ "@testing-library/jest-dom": "^6.9.1",
34
+ "@tsrx/react": "^0.2.37",
35
+ "esbuild": "^0.28.1",
36
+ "react": "^19.2.0",
37
+ "react-dom": "^19.2.0",
38
+ "react-hook-form": "7.81.0",
39
+ "vitest": "^4.1.9",
40
+ "zod": "^3.25.76",
41
+ "@octanejs/testing-library": "0.1.0"
42
+ },
43
+ "scripts": {
44
+ "test": "vitest run"
45
+ }
46
+ }
@@ -0,0 +1,76 @@
1
+ // Vendored from react-hook-form@7.81.0 src/useFormContext.tsx (octane port) —
2
+ // the FormProvider component half of upstream's file. Propagates the useForm
3
+ // methods to all children via context; the memoized value keeps context
4
+ // identity stable across parent re-renders (same deps as upstream).
5
+ import { useMemo } from 'octane';
6
+ import { HookFormContext, HookFormControlContext } from './useFormControlContext.ts';
7
+
8
+ export function FormProvider(props) @{
9
+ const {
10
+ children,
11
+ watch,
12
+ getValues,
13
+ getFieldState,
14
+ setError,
15
+ clearErrors,
16
+ setValue,
17
+ setValues,
18
+ trigger,
19
+ formState,
20
+ resetField,
21
+ reset,
22
+ handleSubmit,
23
+ unregister,
24
+ control,
25
+ register,
26
+ setFocus,
27
+ subscribe,
28
+ } = props;
29
+
30
+ const memoizedValue = useMemo(
31
+ () => ({
32
+ watch,
33
+ getValues,
34
+ getFieldState,
35
+ setError,
36
+ clearErrors,
37
+ setValue,
38
+ setValues,
39
+ trigger,
40
+ formState,
41
+ resetField,
42
+ reset,
43
+ handleSubmit,
44
+ unregister,
45
+ control,
46
+ register,
47
+ setFocus,
48
+ subscribe,
49
+ }),
50
+ [
51
+ clearErrors,
52
+ control,
53
+ formState,
54
+ getFieldState,
55
+ getValues,
56
+ handleSubmit,
57
+ register,
58
+ reset,
59
+ resetField,
60
+ setError,
61
+ setFocus,
62
+ setValue,
63
+ setValues,
64
+ subscribe,
65
+ trigger,
66
+ unregister,
67
+ watch,
68
+ ],
69
+ );
70
+
71
+ <HookFormContext.Provider value={memoizedValue}>
72
+ <HookFormControlContext.Provider
73
+ value={memoizedValue.control}
74
+ >{children}</HookFormControlContext.Provider>
75
+ </HookFormContext.Provider>
76
+ }
@@ -0,0 +1,10 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ import type { FieldValues, FormProviderProps } from './types';
3
+
4
+ export declare const FormProvider: <
5
+ TFieldValues extends FieldValues,
6
+ TContext = any,
7
+ TTransformedValues = TFieldValues,
8
+ >(
9
+ props: FormProviderProps<TFieldValues, TContext, TTransformedValues>,
10
+ ) => unknown;
@@ -0,0 +1,31 @@
1
+ // Vendored from react-hook-form@7.81.0 src/constants.ts (octane port).
2
+ export const EVENTS = {
3
+ BLUR: 'blur',
4
+ FOCUS_OUT: 'focusout',
5
+ CHANGE: 'change',
6
+ SUBMIT: 'submit',
7
+ TRIGGER: 'trigger',
8
+ VALID: 'valid',
9
+ } as const;
10
+
11
+ export const VALIDATION_MODE = {
12
+ onBlur: 'onBlur',
13
+ onChange: 'onChange',
14
+ onSubmit: 'onSubmit',
15
+ onTouched: 'onTouched',
16
+ all: 'all',
17
+ } as const;
18
+
19
+ export const INPUT_VALIDATION_RULES = {
20
+ max: 'max',
21
+ min: 'min',
22
+ maxLength: 'maxLength',
23
+ minLength: 'minLength',
24
+ pattern: 'pattern',
25
+ required: 'required',
26
+ validate: 'validate',
27
+ } as const;
28
+
29
+ export const ROOT_ERROR_TYPE = 'root';
30
+
31
+ export const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
@@ -0,0 +1,8 @@
1
+ // Vendored from react-hook-form@7.81.0 src/controller.tsx (octane port).
2
+ // Component based on `useController` to work with controlled components.
3
+ // Authored as .tsrx (full compile) — a component in binding src must have its
4
+ // custom-hook call slot-wrapped by the compiler; the plain-.ts slotting pass
5
+ // only slots BASE octane hooks (see compiler/slot-hooks.js).
6
+ import { useController } from './useController.ts';
7
+
8
+ export const Controller = (props) => props.render(useController(props));
@@ -0,0 +1,52 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ import type { ControllerProps, FieldPath, FieldValues } from './types';
3
+
4
+ /**
5
+ * Component based on `useController` hook to work with controlled component.
6
+ *
7
+ * @remarks
8
+ * [API](https://react-hook-form.com/docs/usecontroller/controller) • [Demo](https://codesandbox.io/s/react-hook-form-v6-controller-ts-jwyzw) • [Video](https://www.youtube.com/watch?v=N2UNk_UCVyA)
9
+ *
10
+ * @param props - the path name to the form field value, and validation rules.
11
+ *
12
+ * @returns provide field handler functions, field and form state.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function App() {
17
+ * const { control } = useForm<FormValues>({
18
+ * defaultValues: {
19
+ * test: ""
20
+ * }
21
+ * });
22
+ *
23
+ * return (
24
+ * <form>
25
+ * <Controller
26
+ * control={control}
27
+ * name="test"
28
+ * render={({ field: { onInput, onBlur, value, ref }, formState, fieldState }) => (
29
+ * <>
30
+ * <input
31
+ * onInput={onInput} // send value to hook form
32
+ * onBlur={onBlur} // notify when input is touched
33
+ * value={value} // return updated value
34
+ * ref={ref} // set ref for focus management
35
+ * />
36
+ * <p>{formState.isSubmitted ? "submitted" : ""}</p>
37
+ * <p>{fieldState.isTouched ? "touched" : ""}</p>
38
+ * </>
39
+ * )}
40
+ * />
41
+ * </form>
42
+ * );
43
+ * }
44
+ * ```
45
+ */
46
+ export declare const Controller: <
47
+ TFieldValues extends FieldValues = FieldValues,
48
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
49
+ TTransformedValues = TFieldValues,
50
+ >(
51
+ props: ControllerProps<TFieldValues, TName, TTransformedValues>,
52
+ ) => unknown;
package/src/form.tsrx ADDED
@@ -0,0 +1,119 @@
1
+ // Vendored from react-hook-form@7.81.0 src/form.tsx (octane port).
2
+ // Form component to manage submission — renders a real <form> (or the headless
3
+ // render prop) and posts via fetch. Same submission/error semantics as
4
+ // upstream; the submit handler receives the NATIVE submit event.
5
+ import { useState, useCallback, useEffect } from 'octane';
6
+ import { flatten } from './utils/flatten.ts';
7
+ import { useFormContext } from './useFormContext.ts';
8
+
9
+ const POST_REQUEST = 'post';
10
+
11
+ export function Form(props) {
12
+ const methods = useFormContext();
13
+ const [mounted, setMounted] = useState(false);
14
+ const {
15
+ control = methods.control,
16
+ onSubmit,
17
+ children,
18
+ action,
19
+ method = POST_REQUEST,
20
+ headers,
21
+ encType,
22
+ onError,
23
+ render,
24
+ onSuccess,
25
+ validateStatus,
26
+ ...rest
27
+ } = props;
28
+
29
+ const submit = useCallback(async (event) => {
30
+ let hasError = false;
31
+ let type = '';
32
+
33
+ await control.handleSubmit(async (data) => {
34
+ const formData = new FormData();
35
+ let formDataJson = '';
36
+
37
+ try {
38
+ formDataJson = JSON.stringify(data);
39
+ } catch {
40
+ }
41
+
42
+ const flattenFormValues = flatten(data);
43
+
44
+ for (const key in flattenFormValues) {
45
+ formData.append(key, flattenFormValues[key]);
46
+ }
47
+
48
+ if (onSubmit) {
49
+ await onSubmit({
50
+ data,
51
+ event,
52
+ method,
53
+ formData,
54
+ formDataJson,
55
+ });
56
+ }
57
+
58
+ if (action) {
59
+ try {
60
+ const shouldStringifySubmissionData = [
61
+ headers && headers['Content-Type'],
62
+ encType,
63
+ ].some((value) => value && value.includes('json'));
64
+
65
+ const response = await fetch(String(action), {
66
+ method,
67
+ headers: {
68
+ ...headers,
69
+ ...(encType && encType !== 'multipart/form-data' ? { 'Content-Type': encType } : {}),
70
+ },
71
+ body: shouldStringifySubmissionData ? formDataJson : formData,
72
+ });
73
+
74
+ if (
75
+ response &&
76
+ (validateStatus
77
+ ? !validateStatus(response.status)
78
+ : response.status < 200 || response.status >= 300)
79
+ ) {
80
+ hasError = true;
81
+ onError && onError({ response });
82
+ type = String(response.status);
83
+ } else {
84
+ onSuccess && onSuccess({ response });
85
+ }
86
+ } catch (error) {
87
+ hasError = true;
88
+ onError && onError({ error });
89
+ }
90
+ }
91
+ })(event);
92
+
93
+ if (hasError && control) {
94
+ control._subjects.state.next({
95
+ isSubmitSuccessful: false,
96
+ });
97
+ control.setError('root.server', {
98
+ type,
99
+ });
100
+ }
101
+ }, [control, onSubmit, method, action, headers, encType, validateStatus, onError, onSuccess]);
102
+
103
+ useEffect(() => {
104
+ setMounted(true);
105
+ }, []);
106
+
107
+ if (render) {
108
+ return render({ submit });
109
+ }
110
+
111
+ return <form
112
+ noValidate={mounted}
113
+ action={action}
114
+ method={method}
115
+ encType={encType}
116
+ onSubmit={submit}
117
+ {...rest}
118
+ >{children}</form>;
119
+ }
@@ -0,0 +1,6 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ import type { FieldValues, FormProps } from './types';
3
+
4
+ export declare function Form<TFieldValues extends FieldValues, TTransformedValues = TFieldValues>(
5
+ props: FormProps<TFieldValues, TTransformedValues>,
6
+ ): unknown;
@@ -0,0 +1,10 @@
1
+ // Vendored from react-hook-form@7.81.0 src/formStateSubscribe.tsx (octane port).
2
+ // FormStateSubscribe component — render-prop subscription to form state.
3
+ // Authored as .tsrx (full compile) so the useFormState call is slot-wrapped
4
+ // (see controller.tsrx note).
5
+ import { useFormState } from './useFormState.ts';
6
+
7
+ export const FormStateSubscribe = (props) => {
8
+ const { control, disabled, exact, name, render } = props;
9
+ return render(useFormState({ control, name, disabled, exact }));
10
+ };
@@ -0,0 +1,16 @@
1
+ // Type declaration for the .tsrx component (resolved by relative path).
2
+ import type { FieldValues, UseFormStateProps, UseFormStateReturn } from './types';
3
+
4
+ export type FormStateSubscribeProps<
5
+ TFieldValues extends FieldValues,
6
+ TTransformedValues = TFieldValues,
7
+ > = UseFormStateProps<TFieldValues, TTransformedValues> & {
8
+ render: (values: UseFormStateReturn<TFieldValues>) => unknown;
9
+ };
10
+
11
+ export declare const FormStateSubscribe: <
12
+ TFieldValues extends FieldValues,
13
+ TTransformedValues = TFieldValues,
14
+ >(
15
+ props: FormStateSubscribeProps<TFieldValues, TTransformedValues>,
16
+ ) => unknown;
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ // Vendored from react-hook-form@7.81.0 src/index.ts (octane port).
2
+ // Same public surface as upstream (pinned by tests/conformance/exports.test.ts);
3
+ // upstream's `./form` and the FormProvider half of `./useFormContext` are .tsrx
4
+ // components here. index.react-server.ts is not ported (octane has no server
5
+ // components).
6
+ export { Controller } from './controller.tsrx';
7
+ export { Form } from './form.tsrx';
8
+ export { FormStateSubscribe } from './formStateSubscribe.tsrx';
9
+ export type { FormStateSubscribeProps } from './formStateSubscribe.tsrx';
10
+ export * from './logic';
11
+ export * from './types';
12
+ export * from './useController';
13
+ export * from './useFieldArray';
14
+ export * from './useForm';
15
+ export * from './useFormContext';
16
+ export * from './useFormState';
17
+ export * from './useWatch';
18
+ export * from './utils';
19
+ export { Watch } from './watch.tsrx';
@@ -0,0 +1,19 @@
1
+ // Vendored from react-hook-form@7.81.0 src/logic/appendErrors.ts (octane port).
2
+ import type { InternalFieldErrors, InternalFieldName, ValidateResult } from '../types';
3
+
4
+ export default (
5
+ name: InternalFieldName,
6
+ validateAllFieldCriteria: boolean,
7
+ errors: InternalFieldErrors,
8
+ type: string,
9
+ message: ValidateResult,
10
+ ) =>
11
+ validateAllFieldCriteria
12
+ ? {
13
+ ...errors[name],
14
+ types: {
15
+ ...(errors[name] && errors[name]!.types ? errors[name]!.types : {}),
16
+ [type]: message || true,
17
+ },
18
+ }
19
+ : {};