@vuehookform/core 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.
@@ -0,0 +1,637 @@
1
+ import { computed, inject, provide, reactive, ref, shallowRef } from "vue";
2
+ function get(obj, path) {
3
+ if (!path) return obj;
4
+ const keys = path.split(".");
5
+ let result = obj;
6
+ for (const key of keys) {
7
+ if (result === null || result === void 0) return;
8
+ result = result[key];
9
+ }
10
+ return result;
11
+ }
12
+ function set(obj, path, value) {
13
+ if (!path) return;
14
+ const keys = path.split(".");
15
+ const UNSAFE_KEYS = [
16
+ "__proto__",
17
+ "constructor",
18
+ "prototype"
19
+ ];
20
+ if (keys.some((k) => UNSAFE_KEYS.includes(k))) return;
21
+ const lastKey = keys.pop();
22
+ let current = obj;
23
+ for (const key of keys) {
24
+ if (!(key in current) || typeof current[key] !== "object") {
25
+ const nextKey = keys[keys.indexOf(key) + 1];
26
+ current[key] = nextKey && /^\d+$/.test(nextKey) ? [] : {};
27
+ }
28
+ current = current[key];
29
+ }
30
+ current[lastKey] = value;
31
+ }
32
+ function unset(obj, path) {
33
+ if (!path) return;
34
+ const keys = path.split(".");
35
+ const lastKey = keys.pop();
36
+ let current = obj;
37
+ for (const key of keys) {
38
+ if (!(key in current)) return;
39
+ current = current[key];
40
+ }
41
+ delete current[lastKey];
42
+ }
43
+ var idCounter = 0;
44
+ function generateId() {
45
+ return `field_${Date.now()}_${idCounter++}`;
46
+ }
47
+ function createFormContext(options) {
48
+ const formData = reactive({});
49
+ const defaultValues = reactive({});
50
+ const isAsyncDefaults = typeof options.defaultValues === "function";
51
+ const isLoading = ref(isAsyncDefaults);
52
+ if (isAsyncDefaults) {
53
+ const asyncFn = options.defaultValues;
54
+ asyncFn().then((values) => {
55
+ Object.assign(defaultValues, values);
56
+ Object.assign(formData, values);
57
+ isLoading.value = false;
58
+ }).catch((error) => {
59
+ console.error("Failed to load async default values:", error);
60
+ isLoading.value = false;
61
+ });
62
+ } else if (options.defaultValues) {
63
+ Object.assign(defaultValues, options.defaultValues);
64
+ Object.assign(formData, defaultValues);
65
+ }
66
+ return {
67
+ formData,
68
+ defaultValues,
69
+ errors: shallowRef({}),
70
+ touchedFields: ref({}),
71
+ dirtyFields: ref({}),
72
+ isSubmitting: ref(false),
73
+ isLoading,
74
+ submitCount: ref(0),
75
+ fieldRefs: /* @__PURE__ */ new Map(),
76
+ fieldOptions: /* @__PURE__ */ new Map(),
77
+ fieldArrays: /* @__PURE__ */ new Map(),
78
+ debounceTimers: /* @__PURE__ */ new Map(),
79
+ validationRequestIds: /* @__PURE__ */ new Map(),
80
+ options
81
+ };
82
+ }
83
+ function clearFieldErrors(errors, fieldPath) {
84
+ const newErrors = { ...errors };
85
+ for (const key of Object.keys(newErrors)) if (key === fieldPath || key.startsWith(`${fieldPath}.`)) delete newErrors[key];
86
+ return newErrors;
87
+ }
88
+ function groupErrorsByPath(issues) {
89
+ const grouped = /* @__PURE__ */ new Map();
90
+ for (const issue of issues) {
91
+ const path = issue.path.join(".");
92
+ const existing = grouped.get(path) || [];
93
+ existing.push({
94
+ type: issue.code,
95
+ message: issue.message
96
+ });
97
+ grouped.set(path, existing);
98
+ }
99
+ return grouped;
100
+ }
101
+ function createFieldError(errors) {
102
+ if (errors.length === 1) return errors[0].message;
103
+ const types = {};
104
+ for (const err of errors) {
105
+ const existing = types[err.type];
106
+ if (existing) types[err.type] = Array.isArray(existing) ? [...existing, err.message] : [existing, err.message];
107
+ else types[err.type] = err.message;
108
+ }
109
+ return {
110
+ type: errors[0].type,
111
+ message: errors[0].message,
112
+ types
113
+ };
114
+ }
115
+ function createValidation(ctx) {
116
+ async function validate(fieldPath) {
117
+ const result = await ctx.options.schema.safeParseAsync(ctx.formData);
118
+ if (result.success) {
119
+ if (fieldPath) ctx.errors.value = clearFieldErrors(ctx.errors.value, fieldPath);
120
+ else ctx.errors.value = {};
121
+ return true;
122
+ }
123
+ const zodErrors = result.error.issues;
124
+ if (fieldPath) {
125
+ const fieldErrors = zodErrors.filter((issue) => {
126
+ const path = issue.path.join(".");
127
+ return path === fieldPath || path.startsWith(`${fieldPath}.`);
128
+ });
129
+ if (fieldErrors.length === 0) {
130
+ ctx.errors.value = clearFieldErrors(ctx.errors.value, fieldPath);
131
+ return true;
132
+ }
133
+ let newErrors$1 = clearFieldErrors(ctx.errors.value, fieldPath);
134
+ const grouped$1 = groupErrorsByPath(fieldErrors);
135
+ for (const [path, errors] of grouped$1) set(newErrors$1, path, createFieldError(errors));
136
+ ctx.errors.value = newErrors$1;
137
+ return false;
138
+ }
139
+ const newErrors = {};
140
+ const grouped = groupErrorsByPath(zodErrors);
141
+ for (const [path, errors] of grouped) set(newErrors, path, createFieldError(errors));
142
+ ctx.errors.value = newErrors;
143
+ return false;
144
+ }
145
+ return { validate };
146
+ }
147
+ function createFieldRegistration(ctx, validate) {
148
+ function register(name, registerOptions) {
149
+ const fieldRef = ref(null);
150
+ ctx.fieldRefs.set(name, fieldRef);
151
+ if (registerOptions) ctx.fieldOptions.set(name, registerOptions);
152
+ if (get(ctx.formData, name) === void 0) {
153
+ const defaultValue = get(ctx.defaultValues, name);
154
+ if (defaultValue !== void 0) set(ctx.formData, name, defaultValue);
155
+ }
156
+ const runCustomValidation = async (fieldName, value, requestId) => {
157
+ const fieldOpts = ctx.fieldOptions.get(fieldName);
158
+ if (!fieldOpts?.validate || fieldOpts.disabled) return;
159
+ const error = await fieldOpts.validate(value);
160
+ if (requestId !== ctx.validationRequestIds.get(fieldName)) return;
161
+ if (error) ctx.errors.value = {
162
+ ...ctx.errors.value,
163
+ [fieldName]: error
164
+ };
165
+ else {
166
+ const newErrors = { ...ctx.errors.value };
167
+ delete newErrors[fieldName];
168
+ ctx.errors.value = newErrors;
169
+ }
170
+ };
171
+ const onInput = async (e) => {
172
+ const target = e.target;
173
+ const value = target.type === "checkbox" ? target.checked : target.value;
174
+ set(ctx.formData, name, value);
175
+ ctx.dirtyFields.value = {
176
+ ...ctx.dirtyFields.value,
177
+ [name]: true
178
+ };
179
+ if (ctx.options.mode === "onChange" || ctx.options.mode === "onTouched" && ctx.touchedFields.value[name] || ctx.touchedFields.value[name] && ctx.options.reValidateMode === "onChange") await validate(name);
180
+ const fieldOpts = ctx.fieldOptions.get(name);
181
+ if (fieldOpts?.validate && !fieldOpts.disabled) {
182
+ const requestId = Date.now() + Math.random();
183
+ ctx.validationRequestIds.set(name, requestId);
184
+ const debounceMs = fieldOpts.validateDebounce || 0;
185
+ if (debounceMs > 0) {
186
+ const existingTimer = ctx.debounceTimers.get(name);
187
+ if (existingTimer) clearTimeout(existingTimer);
188
+ const timer = setTimeout(() => {
189
+ ctx.debounceTimers.delete(name);
190
+ runCustomValidation(name, value, requestId);
191
+ }, debounceMs);
192
+ ctx.debounceTimers.set(name, timer);
193
+ } else await runCustomValidation(name, value, requestId);
194
+ }
195
+ };
196
+ const onBlur = async (_e) => {
197
+ ctx.touchedFields.value = {
198
+ ...ctx.touchedFields.value,
199
+ [name]: true
200
+ };
201
+ if (ctx.options.mode === "onBlur" || ctx.options.mode === "onTouched" || ctx.submitCount.value > 0 && ctx.options.reValidateMode === "onBlur") await validate(name);
202
+ };
203
+ const refCallback = (el) => {
204
+ const previousEl = fieldRef.value;
205
+ fieldRef.value = el;
206
+ if (el && !registerOptions?.controlled && el instanceof HTMLInputElement) {
207
+ const value = get(ctx.formData, name);
208
+ if (value !== void 0) if (el.type === "checkbox") el.checked = value;
209
+ else el.value = value;
210
+ }
211
+ if (previousEl && !el) {
212
+ if (registerOptions?.shouldUnregister ?? ctx.options.shouldUnregister ?? false) {
213
+ unset(ctx.formData, name);
214
+ const newErrors = { ...ctx.errors.value };
215
+ delete newErrors[name];
216
+ ctx.errors.value = newErrors;
217
+ const newTouched = { ...ctx.touchedFields.value };
218
+ delete newTouched[name];
219
+ ctx.touchedFields.value = newTouched;
220
+ const newDirty = { ...ctx.dirtyFields.value };
221
+ delete newDirty[name];
222
+ ctx.dirtyFields.value = newDirty;
223
+ ctx.fieldRefs.delete(name);
224
+ ctx.fieldOptions.delete(name);
225
+ const timer = ctx.debounceTimers.get(name);
226
+ if (timer) {
227
+ clearTimeout(timer);
228
+ ctx.debounceTimers.delete(name);
229
+ }
230
+ ctx.validationRequestIds.delete(name);
231
+ }
232
+ }
233
+ };
234
+ return {
235
+ name,
236
+ ref: refCallback,
237
+ onInput,
238
+ onBlur,
239
+ ...registerOptions?.controlled && { value: computed({
240
+ get: () => get(ctx.formData, name),
241
+ set: (val) => {
242
+ set(ctx.formData, name, val);
243
+ ctx.dirtyFields.value = {
244
+ ...ctx.dirtyFields.value,
245
+ [name]: true
246
+ };
247
+ }
248
+ }) }
249
+ };
250
+ }
251
+ function unregister(name) {
252
+ ctx.fieldRefs.delete(name);
253
+ ctx.fieldOptions.delete(name);
254
+ const timer = ctx.debounceTimers.get(name);
255
+ if (timer) {
256
+ clearTimeout(timer);
257
+ ctx.debounceTimers.delete(name);
258
+ }
259
+ ctx.validationRequestIds.delete(name);
260
+ }
261
+ return {
262
+ register,
263
+ unregister
264
+ };
265
+ }
266
+ function createFieldArrayManager(ctx, validate) {
267
+ function fields(name) {
268
+ let fieldArray = ctx.fieldArrays.get(name);
269
+ if (!fieldArray) {
270
+ const existingValues = get(ctx.formData, name) || [];
271
+ fieldArray = {
272
+ items: ref([]),
273
+ values: existingValues
274
+ };
275
+ ctx.fieldArrays.set(name, fieldArray);
276
+ if (!get(ctx.formData, name)) set(ctx.formData, name, []);
277
+ }
278
+ const fa = fieldArray;
279
+ const createItem = (key) => ({
280
+ key,
281
+ get index() {
282
+ return fa.items.value.findIndex((item) => item.key === key);
283
+ },
284
+ remove() {
285
+ const currentIndex = fa.items.value.findIndex((item) => item.key === key);
286
+ if (currentIndex !== -1) removeAt(currentIndex);
287
+ }
288
+ });
289
+ if (fa.items.value.length === 0 && fa.values.length > 0) fa.items.value = fa.values.map(() => createItem(generateId()));
290
+ const append = (value) => {
291
+ const newValues = [...get(ctx.formData, name) || [], value];
292
+ set(ctx.formData, name, newValues);
293
+ fa.items.value = [...fa.items.value, createItem(generateId())];
294
+ ctx.dirtyFields.value = {
295
+ ...ctx.dirtyFields.value,
296
+ [name]: true
297
+ };
298
+ if (ctx.options.mode === "onChange") validate(name);
299
+ };
300
+ const prepend = (value) => {
301
+ insert(0, value);
302
+ };
303
+ const update = (index, value) => {
304
+ const currentValues = get(ctx.formData, name) || [];
305
+ if (index < 0 || index >= currentValues.length) return;
306
+ const newValues = [...currentValues];
307
+ newValues[index] = value;
308
+ set(ctx.formData, name, newValues);
309
+ ctx.dirtyFields.value = {
310
+ ...ctx.dirtyFields.value,
311
+ [name]: true
312
+ };
313
+ if (ctx.options.mode === "onChange") validate(name);
314
+ };
315
+ const removeAt = (index) => {
316
+ const newValues = (get(ctx.formData, name) || []).filter((_, i) => i !== index);
317
+ set(ctx.formData, name, newValues);
318
+ const keyToRemove = fa.items.value[index]?.key;
319
+ fa.items.value = fa.items.value.filter((item) => item.key !== keyToRemove);
320
+ ctx.dirtyFields.value = {
321
+ ...ctx.dirtyFields.value,
322
+ [name]: true
323
+ };
324
+ if (ctx.options.mode === "onChange") validate(name);
325
+ };
326
+ const insert = (index, value) => {
327
+ const currentValues = get(ctx.formData, name) || [];
328
+ const newValues = [
329
+ ...currentValues.slice(0, index),
330
+ value,
331
+ ...currentValues.slice(index)
332
+ ];
333
+ set(ctx.formData, name, newValues);
334
+ const newItem = createItem(generateId());
335
+ fa.items.value = [
336
+ ...fa.items.value.slice(0, index),
337
+ newItem,
338
+ ...fa.items.value.slice(index)
339
+ ];
340
+ ctx.dirtyFields.value = {
341
+ ...ctx.dirtyFields.value,
342
+ [name]: true
343
+ };
344
+ if (ctx.options.mode === "onChange") validate(name);
345
+ };
346
+ const swap = (indexA, indexB) => {
347
+ const newValues = [...get(ctx.formData, name) || []];
348
+ [newValues[indexA], newValues[indexB]] = [newValues[indexB], newValues[indexA]];
349
+ set(ctx.formData, name, newValues);
350
+ const newItems = [...fa.items.value];
351
+ const itemA = newItems[indexA];
352
+ const itemB = newItems[indexB];
353
+ if (itemA && itemB) {
354
+ newItems[indexA] = itemB;
355
+ newItems[indexB] = itemA;
356
+ fa.items.value = newItems;
357
+ }
358
+ ctx.dirtyFields.value = {
359
+ ...ctx.dirtyFields.value,
360
+ [name]: true
361
+ };
362
+ if (ctx.options.mode === "onChange") validate(name);
363
+ };
364
+ const move = (from, to) => {
365
+ const newValues = [...get(ctx.formData, name) || []];
366
+ const [removed] = newValues.splice(from, 1);
367
+ if (removed !== void 0) {
368
+ newValues.splice(to, 0, removed);
369
+ set(ctx.formData, name, newValues);
370
+ }
371
+ const newItems = [...fa.items.value];
372
+ const [removedItem] = newItems.splice(from, 1);
373
+ if (removedItem) {
374
+ newItems.splice(to, 0, removedItem);
375
+ fa.items.value = newItems;
376
+ }
377
+ ctx.dirtyFields.value = {
378
+ ...ctx.dirtyFields.value,
379
+ [name]: true
380
+ };
381
+ if (ctx.options.mode === "onChange") validate(name);
382
+ };
383
+ return {
384
+ value: fa.items.value,
385
+ append,
386
+ prepend,
387
+ remove: removeAt,
388
+ insert,
389
+ swap,
390
+ move,
391
+ update
392
+ };
393
+ }
394
+ return { fields };
395
+ }
396
+ function useForm(options) {
397
+ const ctx = createFormContext(options);
398
+ const { validate } = createValidation(ctx);
399
+ const { register, unregister } = createFieldRegistration(ctx, validate);
400
+ const { fields } = createFieldArrayManager(ctx, validate);
401
+ const formState = computed(() => ({
402
+ errors: ctx.errors.value,
403
+ isDirty: Object.keys(ctx.dirtyFields.value).some((k) => ctx.dirtyFields.value[k]),
404
+ dirtyFields: ctx.dirtyFields.value,
405
+ isValid: (ctx.submitCount.value > 0 || Object.keys(ctx.touchedFields.value).length > 0) && Object.keys(ctx.errors.value).length === 0,
406
+ isSubmitting: ctx.isSubmitting.value,
407
+ isLoading: ctx.isLoading.value,
408
+ touchedFields: ctx.touchedFields.value,
409
+ submitCount: ctx.submitCount.value
410
+ }));
411
+ function handleSubmit(onValid, onInvalid) {
412
+ return async (e) => {
413
+ e.preventDefault();
414
+ ctx.isSubmitting.value = true;
415
+ ctx.submitCount.value++;
416
+ try {
417
+ for (const [name, fieldRef] of ctx.fieldRefs.entries()) {
418
+ const el = fieldRef.value;
419
+ if (el) {
420
+ if (!ctx.fieldOptions.get(name)?.controlled) {
421
+ const value = el.type === "checkbox" ? el.checked : el.value;
422
+ set(ctx.formData, name, value);
423
+ }
424
+ }
425
+ }
426
+ if (await validate()) await onValid(ctx.formData);
427
+ else onInvalid?.(ctx.errors.value);
428
+ } finally {
429
+ ctx.isSubmitting.value = false;
430
+ }
431
+ };
432
+ }
433
+ function setValue(name, value) {
434
+ set(ctx.formData, name, value);
435
+ ctx.dirtyFields.value = {
436
+ ...ctx.dirtyFields.value,
437
+ [name]: true
438
+ };
439
+ const fieldRef = ctx.fieldRefs.get(name);
440
+ if (fieldRef?.value) {
441
+ const el = fieldRef.value;
442
+ if (el.type === "checkbox") el.checked = value;
443
+ else el.value = value;
444
+ }
445
+ if (options.mode === "onChange" || ctx.touchedFields.value[name]) validate(name);
446
+ }
447
+ function getValue(name) {
448
+ return get(ctx.formData, name);
449
+ }
450
+ function reset(values, resetOptions) {
451
+ const opts = resetOptions || {};
452
+ if (!opts.keepDefaultValues && values) Object.assign(ctx.defaultValues, values);
453
+ Object.keys(ctx.formData).forEach((key) => delete ctx.formData[key]);
454
+ const newValues = values || ctx.defaultValues;
455
+ Object.assign(ctx.formData, newValues);
456
+ if (!opts.keepErrors) ctx.errors.value = {};
457
+ if (!opts.keepTouched) ctx.touchedFields.value = {};
458
+ if (!opts.keepDirty) ctx.dirtyFields.value = {};
459
+ if (!opts.keepSubmitCount) ctx.submitCount.value = 0;
460
+ if (!opts.keepIsSubmitting) ctx.isSubmitting.value = false;
461
+ ctx.fieldArrays.clear();
462
+ for (const [name, fieldRef] of ctx.fieldRefs.entries()) {
463
+ const el = fieldRef.value;
464
+ if (el) {
465
+ const value = get(newValues, name);
466
+ if (value !== void 0) if (el.type === "checkbox") el.checked = value;
467
+ else el.value = value;
468
+ }
469
+ }
470
+ }
471
+ function watch(name) {
472
+ return computed(() => {
473
+ if (!name) return ctx.formData;
474
+ if (Array.isArray(name)) return name.reduce((acc, n) => {
475
+ acc[n] = get(ctx.formData, n);
476
+ return acc;
477
+ }, {});
478
+ return get(ctx.formData, name);
479
+ });
480
+ }
481
+ function clearErrors(name) {
482
+ if (name === void 0) {
483
+ ctx.errors.value = {};
484
+ return;
485
+ }
486
+ const fieldsToClean = Array.isArray(name) ? name : [name];
487
+ const newErrors = { ...ctx.errors.value };
488
+ for (const field of fieldsToClean) for (const key of Object.keys(newErrors)) if (key === field || key.startsWith(`${field}.`)) delete newErrors[key];
489
+ ctx.errors.value = newErrors;
490
+ }
491
+ function setError(name, error) {
492
+ const newErrors = { ...ctx.errors.value };
493
+ set(newErrors, name, error.type ? {
494
+ type: error.type,
495
+ message: error.message
496
+ } : error.message);
497
+ ctx.errors.value = newErrors;
498
+ }
499
+ function getValues(nameOrNames) {
500
+ for (const [name, fieldRef] of ctx.fieldRefs.entries()) {
501
+ const el = fieldRef.value;
502
+ if (el) {
503
+ if (!ctx.fieldOptions.get(name)?.controlled) {
504
+ const value = el.type === "checkbox" ? el.checked : el.value;
505
+ set(ctx.formData, name, value);
506
+ }
507
+ }
508
+ }
509
+ if (nameOrNames === void 0) return { ...ctx.formData };
510
+ if (Array.isArray(nameOrNames)) {
511
+ const result = {};
512
+ for (const fieldName of nameOrNames) result[fieldName] = get(ctx.formData, fieldName);
513
+ return result;
514
+ }
515
+ return get(ctx.formData, nameOrNames);
516
+ }
517
+ function getFieldState(name) {
518
+ const error = get(ctx.errors.value, name);
519
+ return {
520
+ isDirty: ctx.dirtyFields.value[name] === true,
521
+ isTouched: ctx.touchedFields.value[name] === true,
522
+ invalid: error !== void 0 && error !== null,
523
+ error
524
+ };
525
+ }
526
+ async function trigger(name) {
527
+ if (name === void 0) return await validate();
528
+ if (Array.isArray(name)) {
529
+ let allValid = true;
530
+ for (const fieldName of name) if (!await validate(fieldName)) allValid = false;
531
+ return allValid;
532
+ }
533
+ return await validate(name);
534
+ }
535
+ function setFocus(name, focusOptions) {
536
+ const fieldRef = ctx.fieldRefs.get(name);
537
+ if (!fieldRef?.value) return;
538
+ const el = fieldRef.value;
539
+ if (typeof el.focus === "function") {
540
+ el.focus();
541
+ if (focusOptions?.shouldSelect && el instanceof HTMLInputElement && typeof el.select === "function") el.select();
542
+ }
543
+ }
544
+ return {
545
+ register,
546
+ unregister,
547
+ handleSubmit,
548
+ formState,
549
+ fields,
550
+ setValue,
551
+ getValue,
552
+ reset,
553
+ watch,
554
+ validate,
555
+ clearErrors,
556
+ setError,
557
+ getValues,
558
+ getFieldState,
559
+ trigger,
560
+ setFocus
561
+ };
562
+ }
563
+ const FormContextKey = Symbol("FormContext");
564
+ function provideForm(methods) {
565
+ provide(FormContextKey, methods);
566
+ }
567
+ function useFormContext() {
568
+ const context = inject(FormContextKey);
569
+ if (!context) throw new Error("useFormContext must be used within a component tree where provideForm() has been called. Make sure to call provideForm(useForm({ schema })) in a parent component.");
570
+ return context;
571
+ }
572
+ function useWatch(options = {}) {
573
+ const { control, name, defaultValue } = options;
574
+ const form = control ?? useFormContext();
575
+ return computed(() => {
576
+ if (name === void 0) return form.getValues();
577
+ if (Array.isArray(name)) {
578
+ const result = {};
579
+ for (const fieldName of name) result[fieldName] = get(form.getValues(), fieldName) ?? defaultValue;
580
+ return result;
581
+ }
582
+ return get(form.getValues(), name) ?? defaultValue;
583
+ });
584
+ }
585
+ function useController(options) {
586
+ const { name, control, defaultValue } = options;
587
+ const form = control ?? useFormContext();
588
+ const elementRef = ref(null);
589
+ if (defaultValue !== void 0 && form.getValue(name) === void 0) form.setValue(name, defaultValue);
590
+ const value = computed({
591
+ get: () => {
592
+ return form.getValue(name) ?? defaultValue;
593
+ },
594
+ set: (newValue) => {
595
+ form.setValue(name, newValue);
596
+ }
597
+ });
598
+ const onChange = (newValue) => {
599
+ form.setValue(name, newValue);
600
+ };
601
+ const onBlur = () => {
602
+ form.trigger(name);
603
+ };
604
+ const refCallback = (el) => {
605
+ elementRef.value = el;
606
+ };
607
+ const fieldState = computed(() => {
608
+ return form.getFieldState(name);
609
+ });
610
+ return {
611
+ field: {
612
+ value,
613
+ name,
614
+ onChange,
615
+ onBlur,
616
+ ref: refCallback
617
+ },
618
+ fieldState
619
+ };
620
+ }
621
+ function useFormState(options = {}) {
622
+ const { control, name } = options;
623
+ const form = control ?? useFormContext();
624
+ return computed(() => {
625
+ const fullState = form.formState.value;
626
+ if (name === void 0) return { ...fullState };
627
+ if (Array.isArray(name)) {
628
+ const result = {};
629
+ for (const key of name) result[key] = fullState[key];
630
+ return result;
631
+ }
632
+ return { [name]: fullState[name] };
633
+ });
634
+ }
635
+ export { FormContextKey, provideForm, useController, useForm, useFormContext, useFormState, useWatch };
636
+
637
+ //# sourceMappingURL=vuehookform.js.map