@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.
- package/dist/components/Field.vue.d.ts +7 -7
- package/dist/composables/useField.d.ts +1 -0
- package/dist/composables/useFieldRegistry.d.ts +2 -2
- package/dist/composables/useValidation.d.ts +1 -1
- package/dist/index.mjs +160 -138
- package/dist/types/form.d.ts +7 -3
- package/package.json +1 -1
- package/src/components/Field.vue +2 -2
- package/src/composables/useField.ts +18 -1
- package/src/composables/useFieldRegistry.ts +12 -6
- package/src/composables/useForm.ts +4 -2
- package/src/composables/useFormState.ts +3 -3
- package/src/composables/useSubform.ts +4 -4
- package/src/composables/useValidation.ts +2 -2
- package/src/types/form.ts +13 -3
- package/tsconfig.json +3 -4
|
@@ -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,
|
|
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:
|
|
16
|
-
path:
|
|
17
|
-
initialValue:
|
|
18
|
-
errors:
|
|
19
|
-
touched:
|
|
20
|
-
dirty:
|
|
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: () =>
|
|
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<
|
|
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
|
|
4
|
-
import { toValue as W, toRaw as
|
|
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
|
|
7
|
-
const r = W(e), t =
|
|
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
|
|
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
|
|
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
|
-
(
|
|
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
|
|
30
|
+
const $ = (e, r) => d({
|
|
31
31
|
get() {
|
|
32
|
-
return
|
|
32
|
+
return R(u(e), u(r));
|
|
33
33
|
},
|
|
34
34
|
set(t) {
|
|
35
|
-
|
|
35
|
+
Z(u(e), u(r), t);
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
|
-
function
|
|
38
|
+
function m(e, r) {
|
|
39
39
|
return !e && !r ? "" : !e && r ? r : !r && e ? e : `${e}.${r}`;
|
|
40
40
|
}
|
|
41
|
-
function
|
|
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
|
|
56
|
-
|
|
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(
|
|
60
|
-
errors:
|
|
81
|
+
initialValue: d(() => Object.freeze(F(e.initialValue))),
|
|
82
|
+
errors: u(e.errors) || [],
|
|
61
83
|
touched: !1
|
|
62
84
|
});
|
|
63
|
-
|
|
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
|
-
},
|
|
72
|
-
r.value =
|
|
93
|
+
}, o = () => {
|
|
94
|
+
r.value = F(r.initialValue), r.touched = !1, r.errors = [];
|
|
73
95
|
}, v = (f) => {
|
|
74
96
|
r.errors = f;
|
|
75
|
-
},
|
|
97
|
+
}, l = () => {
|
|
76
98
|
r.errors = [];
|
|
77
|
-
},
|
|
99
|
+
}, c = A(r);
|
|
78
100
|
return {
|
|
79
|
-
data:
|
|
80
|
-
path:
|
|
81
|
-
initialValue:
|
|
82
|
-
errors:
|
|
83
|
-
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:
|
|
110
|
+
reset: o,
|
|
89
111
|
setErrors: v,
|
|
90
|
-
clearErrors:
|
|
112
|
+
clearErrors: l
|
|
91
113
|
};
|
|
92
114
|
}
|
|
93
|
-
function
|
|
94
|
-
const r = {}, t = (
|
|
95
|
-
const v =
|
|
96
|
-
r[v] =
|
|
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: (
|
|
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: (
|
|
104
|
-
const v =
|
|
105
|
-
...
|
|
106
|
-
value:
|
|
107
|
-
initialValue: d(() =>
|
|
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
|
|
114
|
-
const r = d(() => e.getFields().some((a) =>
|
|
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
|
|
142
|
+
function Y(e) {
|
|
121
143
|
return e.filter(
|
|
122
144
|
(r, t, a) => a.indexOf(r) === t
|
|
123
145
|
);
|
|
124
146
|
}
|
|
125
|
-
function
|
|
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
|
|
157
|
+
return Y(s);
|
|
136
158
|
}, e[0]);
|
|
137
159
|
}
|
|
138
|
-
function
|
|
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]:
|
|
165
|
+
[a]: z(...s)
|
|
144
166
|
};
|
|
145
167
|
}, {});
|
|
146
168
|
}
|
|
147
|
-
function
|
|
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:
|
|
157
|
-
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
250
|
+
class sr {
|
|
229
251
|
constructor(r, t) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
this.schema = r, this.validateFn = t, this.schemaValidator = new
|
|
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:
|
|
263
|
+
errors: b(t.errors, a.errors)
|
|
242
264
|
};
|
|
243
265
|
}
|
|
244
266
|
}
|
|
245
|
-
function
|
|
246
|
-
return d(() => new
|
|
247
|
-
|
|
248
|
-
|
|
267
|
+
function j(e) {
|
|
268
|
+
return d(() => new sr(
|
|
269
|
+
u(e.schema),
|
|
270
|
+
u(e.validateFn)
|
|
249
271
|
));
|
|
250
272
|
}
|
|
251
|
-
function
|
|
252
|
-
const t =
|
|
253
|
-
validators:
|
|
273
|
+
function ir(e, r) {
|
|
274
|
+
const t = w({
|
|
275
|
+
validators: y([j(r)]),
|
|
254
276
|
isValidated: !1,
|
|
255
|
-
errors:
|
|
277
|
+
errors: u(r.errors) ?? V.errors
|
|
256
278
|
});
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
n(
|
|
260
|
-
}, { immediate: !0 }),
|
|
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 (
|
|
284
|
+
async (l) => {
|
|
263
285
|
if (t.isValidated)
|
|
264
|
-
if (
|
|
265
|
-
const
|
|
266
|
-
t.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
|
-
),
|
|
272
|
-
t.isValidated &&
|
|
293
|
+
), E(() => e.data, () => {
|
|
294
|
+
t.isValidated && o();
|
|
273
295
|
});
|
|
274
|
-
const a = (
|
|
275
|
-
const
|
|
276
|
-
return t.validators.push(
|
|
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 !==
|
|
300
|
+
(f) => f !== c
|
|
279
301
|
);
|
|
280
|
-
}),
|
|
302
|
+
}), c;
|
|
281
303
|
};
|
|
282
304
|
async function s() {
|
|
283
|
-
const
|
|
284
|
-
t.validators.filter((p) =>
|
|
285
|
-
),
|
|
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 (!
|
|
288
|
-
const p =
|
|
289
|
-
f =
|
|
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:
|
|
315
|
+
isValid: c
|
|
294
316
|
};
|
|
295
317
|
}
|
|
296
|
-
const n = (
|
|
297
|
-
t.errors =
|
|
298
|
-
},
|
|
299
|
-
const
|
|
300
|
-
return n(
|
|
301
|
-
isValid: !
|
|
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(() => !
|
|
326
|
+
}, v = d(() => !O(t.errors));
|
|
305
327
|
return {
|
|
306
|
-
...
|
|
307
|
-
validateForm:
|
|
328
|
+
...A(t),
|
|
329
|
+
validateForm: o,
|
|
308
330
|
defineValidator: a,
|
|
309
331
|
isValid: v
|
|
310
332
|
};
|
|
311
333
|
}
|
|
312
|
-
class
|
|
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 =
|
|
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
|
-
|
|
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
|
|
336
|
-
const a =
|
|
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(() =>
|
|
360
|
+
path: d(() => u(i.path).replace(r + ".", "")),
|
|
339
361
|
setData: (h) => {
|
|
340
362
|
i.setData(h);
|
|
341
363
|
}
|
|
342
|
-
}),
|
|
343
|
-
const h =
|
|
344
|
-
|
|
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 =
|
|
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
|
-
},
|
|
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)),
|
|
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(() =>
|
|
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:
|
|
364
|
-
getFields:
|
|
384
|
+
getField: o,
|
|
385
|
+
getFields: l,
|
|
365
386
|
isDirty: f,
|
|
366
387
|
isTouched: p,
|
|
367
|
-
isValid:
|
|
368
|
-
isValidated:
|
|
369
|
-
errors:
|
|
388
|
+
isValid: D,
|
|
389
|
+
isValidated: C,
|
|
390
|
+
errors: M,
|
|
370
391
|
defineValidator: (i) => {
|
|
371
|
-
const h = _(i) ? i :
|
|
372
|
-
() => new
|
|
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: () =>
|
|
397
|
+
reset: () => c().forEach((i) => i.reset()),
|
|
377
398
|
validateForm: () => e.validateForm(),
|
|
378
399
|
getSubForm: (i, h) => {
|
|
379
|
-
const g =
|
|
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
|
|
388
|
-
const r = d(() => Object.freeze(
|
|
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 =
|
|
392
|
-
t.value =
|
|
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
|
|
395
|
-
return
|
|
417
|
+
function l(f, p) {
|
|
418
|
+
return or(c, f);
|
|
396
419
|
}
|
|
397
|
-
const
|
|
420
|
+
const c = {
|
|
398
421
|
...s,
|
|
399
422
|
...n,
|
|
400
|
-
...
|
|
423
|
+
...o,
|
|
401
424
|
reset: v,
|
|
402
|
-
getSubForm:
|
|
403
|
-
initialData:
|
|
404
|
-
data:
|
|
425
|
+
getSubForm: l,
|
|
426
|
+
initialData: P(a, "initialData"),
|
|
427
|
+
data: P(a, "data")
|
|
405
428
|
};
|
|
406
|
-
return
|
|
429
|
+
return c;
|
|
407
430
|
}
|
|
408
|
-
const
|
|
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) =>
|
|
444
|
+
return (a, s) => G(a.$slots, "default", L(U(w(u(t)))));
|
|
423
445
|
}
|
|
424
446
|
});
|
|
425
447
|
export {
|
|
426
|
-
|
|
427
|
-
|
|
448
|
+
Vr as Field,
|
|
449
|
+
pr as useForm
|
|
428
450
|
};
|
package/dist/types/form.d.ts
CHANGED
|
@@ -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
|
|
27
|
-
getFields: () =>
|
|
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<
|
|
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
package/src/components/Field.vue
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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(
|
|
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>()
|
|
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<
|
|
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>
|
|
33
|
-
getFields: () =>
|
|
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<
|
|
52
|
+
defineValidator: <TData extends T>(options: ValidatorOptions<TData> | Ref<Validator<TData>>) => Ref<Validator<TData> | undefined>
|
|
43
53
|
|
|
44
54
|
// Operations
|
|
45
55
|
reset: () => void
|