@formisch/solid 0.2.0 → 0.3.1
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 +17 -0
- package/dist/dev.js +19 -17
- package/dist/dev.jsx +19 -17
- package/dist/index.d.ts +8 -8
- package/dist/index.js +19 -17
- package/dist/index.jsx +19 -17
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Formisch is a schema-based, headless form library for SolidJS. 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-solid)!
|
|
4
4
|
|
|
5
|
+
Formisch is also available for [Preact][formisch-preact], [Qwik][formisch-qwik], [Svelte][formisch-svelte] and [Vue][formisch-vue].
|
|
6
|
+
|
|
5
7
|
## Highlights
|
|
6
8
|
|
|
7
9
|
- Small bundle size starting at 2.5 kB
|
|
@@ -55,6 +57,16 @@ export default function LoginPage() {
|
|
|
55
57
|
|
|
56
58
|
In addition, Formisch offers several functions (we call them "methods") that can be used to read and manipulate the form state. These include `focus`, `getErrors`, `getAllErrors`, `getInput`, `insert`, `move`, `remove`, `replace`, `reset`, `setErrors`, `setInput`, `submit`, `swap` and `validate`. These methods allow you to control the form programmatically.
|
|
57
59
|
|
|
60
|
+
## Comparison
|
|
61
|
+
|
|
62
|
+
What makes Formisch unique is its framework-agnostic core, which is fully native to the framework you are using. It works by inserting framework-specific reactivity blocks when the core package is built. The result is a small bundle size and native performance for any UI update. This feature, along with a few others, distinguishes Formisch from other form libraries. My vision for Formisch is to create a framework-agnostic platform similar to [Vite](https://vite.dev/), but for forms.
|
|
63
|
+
|
|
64
|
+
## Partners
|
|
65
|
+
|
|
66
|
+
Thanks to our partners who support the development! [Join them](https://github.com/sponsors/fabian-hiller) and contribute to the sustainability of open source software!
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
|
|
58
70
|
## Feedback
|
|
59
71
|
|
|
60
72
|
Find a bug or have an idea how to improve the library? Please fill out an [issue](https://github.com/fabian-hiller/formisch/issues/new). Together we can make forms even better!
|
|
@@ -62,3 +74,8 @@ Find a bug or have an idea how to improve the library? Please fill out an [issue
|
|
|
62
74
|
## License
|
|
63
75
|
|
|
64
76
|
This project is available free of charge and licensed under the [MIT license](https://github.com/fabian-hiller/formisch/blob/main/LICENSE.md).
|
|
77
|
+
|
|
78
|
+
[formisch-preact]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/preact
|
|
79
|
+
[formisch-qwik]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/qwik
|
|
80
|
+
[formisch-svelte]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/svelte
|
|
81
|
+
[formisch-vue]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/vue
|
package/dist/dev.js
CHANGED
|
@@ -40,7 +40,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
40
40
|
} else for (let index = 0; index < schema.items; index++) {
|
|
41
41
|
internalFieldStore.children[index] = {};
|
|
42
42
|
path.push(index);
|
|
43
|
-
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput
|
|
43
|
+
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
|
|
44
44
|
path.pop();
|
|
45
45
|
}
|
|
46
46
|
const initialItems = internalFieldStore.children.map(createUniqueId);
|
|
@@ -58,7 +58,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
58
58
|
for (const key in schema.entries) {
|
|
59
59
|
internalFieldStore.children[key] = {};
|
|
60
60
|
path.push(key);
|
|
61
|
-
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput
|
|
61
|
+
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
62
62
|
path.pop();
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -244,25 +244,27 @@ function setFieldBool(internalFieldStore, type, bool) {
|
|
|
244
244
|
function setFieldInput(internalFieldStore, input) {
|
|
245
245
|
batch(() => {
|
|
246
246
|
if (internalFieldStore.kind === "array") {
|
|
247
|
+
const arrayInput = input ?? [];
|
|
247
248
|
const items = untrack(() => internalFieldStore.items.value);
|
|
248
|
-
if (
|
|
249
|
-
else if (
|
|
250
|
-
if (
|
|
249
|
+
if (arrayInput.length < items.length) internalFieldStore.items.value = items.slice(0, arrayInput.length);
|
|
250
|
+
else if (arrayInput.length > items.length) {
|
|
251
|
+
if (arrayInput.length > internalFieldStore.children.length) {
|
|
251
252
|
const path = JSON.parse(internalFieldStore.name);
|
|
252
|
-
for (let index = internalFieldStore.children.length; index <
|
|
253
|
+
for (let index = internalFieldStore.children.length; index < arrayInput.length; index++) {
|
|
253
254
|
internalFieldStore.children[index] = {};
|
|
254
255
|
path.push(index);
|
|
255
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
256
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
256
257
|
path.pop();
|
|
257
258
|
}
|
|
258
259
|
}
|
|
259
|
-
internalFieldStore.items.value = [...items, ...
|
|
260
|
+
internalFieldStore.items.value = [...items, ...arrayInput.slice(items.length).map(createUniqueId)];
|
|
260
261
|
}
|
|
261
|
-
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index],
|
|
262
|
+
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index], arrayInput[index]);
|
|
262
263
|
internalFieldStore.isDirty.value = untrack(() => internalFieldStore.startItems.value).length !== items.length;
|
|
263
|
-
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
|
|
264
|
+
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input?.[key]);
|
|
264
265
|
else {
|
|
265
266
|
internalFieldStore.input.value = input;
|
|
267
|
+
internalFieldStore.isTouched.value = true;
|
|
266
268
|
const startInput = untrack(() => internalFieldStore.startInput.value);
|
|
267
269
|
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
268
270
|
}
|
|
@@ -271,17 +273,18 @@ function setFieldInput(internalFieldStore, input) {
|
|
|
271
273
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
272
274
|
batch(() => {
|
|
273
275
|
if (internalFieldStore.kind === "array") {
|
|
274
|
-
|
|
276
|
+
const initialArrayInput = initialInput ?? [];
|
|
277
|
+
if (initialArrayInput.length > internalFieldStore.children.length) {
|
|
275
278
|
const path = JSON.parse(internalFieldStore.name);
|
|
276
|
-
for (let index = internalFieldStore.children.length; index <
|
|
279
|
+
for (let index = internalFieldStore.children.length; index < initialArrayInput.length; index++) {
|
|
277
280
|
internalFieldStore.children[index] = {};
|
|
278
281
|
path.push(index);
|
|
279
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
282
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
280
283
|
path.pop();
|
|
281
284
|
}
|
|
282
285
|
}
|
|
283
|
-
internalFieldStore.initialItems.value =
|
|
284
|
-
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index],
|
|
286
|
+
internalFieldStore.initialItems.value = initialArrayInput.map(createUniqueId);
|
|
287
|
+
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
285
288
|
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
286
289
|
else internalFieldStore.initialInput.value = initialInput;
|
|
287
290
|
});
|
|
@@ -487,7 +490,6 @@ function setInput(form, config) {
|
|
|
487
490
|
batch(() => {
|
|
488
491
|
const internalFormStore = form[INTERNAL];
|
|
489
492
|
const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
490
|
-
setFieldBool(internalFieldStore, "isTouched", true);
|
|
491
493
|
setFieldInput(internalFieldStore, config.input);
|
|
492
494
|
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
493
495
|
});
|
|
@@ -517,7 +519,7 @@ function validate(form, config) {
|
|
|
517
519
|
function createForm(config) {
|
|
518
520
|
const internalFormStore = createFormStore(
|
|
519
521
|
config,
|
|
520
|
-
|
|
522
|
+
(input) => v.safeParseAsync(config.schema, input)
|
|
521
523
|
);
|
|
522
524
|
const getIsTouched = createMemo(
|
|
523
525
|
() => getFieldBool(internalFormStore, "isTouched")
|
package/dist/dev.jsx
CHANGED
|
@@ -38,7 +38,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
38
38
|
} else for (let index = 0; index < schema.items; index++) {
|
|
39
39
|
internalFieldStore.children[index] = {};
|
|
40
40
|
path.push(index);
|
|
41
|
-
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput
|
|
41
|
+
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
|
|
42
42
|
path.pop();
|
|
43
43
|
}
|
|
44
44
|
const initialItems = internalFieldStore.children.map(createId);
|
|
@@ -56,7 +56,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
56
56
|
for (const key in schema.entries) {
|
|
57
57
|
internalFieldStore.children[key] = {};
|
|
58
58
|
path.push(key);
|
|
59
|
-
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput
|
|
59
|
+
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
60
60
|
path.pop();
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -242,25 +242,27 @@ function setFieldBool(internalFieldStore, type, bool) {
|
|
|
242
242
|
function setFieldInput(internalFieldStore, input) {
|
|
243
243
|
batch(() => {
|
|
244
244
|
if (internalFieldStore.kind === "array") {
|
|
245
|
+
const arrayInput = input ?? [];
|
|
245
246
|
const items = untrack(() => internalFieldStore.items.value);
|
|
246
|
-
if (
|
|
247
|
-
else if (
|
|
248
|
-
if (
|
|
247
|
+
if (arrayInput.length < items.length) internalFieldStore.items.value = items.slice(0, arrayInput.length);
|
|
248
|
+
else if (arrayInput.length > items.length) {
|
|
249
|
+
if (arrayInput.length > internalFieldStore.children.length) {
|
|
249
250
|
const path = JSON.parse(internalFieldStore.name);
|
|
250
|
-
for (let index = internalFieldStore.children.length; index <
|
|
251
|
+
for (let index = internalFieldStore.children.length; index < arrayInput.length; index++) {
|
|
251
252
|
internalFieldStore.children[index] = {};
|
|
252
253
|
path.push(index);
|
|
253
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
254
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
254
255
|
path.pop();
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
|
-
internalFieldStore.items.value = [...items, ...
|
|
258
|
+
internalFieldStore.items.value = [...items, ...arrayInput.slice(items.length).map(createId)];
|
|
258
259
|
}
|
|
259
|
-
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index],
|
|
260
|
+
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index], arrayInput[index]);
|
|
260
261
|
internalFieldStore.isDirty.value = untrack(() => internalFieldStore.startItems.value).length !== items.length;
|
|
261
|
-
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
|
|
262
|
+
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input?.[key]);
|
|
262
263
|
else {
|
|
263
264
|
internalFieldStore.input.value = input;
|
|
265
|
+
internalFieldStore.isTouched.value = true;
|
|
264
266
|
const startInput = untrack(() => internalFieldStore.startInput.value);
|
|
265
267
|
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
266
268
|
}
|
|
@@ -269,17 +271,18 @@ function setFieldInput(internalFieldStore, input) {
|
|
|
269
271
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
270
272
|
batch(() => {
|
|
271
273
|
if (internalFieldStore.kind === "array") {
|
|
272
|
-
|
|
274
|
+
const initialArrayInput = initialInput ?? [];
|
|
275
|
+
if (initialArrayInput.length > internalFieldStore.children.length) {
|
|
273
276
|
const path = JSON.parse(internalFieldStore.name);
|
|
274
|
-
for (let index = internalFieldStore.children.length; index <
|
|
277
|
+
for (let index = internalFieldStore.children.length; index < initialArrayInput.length; index++) {
|
|
275
278
|
internalFieldStore.children[index] = {};
|
|
276
279
|
path.push(index);
|
|
277
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
280
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
278
281
|
path.pop();
|
|
279
282
|
}
|
|
280
283
|
}
|
|
281
|
-
internalFieldStore.initialItems.value =
|
|
282
|
-
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index],
|
|
284
|
+
internalFieldStore.initialItems.value = initialArrayInput.map(createId);
|
|
285
|
+
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
283
286
|
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
284
287
|
else internalFieldStore.initialInput.value = initialInput;
|
|
285
288
|
});
|
|
@@ -485,7 +488,6 @@ function setInput(form, config) {
|
|
|
485
488
|
batch(() => {
|
|
486
489
|
const internalFormStore = form[INTERNAL];
|
|
487
490
|
const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
488
|
-
setFieldBool(internalFieldStore, "isTouched", true);
|
|
489
491
|
setFieldInput(internalFieldStore, config.input);
|
|
490
492
|
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
491
493
|
});
|
|
@@ -519,7 +521,7 @@ import * as v2 from "valibot";
|
|
|
519
521
|
function createForm(config) {
|
|
520
522
|
const internalFormStore = createFormStore(
|
|
521
523
|
config,
|
|
522
|
-
|
|
524
|
+
(input) => v2.safeParseAsync(config.schema, input)
|
|
523
525
|
);
|
|
524
526
|
const getIsTouched = createMemo(
|
|
525
527
|
() => getFieldBool(internalFormStore, "isTouched")
|
package/dist/index.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ interface InternalFormStore<TSchema extends Schema = Schema> extends InternalObj
|
|
|
94
94
|
interface BaseFormStore<TSchema extends Schema = Schema> {
|
|
95
95
|
[INTERNAL]: InternalFormStore<TSchema>;
|
|
96
96
|
}
|
|
97
|
-
type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<
|
|
97
|
+
type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
|
|
98
98
|
//#endregion
|
|
99
99
|
//#region src/types/path.d.ts
|
|
100
100
|
/**
|
|
@@ -124,16 +124,16 @@ type MergeUnion<T> = { [K in KeyOf<T>]: T extends Record<K, infer V> ? V : never
|
|
|
124
124
|
/**
|
|
125
125
|
* Lazily evaluate only the first valid path segment based on the given value.
|
|
126
126
|
*/
|
|
127
|
-
type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends KeyOf<TValue>, ...infer TPathRest extends Path] ? LazyPath<MergeUnion<TValue>[TFirstKey]
|
|
127
|
+
type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends KeyOf<TValue>, ...infer TPathRest extends Path] ? LazyPath<Required<MergeUnion<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<KeyOf<TValue>> extends false ? readonly [...TValidPath, KeyOf<TValue>] : TValidPath;
|
|
128
128
|
/**
|
|
129
129
|
* Returns the path if valid, otherwise the first possible valid path based on
|
|
130
130
|
* the given value.
|
|
131
131
|
*/
|
|
132
|
-
type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<TValue
|
|
132
|
+
type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
|
|
133
133
|
/**
|
|
134
134
|
* Extracts the value type at the given path.
|
|
135
135
|
*/
|
|
136
|
-
type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends KeyOf<TValue
|
|
136
|
+
type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends KeyOf<Required<TValue>> ? PathValue<MergeUnion<Required<TValue>>[TKey], TRest> : unknown : TValue;
|
|
137
137
|
/**
|
|
138
138
|
* Checks if a value is an array or contains one.
|
|
139
139
|
*/
|
|
@@ -141,16 +141,16 @@ type IsOrHasArray<TValue> = IsAny<TValue> extends true ? false : TValue extends
|
|
|
141
141
|
/**
|
|
142
142
|
* Extracts the exact keys of a tuple, array or object that contain arrays.
|
|
143
143
|
*/
|
|
144
|
-
type KeyOfArrayPath<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? IsOrHasArray<TItem> extends true ? number : never : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? IsOrHasArray<TValue[TKey]
|
|
144
|
+
type KeyOfArrayPath<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? IsOrHasArray<TItem> extends true ? number : never : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TIndex : never : never }[number] : TValue extends Record<string, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TKey : never }[keyof TValue] & PathKey : never;
|
|
145
145
|
/**
|
|
146
146
|
* Lazily evaluate only the first valid array path segment based on the given value.
|
|
147
147
|
*/
|
|
148
|
-
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? TValidPath : readonly [...TValidPath, KeyOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends KeyOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<MergeUnion<TValue>[TFirstKey]
|
|
148
|
+
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? TValidPath : readonly [...TValidPath, KeyOfArrayPath<TValue>] : TPathToCheck extends readonly [infer TFirstKey extends KeyOfArrayPath<TValue>, ...infer TPathRest extends Path] ? LazyArrayPath<Required<MergeUnion<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<KeyOfArrayPath<TValue>> extends false ? readonly [...TValidPath, KeyOfArrayPath<TValue>] : never;
|
|
149
149
|
/**
|
|
150
150
|
* Returns the path if valid, otherwise the first possible valid array path based on
|
|
151
151
|
* the given value.
|
|
152
152
|
*/
|
|
153
|
-
type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<TValue
|
|
153
|
+
type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
|
|
154
154
|
//#endregion
|
|
155
155
|
//#region src/array/copyItemState/copyItemState.d.ts
|
|
156
156
|
/**
|
|
@@ -371,7 +371,7 @@ interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath exten
|
|
|
371
371
|
declare function FieldArray<TSchema extends Schema, TFieldArrayPath extends RequiredPath>(props: FieldArrayProps<TSchema, TFieldArrayPath>): JSX.Element;
|
|
372
372
|
//#endregion
|
|
373
373
|
//#region src/components/Form/Form.d.ts
|
|
374
|
-
type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> & {
|
|
374
|
+
type FormProps<TSchema extends Schema = Schema> = Omit<JSX.FormHTMLAttributes<HTMLFormElement>, "onSubmit" | "novalidate" | "noValidate"> & {
|
|
375
375
|
of: FormStore<TSchema>;
|
|
376
376
|
children: JSX.Element;
|
|
377
377
|
onSubmit: SubmitHandler<TSchema>;
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
40
40
|
} else for (let index = 0; index < schema.items; index++) {
|
|
41
41
|
internalFieldStore.children[index] = {};
|
|
42
42
|
path.push(index);
|
|
43
|
-
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput
|
|
43
|
+
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
|
|
44
44
|
path.pop();
|
|
45
45
|
}
|
|
46
46
|
const initialItems = internalFieldStore.children.map(createUniqueId);
|
|
@@ -58,7 +58,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
58
58
|
for (const key in schema.entries) {
|
|
59
59
|
internalFieldStore.children[key] = {};
|
|
60
60
|
path.push(key);
|
|
61
|
-
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput
|
|
61
|
+
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
62
62
|
path.pop();
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -244,25 +244,27 @@ function setFieldBool(internalFieldStore, type, bool) {
|
|
|
244
244
|
function setFieldInput(internalFieldStore, input) {
|
|
245
245
|
batch(() => {
|
|
246
246
|
if (internalFieldStore.kind === "array") {
|
|
247
|
+
const arrayInput = input ?? [];
|
|
247
248
|
const items = untrack(() => internalFieldStore.items.value);
|
|
248
|
-
if (
|
|
249
|
-
else if (
|
|
250
|
-
if (
|
|
249
|
+
if (arrayInput.length < items.length) internalFieldStore.items.value = items.slice(0, arrayInput.length);
|
|
250
|
+
else if (arrayInput.length > items.length) {
|
|
251
|
+
if (arrayInput.length > internalFieldStore.children.length) {
|
|
251
252
|
const path = JSON.parse(internalFieldStore.name);
|
|
252
|
-
for (let index = internalFieldStore.children.length; index <
|
|
253
|
+
for (let index = internalFieldStore.children.length; index < arrayInput.length; index++) {
|
|
253
254
|
internalFieldStore.children[index] = {};
|
|
254
255
|
path.push(index);
|
|
255
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
256
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
256
257
|
path.pop();
|
|
257
258
|
}
|
|
258
259
|
}
|
|
259
|
-
internalFieldStore.items.value = [...items, ...
|
|
260
|
+
internalFieldStore.items.value = [...items, ...arrayInput.slice(items.length).map(createUniqueId)];
|
|
260
261
|
}
|
|
261
|
-
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index],
|
|
262
|
+
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index], arrayInput[index]);
|
|
262
263
|
internalFieldStore.isDirty.value = untrack(() => internalFieldStore.startItems.value).length !== items.length;
|
|
263
|
-
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
|
|
264
|
+
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input?.[key]);
|
|
264
265
|
else {
|
|
265
266
|
internalFieldStore.input.value = input;
|
|
267
|
+
internalFieldStore.isTouched.value = true;
|
|
266
268
|
const startInput = untrack(() => internalFieldStore.startInput.value);
|
|
267
269
|
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
268
270
|
}
|
|
@@ -271,17 +273,18 @@ function setFieldInput(internalFieldStore, input) {
|
|
|
271
273
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
272
274
|
batch(() => {
|
|
273
275
|
if (internalFieldStore.kind === "array") {
|
|
274
|
-
|
|
276
|
+
const initialArrayInput = initialInput ?? [];
|
|
277
|
+
if (initialArrayInput.length > internalFieldStore.children.length) {
|
|
275
278
|
const path = JSON.parse(internalFieldStore.name);
|
|
276
|
-
for (let index = internalFieldStore.children.length; index <
|
|
279
|
+
for (let index = internalFieldStore.children.length; index < initialArrayInput.length; index++) {
|
|
277
280
|
internalFieldStore.children[index] = {};
|
|
278
281
|
path.push(index);
|
|
279
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
282
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
280
283
|
path.pop();
|
|
281
284
|
}
|
|
282
285
|
}
|
|
283
|
-
internalFieldStore.initialItems.value =
|
|
284
|
-
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index],
|
|
286
|
+
internalFieldStore.initialItems.value = initialArrayInput.map(createUniqueId);
|
|
287
|
+
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
285
288
|
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
286
289
|
else internalFieldStore.initialInput.value = initialInput;
|
|
287
290
|
});
|
|
@@ -487,7 +490,6 @@ function setInput(form, config) {
|
|
|
487
490
|
batch(() => {
|
|
488
491
|
const internalFormStore = form[INTERNAL];
|
|
489
492
|
const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
490
|
-
setFieldBool(internalFieldStore, "isTouched", true);
|
|
491
493
|
setFieldInput(internalFieldStore, config.input);
|
|
492
494
|
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
493
495
|
});
|
|
@@ -517,7 +519,7 @@ function validate(form, config) {
|
|
|
517
519
|
function createForm(config) {
|
|
518
520
|
const internalFormStore = createFormStore(
|
|
519
521
|
config,
|
|
520
|
-
|
|
522
|
+
(input) => v.safeParseAsync(config.schema, input)
|
|
521
523
|
);
|
|
522
524
|
const getIsTouched = createMemo(
|
|
523
525
|
() => getFieldBool(internalFormStore, "isTouched")
|
package/dist/index.jsx
CHANGED
|
@@ -38,7 +38,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
38
38
|
} else for (let index = 0; index < schema.items; index++) {
|
|
39
39
|
internalFieldStore.children[index] = {};
|
|
40
40
|
path.push(index);
|
|
41
|
-
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput
|
|
41
|
+
initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
|
|
42
42
|
path.pop();
|
|
43
43
|
}
|
|
44
44
|
const initialItems = internalFieldStore.children.map(createId);
|
|
@@ -56,7 +56,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path) {
|
|
|
56
56
|
for (const key in schema.entries) {
|
|
57
57
|
internalFieldStore.children[key] = {};
|
|
58
58
|
path.push(key);
|
|
59
|
-
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput
|
|
59
|
+
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
60
60
|
path.pop();
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -242,25 +242,27 @@ function setFieldBool(internalFieldStore, type, bool) {
|
|
|
242
242
|
function setFieldInput(internalFieldStore, input) {
|
|
243
243
|
batch(() => {
|
|
244
244
|
if (internalFieldStore.kind === "array") {
|
|
245
|
+
const arrayInput = input ?? [];
|
|
245
246
|
const items = untrack(() => internalFieldStore.items.value);
|
|
246
|
-
if (
|
|
247
|
-
else if (
|
|
248
|
-
if (
|
|
247
|
+
if (arrayInput.length < items.length) internalFieldStore.items.value = items.slice(0, arrayInput.length);
|
|
248
|
+
else if (arrayInput.length > items.length) {
|
|
249
|
+
if (arrayInput.length > internalFieldStore.children.length) {
|
|
249
250
|
const path = JSON.parse(internalFieldStore.name);
|
|
250
|
-
for (let index = internalFieldStore.children.length; index <
|
|
251
|
+
for (let index = internalFieldStore.children.length; index < arrayInput.length; index++) {
|
|
251
252
|
internalFieldStore.children[index] = {};
|
|
252
253
|
path.push(index);
|
|
253
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
254
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
|
|
254
255
|
path.pop();
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
|
-
internalFieldStore.items.value = [...items, ...
|
|
258
|
+
internalFieldStore.items.value = [...items, ...arrayInput.slice(items.length).map(createId)];
|
|
258
259
|
}
|
|
259
|
-
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index],
|
|
260
|
+
for (let index = 0; index < items.length; index++) setFieldInput(internalFieldStore.children[index], arrayInput[index]);
|
|
260
261
|
internalFieldStore.isDirty.value = untrack(() => internalFieldStore.startItems.value).length !== items.length;
|
|
261
|
-
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
|
|
262
|
+
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input?.[key]);
|
|
262
263
|
else {
|
|
263
264
|
internalFieldStore.input.value = input;
|
|
265
|
+
internalFieldStore.isTouched.value = true;
|
|
264
266
|
const startInput = untrack(() => internalFieldStore.startInput.value);
|
|
265
267
|
internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
|
|
266
268
|
}
|
|
@@ -269,17 +271,18 @@ function setFieldInput(internalFieldStore, input) {
|
|
|
269
271
|
function setInitialFieldInput(internalFieldStore, initialInput) {
|
|
270
272
|
batch(() => {
|
|
271
273
|
if (internalFieldStore.kind === "array") {
|
|
272
|
-
|
|
274
|
+
const initialArrayInput = initialInput ?? [];
|
|
275
|
+
if (initialArrayInput.length > internalFieldStore.children.length) {
|
|
273
276
|
const path = JSON.parse(internalFieldStore.name);
|
|
274
|
-
for (let index = internalFieldStore.children.length; index <
|
|
277
|
+
for (let index = internalFieldStore.children.length; index < initialArrayInput.length; index++) {
|
|
275
278
|
internalFieldStore.children[index] = {};
|
|
276
279
|
path.push(index);
|
|
277
|
-
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item,
|
|
280
|
+
initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
|
|
278
281
|
path.pop();
|
|
279
282
|
}
|
|
280
283
|
}
|
|
281
|
-
internalFieldStore.initialItems.value =
|
|
282
|
-
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index],
|
|
284
|
+
internalFieldStore.initialItems.value = initialArrayInput.map(createId);
|
|
285
|
+
for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
|
|
283
286
|
} else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setInitialFieldInput(internalFieldStore.children[key], initialInput?.[key]);
|
|
284
287
|
else internalFieldStore.initialInput.value = initialInput;
|
|
285
288
|
});
|
|
@@ -485,7 +488,6 @@ function setInput(form, config) {
|
|
|
485
488
|
batch(() => {
|
|
486
489
|
const internalFormStore = form[INTERNAL];
|
|
487
490
|
const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
488
|
-
setFieldBool(internalFieldStore, "isTouched", true);
|
|
489
491
|
setFieldInput(internalFieldStore, config.input);
|
|
490
492
|
validateIfRequired(internalFormStore, internalFieldStore, "input");
|
|
491
493
|
});
|
|
@@ -519,7 +521,7 @@ import * as v2 from "valibot";
|
|
|
519
521
|
function createForm(config) {
|
|
520
522
|
const internalFormStore = createFormStore(
|
|
521
523
|
config,
|
|
522
|
-
|
|
524
|
+
(input) => v2.safeParseAsync(config.schema, input)
|
|
523
525
|
);
|
|
524
526
|
const getIsTouched = createMemo(
|
|
525
527
|
() => getFieldBool(internalFormStore, "isTouched")
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formisch/solid",
|
|
3
3
|
"description": "The modular and type-safe form library for SolidJS",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fabian Hiller",
|
|
7
7
|
"homepage": "https://formisch.dev",
|
|
@@ -43,18 +43,8 @@
|
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
|
-
"scripts": {
|
|
47
|
-
"test": "vitest --typecheck",
|
|
48
|
-
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
49
|
-
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
50
|
-
"format": "prettier --write ./src",
|
|
51
|
-
"format.check": "prettier --check ./src",
|
|
52
|
-
"build": "tsup && tsdown"
|
|
53
|
-
},
|
|
54
46
|
"devDependencies": {
|
|
55
47
|
"@eslint/js": "^9.31.0",
|
|
56
|
-
"@formisch/core": "workspace:*",
|
|
57
|
-
"@formisch/methods": "workspace:*",
|
|
58
48
|
"@vitest/coverage-v8": "^3.2.4",
|
|
59
49
|
"eslint": "^9.31.0",
|
|
60
50
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -71,7 +61,9 @@
|
|
|
71
61
|
"typescript": "^5.8.3",
|
|
72
62
|
"typescript-eslint": "^8.36.0",
|
|
73
63
|
"valibot": "^1.1.0",
|
|
74
|
-
"vitest": "3.2.4"
|
|
64
|
+
"vitest": "3.2.4",
|
|
65
|
+
"@formisch/core": "0.3.1",
|
|
66
|
+
"@formisch/methods": "0.2.0"
|
|
75
67
|
},
|
|
76
68
|
"peerDependencies": {
|
|
77
69
|
"solid-js": "^1.6.0",
|
|
@@ -84,5 +76,13 @@
|
|
|
84
76
|
}
|
|
85
77
|
},
|
|
86
78
|
"browser": {},
|
|
87
|
-
"typesVersions": {}
|
|
88
|
-
|
|
79
|
+
"typesVersions": {},
|
|
80
|
+
"scripts": {
|
|
81
|
+
"test": "vitest --typecheck",
|
|
82
|
+
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
83
|
+
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
84
|
+
"format": "prettier --write ./src",
|
|
85
|
+
"format.check": "prettier --check ./src",
|
|
86
|
+
"build": "tsup && tsdown"
|
|
87
|
+
}
|
|
88
|
+
}
|