@vuehookform/core 0.4.1 → 0.4.3
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/LICENSE +1 -1
- package/README.md +46 -6
- package/dist/core/domSync.d.ts +29 -3
- package/dist/core/fieldState.d.ts +19 -13
- package/dist/core/formContext.d.ts +65 -8
- package/dist/index.d.ts +2 -1
- package/dist/types.d.ts +30 -5
- package/dist/useForm.d.ts +6 -0
- package/dist/utils/clone.d.ts +2 -2
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/modeChecks.d.ts +22 -0
- package/dist/utils/paths.d.ts +15 -3
- package/dist/vuehookform.cjs +426 -227
- package/dist/vuehookform.js +423 -229
- package/package.json +7 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -121,12 +121,52 @@ const { value, ...bindings } = register('field', { controlled: true })
|
|
|
121
121
|
|
|
122
122
|
### Common Mistakes
|
|
123
123
|
|
|
124
|
-
| Wrong
|
|
125
|
-
|
|
|
126
|
-
| `items[0].name`
|
|
127
|
-
| `:key="index"`
|
|
128
|
-
| `formState.errors`
|
|
129
|
-
| `v-model` + `register()`
|
|
124
|
+
| Wrong | Right | Why |
|
|
125
|
+
| ------------------------------------ | ----------------------------------------- | -------------------------------------------- |
|
|
126
|
+
| `items[0].name` | `items.0.name` | Always use dot notation for paths |
|
|
127
|
+
| `:key="index"` | `:key="field.key"` | Index can change during reordering |
|
|
128
|
+
| `formState.errors` | `formState.value.errors` | formState is a Ref, must access `.value` |
|
|
129
|
+
| `v-model` + `register()` | Either one, not both | Causes double binding conflict |
|
|
130
|
+
| `const state = getFieldState('x')` | `formState.value.errors.x` | getFieldState returns snapshot, not reactive |
|
|
131
|
+
| `<CustomInput v-bind="register()"/>` | Use `controlled: true` or `useController` | Custom components need controlled mode |
|
|
132
|
+
|
|
133
|
+
#### ⚠️ Critical: `getFieldState()` is NOT Reactive
|
|
134
|
+
|
|
135
|
+
**Problem:** Calling `getFieldState()` once returns a snapshot that never updates.
|
|
136
|
+
|
|
137
|
+
```vue
|
|
138
|
+
<!-- ❌ WRONG - Error will persist even after fixing the input -->
|
|
139
|
+
<script setup>
|
|
140
|
+
const emailState = getFieldState('email')
|
|
141
|
+
</script>
|
|
142
|
+
<template>
|
|
143
|
+
<span v-if="emailState.error">{{ emailState.error }}</span>
|
|
144
|
+
</template>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Solutions:**
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<!-- ✅ Option 1: Use formState (always reactive) -->
|
|
151
|
+
<span v-if="formState.value.errors.email">{{ formState.value.errors.email }}</span>
|
|
152
|
+
|
|
153
|
+
<!-- ✅ Option 2: Use computed for specific field -->
|
|
154
|
+
<script setup>
|
|
155
|
+
const emailError = computed(() => formState.value.errors.email)
|
|
156
|
+
</script>
|
|
157
|
+
<template>
|
|
158
|
+
<span v-if="emailError">{{ emailError }}</span>
|
|
159
|
+
</template>
|
|
160
|
+
|
|
161
|
+
<!-- ✅ Option 3: Use useController for reusable components -->
|
|
162
|
+
<script setup>
|
|
163
|
+
const { fieldState } = useController({ name: 'email', control })
|
|
164
|
+
// fieldState is a ComputedRef that updates automatically
|
|
165
|
+
</script>
|
|
166
|
+
<template>
|
|
167
|
+
<span v-if="fieldState.error">{{ fieldState.error }}</span>
|
|
168
|
+
</template>
|
|
169
|
+
```
|
|
130
170
|
|
|
131
171
|
## Contributing
|
|
132
172
|
|
package/dist/core/domSync.d.ts
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
2
|
import { RegisterOptions } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Extract the actual HTMLInputElement from a ref value.
|
|
5
|
+
* Handles both native elements and Vue component instances (PrimeVue, Vuetify, etc.)
|
|
6
|
+
*
|
|
7
|
+
* Vue component libraries typically expose:
|
|
8
|
+
* - $el: The root DOM element of the component
|
|
9
|
+
* - Some components wrap inputs in divs, so we may need to query for the input
|
|
10
|
+
*
|
|
11
|
+
* @param refValue - The value from fieldRef.value (HTMLInputElement, Component, or null)
|
|
12
|
+
* @returns The underlying HTMLInputElement, or null if not found
|
|
13
|
+
*/
|
|
14
|
+
export declare function getInputElement(refValue: unknown): HTMLInputElement | null;
|
|
15
|
+
/**
|
|
16
|
+
* Get a focusable element from a ref value.
|
|
17
|
+
* Works with both native elements and Vue component instances.
|
|
18
|
+
*
|
|
19
|
+
* @param refValue - The value from fieldRef.value
|
|
20
|
+
* @returns The focusable HTMLElement, or null if not found
|
|
21
|
+
*/
|
|
22
|
+
export declare function getFocusableElement(refValue: unknown): HTMLElement | null;
|
|
3
23
|
/**
|
|
4
24
|
* Sync values from uncontrolled DOM inputs to form data
|
|
5
25
|
*
|
|
6
26
|
* This reads the current DOM state from uncontrolled inputs and updates
|
|
7
27
|
* the formData object. Used before form submission and when getting values.
|
|
8
28
|
*
|
|
29
|
+
* Handles type coercion for:
|
|
30
|
+
* - checkbox: returns boolean (el.checked)
|
|
31
|
+
* - number/range: returns number (el.valueAsNumber)
|
|
32
|
+
* - all other types: returns string (el.value)
|
|
33
|
+
*
|
|
9
34
|
* @param fieldRefs - Map of field names to their DOM element refs
|
|
10
35
|
* @param fieldOptions - Map of field names to their registration options
|
|
11
36
|
* @param formData - The reactive form data object to update
|
|
12
37
|
*/
|
|
13
|
-
export declare function syncUncontrolledInputs(fieldRefs: Map<string, Ref<
|
|
38
|
+
export declare function syncUncontrolledInputs(fieldRefs: Map<string, Ref<unknown>>, fieldOptions: Map<string, RegisterOptions>, formData: Record<string, unknown>): void;
|
|
14
39
|
/**
|
|
15
40
|
* Update a single DOM element with a new value
|
|
16
41
|
*
|
|
17
42
|
* Handles both checkbox and text inputs appropriately.
|
|
43
|
+
* Supports both native elements and Vue component instances.
|
|
18
44
|
*
|
|
19
|
-
* @param
|
|
45
|
+
* @param refValue - The ref value (HTMLInputElement, Vue component, or null)
|
|
20
46
|
* @param value - The value to set
|
|
21
47
|
*/
|
|
22
|
-
export declare function updateDomElement(
|
|
48
|
+
export declare function updateDomElement(refValue: unknown, value: unknown): void;
|
|
@@ -1,42 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ShallowRef } from 'vue';
|
|
2
2
|
/**
|
|
3
3
|
* Mark a field as dirty (value has changed from default).
|
|
4
4
|
* Optimized to skip clone if already dirty.
|
|
5
|
-
* Maintains O(1) dirty field count for performance.
|
|
6
5
|
*
|
|
7
6
|
* @param dirtyFields - The reactive dirty fields record
|
|
8
|
-
* @param dirtyFieldCount - Counter for O(1) isDirty checks
|
|
9
7
|
* @param fieldName - Name of the field to mark as dirty
|
|
10
8
|
*/
|
|
11
|
-
export declare function markFieldDirty(dirtyFields: ShallowRef<Record<string, boolean>>,
|
|
9
|
+
export declare function markFieldDirty(dirtyFields: ShallowRef<Record<string, boolean>>, fieldName: string): void;
|
|
12
10
|
/**
|
|
13
11
|
* Mark a field as touched (user has interacted with it).
|
|
14
12
|
* Optimized to skip clone if already touched.
|
|
15
|
-
* Maintains O(1) touched field count for performance.
|
|
16
13
|
*
|
|
17
14
|
* @param touchedFields - The reactive touched fields record
|
|
18
|
-
* @param touchedFieldCount - Counter for O(1) touched checks
|
|
19
15
|
* @param fieldName - Name of the field to mark as touched
|
|
20
16
|
*/
|
|
21
|
-
export declare function markFieldTouched(touchedFields: ShallowRef<Record<string, boolean>>,
|
|
17
|
+
export declare function markFieldTouched(touchedFields: ShallowRef<Record<string, boolean>>, fieldName: string): void;
|
|
22
18
|
/**
|
|
23
19
|
* Clear dirty state for a field.
|
|
24
|
-
* Maintains O(1) dirty field count for performance.
|
|
25
20
|
*
|
|
26
21
|
* @param dirtyFields - The reactive dirty fields record
|
|
27
|
-
* @param dirtyFieldCount - Counter for O(1) isDirty checks
|
|
28
22
|
* @param fieldName - Name of the field to clear
|
|
29
23
|
*/
|
|
30
|
-
export declare function clearFieldDirty(dirtyFields: ShallowRef<Record<string, boolean>>,
|
|
24
|
+
export declare function clearFieldDirty(dirtyFields: ShallowRef<Record<string, boolean>>, fieldName: string): void;
|
|
31
25
|
/**
|
|
32
26
|
* Clear touched state for a field.
|
|
33
|
-
* Maintains O(1) touched field count for performance.
|
|
34
27
|
*
|
|
35
28
|
* @param touchedFields - The reactive touched fields record
|
|
36
|
-
* @param touchedFieldCount - Counter for O(1) touched checks
|
|
37
29
|
* @param fieldName - Name of the field to clear
|
|
38
30
|
*/
|
|
39
|
-
export declare function clearFieldTouched(touchedFields: ShallowRef<Record<string, boolean>>,
|
|
31
|
+
export declare function clearFieldTouched(touchedFields: ShallowRef<Record<string, boolean>>, fieldName: string): void;
|
|
40
32
|
/**
|
|
41
33
|
* Clear errors for a field and its nested paths.
|
|
42
34
|
* Optimized with early exit if nothing to delete.
|
|
@@ -45,3 +37,17 @@ export declare function clearFieldTouched(touchedFields: ShallowRef<Record<strin
|
|
|
45
37
|
* @param fieldName - Name of the field (clears exact match and all nested paths)
|
|
46
38
|
*/
|
|
47
39
|
export declare function clearFieldErrors<T>(errors: ShallowRef<Record<string, T>>, fieldName: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Update field dirty state based on value comparison with default.
|
|
42
|
+
* Field is dirty only if current value differs from default value.
|
|
43
|
+
*
|
|
44
|
+
* Uses lazy hash computation - default hashes are computed on first access
|
|
45
|
+
* and cached for subsequent comparisons.
|
|
46
|
+
*
|
|
47
|
+
* @param dirtyFields - The reactive dirty fields record
|
|
48
|
+
* @param defaultValues - The original default values
|
|
49
|
+
* @param defaultValueHashes - Cache of hashed default values
|
|
50
|
+
* @param fieldName - Name of the field to check
|
|
51
|
+
* @param currentValue - The current value to compare against default
|
|
52
|
+
*/
|
|
53
|
+
export declare function updateFieldDirtyState(dirtyFields: ShallowRef<Record<string, boolean>>, defaultValues: Record<string, unknown>, defaultValueHashes: Map<string, string>, fieldName: string, currentValue: unknown): void;
|
|
@@ -2,57 +2,114 @@ import { Ref, ShallowRef } from 'vue';
|
|
|
2
2
|
import { ZodType } from 'zod';
|
|
3
3
|
import { UseFormOptions, FieldErrors, FieldErrorValue, InferSchema, RegisterOptions, FieldArrayItem, FieldArrayRules } from '../types';
|
|
4
4
|
/**
|
|
5
|
-
* Internal state for field array management
|
|
5
|
+
* Internal state for field array management.
|
|
6
|
+
* Tracks items, their indices, and array-level validation rules.
|
|
7
|
+
*
|
|
8
|
+
* @internal This interface is used internally by useFieldArray and should not be
|
|
9
|
+
* directly instantiated by consumers.
|
|
6
10
|
*/
|
|
7
11
|
export interface FieldArrayState {
|
|
12
|
+
/** Reactive list of field array items with stable keys for Vue reconciliation */
|
|
8
13
|
items: Ref<FieldArrayItem[]>;
|
|
14
|
+
/** Raw array values (kept in sync with formData) */
|
|
9
15
|
values: unknown[];
|
|
16
|
+
/** O(1) lookup cache mapping item keys to their current indices */
|
|
10
17
|
indexCache: Map<string, number>;
|
|
18
|
+
/** Optional validation rules for the array itself (minLength, maxLength, custom) */
|
|
11
19
|
rules?: FieldArrayRules;
|
|
12
20
|
}
|
|
13
21
|
/**
|
|
14
|
-
* Cached event handlers for a field
|
|
22
|
+
* Cached event handlers for a field.
|
|
23
|
+
* These are created once per field registration and reused to prevent
|
|
24
|
+
* unnecessary re-renders and closure recreation.
|
|
25
|
+
*
|
|
26
|
+
* @internal This interface is used internally by useFieldRegistration and should not be
|
|
27
|
+
* directly instantiated by consumers.
|
|
15
28
|
*/
|
|
16
29
|
export interface FieldHandlers {
|
|
30
|
+
/** Handler for input events, triggers validation based on mode */
|
|
17
31
|
onInput: (e: Event) => Promise<void>;
|
|
18
|
-
|
|
32
|
+
/** Handler for blur events, marks field as touched and may trigger validation */
|
|
33
|
+
onBlur: () => Promise<void>;
|
|
34
|
+
/** Ref callback to capture the DOM element reference */
|
|
19
35
|
refCallback: (el: unknown) => void;
|
|
20
36
|
}
|
|
21
37
|
/**
|
|
22
|
-
* Shared form context containing all reactive state
|
|
23
|
-
* This is passed to sub-modules via dependency injection
|
|
38
|
+
* Shared form context containing all reactive state.
|
|
39
|
+
* This is the central state container passed to sub-modules via dependency injection.
|
|
40
|
+
*
|
|
41
|
+
* The context is organized into several categories:
|
|
42
|
+
* - **Form Data**: Raw form values and their defaults
|
|
43
|
+
* - **Form State**: Validation errors, touched/dirty tracking, submission state
|
|
44
|
+
* - **Field Tracking**: DOM refs, registration options, field arrays
|
|
45
|
+
* - **Validation**: Caching, debouncing, and async validation coordination
|
|
46
|
+
* - **Configuration**: Form options and disabled state
|
|
47
|
+
*
|
|
48
|
+
* @typeParam FormValues - The inferred type from the Zod schema
|
|
49
|
+
*
|
|
50
|
+
* @internal This interface is used internally by useForm and its sub-modules.
|
|
51
|
+
* Consumers should use the public API returned by useForm() instead.
|
|
24
52
|
*/
|
|
25
53
|
export interface FormContext<FormValues> {
|
|
54
|
+
/** Reactive form data object containing current field values */
|
|
26
55
|
formData: Record<string, unknown>;
|
|
56
|
+
/** Original default values used for reset() and dirty detection */
|
|
27
57
|
defaultValues: Record<string, unknown>;
|
|
58
|
+
/** Current validation errors keyed by field path */
|
|
28
59
|
errors: ShallowRef<FieldErrors<FormValues>>;
|
|
60
|
+
/** Record of field paths that have been touched (blurred) */
|
|
29
61
|
touchedFields: ShallowRef<Record<string, boolean>>;
|
|
62
|
+
/** Record of field paths that differ from default values */
|
|
30
63
|
dirtyFields: ShallowRef<Record<string, boolean>>;
|
|
64
|
+
/** Whether the form is currently being submitted */
|
|
31
65
|
isSubmitting: Ref<boolean>;
|
|
66
|
+
/** Whether async default values are being loaded */
|
|
32
67
|
isLoading: Ref<boolean>;
|
|
68
|
+
/** Number of times the form has been submitted */
|
|
33
69
|
submitCount: Ref<number>;
|
|
70
|
+
/** Error that occurred while loading async default values */
|
|
34
71
|
defaultValuesError: Ref<unknown>;
|
|
72
|
+
/** Whether the last submission completed successfully */
|
|
35
73
|
isSubmitSuccessful: Ref<boolean>;
|
|
74
|
+
/** Set of field paths currently being validated (for isValidating state) */
|
|
36
75
|
validatingFields: ShallowRef<Set<string>>;
|
|
76
|
+
/** External errors (e.g., from server) merged with validation errors */
|
|
37
77
|
externalErrors: ShallowRef<FieldErrors<FormValues>>;
|
|
78
|
+
/** Timers for delayed error display per field */
|
|
38
79
|
errorDelayTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
80
|
+
/** Pending errors waiting for delay timer to complete */
|
|
39
81
|
pendingErrors: Map<string, FieldErrorValue>;
|
|
82
|
+
/** DOM element refs for registered uncontrolled fields */
|
|
40
83
|
fieldRefs: Map<string, Ref<HTMLInputElement | null>>;
|
|
84
|
+
/** Registration options per field path */
|
|
41
85
|
fieldOptions: Map<string, RegisterOptions>;
|
|
86
|
+
/** Field array state for array fields managed by fields() */
|
|
42
87
|
fieldArrays: Map<string, FieldArrayState>;
|
|
88
|
+
/** Cached event handlers to prevent recreation on re-render */
|
|
43
89
|
fieldHandlers: Map<string, FieldHandlers>;
|
|
90
|
+
/** Debounce timers for custom async validation per field */
|
|
44
91
|
debounceTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
92
|
+
/** Request IDs for canceling stale async validation results */
|
|
45
93
|
validationRequestIds: Map<string, number>;
|
|
94
|
+
/** Generation counter incremented on reset to cancel in-flight validations */
|
|
46
95
|
resetGeneration: Ref<number>;
|
|
47
|
-
|
|
48
|
-
dirtyFieldCount: Ref<number>;
|
|
49
|
-
touchedFieldCount: Ref<number>;
|
|
96
|
+
/** Cache of validation results keyed by field path and value hash */
|
|
50
97
|
validationCache: Map<string, {
|
|
51
98
|
hash: string;
|
|
52
99
|
isValid: boolean;
|
|
53
100
|
}>;
|
|
101
|
+
/** Debounce timers for schema validation per field */
|
|
54
102
|
schemaValidationTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
103
|
+
/** Set of field paths with persistent errors (survive validation cycles) */
|
|
104
|
+
persistentErrorFields: Set<string>;
|
|
105
|
+
/** Hashed default values for value-comparison dirty detection */
|
|
106
|
+
defaultValueHashes: Map<string, string>;
|
|
107
|
+
/** Whether the entire form is disabled */
|
|
108
|
+
isDisabled: Ref<boolean>;
|
|
109
|
+
/** Original options passed to useForm() */
|
|
55
110
|
options: UseFormOptions<ZodType>;
|
|
111
|
+
/** Cleanup function to stop all watchers and prevent memory leaks */
|
|
112
|
+
cleanup: () => void;
|
|
56
113
|
}
|
|
57
114
|
/**
|
|
58
115
|
* Create a new form context with all reactive state initialized
|
package/dist/index.d.ts
CHANGED
|
@@ -20,4 +20,5 @@ export { useWatch, type UseWatchOptions } from './useWatch';
|
|
|
20
20
|
export { useController, type UseControllerOptions, type UseControllerReturn, type ControllerFieldProps, } from './useController';
|
|
21
21
|
export { useFormState, type UseFormStateOptions, type FormStateKey } from './useFormState';
|
|
22
22
|
export { isFieldError } from './types';
|
|
23
|
-
export type { UseFormOptions, UseFormReturn, RegisterOptions, RegisterReturn, FormState, FieldState, FieldErrors, FieldError, FieldErrorValue, ErrorOption, SetErrorsOptions, FieldArray, FieldArrayItem, InferSchema, FormValues, FormPath, Path, PathValue, ArrayElement, ArrayPath, FieldPath, ValidationMode, SetFocusOptions, ResetOptions, ResetFieldOptions, AsyncDefaultValues, } from './types';
|
|
23
|
+
export type { UseFormOptions, UseFormReturn, RegisterOptions, RegisterReturn, FormState, FieldState, FieldErrors, FieldError, FieldErrorValue, ErrorOption, SetErrorsOptions, FieldArray, FieldArrayItem, FieldArrayOptions, FieldArrayRules, FieldArrayFocusOptions, InferSchema, FormValues, FormPath, Path, PathValue, ArrayElement, ArrayPath, FieldPath, ValidationMode, SetFocusOptions, ResetOptions, ResetFieldOptions, AsyncDefaultValues, TriggerOptions, SetValueOptions, UnregisterOptions, CriteriaMode, } from './types';
|
|
24
|
+
export { get, set, unset, generateId, clearPathCache } from './utils/paths';
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type ValidationMode = 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched';
|
|
|
7
7
|
/**
|
|
8
8
|
* Extract the inferred type from a Zod schema
|
|
9
9
|
*/
|
|
10
|
-
export type InferSchema<
|
|
10
|
+
export type InferSchema<TSchema extends ZodType> = z.infer<TSchema>;
|
|
11
11
|
/**
|
|
12
12
|
* Alias for InferSchema - extracts form value type from schema.
|
|
13
13
|
* Use this when you need the actual form data type.
|
|
@@ -198,7 +198,7 @@ export interface FieldState {
|
|
|
198
198
|
/** Whether field has a validation error */
|
|
199
199
|
invalid: boolean;
|
|
200
200
|
/** The error (string for backward compatibility, or FieldError for structured errors) */
|
|
201
|
-
error?:
|
|
201
|
+
error?: FieldErrorValue;
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
* Error option for setError()
|
|
@@ -208,6 +208,11 @@ export interface ErrorOption {
|
|
|
208
208
|
type?: string;
|
|
209
209
|
/** Error message to display */
|
|
210
210
|
message: string;
|
|
211
|
+
/**
|
|
212
|
+
* If true, the error will not be cleared by subsequent validations.
|
|
213
|
+
* Useful for server-side validation errors that should persist until explicitly cleared.
|
|
214
|
+
*/
|
|
215
|
+
persistent?: boolean;
|
|
211
216
|
}
|
|
212
217
|
/**
|
|
213
218
|
* Options for setFocus()
|
|
@@ -241,6 +246,16 @@ export interface ResetFieldOptions<TValue = unknown> {
|
|
|
241
246
|
/** New default value (updates stored default) - typed to match field */
|
|
242
247
|
defaultValue?: TValue;
|
|
243
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Options for trigger()
|
|
251
|
+
*/
|
|
252
|
+
export interface TriggerOptions {
|
|
253
|
+
/**
|
|
254
|
+
* If true, increments submitCount to activate reValidateMode behavior.
|
|
255
|
+
* Useful when you want manual validation to trigger reValidation on subsequent changes.
|
|
256
|
+
*/
|
|
257
|
+
markAsSubmitted?: boolean;
|
|
258
|
+
}
|
|
244
259
|
/**
|
|
245
260
|
* Options for unregister()
|
|
246
261
|
*/
|
|
@@ -341,7 +356,7 @@ export interface RegisterReturn<TValue = unknown> {
|
|
|
341
356
|
/** Input handler (fires on every keystroke) */
|
|
342
357
|
onInput: (e: Event) => void;
|
|
343
358
|
/** Blur handler */
|
|
344
|
-
onBlur: (
|
|
359
|
+
onBlur: () => void;
|
|
345
360
|
/** Current value (for controlled mode) - only present when controlled: true */
|
|
346
361
|
value?: Ref<TValue>;
|
|
347
362
|
/** Disabled state from form-level disabled option */
|
|
@@ -403,6 +418,10 @@ export interface FieldArrayOptions<T = unknown> {
|
|
|
403
418
|
* - minLength rule would be violated (remove, removeAll, removeMany)
|
|
404
419
|
* - Index is out of bounds (remove, update, swap, move)
|
|
405
420
|
*
|
|
421
|
+
* **Reactivity:** The `value` property is fully reactive - it automatically
|
|
422
|
+
* updates when array methods (append, remove, swap, etc.) are called.
|
|
423
|
+
* Your template will re-render when items change.
|
|
424
|
+
*
|
|
406
425
|
* @template TItem - The type of items in the array (inferred from field path)
|
|
407
426
|
*
|
|
408
427
|
* @example
|
|
@@ -418,7 +437,7 @@ export interface FieldArrayOptions<T = unknown> {
|
|
|
418
437
|
* }
|
|
419
438
|
*/
|
|
420
439
|
export interface FieldArray<TItem = unknown> {
|
|
421
|
-
/** Current field items with metadata */
|
|
440
|
+
/** Current field items with metadata. Reactive - updates when array methods are called. */
|
|
422
441
|
value: FieldArrayItem[];
|
|
423
442
|
/** Append item(s) to end of array. Returns false if maxLength exceeded. */
|
|
424
443
|
append: (value: TItem | TItem[], options?: FieldArrayFocusOptions) => boolean;
|
|
@@ -839,14 +858,20 @@ export interface UseFormReturn<TSchema extends ZodType> {
|
|
|
839
858
|
/**
|
|
840
859
|
* Manually trigger validation for specific fields or entire form
|
|
841
860
|
* @param name - Optional field path or array of paths
|
|
861
|
+
* @param options - Optional trigger options (e.g., markAsSubmitted)
|
|
842
862
|
*/
|
|
843
|
-
trigger: <TPath extends Path<InferSchema<TSchema>>>(name?: TPath | TPath[]) => Promise<boolean>;
|
|
863
|
+
trigger: <TPath extends Path<InferSchema<TSchema>>>(name?: TPath | TPath[], options?: TriggerOptions) => Promise<boolean>;
|
|
844
864
|
/**
|
|
845
865
|
* Programmatically focus a field
|
|
846
866
|
* @param name - Field path
|
|
847
867
|
* @param options - Focus options
|
|
848
868
|
*/
|
|
849
869
|
setFocus: <TPath extends Path<InferSchema<TSchema>>>(name: TPath, options?: SetFocusOptions) => void;
|
|
870
|
+
/**
|
|
871
|
+
* Form configuration options (mode, reValidateMode).
|
|
872
|
+
* Useful for composables like useController that need to respect validation modes.
|
|
873
|
+
*/
|
|
874
|
+
options: Pick<UseFormOptions<TSchema>, 'mode' | 'reValidateMode'>;
|
|
850
875
|
}
|
|
851
876
|
/**
|
|
852
877
|
* Type guard to check if an error value is a structured FieldError object.
|
package/dist/useForm.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ZodType } from 'zod';
|
|
2
2
|
import { UseFormOptions, UseFormReturn } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Set the internal flag to suppress getFieldState warnings.
|
|
5
|
+
* Used by useController before calling getFieldState inside computed().
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare function setCalledFromController(value: boolean): void;
|
|
3
9
|
/**
|
|
4
10
|
* Main form management composable
|
|
5
11
|
*
|
package/dist/utils/clone.d.ts
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
* - Arrays (recursive clone)
|
|
9
9
|
* - Date objects (new Date instance)
|
|
10
10
|
* - null/undefined (pass-through)
|
|
11
|
+
* - Circular references (recreates the circular structure in the clone)
|
|
11
12
|
*
|
|
12
13
|
* Does NOT handle (by design, not needed for form data):
|
|
13
|
-
* - Circular references
|
|
14
14
|
* - Map/Set/WeakMap/WeakSet
|
|
15
15
|
* - Functions
|
|
16
16
|
* - Symbols
|
|
17
17
|
* - Class instances (cloned as plain objects)
|
|
18
18
|
*/
|
|
19
|
-
export declare function deepClone<T>(obj: T): T;
|
|
19
|
+
export declare function deepClone<T>(obj: T, seen?: Map<object, unknown>): T;
|
package/dist/utils/hash.d.ts
CHANGED
|
@@ -2,5 +2,8 @@
|
|
|
2
2
|
* Fast value hashing for validation cache.
|
|
3
3
|
* Uses JSON.stringify for objects/arrays, direct conversion for primitives.
|
|
4
4
|
* Returns a string that can be compared for equality.
|
|
5
|
+
*
|
|
6
|
+
* Handles circular references by assigning stable IDs via WeakMap,
|
|
7
|
+
* ensuring the same object always produces the same hash.
|
|
5
8
|
*/
|
|
6
9
|
export declare function hashValue(value: unknown): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ValidationMode } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Determines if validation should occur on change event.
|
|
4
|
+
* Used by useController and register for consistent mode handling.
|
|
5
|
+
*
|
|
6
|
+
* @param mode - The form's validation mode
|
|
7
|
+
* @param isTouched - Whether the field has been touched
|
|
8
|
+
* @param reValidateMode - The form's reValidateMode (used after first submit)
|
|
9
|
+
* @param hasSubmitted - Whether the form has been submitted at least once (optional, for reValidateMode)
|
|
10
|
+
* @returns true if validation should be triggered
|
|
11
|
+
*/
|
|
12
|
+
export declare function shouldValidateOnChange(mode: ValidationMode, isTouched: boolean, reValidateMode?: ValidationMode, hasSubmitted?: boolean): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Determines if validation should occur on blur event.
|
|
15
|
+
* Used by useController and register for consistent mode handling.
|
|
16
|
+
*
|
|
17
|
+
* @param mode - The form's validation mode
|
|
18
|
+
* @param hasSubmitted - Whether the form has been submitted at least once
|
|
19
|
+
* @param reValidateMode - The form's reValidateMode (used after first submit)
|
|
20
|
+
* @returns true if validation should be triggered
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldValidateOnBlur(mode: ValidationMode, hasSubmitted: boolean, reValidateMode?: ValidationMode): boolean;
|
package/dist/utils/paths.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Clear the path cache.
|
|
3
|
-
*
|
|
2
|
+
* Clear the path segment cache.
|
|
3
|
+
* Call this between SSR requests to prevent memory accumulation,
|
|
4
|
+
* or in tests to reset state.
|
|
5
|
+
*
|
|
6
|
+
* The cache is bounded to 256 entries, so clearing is optional
|
|
7
|
+
* for client-side only applications.
|
|
4
8
|
*/
|
|
5
9
|
export declare function clearPathCache(): void;
|
|
6
10
|
/**
|
|
@@ -19,7 +23,15 @@ export declare function set(obj: Record<string, unknown>, path: string, value: u
|
|
|
19
23
|
*/
|
|
20
24
|
export declare function unset(obj: Record<string, unknown>, path: string): void;
|
|
21
25
|
/**
|
|
22
|
-
* Check if path exists in object
|
|
26
|
+
* Check if path exists in object.
|
|
27
|
+
* Unlike `get(obj, path) !== undefined`, this properly distinguishes between
|
|
28
|
+
* a missing path and a path that exists with an `undefined` value.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* has({ name: undefined }, 'name') // true - path exists
|
|
32
|
+
* has({ }, 'name') // false - path doesn't exist
|
|
33
|
+
* has({ user: { name: 'John' } }, 'user.name') // true
|
|
34
|
+
* has({ user: { name: 'John' } }, 'user.age') // false
|
|
23
35
|
*/
|
|
24
36
|
export declare function has(obj: Record<string, unknown>, path: string): boolean;
|
|
25
37
|
export declare function generateId(): string;
|