@formisch/qwik 0.10.0 → 0.10.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/dist/index.d.ts CHANGED
@@ -4,13 +4,13 @@ import * as _qwik_dev_core_internal0 from "@qwik.dev/core/internal";
4
4
 
5
5
  //#region ../../packages/core/dist/index.qwik.d.ts
6
6
 
7
- //#region src/types/schema.d.ts
7
+ //#region src/types/schema/schema.d.ts
8
8
  /**
9
9
  * Schema type.
10
10
  */
11
11
  type Schema = v.GenericSchema | v.GenericSchemaAsync;
12
12
  //#endregion
13
- //#region src/types/signal.d.ts
13
+ //#region src/types/signal/signal.d.ts
14
14
  /**
15
15
  * Signal interface.
16
16
  */
@@ -25,13 +25,13 @@ interface Signal<T> {
25
25
  */
26
26
 
27
27
  //#endregion
28
- //#region src/types/field.d.ts
28
+ //#region src/types/field/field.d.ts
29
29
  /**
30
30
  * Field element type.
31
31
  */
32
32
  type FieldElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
33
33
  //#endregion
34
- //#region src/types/field.qwik.d.ts
34
+ //#region src/types/field/field.qwik.d.ts
35
35
  /**
36
36
  * Internal base store interface.
37
37
  */
@@ -197,7 +197,7 @@ type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalVal
197
197
  */
198
198
  declare const INTERNAL: "~internal";
199
199
  //#endregion
200
- //#region src/types/utils.d.ts
200
+ //#region src/types/utils/utils.d.ts
201
201
  /**
202
202
  * Checks if a type is `any`.
203
203
  */
@@ -223,7 +223,7 @@ type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonl
223
223
  */
224
224
  type PartialValues<TValue> = TValue extends readonly (infer TItem)[] ? number extends TValue["length"] ? (TItem extends Record<PropertyKey, unknown> | readonly unknown[] ? { [TKey in keyof TItem]: PartialValues<TItem[TKey]> } : TItem)[] : { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue extends Record<PropertyKey, unknown> ? { [TKey in keyof TValue]: PartialValues<TValue[TKey]> } : TValue | undefined;
225
225
  //#endregion
226
- //#region src/types/form.d.ts
226
+ //#region src/types/form/form.d.ts
227
227
  /**
228
228
  * Validation mode type.
229
229
  */
@@ -237,7 +237,7 @@ type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>) =>
237
237
  */
238
238
  type SubmitEventHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
239
239
  //#endregion
240
- //#region src/types/form.qwik.d.ts
240
+ //#region src/types/form/form.qwik.d.ts
241
241
  /**
242
242
  * Form config interface.
243
243
  */
@@ -308,7 +308,7 @@ interface BaseFormStore<TSchema extends Schema = Schema> {
308
308
  readonly [INTERNAL]: InternalFormStore<TSchema>;
309
309
  }
310
310
  //#endregion
311
- //#region src/types/path.d.ts
311
+ //#region src/types/path/path.d.ts
312
312
  /**
313
313
  * Path key type.
314
314
  */
@@ -322,42 +322,88 @@ type Path = readonly PathKey[];
322
322
  */
323
323
  type RequiredPath = readonly [PathKey, ...Path];
324
324
  /**
325
- * Extracts the exact keys of a tuple, array or object.
325
+ * Extracts the exact keys of a tuple, array or object. Tuples return their
326
+ * literal numeric indices, dynamic arrays return `number`, objects return
327
+ * their `keyof` keys, and any other input returns `never`.
326
328
  */
327
- type KeyOf<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly unknown[] ? number extends TValue["length"] ? number : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never }[number] : TValue extends Record<string, unknown> ? keyof TValue & PathKey : never;
329
+ type ExactKeysOf<TValue> = IsAny<TValue> extends true ? never : TValue extends readonly unknown[] ? number extends TValue["length"] ? number : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never }[number] : TValue extends Record<PropertyKey, unknown> ? keyof TValue & PathKey : never;
328
330
  /**
329
- * Merges array and object unions into a single object.
331
+ * Returns the flat object of all indexable properties of `TValue`. For object
332
+ * unions, properties from every member are merged so that any single property
333
+ * is accessible. For primitives and other non-indexable types, the result is
334
+ * `{}`.
330
335
  *
331
- * Hint: This is necessary to make any property accessible. By default,
332
- * properties that do not exist in all union options are not accessible
333
- * and result in "any" when accessed.
336
+ * Hint: This is necessary to make properties accessible across union members.
337
+ * By default, properties that do not exist in all union options are not
338
+ * accessible and result in "any" when accessed.
334
339
  */
