@vuehookform/core 0.5.0 → 0.7.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/dist/core/useFieldRegistration.d.ts +9 -2
- package/dist/index.d.ts +1 -0
- package/dist/types.d.ts +24 -0
- package/dist/useFieldError.d.ts +54 -0
- package/dist/useFormState.d.ts +5 -6
- package/dist/useWatch.d.ts +1 -1
- package/dist/vuehookform.cjs +68 -36
- package/dist/vuehookform.cjs.map +1 -0
- package/dist/vuehookform.js +68 -37
- package/dist/vuehookform.js.map +1 -0
- package/package.json +1 -1
package/dist/vuehookform.js
CHANGED
|
@@ -539,14 +539,15 @@ function clearFieldTouched(touchedFields, fieldName) {
|
|
|
539
539
|
}
|
|
540
540
|
function clearFieldErrors(errors, fieldName) {
|
|
541
541
|
const currentErrors = errors.value;
|
|
542
|
-
|
|
543
|
-
|
|
542
|
+
if (Object.keys(currentErrors).length === 0) return;
|
|
543
|
+
const nestedError = get(currentErrors, fieldName);
|
|
544
544
|
const prefix = `${fieldName}.`;
|
|
545
|
-
const
|
|
546
|
-
for (const key of keys) if (key === fieldName || key.startsWith(prefix))
|
|
547
|
-
if (
|
|
545
|
+
const flatKeysToDelete = [];
|
|
546
|
+
for (const key of Object.keys(currentErrors)) if (key === fieldName || key.startsWith(prefix)) flatKeysToDelete.push(key);
|
|
547
|
+
if (nestedError === void 0 && flatKeysToDelete.length === 0) return;
|
|
548
548
|
const newErrors = { ...currentErrors };
|
|
549
|
-
for (const key of
|
|
549
|
+
for (const key of flatKeysToDelete) delete newErrors[key];
|
|
550
|
+
if (nestedError !== void 0) unset(newErrors, fieldName);
|
|
550
551
|
errors.value = newErrors;
|
|
551
552
|
}
|
|
552
553
|
function updateFieldDirtyState(dirtyFields, defaultValues, defaultValueHashes, fieldName, currentValue) {
|
|
@@ -590,7 +591,6 @@ function createFieldError(errors, criteriaMode = "firstError") {
|
|
|
590
591
|
const firstError = errors[0];
|
|
591
592
|
if (!firstError) return "";
|
|
592
593
|
if (criteriaMode === "firstError") return firstError.message;
|
|
593
|
-
if (errors.length === 1) return firstError.message;
|
|
594
594
|
const types = {};
|
|
595
595
|
for (const err of errors) {
|
|
596
596
|
const existing = types[err.type];
|
|
@@ -816,7 +816,7 @@ function shouldValidateOnBlur(mode, hasSubmitted, reValidateMode) {
|
|
|
816
816
|
return mode === "onBlur" || mode === "onTouched" || hasSubmitted && (reValidateMode === "onBlur" || reValidateMode === "onTouched");
|
|
817
817
|
}
|
|
818
818
|
var validationRequestCounter = 0;
|
|
819
|
-
function createFieldRegistration(ctx, validate) {
|
|
819
|
+
function createFieldRegistration(ctx, validate, onChangeHelpers) {
|
|
820
820
|
function register(name, registerOptions) {
|
|
821
821
|
if (__DEV__) {
|
|
822
822
|
const syntaxError = validatePathSyntax(name);
|
|
@@ -843,13 +843,13 @@ function createFieldRegistration(ctx, validate) {
|
|
|
843
843
|
const error = await fieldOpts.validate(value);
|
|
844
844
|
if (requestId !== ctx.validationRequestIds.get(fieldName)) return;
|
|
845
845
|
if (ctx.resetGeneration.value !== resetGenAtStart) return;
|
|
846
|
-
if (error)
|
|
847
|
-
...ctx.errors.value
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
else {
|
|
846
|
+
if (error) {
|
|
847
|
+
const newErrors = { ...ctx.errors.value };
|
|
848
|
+
set(newErrors, fieldName, error);
|
|
849
|
+
ctx.errors.value = newErrors;
|
|
850
|
+
} else {
|
|
851
851
|
const newErrors = { ...ctx.errors.value };
|
|
852
|
-
|
|
852
|
+
unset(newErrors, fieldName);
|
|
853
853
|
ctx.errors.value = newErrors;
|
|
854
854
|
}
|
|
855
855
|
};
|
|
@@ -862,6 +862,11 @@ function createFieldRegistration(ctx, validate) {
|
|
|
862
862
|
set(ctx.formData, name, value);
|
|
863
863
|
updateFieldDirtyState(ctx.dirtyFields, ctx.defaultValues, ctx.defaultValueHashes, name, value);
|
|
864
864
|
const fieldOpts = ctx.fieldOptions.get(name);
|
|
865
|
+
if (fieldOpts?.onChange && onChangeHelpers?.setValue) try {
|
|
866
|
+
fieldOpts.onChange(value, { setValue: onChangeHelpers.setValue });
|
|
867
|
+
} catch (err) {
|
|
868
|
+
if (__DEV__) console.error(`[vue-hook-form] Error in onChange callback for field '${name}':`, err);
|
|
869
|
+
}
|
|
865
870
|
if (shouldValidateOnChange(ctx.options.mode ?? "onSubmit", ctx.touchedFields.value[name] === true, ctx.submitCount.value > 0, ctx.options.reValidateMode)) {
|
|
866
871
|
const validationDebounceMs = ctx.options.validationDebounce || 0;
|
|
867
872
|
if (validationDebounceMs > 0) {
|
|
@@ -1421,7 +1426,8 @@ function useForm(options) {
|
|
|
1421
1426
|
ctx.cleanup();
|
|
1422
1427
|
});
|
|
1423
1428
|
const { validate, clearAllPendingErrors } = createValidation(ctx);
|
|
1424
|
-
const {
|
|
1429
|
+
const onChangeHelpers = { setValue: null };
|
|
1430
|
+
const { register, unregister } = createFieldRegistration(ctx, validate, onChangeHelpers);
|
|
1425
1431
|
function setFocus(name, focusOptions) {
|
|
1426
1432
|
if (__DEV__) {
|
|
1427
1433
|
const syntaxError = validatePathSyntax(name);
|
|
@@ -1512,6 +1518,12 @@ function useForm(options) {
|
|
|
1512
1518
|
},
|
|
1513
1519
|
get disabled() {
|
|
1514
1520
|
return ctx.isDisabled.value;
|
|
1521
|
+
},
|
|
1522
|
+
get isPristine() {
|
|
1523
|
+
return !isDirtyComputed.value;
|
|
1524
|
+
},
|
|
1525
|
+
get canSubmit() {
|
|
1526
|
+
return isValidComputed.value && !ctx.isSubmitting.value && !ctx.isLoading.value && !ctx.isDisabled.value;
|
|
1515
1527
|
}
|
|
1516
1528
|
});
|
|
1517
1529
|
const formState = computed(() => formStateInternal);
|
|
@@ -1527,7 +1539,7 @@ function useForm(options) {
|
|
|
1527
1539
|
try {
|
|
1528
1540
|
syncWithDebounce();
|
|
1529
1541
|
if (await validate()) {
|
|
1530
|
-
await onValid(ctx.formData);
|
|
1542
|
+
await onValid(deepClone(ctx.formData));
|
|
1531
1543
|
ctx.isSubmitSuccessful.value = true;
|
|
1532
1544
|
} else {
|
|
1533
1545
|
onInvalid?.(formState.value.errors);
|
|
@@ -1561,6 +1573,7 @@ function useForm(options) {
|
|
|
1561
1573
|
}
|
|
1562
1574
|
if (setValueOptions?.shouldValidate) validate(name);
|
|
1563
1575
|
}
|
|
1576
|
+
onChangeHelpers.setValue = setValue;
|
|
1564
1577
|
function reset(values, resetOptions) {
|
|
1565
1578
|
const opts = resetOptions || {};
|
|
1566
1579
|
ctx.validationCache.clear();
|
|
@@ -1609,7 +1622,6 @@ function useForm(options) {
|
|
|
1609
1622
|
}
|
|
1610
1623
|
}
|
|
1611
1624
|
const opts = resetFieldOptions || {};
|
|
1612
|
-
ctx.resetGeneration.value++;
|
|
1613
1625
|
ctx.validationCache.delete(`${name}:partial`);
|
|
1614
1626
|
ctx.validationCache.delete(`${name}:full`);
|
|
1615
1627
|
const errorTimer = ctx.errorDelayTimers.get(name);
|
|
@@ -1618,6 +1630,11 @@ function useForm(options) {
|
|
|
1618
1630
|
ctx.errorDelayTimers.delete(name);
|
|
1619
1631
|
}
|
|
1620
1632
|
ctx.pendingErrors.delete(name);
|
|
1633
|
+
const schemaTimer = ctx.schemaValidationTimers.get(name);
|
|
1634
|
+
if (schemaTimer) {
|
|
1635
|
+
clearTimeout(schemaTimer);
|
|
1636
|
+
ctx.schemaValidationTimers.delete(name);
|
|
1637
|
+
}
|
|
1621
1638
|
let defaultValue = opts.defaultValue;
|
|
1622
1639
|
if (defaultValue === void 0) defaultValue = get(ctx.defaultValues, name);
|
|
1623
1640
|
else {
|
|
@@ -1730,13 +1747,13 @@ function useForm(options) {
|
|
|
1730
1747
|
}
|
|
1731
1748
|
}
|
|
1732
1749
|
syncWithDebounce();
|
|
1733
|
-
if (nameOrNames === void 0) return
|
|
1750
|
+
if (nameOrNames === void 0) return deepClone(ctx.formData);
|
|
1734
1751
|
if (Array.isArray(nameOrNames)) {
|
|
1735
1752
|
const result = {};
|
|
1736
|
-
for (const fieldName of nameOrNames) result[fieldName] = get(ctx.formData, fieldName);
|
|
1753
|
+
for (const fieldName of nameOrNames) result[fieldName] = deepClone(get(ctx.formData, fieldName));
|
|
1737
1754
|
return result;
|
|
1738
1755
|
}
|
|
1739
|
-
return get(ctx.formData, nameOrNames);
|
|
1756
|
+
return deepClone(get(ctx.formData, nameOrNames));
|
|
1740
1757
|
}
|
|
1741
1758
|
function getFieldState(name) {
|
|
1742
1759
|
if (__DEV__) {
|
|
@@ -1770,11 +1787,7 @@ function useForm(options) {
|
|
|
1770
1787
|
}
|
|
1771
1788
|
if (options$1?.markAsSubmitted) ctx.submitCount.value++;
|
|
1772
1789
|
if (name === void 0) return await validate();
|
|
1773
|
-
if (Array.isArray(name))
|
|
1774
|
-
let allValid = true;
|
|
1775
|
-
for (const fieldName of name) if (!await validate(fieldName)) allValid = false;
|
|
1776
|
-
return allValid;
|
|
1777
|
-
}
|
|
1790
|
+
if (Array.isArray(name)) return (await Promise.all(name.map((fieldName) => validate(fieldName)))).every((isValid) => isValid);
|
|
1778
1791
|
return await validate(name);
|
|
1779
1792
|
}
|
|
1780
1793
|
const setFocusWrapper = (name) => setFocus(name);
|
|
@@ -1826,25 +1839,28 @@ function useFormContext() {
|
|
|
1826
1839
|
function useWatch(options = {}) {
|
|
1827
1840
|
const { control, name, defaultValue } = options;
|
|
1828
1841
|
const form = control ?? useFormContext();
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1842
|
+
if (name === void 0) return form.watch();
|
|
1843
|
+
if (Array.isArray(name)) {
|
|
1844
|
+
const watched$1 = form.watch(name);
|
|
1845
|
+
if (defaultValue === void 0) return watched$1;
|
|
1846
|
+
return computed(() => {
|
|
1847
|
+
const result = { ...watched$1.value };
|
|
1848
|
+
for (const fieldName of name) if (result[fieldName] === void 0) result[fieldName] = defaultValue;
|
|
1834
1849
|
return result;
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
const watched = form.watch(name);
|
|
1853
|
+
if (defaultValue === void 0) return watched;
|
|
1854
|
+
return computed(() => watched.value ?? defaultValue);
|
|
1838
1855
|
}
|
|
1839
1856
|
function useController(options) {
|
|
1840
1857
|
const { name, control, defaultValue } = options;
|
|
1841
1858
|
const form = control ?? useFormContext();
|
|
1842
1859
|
const elementRef = ref(null);
|
|
1843
1860
|
if (defaultValue !== void 0 && form.getValues(name) === void 0) form.setValue(name, defaultValue);
|
|
1861
|
+
const watchedValue = form.watch(name);
|
|
1844
1862
|
const value = computed({
|
|
1845
|
-
get: () =>
|
|
1846
|
-
return form.getValues(name) ?? defaultValue;
|
|
1847
|
-
},
|
|
1863
|
+
get: () => watchedValue.value ?? defaultValue,
|
|
1848
1864
|
set: (newValue) => {
|
|
1849
1865
|
form.setValue(name, newValue);
|
|
1850
1866
|
}
|
|
@@ -1903,7 +1919,22 @@ function useFormState(options = {}) {
|
|
|
1903
1919
|
return { [name]: fullState[name] };
|
|
1904
1920
|
});
|
|
1905
1921
|
}
|
|
1922
|
+
function useFieldError(options) {
|
|
1923
|
+
const form = options.control ?? useFormContext();
|
|
1924
|
+
return computed(() => {
|
|
1925
|
+
const error = get(form.formState.value.errors, options.name);
|
|
1926
|
+
if (!error) return void 0;
|
|
1927
|
+
if (typeof error === "string") return error;
|
|
1928
|
+
if (Array.isArray(error)) {
|
|
1929
|
+
if (__DEV__) console.warn(`[vue-hook-form] useFieldError('${options.name}') resolved to an array of per-item errors.\nuseFieldError only returns scalar error messages. Use formState.value.errors['${options.name}'] directly for item-level errors.`);
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
if (typeof error === "object" && "message" in error) return error.message;
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1906
1935
|
function isFieldError(error) {
|
|
1907
1936
|
return typeof error === "object" && error !== null && "type" in error && "message" in error && typeof error.type === "string" && typeof error.message === "string";
|
|
1908
1937
|
}
|
|
1909
|
-
export { FormContextKey, clearPathCache, get, isFieldError, provideForm, set, unset, useController, useForm, useFormContext, useFormState, useWatch };
|
|
1938
|
+
export { FormContextKey, clearPathCache, get, isFieldError, provideForm, set, unset, useController, useFieldError, useForm, useFormContext, useFormState, useWatch };
|
|
1939
|
+
|
|
1940
|
+
//# sourceMappingURL=vuehookform.js.map
|