@tanstack/vue-form 2.0.0-alpha.2 → 2.0.0-alpha.3
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.
|
@@ -1,48 +1,26 @@
|
|
|
1
1
|
import { VueComponentInstance } from "../vueTypes.lib.js";
|
|
2
2
|
import { VueTanStackFormComponents } from "../VueForm/Components.public.js";
|
|
3
3
|
import { FieldGroupApi } from "./FieldGroupApi.public.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FieldGroupFieldBindings, FieldGroupFieldBindingsProps, FieldGroupFieldData, FieldGroupFields, FieldGroupFieldsPropName, FieldGroupHelper, FormApi } from "@tanstack/form-core";
|
|
5
5
|
import { Component, PublicProps } from "vue";
|
|
6
6
|
//#region src/FieldGroup/withFields.public.d.ts
|
|
7
|
-
declare const fieldGroupFieldSlotValueSymbol: unique symbol;
|
|
8
7
|
declare const fieldGroupFieldsSymbol: unique symbol;
|
|
9
|
-
type FieldGroupFieldSlotMode = 'strict' | 'loose';
|
|
10
|
-
interface FieldGroupFieldSlot<out TValue, out TMode extends FieldGroupFieldSlotMode = FieldGroupFieldSlotMode> {
|
|
11
|
-
readonly mode: TMode;
|
|
12
|
-
readonly [fieldGroupFieldSlotValueSymbol]: TValue;
|
|
13
|
-
}
|
|
14
|
-
type AnyFieldGroupFieldSlot = FieldGroupFieldSlot<any>;
|
|
15
|
-
type StrictFieldGroupFieldSlot<TValue> = FieldGroupFieldSlot<TValue, 'strict'>;
|
|
16
|
-
type LooseFieldGroupFieldSlot<TValue> = FieldGroupFieldSlot<TValue, 'loose'>;
|
|
17
|
-
type FieldGroupFieldSlotValue<TSlot> = TSlot extends FieldGroupFieldSlot<infer TValue> ? TValue : never;
|
|
18
|
-
type FieldGroupFieldSlotModeOf<TSlot> = TSlot extends FieldGroupFieldSlot<any, infer TMode> ? TMode : never;
|
|
19
|
-
type IsSame<TTypeA, TTypeB> = [TTypeA] extends [TTypeB] ? [TTypeB] extends [TTypeA] ? true : false : false;
|
|
20
|
-
type FieldGroupFieldSlotAllows<TSlot, TValue> = TSlot extends FieldGroupFieldSlot<infer TAcceptedValue, infer TMode> ? TMode extends 'strict' ? IsSame<TValue, TAcceptedValue> : [TValue] extends [TAcceptedValue] ? true : false : false;
|
|
21
|
-
type FieldGroupFieldNameForSlot<TFieldData, TSlot extends AnyFieldGroupFieldSlot> = { [TFieldName in DeepKeys<TFieldData>]: FieldGroupFieldSlotAllows<TSlot, DeepValue<TFieldData, TFieldName>> extends true ? TFieldName : never; }[DeepKeys<TFieldData>];
|
|
22
|
-
type FieldGroupFields = Record<string, AnyFieldGroupFieldSlot>;
|
|
23
|
-
type FieldGroupFieldNames<TFieldData, TFields extends FieldGroupFields> = { [TFieldName in keyof TFields]: FieldGroupFieldNameForSlot<TFieldData, TFields[TFieldName]>; };
|
|
24
|
-
type FieldGroupFieldData<TFields extends FieldGroupFields> = { [TFieldName in keyof TFields]: TFields[TFieldName] extends FieldGroupFieldSlot<infer TValue, any> ? TValue : never; };
|
|
25
8
|
type FieldGroupFieldsOf<TFieldGroup> = TFieldGroup extends {
|
|
26
|
-
readonly [fieldGroupFieldsSymbol]: infer TFields;
|
|
9
|
+
readonly [fieldGroupFieldsSymbol]: infer TFields extends FieldGroupFields;
|
|
27
10
|
} ? TFields : never;
|
|
28
11
|
type VueFieldGroup<TFields extends FieldGroupFields, TFieldComponents extends Record<string, Component> = Record<never, never>> = FieldGroupApi<FieldGroupFieldData<TFields>, TFieldComponents> & {
|
|
29
12
|
readonly [fieldGroupFieldsSymbol]: TFields;
|
|
30
13
|
};
|
|
31
14
|
type FieldGroupFieldComponentsOf<TFieldGroup> = TFieldGroup extends VueFieldGroup<any, infer TFieldComponents> ? TFieldComponents : never;
|
|
32
15
|
type FieldGroupForm<TFieldComponents extends Record<string, Component> = Record<never, never>, TFormData = any> = FormApi<TFormData, any> & VueTanStackFormComponents<TFormData, any, TFieldComponents>;
|
|
33
|
-
type FieldGroupFieldBindingForSlot<TFormData, TSlot extends AnyFieldGroupFieldSlot> = TSlot extends FieldGroupFieldSlot<infer TValue, infer TMode> ? TMode extends 'strict' ? FieldGroupFieldNameForSlot<TFormData, TSlot> : DeepKeysWhereValueIncludes<TFormData, TValue> : never;
|
|
34
|
-
type FieldGroupFieldBindings<TFields extends FieldGroupFields, TFormData = any> = { [TFieldName in keyof TFields]: FieldGroupFieldBindingForSlot<TFormData, TFields[TFieldName]>; };
|
|
35
16
|
type FieldGroupFieldBindingsOf<TFieldGroup, TFormData> = FieldGroupFieldsOf<TFieldGroup> extends FieldGroupFields ? FieldGroupFieldBindings<FieldGroupFieldsOf<TFieldGroup>, TFormData> : never;
|
|
36
|
-
type
|
|
17
|
+
type FieldsPropsDefinition<TFieldGroup extends VueFieldGroup<any, any>, TFormData, TFieldsPropName extends PropertyKey> = { [TPropName in TFieldsPropName]: FieldGroupFieldBindingsOf<TFieldGroup, TFormData>; };
|
|
18
|
+
type FieldGroupFieldBindingsInstanceProp<TFieldGroup extends VueFieldGroup<any, any>, TFormData, TFieldsPropName extends PropertyKey> = FieldsPropsDefinition<TFieldGroup, TFormData, TFieldsPropName> | FieldGroupFieldBindingsProps<FieldGroupFieldsOf<TFieldGroup>, TFormData, TFieldsPropName>;
|
|
37
19
|
type FieldGroupWithFieldsFn<TFieldGroup extends VueFieldGroup<any, any>> = <TProps extends object, const TFieldsPropName extends PropertyKey>(component: Component & (new (props: TProps & PublicProps) => any), fieldsPropName: TFieldsPropName & FieldGroupFieldsPropName<TProps, TFieldGroup>) => new <TFormData>(props: Omit<TProps, TFieldsPropName | 'form'> & {
|
|
38
20
|
form: FieldGroupForm<FieldGroupFieldComponentsOf<TFieldGroup>, TFormData>;
|
|
39
|
-
} &
|
|
21
|
+
} & FieldGroupFieldBindingsProps<FieldGroupFieldsOf<TFieldGroup>, TFormData, TFieldsPropName> & PublicProps) => VueComponentInstance<Omit<TProps, TFieldsPropName | 'form'> & {
|
|
40
22
|
form: FieldGroupForm<FieldGroupFieldComponentsOf<TFieldGroup>, TFormData>;
|
|
41
|
-
} &
|
|
42
|
-
interface FieldGroupHelper {
|
|
43
|
-
strict: <TValue>() => StrictFieldGroupFieldSlot<TValue>;
|
|
44
|
-
loose: <TValue>() => LooseFieldGroupFieldSlot<TValue>;
|
|
45
|
-
}
|
|
23
|
+
} & FieldGroupFieldBindingsInstanceProp<TFieldGroup, TFormData, TFieldsPropName> & Record<string, any>, {}>;
|
|
46
24
|
interface FieldGroupDefinition<TFields extends FieldGroupFields, TFieldComponents extends Record<string, Component>> {
|
|
47
25
|
/** The virtual field-group API injected into the bound component. */
|
|
48
26
|
fields: VueFieldGroup<TFields, TFieldComponents>;
|
|
@@ -54,4 +32,4 @@ type DefineFieldGroupFn<TFieldComponents extends Record<string, Component>> = <c
|
|
|
54
32
|
/** Defines a reusable group of virtual fields. */
|
|
55
33
|
declare const defineFieldGroup: DefineFieldGroupFn<Record<never, never>>;
|
|
56
34
|
//#endregion
|
|
57
|
-
export {
|
|
35
|
+
export { DefineFieldGroupFn, FieldGroupDefinition, FieldGroupFieldBindingsOf, FieldGroupFieldComponentsOf, FieldGroupFieldsOf, FieldGroupForm, FieldGroupWithFieldsFn, VueFieldGroup, defineFieldGroup };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Subscribe } from "../Subscribe.public.js";
|
|
2
2
|
import { createArrayFieldSubscription, createValueFieldSubscription } from "./fieldSubscriptions.lib.js";
|
|
3
|
+
import { createFieldView } from "./fieldView.lib.js";
|
|
3
4
|
import { useField } from "./useField.lib.js";
|
|
4
5
|
import { shallow, useSelector } from "@tanstack/vue-store";
|
|
5
6
|
import { InternalFormGroupApi } from "@tanstack/form-core/internals";
|
|
@@ -20,12 +21,14 @@ function createFieldComponent(form, fieldComponents, array, fieldContext) {
|
|
|
20
21
|
...context.attrs,
|
|
21
22
|
form
|
|
22
23
|
});
|
|
23
|
-
const fieldApi = useField(options
|
|
24
|
-
const selection = array ? createArrayFieldSubscription(fieldApi) : createValueFieldSubscription(fieldApi);
|
|
25
|
-
|
|
24
|
+
const fieldApi = useField(options);
|
|
25
|
+
const { selection, meta } = array ? createArrayFieldSubscription(fieldApi) : createValueFieldSubscription(fieldApi);
|
|
26
|
+
const field = createFieldView(fieldApi, selection, meta);
|
|
27
|
+
if (fieldComponents !== null) Object.assign(field, fieldComponents);
|
|
28
|
+
if (fieldContext) provide(fieldContext, field);
|
|
26
29
|
return () => {
|
|
27
30
|
selection.value;
|
|
28
|
-
return context.slots.default?.({ field
|
|
31
|
+
return context.slots.default?.({ field });
|
|
29
32
|
};
|
|
30
33
|
}, {
|
|
31
34
|
name: array ? "TanStackForm.ArrayField" : "TanStackForm.Field",
|
|
@@ -4,9 +4,12 @@ import { shallowRef, toRaw, watch } from "vue";
|
|
|
4
4
|
//#region src/VueForm/fieldSubscriptions.lib.ts
|
|
5
5
|
function createFieldSelection(fieldApi, selector) {
|
|
6
6
|
const selected = shallowRef(selector(fieldApi.value));
|
|
7
|
+
const meta = shallowRef(fieldApi.value.meta);
|
|
7
8
|
watch(fieldApi, (field, _previous, onCleanup) => {
|
|
9
|
+
meta.value = field.meta;
|
|
8
10
|
selected.value = selector(field);
|
|
9
11
|
const subscription = field.atom.subscribe(() => {
|
|
12
|
+
meta.value = field.meta;
|
|
10
13
|
const next = selector(field);
|
|
11
14
|
if (!shallow(toRaw(selected.value), next)) selected.value = next;
|
|
12
15
|
});
|
|
@@ -15,7 +18,10 @@ function createFieldSelection(fieldApi, selector) {
|
|
|
15
18
|
immediate: true,
|
|
16
19
|
flush: "sync"
|
|
17
20
|
});
|
|
18
|
-
return
|
|
21
|
+
return {
|
|
22
|
+
selection: selected,
|
|
23
|
+
meta
|
|
24
|
+
};
|
|
19
25
|
}
|
|
20
26
|
function createValueFieldSubscription(fieldApi) {
|
|
21
27
|
return createFieldSelection(fieldApi, (field) => ({
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/VueForm/fieldView.lib.ts
|
|
2
|
+
/**
|
|
3
|
+
* The public field shared by slots and injected components. State getters
|
|
4
|
+
* track the existing subscription in the component that reads them, while
|
|
5
|
+
* handlers follow the current core field after a reset or name change.
|
|
6
|
+
*/
|
|
7
|
+
function createFieldView(fieldApi, selection, meta) {
|
|
8
|
+
return {
|
|
9
|
+
get form() {
|
|
10
|
+
return fieldApi.value.form;
|
|
11
|
+
},
|
|
12
|
+
get name() {
|
|
13
|
+
return fieldApi.value.name;
|
|
14
|
+
},
|
|
15
|
+
get atom() {
|
|
16
|
+
return fieldApi.value.atom;
|
|
17
|
+
},
|
|
18
|
+
get value() {
|
|
19
|
+
selection.value;
|
|
20
|
+
return fieldApi.value.value;
|
|
21
|
+
},
|
|
22
|
+
get meta() {
|
|
23
|
+
return meta.value;
|
|
24
|
+
},
|
|
25
|
+
get errors() {
|
|
26
|
+
return meta.value.errors;
|
|
27
|
+
},
|
|
28
|
+
handleChange: (value, options) => fieldApi.value.handleChange(value, options),
|
|
29
|
+
handleBlur: () => fieldApi.value.handleBlur(),
|
|
30
|
+
reset: () => fieldApi.value.reset(),
|
|
31
|
+
swapValues: (indexA, indexB) => fieldApi.value.swapValues(indexA, indexB),
|
|
32
|
+
moveValue: (fromIndex, toIndex, options) => fieldApi.value.moveValue(fromIndex, toIndex, options),
|
|
33
|
+
pushValue: (value, options) => fieldApi.value.pushValue(value, options),
|
|
34
|
+
insertValue: (index, value, options) => fieldApi.value.insertValue(index, value, options),
|
|
35
|
+
clearValues: (options) => fieldApi.value.clearValues(options),
|
|
36
|
+
replaceValue: (index, value, options) => fieldApi.value.replaceValue(index, value, options),
|
|
37
|
+
removeValue: (index, options) => fieldApi.value.removeValue(index, options),
|
|
38
|
+
filterValues: (predicate, options) => fieldApi.value.filterValues(predicate, options)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createFieldView };
|
|
@@ -2,17 +2,15 @@ import { useSelector } from "@tanstack/vue-store";
|
|
|
2
2
|
import { onMounted, onUnmounted, shallowRef, watch, watchEffect } from "vue";
|
|
3
3
|
|
|
4
4
|
//#region src/VueForm/useField.lib.ts
|
|
5
|
-
function useField(options
|
|
5
|
+
function useField(options) {
|
|
6
6
|
const initialOptions = options();
|
|
7
7
|
const resetVersion = useSelector(initialOptions.form._atoms.resetVersion);
|
|
8
8
|
const createField = () => {
|
|
9
9
|
const current = options();
|
|
10
|
-
|
|
10
|
+
return current.form._getOrCreateFieldApi({
|
|
11
11
|
...current,
|
|
12
12
|
name: current.name
|
|
13
13
|
}, "field");
|
|
14
|
-
if (fieldComponents !== null) Object.assign(field, fieldComponents);
|
|
15
|
-
return field;
|
|
16
14
|
};
|
|
17
15
|
const fieldApi = shallowRef(createField());
|
|
18
16
|
watch([
|
package/dist/index.d.ts
CHANGED
|
@@ -5,11 +5,11 @@ import { UseFormHook, useForm } from "./VueForm/useForm.public.js";
|
|
|
5
5
|
import { VueFormType } from "./VueForm/formType.public.js";
|
|
6
6
|
import { Subscribe, SubscribeComponent, SubscribeProps, SubscribeSource } from "./Subscribe.public.js";
|
|
7
7
|
import { AnyFieldGroupApi, FieldGroupApi, FieldGroupArrayFieldComponent, FieldGroupFieldComponent, FieldGroupFormState, FieldGroupSubscribeComponent, FieldGroupSubscribeProps } from "./FieldGroup/FieldGroupApi.public.js";
|
|
8
|
-
import {
|
|
8
|
+
import { DefineFieldGroupFn, FieldGroupDefinition, FieldGroupFieldBindingsOf, FieldGroupFieldComponentsOf, FieldGroupFieldsOf, FieldGroupForm, FieldGroupWithFieldsFn, VueFieldGroup, defineFieldGroup } from "./FieldGroup/withFields.public.js";
|
|
9
9
|
import { AppFormComponent, VueAppFormApi } from "./AppForm/VueAppFormApi.public.js";
|
|
10
10
|
import { AppFormHookResult, CreateFormHookOptions, UseAppFormHook } from "./AppForm/createFormHookTypes.public.js";
|
|
11
11
|
import { createFormHook } from "./AppForm/createFormHook.public.js";
|
|
12
12
|
import { FormHookHelpers, getFormHookHelpers } from "./AppForm/getFormHookHelpers.public.js";
|
|
13
13
|
export * from "@tanstack/form-core";
|
|
14
14
|
export * from "@tanstack/vue-store";
|
|
15
|
-
export { AnyFieldGroupApi,
|
|
15
|
+
export { AnyFieldGroupApi, AnyVueFormApi, AnyVueFormComponentMap, AppFormComponent, AppFormHookResult, CreateFormHookOptions, DefaultVueFormComponentMap, DefineFieldGroupFn, FieldGroupApi, FieldGroupArrayFieldComponent, FieldGroupDefinition, FieldGroupFieldBindingsOf, FieldGroupFieldComponent, FieldGroupFieldComponentsOf, FieldGroupFieldsOf, FieldGroupForm, FieldGroupFormState, FieldGroupSubscribeComponent, FieldGroupSubscribeProps, FieldGroupWithFieldsFn, FormHookHelpers, Subscribe, SubscribeComponent, SubscribeProps, SubscribeSource, UseAppFormHook, UseFormHook, VueAppFormApi, VueFieldApi, VueFieldGroup, VueFormApi, VueFormArrayFieldComponent, VueFormComponentMap, VueFormFieldComponent, VueFormFieldProps, VueFormGroupApi, VueFormGroupArrayFieldComponent, VueFormGroupComponent, VueFormGroupFieldComponent, VueFormGroupProps, VueFormGroupSubscribeComponent, VueFormGroupSubscribeProps, VueFormSubscribeComponent, VueFormSubscribeProps, VueFormType, VueTanStackFormComponents, createFormHook, defineFieldGroup, getFormHookHelpers, useForm };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/vue-form",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.3",
|
|
4
4
|
"description": "Powerful, type-safe forms for Vue.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@tanstack/
|
|
29
|
-
"@tanstack/
|
|
28
|
+
"@tanstack/form-core": "2.0.0-alpha.3",
|
|
29
|
+
"@tanstack/vue-store": "^0.11.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@vitejs/plugin-vue": "^6.0.8",
|
|
32
|
+
"@vitejs/plugin-vue": "^6.0.9",
|
|
34
33
|
"unplugin-vue": "^7.2.0",
|
|
35
|
-
"vue": "^3.
|
|
36
|
-
"vue
|
|
34
|
+
"vitest-browser-vue": "^3.1.0",
|
|
35
|
+
"vue": "^3.6.0-rc.9",
|
|
36
|
+
"vue-tsc": "^3.3.11"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"vue": "^3.6.0-rc.2"
|