335
- type MergeUnion<TValue> = { [TKey in KeyOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
340
+ type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
336
341
  /**
337
342
  * Lazily evaluates only the first valid path segment based on the given value.
338
343
  */
339
- 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;
344
+ type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends ExactKeysOf<TValue>, ...infer TPathRest extends Path] ? LazyPath<Required<PropertiesOf<TValue>[TFirstKey]>, TPathRest, readonly [...TValidPath, TFirstKey]> : IsNever<ExactKeysOf<TValue>> extends false ? readonly [...TValidPath, ExactKeysOf<TValue>] : TValidPath;
340
345
  /**
341
346
  * Returns the path if valid, otherwise the first possible valid path based on
342
347
  * the given value.
343
348
  */
344
349
  type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
345
350
  /**
351
+ * Detects whether the consuming project is configured with
352
+ * `exactOptionalPropertyTypes: true`.
353
+ *
354
+ * Hint: If `false` the built-in `Required<T>` strips `| undefined` from
355
+ * optional properties, so `Required<{ key?: undefined }>['key']` collapses
356
+ * to `never` — under strict mode the same expression yields `undefined`.
357
+ */
358
+ type IsExactOptionalProps = Required<{
359
+ key?: undefined;
360
+ }>["key"] extends never ? false : true;
361
+ /**
362
+ * Like the built-in `Required<T>`, but preserves `| undefined` in two
363
+ * places where `Required<T>` strips it:
364
+ *
365
+ * 1. Optional property values under `exactOptionalPropertyTypes: false`
366
+ * — without this, input typings for `v.optional`/`v.nullish` schemas
367
+ * narrow incorrectly (issue #15).
368
+ * 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
369
+ * `(string | undefined)[]` instead of becoming `string[]`. Arrays
370
+ * fall through unchanged because they only have a numeric index
371
+ * signature and don't structurally extend `Record<PropertyKey,
372
+ * unknown>` (which requires string keys).
373
+ */
374
+ type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
375
+ /**
346
376
  * Extracts the value type at the given path.
347
377
  */
348
- 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;
378
+ 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;
349
379
  /**
350
- * Checks if a value is an array or contains one.
380
+ * Checks whether a value is an array or contains one anywhere in its shape.
381
+ *
382
+ * Hint: The inner conditionals (`TValue extends readonly unknown[]` and
383
+ * `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
384
+ * so the inner expression returns the union of each member's result (e.g.
385
+ * `true | false` when some members contain arrays and others don't).
386
+ * Downstream code uses `IsOrHasArray<T> extends true`, but
387
+ * `boolean extends true` is `false` — so we collapse the result via
388
+ * `true extends ...`, which is `true` whenever at least one union member
389
+ * contributed `true`.
351
390
  */
352
- type IsOrHasArray<TValue> = IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? true : TValue extends Record<string, unknown> ? true extends { [TKey in keyof TValue]: IsOrHasArray<TValue[TKey]> }[keyof TValue] ? true : false : false;
391
+ 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;
353
392
  /**
354
393
  * Extracts the exact keys of a tuple, array or object that contain arrays.
355
394
  */
356
- 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;
395
+ type ExactKeysOfArrayPath<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<PropertyKey, unknown> ? { [TKey in keyof TValue]: IsOrHasArray<NonNullable<TValue[TKey]>> extends true ? TKey : never }[keyof TValue] & PathKey : never;
396
+ /**
397
+ * Returns the flat object of indexable properties of `TValue` whose values
398
+ * are or contain arrays. Mirrors `PropertiesOf` but keyed by
399
+ * `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
400
+ * navigation in `LazyArrayPath`.
401
+ */
402
+ type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
357
403
  /**
358
404
  * Lazily evaluates only the first valid array path segment based on the given value.
359
405
  */
360
- 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;
406
+ 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;
361
407
  /**
362
408
  * Returns the path if valid, otherwise the first possible valid array path
363
409
  * based on the given value.
@@ -86,7 +86,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
86
86
  if (internalFieldStore.kind === "object") {
87
87
  internalFieldStore.children ??= {};
88
88
  for (const key in schema.entries) {
89
- internalFieldStore.children[key] = {};
89
+ internalFieldStore.children[key] ??= {};
90
90
  path.push(key);
91
91
  initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
92
92
  path.pop();
@@ -97,6 +97,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
97
97
  internalFieldStore.input = createSignal(objectInput);
98
98
  }
99
99
  } else {
100
+ if (internalFieldStore.kind && internalFieldStore.kind !== "value") throw new Error(`Store initialized as "${internalFieldStore.kind}" cannot be reinitialized as "value"`);
100
101
  internalFieldStore.kind = "value";
101
102
  if (internalFieldStore.kind === "value") {
102
103
  internalFieldStore.initialInput = createSignal(initialInput);
@@ -714,7 +715,7 @@ function reset(form, config) {
714
715
  untrack(() => {
715
716
  const internalFormStore = form[INTERNAL];
716
717
  const internalFieldStore = config?.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
717
- if (config?.initialInput) setInitialFieldInput(internalFieldStore, config.initialInput);
718
+ if (config && "initialInput" in config) setInitialFieldInput(internalFieldStore, config.initialInput);
718
719
  walkFieldStore(internalFieldStore, (internalFieldStore$1) => {
719
720
  internalFieldStore$1.elements = internalFieldStore$1.initialElements;
720
721
  if (!config?.keepErrors) internalFieldStore$1.errors.value = null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formisch/qwik",
3
- "description": "The modular and type-safe form library for Qwik",
4
- "version": "0.10.0",
3
+ "description": "The lightweight, schema-first, and fully type-safe form library for Qwik",
4
+ "version": "0.10.1",
5
5
  "license": "MIT",
6
6
  "author": "Fabian Hiller",
7
7
  "homepage": "https://formisch.dev",