@teamnovu/kit-vue-forms 0.1.9 → 0.1.11

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.
@@ -19,6 +19,7 @@ declare const _default: <TData extends object, TPath extends Paths<TData>>(__VLS
19
19
  touched: boolean;
20
20
  dirty: boolean;
21
21
  setData: (newData: PickProps<TData, TPath>) => void;
22
+ setInitialData: (newData: PickProps<TData, TPath>) => void;
22
23
  onBlur: () => void;
23
24
  onFocus: () => void;
24
25
  reset: () => void;
package/dist/index.js CHANGED
@@ -1,43 +1,43 @@
1
1
  var T = Object.defineProperty;
2
2
  var G = (t, e, r) => e in t ? T(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
3
- var E = (t, e, r) => G(t, typeof e != "symbol" ? e + "" : e, r);
4
- import { toValue as L, toRaw as Z, computed as c, unref as d, isRef as O, reactive as D, toRefs as W, shallowReactive as q, toRef as _, onScopeDispose as H, ref as k, watch as w, getCurrentScope as Q, onBeforeUnmount as X, defineComponent as $, renderSlot as j, normalizeProps as z, guardReactiveProps as B, resolveComponent as Y, createBlock as A, openBlock as C, withCtx as M, resolveDynamicComponent as x, mergeProps as ee } from "vue";
3
+ var w = (t, e, r) => G(t, typeof e != "symbol" ? e + "" : e, r);
4
+ import { toValue as L, toRaw as Z, computed as d, unref as f, isRef as O, ref as j, watch as E, reactive as D, toRefs as W, shallowReactive as q, toRef as _, onScopeDispose as H, getCurrentScope as Q, onBeforeUnmount as X, defineComponent as $, renderSlot as A, normalizeProps as k, guardReactiveProps as B, resolveComponent as Y, createBlock as C, openBlock as M, withCtx as z, resolveDynamicComponent as x, mergeProps as ee } from "vue";
5
5
  import { cloneDeep as re } from "lodash-es";
6
6
  import "zod";
7
7
  function g(t) {
8
8
  const e = L(t), r = Z(e);
9
9
  return re(r);
10
10
  }
11
- function K(t) {
11
+ function I(t) {
12
12
  return t === "" ? [] : t.split(/\s*\.\s*/).filter(Boolean);
13
13
  }
14
14
  function P(t, e) {
15
- return (Array.isArray(e) ? e : K(e)).reduce(
15
+ return (Array.isArray(e) ? e : I(e)).reduce(
16
16
  (s, o) => s == null ? void 0 : s[o],
17
17
  t
18
18
  );
19
19
  }
20
20
  function te(t, e, r) {
21
- const s = Array.isArray(e) ? e : K(e), o = s.at(-1);
21
+ const s = Array.isArray(e) ? e : I(e), o = s.at(-1);
22
22
  if (o) {
23
- const n = s.slice(0, -1).reduce(
24
- (p, h) => p[h],
23
+ const i = s.slice(0, -1).reduce(
24
+ (h, v) => h[v],
25
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- d(t)
26
+ f(t)
27
27
  );
28
- n[o] = r;
28
+ i[o] = r;
29
29
  } else {
30
30
  if (!O(t))
31
31
  return;
32
32
  t.value = r;
33
33
  }
34
34
  }
35
- const U = (t, e) => c({
35
+ const K = (t, e) => d({
36
36
  get() {
37
- return P(d(t), d(e));
37
+ return P(f(t), f(e));
38
38
  },
39
39
  set(r) {
40
- te(t, d(e), r);
40
+ te(t, f(e), r);
41
41
  }
42
42
  });
43
43
  function R(t, e) {
@@ -48,7 +48,7 @@ function se(t, e) {
48
48
  return t;
49
49
  const r = `${e}.`, s = Object.fromEntries(
50
50
  Object.entries(t.propertyErrors).filter(([o]) => o.startsWith(r)).map(
51
- ([o, n]) => [o.slice(r.length), n]
51
+ ([o, i]) => [o.slice(r.length), i]
52
52
  )
53
53
  );
54
54
  return {
@@ -59,7 +59,7 @@ function se(t, e) {
59
59
  }
60
60
  class ae {
61
61
  constructor(e) {
62
- E(this, "rc", 1);
62
+ w(this, "rc", 1);
63
63
  this.drop = e;
64
64
  }
65
65
  inc() {
@@ -70,58 +70,68 @@ class ae {
70
70
  }
71
71
  }
72
72
  function oe(t) {
73
- const e = D({
73
+ const e = j(Object.freeze(g(t.initialValue)));
74
+ E(
75
+ () => f(t.initialValue),
76
+ (u) => {
77
+ e.value = Object.freeze(g(u));
78
+ }
79
+ );
80
+ const r = D({
74
81
  value: t.value,
75
82
  path: t.path,
76
- initialValue: c(() => Object.freeze(g(t.initialValue))),
83
+ initialValue: e,
77
84
  errors: t.errors,
78
85
  touched: !1
79
- }), r = c(() => JSON.stringify(e.value) !== JSON.stringify(e.initialValue)), s = (a) => {
80
- e.value = a;
81
- }, o = () => {
82
- e.touched = !0;
83
- }, n = () => {
84
- }, p = () => {
85
- e.value = g(e.initialValue), e.touched = !1, e.errors = [];
86
- }, h = (a) => {
87
- e.errors = a;
88
- }, V = () => {
89
- e.errors = [];
90
- }, i = W(e);
86
+ }), s = d(() => JSON.stringify(r.value) !== JSON.stringify(r.initialValue)), o = (u) => {
87
+ r.value = u;
88
+ }, i = () => {
89
+ r.touched = !0;
90
+ }, h = () => {
91
+ }, v = () => {
92
+ r.value = g(r.initialValue), r.touched = !1, r.errors = [];
93
+ }, V = (u) => {
94
+ s.value || o(g(u)), r.initialValue = u;
95
+ }, n = (u) => {
96
+ r.errors = u;
97
+ }, a = () => {
98
+ r.errors = [];
99
+ }, c = W(r);
91
100
  return {
92
- data: i.value,
93
- path: i.path,
94
- initialValue: i.initialValue,
95
- errors: i.errors,
96
- touched: i.touched,
97
- dirty: r,
98
- setData: s,
99
- onBlur: o,
100
- onFocus: n,
101
- reset: p,
102
- setErrors: h,
103
- clearErrors: V
101
+ data: c.value,
102
+ path: c.path,
103
+ initialValue: c.initialValue,
104
+ errors: c.errors,
105
+ touched: c.touched,
106
+ dirty: s,
107
+ setData: o,
108
+ setInitialData: V,
109
+ onBlur: i,
110
+ onFocus: h,
111
+ reset: v,
112
+ setErrors: n,
113
+ clearErrors: a
104
114
  };
105
115
  }
106
- function ne(t, e) {
116
+ function ie(t, e) {
107
117
  const r = /* @__PURE__ */ new Map(), s = q(/* @__PURE__ */ new Map()), o = (a) => {
108
- const u = d(a.path);
109
- s.set(u, a);
110
- }, n = (a) => {
118
+ const c = f(a.path);
119
+ s.set(c, a);
120
+ }, i = (a) => {
111
121
  s.delete(a);
112
- }, p = (a) => {
113
- var u;
114
- r.has(a) ? (u = r.get(a)) == null || u.inc() : r.set(a, new ae(() => n(a)));
115
122
  }, h = (a) => {
116
- var u;
117
- r.has(a) && ((u = r.get(a)) == null || u.dec());
123
+ var c;
124
+ r.has(a) ? (c = r.get(a)) == null || c.inc() : r.set(a, new ae(() => i(a)));
125
+ }, v = (a) => {
126
+ var c;
127
+ r.has(a) && ((c = r.get(a)) == null || c.dec());
118
128
  }, V = (a) => {
119
129
  if (!s.has(a)) {
120
- const v = oe({
130
+ const u = oe({
121
131
  path: a,
122
- value: U(_(t, "data"), a),
123
- initialValue: c(() => P(t.initialData, a)),
124
- errors: c({
132
+ value: K(_(t, "data"), a),
133
+ initialValue: d(() => P(t.initialData, a)),
134
+ errors: d({
125
135
  get() {
126
136
  return e.errors.value.propertyErrors[a] || [];
127
137
  },
@@ -130,23 +140,23 @@ function ne(t, e) {
130
140
  }
131
141
  })
132
142
  });
133
- o(v);
143
+ o(u);
134
144
  }
135
- const u = s.get(a);
136
- return p(a), H(() => {
137
- h(a);
138
- }), u;
139
- }, i = (a) => V(a.path);
145
+ const c = s.get(a);
146
+ return h(a), H(() => {
147
+ v(a);
148
+ }), c;
149
+ }, n = (a) => V(a.path);
140
150
  return {
141
- fields: c(() => [...s.values()]),
151
+ fields: d(() => [...s.values()]),
142
152
  getField: V,
143
153
  registerField: o,
144
- deregisterField: n,
145
- defineField: i
154
+ deregisterField: i,
155
+ defineField: n
146
156
  };
147
157
  }
148
- function ie(t) {
149
- const e = c(() => t.fields.value.some((s) => d(s.dirty))), r = c(() => t.fields.value.some((s) => d(s.touched)));
158
+ function ne(t) {
159
+ const e = d(() => t.fields.value.some((s) => f(s.dirty))), r = d(() => t.fields.value.some((s) => f(s.touched)));
150
160
  return {
151
161
  isDirty: e,
152
162
  isTouched: r
@@ -157,7 +167,7 @@ function le(t) {
157
167
  (e, r, s) => s.indexOf(e) === r
158
168
  );
159
169
  }
160
- function I(...t) {
170
+ function U(...t) {
161
171
  return t.slice(1).reduce((e, r) => {
162
172
  if (!e && !r)
163
173
  return;
@@ -172,10 +182,10 @@ function I(...t) {
172
182
  }
173
183
  function ce(...t) {
174
184
  return t.map((r) => Object.keys(r)).flat().reduce((r, s) => {
175
- const o = t.map((n) => n[s]).filter(Boolean);
185
+ const o = t.map((i) => i[s]).filter(Boolean);
176
186
  return {
177
187
  ...r,
178
- [s]: I(...o)
188
+ [s]: U(...o)
179
189
  };
180
190
  }, {});
181
191
  }
@@ -188,7 +198,7 @@ function S(...t) {
188
198
  const e = t[0];
189
199
  return t.length === 1 ? e : t.slice(1).reduce(
190
200
  (r, s) => ({
191
- general: I(r.general, s.general),
201
+ general: U(r.general, s.general),
192
202
  propertyErrors: ce(r.propertyErrors ?? {}, s.propertyErrors ?? {})
193
203
  }),
194
204
  e
@@ -201,10 +211,10 @@ function N(t) {
201
211
  }
202
212
  function ue(t) {
203
213
  const e = t.issues.filter((s) => s.path.length === 0).map((s) => s.message), r = t.issues.filter((s) => s.path.length > 0).reduce((s, o) => {
204
- const n = o.path.join(".");
214
+ const i = o.path.join(".");
205
215
  return {
206
216
  ...s,
207
- [n]: [...s[n] ?? [], o.message]
217
+ [i]: [...s[i] ?? [], o.message]
208
218
  };
209
219
  }, {});
210
220
  return {
@@ -262,8 +272,8 @@ class fe {
262
272
  }
263
273
  class pe {
264
274
  constructor(e, r) {
265
- E(this, "schemaValidator");
266
- E(this, "functionValidator");
275
+ w(this, "schemaValidator");
276
+ w(this, "functionValidator");
267
277
  this.schema = e, this.validateFn = r, this.schemaValidator = new de(this.schema), this.functionValidator = new fe(this.validateFn);
268
278
  }
269
279
  async validate(e) {
@@ -278,75 +288,75 @@ class pe {
278
288
  }
279
289
  }
280
290
  function b(t) {
281
- return c(() => new pe(
282
- d(t.schema),
283
- d(t.validateFn)
291
+ return d(() => new pe(
292
+ f(t.schema),
293
+ f(t.validateFn)
284
294
  ));
285
295
  }
286
296
  function he(t, e) {
287
297
  const r = D({
288
- validators: k([b(e)]),
298
+ validators: j([b(e)]),
289
299
  isValidated: !1,
290
- errors: d(e.errors) ?? m.errors
291
- }), s = (i = m.errors) => {
292
- r.errors = S(d(e.errors) ?? m.errors, i);
300
+ errors: f(e.errors) ?? m.errors
301
+ }), s = (n = m.errors) => {
302
+ r.errors = S(f(e.errors) ?? m.errors, n);
293
303
  };
294
- w(() => d(e.errors), async () => {
304
+ E(() => f(e.errors), async () => {
295
305
  if (r.isValidated) {
296
- const i = await n();
297
- s(i.errors);
306
+ const n = await i();
307
+ s(n.errors);
298
308
  } else
299
309
  s();
300
- }, { immediate: !0 }), w(
310
+ }, { immediate: !0 }), E(
301
311
  [() => r.validators],
302
- async (i) => {
312
+ async (n) => {
303
313
  if (r.isValidated)
304
- if (i) {
305
- const a = await n();
314
+ if (n) {
315
+ const a = await i();
306
316
  r.errors = a.errors;
307
317
  } else
308
318
  r.errors = m.errors;
309
319
  },
310
320
  { immediate: !0 }
311
- ), w(() => t.data, () => {
312
- r.isValidated && p();
321
+ ), E(() => t.data, () => {
322
+ r.isValidated && h();
313
323
  });
314
- const o = (i) => {
315
- const a = O(i) ? i : b(i);
324
+ const o = (n) => {
325
+ const a = O(n) ? n : b(n);
316
326
  return r.validators.push(a), Q() && X(() => {
317
327
  r.validators = r.validators.filter(
318
- (u) => u !== a
328
+ (c) => c !== a
319
329
  );
320
330
  }), a;
321
331
  };
322
- async function n() {
323
- const i = await Promise.all(
324
- r.validators.filter((v) => d(v) !== void 0).map((v) => d(v).validate(t.data))
325
- ), a = i.every((v) => v.isValid);
326
- let { errors: u } = m;
332
+ async function i() {
333
+ const n = await Promise.all(
334
+ r.validators.filter((u) => f(u) !== void 0).map((u) => f(u).validate(t.data))
335
+ ), a = n.every((u) => u.isValid);
336
+ let { errors: c } = m;
327
337
  if (!a) {
328
- const v = i.map((F) => F.errors);
329
- u = S(...v);
338
+ const u = n.map((F) => F.errors);
339
+ c = S(...u);
330
340
  }
331
341
  return {
332
- errors: u,
342
+ errors: c,
333
343
  isValid: a
334
344
  };
335
345
  }
336
- const p = async () => {
337
- const i = await n();
338
- return s(i.errors), r.isValidated = !0, {
339
- isValid: !N(i.errors),
346
+ const h = async () => {
347
+ const n = await i();
348
+ return s(n.errors), r.isValidated = !0, {
349
+ isValid: !N(n.errors),
340
350
  errors: r.errors
341
351
  };
342
- }, h = c(() => !N(r.errors)), V = () => {
343
- r.isValidated = !1, r.errors = d(e.errors) ?? m.errors;
352
+ }, v = d(() => !N(r.errors)), V = () => {
353
+ r.isValidated = !1, r.errors = f(e.errors) ?? m.errors;
344
354
  };
345
355
  return {
346
356
  ...W(r),
347
- validateForm: p,
357
+ validateForm: h,
348
358
  defineValidator: o,
349
- isValid: h,
359
+ isValid: v,
350
360
  reset: V
351
361
  };
352
362
  }
@@ -364,9 +374,9 @@ class ve {
364
374
  errors: {
365
375
  general: s.errors.general || [],
366
376
  propertyErrors: s.errors.propertyErrors ? Object.fromEntries(
367
- Object.entries(s.errors.propertyErrors).map(([o, n]) => [
377
+ Object.entries(s.errors.propertyErrors).map(([o, i]) => [
368
378
  R(this.path, o),
369
- n
379
+ i
370
380
  ])
371
381
  ) : {}
372
382
  }
@@ -374,82 +384,82 @@ class ve {
374
384
  }
375
385
  }
376
386
  function me(t, e, r) {
377
- const s = U(t.data, e), o = c(() => P(t.initialData.value, e)), n = (l) => ({
387
+ const s = K(t.data, e), o = d(() => P(t.initialData.value, e)), i = (l) => ({
378
388
  ...l,
379
- path: c(() => d(l.path).replace(e + ".", "")),
380
- setData: (f) => {
381
- l.setData(f);
389
+ path: d(() => f(l.path).replace(e + ".", "")),
390
+ setData: (p) => {
391
+ l.setData(p);
382
392
  }
383
- }), p = (l) => {
384
- const f = R(e, l), y = t.getField(f);
385
- return y ? n(y) : {};
386
- }, h = (l) => {
387
- const f = R(e, l.path), y = t.defineField({
393
+ }), h = (l) => {
394
+ const p = R(e, l), y = t.getField(p);
395
+ return y ? i(y) : {};
396
+ }, v = (l) => {
397
+ const p = R(e, l.path), y = t.defineField({
388
398
  ...l,
389
- path: f
399
+ path: p
390
400
  });
391
- return n(y);
392
- }, V = c(() => t.fields.value.filter((l) => {
393
- const f = l.path.value;
394
- return f.startsWith(e + ".") || f === e;
395
- }).map((l) => n(l))), i = () => t.fields.value.filter((l) => {
396
- const f = l.path.value;
397
- return f.startsWith(e + ".") || f === e;
398
- }), a = c(() => i().some((l) => l.dirty.value)), u = c(() => i().some((l) => l.touched.value)), v = c(() => t.isValid.value), F = c(() => t.isValidated.value), J = c(() => se(d(t.errors), e));
401
+ return i(y);
402
+ }, V = d(() => t.fields.value.filter((l) => {
403
+ const p = l.path.value;
404
+ return p.startsWith(e + ".") || p === e;
405
+ }).map((l) => i(l))), n = () => t.fields.value.filter((l) => {
406
+ const p = l.path.value;
407
+ return p.startsWith(e + ".") || p === e;
408
+ }), a = d(() => n().some((l) => l.dirty.value)), c = d(() => n().some((l) => l.touched.value)), u = d(() => t.isValid.value), F = d(() => t.isValidated.value), J = d(() => se(f(t.errors), e));
399
409
  return {
400
410
  data: s,
401
411
  fields: V,
402
412
  initialData: o,
403
- defineField: h,
404
- getField: p,
413
+ defineField: v,
414
+ getField: h,
405
415
  isDirty: a,
406
- isTouched: u,
407
- isValid: v,
416
+ isTouched: c,
417
+ isValid: u,
408
418
  isValidated: F,
409
419
  errors: J,
410
420
  defineValidator: (l) => {
411
- const f = O(l) ? l : b(l), y = c(
412
- () => new ve(e, d(f))
421
+ const p = O(l) ? l : b(l), y = d(
422
+ () => new ve(e, f(p))
413
423
  );
414
- return t.defineValidator(y), f;
424
+ return t.defineValidator(y), p;
415
425
  },
416
- reset: () => i().forEach((l) => l.reset()),
426
+ reset: () => n().forEach((l) => l.reset()),
417
427
  validateForm: () => t.validateForm(),
418
- getSubForm: (l, f) => {
428
+ getSubForm: (l, p) => {
419
429
  const y = R(e, l);
420
430
  return t.getSubForm(
421
431
  y,
422
- f
432
+ p
423
433
  );
424
434
  }
425
435
  };
426
436
  }
427
437
  function Pe(t) {
428
- const e = c(() => Object.freeze(g(t.initialData))), r = k(g(e)), s = D({
438
+ const e = d(() => Object.freeze(g(t.initialData))), r = j(g(e)), s = D({
429
439
  initialData: e,
430
440
  data: r
431
441
  });
432
- w(e, (a) => {
442
+ E(e, (a) => {
433
443
  s.data = g(a);
434
444
  });
435
- const o = he(s, t), n = ne(s, o), p = ie(n), h = () => {
436
- r.value = g(e), o.reset(), n.fields.value.forEach(
445
+ const o = he(s, t), i = ie(s, o), h = ne(i), v = () => {
446
+ r.value = g(e), o.reset(), i.fields.value.forEach(
437
447
  (a) => a.reset()
438
448
  );
439
449
  };
440
- function V(a, u) {
441
- return me(i, a);
450
+ function V(a, c) {
451
+ return me(n, a);
442
452
  }
443
- const i = {
444
- ...n,
453
+ const n = {
454
+ ...i,
445
455
  ...o,
446
- ...p,
447
- reset: h,
456
+ ...h,
457
+ reset: v,
448
458
  getSubForm: V,
449
459
  initialData: _(s, "initialData"),
450
460
  data: _(s, "data")
451
461
  };
452
- return i;
462
+ return n;
453
463
  }
454
464
  const _e = /* @__PURE__ */ $({
455
465
  __name: "Field",
@@ -464,7 +474,7 @@ const _e = /* @__PURE__ */ $({
464
474
  const e = t, r = e.form.defineField({
465
475
  path: e.path
466
476
  }), s = D(r);
467
- return (o, n) => j(o.$slots, "default", z(B(s)));
477
+ return (o, i) => A(o.$slots, "default", k(B(s)));
468
478
  }
469
479
  }), Se = /* @__PURE__ */ $({
470
480
  inheritAttrs: !1,
@@ -478,19 +488,19 @@ const _e = /* @__PURE__ */ $({
478
488
  setup(t) {
479
489
  return (e, r) => {
480
490
  const s = Y("Field");
481
- return C(), A(s, {
491
+ return M(), C(s, {
482
492
  form: e.form,
483
493
  path: e.path
484
494
  }, {
485
- default: M(({ errors: o, data: n, setData: p }) => [
486
- (C(), A(x(e.component), ee({ ...e.componentProps, ...e.$attrs }, {
487
- "model-value": n,
495
+ default: z(({ errors: o, data: i, setData: h }) => [
496
+ (M(), C(x(e.component), ee({ ...e.componentProps, ...e.$attrs }, {
497
+ "model-value": i,
488
498
  errors: o,
489
499
  name: e.path,
490
- "onUpdate:modelValue": p
500
+ "onUpdate:modelValue": h
491
501
  }), {
492
- default: M(() => [
493
- j(e.$slots, "default")
502
+ default: z(() => [
503
+ A(e.$slots, "default")
494
504
  ]),
495
505
  _: 2
496
506
  }, 1040, ["model-value", "errors", "name", "onUpdate:modelValue"]))
@@ -506,8 +516,8 @@ const _e = /* @__PURE__ */ $({
506
516
  path: {}
507
517
  },
508
518
  setup(t) {
509
- const e = t, r = c(() => e.form.getSubForm(e.path));
510
- return (s, o) => j(s.$slots, "default", z(B({ subform: r.value })));
519
+ const e = t, r = d(() => e.form.getSubForm(e.path));
520
+ return (s, o) => A(s.$slots, "default", k(B({ subform: r.value })));
511
521
  }
512
522
  });
513
523
  export {
@@ -13,6 +13,11 @@ export interface FormField<T, P extends string> {
13
13
  touched: Ref<boolean>;
14
14
  dirty: Ref<boolean>;
15
15
  setData: (newData: T) => void;
16
+ /**
17
+ * Sets the initial data for the field. If the field is not dirty, it also updates the current data.
18
+ * @param newData - The new initial data to set.
19
+ */
20
+ setInitialData: (newData: T) => void;
16
21
  onBlur: () => void;
17
22
  onFocus: () => void;
18
23
  reset: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnovu/kit-vue-forms",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,4 +1,4 @@
1
- import { computed, reactive, toRefs, type MaybeRef, type MaybeRefOrGetter, type WritableComputedRef } from 'vue'
1
+ import { computed, reactive, ref, toRefs, unref, watch, type MaybeRef, type MaybeRefOrGetter, type Ref, type WritableComputedRef } from 'vue'
2
2
  import type { FormField } from '../types/form'
3
3
  import type { ValidationErrorMessage, ValidationErrors } from '../types/validation'
4
4
  import { cloneRefValue } from '../utils/general'
@@ -11,10 +11,19 @@ export interface UseFieldOptions<T, K extends string> {
11
11
  }
12
12
 
13
13
  export function useField<T, K extends string>(options: UseFieldOptions<T, K>): FormField<T, K> {
14
+ const initialValue = ref(Object.freeze(cloneRefValue(options.initialValue))) as Ref<Readonly<T | undefined>>
15
+
16
+ watch(
17
+ () => unref(options.initialValue),
18
+ (newInitialValue) => {
19
+ initialValue.value = Object.freeze(cloneRefValue(newInitialValue))
20
+ },
21
+ )
22
+
14
23
  const state = reactive({
15
24
  value: options.value,
16
25
  path: options.path,
17
- initialValue: computed(() => Object.freeze(cloneRefValue(options.initialValue))),
26
+ initialValue,
18
27
  errors: options.errors,
19
28
  touched: false,
20
29
  })
@@ -41,6 +50,13 @@ export function useField<T, K extends string>(options: UseFieldOptions<T, K>): F
41
50
  state.errors = []
42
51
  }
43
52
 
53
+ const setInitialData = (newData: T): void => {
54
+ if (!dirty.value) {
55
+ setData(cloneRefValue(newData))
56
+ }
57
+ state.initialValue = newData
58
+ }
59
+
44
60
  const setErrors = (newErrors: ValidationErrorMessage[]): void => {
45
61
  state.errors = newErrors
46
62
  }
@@ -59,6 +75,7 @@ export function useField<T, K extends string>(options: UseFieldOptions<T, K>): F
59
75
  touched: refs.touched as FormField<T, K>['touched'],
60
76
  dirty,
61
77
  setData,
78
+ setInitialData,
62
79
  onBlur,
63
80
  onFocus,
64
81
  reset,
package/src/types/form.ts CHANGED
@@ -15,6 +15,11 @@ export interface FormField<T, P extends string> {
15
15
  touched: Ref<boolean>
16
16
  dirty: Ref<boolean>
17
17
  setData: (newData: T) => void
18
+ /**
19
+ * Sets the initial data for the field. If the field is not dirty, it also updates the current data.
20
+ * @param newData - The new initial data to set.
21
+ */
22
+ setInitialData: (newData: T) => void
18
23
  onBlur: () => void
19
24
  onFocus: () => void
20
25
  reset: () => void
@@ -160,10 +160,51 @@ describe('useField', () => {
160
160
 
161
161
  watch(initialValue, () => {
162
162
  resolve(true)
163
- }, { once: true, deep: true })
163
+ }, {
164
+ once: true,
165
+ deep: true,
166
+ })
164
167
 
165
168
  field.setData(['a', 'b', 'c', 'd'])
166
169
  expect(field.dirty.value).toBe(true)
167
170
  })
168
171
  }))
172
+
173
+ it('it should set the initial value if the field is not dirty', { timeout: 500 }, () => {
174
+ const field = useField({
175
+ initialValue: 'foo',
176
+ value: 'foo',
177
+ path: 'name',
178
+ })
179
+
180
+ expect(field.data.value).toBe('foo')
181
+ expect(field.path.value).toBe('name')
182
+ expect(field.touched.value).toBe(false)
183
+ expect(field.dirty.value).toBe(false)
184
+
185
+ field.setInitialData('bar')
186
+
187
+ expect(field.initialValue.value).toBe('bar')
188
+ expect(field.data.value).toBe('bar')
189
+ })
190
+
191
+ it('it should set the initial value but not the data if the field is dirty', { timeout: 500 }, () => {
192
+ const field = useField({
193
+ initialValue: 'foo',
194
+ value: 'foo',
195
+ path: 'name',
196
+ })
197
+
198
+ expect(field.data.value).toBe('foo')
199
+ expect(field.path.value).toBe('name')
200
+ expect(field.touched.value).toBe(false)
201
+ expect(field.dirty.value).toBe(false)
202
+
203
+ field.data.value = 'modified'
204
+
205
+ field.setInitialData('bar')
206
+
207
+ expect(field.initialValue.value).toBe('bar')
208
+ expect(field.data.value).toBe('modified')
209
+ })
169
210
  })