@vuehookform/core 0.3.0 → 0.3.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/README.md +1 -1
- package/dist/utils/devWarnings.d.ts +0 -4
- package/dist/vuehookform.cjs +234 -20
- package/dist/vuehookform.js +1 -1
- package/package.json +9 -17
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ A TypeScript-first form library for Vue 3, inspired by React Hook Form.
|
|
|
10
10
|
- **Field Arrays** - Dynamic lists with stable keys built-in
|
|
11
11
|
- **Performant** - Minimal re-renders using uncontrolled inputs
|
|
12
12
|
- **Zod Native** - First-class Zod integration for validation
|
|
13
|
-
- **Tiny Bundle** -
|
|
13
|
+
- **Tiny Bundle** - ~10kb gzipped, tree-shakable
|
|
14
14
|
- **UI Agnostic** - Works with any UI library or custom components
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
package/dist/vuehookform.cjs
CHANGED
|
@@ -53,11 +53,26 @@ function generateId() {
|
|
|
53
53
|
const random = Math.random().toString(36).substring(2, 11);
|
|
54
54
|
return `field_${Date.now()}_${idCounter++}_${random}`;
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
var proc = globalThis.process;
|
|
57
|
+
const __DEV__ = proc?.env?.NODE_ENV !== "production";
|
|
57
58
|
var warnedMessages = /* @__PURE__ */ new Set();
|
|
58
|
-
function warnOnce(message, key) {
|
|
59
|
-
|
|
59
|
+
function warnOnce(message, key) {
|
|
60
|
+
if (!__DEV__) return;
|
|
61
|
+
const cacheKey = key ?? message;
|
|
62
|
+
if (warnedMessages.has(cacheKey)) return;
|
|
63
|
+
warnedMessages.add(cacheKey);
|
|
64
|
+
console.warn(`[vue-hook-form] ${message}`);
|
|
65
|
+
}
|
|
66
|
+
function warn(message) {
|
|
67
|
+
if (!__DEV__) return;
|
|
68
|
+
console.warn(`[vue-hook-form] ${message}`);
|
|
69
|
+
}
|
|
60
70
|
function validatePathSyntax(path) {
|
|
71
|
+
if (!__DEV__) return null;
|
|
72
|
+
if (!path || path.trim() === "") return "Path cannot be empty";
|
|
73
|
+
if (path.startsWith(".") || path.endsWith(".") || path.includes("..")) return `Invalid path "${path}": contains empty segments`;
|
|
74
|
+
if (path.includes("[")) return `Invalid path "${path}": use dot notation (e.g., "items.0") instead of bracket notation (e.g., "items[0]")`;
|
|
75
|
+
if (/\s/.test(path)) return `Invalid path "${path}": paths cannot contain whitespace`;
|
|
61
76
|
return null;
|
|
62
77
|
}
|
|
63
78
|
function traverseSchemaPath(schema, path) {
|
|
@@ -94,16 +109,77 @@ function traverseSchemaPath(schema, path) {
|
|
|
94
109
|
return { schema: currentSchema };
|
|
95
110
|
}
|
|
96
111
|
function validatePathAgainstSchema(schema, path) {
|
|
97
|
-
return { valid: true };
|
|
112
|
+
if (!__DEV__) return { valid: true };
|
|
113
|
+
try {
|
|
114
|
+
const result = traverseSchemaPath(schema, path);
|
|
115
|
+
if ("error" in result) return {
|
|
116
|
+
valid: false,
|
|
117
|
+
reason: result.error,
|
|
118
|
+
availableFields: result.availableFields
|
|
119
|
+
};
|
|
120
|
+
return { valid: true };
|
|
121
|
+
} catch {
|
|
122
|
+
return { valid: true };
|
|
123
|
+
}
|
|
98
124
|
}
|
|
99
125
|
function isArrayFieldInSchema(schema, path) {
|
|
100
|
-
return null;
|
|
126
|
+
if (!__DEV__) return null;
|
|
127
|
+
try {
|
|
128
|
+
const result = traverseSchemaPath(schema, path);
|
|
129
|
+
if ("error" in result) return null;
|
|
130
|
+
return isZodArray(unwrapSchema(result.schema));
|
|
131
|
+
} catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function warnInvalidPath(fnName, path, reason) {
|
|
136
|
+
if (!__DEV__) return;
|
|
137
|
+
let message = `${fnName}("${path}"): ${reason}`;
|
|
138
|
+
if (reason.includes("bracket notation")) {
|
|
139
|
+
const fixedPath = path.replace(/\[(\d+)\]/g, ".$1");
|
|
140
|
+
message += `\n FIX: Use dot notation for array indices`;
|
|
141
|
+
message += `\n EXAMPLE: ${fnName}("${fixedPath}")`;
|
|
142
|
+
} else if (reason.includes("empty")) {
|
|
143
|
+
message += `\n FIX: Provide a non-empty field path`;
|
|
144
|
+
message += `\n EXAMPLE: ${fnName}("email") or ${fnName}("user.address.city")`;
|
|
145
|
+
} else if (reason.includes("whitespace")) {
|
|
146
|
+
const fixedPath = path.replace(/\s/g, "");
|
|
147
|
+
message += `\n FIX: Remove spaces from the field path`;
|
|
148
|
+
message += `\n EXAMPLE: ${fnName}("${fixedPath}")`;
|
|
149
|
+
} else if (reason.includes("empty segments")) {
|
|
150
|
+
const fixedPath = path.replace(/\.{2,}/g, ".").replace(/^\./, "").replace(/\.$/, "");
|
|
151
|
+
message += `\n FIX: Remove extra dots from the path`;
|
|
152
|
+
message += `\n EXAMPLE: ${fnName}("${fixedPath}")`;
|
|
153
|
+
}
|
|
154
|
+
warnOnce(message, `invalid-path:${fnName}:${path}`);
|
|
155
|
+
}
|
|
156
|
+
function warnPathNotInSchema(fnName, path, availableFields) {
|
|
157
|
+
if (!__DEV__) return;
|
|
158
|
+
let message = `${fnName}("${path}"): Path does not exist in your Zod schema.`;
|
|
159
|
+
message += `\n FIX: Check that the path matches your schema definition exactly (case-sensitive)`;
|
|
160
|
+
if (availableFields && availableFields.length > 0) {
|
|
161
|
+
const pathLower = path.toLowerCase();
|
|
162
|
+
const suggestions = availableFields.filter((f) => f.toLowerCase().includes(pathLower) || pathLower.includes(f.toLowerCase()));
|
|
163
|
+
if (suggestions.length > 0) message += `\n DID YOU MEAN: ${suggestions.slice(0, 3).map((s) => `"${s}"`).join(", ")}`;
|
|
164
|
+
message += `\n AVAILABLE: ${availableFields.slice(0, 8).join(", ")}${availableFields.length > 8 ? "..." : ""}`;
|
|
165
|
+
}
|
|
166
|
+
warnOnce(message, `path-not-in-schema:${fnName}:${path}`);
|
|
167
|
+
}
|
|
168
|
+
function warnFieldsOnNonArray(path) {
|
|
169
|
+
if (!__DEV__) return;
|
|
170
|
+
warnOnce(`fields("${path}"): Expected an array field, but this path does not point to an array in your schema. The fields() method is only for array fields. Use register() for non-array fields.`, `fields-non-array:${path}`);
|
|
171
|
+
}
|
|
172
|
+
function warnArrayOperationRejected(operation, path, reason, details) {
|
|
173
|
+
if (!__DEV__) return;
|
|
174
|
+
warn(`${operation}() on "${path}": ${{
|
|
175
|
+
maxLength: details ? `Would exceed maxLength (current: ${details.current}, max: ${details.limit})` : "Would exceed maxLength rule",
|
|
176
|
+
minLength: details ? `Would violate minLength (current: ${details.current}, min: ${details.limit})` : "Would violate minLength rule"
|
|
177
|
+
}[reason]}. Operation was silently ignored.`);
|
|
178
|
+
}
|
|
179
|
+
function warnArrayIndexOutOfBounds(operation, path, index, length) {
|
|
180
|
+
if (!__DEV__) return;
|
|
181
|
+
warn(`${operation}() on "${path}": Index ${index} is out of bounds (array length: ${length}). Operation was silently ignored.`);
|
|
101
182
|
}
|
|
102
|
-
function warnInvalidPath(fnName, path, reason) {}
|
|
103
|
-
function warnPathNotInSchema(fnName, path, availableFields) {}
|
|
104
|
-
function warnFieldsOnNonArray(path) {}
|
|
105
|
-
function warnArrayOperationRejected(operation, path, reason, details) {}
|
|
106
|
-
function warnArrayIndexOutOfBounds(operation, path, index, length) {}
|
|
107
183
|
function getDefProp(schema, prop) {
|
|
108
184
|
return schema.def[prop];
|
|
109
185
|
}
|
|
@@ -369,6 +445,12 @@ function createValidation(ctx) {
|
|
|
369
445
|
var validationRequestCounter = 0;
|
|
370
446
|
function createFieldRegistration(ctx, validate) {
|
|
371
447
|
function register(name, registerOptions) {
|
|
448
|
+
if (__DEV__) {
|
|
449
|
+
const syntaxError = validatePathSyntax(name);
|
|
450
|
+
if (syntaxError) warnInvalidPath("register", name, syntaxError);
|
|
451
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
452
|
+
if (!schemaResult.valid) warnPathNotInSchema("register", name, schemaResult.availableFields);
|
|
453
|
+
}
|
|
372
454
|
let fieldRef = ctx.fieldRefs.get(name);
|
|
373
455
|
if (!fieldRef) {
|
|
374
456
|
fieldRef = (0, vue.ref)(null);
|
|
@@ -535,6 +617,13 @@ function createFieldRegistration(ctx, validate) {
|
|
|
535
617
|
}
|
|
536
618
|
function createFieldArrayManager(ctx, validate, setFocus) {
|
|
537
619
|
function fields(name, options) {
|
|
620
|
+
if (__DEV__) {
|
|
621
|
+
const syntaxError = validatePathSyntax(name);
|
|
622
|
+
if (syntaxError) warnInvalidPath("fields", name, syntaxError);
|
|
623
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
624
|
+
if (!schemaResult.valid) warnPathNotInSchema("fields", name, schemaResult.availableFields);
|
|
625
|
+
if (isArrayFieldInSchema(ctx.options.schema, name) === false) warnFieldsOnNonArray(name);
|
|
626
|
+
}
|
|
538
627
|
let fieldArray = ctx.fieldArrays.get(name);
|
|
539
628
|
if (!fieldArray) {
|
|
540
629
|
const existingValues = get(ctx.formData, name) || [];
|
|
@@ -586,7 +675,13 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
586
675
|
const currentValues = get(ctx.formData, name) || [];
|
|
587
676
|
const insertIndex = currentValues.length;
|
|
588
677
|
const rules = fa.rules;
|
|
589
|
-
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value)
|
|
678
|
+
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {
|
|
679
|
+
if (__DEV__) warnArrayOperationRejected("append", name, "maxLength", {
|
|
680
|
+
current: currentValues.length,
|
|
681
|
+
limit: rules.maxLength.value
|
|
682
|
+
});
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
590
685
|
const newValues = [...currentValues, ...values];
|
|
591
686
|
set(ctx.formData, name, newValues);
|
|
592
687
|
const newItems = values.map(() => createItem(generateId()));
|
|
@@ -605,7 +700,13 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
605
700
|
if (values.length === 0) return true;
|
|
606
701
|
const currentValues = get(ctx.formData, name) || [];
|
|
607
702
|
const rules = fa.rules;
|
|
608
|
-
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value)
|
|
703
|
+
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {
|
|
704
|
+
if (__DEV__) warnArrayOperationRejected("prepend", name, "maxLength", {
|
|
705
|
+
current: currentValues.length,
|
|
706
|
+
limit: rules.maxLength.value
|
|
707
|
+
});
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
609
710
|
const newValues = [...values, ...currentValues];
|
|
610
711
|
set(ctx.formData, name, newValues);
|
|
611
712
|
const newItems = values.map(() => createItem(generateId()));
|
|
@@ -621,7 +722,10 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
621
722
|
};
|
|
622
723
|
const update = (index, value) => {
|
|
623
724
|
const currentValues = get(ctx.formData, name) || [];
|
|
624
|
-
if (index < 0 || index >= currentValues.length)
|
|
725
|
+
if (index < 0 || index >= currentValues.length) {
|
|
726
|
+
if (__DEV__) warnArrayIndexOutOfBounds("update", name, index, currentValues.length);
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
625
729
|
const newValues = [...currentValues];
|
|
626
730
|
newValues[index] = value;
|
|
627
731
|
set(ctx.formData, name, newValues);
|
|
@@ -634,9 +738,18 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
634
738
|
};
|
|
635
739
|
const removeAt = (index) => {
|
|
636
740
|
const currentValues = get(ctx.formData, name) || [];
|
|
637
|
-
if (index < 0 || index >= currentValues.length)
|
|
741
|
+
if (index < 0 || index >= currentValues.length) {
|
|
742
|
+
if (__DEV__) warnArrayIndexOutOfBounds("remove", name, index, currentValues.length);
|
|
743
|
+
return false;
|
|
744
|
+
}
|
|
638
745
|
const rules = fa.rules;
|
|
639
|
-
if (rules?.minLength && currentValues.length - 1 < rules.minLength.value)
|
|
746
|
+
if (rules?.minLength && currentValues.length - 1 < rules.minLength.value) {
|
|
747
|
+
if (__DEV__) warnArrayOperationRejected("remove", name, "minLength", {
|
|
748
|
+
current: currentValues.length,
|
|
749
|
+
limit: rules.minLength.value
|
|
750
|
+
});
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
640
753
|
const newValues = currentValues.filter((_, i) => i !== index);
|
|
641
754
|
set(ctx.formData, name, newValues);
|
|
642
755
|
const keyToRemove = fa.items.value[index]?.key;
|
|
@@ -654,7 +767,13 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
654
767
|
if (values.length === 0) return true;
|
|
655
768
|
const currentValues = get(ctx.formData, name) || [];
|
|
656
769
|
const rules = fa.rules;
|
|
657
|
-
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value)
|
|
770
|
+
if (rules?.maxLength && currentValues.length + values.length > rules.maxLength.value) {
|
|
771
|
+
if (__DEV__) warnArrayOperationRejected("insert", name, "maxLength", {
|
|
772
|
+
current: currentValues.length,
|
|
773
|
+
limit: rules.maxLength.value
|
|
774
|
+
});
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
658
777
|
const clampedIndex = Math.max(0, Math.min(index, currentValues.length));
|
|
659
778
|
const newValues = [
|
|
660
779
|
...currentValues.slice(0, clampedIndex),
|
|
@@ -679,7 +798,10 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
679
798
|
};
|
|
680
799
|
const swap = (indexA, indexB) => {
|
|
681
800
|
const currentValues = get(ctx.formData, name) || [];
|
|
682
|
-
if (indexA < 0 || indexB < 0 || indexA >= currentValues.length || indexB >= currentValues.length)
|
|
801
|
+
if (indexA < 0 || indexB < 0 || indexA >= currentValues.length || indexB >= currentValues.length) {
|
|
802
|
+
if (__DEV__) warnArrayIndexOutOfBounds("swap", name, indexA < 0 || indexA >= currentValues.length ? indexA : indexB, currentValues.length);
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
683
805
|
const newValues = [...currentValues];
|
|
684
806
|
[newValues[indexA], newValues[indexB]] = [newValues[indexB], newValues[indexA]];
|
|
685
807
|
set(ctx.formData, name, newValues);
|
|
@@ -701,7 +823,10 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
701
823
|
};
|
|
702
824
|
const move = (from, to) => {
|
|
703
825
|
const currentValues = get(ctx.formData, name) || [];
|
|
704
|
-
if (from < 0 || from >= currentValues.length || to < 0)
|
|
826
|
+
if (from < 0 || from >= currentValues.length || to < 0) {
|
|
827
|
+
if (__DEV__) warnArrayIndexOutOfBounds("move", name, from < 0 || from >= currentValues.length ? from : to, currentValues.length);
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
705
830
|
const newValues = [...currentValues];
|
|
706
831
|
const [removed] = newValues.splice(from, 1);
|
|
707
832
|
if (removed !== void 0) {
|
|
@@ -738,7 +863,13 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
738
863
|
};
|
|
739
864
|
const removeAll = () => {
|
|
740
865
|
const rules = fa.rules;
|
|
741
|
-
if (rules?.minLength && rules.minLength.value > 0)
|
|
866
|
+
if (rules?.minLength && rules.minLength.value > 0) {
|
|
867
|
+
if (__DEV__) warnArrayOperationRejected("removeAll", name, "minLength", {
|
|
868
|
+
current: fa.items.value.length,
|
|
869
|
+
limit: rules.minLength.value
|
|
870
|
+
});
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
742
873
|
set(ctx.formData, name, []);
|
|
743
874
|
fa.items.value = [];
|
|
744
875
|
rebuildIndexCache();
|
|
@@ -755,7 +886,13 @@ function createFieldArrayManager(ctx, validate, setFocus) {
|
|
|
755
886
|
if (validIndices.length === 0) return true;
|
|
756
887
|
const rules = fa.rules;
|
|
757
888
|
const remainingCount = currentValues.length - validIndices.length;
|
|
758
|
-
if (rules?.minLength && remainingCount < rules.minLength.value)
|
|
889
|
+
if (rules?.minLength && remainingCount < rules.minLength.value) {
|
|
890
|
+
if (__DEV__) warnArrayOperationRejected("removeMany", name, "minLength", {
|
|
891
|
+
current: currentValues.length,
|
|
892
|
+
limit: rules.minLength.value
|
|
893
|
+
});
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
759
896
|
const sortedIndices = [...new Set(validIndices)].sort((a, b) => b - a);
|
|
760
897
|
const indicesToRemove = new Set(sortedIndices);
|
|
761
898
|
const newValues = currentValues.filter((_, i) => !indicesToRemove.has(i));
|
|
@@ -829,6 +966,14 @@ function useForm(options) {
|
|
|
829
966
|
const { validate, clearAllPendingErrors } = createValidation(ctx);
|
|
830
967
|
const { register, unregister } = createFieldRegistration(ctx, validate);
|
|
831
968
|
function setFocus(name, focusOptions) {
|
|
969
|
+
if (__DEV__) {
|
|
970
|
+
const syntaxError = validatePathSyntax(name);
|
|
971
|
+
if (syntaxError) warnInvalidPath("setFocus", name, syntaxError);
|
|
972
|
+
else {
|
|
973
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
974
|
+
if (!schemaResult.valid) warnPathNotInSchema("setFocus", name, schemaResult.availableFields);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
832
977
|
const fieldRef = ctx.fieldRefs.get(name);
|
|
833
978
|
if (!fieldRef?.value) return;
|
|
834
979
|
const el = fieldRef.value;
|
|
@@ -891,6 +1036,14 @@ function useForm(options) {
|
|
|
891
1036
|
};
|
|
892
1037
|
}
|
|
893
1038
|
function setValue(name, value, setValueOptions) {
|
|
1039
|
+
if (__DEV__) {
|
|
1040
|
+
const syntaxError = validatePathSyntax(name);
|
|
1041
|
+
if (syntaxError) warnInvalidPath("setValue", name, syntaxError);
|
|
1042
|
+
else {
|
|
1043
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
1044
|
+
if (!schemaResult.valid) warnPathNotInSchema("setValue", name, schemaResult.availableFields);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
894
1047
|
set(ctx.formData, name, value);
|
|
895
1048
|
if (setValueOptions?.shouldDirty !== false) markFieldDirty(ctx.dirtyFields, name);
|
|
896
1049
|
if (setValueOptions?.shouldTouch) markFieldTouched(ctx.touchedFields, name);
|
|
@@ -927,6 +1080,14 @@ function useForm(options) {
|
|
|
927
1080
|
}
|
|
928
1081
|
}
|
|
929
1082
|
function resetField(name, resetFieldOptions) {
|
|
1083
|
+
if (__DEV__) {
|
|
1084
|
+
const syntaxError = validatePathSyntax(name);
|
|
1085
|
+
if (syntaxError) warnInvalidPath("resetField", name, syntaxError);
|
|
1086
|
+
else {
|
|
1087
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
1088
|
+
if (!schemaResult.valid) warnPathNotInSchema("resetField", name, schemaResult.availableFields);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
930
1091
|
const opts = resetFieldOptions || {};
|
|
931
1092
|
ctx.resetGeneration.value++;
|
|
932
1093
|
const errorTimer = ctx.errorDelayTimers.get(name);
|
|
@@ -949,6 +1110,17 @@ function useForm(options) {
|
|
|
949
1110
|
}
|
|
950
1111
|
}
|
|
951
1112
|
function watch$1(name) {
|
|
1113
|
+
if (__DEV__ && name) {
|
|
1114
|
+
const names = Array.isArray(name) ? name : [name];
|
|
1115
|
+
for (const n of names) {
|
|
1116
|
+
const syntaxError = validatePathSyntax(n);
|
|
1117
|
+
if (syntaxError) warnInvalidPath("watch", n, syntaxError);
|
|
1118
|
+
else {
|
|
1119
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, n);
|
|
1120
|
+
if (!schemaResult.valid) warnPathNotInSchema("watch", n, schemaResult.availableFields);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
952
1124
|
return (0, vue.computed)(() => {
|
|
953
1125
|
if (!name) return ctx.formData;
|
|
954
1126
|
if (Array.isArray(name)) {
|
|
@@ -960,6 +1132,18 @@ function useForm(options) {
|
|
|
960
1132
|
});
|
|
961
1133
|
}
|
|
962
1134
|
function clearErrors(name) {
|
|
1135
|
+
if (__DEV__ && name && !String(name).startsWith("root")) {
|
|
1136
|
+
const names = Array.isArray(name) ? name : [name];
|
|
1137
|
+
for (const n of names) {
|
|
1138
|
+
if (String(n).startsWith("root")) continue;
|
|
1139
|
+
const syntaxError = validatePathSyntax(n);
|
|
1140
|
+
if (syntaxError) warnInvalidPath("clearErrors", n, syntaxError);
|
|
1141
|
+
else {
|
|
1142
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, n);
|
|
1143
|
+
if (!schemaResult.valid) warnPathNotInSchema("clearErrors", n, schemaResult.availableFields);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
963
1147
|
if (name === void 0) {
|
|
964
1148
|
ctx.errors.value = {};
|
|
965
1149
|
return;
|
|
@@ -998,6 +1182,17 @@ function useForm(options) {
|
|
|
998
1182
|
return get(mergedErrors, fieldPath);
|
|
999
1183
|
}
|
|
1000
1184
|
function getValues(nameOrNames) {
|
|
1185
|
+
if (__DEV__ && nameOrNames) {
|
|
1186
|
+
const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames];
|
|
1187
|
+
for (const n of names) {
|
|
1188
|
+
const syntaxError = validatePathSyntax(n);
|
|
1189
|
+
if (syntaxError) warnInvalidPath("getValues", n, syntaxError);
|
|
1190
|
+
else {
|
|
1191
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, n);
|
|
1192
|
+
if (!schemaResult.valid) warnPathNotInSchema("getValues", n, schemaResult.availableFields);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1001
1196
|
syncUncontrolledInputs(ctx.fieldRefs, ctx.fieldOptions, ctx.formData);
|
|
1002
1197
|
if (nameOrNames === void 0) return { ...ctx.formData };
|
|
1003
1198
|
if (Array.isArray(nameOrNames)) {
|
|
@@ -1008,6 +1203,14 @@ function useForm(options) {
|
|
|
1008
1203
|
return get(ctx.formData, nameOrNames);
|
|
1009
1204
|
}
|
|
1010
1205
|
function getFieldState(name) {
|
|
1206
|
+
if (__DEV__) {
|
|
1207
|
+
const syntaxError = validatePathSyntax(name);
|
|
1208
|
+
if (syntaxError) warnInvalidPath("getFieldState", name, syntaxError);
|
|
1209
|
+
else {
|
|
1210
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, name);
|
|
1211
|
+
if (!schemaResult.valid) warnPathNotInSchema("getFieldState", name, schemaResult.availableFields);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1011
1214
|
const error = get(ctx.errors.value, name);
|
|
1012
1215
|
return {
|
|
1013
1216
|
isDirty: ctx.dirtyFields.value[name] === true,
|
|
@@ -1017,6 +1220,17 @@ function useForm(options) {
|
|
|
1017
1220
|
};
|
|
1018
1221
|
}
|
|
1019
1222
|
async function trigger(name) {
|
|
1223
|
+
if (__DEV__ && name) {
|
|
1224
|
+
const names = Array.isArray(name) ? name : [name];
|
|
1225
|
+
for (const n of names) {
|
|
1226
|
+
const syntaxError = validatePathSyntax(n);
|
|
1227
|
+
if (syntaxError) warnInvalidPath("trigger", n, syntaxError);
|
|
1228
|
+
else {
|
|
1229
|
+
const schemaResult = validatePathAgainstSchema(ctx.options.schema, n);
|
|
1230
|
+
if (!schemaResult.valid) warnPathNotInSchema("trigger", n, schemaResult.availableFields);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1020
1234
|
if (name === void 0) return await validate();
|
|
1021
1235
|
if (Array.isArray(name)) {
|
|
1022
1236
|
let allValid = true;
|
package/dist/vuehookform.js
CHANGED
|
@@ -52,7 +52,7 @@ function generateId() {
|
|
|
52
52
|
const random = Math.random().toString(36).substring(2, 11);
|
|
53
53
|
return `field_${Date.now()}_${idCounter++}_${random}`;
|
|
54
54
|
}
|
|
55
|
-
const __DEV__ =
|
|
55
|
+
const __DEV__ = globalThis.process?.env?.NODE_ENV !== "production";
|
|
56
56
|
var warnedMessages = /* @__PURE__ */ new Set();
|
|
57
57
|
function warnOnce(message, key) {
|
|
58
58
|
if (!__DEV__) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuehookform/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "TypeScript-first form library for Vue 3, inspired by React Hook Form. Form-level state management with Zod validation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/vuehookform.cjs",
|
|
@@ -21,22 +21,19 @@
|
|
|
21
21
|
"node": "^20.19.0 || >=22.12.0"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
|
-
"
|
|
25
|
-
"build": "run-p type-check
|
|
26
|
-
"
|
|
27
|
-
"build
|
|
28
|
-
"preview": "
|
|
29
|
-
"build-only": "vite build",
|
|
24
|
+
"build:lib": "vite build --config vite.config.lib.ts",
|
|
25
|
+
"build": "run-p type-check build:lib",
|
|
26
|
+
"docs": "vitepress dev docs",
|
|
27
|
+
"docs:build": "vitepress build docs",
|
|
28
|
+
"docs:preview": "vitepress preview docs",
|
|
30
29
|
"type-check": "vue-tsc --build",
|
|
31
30
|
"lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
|
|
32
31
|
"lint:eslint": "eslint . --fix --cache",
|
|
33
32
|
"lint": "run-s lint:*",
|
|
34
|
-
"format": "prettier --write --experimental-cli
|
|
33
|
+
"format": "prettier --write --experimental-cli lib/ docs/",
|
|
35
34
|
"test": "vitest",
|
|
36
35
|
"test:run": "vitest run",
|
|
37
36
|
"test:coverage": "vitest run --coverage",
|
|
38
|
-
"prepublishOnly": "npm run build:lib",
|
|
39
|
-
"postversion": "git push && git push --tags",
|
|
40
37
|
"prepare": "husky"
|
|
41
38
|
},
|
|
42
39
|
"repository": {
|
|
@@ -70,7 +67,6 @@
|
|
|
70
67
|
},
|
|
71
68
|
"devDependencies": {
|
|
72
69
|
"@prettier/plugin-oxc": "^0.0.5",
|
|
73
|
-
"@tailwindcss/vite": "^4.1.18",
|
|
74
70
|
"@tsconfig/node24": "^24.0.3",
|
|
75
71
|
"@types/node": "^24.10.1",
|
|
76
72
|
"@vitejs/plugin-vue": "^6.0.2",
|
|
@@ -85,20 +81,16 @@
|
|
|
85
81
|
"husky": "^9.1.7",
|
|
86
82
|
"jiti": "^2.6.1",
|
|
87
83
|
"lint-staged": "^16.2.7",
|
|
88
|
-
"material-icons": "^1.13.14",
|
|
89
|
-
"material-symbols": "^0.40.2",
|
|
90
84
|
"npm-run-all2": "^8.0.4",
|
|
85
|
+
"oxc-minify": "^0.105.0",
|
|
91
86
|
"oxlint": "~1.29.0",
|
|
92
|
-
"pinia": "^3.0.4",
|
|
93
87
|
"prettier": "3.6.2",
|
|
94
|
-
"tailwindcss": "^4.1.18",
|
|
95
88
|
"typescript": "~5.9.0",
|
|
96
89
|
"vite": "npm:rolldown-vite@latest",
|
|
97
|
-
"vite-plugin-compression2": "^2.4.0",
|
|
98
90
|
"vite-plugin-dts": "^4.5.4",
|
|
91
|
+
"vitepress": "^2.0.0-alpha.15",
|
|
99
92
|
"vitest": "^4.0.16",
|
|
100
93
|
"vue": "^3.5.25",
|
|
101
|
-
"vue-router": "^4.6.3",
|
|
102
94
|
"vue-tsc": "^3.1.5",
|
|
103
95
|
"zod": "^4.2.1"
|
|
104
96
|
},
|