@teamnovu/kit-vue-forms 0.1.10 → 0.1.12

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/index.js CHANGED
@@ -1,7 +1,7 @@
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 u, 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) {
@@ -21,9 +21,9 @@ function te(t, e, r) {
21
21
  const s = Array.isArray(e) ? e : I(e), o = s.at(-1);
22
22
  if (o) {
23
23
  const i = s.slice(0, -1).reduce(
24
- (p, h) => p[h],
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
28
  i[o] = r;
29
29
  } else {
@@ -32,12 +32,12 @@ function te(t, e, r) {
32
32
  t.value = r;
33
33
  }
34
34
  }
35
- const K = (t, e) => u({
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) {
@@ -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,61 +70,69 @@ 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
+ { flush: "sync" }
80
+ );
81
+ const r = D({
74
82
  value: t.value,
75
83
  path: t.path,
76
- initialValue: u(() => Object.freeze(g(t.initialValue))),
84
+ initialValue: e,
77
85
  errors: t.errors,
78
86
  touched: !1
79
- }), r = u(() => JSON.stringify(e.value) !== JSON.stringify(e.initialValue)), s = (c) => {
80
- e.value = c;
81
- }, o = () => {
82
- e.touched = !0;
87
+ }), s = d(() => JSON.stringify(r.value) !== JSON.stringify(r.initialValue)), o = (u) => {
88
+ r.value = u;
83
89
  }, i = () => {
84
- }, p = () => {
85
- e.value = g(e.initialValue), e.touched = !1, e.errors = [];
86
- }, h = (c) => {
87
- r.value || s(g(c)), e.initialValue = c;
88
- }, V = (c) => {
89
- e.errors = c;
90
- }, n = () => {
91
- e.errors = [];
92
- }, a = W(e);
90
+ r.touched = !0;
91
+ }, h = () => {
92
+ }, v = () => {
93
+ r.value = g(r.initialValue), r.touched = !1, r.errors = [];
94
+ }, V = (u) => {
95
+ s.value || o(g(u)), r.initialValue = u;
96
+ }, n = (u) => {
97
+ r.errors = u;
98
+ }, a = () => {
99
+ r.errors = [];
100
+ }, c = W(r);
93
101
  return {
94
- data: a.value,
95
- path: a.path,
96
- initialValue: a.initialValue,
97
- errors: a.errors,
98
- touched: a.touched,
99
- dirty: r,
100
- setData: s,
101
- setInitialData: h,
102
- onBlur: o,
103
- onFocus: i,
104
- reset: p,
105
- setErrors: V,
106
- clearErrors: n
102
+ data: c.value,
103
+ path: c.path,
104
+ initialValue: c.initialValue,
105
+ errors: c.errors,
106
+ touched: c.touched,
107
+ dirty: s,
108
+ setData: o,
109
+ setInitialData: V,
110
+ onBlur: i,
111
+ onFocus: h,
112
+ reset: v,
113
+ setErrors: n,
114
+ clearErrors: a
107
115
  };
108
116
  }
109
117
  function ie(t, e) {
110
118
  const r = /* @__PURE__ */ new Map(), s = q(/* @__PURE__ */ new Map()), o = (a) => {
111
- const c = d(a.path);
119
+ const c = f(a.path);
112
120
  s.set(c, a);
113
121
  }, i = (a) => {
114
122
  s.delete(a);
115
- }, p = (a) => {
123
+ }, h = (a) => {
116
124
  var c;
117
125
  r.has(a) ? (c = r.get(a)) == null || c.inc() : r.set(a, new ae(() => i(a)));
118
- }, h = (a) => {
126
+ }, v = (a) => {
119
127
  var c;
120
128
  r.has(a) && ((c = r.get(a)) == null || c.dec());
121
129
  }, V = (a) => {
122
130
  if (!s.has(a)) {
123
- const v = oe({
131
+ const u = oe({
124
132
  path: a,
125
133
  value: K(_(t, "data"), a),
126
- initialValue: u(() => P(t.initialData, a)),
127
- errors: u({
134
+ initialValue: d(() => P(t.initialData, a)),
135
+ errors: d({
128
136
  get() {
129
137
  return e.errors.value.propertyErrors[a] || [];
130
138
  },
@@ -133,15 +141,15 @@ function ie(t, e) {
133
141
  }
134
142
  })
135
143
  });
136
- o(v);
144
+ o(u);
137
145
  }
138
146
  const c = s.get(a);
139
- return p(a), H(() => {
140
- h(a);
147
+ return h(a), H(() => {
148
+ v(a);
141
149
  }), c;
142
150
  }, n = (a) => V(a.path);
143
151
  return {
144
- fields: u(() => [...s.values()]),
152
+ fields: d(() => [...s.values()]),
145
153
  getField: V,
146
154
  registerField: o,
147
155
  deregisterField: i,
@@ -149,7 +157,7 @@ function ie(t, e) {
149
157
  };
150
158
  }
151
159
  function ne(t) {
152
- const e = u(() => t.fields.value.some((s) => d(s.dirty))), r = u(() => t.fields.value.some((s) => d(s.touched)));
160
+ const e = d(() => t.fields.value.some((s) => f(s.dirty))), r = d(() => t.fields.value.some((s) => f(s.touched)));
153
161
  return {
154
162
  isDirty: e,
155
163
  isTouched: r
@@ -265,8 +273,8 @@ class fe {
265
273
  }
266
274
  class pe {
267
275
  constructor(e, r) {
268
- E(this, "schemaValidator");
269
- E(this, "functionValidator");
276
+ w(this, "schemaValidator");
277
+ w(this, "functionValidator");
270
278
  this.schema = e, this.validateFn = r, this.schemaValidator = new de(this.schema), this.functionValidator = new fe(this.validateFn);
271
279
  }
272
280
  async validate(e) {
@@ -281,26 +289,26 @@ class pe {
281
289
  }
282
290
  }
283
291
  function b(t) {
284
- return u(() => new pe(
285
- d(t.schema),
286
- d(t.validateFn)
292
+ return d(() => new pe(
293
+ f(t.schema),
294
+ f(t.validateFn)
287
295
  ));
288
296
  }
289
297
  function he(t, e) {
290
298
  const r = D({
291
- validators: k([b(e)]),
299
+ validators: j([b(e)]),
292
300
  isValidated: !1,
293
- errors: d(e.errors) ?? m.errors
301
+ errors: f(e.errors) ?? m.errors
294
302
  }), s = (n = m.errors) => {
295
- r.errors = S(d(e.errors) ?? m.errors, n);
303
+ r.errors = S(f(e.errors) ?? m.errors, n);
296
304
  };
297
- w(() => d(e.errors), async () => {
305
+ E(() => f(e.errors), async () => {
298
306
  if (r.isValidated) {
299
307
  const n = await i();
300
308
  s(n.errors);
301
309
  } else
302
310
  s();
303
- }, { immediate: !0 }), w(
311
+ }, { immediate: !0 }), E(
304
312
  [() => r.validators],
305
313
  async (n) => {
306
314
  if (r.isValidated)
@@ -311,8 +319,8 @@ function he(t, e) {
311
319
  r.errors = m.errors;
312
320
  },
313
321
  { immediate: !0 }
314
- ), w(() => t.data, () => {
315
- r.isValidated && p();
322
+ ), E(() => t.data, () => {
323
+ r.isValidated && h();
316
324
  });
317
325
  const o = (n) => {
318
326
  const a = O(n) ? n : b(n);
@@ -324,32 +332,32 @@ function he(t, e) {
324
332
  };
325
333
  async function i() {
326
334
  const n = await Promise.all(
327
- r.validators.filter((v) => d(v) !== void 0).map((v) => d(v).validate(t.data))
328
- ), a = n.every((v) => v.isValid);
335
+ r.validators.filter((u) => f(u) !== void 0).map((u) => f(u).validate(t.data))
336
+ ), a = n.every((u) => u.isValid);
329
337
  let { errors: c } = m;
330
338
  if (!a) {
331
- const v = n.map((F) => F.errors);
332
- c = S(...v);
339
+ const u = n.map((F) => F.errors);
340
+ c = S(...u);
333
341
  }
334
342
  return {
335
343
  errors: c,
336
344
  isValid: a
337
345
  };
338
346
  }
339
- const p = async () => {
347
+ const h = async () => {
340
348
  const n = await i();
341
349
  return s(n.errors), r.isValidated = !0, {
342
350
  isValid: !N(n.errors),
343
351
  errors: r.errors
344
352
  };
345
- }, h = u(() => !N(r.errors)), V = () => {
346
- r.isValidated = !1, r.errors = d(e.errors) ?? m.errors;
353
+ }, v = d(() => !N(r.errors)), V = () => {
354
+ r.isValidated = !1, r.errors = f(e.errors) ?? m.errors;
347
355
  };
348
356
  return {
349
357
  ...W(r),
350
- validateForm: p,
358
+ validateForm: h,
351
359
  defineValidator: o,
352
- isValid: h,
360
+ isValid: v,
353
361
  reset: V
354
362
  };
355
363
  }
@@ -377,65 +385,65 @@ class ve {
377
385
  }
378
386
  }
379
387
  function me(t, e, r) {
380
- const s = K(t.data, e), o = u(() => P(t.initialData.value, e)), i = (l) => ({
388
+ const s = K(t.data, e), o = d(() => P(t.initialData.value, e)), i = (l) => ({
381
389
  ...l,
382
- path: u(() => d(l.path).replace(e + ".", "")),
383
- setData: (f) => {
384
- l.setData(f);
390
+ path: d(() => f(l.path).replace(e + ".", "")),
391
+ setData: (p) => {
392
+ l.setData(p);
385
393
  }
386
- }), p = (l) => {
387
- const f = R(e, l), y = t.getField(f);
394
+ }), h = (l) => {
395
+ const p = R(e, l), y = t.getField(p);
388
396
  return y ? i(y) : {};
389
- }, h = (l) => {
390
- const f = R(e, l.path), y = t.defineField({
397
+ }, v = (l) => {
398
+ const p = R(e, l.path), y = t.defineField({
391
399
  ...l,
392
- path: f
400
+ path: p
393
401
  });
394
402
  return i(y);
395
- }, V = u(() => t.fields.value.filter((l) => {
396
- const f = l.path.value;
397
- return f.startsWith(e + ".") || f === e;
403
+ }, V = d(() => t.fields.value.filter((l) => {
404
+ const p = l.path.value;
405
+ return p.startsWith(e + ".") || p === e;
398
406
  }).map((l) => i(l))), n = () => t.fields.value.filter((l) => {
399
- const f = l.path.value;
400
- return f.startsWith(e + ".") || f === e;
401
- }), a = u(() => n().some((l) => l.dirty.value)), c = u(() => n().some((l) => l.touched.value)), v = u(() => t.isValid.value), F = u(() => t.isValidated.value), J = u(() => se(d(t.errors), e));
407
+ const p = l.path.value;
408
+ return p.startsWith(e + ".") || p === e;
409
+ }), 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));
402
410
  return {
403
411
  data: s,
404
412
  fields: V,
405
413
  initialData: o,
406
- defineField: h,
407
- getField: p,
414
+ defineField: v,
415
+ getField: h,
408
416
  isDirty: a,
409
417
  isTouched: c,
410
- isValid: v,
418
+ isValid: u,
411
419
  isValidated: F,
412
420
  errors: J,
413
421
  defineValidator: (l) => {
414
- const f = O(l) ? l : b(l), y = u(
415
- () => new ve(e, d(f))
422
+ const p = O(l) ? l : b(l), y = d(
423
+ () => new ve(e, f(p))
416
424
  );
417
- return t.defineValidator(y), f;
425
+ return t.defineValidator(y), p;
418
426
  },
419
427
  reset: () => n().forEach((l) => l.reset()),
420
428
  validateForm: () => t.validateForm(),
421
- getSubForm: (l, f) => {
429
+ getSubForm: (l, p) => {
422
430
  const y = R(e, l);
423
431
  return t.getSubForm(
424
432
  y,
425
- f
433
+ p
426
434
  );
427
435
  }
428
436
  };
429
437
  }
430
438
  function Pe(t) {
431
- const e = u(() => Object.freeze(g(t.initialData))), r = k(g(e)), s = D({
439
+ const e = d(() => Object.freeze(g(t.initialData))), r = j(g(e)), s = D({
432
440
  initialData: e,
433
441
  data: r
434
442
  });
435
- w(e, (a) => {
443
+ E(e, (a) => {
436
444
  s.data = g(a);
437
- });
438
- const o = he(s, t), i = ie(s, o), p = ne(i), h = () => {
445
+ }, { flush: "sync" });
446
+ const o = he(s, t), i = ie(s, o), h = ne(i), v = () => {
439
447
  r.value = g(e), o.reset(), i.fields.value.forEach(
440
448
  (a) => a.reset()
441
449
  );
@@ -446,8 +454,8 @@ function Pe(t) {
446
454
  const n = {
447
455
  ...i,
448
456
  ...o,
449
- ...p,
450
- reset: h,
457
+ ...h,
458
+ reset: v,
451
459
  getSubForm: V,
452
460
  initialData: _(s, "initialData"),
453
461
  data: _(s, "data")
@@ -467,7 +475,7 @@ const _e = /* @__PURE__ */ $({
467
475
  const e = t, r = e.form.defineField({
468
476
  path: e.path
469
477
  }), s = D(r);
470
- return (o, i) => j(o.$slots, "default", z(B(s)));
478
+ return (o, i) => A(o.$slots, "default", k(B(s)));
471
479
  }
472
480
  }), Se = /* @__PURE__ */ $({
473
481
  inheritAttrs: !1,
@@ -481,19 +489,19 @@ const _e = /* @__PURE__ */ $({
481
489
  setup(t) {
482
490
  return (e, r) => {
483
491
  const s = Y("Field");
484
- return C(), A(s, {
492
+ return M(), C(s, {
485
493
  form: e.form,
486
494
  path: e.path
487
495
  }, {
488
- default: M(({ errors: o, data: i, setData: p }) => [
489
- (C(), A(x(e.component), ee({ ...e.componentProps, ...e.$attrs }, {
496
+ default: z(({ errors: o, data: i, setData: h }) => [
497
+ (M(), C(x(e.component), ee({ ...e.componentProps, ...e.$attrs }, {
490
498
  "model-value": i,
491
499
  errors: o,
492
500
  name: e.path,
493
- "onUpdate:modelValue": p
501
+ "onUpdate:modelValue": h
494
502
  }), {
495
- default: M(() => [
496
- j(e.$slots, "default")
503
+ default: z(() => [
504
+ A(e.$slots, "default")
497
505
  ]),
498
506
  _: 2
499
507
  }, 1040, ["model-value", "errors", "name", "onUpdate:modelValue"]))
@@ -509,8 +517,8 @@ const _e = /* @__PURE__ */ $({
509
517
  path: {}
510
518
  },
511
519
  setup(t) {
512
- const e = t, r = u(() => e.form.getSubForm(e.path));
513
- return (s, o) => j(s.$slots, "default", z(B({ subform: r.value })));
520
+ const e = t, r = d(() => e.form.getSubForm(e.path));
521
+ return (s, o) => A(s.$slots, "default", k(B({ subform: r.value })));
514
522
  }
515
523
  });
516
524
  export {
@@ -13,6 +13,10 @@ 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
+ */
16
20
  setInitialData: (newData: T) => void;
17
21
  onBlur: () => void;
18
22
  onFocus: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnovu/kit-vue-forms",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
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,20 @@ 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
+ { flush: 'sync' },
22
+ )
23
+
14
24
  const state = reactive({
15
25
  value: options.value,
16
26
  path: options.path,
17
- initialValue: computed(() => Object.freeze(cloneRefValue(options.initialValue))),
27
+ initialValue,
18
28
  errors: options.errors,
19
29
  touched: false,
20
30
  })
@@ -41,10 +51,6 @@ export function useField<T, K extends string>(options: UseFieldOptions<T, K>): F
41
51
  state.errors = []
42
52
  }
43
53
 
44
- /**
45
- * Sets the initial data for the field. If the field is not dirty, it also updates the current data.
46
- * @param newData - The new initial data to set.
47
- */
48
54
  const setInitialData = (newData: T): void => {
49
55
  if (!dirty.value) {
50
56
  setData(cloneRefValue(newData))
@@ -28,7 +28,7 @@ export function useForm<T extends FormDataDefault>(options: UseFormOptions<T>) {
28
28
 
29
29
  watch(initialData, (newValue) => {
30
30
  state.data = cloneRefValue(newValue)
31
- })
31
+ }, { flush: 'sync' })
32
32
 
33
33
  const validationState = useValidation(state, options)
34
34
  const fieldRegistry = useFieldRegistry(state, validationState)
package/src/types/form.ts CHANGED
@@ -15,6 +15,10 @@ 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
+ */
18
22
  setInitialData: (newData: T) => void
19
23
  onBlur: () => void
20
24
  onFocus: () => 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
  })
@@ -290,4 +290,37 @@ describe('useForm', () => {
290
290
 
291
291
  expect(form.fields.value.length).toBe(0)
292
292
  })
293
+
294
+ it('it should take over the new initial data from the form', { timeout: 500 }, async () => {
295
+ const initialData = ref({
296
+ name: 'foo',
297
+ })
298
+
299
+ const form = useForm({
300
+ initialData,
301
+ })
302
+
303
+ const nameField = form.getField('name')
304
+
305
+ expect(form.isDirty.value).toBe(false)
306
+ expect(nameField.dirty.value).toBe(false)
307
+
308
+ nameField.setData('modified')
309
+
310
+ expect(form.isDirty.value).toBe(true)
311
+ expect(nameField.dirty.value).toBe(true)
312
+
313
+ initialData.value = {
314
+ name: 'bar',
315
+ }
316
+
317
+ expect(form.initialData.value.name).toBe('bar')
318
+ expect(nameField.initialValue.value).toBe('bar')
319
+ expect(nameField.data.value).toBe('bar')
320
+
321
+ nameField.setInitialData('another')
322
+
323
+ expect(nameField.initialValue.value).toBe('another')
324
+ expect(nameField.data.value).toBe('another')
325
+ })
293
326
  })