@teamnovu/kit-vue-forms 0.0.9 → 0.0.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.
@@ -1,7 +1,7 @@
1
1
  import { Form } from '../types/form.ts';
2
2
  import { Paths, PickProps } from '../types/util.ts';
3
3
  import { UseFieldOptions } from '../composables/useField.ts';
4
- import { VNodeProps, AllowedComponentProps, ComponentCustomProps, PublicProps, ShallowUnwrapRef, Ref, VNode } from 'vue';
4
+ import { VNodeProps, AllowedComponentProps, ComponentCustomProps, PublicProps, ShallowUnwrapRef, VNode } from 'vue';
5
5
  import { ValidationErrors, ErrorMessage } from '../index.js';
6
6
  export interface FieldProps<TData extends object, TPath extends string> extends UseFieldOptions<PickProps<TData, TPath>, TPath> {
7
7
  form: Form<TData>;
@@ -12,12 +12,12 @@ declare const _default: <TData extends object, TPath extends Paths<TData>>(__VLS
12
12
  attrs: any;
13
13
  slots: {
14
14
  default?(_: {
15
- data: Ref<PickProps<TData, TPath>, PickProps<TData, TPath>>;
16
- path: Ref<TPath, TPath>;
17
- initialValue: Readonly< Ref<PickProps<TData, TPath>, PickProps<TData, TPath>>>;
18
- errors: Ref<ValidationErrors>;
19
- touched: Ref<boolean>;
20
- dirty: Ref<boolean>;
15
+ data: PickProps<TData, TPath>;
16
+ path: TPath;
17
+ initialValue: PickProps<TData, TPath>;
18
+ errors: ValidationErrors;
19
+ touched: boolean;
20
+ dirty: boolean;
21
21
  setData: (newData: PickProps<TData, TPath>) => void;
22
22
  onBlur: () => void;
23
23
  onFocus: () => void;
@@ -7,4 +7,5 @@ export interface UseFieldOptions<T, K extends string> {
7
7
  path: K;
8
8
  errors?: MaybeRef<ValidationErrors>;
9
9
  }
10
+ export declare function getEmptyField(): FormField<unknown, string>;
10
11
  export declare function useField<T, K extends string>(options: UseFieldOptions<T, K>): FormField<T, K>;
@@ -1,4 +1,4 @@
1
- import { FormDataDefault, FormField } from '../types/form';
1
+ import { FieldsTuple, FormDataDefault, FormField } from '../types/form';
2
2
  import { Paths, PickProps } from '../types/util';
3
3
  import { UseFieldOptions } from './useField';
4
4
  type FieldRegistryCache<T> = Record<Paths<T>, FormField<any, string>>;
@@ -11,7 +11,7 @@ interface FormState<T extends FormDataDefault, TIn extends FormDataDefault = T>
11
11
  export declare function useFieldRegistry<T extends FormDataDefault>(formState: FormState<T>): {
12
12
  fields: FieldRegistryCache<T>;
13
13
  getField: <K extends Paths<T>>(path: K) => ResolvedFormField<T, K>;
14
- getFields: () => ResolvedFormField<T, Paths<T>>[];
14
+ getFields: <TData extends T>() => FieldsTuple<TData>;
15
15
  registerField: <K extends Paths<T>>(field: ResolvedFormField<T, K>) => void;
16
16
  defineField: <K extends Paths<T>>(options: DefineFieldOptions<PickProps<T, K>, K>) => FormField<K extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_1 ? T_1 extends TRest ? T_1 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_2 ? T_2 extends TRest ? T_2 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_3 ? T_3 extends TRest ? T_3 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_4 ? T_4 extends TRest ? T_4 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_5 ? T_5 extends TRest ? T_5 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_6 ? T_6 extends TRest ? T_6 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_7 ? T_7 extends TRest ? T_7 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_8 ? T_8 extends TRest ? T_8 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_9 ? T_9 extends TRest ? T_9 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? TRest extends infer T_10 ? T_10 extends TRest ? T_10 extends `${infer TRoot}.${infer TRest}` ? TRoot extends string | number | symbol ? TRest extends string ? /*elided*/ any : never : TRoot extends `${number}` ? never : never : T_10 extends string | number | symbol ? Required<any>[T_10] : T_10 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_9 extends string | number | symbol ? Required<any>[T_9] : T_9 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_8 extends string | number | symbol ? Required<any>[T_8] : T_8 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_7 extends string | number | symbol ? Required<any>[T_7] : T_7 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_6 extends string | number | symbol ? Required<any>[T_6] : T_6 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_5 extends string | number | symbol ? Required<any>[T_5] : T_5 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_4 extends string | number | symbol ? Required<any>[T_4] : T_4 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_3 extends string | number | symbol ? Required<any>[T_3] : T_3 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_2 extends string | number | symbol ? Required<any>[T_2] : T_2 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : T_1 extends string | number | symbol ? Required<any>[T_1] : T_1 extends `${number}` ? never : never : never : never : never : TRoot extends `${number}` ? never : never : K extends string | number | symbol ? any : K extends `${number}` ? never : never, K>;
17
17
  };
@@ -16,7 +16,7 @@ export declare function useValidation<T extends FormDataDefault>(formState: {
16
16
  data: T;
17
17
  }, options: ValidationOptions<T>): {
18
18
  validateForm: () => Promise<ValidationResult>;
19
- defineValidator: (options: ValidatorOptions<T> | Ref<Validator<T>>) => Ref<Validator<T> | undefined, Validator<T> | undefined>;
19
+ defineValidator: <TData extends T>(options: ValidatorOptions<TData> | Ref<Validator<TData>>) => Ref<Validator<TData> | undefined, Validator<TData> | undefined>;
20
20
  isValid: ComputedRef<boolean>;
21
21
  validators: Ref<Ref<Validator<T> | undefined, Validator<T> | undefined>[], Ref<Validator<T> | undefined, Validator<T> | undefined>[]>;
22
22
  isValidated: Ref<boolean, boolean>;
package/dist/index.mjs CHANGED
@@ -1,44 +1,44 @@
1
1
  var x = Object.defineProperty;
2
2
  var K = (e, r, t) => r in e ? x(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t;
3
- var R = (e, r, t) => K(e, typeof r != "symbol" ? r + "" : r, t);
4
- import { toValue as W, toRaw as q, computed as d, unref as c, reactive as b, watch as F, toRefs as O, toRef as S, ref as A, isRef as _, getCurrentScope as I, onBeforeUnmount as J, defineComponent as T, renderSlot as B, normalizeProps as G, guardReactiveProps as L } from "vue";
3
+ var S = (e, r, t) => K(e, typeof r != "symbol" ? r + "" : r, t);
4
+ import { toValue as W, toRaw as B, computed as d, unref as u, reactive as w, watch as E, toRefs as A, ref as y, toRef as P, isRef as _, getCurrentScope as I, onBeforeUnmount as J, defineComponent as T, renderSlot as G, normalizeProps as L, guardReactiveProps as U } from "vue";
5
5
  import "zod";
6
- function y(e) {
7
- const r = W(e), t = q(r);
6
+ function F(e) {
7
+ const r = W(e), t = B(r);
8
8
  return structuredClone(t);
9
9
  }
10
10
  function N(e) {
11
11
  return e === "" ? [] : e.split(/\s*\.\s*/).filter(Boolean);
12
12
  }
13
- function m(e, r) {
13
+ function R(e, r) {
14
14
  return (Array.isArray(r) ? r : N(r)).reduce(
15
15
  (a, s) => a == null ? void 0 : a[s],
16
16
  e
17
17
  );
18
18
  }
19
- function U(e, r, t) {
19
+ function Z(e, r, t) {
20
20
  const a = Array.isArray(r) ? r : N(r);
21
21
  if (a.length === 0)
22
22
  throw new Error("Path cannot be empty");
23
23
  const s = a.at(-1), n = a.slice(0, -1).reduce(
24
- (u, v) => u[v],
24
+ (o, v) => o[v],
25
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
26
  e
27
27
  );
28
28
  n[s] = t;
29
29
  }
30
- const z = (e, r) => d({
30
+ const $ = (e, r) => d({
31
31
  get() {
32
- return m(c(e), c(r));
32
+ return R(u(e), u(r));
33
33
  },
34
34
  set(t) {
35
- U(c(e), c(r), t);
35
+ Z(u(e), u(r), t);
36
36
  }
37
37
  });
38
- function E(e, r) {
38
+ function m(e, r) {
39
39
  return !e && !r ? "" : !e && r ? r : !r && e ? e : `${e}.${r}`;
40
40
  }
41
- function Z(e, r) {
41
+ function k(e, r) {
42
42
  if (!r)
43
43
  return e;
44
44
  const t = `${r}.`, a = Object.fromEntries(
@@ -52,15 +52,37 @@ function Z(e, r) {
52
52
  propertyErrors: a
53
53
  };
54
54
  }
55
- function k(e) {
56
- const r = b({
55
+ function q() {
56
+ return {
57
+ setData: () => {
58
+ },
59
+ onBlur: () => {
60
+ },
61
+ onFocus: () => {
62
+ },
63
+ reset: () => {
64
+ },
65
+ setErrors: () => {
66
+ },
67
+ clearErrors: () => {
68
+ },
69
+ data: y(void 0),
70
+ initialValue: y(void 0),
71
+ path: y(""),
72
+ errors: y([]),
73
+ touched: y(!1),
74
+ dirty: d(() => !1)
75
+ };
76
+ }
77
+ function H(e) {
78
+ const r = w({
57
79
  value: e.value,
58
80
  path: e.path,
59
- initialValue: d(() => Object.freeze(y(e.initialValue))),
60
- errors: c(e.errors) || [],
81
+ initialValue: d(() => Object.freeze(F(e.initialValue))),
82
+ errors: u(e.errors) || [],
61
83
  touched: !1
62
84
  });
63
- F(() => c(e.errors), (f) => {
85
+ E(() => u(e.errors), (f) => {
64
86
  r.errors = f || [];
65
87
  });
66
88
  const t = d(() => JSON.stringify(r.value) !== JSON.stringify(r.initialValue)), a = (f) => {
@@ -68,61 +90,61 @@ function k(e) {
68
90
  }, s = () => {
69
91
  r.touched = !0;
70
92
  }, n = () => {
71
- }, u = () => {
72
- r.value = y(r.initialValue), r.touched = !1, r.errors = [];
93
+ }, o = () => {
94
+ r.value = F(r.initialValue), r.touched = !1, r.errors = [];
73
95
  }, v = (f) => {
74
96
  r.errors = f;
75
- }, o = () => {
97
+ }, l = () => {
76
98
  r.errors = [];
77
- }, l = O(r);
99
+ }, c = A(r);
78
100
  return {
79
- data: l.value,
80
- path: l.path,
81
- initialValue: l.initialValue,
82
- errors: l.errors,
83
- touched: l.touched,
101
+ data: c.value,
102
+ path: c.path,
103
+ initialValue: c.initialValue,
104
+ errors: c.errors,
105
+ touched: c.touched,
84
106
  dirty: t,
85
107
  setData: a,
86
108
  onBlur: s,
87
109
  onFocus: n,
88
- reset: u,
110
+ reset: o,
89
111
  setErrors: v,
90
- clearErrors: o
112
+ clearErrors: l
91
113
  };
92
114
  }
93
- function H(e) {
94
- const r = {}, t = (u) => {
95
- const v = c(u.path);
96
- r[v] = u;
115
+ function Q(e) {
116
+ const r = {}, t = (o) => {
117
+ const v = u(o.path);
118
+ r[v] = o;
97
119
  };
98
120
  return {
99
121
  fields: r,
100
- getField: (u) => r[u] ?? {},
122
+ getField: (o) => o in r ? r[o] : (console.warn(`Field with path "${o}" is not registered.`), q()),
101
123
  getFields: () => Object.values(r),
102
124
  registerField: t,
103
- defineField: (u) => {
104
- const v = k({
105
- ...u,
106
- value: z(S(e, "data"), u.path),
107
- initialValue: d(() => m(e.initialData, c(u.path)))
125
+ defineField: (o) => {
126
+ const v = H({
127
+ ...o,
128
+ value: $(P(e, "data"), o.path),
129
+ initialValue: d(() => R(e.initialData, u(o.path)))
108
130
  });
109
131
  return t(v), v;
110
132
  }
111
133
  };
112
134
  }
113
- function Q(e) {
114
- const r = d(() => e.getFields().some((a) => c(a.dirty))), t = d(() => e.getFields().some((a) => c(a.touched)));
135
+ function X(e) {
136
+ const r = d(() => e.getFields().some((a) => u(a.dirty))), t = d(() => e.getFields().some((a) => u(a.touched)));
115
137
  return {
116
138
  isDirty: r,
117
139
  isTouched: t
118
140
  };
119
141
  }
120
- function X(e) {
142
+ function Y(e) {
121
143
  return e.filter(
122
144
  (r, t, a) => a.indexOf(r) === t
123
145
  );
124
146
  }
125
- function C(...e) {
147
+ function z(...e) {
126
148
  return e.slice(1).reduce((r, t) => {
127
149
  if (!r && !t)
128
150
  return;
@@ -132,19 +154,19 @@ function C(...e) {
132
154
  if (!a)
133
155
  return r;
134
156
  const s = (r ?? []).concat(t);
135
- return X(s);
157
+ return Y(s);
136
158
  }, e[0]);
137
159
  }
138
- function Y(...e) {
160
+ function rr(...e) {
139
161
  return e.map((t) => Object.keys(t)).flat().reduce((t, a) => {
140
162
  const s = e.map((n) => n[a]).filter(Boolean);
141
163
  return {
142
164
  ...t,
143
- [a]: C(...s)
165
+ [a]: z(...s)
144
166
  };
145
167
  }, {});
146
168
  }
147
- function D(...e) {
169
+ function b(...e) {
148
170
  if (!e.length)
149
171
  return {
150
172
  general: [],
@@ -153,18 +175,18 @@ function D(...e) {
153
175
  const r = e[0];
154
176
  return e.length === 1 ? r : e.slice(1).reduce(
155
177
  (t, a) => ({
156
- general: C(t.general, a.general),
157
- propertyErrors: Y(t.propertyErrors ?? {}, a.propertyErrors ?? {})
178
+ general: z(t.general, a.general),
179
+ propertyErrors: rr(t.propertyErrors ?? {}, a.propertyErrors ?? {})
158
180
  }),
159
181
  r
160
182
  );
161
183
  }
162
- function j(e) {
184
+ function O(e) {
163
185
  var a;
164
186
  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;
165
187
  return r || t;
166
188
  }
167
- function rr(e) {
189
+ function er(e) {
168
190
  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) => {
169
191
  const n = s.path.join(".");
170
192
  return {
@@ -184,7 +206,7 @@ const V = {
184
206
  propertyErrors: {}
185
207
  }
186
208
  };
187
- class er {
209
+ class tr {
188
210
  constructor(r) {
189
211
  this.schema = r;
190
212
  }
@@ -194,7 +216,7 @@ class er {
194
216
  const t = await this.schema.safeParseAsync(r);
195
217
  if (t.success)
196
218
  return V;
197
- const a = rr(t.error);
219
+ const a = er(t.error);
198
220
  return {
199
221
  isValid: !1,
200
222
  errors: {
@@ -204,7 +226,7 @@ class er {
204
226
  };
205
227
  }
206
228
  }
207
- class tr {
229
+ class ar {
208
230
  constructor(r) {
209
231
  this.validateFn = r;
210
232
  }
@@ -225,11 +247,11 @@ class tr {
225
247
  }
226
248
  }
227
249
  }
228
- class ar {
250
+ class sr {
229
251
  constructor(r, t) {
230
- R(this, "schemaValidator");
231
- R(this, "functionValidator");
232
- this.schema = r, this.validateFn = t, this.schemaValidator = new er(this.schema), this.functionValidator = new tr(this.validateFn);
252
+ S(this, "schemaValidator");
253
+ S(this, "functionValidator");
254
+ this.schema = r, this.validateFn = t, this.schemaValidator = new tr(this.schema), this.functionValidator = new ar(this.validateFn);
233
255
  }
234
256
  async validate(r) {
235
257
  const [t, a] = await Promise.all([
@@ -238,83 +260,83 @@ class ar {
238
260
  ]);
239
261
  return {
240
262
  isValid: t.isValid && a.isValid,
241
- errors: D(t.errors, a.errors)
263
+ errors: b(t.errors, a.errors)
242
264
  };
243
265
  }
244
266
  }
245
- function P(e) {
246
- return d(() => new ar(
247
- c(e.schema),
248
- c(e.validateFn)
267
+ function j(e) {
268
+ return d(() => new sr(
269
+ u(e.schema),
270
+ u(e.validateFn)
249
271
  ));
250
272
  }
251
- function sr(e, r) {
252
- const t = b({
253
- validators: A([P(r)]),
273
+ function ir(e, r) {
274
+ const t = w({
275
+ validators: y([j(r)]),
254
276
  isValidated: !1,
255
- errors: c(r.errors) ?? V.errors
277
+ errors: u(r.errors) ?? V.errors
256
278
  });
257
- F(() => c(r.errors), async () => {
258
- const o = await s();
259
- n(o.errors);
260
- }, { immediate: !0 }), F(
279
+ E(() => u(r.errors), async () => {
280
+ const l = await s();
281
+ n(l.errors);
282
+ }, { immediate: !0 }), E(
261
283
  [() => t.validators],
262
- async (o) => {
284
+ async (l) => {
263
285
  if (t.isValidated)
264
- if (o) {
265
- const l = await s();
266
- t.errors = l.errors;
286
+ if (l) {
287
+ const c = await s();
288
+ t.errors = c.errors;
267
289
  } else
268
290
  t.errors = V.errors;
269
291
  },
270
292
  { immediate: !0 }
271
- ), F(() => e.data, () => {
272
- t.isValidated && u();
293
+ ), E(() => e.data, () => {
294
+ t.isValidated && o();
273
295
  });
274
- const a = (o) => {
275
- const l = _(o) ? o : P(o);
276
- return t.validators.push(l), I() && J(() => {
296
+ const a = (l) => {
297
+ const c = _(l) ? l : j(l);
298
+ return t.validators.push(c), I() && J(() => {
277
299
  t.validators = t.validators.filter(
278
- (f) => f !== l
300
+ (f) => f !== c
279
301
  );
280
- }), l;
302
+ }), c;
281
303
  };
282
304
  async function s() {
283
- const o = await Promise.all(
284
- t.validators.filter((p) => c(p) !== void 0).map((p) => c(p).validate(e.data))
285
- ), l = o.every((p) => p.isValid);
305
+ const l = await Promise.all(
306
+ t.validators.filter((p) => u(p) !== void 0).map((p) => u(p).validate(e.data))
307
+ ), c = l.every((p) => p.isValid);
286
308
  let { errors: f } = V;
287
- if (!l) {
288
- const p = o.map((w) => w.errors);
289
- f = D(...p);
309
+ if (!c) {
310
+ const p = l.map((D) => D.errors);
311
+ f = b(...p);
290
312
  }
291
313
  return {
292
314
  errors: f,
293
- isValid: l
315
+ isValid: c
294
316
  };
295
317
  }
296
- const n = (o) => {
297
- t.errors = D(c(r.errors) ?? V.errors, o);
298
- }, u = async () => {
299
- const o = await s();
300
- return n(o.errors), t.isValidated = !0, {
301
- isValid: !j(o.errors),
318
+ const n = (l) => {
319
+ t.errors = b(u(r.errors) ?? V.errors, l);
320
+ }, o = async () => {
321
+ const l = await s();
322
+ return n(l.errors), t.isValidated = !0, {
323
+ isValid: !O(l.errors),
302
324
  errors: t.errors
303
325
  };
304
- }, v = d(() => !j(t.errors));
326
+ }, v = d(() => !O(t.errors));
305
327
  return {
306
- ...O(t),
307
- validateForm: u,
328
+ ...A(t),
329
+ validateForm: o,
308
330
  defineValidator: a,
309
331
  isValid: v
310
332
  };
311
333
  }
312
- class ir {
334
+ class nr {
313
335
  constructor(r, t) {
314
336
  this.path = r, this.validator = t;
315
337
  }
316
338
  async validate(r) {
317
- const t = m(r, this.path);
339
+ const t = R(r, this.path);
318
340
  if (!this.validator)
319
341
  return V;
320
342
  const a = await this.validator.validate(t);
@@ -324,7 +346,7 @@ class ir {
324
346
  general: a.errors.general || [],
325
347
  propertyErrors: a.errors.propertyErrors ? Object.fromEntries(
326
348
  Object.entries(a.errors.propertyErrors).map(([s, n]) => [
327
- E(this.path, s),
349
+ m(this.path, s),
328
350
  n
329
351
  ])
330
352
  ) : {}
@@ -332,51 +354,50 @@ class ir {
332
354
  };
333
355
  }
334
356
  }
335
- function nr(e, r, t) {
336
- const a = z(e.data, r), s = d(() => m(e.initialData.value, r)), n = (i) => ({
357
+ function or(e, r, t) {
358
+ const a = $(e.data, r), s = d(() => R(e.initialData.value, r)), n = (i) => ({
337
359
  ...i,
338
- path: d(() => c(i.path).replace(r + ".", "")),
360
+ path: d(() => u(i.path).replace(r + ".", "")),
339
361
  setData: (h) => {
340
362
  i.setData(h);
341
363
  }
342
- }), u = (i) => {
343
- const h = E(r, i), g = e.getField(h);
344
- if (g)
345
- return n(g);
364
+ }), o = (i) => {
365
+ const h = m(r, i), g = e.getField(h);
366
+ return g ? n(g) : {};
346
367
  }, v = (i) => {
347
- const h = E(r, i.path), g = e.defineField({
368
+ const h = m(r, i.path), g = e.defineField({
348
369
  ...i,
349
370
  path: h
350
371
  });
351
372
  return n(g);
352
- }, o = () => e.getFields().filter((i) => {
373
+ }, l = () => e.getFields().filter((i) => {
353
374
  const h = i.path.value;
354
375
  return h.startsWith(r + ".") || h === r;
355
- }).map((i) => n(i)), l = () => e.getFields().filter((i) => {
376
+ }).map((i) => n(i)), c = () => e.getFields().filter((i) => {
356
377
  const h = i.path.value;
357
378
  return h.startsWith(r + ".") || h === r;
358
- }), f = d(() => l().some((i) => i.dirty.value)), p = d(() => l().some((i) => i.touched.value)), w = d(() => e.isValid.value), M = d(() => e.isValidated.value), $ = d(() => Z(c(e.errors), r));
379
+ }), f = d(() => c().some((i) => i.dirty.value)), p = d(() => c().some((i) => i.touched.value)), D = d(() => e.isValid.value), C = d(() => e.isValidated.value), M = d(() => k(u(e.errors), r));
359
380
  return {
360
381
  data: a,
361
382
  initialData: s,
362
383
  defineField: v,
363
- getField: u,
364
- getFields: o,
384
+ getField: o,
385
+ getFields: l,
365
386
  isDirty: f,
366
387
  isTouched: p,
367
- isValid: w,
368
- isValidated: M,
369
- errors: $,
388
+ isValid: D,
389
+ isValidated: C,
390
+ errors: M,
370
391
  defineValidator: (i) => {
371
- const h = _(i) ? i : P(i), g = d(
372
- () => new ir(r, c(h))
392
+ const h = _(i) ? i : j(i), g = d(
393
+ () => new nr(r, u(h))
373
394
  );
374
395
  return e.defineValidator(g), h;
375
396
  },
376
- reset: () => l().forEach((i) => i.reset()),
397
+ reset: () => c().forEach((i) => i.reset()),
377
398
  validateForm: () => e.validateForm(),
378
399
  getSubForm: (i, h) => {
379
- const g = E(r, i);
400
+ const g = m(r, i);
380
401
  return e.getSubForm(
381
402
  g,
382
403
  h
@@ -384,28 +405,30 @@ function nr(e, r, t) {
384
405
  }
385
406
  };
386
407
  }
387
- function vr(e) {
388
- const r = d(() => Object.freeze(y(e.initialData))), t = A(y(r)), a = b({
408
+ function pr(e) {
409
+ const r = d(() => Object.freeze(F(e.initialData))), t = y(F(r)), a = w({
389
410
  initialData: r,
390
411
  data: t
391
- }), s = H(a), n = sr(a, e), u = Q(s), v = () => {
392
- t.value = y(r), s.getFields().forEach((f) => f.reset());
412
+ }), s = Q(a), n = ir(a, e), o = X(s), v = () => {
413
+ t.value = F(r), s.getFields().forEach(
414
+ (f) => f.reset()
415
+ );
393
416
  };
394
- function o(f, p) {
395
- return nr(l, f);
417
+ function l(f, p) {
418
+ return or(c, f);
396
419
  }
397
- const l = {
420
+ const c = {
398
421
  ...s,
399
422
  ...n,
400
- ...u,
423
+ ...o,
401
424
  reset: v,
402
- getSubForm: o,
403
- initialData: S(a, "initialData"),
404
- data: S(a, "data")
425
+ getSubForm: l,
426
+ initialData: P(a, "initialData"),
427
+ data: P(a, "data")
405
428
  };
406
- return l;
429
+ return c;
407
430
  }
408
- const pr = /* @__PURE__ */ T({
431
+ const Vr = /* @__PURE__ */ T({
409
432
  __name: "Field",
410
433
  props: {
411
434
  form: {},
@@ -416,13 +439,12 @@ const pr = /* @__PURE__ */ T({
416
439
  },
417
440
  setup(e) {
418
441
  const r = e, t = r.form.defineField({
419
- path: r.path,
420
- required: r.required
442
+ path: r.path
421
443
  });
422
- return (a, s) => B(a.$slots, "default", G(L(c(t))));
444
+ return (a, s) => G(a.$slots, "default", L(U(w(u(t)))));
423
445
  }
424
446
  });
425
447
  export {
426
- pr as Field,
427
- vr as useForm
448
+ Vr as Field,
449
+ pr as useForm
428
450
  };
@@ -19,18 +19,22 @@ export interface FormField<T, P extends string> {
19
19
  setErrors: (newErrors: ValidationErrorMessage[]) => void;
20
20
  clearErrors: () => void;
21
21
  }
22
+ export type FieldsTuple<T, TPaths = Paths<T>> = [
23
+ ...(TPaths extends infer P ? P extends string ? FormField<PickProps<T, P>, P> : never : never)[]
24
+ ];
25
+ export type AnyField<T> = FormField<PickProps<T, Paths<T>>, Paths<T>>;
22
26
  export interface Form<T extends FormDataDefault> {
23
27
  data: Ref<T>;
24
28
  initialData: Readonly<Ref<T>>;
25
29
  defineField: <P extends Paths<T>>(options: DefineFieldOptions<PickProps<T, P>, P>) => FormField<PickProps<T, P>, P>;
26
- getField: <P extends Paths<T>>(path: P) => FormField<PickProps<T, P>, P> | undefined;
27
- getFields: () => FormField<PickProps<T, Paths<T>>, Paths<T>>[];
30
+ getField: <P extends Paths<T>>(path: P) => FormField<PickProps<T, P>, P>;
31
+ getFields: <TData extends T>() => FieldsTuple<TData>;
28
32
  isDirty: Ref<boolean>;
29
33
  isTouched: Ref<boolean>;
30
34
  isValid: Ref<boolean>;
31
35
  isValidated: Ref<boolean>;
32
36
  errors: Ref<ErrorBag>;
33
- defineValidator: (options: ValidatorOptions<T> | Ref<Validator<T>>) => Ref<Validator<T> | undefined>;
37
+ defineValidator: <TData extends T>(options: ValidatorOptions<TData> | Ref<Validator<TData>>) => Ref<Validator<TData> | undefined>;
34
38
  reset: () => void;
35
39
  validateForm: () => Promise<ValidationResult>;
36
40
  getSubForm: <P extends EntityPaths<T>>(path: P, options?: SubformOptions<PickEntity<T, P>>) => Form<PickEntity<T, P>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnovu/kit-vue-forms",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -1,11 +1,12 @@
1
1
  <template>
2
- <slot v-bind="field" />
2
+ <slot v-bind="reactive(field)" />
3
3
  </template>
4
4
 
5
5
  <script
6
6
  setup lang="ts"
7
7
  generic="TData extends object, TPath extends Paths<TData>"
8
8
  >
9
+ import { reactive } from 'vue'
9
10
  import type { Form } from '../types/form.ts'
10
11
  import type { Paths, PickProps } from '../types/util.ts'
11
12
  import type { UseFieldOptions } from '../composables/useField.ts'
@@ -18,6 +19,5 @@ const props = defineProps<FieldProps<TData, TPath>>()
18
19
 
19
20
  const field = props.form.defineField({
20
21
  path: props.path,
21
- required: props.required,
22
22
  })
23
23
  </script>
@@ -1,4 +1,4 @@
1
- import { computed, reactive, toRefs, unref, watch, type MaybeRef, type MaybeRefOrGetter } from 'vue'
1
+ import { computed, reactive, ref, toRefs, unref, watch, type MaybeRef, type MaybeRefOrGetter } 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'
@@ -10,6 +10,23 @@ export interface UseFieldOptions<T, K extends string> {
10
10
  errors?: MaybeRef<ValidationErrors>
11
11
  }
12
12
 
13
+ export function getEmptyField(): FormField<unknown, string> {
14
+ return {
15
+ setData: () => {},
16
+ onBlur: () => {},
17
+ onFocus: () => {},
18
+ reset: () => {},
19
+ setErrors: () => {},
20
+ clearErrors: () => {},
21
+ data: ref(undefined),
22
+ initialValue: ref(undefined),
23
+ path: ref(''),
24
+ errors: ref([]),
25
+ touched: ref(false),
26
+ dirty: computed(() => false),
27
+ }
28
+ }
29
+
13
30
  export function useField<T, K extends string>(options: UseFieldOptions<T, K>): FormField<T, K> {
14
31
  const state = reactive({
15
32
  value: options.value,
@@ -1,8 +1,8 @@
1
1
  import { computed, toRef, unref } from 'vue'
2
- import type { FormDataDefault, FormField } from '../types/form'
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 { useField, type UseFieldOptions } from './useField'
5
+ import { getEmptyField, useField, type UseFieldOptions } from './useField'
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
8
  type FieldRegistryCache<T> = Record<Paths<T>, FormField<any, string>>
@@ -26,12 +26,18 @@ export function useFieldRegistry<T extends FormDataDefault>(
26
26
  fields[path] = field
27
27
  }
28
28
 
29
- const getField = <K extends Paths<T>>(path: K) => {
30
- return (fields[path] ?? {}) as ResolvedFormField<T, K>
29
+ const getField = <K extends Paths<T>>(path: K): ResolvedFormField<T, K> => {
30
+ if (!(path in fields)) {
31
+ console.warn(`Field with path "${path}" is not registered.`)
32
+
33
+ return getEmptyField() as ResolvedFormField<T, K>
34
+ }
35
+
36
+ return fields[path] as ResolvedFormField<T, K>
31
37
  }
32
38
 
33
- const getFields = () => {
34
- return Object.values(fields) as ResolvedFormField<T, Paths<T>>[]
39
+ const getFields = <TData extends T>() => {
40
+ return Object.values(fields) as FieldsTuple<TData>
35
41
  }
36
42
 
37
43
  const defineField = <K extends Paths<T>>(options: DefineFieldOptions<PickProps<T, K>, K>) => {
@@ -1,5 +1,5 @@
1
1
  import { computed, reactive, ref, toRef, type MaybeRef, type MaybeRefOrGetter, type Ref } from 'vue'
2
- import type { Form, FormDataDefault } from '../types/form'
2
+ import type { AnyField, Form, FormDataDefault } from '../types/form'
3
3
  import type { EntityPaths, PickEntity } from '../types/util'
4
4
  import type { ValidationStrategy } from '../types/validation'
5
5
  import { cloneRefValue } from '../utils/general'
@@ -32,7 +32,9 @@ export function useForm<T extends FormDataDefault>(options: UseFormOptions<T>) {
32
32
 
33
33
  const reset = () => {
34
34
  data.value = cloneRefValue(initialData)
35
- fields.getFields().forEach(field => field.reset())
35
+ fields.getFields().forEach(
36
+ (field: AnyField<T>) => field.reset(),
37
+ )
36
38
  }
37
39
 
38
40
  function getSubForm<K extends EntityPaths<T>>(
@@ -1,16 +1,16 @@
1
1
  import { computed, unref } from 'vue'
2
- import type { FormDataDefault } from '../types/form'
2
+ import type { AnyField, FormDataDefault } from '../types/form'
3
3
  import type { FieldRegistry } from './useFieldRegistry'
4
4
 
5
5
  export function useFormState<T extends FormDataDefault>(
6
6
  formFieldRegistry: FieldRegistry<T>,
7
7
  ) {
8
8
  const isDirty = computed(() => {
9
- return formFieldRegistry.getFields().some(field => unref(field.dirty))
9
+ return formFieldRegistry.getFields().some((field: AnyField<T>) => unref(field.dirty))
10
10
  })
11
11
 
12
12
  const isTouched = computed(() => {
13
- return formFieldRegistry.getFields().some(field => unref(field.touched))
13
+ return formFieldRegistry.getFields().some((field: AnyField<T>) => unref(field.touched))
14
14
  })
15
15
 
16
16
  return {
@@ -1,5 +1,5 @@
1
1
  import { computed, isRef, unref, type Ref } from 'vue'
2
- import type { Form, FormDataDefault, FormField } from '../types/form'
2
+ import type { FieldsTuple, Form, FormDataDefault, FormField } from '../types/form'
3
3
  import type { EntityPaths, Paths, PickEntity, PickProps } from '../types/util'
4
4
  import type { ValidationResult, Validator } from '../types/validation'
5
5
  import { filterErrorsForPath, getLens, getNestedValue, joinPath } from '../utils/path'
@@ -81,7 +81,7 @@ export function createSubformInterface<
81
81
  const mainFormField = mainForm.getField(fullPath as ScopedMainPaths)
82
82
 
83
83
  if (!mainFormField) {
84
- return
84
+ return {} as FormField<PickProps<ST, P>, P>
85
85
  }
86
86
 
87
87
  return adaptMainFormField<P>(mainFormField)
@@ -99,13 +99,13 @@ export function createSubformInterface<
99
99
  return adaptMainFormField<P>(mainField)
100
100
  }
101
101
 
102
- const getFields = <P extends SP>(): FormField<PickProps<ST, P>, P>[] => {
102
+ const getFields = <P extends SP>() => {
103
103
  return (mainForm.getFields() as FormField<PickProps<T, ScopedMainPaths>, ScopedMainPaths>[])
104
104
  .filter((field) => {
105
105
  const fieldPath = field.path.value
106
106
  return fieldPath.startsWith(path + '.') || fieldPath === path
107
107
  })
108
- .map(field => adaptMainFormField(field))
108
+ .map(field => adaptMainFormField(field)) as FieldsTuple<ST, P>
109
109
  }
110
110
 
111
111
  // Helper function to get all fields without type parameter
@@ -155,10 +155,10 @@ export function useValidation<T extends FormDataDefault>(
155
155
  }
156
156
  })
157
157
 
158
- const defineValidator = (options: ValidatorOptions<T> | Ref<Validator<T>>) => {
158
+ const defineValidator = <TData extends T>(options: ValidatorOptions<TData> | Ref<Validator<TData>>) => {
159
159
  const validator = isRef(options) ? options : createValidator(options)
160
160
 
161
- validationState.validators.push(validator)
161
+ validationState.validators.push(validator as Ref<Validator<T> | undefined>)
162
162
 
163
163
  if (getCurrentScope()) {
164
164
  onBeforeUnmount(() => {
package/src/types/form.ts CHANGED
@@ -22,6 +22,16 @@ export interface FormField<T, P extends string> {
22
22
  clearErrors: () => void
23
23
  }
24
24
 
25
+ export type FieldsTuple<T, TPaths = Paths<T>> = [...(
26
+ TPaths extends infer P
27
+ ? P extends string
28
+ ? FormField<PickProps<T, P>, P>
29
+ : never
30
+ : never
31
+ )[]]
32
+
33
+ export type AnyField<T> = FormField<PickProps<T, Paths<T>>, Paths<T>>
34
+
25
35
  export interface Form<T extends FormDataDefault> {
26
36
  // Data properties
27
37
  data: Ref<T>
@@ -29,8 +39,8 @@ export interface Form<T extends FormDataDefault> {
29
39
 
30
40
  // Field operations
31
41
  defineField: <P extends Paths<T>>(options: DefineFieldOptions<PickProps<T, P>, P>) => FormField<PickProps<T, P>, P>
32
- getField: <P extends Paths<T>>(path: P) => FormField<PickProps<T, P>, P> | undefined
33
- getFields: () => FormField<PickProps<T, Paths<T>>, Paths<T>>[]
42
+ getField: <P extends Paths<T>>(path: P) => FormField<PickProps<T, P>, P>
43
+ getFields: <TData extends T>() => FieldsTuple<TData>
34
44
 
35
45
  // State properties
36
46
  isDirty: Ref<boolean>
@@ -39,7 +49,7 @@ export interface Form<T extends FormDataDefault> {
39
49
  isValidated: Ref<boolean>
40
50
  errors: Ref<ErrorBag>
41
51
 
42
- defineValidator: (options: ValidatorOptions<T> | Ref<Validator<T>>) => Ref<Validator<T> | undefined>
52
+ defineValidator: <TData extends T>(options: ValidatorOptions<TData> | Ref<Validator<TData>>) => Ref<Validator<TData> | undefined>
43
53
 
44
54
  // Operations
45
55
  reset: () => void
package/tsconfig.json CHANGED
@@ -4,12 +4,11 @@
4
4
  "outDir": "dist",
5
5
  "verbatimModuleSyntax": true,
6
6
  "types": [
7
- "vue",
8
- "vite/client",
9
- ],
7
+ "vite/client"
8
+ ]
10
9
  },
11
10
  "include": [
12
- "src/**/*",
11
+ "src/**/*"
13
12
  ],
14
13
  "exclude": [
15
14
  "dist",