@formisch/vue 0.7.5 → 0.7.6
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 +72 -26
- package/dist/index.js +3 -2
- package/package.json +8 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
import * as
|
|
2
|
+
import * as vue3 from "vue";
|
|
3
3
|
import { ComponentPublicInstance, MaybeRefOrGetter, ShallowRef as Signal } from "vue";
|
|
4
4
|
|
|
5
5
|
//#region ../../packages/core/dist/index.vue.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
|
/**
|
|
16
16
|
* Batch interface.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
//#endregion
|
|
20
|
-
//#region src/types/field.d.ts
|
|
20
|
+
//#region src/types/field/field.d.ts
|
|
21
21
|
/**
|
|
22
22
|
* Field element type.
|
|
23
23
|
*/
|
|
@@ -183,7 +183,7 @@ type InternalFieldStore = InternalArrayStore | InternalObjectStore | InternalVal
|
|
|
183
183
|
*/
|
|
184
184
|
declare const INTERNAL: "~internal";
|
|
185
185
|
//#endregion
|
|
186
|
-
//#region src/types/utils.d.ts
|
|
186
|
+
//#region src/types/utils/utils.d.ts
|
|
187
187
|
/**
|
|
188
188
|
* Checks if a type is `any`.
|
|
189
189
|
*/
|
|
@@ -209,7 +209,7 @@ type DeepPartial<TValue> = TValue extends Record<PropertyKey, unknown> | readonl
|
|
|
209
209
|
*/
|
|
210
210
|
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;
|
|
211
211
|
//#endregion
|
|
212
|
-
//#region src/types/form.d.ts
|
|
212
|
+
//#region src/types/form/form.d.ts
|
|
213
213
|
/**
|
|
214
214
|
* Validation mode type.
|
|
215
215
|
*/
|
|
@@ -292,7 +292,7 @@ type SubmitHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>) =>
|
|
|
292
292
|
*/
|
|
293
293
|
type SubmitEventHandler<TSchema extends Schema> = (output: v.InferOutput<TSchema>, event: SubmitEvent) => MaybePromise<unknown>;
|
|
294
294
|
//#endregion
|
|
295
|
-
//#region src/types/path.d.ts
|
|
295
|
+
//#region src/types/path/path.d.ts
|
|
296
296
|
/**
|
|
297
297
|
* Path key type.
|
|
298
298
|
*/
|
|
@@ -306,42 +306,88 @@ type Path = readonly PathKey[];
|
|
|
306
306
|
*/
|
|
307
307
|
type RequiredPath = readonly [PathKey, ...Path];
|
|
308
308
|
/**
|
|
309
|
-
* Extracts the exact keys of a tuple, array or object.
|
|
309
|
+
* Extracts the exact keys of a tuple, array or object. Tuples return their
|
|
310
|
+
* literal numeric indices, dynamic arrays return `number`, objects return
|
|
311
|
+
* their `keyof` keys, and any other input returns `never`.
|
|
310
312
|
*/
|
|
311
|
-
type
|
|
313
|
+
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;
|
|
312
314
|
/**
|
|
313
|
-
*
|
|
315
|
+
* Returns the flat object of all indexable properties of `TValue`. For object
|
|
316
|
+
* unions, properties from every member are merged so that any single property
|
|
317
|
+
* is accessible. For primitives and other non-indexable types, the result is
|
|
318
|
+
* `{}`.
|
|
314
319
|
*
|
|
315
|
-
* Hint: This is necessary to make
|
|
316
|
-
* properties that do not exist in all union options are not
|
|
317
|
-
* and result in "any" when accessed.
|
|
320
|
+
* Hint: This is necessary to make properties accessible across union members.
|
|
321
|
+
* By default, properties that do not exist in all union options are not
|
|
322
|
+
* accessible and result in "any" when accessed.
|
|
318
323
|
*/
|
|
319
|
-
type
|
|
324
|
+
type PropertiesOf<TValue> = { [TKey in ExactKeysOf<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
|
|
320
325
|
/**
|
|
321
326
|
* Lazily evaluates only the first valid path segment based on the given value.
|
|
322
327
|
*/
|
|
323
|
-
type LazyPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValidPath : TPathToCheck extends readonly [infer TFirstKey extends
|
|
328
|
+
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;
|
|
324
329
|
/**
|
|
325
330
|
* Returns the path if valid, otherwise the first possible valid path based on
|
|
326
331
|
* the given value.
|
|
327
332
|
*/
|
|
328
333
|
type ValidPath<TValue, TPath extends RequiredPath> = TPath extends LazyPath<Required<TValue>, TPath> ? TPath : LazyPath<Required<TValue>, TPath>;
|
|
329
334
|
/**
|
|
335
|
+
* Detects whether the consuming project is configured with
|
|
336
|
+
* `exactOptionalPropertyTypes: true`.
|
|
337
|
+
*
|
|
338
|
+
* Hint: If `false` the built-in `Required<T>` strips `| undefined` from
|
|
339
|
+
* optional properties, so `Required<{ key?: undefined }>['key']` collapses
|
|
340
|
+
* to `never` — under strict mode the same expression yields `undefined`.
|
|
341
|
+
*/
|
|
342
|
+
type IsExactOptionalProps = Required<{
|
|
343
|
+
key?: undefined;
|
|
344
|
+
}>["key"] extends never ? false : true;
|
|
345
|
+
/**
|
|
346
|
+
* Like the built-in `Required<T>`, but preserves `| undefined` in two
|
|
347
|
+
* places where `Required<T>` strips it:
|
|
348
|
+
*
|
|
349
|
+
* 1. Optional property values under `exactOptionalPropertyTypes: false`
|
|
350
|
+
* — without this, input typings for `v.optional`/`v.nullish` schemas
|
|
351
|
+
* narrow incorrectly (issue #15).
|
|
352
|
+
* 2. Array/tuple element types — e.g. `(string | undefined)[]` stays
|
|
353
|
+
* `(string | undefined)[]` instead of becoming `string[]`. Arrays
|
|
354
|
+
* fall through unchanged because they only have a numeric index
|
|
355
|
+
* signature and don't structurally extend `Record<PropertyKey,
|
|
356
|
+
* unknown>` (which requires string keys).
|
|
357
|
+
*/
|
|
358
|
+
type ExactRequired<TValue> = TValue extends Record<PropertyKey, unknown> ? IsExactOptionalProps extends true ? Required<TValue> : { [TKey in keyof Required<TValue>]: TValue[TKey] } : TValue;
|
|
359
|
+
/**
|
|
330
360
|
* Extracts the value type at the given path.
|
|
331
361
|
*/
|
|
332
|
-
type PathValue<TValue, TPath extends Path> = TPath extends readonly [infer TKey, ...infer TRest extends Path] ? TKey extends
|
|
362
|
+
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;
|
|
333
363
|
/**
|
|
334
|
-
* Checks
|
|
364
|
+
* Checks whether a value is an array or contains one anywhere in its shape.
|
|
365
|
+
*
|
|
366
|
+
* Hint: The inner conditionals (`TValue extends readonly unknown[]` and
|
|
367
|
+
* `TValue extends Record<PropertyKey, unknown>`) distribute over union members,
|
|
368
|
+
* so the inner expression returns the union of each member's result (e.g.
|
|
369
|
+
* `true | false` when some members contain arrays and others don't).
|
|
370
|
+
* Downstream code uses `IsOrHasArray<T> extends true`, but
|
|
371
|
+
* `boolean extends true` is `false` — so we collapse the result via
|
|
372
|
+
* `true extends ...`, which is `true` whenever at least one union member
|
|
373
|
+
* contributed `true`.
|
|
335
374
|
*/
|
|
336
|
-
type IsOrHasArray<TValue> = IsAny<TValue> extends true ? false : TValue extends readonly unknown[] ? true : TValue extends Record<
|
|
375
|
+
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;
|
|
337
376
|
/**
|
|
338
377
|
* Extracts the exact keys of a tuple, array or object that contain arrays.
|
|
339
378
|
*/
|
|
340
|
-
type
|
|
379
|
+
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;
|
|
380
|
+
/**
|
|
381
|
+
* Returns the flat object of indexable properties of `TValue` whose values
|
|
382
|
+
* are or contain arrays. Mirrors `PropertiesOf` but keyed by
|
|
383
|
+
* `ExactKeysOfArrayPath` so the lookup is provably valid for array-path
|
|
384
|
+
* navigation in `LazyArrayPath`.
|
|
385
|
+
*/
|
|
386
|
+
type PropertiesOfArrayPath<TValue> = { [TKey in ExactKeysOfArrayPath<TValue>]: TValue extends Record<TKey, infer TItem> ? TItem : never };
|
|
341
387
|
/**
|
|
342
388
|
* Lazily evaluates only the first valid array path segment based on the given value.
|
|
343
389
|
*/
|
|
344
|
-
type LazyArrayPath<TValue, TPathToCheck extends Path, TValidPath extends Path = readonly []> = TPathToCheck extends readonly [] ? TValue extends readonly unknown[] ? TValidPath : readonly [...TValidPath,
|
|
390
|
+
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;
|
|
345
391
|
/**
|
|
346
392
|
* Returns the path if valid, otherwise the first possible valid array path
|
|
347
393
|
* based on the given value.
|
|
@@ -959,14 +1005,14 @@ interface FieldProps<TSchema extends Schema = Schema, TFieldPath extends Require
|
|
|
959
1005
|
readonly path: ValidPath<v.InferInput<TSchema>, TFieldPath>;
|
|
960
1006
|
}
|
|
961
1007
|
declare const __VLS_export$2: <TSchema extends Schema, TFieldPath extends RequiredPath>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal$2<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
962
|
-
props: __VLS_PrettifyLocal$2<FieldProps<TSchema, TFieldPath>> &
|
|
1008
|
+
props: __VLS_PrettifyLocal$2<FieldProps<TSchema, TFieldPath>> & vue3.PublicProps;
|
|
963
1009
|
expose: (exposed: {}) => void;
|
|
964
1010
|
attrs: any;
|
|
965
1011
|
slots: {
|
|
966
1012
|
default(props: FieldStore<TSchema, TFieldPath>): any;
|
|
967
1013
|
};
|
|
968
1014
|
emit: {};
|
|
969
|
-
}>) =>
|
|
1015
|
+
}>) => vue3.VNode & {
|
|
970
1016
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
971
1017
|
};
|
|
972
1018
|
declare const _default: typeof __VLS_export$2;
|
|
@@ -987,14 +1033,14 @@ interface FieldArrayProps<TSchema extends Schema = Schema, TFieldArrayPath exten
|
|
|
987
1033
|
readonly path: ValidArrayPath<v.InferInput<TSchema>, TFieldArrayPath>;
|
|
988
1034
|
}
|
|
989
1035
|
declare const __VLS_export$1: <TSchema extends Schema, TFieldArrayPath extends RequiredPath>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal$1<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
990
|
-
props: __VLS_PrettifyLocal$1<FieldArrayProps<TSchema, TFieldArrayPath>> &
|
|
1036
|
+
props: __VLS_PrettifyLocal$1<FieldArrayProps<TSchema, TFieldArrayPath>> & vue3.PublicProps;
|
|
991
1037
|
expose: (exposed: {}) => void;
|
|
992
1038
|
attrs: any;
|
|
993
1039
|
slots: {
|
|
994
1040
|
default(props: FieldArrayStore<TSchema, TFieldArrayPath>): any;
|
|
995
1041
|
};
|
|
996
1042
|
emit: {};
|
|
997
|
-
}>) =>
|
|
1043
|
+
}>) => vue3.VNode & {
|
|
998
1044
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
999
1045
|
};
|
|
1000
1046
|
declare const _default$1: typeof __VLS_export$1;
|
|
@@ -1015,14 +1061,14 @@ interface FormProps<TSchema extends Schema = Schema> {
|
|
|
1015
1061
|
onSubmit: SubmitEventHandler<TSchema>;
|
|
1016
1062
|
}
|
|
1017
1063
|
declare const __VLS_export: <TSchema extends Schema = Schema>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
1018
|
-
props: __VLS_PrettifyLocal<FormProps<TSchema>> &
|
|
1064
|
+
props: __VLS_PrettifyLocal<FormProps<TSchema>> & vue3.PublicProps;
|
|
1019
1065
|
expose: (exposed: {}) => void;
|
|
1020
1066
|
attrs: any;
|
|
1021
1067
|
slots: {
|
|
1022
1068
|
default?: (props: {}) => any;
|
|
1023
1069
|
};
|
|
1024
1070
|
emit: {};
|
|
1025
|
-
}>) =>
|
|
1071
|
+
}>) => vue3.VNode & {
|
|
1026
1072
|
__ctx?: Awaited<typeof __VLS_setup>;
|
|
1027
1073
|
};
|
|
1028
1074
|
declare const _default$2: typeof __VLS_export;
|
package/dist/index.js
CHANGED
|
@@ -96,7 +96,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
|
|
|
96
96
|
if (internalFieldStore.kind === "object") {
|
|
97
97
|
internalFieldStore.children ??= {};
|
|
98
98
|
for (const key in schema.entries) {
|
|
99
|
-
internalFieldStore.children[key]
|
|
99
|
+
internalFieldStore.children[key] ??= {};
|
|
100
100
|
path.push(key);
|
|
101
101
|
initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
|
|
102
102
|
path.pop();
|
|
@@ -107,6 +107,7 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
|
|
|
107
107
|
internalFieldStore.input = createSignal(objectInput);
|
|
108
108
|
}
|
|
109
109
|
} else {
|
|
110
|
+
if (internalFieldStore.kind && internalFieldStore.kind !== "value") throw new Error(`Store initialized as "${internalFieldStore.kind}" cannot be reinitialized as "value"`);
|
|
110
111
|
internalFieldStore.kind = "value";
|
|
111
112
|
if (internalFieldStore.kind === "value") {
|
|
112
113
|
internalFieldStore.initialInput = createSignal(initialInput);
|
|
@@ -697,7 +698,7 @@ function reset(form, config) {
|
|
|
697
698
|
untrack(() => {
|
|
698
699
|
const internalFormStore = form[INTERNAL];
|
|
699
700
|
const internalFieldStore = config?.path ? getFieldStore(internalFormStore, config.path) : internalFormStore;
|
|
700
|
-
if (config
|
|
701
|
+
if (config && "initialInput" in config) setInitialFieldInput(internalFieldStore, config.initialInput);
|
|
701
702
|
walkFieldStore(internalFieldStore, (internalFieldStore$1) => {
|
|
702
703
|
internalFieldStore$1.elements = internalFieldStore$1.initialElements;
|
|
703
704
|
if (!config?.keepErrors) internalFieldStore$1.errors.value = null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formisch/vue",
|
|
3
|
-
"description": "The
|
|
4
|
-
"version": "0.7.
|
|
3
|
+
"description": "The lightweight, schema-first, and fully type-safe form library for Vue",
|
|
4
|
+
"version": "0.7.6",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fabian Hiller",
|
|
7
7
|
"homepage": "https://formisch.dev",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsdown",
|
|
37
|
+
"test": "vitest run --typecheck",
|
|
37
38
|
"lint": "eslint \"src/**/*.ts*\" && tsc --noEmit",
|
|
38
39
|
"lint.fix": "eslint \"src/**/*.ts*\" --fix",
|
|
39
40
|
"format": "prettier --write ./src",
|
|
@@ -44,14 +45,19 @@
|
|
|
44
45
|
"@formisch/core": "workspace:*",
|
|
45
46
|
"@formisch/eslint-config": "workspace:*",
|
|
46
47
|
"@formisch/methods": "workspace:*",
|
|
48
|
+
"@testing-library/jest-dom": "^6.6.0",
|
|
47
49
|
"@types/node": "^24.1.0",
|
|
50
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
48
51
|
"@vue/eslint-config-typescript": "^14.6.0",
|
|
52
|
+
"@vue/test-utils": "^2.4.6",
|
|
49
53
|
"eslint": "^9.32.0",
|
|
50
54
|
"eslint-plugin-vue": "~10.3.0",
|
|
55
|
+
"jsdom": "^26.1.0",
|
|
51
56
|
"tsdown": "^0.16.8",
|
|
52
57
|
"typescript": "~5.8.3",
|
|
53
58
|
"unplugin-vue": "^7.0.0",
|
|
54
59
|
"valibot": "^1.2.0",
|
|
60
|
+
"vitest": "^3.2.4",
|
|
55
61
|
"vue": "^3.5.18",
|
|
56
62
|
"vue-tsc": "^3.0.4"
|
|
57
63
|
},
|