@formisch/qwik 0.2.0 → 0.3.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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Formisch is a schema-based, headless form library for Qwik. 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-qwik)!
4
4
 
5
+ Formisch is also available for [Preact][formisch-preact], [SolidJS][formisch-solid], and [Vue][formisch-vue]. Svelte will follow soon.
6
+
5
7
  ## Highlights
6
8
 
7
9
  - Small bundle size starting at 2.5 kB
@@ -60,6 +62,16 @@ export default component$(() => {
60
62
 
61
63
  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.
62
64
 
65
+ ## Comparison
66
+
67
+ 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.
68
+
69
+ ## Partners
70
+
71
+ 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!
72
+
73
+ ![Partners of Formisch](https://github.com/fabian-hiller/formisch/blob/main/partners.webp?raw=true)
74
+
63
75
  ## Feedback
64
76
 
65
77
  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!
@@ -67,3 +79,7 @@ Find a bug or have an idea how to improve the library? Please fill out an [issue
67
79
  ## License
68
80
 
69
81
  This project is available free of charge and licensed under the [MIT license](https://github.com/fabian-hiller/formisch/blob/main/LICENSE.md).
82
+
83
+ [formisch-preact]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/preact
84
+ [formisch-solid]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/solid
85
+ [formisch-vue]: https://github.com/fabian-hiller/formisch/tree/main/frameworks/vue
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as v from "valibot";
2
2
  import { JSXOutput, NoSerialize, PropsOf, QRL, ReadonlySignal } from "@qwik.dev/core";
3
- import * as _qwik_dev_core_internal1 from "@qwik.dev/core/internal";
3
+ import * as _qwik_dev_core_internal3 from "@qwik.dev/core/internal";
4
4
 
5
5
  //#region ../../packages/core/dist/index.qwik.d.ts
6
6
  //#region src/types/schema.d.ts
@@ -78,7 +78,7 @@ type PartialValues<TValue> = TValue extends readonly unknown[] ? number extends
78
78
  * Value type of the validation mode.
79
79
  */
80
80
  type ValidationMode = "initial" | "touch" | "input" | "change" | "blur" | "submit";
81
- type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<void>;
81
+ type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
82
82
  //#endregion
83
83
  //#region src/types/form.qwik.d.ts
84
84
  interface FormConfig<TSchema extends Schema = Schema> {
@@ -129,16 +129,16 @@ type MergeUnion<T> = { [K in KeyOf<T>]: T extends Record<K, infer V> ? V : never
129
129
  /**
130
130
  * Lazily evaluate only the first valid path segment based on the given value.
131
131
  */
132
- 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], TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<KeyOf<TValue>> extends false ? readonly [...TValidPath, KeyOf<TValue>] : TValidPath;
132
+ 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;
133
133
  /**
134
134
  * Returns the path if valid, otherwise the first possible valid path based on
135
135
  * the given value.
136
136
  */
137
- type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<TValue, TPath> ? TPath : LazyPath<TValue, TPath>;
137
+ type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
138
138
  /**
139
139
  * Extracts the value type at the given path.
140
140
  */
141
- type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends KeyOf<TValue> ? PathValue<MergeUnion<TValue>[TKey], TRest> : unknown : TValue;
141
+ 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;
142
142
  /**
143
143
  * Checks if a value is an array or contains one.
144
144
  */
@@ -146,16 +146,16 @@ type IsOrHasArray<TValue> = IsAny<TValue> extends true ? false : TValue extends
146
146
  /**
147
147
  * Extracts the exact keys of a tuple, array or object that contain arrays.
148
148
  */
149
- 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]> extends true ? TIndex : never : never }[number] : TValue extends Record<string, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> extends true ? TKey : never }[keyof TValue] & PathKey : never;
149
+ 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;
150
150
  /**
151
151
  * Lazily evaluate only the first valid array path segment based on the given value.
152
152
  */
153
- 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], TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<KeyOfArrayPath<TValue>> extends false ? readonly [...TValidPath, KeyOfArrayPath<TValue>] : never;
153
+ 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;
154
154
  /**
155
155
  * Returns the path if valid, otherwise the first possible valid array path based on
156
156
  * the given value.
157
157
  */
158
- type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<TValue, TPath> ? TPath : LazyArrayPath<TValue, TPath>;
158
+ type ValidArrayPath<TValue, TPath extends RequiredPath> = TPath extends LazyArrayPath<Required<TValue>, TPath> ? TPath : LazyArrayPath<Required<TValue>, TPath>;
159
159
  //#endregion
160
160
  //#region src/array/copyItemState/copyItemState.d.ts
161
161
  /**
@@ -353,7 +353,7 @@ interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends Require
353
353
  /**
354
354
  * Headless form field that provides reactive properties and state.
355
355
  */
356
- declare const Field: <TSchema extends Schema, TFieldPath extends RequiredPath>(props: _qwik_dev_core_internal1.PublicProps<FieldProps<TSchema, TFieldPath>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal1.DevJSX) => JSXOutput;
356
+ declare const Field: <TSchema extends Schema, TFieldPath extends RequiredPath>(props: _qwik_dev_core_internal3.PublicProps<FieldProps<TSchema, TFieldPath>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal3.DevJSX) => JSXOutput;
357
357
  //#endregion
358
358
  //#region src/components/FieldArray/FieldArray.d.ts
359
359
  /**
@@ -367,14 +367,14 @@ interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath exten
367
367
  /**
368
368
  * Headless field array that provides reactive properties and state.
369
369
  */
370
- declare const FieldArray: <TSchema extends Schema, TFieldArrayPath extends RequiredPath>(props: _qwik_dev_core_internal1.PublicProps<FieldArrayProps<TSchema, TFieldArrayPath>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal1.DevJSX) => JSXOutput;
370
+ declare const FieldArray: <TSchema extends Schema, TFieldArrayPath extends RequiredPath>(props: _qwik_dev_core_internal3.PublicProps<FieldArrayProps<TSchema, TFieldArrayPath>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal3.DevJSX) => JSXOutput;
371
371
  //#endregion
372
372
  //#region src/components/Form/Form.d.ts
373
373
  type FormProps<TSchema extends Schema = Schema> = Omit<PropsOf<'form'>, 'onSubmit$'> & {
374
374
  of: FormStore<TSchema>;
375
375
  onSubmit$: QRL<SubmitHandler<TSchema>>;
376
376
  };
377
- declare const Form: <TSchema extends Schema>(props: _qwik_dev_core_internal1.PublicProps<FormProps<TSchema>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal1.DevJSX) => JSXOutput;
377
+ declare const Form: <TSchema extends Schema>(props: _qwik_dev_core_internal3.PublicProps<FormProps<TSchema>>, key: string | null, flags: number, dev?: _qwik_dev_core_internal3.DevJSX) => JSXOutput;
378
378
  //#endregion
379
379
  //#region src/hooks/useField/useField.d.ts
380
380
  interface UseFieldConfig<TSchema extends Schema = Schema, TFieldPath extends RequiredPath = RequiredPath> {
@@ -296,6 +296,7 @@ function setFieldInput(internalFieldStore, input) {
296
296
  } else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldInput(internalFieldStore.children[key], input[key]);
297
297
  else {
298
298
  internalFieldStore.input.value = input;
299
+ internalFieldStore.isTouched.value = true;
299
300
  const startInput = untrack(() => internalFieldStore.startInput.value);
300
301
  internalFieldStore.isDirty.value = startInput !== input && (startInput !== void 0 || input !== "" && !Number.isNaN(input));
301
302
  }
@@ -521,7 +522,6 @@ function setInput(form, config) {
521
522
  batch(() => {
522
523
  const internalFormStore = form[INTERNAL];
523
524
  const internalFieldStore = config.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
524
- setFieldBool(internalFieldStore, "isTouched", true);
525
525
  setFieldInput(internalFieldStore, config.input);
526
526
  validateIfRequired(internalFormStore, internalFieldStore, "input");
527
527
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formisch/qwik",
3
3
  "description": "The modular and type-safe form library for Qwik",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "license": "MIT",
6
6
  "author": "Fabian Hiller",
7
7
  "homepage": "https://formisch.dev",