@teamnovu/kit-vue-forms 0.1.2 → 0.1.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/dist/index.js CHANGED
@@ -1,77 +1,89 @@
1
1
  var T = Object.defineProperty;
2
- var G = (e, r, t) => r in e ? T(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t;
3
- var R = (e, r, t) => G(e, typeof r != "symbol" ? r + "" : r, t);
4
- import { toValue as L, toRaw as Z, computed as u, unref as d, reactive as g, toRefs as N, onUnmounted as q, markRaw as H, toRef as D, ref as W, watch as E, isRef as z, getCurrentScope as Q, onBeforeUnmount as X, defineComponent as S, renderSlot as j, normalizeProps as M, guardReactiveProps as U, resolveComponent as Y, createBlock as O, openBlock as $, withCtx as A, resolveDynamicComponent as x, mergeProps as rr } from "vue";
5
- import { cloneDeep as er } from "lodash-es";
2
+ var G = (r, e, t) => e in r ? T(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
+ var E = (r, e, t) => G(r, typeof e != "symbol" ? e + "" : e, t);
4
+ import { toValue as L, toRaw as Z, computed as d, unref as f, reactive as R, toRefs as N, shallowReactive as q, toRef as _, onScopeDispose as H, ref as W, watch as F, isRef as k, getCurrentScope as Q, onBeforeUnmount as X, defineComponent as j, renderSlot as O, normalizeProps as z, guardReactiveProps as B, resolveComponent as Y, createBlock as $, openBlock as A, withCtx as C, resolveDynamicComponent as x, mergeProps as ee } from "vue";
5
+ import { cloneDeep as re } from "lodash-es";
6
6
  import "zod";
7
- function y(e) {
8
- const r = L(e), t = Z(r);
9
- return er(t);
7
+ function y(r) {
8
+ const e = L(r), t = Z(e);
9
+ return re(t);
10
10
  }
11
- function k(e) {
12
- return e === "" ? [] : e.split(/\s*\.\s*/).filter(Boolean);
11
+ function K(r) {
12
+ return r === "" ? [] : r.split(/\s*\.\s*/).filter(Boolean);
13
13
  }
14
- function w(e, r) {
15
- return (Array.isArray(r) ? r : k(r)).reduce(
16
- (a, s) => a == null ? void 0 : a[s],
17
- e
14
+ function D(r, e) {
15
+ return (Array.isArray(e) ? e : K(e)).reduce(
16
+ (s, o) => s == null ? void 0 : s[o],
17
+ r
18
18
  );
19
19
  }
20
- function tr(e, r, t) {
21
- const a = Array.isArray(r) ? r : k(r);
22
- if (a.length === 0)
20
+ function te(r, e, t) {
21
+ const s = Array.isArray(e) ? e : K(e);
22
+ if (s.length === 0)
23
23
  throw new Error("Path cannot be empty");
24
- const s = a.at(-1), o = a.slice(0, -1).reduce(
25
- (h, l) => h[l],
24
+ const o = s.at(-1), n = s.slice(0, -1).reduce(
25
+ (h, v) => h[v],
26
26
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
- e
27
+ r
28
28
  );
29
- o[s] = t;
29
+ n[o] = t;
30
30
  }
31
- const B = (e, r) => u({
31
+ const U = (r, e) => d({
32
32
  get() {
33
- return w(d(e), d(r));
33
+ return D(f(r), f(e));
34
34
  },
35
35
  set(t) {
36
- tr(d(e), d(r), t);
36
+ te(f(r), f(e), t);
37
37
  }
38
38
  });
39
- function F(e, r) {
40
- return !e && !r ? "" : !e && r ? r : !r && e ? e : `${e}.${r}`;
39
+ function w(r, e) {
40
+ return !r && !e ? "" : !r && e ? e : !e && r ? r : `${r}.${e}`;
41
41
  }
42
- function ar(e, r) {
43
- if (!r)
44
- return e;
45
- const t = `${r}.`, a = Object.fromEntries(
46
- Object.entries(e.propertyErrors).filter(([s]) => s.startsWith(t)).map(
47
- ([s, o]) => [s.slice(t.length), o]
42
+ function se(r, e) {
43
+ if (!e)
44
+ return r;
45
+ const t = `${e}.`, s = Object.fromEntries(
46
+ Object.entries(r.propertyErrors).filter(([o]) => o.startsWith(t)).map(
47
+ ([o, n]) => [o.slice(t.length), n]
48
48
  )
49
49
  );
50
50
  return {
51
- general: e.general,
51
+ general: r.general,
52
52
  // Keep general errors
53
- propertyErrors: a
53
+ propertyErrors: s
54
54
  };
55
55
  }
56
- function sr(e) {
57
- const r = g({
58
- value: e.value,
59
- path: e.path,
60
- initialValue: u(() => Object.freeze(y(e.initialValue))),
61
- errors: e.errors,
56
+ class ae {
57
+ constructor(e) {
58
+ E(this, "rc", 1);
59
+ this.drop = e;
60
+ }
61
+ inc() {
62
+ this.rc += 1;
63
+ }
64
+ dec() {
65
+ this.rc > 0 && (this.rc -= 1, this.rc === 0 && this.drop && this.drop());
66
+ }
67
+ }
68
+ function oe(r) {
69
+ const e = R({
70
+ value: r.value,
71
+ path: r.path,
72
+ initialValue: d(() => Object.freeze(y(r.initialValue))),
73
+ errors: r.errors,
62
74
  touched: !1
63
- }), t = u(() => JSON.stringify(r.value) !== JSON.stringify(r.initialValue)), a = (f) => {
64
- r.value = f;
65
- }, s = () => {
66
- r.touched = !0;
75
+ }), t = d(() => JSON.stringify(e.value) !== JSON.stringify(e.initialValue)), s = (a) => {
76
+ e.value = a;
67
77
  }, o = () => {
68
- }, h = () => {
69
- r.value = y(r.initialValue), r.touched = !1, r.errors = [];
70
- }, l = (f) => {
71
- r.errors = f;
78
+ e.touched = !0;
72
79
  }, n = () => {
73
- r.errors = [];
74
- }, c = N(r);
80
+ }, h = () => {
81
+ e.value = y(e.initialValue), e.touched = !1, e.errors = [];
82
+ }, v = (a) => {
83
+ e.errors = a;
84
+ }, l = () => {
85
+ e.errors = [];
86
+ }, c = N(e);
75
87
  return {
76
88
  data: c.value,
77
89
  path: c.path,
@@ -79,116 +91,120 @@ function sr(e) {
79
91
  errors: c.errors,
80
92
  touched: c.touched,
81
93
  dirty: t,
82
- setData: a,
83
- onBlur: s,
84
- onFocus: o,
94
+ setData: s,
95
+ onBlur: o,
96
+ onFocus: n,
85
97
  reset: h,
86
- setErrors: l,
87
- clearErrors: n
98
+ setErrors: v,
99
+ clearErrors: l
88
100
  };
89
101
  }
90
- function or(e, r) {
91
- const t = g({}), a = (l) => {
92
- const n = d(l.path);
93
- t[n] = H(l);
94
- }, s = (l) => {
95
- delete t[l];
96
- }, o = (l) => {
97
- if (!t[l]) {
98
- const n = sr({
99
- path: l,
100
- value: B(D(e, "data"), l),
101
- initialValue: u(() => w(e.initialData, l)),
102
- errors: u({
102
+ function ne(r, e) {
103
+ const t = /* @__PURE__ */ new Map(), s = q(/* @__PURE__ */ new Map()), o = (a) => {
104
+ const u = f(a.path);
105
+ s.set(u, a);
106
+ }, n = (a) => {
107
+ s.delete(a);
108
+ }, h = (a) => {
109
+ var u;
110
+ t.has(a) ? (u = t.get(a)) == null || u.inc() : t.set(a, new ae(() => n(a)));
111
+ }, v = (a) => {
112
+ var u;
113
+ t.has(a) && ((u = t.get(a)) == null || u.dec());
114
+ }, l = (a) => {
115
+ if (!s.has(a)) {
116
+ const g = oe({
117
+ path: a,
118
+ value: U(_(r, "data"), a),
119
+ initialValue: d(() => D(r.initialData, a)),
120
+ errors: d({
103
121
  get() {
104
- return r.errors.value.propertyErrors[l] || [];
122
+ return e.errors.value.propertyErrors[a] || [];
105
123
  },
106
- set(c) {
107
- r.errors.value.propertyErrors[l] = c;
124
+ set(P) {
125
+ e.errors.value.propertyErrors[a] = P;
108
126
  }
109
127
  })
110
128
  });
111
- return a(n), n;
129
+ o(g);
112
130
  }
113
- return t[l];
114
- }, h = (l) => {
115
- const n = o(l.path);
116
- return q(() => {
117
- s(d(n.path));
118
- }), n;
119
- };
131
+ const u = s.get(a);
132
+ return h(a), H(() => {
133
+ v(a);
134
+ }), u;
135
+ }, c = (a) => l(a.path);
120
136
  return {
121
- fields: u(() => Object.values(t)),
122
- getField: o,
123
- registerField: a,
124
- deregisterField: s,
125
- defineField: h
137
+ fields: d(() => [...s.values()]),
138
+ getField: l,
139
+ registerField: o,
140
+ deregisterField: n,
141
+ defineField: c
126
142
  };
127
143
  }
128
- function nr(e) {
129
- const r = u(() => e.fields.value.some((a) => d(a.dirty))), t = u(() => e.fields.value.some((a) => d(a.touched)));
144
+ function ie(r) {
145
+ const e = d(() => r.fields.value.some((s) => f(s.dirty))), t = d(() => r.fields.value.some((s) => f(s.touched)));
130
146
  return {
131
- isDirty: r,
147
+ isDirty: e,
132
148
  isTouched: t
133
149
  };
134
150
  }
135
- function ir(e) {
136
- return e.filter(
137
- (r, t, a) => a.indexOf(r) === t
151
+ function le(r) {
152
+ return r.filter(
153
+ (e, t, s) => s.indexOf(e) === t
138
154
  );
139
155
  }
140
- function K(...e) {
141
- return e.slice(1).reduce((r, t) => {
142
- if (!r && !t)
156
+ function I(...r) {
157
+ return r.slice(1).reduce((e, t) => {
158
+ if (!e && !t)
143
159
  return;
144
- const a = ((t == null ? void 0 : t.length) ?? 0) > 0;
145
- if (!r && ((t == null ? void 0 : t.length) ?? 0) > 0)
160
+ const s = ((t == null ? void 0 : t.length) ?? 0) > 0;
161
+ if (!e && ((t == null ? void 0 : t.length) ?? 0) > 0)
146
162
  return t;
147
- if (!a)
148
- return r;
149
- const s = (r ?? []).concat(t);
150
- return ir(s);
151
- }, e[0]);
163
+ if (!s)
164
+ return e;
165
+ const o = (e ?? []).concat(t);
166
+ return le(o);
167
+ }, r[0]);
152
168
  }
153
- function lr(...e) {
154
- return e.map((t) => Object.keys(t)).flat().reduce((t, a) => {
155
- const s = e.map((o) => o[a]).filter(Boolean);
169
+ function ce(...r) {
170
+ return r.map((t) => Object.keys(t)).flat().reduce((t, s) => {
171
+ const o = r.map((n) => n[s]).filter(Boolean);
156
172
  return {
157
173
  ...t,
158
- [a]: K(...s)
174
+ [s]: I(...o)
159
175
  };
160
176
  }, {});
161
177
  }
162
- function _(...e) {
163
- if (!e.length)
178
+ function S(...r) {
179
+ if (!r.length)
164
180
  return {
165
181
  general: [],
166
182
  propertyErrors: {}
167
183
  };
168
- const r = e[0];
169
- return e.length === 1 ? r : e.slice(1).reduce(
170
- (t, a) => ({
171
- general: K(t.general, a.general),
172
- propertyErrors: lr(t.propertyErrors ?? {}, a.propertyErrors ?? {})
184
+ const e = r[0];
185
+ return r.length === 1 ? e : r.slice(1).reduce(
186
+ (t, s) => ({
187
+ general: I(t.general, s.general),
188
+ propertyErrors: ce(t.propertyErrors ?? {}, s.propertyErrors ?? {})
173
189
  }),
174
- r
190
+ e
175
191
  );
176
192
  }
177
- function C(e) {
178
- var a;
179
- const r = (((a = e.general) == null ? void 0 : a.length) ?? 0) > 0, t = Object.entries(e.propertyErrors).filter(([, s]) => s == null ? void 0 : s.length).length > 0;
180
- return r || t;
193
+ function M(r) {
194
+ var s;
195
+ const e = (((s = r.general) == null ? void 0 : s.length) ?? 0) > 0, t = Object.entries(r.propertyErrors).filter(([, o]) => o == null ? void 0 : o.length).length > 0;
196
+ return e || t;
181
197
  }
182
- function cr(e) {
183
- const r = e.issues.filter((a) => a.path.length === 0).map((a) => a.message), t = e.issues.filter((a) => a.path.length > 0).reduce((a, s) => {
184
- const o = s.path.join(".");
198
+ function ue(r) {
199
+ const e = r.issues.filter((s) => s.path.length === 0).map((s) => s.message), t = r.issues.filter((s) => s.path.length > 0).reduce((s, o) => {
200
+ const n = o.path.join(".");
185
201
  return {
186
- ...a,
187
- [o]: [...a[o] ?? [], s.message]
202
+ ...s,
203
+ [n]: [...s[n] ?? [], o.message]
188
204
  };
189
205
  }, {});
190
206
  return {
191
- general: r,
207
+ general: e,
192
208
  propertyErrors: t
193
209
  };
194
210
  }
@@ -199,35 +215,35 @@ const m = {
199
215
  propertyErrors: {}
200
216
  }
201
217
  };
202
- class ur {
203
- constructor(r) {
204
- this.schema = r;
218
+ class de {
219
+ constructor(e) {
220
+ this.schema = e;
205
221
  }
206
- async validate(r) {
222
+ async validate(e) {
207
223
  if (!this.schema)
208
224
  return m;
209
- const t = await this.schema.safeParseAsync(r);
225
+ const t = await this.schema.safeParseAsync(e);
210
226
  if (t.success)
211
227
  return m;
212
- const a = cr(t.error);
228
+ const s = ue(t.error);
213
229
  return {
214
230
  isValid: !1,
215
231
  errors: {
216
- general: a.general ?? [],
217
- propertyErrors: a.propertyErrors ?? {}
232
+ general: s.general ?? [],
233
+ propertyErrors: s.propertyErrors ?? {}
218
234
  }
219
235
  };
220
236
  }
221
237
  }
222
- class dr {
223
- constructor(r) {
224
- this.validateFn = r;
238
+ class fe {
239
+ constructor(e) {
240
+ this.validateFn = e;
225
241
  }
226
- async validate(r) {
242
+ async validate(e) {
227
243
  if (!this.validateFn)
228
244
  return m;
229
245
  try {
230
- const t = await this.validateFn(r);
246
+ const t = await this.validateFn(e);
231
247
  return t.isValid ? m : t;
232
248
  } catch (t) {
233
249
  return {
@@ -240,192 +256,192 @@ class dr {
240
256
  }
241
257
  }
242
258
  }
243
- class fr {
244
- constructor(r, t) {
245
- R(this, "schemaValidator");
246
- R(this, "functionValidator");
247
- this.schema = r, this.validateFn = t, this.schemaValidator = new ur(this.schema), this.functionValidator = new dr(this.validateFn);
259
+ class pe {
260
+ constructor(e, t) {
261
+ E(this, "schemaValidator");
262
+ E(this, "functionValidator");
263
+ this.schema = e, this.validateFn = t, this.schemaValidator = new de(this.schema), this.functionValidator = new fe(this.validateFn);
248
264
  }
249
- async validate(r) {
250
- const [t, a] = await Promise.all([
251
- this.schemaValidator.validate(r),
252
- this.functionValidator.validate(r)
265
+ async validate(e) {
266
+ const [t, s] = await Promise.all([
267
+ this.schemaValidator.validate(e),
268
+ this.functionValidator.validate(e)
253
269
  ]);
254
270
  return {
255
- isValid: t.isValid && a.isValid,
256
- errors: _(t.errors, a.errors)
271
+ isValid: t.isValid && s.isValid,
272
+ errors: S(t.errors, s.errors)
257
273
  };
258
274
  }
259
275
  }
260
- function b(e) {
261
- return u(() => new fr(
262
- d(e.schema),
263
- d(e.validateFn)
276
+ function b(r) {
277
+ return d(() => new pe(
278
+ f(r.schema),
279
+ f(r.validateFn)
264
280
  ));
265
281
  }
266
- function pr(e, r) {
267
- const t = g({
268
- validators: W([b(r)]),
282
+ function he(r, e) {
283
+ const t = R({
284
+ validators: W([b(e)]),
269
285
  isValidated: !1,
270
- errors: d(r.errors) ?? m.errors
286
+ errors: f(e.errors) ?? m.errors
271
287
  });
272
- E(() => d(r.errors), async () => {
273
- const n = await s();
274
- o(n.errors);
275
- }, { immediate: !0 }), E(
288
+ F(() => f(e.errors), async () => {
289
+ const l = await o();
290
+ n(l.errors);
291
+ }, { immediate: !0 }), F(
276
292
  [() => t.validators],
277
- async (n) => {
293
+ async (l) => {
278
294
  if (t.isValidated)
279
- if (n) {
280
- const c = await s();
295
+ if (l) {
296
+ const c = await o();
281
297
  t.errors = c.errors;
282
298
  } else
283
299
  t.errors = m.errors;
284
300
  },
285
301
  { immediate: !0 }
286
- ), E(() => e.data, () => {
302
+ ), F(() => r.data, () => {
287
303
  t.isValidated && h();
288
304
  });
289
- const a = (n) => {
290
- const c = z(n) ? n : b(n);
305
+ const s = (l) => {
306
+ const c = k(l) ? l : b(l);
291
307
  return t.validators.push(c), Q() && X(() => {
292
308
  t.validators = t.validators.filter(
293
- (f) => f !== c
309
+ (a) => a !== c
294
310
  );
295
311
  }), c;
296
312
  };
297
- async function s() {
298
- const n = await Promise.all(
299
- t.validators.filter((v) => d(v) !== void 0).map((v) => d(v).validate(e.data))
300
- ), c = n.every((v) => v.isValid);
301
- let { errors: f } = m;
313
+ async function o() {
314
+ const l = await Promise.all(
315
+ t.validators.filter((u) => f(u) !== void 0).map((u) => f(u).validate(r.data))
316
+ ), c = l.every((u) => u.isValid);
317
+ let { errors: a } = m;
302
318
  if (!c) {
303
- const v = n.map((P) => P.errors);
304
- f = _(...v);
319
+ const u = l.map((g) => g.errors);
320
+ a = S(...u);
305
321
  }
306
322
  return {
307
- errors: f,
323
+ errors: a,
308
324
  isValid: c
309
325
  };
310
326
  }
311
- const o = (n) => {
312
- t.errors = _(d(r.errors) ?? m.errors, n);
327
+ const n = (l) => {
328
+ t.errors = S(f(e.errors) ?? m.errors, l);
313
329
  }, h = async () => {
314
- const n = await s();
315
- return o(n.errors), t.isValidated = !0, {
316
- isValid: !C(n.errors),
330
+ const l = await o();
331
+ return n(l.errors), t.isValidated = !0, {
332
+ isValid: !M(l.errors),
317
333
  errors: t.errors
318
334
  };
319
- }, l = u(() => !C(t.errors));
335
+ }, v = d(() => !M(t.errors));
320
336
  return {
321
337
  ...N(t),
322
338
  validateForm: h,
323
- defineValidator: a,
324
- isValid: l
339
+ defineValidator: s,
340
+ isValid: v
325
341
  };
326
342
  }
327
- class hr {
328
- constructor(r, t) {
329
- this.path = r, this.validator = t;
343
+ class ve {
344
+ constructor(e, t) {
345
+ this.path = e, this.validator = t;
330
346
  }
331
- async validate(r) {
332
- const t = w(r, this.path);
347
+ async validate(e) {
348
+ const t = D(e, this.path);
333
349
  if (!this.validator)
334
350
  return m;
335
- const a = await this.validator.validate(t);
351
+ const s = await this.validator.validate(t);
336
352
  return {
337
- isValid: a.isValid,
353
+ isValid: s.isValid,
338
354
  errors: {
339
- general: a.errors.general || [],
340
- propertyErrors: a.errors.propertyErrors ? Object.fromEntries(
341
- Object.entries(a.errors.propertyErrors).map(([s, o]) => [
342
- F(this.path, s),
343
- o
355
+ general: s.errors.general || [],
356
+ propertyErrors: s.errors.propertyErrors ? Object.fromEntries(
357
+ Object.entries(s.errors.propertyErrors).map(([o, n]) => [
358
+ w(this.path, o),
359
+ n
344
360
  ])
345
361
  ) : {}
346
362
  }
347
363
  };
348
364
  }
349
365
  }
350
- function vr(e, r, t) {
351
- const a = B(e.data, r), s = u(() => w(e.initialData.value, r)), o = (i) => ({
366
+ function me(r, e, t) {
367
+ const s = U(r.data, e), o = d(() => D(r.initialData.value, e)), n = (i) => ({
352
368
  ...i,
353
- path: u(() => d(i.path).replace(r + ".", "")),
369
+ path: d(() => f(i.path).replace(e + ".", "")),
354
370
  setData: (p) => {
355
371
  i.setData(p);
356
372
  }
357
373
  }), h = (i) => {
358
- const p = F(r, i), V = e.getField(p);
359
- return V ? o(V) : {};
360
- }, l = (i) => {
361
- const p = F(r, i.path), V = e.defineField({
374
+ const p = w(e, i), V = r.getField(p);
375
+ return V ? n(V) : {};
376
+ }, v = (i) => {
377
+ const p = w(e, i.path), V = r.defineField({
362
378
  ...i,
363
379
  path: p
364
380
  });
365
- return o(V);
366
- }, n = u(() => e.fields.value.filter((i) => {
381
+ return n(V);
382
+ }, l = d(() => r.fields.value.filter((i) => {
367
383
  const p = i.path.value;
368
- return p.startsWith(r + ".") || p === r;
369
- }).map((i) => o(i))), c = () => e.fields.value.filter((i) => {
384
+ return p.startsWith(e + ".") || p === e;
385
+ }).map((i) => n(i))), c = () => r.fields.value.filter((i) => {
370
386
  const p = i.path.value;
371
- return p.startsWith(r + ".") || p === r;
372
- }), f = u(() => c().some((i) => i.dirty.value)), v = u(() => c().some((i) => i.touched.value)), P = u(() => e.isValid.value), I = u(() => e.isValidated.value), J = u(() => ar(d(e.errors), r));
387
+ return p.startsWith(e + ".") || p === e;
388
+ }), a = d(() => c().some((i) => i.dirty.value)), u = d(() => c().some((i) => i.touched.value)), g = d(() => r.isValid.value), P = d(() => r.isValidated.value), J = d(() => se(f(r.errors), e));
373
389
  return {
374
- data: a,
375
- fields: n,
376
- initialData: s,
377
- defineField: l,
390
+ data: s,
391
+ fields: l,
392
+ initialData: o,
393
+ defineField: v,
378
394
  getField: h,
379
- isDirty: f,
380
- isTouched: v,
381
- isValid: P,
382
- isValidated: I,
395
+ isDirty: a,
396
+ isTouched: u,
397
+ isValid: g,
398
+ isValidated: P,
383
399
  errors: J,
384
400
  defineValidator: (i) => {
385
- const p = z(i) ? i : b(i), V = u(
386
- () => new hr(r, d(p))
401
+ const p = k(i) ? i : b(i), V = d(
402
+ () => new ve(e, f(p))
387
403
  );
388
- return e.defineValidator(V), p;
404
+ return r.defineValidator(V), p;
389
405
  },
390
406
  reset: () => c().forEach((i) => i.reset()),
391
- validateForm: () => e.validateForm(),
407
+ validateForm: () => r.validateForm(),
392
408
  getSubForm: (i, p) => {
393
- const V = F(r, i);
394
- return e.getSubForm(
409
+ const V = w(e, i);
410
+ return r.getSubForm(
395
411
  V,
396
412
  p
397
413
  );
398
414
  }
399
415
  };
400
416
  }
401
- function Rr(e) {
402
- const r = u(() => Object.freeze(y(e.initialData))), t = W(y(r)), a = g({
403
- initialData: r,
417
+ function Pe(r) {
418
+ const e = d(() => Object.freeze(y(r.initialData))), t = W(y(e)), s = R({
419
+ initialData: e,
404
420
  data: t
405
421
  });
406
- E(r, (f) => {
407
- a.data = y(f);
422
+ F(e, (a) => {
423
+ s.data = y(a);
408
424
  });
409
- const s = pr(a, e), o = or(a, s), h = nr(o), l = () => {
410
- t.value = y(r), o.fields.value.forEach(
411
- (f) => f.reset()
425
+ const o = he(s, r), n = ne(s, o), h = ie(n), v = () => {
426
+ t.value = y(e), n.fields.value.forEach(
427
+ (a) => a.reset()
412
428
  );
413
429
  };
414
- function n(f, v) {
415
- return vr(c, f);
430
+ function l(a, u) {
431
+ return me(c, a);
416
432
  }
417
433
  const c = {
434
+ ...n,
418
435
  ...o,
419
- ...s,
420
436
  ...h,
421
- reset: l,
422
- getSubForm: n,
423
- initialData: D(a, "initialData"),
424
- data: D(a, "data")
437
+ reset: v,
438
+ getSubForm: l,
439
+ initialData: _(s, "initialData"),
440
+ data: _(s, "data")
425
441
  };
426
442
  return c;
427
443
  }
428
- const Dr = /* @__PURE__ */ S({
444
+ const _e = /* @__PURE__ */ j({
429
445
  __name: "Field",
430
446
  props: {
431
447
  form: {},
@@ -434,13 +450,13 @@ const Dr = /* @__PURE__ */ S({
434
450
  path: {},
435
451
  errors: {}
436
452
  },
437
- setup(e) {
438
- const r = e, t = r.form.defineField({
439
- path: r.path
440
- }), a = g(t);
441
- return (s, o) => j(s.$slots, "default", M(U(a)));
453
+ setup(r) {
454
+ const e = r, t = e.form.defineField({
455
+ path: e.path
456
+ }), s = R(t);
457
+ return (o, n) => O(o.$slots, "default", z(B(s)));
442
458
  }
443
- }), _r = /* @__PURE__ */ S({
459
+ }), Se = /* @__PURE__ */ j({
444
460
  inheritAttrs: !1,
445
461
  __name: "FormFieldWrapper",
446
462
  props: {
@@ -449,22 +465,22 @@ const Dr = /* @__PURE__ */ S({
449
465
  form: {},
450
466
  path: {}
451
467
  },
452
- setup(e) {
453
- return (r, t) => {
454
- const a = Y("Field");
455
- return $(), O(a, {
456
- form: r.form,
457
- path: r.path
468
+ setup(r) {
469
+ return (e, t) => {
470
+ const s = Y("Field");
471
+ return A(), $(s, {
472
+ form: e.form,
473
+ path: e.path
458
474
  }, {
459
- default: A(({ errors: s, data: o, setData: h }) => [
460
- ($(), O(x(r.component), rr({ ...r.componentProps, ...r.$attrs }, {
461
- "model-value": o,
462
- errors: s,
463
- name: r.path,
475
+ default: C(({ errors: o, data: n, setData: h }) => [
476
+ (A(), $(x(e.component), ee({ ...e.componentProps, ...e.$attrs }, {
477
+ "model-value": n,
478
+ errors: o,
479
+ name: e.path,
464
480
  "onUpdate:modelValue": h
465
481
  }), {
466
- default: A(() => [
467
- j(r.$slots, "default")
482
+ default: C(() => [
483
+ O(e.$slots, "default")
468
484
  ]),
469
485
  _: 2
470
486
  }, 1040, ["model-value", "errors", "name", "onUpdate:modelValue"]))
@@ -473,20 +489,20 @@ const Dr = /* @__PURE__ */ S({
473
489
  }, 8, ["form", "path"]);
474
490
  };
475
491
  }
476
- }), br = /* @__PURE__ */ S({
492
+ }), be = /* @__PURE__ */ j({
477
493
  __name: "FormPart",
478
494
  props: {
479
495
  form: {},
480
496
  path: {}
481
497
  },
482
- setup(e) {
483
- const r = e, t = u(() => r.form.getSubForm(r.path));
484
- return (a, s) => j(a.$slots, "default", M(U({ subform: t.value })));
498
+ setup(r) {
499
+ const e = r, t = d(() => e.form.getSubForm(e.path));
500
+ return (s, o) => O(s.$slots, "default", z(B({ subform: t.value })));
485
501
  }
486
502
  });
487
503
  export {
488
- Dr as Field,
489
- _r as FormFieldWrapper,
490
- br as FormPart,
491
- Rr as useForm
504
+ _e as Field,
505
+ Se as FormFieldWrapper,
506
+ be as FormPart,
507
+ Pe as useForm
492
508
  };
@@ -0,0 +1,7 @@
1
+ export declare class Rc {
2
+ private drop?;
3
+ private rc;
4
+ constructor(drop?: (() => void) | undefined);
5
+ inc(): void;
6
+ dec(): void;
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnovu/kit-vue-forms",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,12 +1,13 @@
1
- import { computed, markRaw, onUnmounted, reactive, toRef, unref, watch } from 'vue'
1
+ import { computed, onScopeDispose, shallowReactive, toRef, unref } from 'vue'
2
2
  import type { FieldsTuple, FormDataDefault, FormField } from '../types/form'
3
3
  import type { Paths, PickProps } from '../types/util'
4
4
  import { getLens, getNestedValue } from '../utils/path'
5
+ import { Rc } from '../utils/rc'
5
6
  import { useField, type UseFieldOptions } from './useField'
6
7
  import type { ValidationState } from './useValidation'
7
8
 
8
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- type FieldRegistryCache<T> = Record<Paths<T>, FormField<any, string>>
10
+ type FieldRegistryCache<T> = Map<Paths<T>, FormField<any, string>>
10
11
 
11
12
  export type ResolvedFormField<T, K extends Paths<T>> = FormField<PickProps<T, K>, K>
12
13
 
@@ -21,19 +22,34 @@ export function useFieldRegistry<T extends FormDataDefault>(
21
22
  formState: FormState<T>,
22
23
  validationState: ValidationState<T>,
23
24
  ) {
24
- const fields = reactive({}) as FieldRegistryCache<T>
25
+ const fieldReferenceCounter = new Map<Paths<T>, Rc>()
26
+ const fields = shallowReactive(new Map()) as FieldRegistryCache<T>
25
27
 
26
28
  const registerField = <K extends Paths<T>>(field: ResolvedFormField<T, K>) => {
27
29
  const path = unref(field.path) as Paths<T>
28
- fields[path] = markRaw(field)
30
+ fields.set(path, field)
29
31
  }
30
32
 
31
33
  const deregisterField = (path: Paths<T>) => {
32
- delete fields[path]
34
+ fields.delete(path)
35
+ }
36
+
37
+ const track = (path: Paths<T>) => {
38
+ if (!fieldReferenceCounter.has(path)) {
39
+ fieldReferenceCounter.set(path, new Rc(() => deregisterField(path)))
40
+ } else {
41
+ fieldReferenceCounter.get(path)?.inc()
42
+ }
43
+ }
44
+
45
+ const untrack = (path: Paths<T>) => {
46
+ if (fieldReferenceCounter.has(path)) {
47
+ fieldReferenceCounter.get(path)?.dec()
48
+ }
33
49
  }
34
50
 
35
51
  const getField = <K extends Paths<T>>(path: K): ResolvedFormField<T, K> => {
36
- if (!fields[path]) {
52
+ if (!fields.has(path)) {
37
53
  const field = useField({
38
54
  path,
39
55
  value: getLens(toRef(formState, 'data'), path),
@@ -49,11 +65,18 @@ export function useFieldRegistry<T extends FormDataDefault>(
49
65
  })
50
66
 
51
67
  registerField(field)
52
-
53
- return field
54
68
  }
55
69
 
56
- return fields[path] as ResolvedFormField<T, K>
70
+ const field = fields.get(path) as ResolvedFormField<T, K>
71
+
72
+ track(path)
73
+
74
+ // Clean up field on unmount
75
+ onScopeDispose(() => {
76
+ untrack(path)
77
+ })
78
+
79
+ return field
57
80
  }
58
81
 
59
82
  const defineField = <K extends Paths<T>>(options: DefineFieldOptions<PickProps<T, K>, K>): ResolvedFormField<T, K> => {
@@ -61,17 +84,12 @@ export function useFieldRegistry<T extends FormDataDefault>(
61
84
 
62
85
  // TODO: If more options are ever needed than only the path we have to update the field
63
86
  // here with the new options
64
-
65
- onUnmounted(() => {
66
- // Clean up field on unmount
67
- deregisterField(unref(field.path))
68
- })
69
87
 
70
88
  return field
71
89
  }
72
90
 
73
91
  return {
74
- fields: computed(() => Object.values(fields) as FieldsTuple<T>),
92
+ fields: computed(() => [...fields.values()] as FieldsTuple<T>),
75
93
  getField,
76
94
  registerField,
77
95
  deregisterField,
@@ -0,0 +1,19 @@
1
+ export class Rc {
2
+ private rc: number = 1
3
+
4
+ constructor(private drop?: () => void) {}
5
+
6
+ inc() {
7
+ this.rc += 1
8
+ }
9
+
10
+ dec() {
11
+ if (this.rc > 0) {
12
+ this.rc -= 1
13
+
14
+ if (this.rc === 0 && this.drop) {
15
+ this.drop()
16
+ }
17
+ }
18
+ }
19
+ }
@@ -1,9 +1,14 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { ref, nextTick, effectScope, watch, unref, reactive, toRef } from 'vue'
3
- import { useForm } from '../src/composables/useForm'
1
+ import { describe, expect, it } from 'vitest'
2
+ import { effectScope, isReactive, nextTick, reactive, ref } from 'vue'
4
3
  import { z } from 'zod'
4
+ import { useForm } from '../src/composables/useForm'
5
+
6
+ const scope = effectScope()
5
7
 
6
8
  describe('useForm', () => {
9
+ beforeAll(() => {
10
+
11
+ })
7
12
  it('should initialize form with initial data', () => {
8
13
  const initialData = {
9
14
  name: 'John',
@@ -230,7 +235,6 @@ describe('useForm', () => {
230
235
 
231
236
  const nameField = form.defineField({ path: 'name' })
232
237
 
233
-
234
238
  expect(form.fields.value.length).toBe(1)
235
239
  expect(form.isDirty.value).toBe(false)
236
240
 
@@ -238,4 +242,52 @@ describe('useForm', () => {
238
242
 
239
243
  expect(form.isDirty.value).toBe(true)
240
244
  })
245
+
246
+ it('fields can be made reactive', async () => {
247
+ const form = useForm({
248
+ initialData: {
249
+ name: 'John',
250
+ age: 30,
251
+ },
252
+ })
253
+
254
+ const nameField = form.defineField({ path: 'name' })
255
+
256
+ expect(isReactive(reactive(nameField))).toBe(true)
257
+ })
258
+
259
+ it('fields should only be removed when all references are gone', async () => {
260
+ const form = useForm({
261
+ initialData: {
262
+ name: 'John',
263
+ age: 30,
264
+ },
265
+ })
266
+
267
+ expect(form.fields.value).toEqual([])
268
+
269
+ const scope1 = effectScope()
270
+
271
+ scope1.run(() => {
272
+ form.defineField({ path: 'name' })
273
+ })
274
+
275
+ expect(form.fields.value.length).toBe(1)
276
+
277
+ const scope2 = effectScope()
278
+
279
+ scope2.run(() => {
280
+ form.defineField({ path: 'name' })
281
+ })
282
+
283
+ expect(form.fields.value.length).toBe(1)
284
+
285
+ scope1.stop()
286
+
287
+ expect(form.fields.value.length).toBe(1)
288
+
289
+ scope2.stop()
290
+
291
+ expect(form.fields.value.length).toBe(0)
292
+ })
241
293
  })