@formisch/solid 0.10.0 → 0.11.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 +1 -0
- package/dist/dev.js +99 -73
- package/dist/dev.jsx +98 -72
- package/dist/index.d.ts +14 -4
- package/dist/index.js +99 -73
- package/dist/index.jsx +98 -72
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ Formisch is also available for [Preact][formisch-preact], [Qwik][formisch-qwik],
|
|
|
9
9
|
- Small bundle size starting at 2.5 kB
|
|
10
10
|
- Schema-based validation with Valibot
|
|
11
11
|
- Type safety with autocompletion in editor
|
|
12
|
+
- Open source and fully tested with 100 % coverage
|
|
12
13
|
- It's fast – DOM updates are fine-grained
|
|
13
14
|
- Minimal, readable and well thought out API
|
|
14
15
|
- Supports all native HTML form fields
|
package/dist/dev.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
2
|
import { untrack, batch, createUniqueId, createMemo, onCleanup, splitProps, createSignal as createSignal$1 } from 'solid-js';
|
|
3
|
-
import { memo,
|
|
3
|
+
import { memo, use, spread, mergeProps, template } from 'solid-js/web';
|
|
4
4
|
|
|
5
5
|
// ../../packages/core/dist/index.solid.js
|
|
6
6
|
var framework = "solid";
|
|
@@ -113,29 +113,40 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
|
-
function resetItemState(internalFieldStore,
|
|
116
|
+
function resetItemState(internalFieldStore, input, keepStart = false) {
|
|
117
117
|
batch(() => {
|
|
118
|
-
|
|
118
|
+
const elements = [];
|
|
119
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) internalFieldStore.initialElements = elements;
|
|
120
|
+
internalFieldStore.elements = elements;
|
|
119
121
|
internalFieldStore.errors.value = null;
|
|
120
122
|
internalFieldStore.isTouched.value = false;
|
|
121
123
|
internalFieldStore.isDirty.value = false;
|
|
122
124
|
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
123
|
-
const objectInput =
|
|
124
|
-
internalFieldStore.startInput.value = objectInput;
|
|
125
|
+
const objectInput = input == null ? input : true;
|
|
126
|
+
if (!keepStart) internalFieldStore.startInput.value = objectInput;
|
|
125
127
|
internalFieldStore.input.value = objectInput;
|
|
126
|
-
if (internalFieldStore.kind === "array") if (
|
|
127
|
-
const
|
|
128
|
-
|
|
128
|
+
if (internalFieldStore.kind === "array") if (input) {
|
|
129
|
+
const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
|
|
130
|
+
const newItems = Array.from({ length }, createUniqueId);
|
|
131
|
+
if (!keepStart) internalFieldStore.startItems.value = newItems;
|
|
129
132
|
internalFieldStore.items.value = newItems;
|
|
130
|
-
|
|
133
|
+
let path;
|
|
134
|
+
for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
|
|
135
|
+
else {
|
|
136
|
+
path ??= JSON.parse(internalFieldStore.name);
|
|
137
|
+
internalFieldStore.children[index] = {};
|
|
138
|
+
path.push(index);
|
|
139
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
|
|
140
|
+
path.pop();
|
|
141
|
+
}
|
|
131
142
|
} else {
|
|
132
|
-
internalFieldStore.startItems.value = [];
|
|
143
|
+
if (!keepStart) internalFieldStore.startItems.value = [];
|
|
133
144
|
internalFieldStore.items.value = [];
|
|
134
145
|
}
|
|
135
|
-
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key],
|
|
146
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
|
|
136
147
|
} else {
|
|
137
|
-
internalFieldStore.startInput.value =
|
|
138
|
-
internalFieldStore.input.value =
|
|
148
|
+
if (!keepStart) internalFieldStore.startInput.value = input;
|
|
149
|
+
internalFieldStore.input.value = input;
|
|
139
150
|
}
|
|
140
151
|
});
|
|
141
152
|
}
|
|
@@ -192,6 +203,13 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
192
203
|
});
|
|
193
204
|
});
|
|
194
205
|
}
|
|
206
|
+
function focusFieldElement(internalFieldStore) {
|
|
207
|
+
for (const element of internalFieldStore.elements) {
|
|
208
|
+
element.focus();
|
|
209
|
+
if (element.getRootNode().activeElement === element) return true;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
195
213
|
// @__NO_SIDE_EFFECTS__
|
|
196
214
|
function getFieldBool(internalFieldStore, type) {
|
|
197
215
|
if (internalFieldStore[type].value) return true;
|
|
@@ -275,11 +293,9 @@ function getFieldStore(internalFormStore, path) {
|
|
|
275
293
|
}
|
|
276
294
|
function setFieldBool(internalFieldStore, type, bool) {
|
|
277
295
|
batch(() => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
} else if (internalFieldStore.kind == "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
282
|
-
else internalFieldStore[type].value = bool;
|
|
296
|
+
internalFieldStore[type].value = bool;
|
|
297
|
+
if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
|
|
298
|
+
else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
283
299
|
});
|
|
284
300
|
}
|
|
285
301
|
function setNestedInput(internalFieldStore, input) {
|
|
@@ -287,20 +303,20 @@ function setNestedInput(internalFieldStore, input) {
|
|
|
287
303
|
if (internalFieldStore.kind === "array") {
|
|
288
304
|
const arrayInput = input ?? [];
|
|
289
305
|
const items = internalFieldStore.items.value;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
|
|
307
|
+
if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
|
|
308
|
+
else if (length > items.length) {
|
|
309
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
310
|
+
for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
|
|
311
|
+
else {
|
|
312
|
+
internalFieldStore.children[index] = {};
|
|
313
|
+
path.push(index);
|
|
314
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
315
|
+
path.pop();
|
|
300
316
|
}
|
|
301
|
-
internalFieldStore.items.value = [...items, ...
|
|
317
|
+
internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createUniqueId)];
|
|
302
318
|
}
|
|
303
|
-
for (let index = 0; index <
|
|
319
|
+
for (let index = 0; index < length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
304
320
|
internalFieldStore.input.value = input == null ? input : true;
|
|
305
321
|
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
|
|
306
322
|
} else if (internalFieldStore.kind === "object") {
|
|
@@ -328,21 +344,22 @@ function setFieldInput(internalFormStore, path, input) {
|
|
|
328
344
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
329
345
|
batch(() => {
|
|
330
346
|
if (internalFieldStore.kind === "array") {
|
|
331
|
-
internalFieldStore.
|
|
347
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
332
348
|
const initialArrayInput = initialInput ?? [];
|
|
333
|
-
|
|
349
|
+
const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
|
|
350
|
+
if (length > internalFieldStore.children.length) {
|
|
334
351
|
const path = JSON.parse(internalFieldStore.name);
|
|
335
|
-
for (let index = internalFieldStore.children.length; index <
|
|
352
|
+
for (let index = internalFieldStore.children.length; index < length; index++) {
|
|
336
353
|
internalFieldStore.children[index] = {};
|
|
337
354
|
path.push(index);
|
|
338
355
|
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
339
356
|
path.pop();
|
|
340
357
|
}
|
|
341
358
|
}
|
|
342
|
-
internalFieldStore.initialItems.value =
|
|
359
|
+
internalFieldStore.initialItems.value = Array.from({ length }, createUniqueId);
|
|
343
360
|
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
344
361
|
} else if (internalFieldStore.kind === "object") {
|
|
345
|
-
internalFieldStore.
|
|
362
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
346
363
|
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
347
364
|
} else internalFieldStore.initialInput.value = initialInput;
|
|
348
365
|
});
|
|
@@ -367,44 +384,49 @@ function createFormStore(config, parse) {
|
|
|
367
384
|
async function validateFormInput(internalFormStore, config) {
|
|
368
385
|
internalFormStore.validators++;
|
|
369
386
|
internalFormStore.isValidating.value = true;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const path
|
|
377
|
-
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const name = JSON.stringify(path);
|
|
385
|
-
const fieldErrors = nestedErrors[name];
|
|
386
|
-
if (fieldErrors) fieldErrors.push(issue.message);
|
|
387
|
-
else nestedErrors[name] = [issue.message];
|
|
388
|
-
} else if (rootErrors) rootErrors.push(issue.message);
|
|
389
|
-
else rootErrors = [issue.message];
|
|
390
|
-
}
|
|
391
|
-
let shouldFocus = config?.shouldFocus ?? false;
|
|
392
|
-
batch(() => {
|
|
393
|
-
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
394
|
-
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
395
|
-
else {
|
|
396
|
-
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
397
|
-
internalFieldStore.errors.value = fieldErrors;
|
|
398
|
-
if (shouldFocus && fieldErrors) {
|
|
399
|
-
internalFieldStore.elements[0]?.focus();
|
|
400
|
-
shouldFocus = false;
|
|
387
|
+
try {
|
|
388
|
+
const result = await internalFormStore.parse(untrack(() => /* @__PURE__ */ getFieldInput(internalFormStore)));
|
|
389
|
+
let rootErrors;
|
|
390
|
+
let nestedErrors;
|
|
391
|
+
if (result.issues) {
|
|
392
|
+
nestedErrors = {};
|
|
393
|
+
for (const issue of result.issues) if (issue.path) {
|
|
394
|
+
const path = [];
|
|
395
|
+
for (const pathItem of issue.path) {
|
|
396
|
+
const key = pathItem.key;
|
|
397
|
+
const keyType = typeof key;
|
|
398
|
+
const itemType = pathItem.type;
|
|
399
|
+
if (keyType !== "string" && keyType !== "number" || itemType === "map" || itemType === "set") break;
|
|
400
|
+
path.push(key);
|
|
401
401
|
}
|
|
402
|
-
|
|
402
|
+
const name = JSON.stringify(path);
|
|
403
|
+
const fieldErrors = nestedErrors[name];
|
|
404
|
+
if (fieldErrors) fieldErrors.push(issue.message);
|
|
405
|
+
else nestedErrors[name] = [issue.message];
|
|
406
|
+
} else if (rootErrors) rootErrors.push(issue.message);
|
|
407
|
+
else rootErrors = [issue.message];
|
|
408
|
+
}
|
|
409
|
+
let shouldFocus = config?.shouldFocus ?? false;
|
|
410
|
+
batch(() => {
|
|
411
|
+
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
412
|
+
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
413
|
+
else {
|
|
414
|
+
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
415
|
+
internalFieldStore.errors.value = fieldErrors;
|
|
416
|
+
if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
internalFormStore.validators--;
|
|
420
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
403
421
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
422
|
+
return result;
|
|
423
|
+
} catch (error) {
|
|
424
|
+
batch(() => {
|
|
425
|
+
internalFormStore.validators--;
|
|
426
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
427
|
+
});
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
408
430
|
}
|
|
409
431
|
function validateIfRequired(internalFormStore, internalFieldStore, validationMode) {
|
|
410
432
|
if (validationMode === (internalFormStore.validate === "initial" || (internalFormStore.validate === "submit" ? untrack(() => internalFormStore.isSubmitted.value) : untrack(() => /* @__PURE__ */ getFieldBool(internalFieldStore, "errors"))) ? internalFormStore.revalidate : internalFormStore.validate)) validateFormInput(internalFormStore);
|
|
@@ -413,7 +435,7 @@ var INTERNAL = "~internal";
|
|
|
413
435
|
|
|
414
436
|
// ../../packages/methods/dist/index.solid.js
|
|
415
437
|
function focus(form, config) {
|
|
416
|
-
getFieldStore(form[INTERNAL], config.path)
|
|
438
|
+
focusFieldElement(getFieldStore(form[INTERNAL], config.path));
|
|
417
439
|
}
|
|
418
440
|
// @__NO_SIDE_EFFECTS__
|
|
419
441
|
function getAllErrors(form) {
|
|
@@ -733,9 +755,13 @@ function useField(form, config) {
|
|
|
733
755
|
const internalFieldStore = getInternalFieldStore();
|
|
734
756
|
internalFieldStore.elements.push(element);
|
|
735
757
|
onCleanup(() => {
|
|
736
|
-
|
|
758
|
+
const elements = internalFieldStore.elements.filter(
|
|
737
759
|
(el) => el !== element
|
|
738
760
|
);
|
|
761
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) {
|
|
762
|
+
internalFieldStore.initialElements = elements;
|
|
763
|
+
}
|
|
764
|
+
internalFieldStore.elements = elements;
|
|
739
765
|
});
|
|
740
766
|
},
|
|
741
767
|
onFocus() {
|
package/dist/dev.jsx
CHANGED
|
@@ -111,29 +111,40 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
111
111
|
});
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
function resetItemState(internalFieldStore,
|
|
114
|
+
function resetItemState(internalFieldStore, input, keepStart = false) {
|
|
115
115
|
batch(() => {
|
|
116
|
-
|
|
116
|
+
const elements = [];
|
|
117
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) internalFieldStore.initialElements = elements;
|
|
118
|
+
internalFieldStore.elements = elements;
|
|
117
119
|
internalFieldStore.errors.value = null;
|
|
118
120
|
internalFieldStore.isTouched.value = false;
|
|
119
121
|
internalFieldStore.isDirty.value = false;
|
|
120
122
|
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
121
|
-
const objectInput =
|
|
122
|
-
internalFieldStore.startInput.value = objectInput;
|
|
123
|
+
const objectInput = input == null ? input : true;
|
|
124
|
+
if (!keepStart) internalFieldStore.startInput.value = objectInput;
|
|
123
125
|
internalFieldStore.input.value = objectInput;
|
|
124
|
-
if (internalFieldStore.kind === "array") if (
|
|
125
|
-
const
|
|
126
|
-
|
|
126
|
+
if (internalFieldStore.kind === "array") if (input) {
|
|
127
|
+
const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
|
|
128
|
+
const newItems = Array.from({ length }, createId);
|
|
129
|
+
if (!keepStart) internalFieldStore.startItems.value = newItems;
|
|
127
130
|
internalFieldStore.items.value = newItems;
|
|
128
|
-
|
|
131
|
+
let path;
|
|
132
|
+
for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
|
|
133
|
+
else {
|
|
134
|
+
path ??= JSON.parse(internalFieldStore.name);
|
|
135
|
+
internalFieldStore.children[index] = {};
|
|
136
|
+
path.push(index);
|
|
137
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
|
|
138
|
+
path.pop();
|
|
139
|
+
}
|
|
129
140
|
} else {
|
|
130
|
-
internalFieldStore.startItems.value = [];
|
|
141
|
+
if (!keepStart) internalFieldStore.startItems.value = [];
|
|
131
142
|
internalFieldStore.items.value = [];
|
|
132
143
|
}
|
|
133
|
-
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key],
|
|
144
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
|
|
134
145
|
} else {
|
|
135
|
-
internalFieldStore.startInput.value =
|
|
136
|
-
internalFieldStore.input.value =
|
|
146
|
+
if (!keepStart) internalFieldStore.startInput.value = input;
|
|
147
|
+
internalFieldStore.input.value = input;
|
|
137
148
|
}
|
|
138
149
|
});
|
|
139
150
|
}
|
|
@@ -190,6 +201,13 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
190
201
|
});
|
|
191
202
|
});
|
|
192
203
|
}
|
|
204
|
+
function focusFieldElement(internalFieldStore) {
|
|
205
|
+
for (const element of internalFieldStore.elements) {
|
|
206
|
+
element.focus();
|
|
207
|
+
if (element.getRootNode().activeElement === element) return true;
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
193
211
|
// @__NO_SIDE_EFFECTS__
|
|
194
212
|
function getFieldBool(internalFieldStore, type) {
|
|
195
213
|
if (internalFieldStore[type].value) return true;
|
|
@@ -273,11 +291,9 @@ function getFieldStore(internalFormStore, path) {
|
|
|
273
291
|
}
|
|
274
292
|
function setFieldBool(internalFieldStore, type, bool) {
|
|
275
293
|
batch(() => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
} else if (internalFieldStore.kind == "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
280
|
-
else internalFieldStore[type].value = bool;
|
|
294
|
+
internalFieldStore[type].value = bool;
|
|
295
|
+
if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
|
|
296
|
+
else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
281
297
|
});
|
|
282
298
|
}
|
|
283
299
|
function setNestedInput(internalFieldStore, input) {
|
|
@@ -285,20 +301,20 @@ function setNestedInput(internalFieldStore, input) {
|
|
|
285
301
|
if (internalFieldStore.kind === "array") {
|
|
286
302
|
const arrayInput = input ?? [];
|
|
287
303
|
const items = internalFieldStore.items.value;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
|
|
305
|
+
if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
|
|
306
|
+
else if (length > items.length) {
|
|
307
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
308
|
+
for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
|
|
309
|
+
else {
|
|
310
|
+
internalFieldStore.children[index] = {};
|
|
311
|
+
path.push(index);
|
|
312
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
313
|
+
path.pop();
|
|
298
314
|
}
|
|
299
|
-
internalFieldStore.items.value = [...items, ...
|
|
315
|
+
internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createId)];
|
|
300
316
|
}
|
|
301
|
-
for (let index = 0; index <
|
|
317
|
+
for (let index = 0; index < length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
302
318
|
internalFieldStore.input.value = input == null ? input : true;
|
|
303
319
|
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
|
|
304
320
|
} else if (internalFieldStore.kind === "object") {
|
|
@@ -326,21 +342,22 @@ function setFieldInput(internalFormStore, path, input) {
|
|
|
326
342
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
327
343
|
batch(() => {
|
|
328
344
|
if (internalFieldStore.kind === "array") {
|
|
329
|
-
internalFieldStore.
|
|
345
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
330
346
|
const initialArrayInput = initialInput ?? [];
|
|
331
|
-
|
|
347
|
+
const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
|
|
348
|
+
if (length > internalFieldStore.children.length) {
|
|
332
349
|
const path = JSON.parse(internalFieldStore.name);
|
|
333
|
-
for (let index = internalFieldStore.children.length; index <
|
|
350
|
+
for (let index = internalFieldStore.children.length; index < length; index++) {
|
|
334
351
|
internalFieldStore.children[index] = {};
|
|
335
352
|
path.push(index);
|
|
336
353
|
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
337
354
|
path.pop();
|
|
338
355
|
}
|
|
339
356
|
}
|
|
340
|
-
internalFieldStore.initialItems.value =
|
|
357
|
+
internalFieldStore.initialItems.value = Array.from({ length }, createId);
|
|
341
358
|
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
342
359
|
} else if (internalFieldStore.kind === "object") {
|
|
343
|
-
internalFieldStore.
|
|
360
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
344
361
|
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
345
362
|
} else internalFieldStore.initialInput.value = initialInput;
|
|
346
363
|
});
|
|
@@ -365,44 +382,49 @@ function createFormStore(config, parse) {
|
|
|
365
382
|
async function validateFormInput(internalFormStore, config) {
|
|
366
383
|
internalFormStore.validators++;
|
|
367
384
|
internalFormStore.isValidating.value = true;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const path
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const name = JSON.stringify(path);
|
|
383
|
-
const fieldErrors = nestedErrors[name];
|
|
384
|
-
if (fieldErrors) fieldErrors.push(issue.message);
|
|
385
|
-
else nestedErrors[name] = [issue.message];
|
|
386
|
-
} else if (rootErrors) rootErrors.push(issue.message);
|
|
387
|
-
else rootErrors = [issue.message];
|
|
388
|
-
}
|
|
389
|
-
let shouldFocus = config?.shouldFocus ?? false;
|
|
390
|
-
batch(() => {
|
|
391
|
-
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
392
|
-
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
393
|
-
else {
|
|
394
|
-
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
395
|
-
internalFieldStore.errors.value = fieldErrors;
|
|
396
|
-
if (shouldFocus && fieldErrors) {
|
|
397
|
-
internalFieldStore.elements[0]?.focus();
|
|
398
|
-
shouldFocus = false;
|
|
385
|
+
try {
|
|
386
|
+
const result = await internalFormStore.parse(untrack(() => /* @__PURE__ */ getFieldInput(internalFormStore)));
|
|
387
|
+
let rootErrors;
|
|
388
|
+
let nestedErrors;
|
|
389
|
+
if (result.issues) {
|
|
390
|
+
nestedErrors = {};
|
|
391
|
+
for (const issue of result.issues) if (issue.path) {
|
|
392
|
+
const path = [];
|
|
393
|
+
for (const pathItem of issue.path) {
|
|
394
|
+
const key = pathItem.key;
|
|
395
|
+
const keyType = typeof key;
|
|
396
|
+
const itemType = pathItem.type;
|
|
397
|
+
if (keyType !== "string" && keyType !== "number" || itemType === "map" || itemType === "set") break;
|
|
398
|
+
path.push(key);
|
|
399
399
|
}
|
|
400
|
-
|
|
400
|
+
const name = JSON.stringify(path);
|
|
401
|
+
const fieldErrors = nestedErrors[name];
|
|
402
|
+
if (fieldErrors) fieldErrors.push(issue.message);
|
|
403
|
+
else nestedErrors[name] = [issue.message];
|
|
404
|
+
} else if (rootErrors) rootErrors.push(issue.message);
|
|
405
|
+
else rootErrors = [issue.message];
|
|
406
|
+
}
|
|
407
|
+
let shouldFocus = config?.shouldFocus ?? false;
|
|
408
|
+
batch(() => {
|
|
409
|
+
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
410
|
+
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
411
|
+
else {
|
|
412
|
+
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
413
|
+
internalFieldStore.errors.value = fieldErrors;
|
|
414
|
+
if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
internalFormStore.validators--;
|
|
418
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
401
419
|
});
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
420
|
+
return result;
|
|
421
|
+
} catch (error) {
|
|
422
|
+
batch(() => {
|
|
423
|
+
internalFormStore.validators--;
|
|
424
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
425
|
+
});
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
406
428
|
}
|
|
407
429
|
function validateIfRequired(internalFormStore, internalFieldStore, validationMode) {
|
|
408
430
|
if (validationMode === (internalFormStore.validate === "initial" || (internalFormStore.validate === "submit" ? untrack(() => internalFormStore.isSubmitted.value) : untrack(() => /* @__PURE__ */ getFieldBool(internalFieldStore, "errors"))) ? internalFormStore.revalidate : internalFormStore.validate)) validateFormInput(internalFormStore);
|
|
@@ -411,7 +433,7 @@ var INTERNAL = "~internal";
|
|
|
411
433
|
|
|
412
434
|
// ../../packages/methods/dist/index.solid.js
|
|
413
435
|
function focus(form, config) {
|
|
414
|
-
getFieldStore(form[INTERNAL], config.path)
|
|
436
|
+
focusFieldElement(getFieldStore(form[INTERNAL], config.path));
|
|
415
437
|
}
|
|
416
438
|
// @__NO_SIDE_EFFECTS__
|
|
417
439
|
function getAllErrors(form) {
|
|
@@ -738,9 +760,13 @@ function useField(form, config) {
|
|
|
738
760
|
const internalFieldStore = getInternalFieldStore();
|
|
739
761
|
internalFieldStore.elements.push(element);
|
|
740
762
|
onCleanup(() => {
|
|
741
|
-
|
|
763
|
+
const elements = internalFieldStore.elements.filter(
|
|
742
764
|
(el) => el !== element
|
|
743
765
|
);
|
|
766
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) {
|
|
767
|
+
internalFieldStore.initialElements = elements;
|
|
768
|
+
}
|
|
769
|
+
internalFieldStore.elements = elements;
|
|
744
770
|
});
|
|
745
771
|
},
|
|
746
772
|
onFocus() {
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,13 @@ interface InternalBaseStore {
|
|
|
72
72
|
schema: Schema;
|
|
73
73
|
/**
|
|
74
74
|
* The initial elements of the field.
|
|
75
|
+
*
|
|
76
|
+
* Hint: This may look unused, but do not remove it. `copyItemState` and
|
|
77
|
+
* `swapItemState` move the `elements` reference between field stores when
|
|
78
|
+
* array items are inserted, moved, removed or swapped, and `reset` restores
|
|
79
|
+
* each field's original element via `elements = initialElements`. Without it,
|
|
80
|
+
* focus and file reset target the wrong element after a reorder followed by a
|
|
81
|
+
* reset.
|
|
75
82
|
*/
|
|
76
83
|
initialElements: FieldElement[];
|
|
77
84
|
/**
|
|
@@ -393,7 +400,10 @@ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExa
|
|
|
393
400
|
*/
|
|
394
401
|
type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends ExactKeysOf<ExactRequired<TValue>> ? PathValue<PropertiesOf<ExactRequired<TValue>>[TKey], TRest> : unknown : TValue;
|
|
395
402
|
/**
|
|
396
|
-
* Checks whether a value is
|
|
403
|
+
* Checks whether a value is a dynamic array or contains one anywhere in its
|
|
404
|
+
* shape. A fixed-length tuple is not itself a dynamic array, but it counts when
|
|
405
|
+
* it contains one, so paths can still navigate through tuples to reach nested
|
|
406
|
+
* arrays.
|
|
397
407
|
*
|
|
398
408
|
* Hint: The inner conditionals (`TValue extends readonly unknown[]` and
|
|
399
409
|
* `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
|
|
@@ -404,7 +414,7 @@ type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey,
|
|
|
404
414
|
* `true extends ...`, which is `true` whenever at least one union member
|
|
405
415
|
* contributed `true`.
|
|
406
416
|
*/
|
|
407
|
-
type IsOrHasArray<TValue> = true extends (IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? true : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> }[keyof TValue] : false) ? true : false;
|
|
417
|
+
type IsOrHasArray<TValue> = true extends (IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? number extends TValue["length"] ? true : IsOrHasArray<TValue[number]> : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> }[keyof TValue] : false) ? true : false;
|
|
408
418
|
/**
|
|
409
419
|
* Extracts the exact keys of a tuple, array or object that contain arrays.
|
|
410
420
|
*/
|
|
@@ -419,7 +429,7 @@ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: T
|
|
|
419
429
|
/**
|
|
420
430
|
* Lazily evaluates only the first valid array path segment based on the given value.
|
|
421
431
|
*/
|
|
422
|
-
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? TValidPath : readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<Required<PropertiesOfArrayPath<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never;
|
|
432
|
+
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? number extends TValue["length"] ? TValidPath : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never : readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<Required<PropertiesOfArrayPath<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOfArrayPath<TValue>> extends false ? readonly [...TValidPath, ExactKeysOfArrayPath<TValue>] : never;
|
|
423
433
|
/**
|
|
424
434
|
* Returns the path if valid, otherwise the first possible valid array path
|
|
425
435
|
* based on the given value.
|
|
@@ -472,7 +482,7 @@ interface FocusFieldConfig<TSchema extends FormSchema, TFieldPath extends Requir
|
|
|
472
482
|
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
473
483
|
}
|
|
474
484
|
/**
|
|
475
|
-
* Focuses the first input element of a field. This is useful for
|
|
485
|
+
* Focuses the first focusable input element of a field. This is useful for
|
|
476
486
|
* programmatically setting focus to a specific field, such as after
|
|
477
487
|
* validation errors or user interactions.
|
|
478
488
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as v from 'valibot';
|
|
2
2
|
import { untrack, batch, createUniqueId, createMemo, onCleanup, splitProps, createSignal as createSignal$1 } from 'solid-js';
|
|
3
|
-
import { memo,
|
|
3
|
+
import { memo, use, spread, mergeProps, template } from 'solid-js/web';
|
|
4
4
|
|
|
5
5
|
// ../../packages/core/dist/index.solid.js
|
|
6
6
|
var framework = "solid";
|
|
@@ -113,29 +113,40 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
113
113
|
});
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
|
-
function resetItemState(internalFieldStore,
|
|
116
|
+
function resetItemState(internalFieldStore, input, keepStart = false) {
|
|
117
117
|
batch(() => {
|
|
118
|
-
|
|
118
|
+
const elements = [];
|
|
119
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) internalFieldStore.initialElements = elements;
|
|
120
|
+
internalFieldStore.elements = elements;
|
|
119
121
|
internalFieldStore.errors.value = null;
|
|
120
122
|
internalFieldStore.isTouched.value = false;
|
|
121
123
|
internalFieldStore.isDirty.value = false;
|
|
122
124
|
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
123
|
-
const objectInput =
|
|
124
|
-
internalFieldStore.startInput.value = objectInput;
|
|
125
|
+
const objectInput = input == null ? input : true;
|
|
126
|
+
if (!keepStart) internalFieldStore.startInput.value = objectInput;
|
|
125
127
|
internalFieldStore.input.value = objectInput;
|
|
126
|
-
if (internalFieldStore.kind === "array") if (
|
|
127
|
-
const
|
|
128
|
-
|
|
128
|
+
if (internalFieldStore.kind === "array") if (input) {
|
|
129
|
+
const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
|
|
130
|
+
const newItems = Array.from({ length }, createUniqueId);
|
|
131
|
+
if (!keepStart) internalFieldStore.startItems.value = newItems;
|
|
129
132
|
internalFieldStore.items.value = newItems;
|
|
130
|
-
|
|
133
|
+
let path;
|
|
134
|
+
for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
|
|
135
|
+
else {
|
|
136
|
+
path ??= JSON.parse(internalFieldStore.name);
|
|
137
|
+
internalFieldStore.children[index] = {};
|
|
138
|
+
path.push(index);
|
|
139
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
|
|
140
|
+
path.pop();
|
|
141
|
+
}
|
|
131
142
|
} else {
|
|
132
|
-
internalFieldStore.startItems.value = [];
|
|
143
|
+
if (!keepStart) internalFieldStore.startItems.value = [];
|
|
133
144
|
internalFieldStore.items.value = [];
|
|
134
145
|
}
|
|
135
|
-
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key],
|
|
146
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
|
|
136
147
|
} else {
|
|
137
|
-
internalFieldStore.startInput.value =
|
|
138
|
-
internalFieldStore.input.value =
|
|
148
|
+
if (!keepStart) internalFieldStore.startInput.value = input;
|
|
149
|
+
internalFieldStore.input.value = input;
|
|
139
150
|
}
|
|
140
151
|
});
|
|
141
152
|
}
|
|
@@ -192,6 +203,13 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
192
203
|
});
|
|
193
204
|
});
|
|
194
205
|
}
|
|
206
|
+
function focusFieldElement(internalFieldStore) {
|
|
207
|
+
for (const element of internalFieldStore.elements) {
|
|
208
|
+
element.focus();
|
|
209
|
+
if (element.getRootNode().activeElement === element) return true;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
195
213
|
// @__NO_SIDE_EFFECTS__
|
|
196
214
|
function getFieldBool(internalFieldStore, type) {
|
|
197
215
|
if (internalFieldStore[type].value) return true;
|
|
@@ -275,11 +293,9 @@ function getFieldStore(internalFormStore, path) {
|
|
|
275
293
|
}
|
|
276
294
|
function setFieldBool(internalFieldStore, type, bool) {
|
|
277
295
|
batch(() => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
} else if (internalFieldStore.kind == "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
282
|
-
else internalFieldStore[type].value = bool;
|
|
296
|
+
internalFieldStore[type].value = bool;
|
|
297
|
+
if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
|
|
298
|
+
else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
283
299
|
});
|
|
284
300
|
}
|
|
285
301
|
function setNestedInput(internalFieldStore, input) {
|
|
@@ -287,20 +303,20 @@ function setNestedInput(internalFieldStore, input) {
|
|
|
287
303
|
if (internalFieldStore.kind === "array") {
|
|
288
304
|
const arrayInput = input ?? [];
|
|
289
305
|
const items = internalFieldStore.items.value;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
|
|
307
|
+
if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
|
|
308
|
+
else if (length > items.length) {
|
|
309
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
310
|
+
for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
|
|
311
|
+
else {
|
|
312
|
+
internalFieldStore.children[index] = {};
|
|
313
|
+
path.push(index);
|
|
314
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
315
|
+
path.pop();
|
|
300
316
|
}
|
|
301
|
-
internalFieldStore.items.value = [...items, ...
|
|
317
|
+
internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createUniqueId)];
|
|
302
318
|
}
|
|
303
|
-
for (let index = 0; index <
|
|
319
|
+
for (let index = 0; index < length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
304
320
|
internalFieldStore.input.value = input == null ? input : true;
|
|
305
321
|
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
|
|
306
322
|
} else if (internalFieldStore.kind === "object") {
|
|
@@ -328,21 +344,22 @@ function setFieldInput(internalFormStore, path, input) {
|
|
|
328
344
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
329
345
|
batch(() => {
|
|
330
346
|
if (internalFieldStore.kind === "array") {
|
|
331
|
-
internalFieldStore.
|
|
347
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
332
348
|
const initialArrayInput = initialInput ?? [];
|
|
333
|
-
|
|
349
|
+
const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
|
|
350
|
+
if (length > internalFieldStore.children.length) {
|
|
334
351
|
const path = JSON.parse(internalFieldStore.name);
|
|
335
|
-
for (let index = internalFieldStore.children.length; index <
|
|
352
|
+
for (let index = internalFieldStore.children.length; index < length; index++) {
|
|
336
353
|
internalFieldStore.children[index] = {};
|
|
337
354
|
path.push(index);
|
|
338
355
|
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
339
356
|
path.pop();
|
|
340
357
|
}
|
|
341
358
|
}
|
|
342
|
-
internalFieldStore.initialItems.value =
|
|
359
|
+
internalFieldStore.initialItems.value = Array.from({ length }, createUniqueId);
|
|
343
360
|
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
344
361
|
} else if (internalFieldStore.kind === "object") {
|
|
345
|
-
internalFieldStore.
|
|
362
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
346
363
|
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
347
364
|
} else internalFieldStore.initialInput.value = initialInput;
|
|
348
365
|
});
|
|
@@ -367,44 +384,49 @@ function createFormStore(config, parse) {
|
|
|
367
384
|
async function validateFormInput(internalFormStore, config) {
|
|
368
385
|
internalFormStore.validators++;
|
|
369
386
|
internalFormStore.isValidating.value = true;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const path
|
|
377
|
-
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const name = JSON.stringify(path);
|
|
385
|
-
const fieldErrors = nestedErrors[name];
|
|
386
|
-
if (fieldErrors) fieldErrors.push(issue.message);
|
|
387
|
-
else nestedErrors[name] = [issue.message];
|
|
388
|
-
} else if (rootErrors) rootErrors.push(issue.message);
|
|
389
|
-
else rootErrors = [issue.message];
|
|
390
|
-
}
|
|
391
|
-
let shouldFocus = config?.shouldFocus ?? false;
|
|
392
|
-
batch(() => {
|
|
393
|
-
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
394
|
-
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
395
|
-
else {
|
|
396
|
-
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
397
|
-
internalFieldStore.errors.value = fieldErrors;
|
|
398
|
-
if (shouldFocus && fieldErrors) {
|
|
399
|
-
internalFieldStore.elements[0]?.focus();
|
|
400
|
-
shouldFocus = false;
|
|
387
|
+
try {
|
|
388
|
+
const result = await internalFormStore.parse(untrack(() => /* @__PURE__ */ getFieldInput(internalFormStore)));
|
|
389
|
+
let rootErrors;
|
|
390
|
+
let nestedErrors;
|
|
391
|
+
if (result.issues) {
|
|
392
|
+
nestedErrors = {};
|
|
393
|
+
for (const issue of result.issues) if (issue.path) {
|
|
394
|
+
const path = [];
|
|
395
|
+
for (const pathItem of issue.path) {
|
|
396
|
+
const key = pathItem.key;
|
|
397
|
+
const keyType = typeof key;
|
|
398
|
+
const itemType = pathItem.type;
|
|
399
|
+
if (keyType !== "string" && keyType !== "number" || itemType === "map" || itemType === "set") break;
|
|
400
|
+
path.push(key);
|
|
401
401
|
}
|
|
402
|
-
|
|
402
|
+
const name = JSON.stringify(path);
|
|
403
|
+
const fieldErrors = nestedErrors[name];
|
|
404
|
+
if (fieldErrors) fieldErrors.push(issue.message);
|
|
405
|
+
else nestedErrors[name] = [issue.message];
|
|
406
|
+
} else if (rootErrors) rootErrors.push(issue.message);
|
|
407
|
+
else rootErrors = [issue.message];
|
|
408
|
+
}
|
|
409
|
+
let shouldFocus = config?.shouldFocus ?? false;
|
|
410
|
+
batch(() => {
|
|
411
|
+
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
412
|
+
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
413
|
+
else {
|
|
414
|
+
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
415
|
+
internalFieldStore.errors.value = fieldErrors;
|
|
416
|
+
if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
internalFormStore.validators--;
|
|
420
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
403
421
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
422
|
+
return result;
|
|
423
|
+
} catch (error) {
|
|
424
|
+
batch(() => {
|
|
425
|
+
internalFormStore.validators--;
|
|
426
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
427
|
+
});
|
|
428
|
+
throw error;
|
|
429
|
+
}
|
|
408
430
|
}
|
|
409
431
|
function validateIfRequired(internalFormStore, internalFieldStore, validationMode) {
|
|
410
432
|
if (validationMode === (internalFormStore.validate === "initial" || (internalFormStore.validate === "submit" ? untrack(() => internalFormStore.isSubmitted.value) : untrack(() => /* @__PURE__ */ getFieldBool(internalFieldStore, "errors"))) ? internalFormStore.revalidate : internalFormStore.validate)) validateFormInput(internalFormStore);
|
|
@@ -413,7 +435,7 @@ var INTERNAL = "~internal";
|
|
|
413
435
|
|
|
414
436
|
// ../../packages/methods/dist/index.solid.js
|
|
415
437
|
function focus(form, config) {
|
|
416
|
-
getFieldStore(form[INTERNAL], config.path)
|
|
438
|
+
focusFieldElement(getFieldStore(form[INTERNAL], config.path));
|
|
417
439
|
}
|
|
418
440
|
// @__NO_SIDE_EFFECTS__
|
|
419
441
|
function getAllErrors(form) {
|
|
@@ -733,9 +755,13 @@ function useField(form, config) {
|
|
|
733
755
|
const internalFieldStore = getInternalFieldStore();
|
|
734
756
|
internalFieldStore.elements.push(element);
|
|
735
757
|
onCleanup(() => {
|
|
736
|
-
|
|
758
|
+
const elements = internalFieldStore.elements.filter(
|
|
737
759
|
(el) => el !== element
|
|
738
760
|
);
|
|
761
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) {
|
|
762
|
+
internalFieldStore.initialElements = elements;
|
|
763
|
+
}
|
|
764
|
+
internalFieldStore.elements = elements;
|
|
739
765
|
});
|
|
740
766
|
},
|
|
741
767
|
onFocus() {
|
package/dist/index.jsx
CHANGED
|
@@ -111,29 +111,40 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
|
|
|
111
111
|
});
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
-
function resetItemState(internalFieldStore,
|
|
114
|
+
function resetItemState(internalFieldStore, input, keepStart = false) {
|
|
115
115
|
batch(() => {
|
|
116
|
-
|
|
116
|
+
const elements = [];
|
|
117
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) internalFieldStore.initialElements = elements;
|
|
118
|
+
internalFieldStore.elements = elements;
|
|
117
119
|
internalFieldStore.errors.value = null;
|
|
118
120
|
internalFieldStore.isTouched.value = false;
|
|
119
121
|
internalFieldStore.isDirty.value = false;
|
|
120
122
|
if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
|
|
121
|
-
const objectInput =
|
|
122
|
-
internalFieldStore.startInput.value = objectInput;
|
|
123
|
+
const objectInput = input == null ? input : true;
|
|
124
|
+
if (!keepStart) internalFieldStore.startInput.value = objectInput;
|
|
123
125
|
internalFieldStore.input.value = objectInput;
|
|
124
|
-
if (internalFieldStore.kind === "array") if (
|
|
125
|
-
const
|
|
126
|
-
|
|
126
|
+
if (internalFieldStore.kind === "array") if (input) {
|
|
127
|
+
const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
|
|
128
|
+
const newItems = Array.from({ length }, createId);
|
|
129
|
+
if (!keepStart) internalFieldStore.startItems.value = newItems;
|
|
127
130
|
internalFieldStore.items.value = newItems;
|
|
128
|
-
|
|
131
|
+
let path;
|
|
132
|
+
for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
|
|
133
|
+
else {
|
|
134
|
+
path ??= JSON.parse(internalFieldStore.name);
|
|
135
|
+
internalFieldStore.children[index] = {};
|
|
136
|
+
path.push(index);
|
|
137
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
|
|
138
|
+
path.pop();
|
|
139
|
+
}
|
|
129
140
|
} else {
|
|
130
|
-
internalFieldStore.startItems.value = [];
|
|
141
|
+
if (!keepStart) internalFieldStore.startItems.value = [];
|
|
131
142
|
internalFieldStore.items.value = [];
|
|
132
143
|
}
|
|
133
|
-
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key],
|
|
144
|
+
else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
|
|
134
145
|
} else {
|
|
135
|
-
internalFieldStore.startInput.value =
|
|
136
|
-
internalFieldStore.input.value =
|
|
146
|
+
if (!keepStart) internalFieldStore.startInput.value = input;
|
|
147
|
+
internalFieldStore.input.value = input;
|
|
137
148
|
}
|
|
138
149
|
});
|
|
139
150
|
}
|
|
@@ -190,6 +201,13 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
|
|
|
190
201
|
});
|
|
191
202
|
});
|
|
192
203
|
}
|
|
204
|
+
function focusFieldElement(internalFieldStore) {
|
|
205
|
+
for (const element of internalFieldStore.elements) {
|
|
206
|
+
element.focus();
|
|
207
|
+
if (element.getRootNode().activeElement === element) return true;
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
193
211
|
// @__NO_SIDE_EFFECTS__
|
|
194
212
|
function getFieldBool(internalFieldStore, type) {
|
|
195
213
|
if (internalFieldStore[type].value) return true;
|
|
@@ -273,11 +291,9 @@ function getFieldStore(internalFormStore, path) {
|
|
|
273
291
|
}
|
|
274
292
|
function setFieldBool(internalFieldStore, type, bool) {
|
|
275
293
|
batch(() => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
} else if (internalFieldStore.kind == "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
280
|
-
else internalFieldStore[type].value = bool;
|
|
294
|
+
internalFieldStore[type].value = bool;
|
|
295
|
+
if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
|
|
296
|
+
else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
|
|
281
297
|
});
|
|
282
298
|
}
|
|
283
299
|
function setNestedInput(internalFieldStore, input) {
|
|
@@ -285,20 +301,20 @@ function setNestedInput(internalFieldStore, input) {
|
|
|
285
301
|
if (internalFieldStore.kind === "array") {
|
|
286
302
|
const arrayInput = input ?? [];
|
|
287
303
|
const items = internalFieldStore.items.value;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
|
|
305
|
+
if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
|
|
306
|
+
else if (length > items.length) {
|
|
307
|
+
const path = JSON.parse(internalFieldStore.name);
|
|
308
|
+
for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
|
|
309
|
+
else {
|
|
310
|
+
internalFieldStore.children[index] = {};
|
|
311
|
+
path.push(index);
|
|
312
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
313
|
+
path.pop();
|
|
298
314
|
}
|
|
299
|
-
internalFieldStore.items.value = [...items, ...
|
|
315
|
+
internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createId)];
|
|
300
316
|
}
|
|
301
|
-
for (let index = 0; index <
|
|
317
|
+
for (let index = 0; index < length; index++) setNestedInput(internalFieldStore.children[index], arrayInput[index]);
|
|
302
318
|
internalFieldStore.input.value = input == null ? input : true;
|
|
303
319
|
internalFieldStore.isDirty.value = internalFieldStore.startInput.value !== internalFieldStore.input.value || internalFieldStore.startItems.value.length !== internalFieldStore.items.value.length;
|
|
304
320
|
} else if (internalFieldStore.kind === "object") {
|
|
@@ -326,21 +342,22 @@ function setFieldInput(internalFormStore, path, input) {
|
|
|
326
342
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
327
343
|
batch(() => {
|
|
328
344
|
if (internalFieldStore.kind === "array") {
|
|
329
|
-
internalFieldStore.
|
|
345
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
330
346
|
const initialArrayInput = initialInput ?? [];
|
|
331
|
-
|
|
347
|
+
const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
|
|
348
|
+
if (length > internalFieldStore.children.length) {
|
|
332
349
|
const path = JSON.parse(internalFieldStore.name);
|
|
333
|
-
for (let index = internalFieldStore.children.length; index <
|
|
350
|
+
for (let index = internalFieldStore.children.length; index < length; index++) {
|
|
334
351
|
internalFieldStore.children[index] = {};
|
|
335
352
|
path.push(index);
|
|
336
353
|
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
337
354
|
path.pop();
|
|
338
355
|
}
|
|
339
356
|
}
|
|
340
|
-
internalFieldStore.initialItems.value =
|
|
357
|
+
internalFieldStore.initialItems.value = Array.from({ length }, createId);
|
|
341
358
|
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
342
359
|
} else if (internalFieldStore.kind === "object") {
|
|
343
|
-
internalFieldStore.
|
|
360
|
+
internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
|
|
344
361
|
for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
345
362
|
} else internalFieldStore.initialInput.value = initialInput;
|
|
346
363
|
});
|
|
@@ -365,44 +382,49 @@ function createFormStore(config, parse) {
|
|
|
365
382
|
async function validateFormInput(internalFormStore, config) {
|
|
366
383
|
internalFormStore.validators++;
|
|
367
384
|
internalFormStore.isValidating.value = true;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const path
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const name = JSON.stringify(path);
|
|
383
|
-
const fieldErrors = nestedErrors[name];
|
|
384
|
-
if (fieldErrors) fieldErrors.push(issue.message);
|
|
385
|
-
else nestedErrors[name] = [issue.message];
|
|
386
|
-
} else if (rootErrors) rootErrors.push(issue.message);
|
|
387
|
-
else rootErrors = [issue.message];
|
|
388
|
-
}
|
|
389
|
-
let shouldFocus = config?.shouldFocus ?? false;
|
|
390
|
-
batch(() => {
|
|
391
|
-
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
392
|
-
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
393
|
-
else {
|
|
394
|
-
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
395
|
-
internalFieldStore.errors.value = fieldErrors;
|
|
396
|
-
if (shouldFocus && fieldErrors) {
|
|
397
|
-
internalFieldStore.elements[0]?.focus();
|
|
398
|
-
shouldFocus = false;
|
|
385
|
+
try {
|
|
386
|
+
const result = await internalFormStore.parse(untrack(() => /* @__PURE__ */ getFieldInput(internalFormStore)));
|
|
387
|
+
let rootErrors;
|
|
388
|
+
let nestedErrors;
|
|
389
|
+
if (result.issues) {
|
|
390
|
+
nestedErrors = {};
|
|
391
|
+
for (const issue of result.issues) if (issue.path) {
|
|
392
|
+
const path = [];
|
|
393
|
+
for (const pathItem of issue.path) {
|
|
394
|
+
const key = pathItem.key;
|
|
395
|
+
const keyType = typeof key;
|
|
396
|
+
const itemType = pathItem.type;
|
|
397
|
+
if (keyType !== "string" && keyType !== "number" || itemType === "map" || itemType === "set") break;
|
|
398
|
+
path.push(key);
|
|
399
399
|
}
|
|
400
|
-
|
|
400
|
+
const name = JSON.stringify(path);
|
|
401
|
+
const fieldErrors = nestedErrors[name];
|
|
402
|
+
if (fieldErrors) fieldErrors.push(issue.message);
|
|
403
|
+
else nestedErrors[name] = [issue.message];
|
|
404
|
+
} else if (rootErrors) rootErrors.push(issue.message);
|
|
405
|
+
else rootErrors = [issue.message];
|
|
406
|
+
}
|
|
407
|
+
let shouldFocus = config?.shouldFocus ?? false;
|
|
408
|
+
batch(() => {
|
|
409
|
+
walkFieldStore(internalFormStore, (internalFieldStore) => {
|
|
410
|
+
if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
|
|
411
|
+
else {
|
|
412
|
+
const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
|
|
413
|
+
internalFieldStore.errors.value = fieldErrors;
|
|
414
|
+
if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
internalFormStore.validators--;
|
|
418
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
401
419
|
});
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
420
|
+
return result;
|
|
421
|
+
} catch (error) {
|
|
422
|
+
batch(() => {
|
|
423
|
+
internalFormStore.validators--;
|
|
424
|
+
internalFormStore.isValidating.value = internalFormStore.validators > 0;
|
|
425
|
+
});
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
406
428
|
}
|
|
407
429
|
function validateIfRequired(internalFormStore, internalFieldStore, validationMode) {
|
|
408
430
|
if (validationMode === (internalFormStore.validate === "initial" || (internalFormStore.validate === "submit" ? untrack(() => internalFormStore.isSubmitted.value) : untrack(() => /* @__PURE__ */ getFieldBool(internalFieldStore, "errors"))) ? internalFormStore.revalidate : internalFormStore.validate)) validateFormInput(internalFormStore);
|
|
@@ -411,7 +433,7 @@ var INTERNAL = "~internal";
|
|
|
411
433
|
|
|
412
434
|
// ../../packages/methods/dist/index.solid.js
|
|
413
435
|
function focus(form, config) {
|
|
414
|
-
getFieldStore(form[INTERNAL], config.path)
|
|
436
|
+
focusFieldElement(getFieldStore(form[INTERNAL], config.path));
|
|
415
437
|
}
|
|
416
438
|
// @__NO_SIDE_EFFECTS__
|
|
417
439
|
function getAllErrors(form) {
|
|
@@ -738,9 +760,13 @@ function useField(form, config) {
|
|
|
738
760
|
const internalFieldStore = getInternalFieldStore();
|
|
739
761
|
internalFieldStore.elements.push(element);
|
|
740
762
|
onCleanup(() => {
|
|
741
|
-
|
|
763
|
+
const elements = internalFieldStore.elements.filter(
|
|
742
764
|
(el) => el !== element
|
|
743
765
|
);
|
|
766
|
+
if (internalFieldStore.elements === internalFieldStore.initialElements) {
|
|
767
|
+
internalFieldStore.initialElements = elements;
|
|
768
|
+
}
|
|
769
|
+
internalFieldStore.elements = elements;
|
|
744
770
|
});
|
|
745
771
|
},
|
|
746
772
|
onFocus() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formisch/solid",
|
|
3
3
|
"description": "The lightweight, schema-first, and fully type-safe form library for SolidJS",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fabian Hiller",
|
|
7
7
|
"homepage": "https://formisch.dev",
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
"@formisch/methods": "workspace:*",
|
|
58
58
|
"@solidjs/testing-library": "^0.8.10",
|
|
59
59
|
"@testing-library/jest-dom": "^6.6.0",
|
|
60
|
-
"@
|
|
60
|
+
"@types/node": "24.0.13",
|
|
61
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
61
62
|
"eslint": "^9.31.0",
|
|
62
63
|
"eslint-plugin-solid": "^0.14.5",
|
|
63
64
|
"jsdom": "^26.1.0",
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
"typescript": "^5.8.3",
|
|
71
72
|
"valibot": "^1.4.1",
|
|
72
73
|
"vite-plugin-solid": "^2.11.6",
|
|
73
|
-
"vitest": "
|
|
74
|
+
"vitest": "4.1.7"
|
|
74
75
|
},
|
|
75
76
|
"peerDependencies": {
|
|
76
77
|
"solid-js": "^1.6.0",
|