@formisch/preact 0.3.0 → 0.4.0
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/README.md +2 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +144 -104
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Formisch is a schema-based, headless form library for Preact. It manages form state and validation. It is type-safe, fast by default and its bundle size is small due to its modular design. Try it out in our [playground](https://stackblitz.com/edit/formisch-playground-preact)!
|
|
4
4
|
|
|
5
|
-
Formisch is also available for [Qwik][formisch-qwik], [SolidJS][formisch-solid], and [Vue][formisch-vue].
|
|
5
|
+
Formisch is also available for [Qwik][formisch-qwik], [SolidJS][formisch-solid], [Svelte][formisch-svelte] and [Vue][formisch-vue].
|
|
6
6
|
|
|
7
7
|
## Highlights
|
|
8
8
|
|
|
@@ -77,4 +77,5 @@ This project is available free of charge and licensed under the [MIT license](ht
|
|
|
77
77
|
|
|
78
78
|
[formisch-qwik]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/qwik
|
|
79
79
|
[formisch-solid]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/solid
|
|
80
|
+
[formisch-svelte]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/svelte
|
|
80
81
|
[formisch-vue]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/vue
|
package/dist/index.d.ts
CHANGED
|
@@ -18,29 +18,34 @@ interface InternalBaseStore {
|
|
|
18
18
|
kind: "array" | "object" | "value";
|
|
19
19
|
name: string;
|
|
20
20
|
schema: Schema;
|
|
21
|
+
initialElements: FieldElement[];
|
|
21
22
|
elements: FieldElement[];
|
|
22
23
|
errors: Signal<[string, ...string[]] | null>;
|
|
24
|
+
isTouched: Signal<boolean>;
|
|
25
|
+
isDirty: Signal<boolean>;
|
|
23
26
|
}
|
|
24
27
|
interface InternalArrayStore extends InternalBaseStore {
|
|
25
28
|
kind: "array";
|
|
26
29
|
children: InternalFieldStore[];
|
|
30
|
+
initialInput: Signal<true | null | undefined>;
|
|
31
|
+
startInput: Signal<true | null | undefined>;
|
|
32
|
+
input: Signal<true | null | undefined>;
|
|
27
33
|
initialItems: Signal<string[]>;
|
|
28
34
|
startItems: Signal<string[]>;
|
|
29
35
|
items: Signal<string[]>;
|
|
30
|
-
isTouched: Signal<boolean>;
|
|
31
|
-
isDirty: Signal<boolean>;
|
|
32
36
|
}
|
|
33
37
|
interface InternalObjectStore extends InternalBaseStore {
|
|
34
38
|
kind: "object";
|
|
35
39
|
children: Record<string, InternalFieldStore>;
|
|
40
|
+
initialInput: Signal<true | null | undefined>;
|
|
41
|
+
startInput: Signal<true | null | undefined>;
|
|
42
|
+
input: Signal<true | null | undefined>;
|
|
36
43
|
}
|
|
37
44
|
interface InternalValueStore extends InternalBaseStore {
|
|
38
45
|
kind: "value";
|
|
39
46
|
initialInput: Signal<unknown>;
|
|
40
47
|
startInput: Signal<unknown>;
|
|
41
48
|
input: Signal<unknown>;
|
|
42
|
-
isTouched: Signal<boolean>;
|
|
43
|
-
isDirty: Signal<boolean>;
|
|
44
49
|
}
|
|
45
50
|
type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalValueStore;
|
|
46
51
|
//#endregion
|
|
@@ -372,7 +377,7 @@ declare function FieldArray<TSchema extends Schema, TFieldArrayPath extends Requ
|
|
|
372
377
|
}: FieldArrayProps<TSchema, TFieldArrayPath>): JSX.Element;
|
|
373
378
|
//#endregion
|
|
374
379
|
//#region src/components/Form/Form.d.ts
|
|
375
|
-
type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> & {
|
|
380
|
+
type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "novalidate" | "noValidate"> & {
|
|
376
381
|
of: FormStore<TSchema>;
|
|
377
382
|
onSubmit: SubmitHandler<TSchema>;
|
|
378
383
|
};
|
package/dist/index.js
CHANGED
|
@@ -12,16 +12,21 @@ function createId() {
|
|
|
12
12
|
* TODO: Add comment
|
|
13
13
|
* TODO: Should this stay in /primitives or move to /utils?
|
|
14
14
|
*/
|
|
15
|
-
function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
15
|
+
function initializeFieldStore(internalFieldStore, schema, initialInput, path, nullish = false) {
|
|
16
16
|
if (framework === "qwik" && schema.type === "lazy" || schema.type === "object_with_rest" || schema.type === "record" || schema.type === "tuple_with_rest" || schema.type === "promise") throw new Error(`"${schema.type}" schema is not supported`);
|
|
17
17
|
else if (schema.type === "lazy") initializeFieldStore(internalFieldStore, schema.getter(void 0), initialInput, path);
|
|
18
|
-
else if (schema.type === "exact_optional" || schema.type === "
|
|
18
|
+
else if (schema.type === "exact_optional" || schema.type === "nullable" || schema.type === "nullish" || schema.type === "optional" || schema.type === "undefinedable") initializeFieldStore(internalFieldStore, schema.wrapped, initialInput ?? v.getDefault(schema), path, true);
|
|
19
|
+
else if (schema.type === "non_nullable" || schema.type === "non_nullish" || schema.type === "non_optional") initializeFieldStore(internalFieldStore, schema.wrapped, initialInput, path);
|
|
19
20
|
else if (schema.type === "intersect" || schema.type === "union" || schema.type === "variant") for (const schemaOption of schema.options) initializeFieldStore(internalFieldStore, schemaOption, initialInput, path);
|
|
20
21
|
else {
|
|
21
22
|
internalFieldStore.schema = schema;
|
|
22
23
|
internalFieldStore.name = JSON.stringify(path);
|
|
23
|
-
|
|
24
|
+
const initialElements = [];
|
|
25
|
+
internalFieldStore.initialElements = initialElements;
|
|
26
|
+
internalFieldStore.elements = initialElements;
|
|
24
27
|
internalFieldStore.errors = createSignal(null);
|
|
28
|
+
internalFieldStore.isTouched = createSignal(false);
|
|
29
|
+
internalFieldStore.isDirty = createSignal(false);
|
|
25
30
|
if (schema.type === "array" || schema.type === "loose_tuple" || schema.type === "strict_tuple" || schema.type === "tuple") {
|
|
26
31
|
if (internalFieldStore.kind && internalFieldStore.kind !== "array") throw new Error(`Store initialized as "${internalFieldStore.kind}" cannot be reinitialized as "array"`);
|
|
27
32
|
internalFieldStore.kind = "array";
|
|
@@ -37,15 +42,17 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
37
42
|
} else for (let index = 0; index < schema.items; index++) {
|
|
38
43
|
internalFieldStore.children[index] = {};
|
|
39
44
|
path.push(index);
|
|
40
|
-
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput
|
|
45
|
+
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
|
|
41
46
|
path.pop();
|
|
42
47
|
}
|
|
48
|
+
const arrayInput = nullish && initialInput == null ? initialInput : true;
|
|
49
|
+
internalFieldStore.initialInput = createSignal(arrayInput);
|
|
50
|
+
internalFieldStore.startInput = createSignal(arrayInput);
|
|
51
|
+
internalFieldStore.input = createSignal(arrayInput);
|
|
43
52
|
const initialItems = internalFieldStore.children.map(createId);
|
|
44
53
|
internalFieldStore.initialItems = createSignal(initialItems);
|
|
45
54
|
internalFieldStore.startItems = createSignal(initialItems);
|
|
46
55
|
internalFieldStore.items = createSignal(initialItems);
|
|
47
|
-
internalFieldStore.isTouched = createSignal(false);
|
|
48
|
-
internalFieldStore.isDirty = createSignal(false);
|
|
49
56
|
}
|
|
50
57
|
} else if (schema.type === "loose_object" || schema.type === "object" || schema.type === "strict_object") {
|
|
51
58
|
if (internalFieldStore.kind && internalFieldStore.kind !== "object") throw new Error(`Store initialized as "${internalFieldStore.kind}" cannot be reinitialized as "object"`);
|
|
@@ -55,9 +62,13 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
55
62
|
for (const key in schema.entries) {
|
|
56
63
|
internalFieldStore.children[key] = {};
|
|
57
64
|
path.push(key);
|
|
58
|
-
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput
|
|
65
|
+
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
59
66
|
path.pop();
|
|
60
67
|
}
|
|
68
|
+
const objectInput = nullish && initialInput == null ? initialInput : true;
|
|
69
|
+
internalFieldStore.initialInput = createSignal(objectInput);
|
|
70
|
+
internalFieldStore.startInput = createSignal(objectInput);
|
|
71
|
+
internalFieldStore.input = createSignal(objectInput);
|
|
61
72
|
}
|
|
62
73
|
} else {
|
|
63
74
|
internalFieldStore.kind = "value";
|
|
@@ -65,8 +76,6 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
65
76
|
internalFieldStore.initialInput = createSignal(initialInput);
|
|
66
77
|
internalFieldStore.startInput = createSignal(initialInput);
|
|
67
78
|
internalFieldStore.input = createSignal(initialInput);
|
|
68
|
-
internalFieldStore.isTouched = createSignal(false);
|
|
69
|
-
internalFieldStore.isDirty = createSignal(false);
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
81
|
}
|
|
@@ -83,10 +92,14 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
83
92
|
function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
84
93
|
batch(() => {
|
|
85
94
|
untrack(() => {
|
|
95
|
+
toInternalFieldStore.elements = fromInternalFieldStore.elements;
|
|
96
|
+
toInternalFieldStore.errors.value = fromInternalFieldStore.errors.value;
|
|
97
|
+
toInternalFieldStore.startInput.value = fromInternalFieldStore.startInput.value;
|
|
98
|
+
toInternalFieldStore.input.value = fromInternalFieldStore.input.value;
|
|
99
|
+
toInternalFieldStore.isTouched.value = fromInternalFieldStore.isTouched.value;
|
|
100
|
+
toInternalFieldStore.isDirty.value = fromInternalFieldStore.isDirty.value;
|
|
86
101
|
if (fromInternalFieldStore.kind === "array" && toInternalFieldStore.kind === "array") {
|
|
87
102
|
const fromItems = fromInternalFieldStore.items.value;
|
|
88
|
-
toInternalFieldStore.isTouched.value = fromInternalFieldStore.isTouched.value;
|
|
89
|
-
toInternalFieldStore.isDirty.value = fromInternalFieldStore.isDirty.value;
|
|
90
103
|
toInternalFieldStore.startItems.value = fromInternalFieldStore.startItems.value;
|
|
91
104
|
toInternalFieldStore.items.value = fromItems;
|
|
92
105
|
let path;
|
|
@@ -101,12 +114,6 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
101
114
|
copyItemState(fromInternalFieldStore.children[index], toInternalFieldStore.children[index]);
|
|
102
115
|
}
|
|
103
116
|
} else if (fromInternalFieldStore.kind === "object" && toInternalFieldStore.kind === "object") for (const key in fromInternalFieldStore.children) copyItemState(fromInternalFieldStore.children[key], toInternalFieldStore.children[key]);
|
|
104
|
-
else if (fromInternalFieldStore.kind === "value" && toInternalFieldStore.kind === "value") {
|
|
105
|
-
toInternalFieldStore.isTouched.value = fromInternalFieldStore.isTouched.value;
|
|
106
|
-
toInternalFieldStore.isDirty.value = fromInternalFieldStore.isDirty.value;
|
|
107
|
-
toInternalFieldStore.startInput.value = fromInternalFieldStore.startInput.value;
|
|
108
|
-
toInternalFieldStore.input.value = fromInternalFieldStore.input.value;
|
|
109
|
-
}
|
|
110
117
|
});
|
|
111
118
|
});
|
|
112
119
|
}
|
|
@@ -121,11 +128,15 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
121
128
|
*/
|
|
122
129
|
function resetItemState(internalFieldStore, initialInput) {
|
|
123
130
|
batch(() => {
|
|
131
|
+
internalFieldStore.elements = [];
|
|
124
132
|
internalFieldStore.errors.value = null;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
133
|
+
internalFieldStore.isTouched.value = false;
|
|
134
|
+
internalFieldStore.isDirty.value = false;
|
|
135
|
+
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
136
|
+
const objectInput = initialInput == null ? initialInput : true;
|
|
137
|
+
internalFieldStore.startInput.value = objectInput;
|
|
138
|
+
internalFieldStore.input.value = objectInput;
|
|
139
|
+
if (internalFieldStore.kind === "array") if (initialInput) {
|
|
129
140
|
const newItems = initialInput.map(createId);
|
|
130
141
|
internalFieldStore.startItems.value = newItems;
|
|
131
142
|
internalFieldStore.items.value = newItems;
|
|
@@ -134,10 +145,8 @@ function resetItemState(internalFieldStore, initialInput) {
|
|
|
134
145
|
internalFieldStore.startItems.value = [];
|
|
135
146
|
internalFieldStore.items.value = [];
|
|
136
147
|
}
|
|
137
|
-
|
|
138
|
-
else {
|
|
139
|
-
internalFieldStore.isTouched.value = false;
|
|
140
|
-
internalFieldStore.isDirty.value = false;
|
|
148
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], initialInput?.[key]);
|
|
149
|
+
} else {
|
|
141
150
|
internalFieldStore.startInput.value = initialInput;
|
|
142
151
|
internalFieldStore.input.value = initialInput;
|
|
143
152
|
}
|
|
@@ -154,15 +163,27 @@ function resetItemState(internalFieldStore, initialInput) {
|
|
|
154
163
|
function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
155
164
|
batch(() => {
|
|
156
165
|
untrack(() => {
|
|
166
|
+
const tempElements = firstInternalFieldStore.elements;
|
|
167
|
+
firstInternalFieldStore.elements = secondInternalFieldStore.elements;
|
|
168
|
+
secondInternalFieldStore.elements = tempElements;
|
|
169
|
+
const tempErrors = firstInternalFieldStore.errors.value;
|
|
170
|
+
firstInternalFieldStore.errors.value = secondInternalFieldStore.errors.value;
|
|
171
|
+
secondInternalFieldStore.errors.value = tempErrors;
|
|
172
|
+
const tempStartInput = firstInternalFieldStore.startInput.value;
|
|
173
|
+
firstInternalFieldStore.startInput.value = secondInternalFieldStore.startInput.value;
|
|
174
|
+
secondInternalFieldStore.startInput.value = tempStartInput;
|
|
175
|
+
const tempInput = firstInternalFieldStore.input.value;
|
|
176
|
+
firstInternalFieldStore.input.value = secondInternalFieldStore.input.value;
|
|
177
|
+
secondInternalFieldStore.input.value = tempInput;
|
|
178
|
+
const tempIsTouched = firstInternalFieldStore.isTouched.value;
|
|
179
|
+
firstInternalFieldStore.isTouched.value = secondInternalFieldStore.isTouched.value;
|
|
180
|
+
secondInternalFieldStore.isTouched.value = tempIsTouched;
|
|
181
|
+
const tempIsDirty = firstInternalFieldStore.isDirty.value;
|
|
182
|
+
firstInternalFieldStore.isDirty.value = secondInternalFieldStore.isDirty.value;
|
|
183
|
+
secondInternalFieldStore.isDirty.value = tempIsDirty;
|
|
157
184
|
if (firstInternalFieldStore.kind === "array" && secondInternalFieldStore.kind === "array") {
|
|
158
185
|
const firstItems = firstInternalFieldStore.items.value;
|
|
159
186
|
const secondItems = secondInternalFieldStore.items.value;
|
|
160
|
-
const tempIsTouched = firstInternalFieldStore.isTouched.value;
|
|
161
|
-
firstInternalFieldStore.isTouched.value = secondInternalFieldStore.isTouched.value;
|
|
162
|
-
secondInternalFieldStore.isTouched.value = tempIsTouched;
|
|
163
|
-
const tempIsDirty = firstInternalFieldStore.isDirty.value;
|
|
164
|
-
firstInternalFieldStore.isDirty.value = secondInternalFieldStore.isDirty.value;
|
|
165
|
-
secondInternalFieldStore.isDirty.value = tempIsDirty;
|
|
166
187
|
const tempStartItems = firstInternalFieldStore.startItems.value;
|
|
167
188
|
firstInternalFieldStore.startItems.value = secondInternalFieldStore.startItems.value;
|
|
168
189
|
secondInternalFieldStore.startItems.value = tempStartItems;
|
|
@@ -189,33 +210,25 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
189
210
|
swapItemState(firstInternalFieldStore.children[index], secondInternalFieldStore.children[index]);
|
|
190
211
|
}
|
|
191
212
|
} else if (firstInternalFieldStore.kind === "object" && secondInternalFieldStore.kind === "object") for (const key in firstInternalFieldStore.children) swapItemState(firstInternalFieldStore.children[key], secondInternalFieldStore.children[key]);
|
|
192
|
-
else if (firstInternalFieldStore.kind === "value" && secondInternalFieldStore.kind === "value") {
|
|
193
|
-
const tempIsTouched = firstInternalFieldStore.isTouched.value;
|
|
194
|
-
firstInternalFieldStore.isTouched.value = secondInternalFieldStore.isTouched.value;
|
|
195
|
-
secondInternalFieldStore.isTouched.value = tempIsTouched;
|
|
196
|
-
const tempIsDirty = firstInternalFieldStore.isDirty.value;
|
|
197
|
-
firstInternalFieldStore.isDirty.value = secondInternalFieldStore.isDirty.value;
|
|
198
|
-
secondInternalFieldStore.isDirty.value = tempIsDirty;
|
|
199
|
-
const tempStartInput = firstInternalFieldStore.startInput.value;
|
|
200
|
-
firstInternalFieldStore.startInput.value = secondInternalFieldStore.startInput.value;
|
|
201
|
-
secondInternalFieldStore.startInput.value = tempStartInput;
|
|
202
|
-
const tempInput = firstInternalFieldStore.input.value;
|
|
203
|
-
firstInternalFieldStore.input.value = secondInternalFieldStore.input.value;
|
|
204
|
-
secondInternalFieldStore.input.value = tempInput;
|
|
205
|
-
}
|
|
206
213
|
});
|
|
207
214
|
});
|
|
208
215
|
}
|
|
209
216
|
function getFieldInput(internalFieldStore) {
|
|
210
217
|
if (internalFieldStore.kind === "array") {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
218
|
+
if (internalFieldStore.input.value) {
|
|
219
|
+
const value = [];
|
|
220
|
+
for (let index = 0; index < internalFieldStore.items.value.length; index++) value[index] = getFieldInput(internalFieldStore.children[index]);
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
return internalFieldStore.input.value;
|
|
214
224
|
}
|
|
215
225
|
if (internalFieldStore.kind === "object") {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
226
|
+
if (internalFieldStore.input.value) {
|
|
227
|
+
const value = {};
|
|
228
|
+
for (const key in internalFieldStore.children) value[key] = getFieldInput(internalFieldStore.children[key]);
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
return internalFieldStore.input.value;
|
|
219
232
|
}
|
|
220
233
|
return internalFieldStore.input.value;
|
|
221
234
|
}
|
|
@@ -246,17 +259,16 @@ function getElementInput(element, internalFieldStore) {
|
|
|
246
259
|
return element.value;
|
|
247
260
|
}
|
|
248
261
|
function getFieldBool(internalFieldStore, type) {
|
|
262
|
+
if (internalFieldStore[type].value) return true;
|
|
249
263
|
if (internalFieldStore.kind === "array") {
|
|
250
|
-
if (internalFieldStore[type].value) return true;
|
|
251
264
|
for (let index = 0; index < internalFieldStore.items.value.length; index++) if (getFieldBool(internalFieldStore.children[index], type)) return true;
|
|
252
265
|
return false;
|
|
253
266
|
}
|
|
254
267
|
if (internalFieldStore.kind == "object") {
|
|
255
|
-
if (type === "errors" && internalFieldStore[type].value) return true;
|
|
256
268
|
for (const key in internalFieldStore.children) if (getFieldBool(internalFieldStore.children[key], type)) return true;
|
|
257
269
|
return false;
|
|
258
270
|
}
|
|
259
|
-
return
|
|
271
|
+
return false;
|
|
260
272
|
}
|
|
261
273
|
function getFieldStore(internalFormStore, path) {
|
|
262
274
|
let internalFieldStore = internalFormStore;
|
|
@@ -272,50 +284,69 @@ function setFieldBool(internalFieldStore, type, bool) {
|
|
|
272
284
|
else internalFieldStore[type].value = bool;
|
|
273
285
|
});
|
|
274
286
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
function setNestedInput(internalFieldStore, input) {
|
|
288
|
+
internalFieldStore.isTouched.value = true;
|
|
289
|
+
if (internalFieldStore.kind === "array") {
|
|
290
|
+
const arrayInput = input ?? [];
|
|
291
|
+
const items = internalFieldStore.items.value;
|
|
292
|
+
if (arrayInput.length < items.length) internalFieldStore.items.value = items.slice(0, arrayInput.length);
|
|
293
|
+
else if (arrayInput.length > items.length) {
|
|
294
|
+
if (arrayInput.length > internalFieldStore.children.length) {
|
|
295
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
296
|
+
for (let index = internalFieldStore.children.length; index < arrayInput.length; index++) {
|
|
297
|
+
internalFieldStore.children[index] = {};
|
|
298
|
+
path.push(index);
|
|
299
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
300
|
+
path.pop();
|
|
289
301
|
}
|
|
290
|
-
internalFieldStore.items.value = [...items, ...input.slice(items.length).map(createId)];
|
|
291
302
|
}
|
|
292
|
-
|
|
293
|
-
internalFieldStore.isDirty.value = untrack(() => internalFieldStore.startItems.value).length !== items.length;
|
|
294
|
-
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
|
|
295
|
-
else {
|
|
296
|
-
internalFieldStore.input.value = input;
|
|
297
|
-
internalFieldStore.isTouched.value = true;
|
|
298
|
-
const startInput = untrack(() => internalFieldStore.startInput.value);
|
|
299
|
-
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
303
|
+
internalFieldStore.items.value = [...items, ...arrayInput.slice(items.length).map(createId)];
|
|
300
304
|
}
|
|
305
|
+
for (let index = 0; index < items.length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
306
|
+
internalFieldStore.input.value = input == null ? input : true;
|
|
307
|
+
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== items.length;
|
|
308
|
+
} else if (internalFieldStore.kind === "object") {
|
|
309
|
+
for (const key in internalFieldStore.children) setNestedInput(internalFieldStore.children[key], input?.[key]);
|
|
310
|
+
internalFieldStore.input.value = input == null ? input : true;
|
|
311
|
+
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value;
|
|
312
|
+
} else {
|
|
313
|
+
internalFieldStore.input.value = input;
|
|
314
|
+
const startInput = internalFieldStore.startInput.value;
|
|
315
|
+
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function setFieldInput(internalFormStore, path, input) {
|
|
319
|
+
batch(() => {
|
|
320
|
+
untrack(() => {
|
|
321
|
+
let internalFieldStore = internalFormStore;
|
|
322
|
+
for (let index = 0; index < path.length; index++) {
|
|
323
|
+
internalFieldStore = internalFieldStore.children[path[index]];
|
|
324
|
+
if (index < path.length - 1) internalFieldStore.input.value = true;
|
|
325
|
+
else setNestedInput(internalFieldStore, input);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
301
328
|
});
|
|
302
329
|
}
|
|
303
330
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
304
331
|
batch(() => {
|
|
305
332
|
if (internalFieldStore.kind === "array") {
|
|
306
|
-
|
|
333
|
+
internalFieldStore.input.value = initialInput == null ? initialInput : true;
|
|
334
|
+
const initialArrayInput = initialInput ?? [];
|
|
335
|
+
if (initialArrayInput.length > internalFieldStore.children.length) {
|
|
307
336
|
const path = JSON.parse(internalFieldStore.name);
|
|
308
|
-
for (let index = internalFieldStore.children.length; index <
|
|
337
|
+
for (let index = internalFieldStore.children.length; index < initialArrayInput.length; index++) {
|
|
309
338
|
internalFieldStore.children[index] = {};
|
|
310
339
|
path.push(index);
|
|
311
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
340
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
312
341
|
path.pop();
|
|
313
342
|
}
|
|
314
343
|
}
|
|
315
|
-
internalFieldStore.initialItems.value =
|
|
316
|
-
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index],
|
|
317
|
-
} else if (internalFieldStore.kind === "object")
|
|
318
|
-
|
|
344
|
+
internalFieldStore.initialItems.value = initialArrayInput.map(createId);
|
|
345
|
+
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
346
|
+
} else if (internalFieldStore.kind === "object") {
|
|
347
|
+
internalFieldStore.input.value = initialInput == null ? initialInput : true;
|
|
348
|
+
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
349
|
+
} else internalFieldStore.initialInput.value = initialInput;
|
|
319
350
|
});
|
|
320
351
|
}
|
|
321
352
|
function walkFieldStore(internalFieldStore, callback) {
|
|
@@ -376,8 +407,8 @@ async function validateFormInput(internalFormStore, config) {
|
|
|
376
407
|
});
|
|
377
408
|
return result;
|
|
378
409
|
}
|
|
379
|
-
function validateIfRequired(internalFormStore, internalFieldStore,
|
|
380
|
-
if (
|
|
410
|
+
function validateIfRequired(internalFormStore, internalFieldStore, validationMode) {
|
|
411
|
+
if (validationMode === (internalFormStore.validate === "initial" || (internalFormStore.validate === "submit" ? untrack(() => internalFormStore.isSubmitted.value) : untrack(() => getFieldBool(internalFieldStore, "errors"))) ? internalFormStore.revalidate : internalFormStore.validate)) validateFormInput(internalFormStore);
|
|
381
412
|
}
|
|
382
413
|
const INTERNAL = "~internal";
|
|
383
414
|
|
|
@@ -419,7 +450,12 @@ function handleSubmit(form, handler) {
|
|
|
419
450
|
}
|
|
420
451
|
function insert(form, config) {
|
|
421
452
|
const internalFormStore = form[INTERNAL];
|
|
422
|
-
|
|
453
|
+
let internalFieldStore = internalFormStore;
|
|
454
|
+
for (let index = 0; index < config.path.length; index++) {
|
|
455
|
+
internalFieldStore = internalFieldStore.children[config.path[index]];
|
|
456
|
+
if (index < config.path.length - 1) internalFieldStore.input.value = true;
|
|
457
|
+
}
|
|
458
|
+
const internalArrayStore = internalFieldStore;
|
|
423
459
|
const items = untrack(() => internalArrayStore.items.value);
|
|
424
460
|
const insertIndex = config.at === void 0 ? items.length : config.at;
|
|
425
461
|
if (insertIndex >= 0 && insertIndex <= items.length) batch(() => {
|
|
@@ -433,6 +469,7 @@ function insert(form, config) {
|
|
|
433
469
|
path.push(insertIndex);
|
|
434
470
|
initializeFieldStore(internalArrayStore.children[insertIndex], internalArrayStore.schema.item, config.initialInput, path);
|
|
435
471
|
} else resetItemState(internalArrayStore.children[insertIndex], config.initialInput);
|
|
472
|
+
internalArrayStore.input.value = true;
|
|
436
473
|
internalArrayStore.isTouched.value = true;
|
|
437
474
|
internalArrayStore.isDirty.value = true;
|
|
438
475
|
validateIfRequired(internalFormStore, internalArrayStore, "input");
|
|
@@ -492,17 +529,20 @@ function reset(form, config) {
|
|
|
492
529
|
const internalFieldStore = config?.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
493
530
|
if (config?.initialInput) setInitialFieldInput(internalFieldStore, config.initialInput);
|
|
494
531
|
walkFieldStore(internalFieldStore, (internalFieldStore$1) => {
|
|
532
|
+
internalFieldStore$1.elements = internalFieldStore$1.initialElements;
|
|
495
533
|
if (!config?.keepErrors) internalFieldStore$1.errors.value = null;
|
|
534
|
+
if (!config?.keepTouched) internalFieldStore$1.isTouched.value = false;
|
|
535
|
+
internalFieldStore$1.startInput.value = internalFieldStore$1.initialInput.value;
|
|
536
|
+
if (!config?.keepInput) internalFieldStore$1.input.value = internalFieldStore$1.initialInput.value;
|
|
496
537
|
if (internalFieldStore$1.kind === "array") {
|
|
497
538
|
internalFieldStore$1.startItems.value = internalFieldStore$1.initialItems.value;
|
|
498
539
|
if (!config?.keepInput || internalFieldStore$1.startItems.value.length === internalFieldStore$1.items.value.length) internalFieldStore$1.items.value = internalFieldStore$1.initialItems.value;
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
internalFieldStore$1.isDirty.value = internalFieldStore$1.startInput.value !== internalFieldStore$1.input.value;
|
|
540
|
+
internalFieldStore$1.isDirty.value = internalFieldStore$1.startInput.value !== internalFieldStore$1.input.value || internalFieldStore$1.startItems.value !== internalFieldStore$1.items.value;
|
|
541
|
+
} else if (internalFieldStore$1.kind === "object") internalFieldStore$1.isDirty.value = internalFieldStore$1.startInput.value !== internalFieldStore$1.input.value;
|
|
542
|
+
else {
|
|
543
|
+
const startInput = internalFieldStore$1.startInput.value;
|
|
544
|
+
const input = internalFieldStore$1.input.value;
|
|
545
|
+
internalFieldStore$1.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
506
546
|
for (const element of internalFieldStore$1.elements) if (element.type === "file") element.value = "";
|
|
507
547
|
}
|
|
508
548
|
});
|
|
@@ -519,9 +559,8 @@ function setErrors(form, config) {
|
|
|
519
559
|
function setInput(form, config) {
|
|
520
560
|
batch(() => {
|
|
521
561
|
const internalFormStore = form[INTERNAL];
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
562
|
+
setFieldInput(internalFormStore, config.path ?? [], config.input);
|
|
563
|
+
validateIfRequired(internalFormStore, config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore, "input");
|
|
525
564
|
});
|
|
526
565
|
}
|
|
527
566
|
function submit(form) {
|
|
@@ -564,7 +603,8 @@ function usePathSignal(path) {
|
|
|
564
603
|
//#region src/hooks/useField/useField.ts
|
|
565
604
|
function useField(form, config) {
|
|
566
605
|
const pathSignal = usePathSignal(config.path);
|
|
567
|
-
const
|
|
606
|
+
const internalFormStore = form[INTERNAL];
|
|
607
|
+
const internalFieldStore = useComputed(() => getFieldStore(internalFormStore, pathSignal.value));
|
|
568
608
|
useSignalEffect(() => {
|
|
569
609
|
return () => {
|
|
570
610
|
internalFieldStore.value.elements = internalFieldStore.value.elements.filter((element) => element.isConnected);
|
|
@@ -587,17 +627,17 @@ function useField(form, config) {
|
|
|
587
627
|
},
|
|
588
628
|
onFocus() {
|
|
589
629
|
setFieldBool(internalFieldStore.value, "isTouched", true);
|
|
590
|
-
validateIfRequired(
|
|
630
|
+
validateIfRequired(internalFormStore, internalFieldStore.value, "touch");
|
|
591
631
|
},
|
|
592
632
|
onInput(event) {
|
|
593
|
-
setFieldInput(
|
|
594
|
-
validateIfRequired(
|
|
633
|
+
setFieldInput(internalFormStore, pathSignal.value, getElementInput(event.currentTarget, internalFieldStore.value));
|
|
634
|
+
validateIfRequired(internalFormStore, internalFieldStore.value, "input");
|
|
595
635
|
},
|
|
596
636
|
onChange() {
|
|
597
|
-
validateIfRequired(
|
|
637
|
+
validateIfRequired(internalFormStore, internalFieldStore.value, "change");
|
|
598
638
|
},
|
|
599
639
|
onBlur() {
|
|
600
|
-
validateIfRequired(
|
|
640
|
+
validateIfRequired(internalFormStore, internalFieldStore.value, "blur");
|
|
601
641
|
}
|
|
602
642
|
}
|
|
603
643
|
}), []);
|
|
@@ -622,7 +662,7 @@ function useFieldArray(form, config) {
|
|
|
622
662
|
//#region src/hooks/useForm/useForm.ts
|
|
623
663
|
function useForm(config) {
|
|
624
664
|
const form = useMemo(() => {
|
|
625
|
-
const internalFormStore = createFormStore(config,
|
|
665
|
+
const internalFormStore = createFormStore(config, (input) => v.safeParseAsync(config.schema, input));
|
|
626
666
|
return {
|
|
627
667
|
[INTERNAL]: internalFormStore,
|
|
628
668
|
isSubmitting: internalFormStore.isSubmitting,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formisch/preact",
|
|
3
3
|
"description": "The modular and type-safe form library for Preact",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fabian Hiller",
|
|
7
7
|
"homepage": "https://formisch.dev",
|
|
@@ -32,17 +32,8 @@
|
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
|
-
"scripts": {
|
|
36
|
-
"build": "tsdown",
|
|
37
|
-
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
38
|
-
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
39
|
-
"format": "prettier --write ./src",
|
|
40
|
-
"format.check": "prettier --check ./src"
|
|
41
|
-
},
|
|
42
35
|
"devDependencies": {
|
|
43
36
|
"@eslint/js": "^9.31.0",
|
|
44
|
-
"@formisch/core": "workspace:*",
|
|
45
|
-
"@formisch/methods": "workspace:*",
|
|
46
37
|
"@preact/preset-vite": "^2.9.3",
|
|
47
38
|
"@preact/signals": "^2.2.1",
|
|
48
39
|
"eslint": "^9.31.0",
|
|
@@ -51,7 +42,9 @@
|
|
|
51
42
|
"tsdown": "^0.12.9",
|
|
52
43
|
"typescript": "^5.8.3",
|
|
53
44
|
"typescript-eslint": "^8.37.0",
|
|
54
|
-
"vite": "^6.0.4"
|
|
45
|
+
"vite": "^6.0.4",
|
|
46
|
+
"@formisch/core": "0.4.0",
|
|
47
|
+
"@formisch/methods": "0.3.0"
|
|
55
48
|
},
|
|
56
49
|
"peerDependencies": {
|
|
57
50
|
"@preact/signals": "^2.0.0",
|
|
@@ -63,5 +56,12 @@
|
|
|
63
56
|
"typescript": {
|
|
64
57
|
"optional": true
|
|
65
58
|
}
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsdown",
|
|
62
|
+
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
63
|
+
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
64
|
+
"format": "prettier --write ./src",
|
|
65
|
+
"format.check": "prettier --check ./src"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|