@tanstack/form-core 1.20.0 → 1.21.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/dist/cjs/EventClient.cjs +13 -0
- package/dist/cjs/EventClient.cjs.map +1 -0
- package/dist/cjs/EventClient.d.cts +52 -0
- package/dist/cjs/FormApi.cjs +68 -3
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +11 -2
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/esm/EventClient.d.ts +52 -0
- package/dist/esm/EventClient.js +13 -0
- package/dist/esm/EventClient.js.map +1 -0
- package/dist/esm/FormApi.d.ts +11 -2
- package/dist/esm/FormApi.js +68 -3
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -2
- package/src/EventClient.ts +73 -0
- package/src/FormApi.ts +123 -5
- package/src/index.ts +1 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const devtoolsEventClient = require("@tanstack/devtools-event-client");
|
|
4
|
+
class FormEventClient extends devtoolsEventClient.EventClient {
|
|
5
|
+
constructor() {
|
|
6
|
+
super({
|
|
7
|
+
pluginId: "form-devtools"
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const formEventClient = new FormEventClient();
|
|
12
|
+
exports.formEventClient = formEventClient;
|
|
13
|
+
//# sourceMappingURL=EventClient.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventClient.cjs","sources":["../../src/EventClient.ts"],"sourcesContent":["import { EventClient } from '@tanstack/devtools-event-client'\n\nimport type { AnyFormOptions, AnyFormState } from './FormApi'\n\ntype ExtractEventNames<T> = T extends `${string}:${infer EventName}`\n ? EventName\n : never\n\nexport type BroadcastFormState = {\n id: string\n state: AnyFormState\n options: AnyFormOptions\n}\n\nexport type BroadcastFormSubmissionState =\n | {\n id: string\n submissionAttempt: number\n successful: false\n stage: 'validateAllFields' | 'validate'\n errors: any[]\n }\n | {\n id: string\n submissionAttempt: number\n successful: false\n stage: 'inflight'\n onError: unknown\n }\n | {\n id: string\n submissionAttempt: number\n successful: true\n }\n\nexport type BroadcastFormUnmounted = {\n id: string\n}\n\nexport type RequestFormState = {\n id: string\n}\n\nexport type RequestFormReset = {\n id: string\n}\n\nexport type RequestFormForceReset = {\n id: string\n}\n\ntype EventMap = {\n 'form-devtools:form-state-change': BroadcastFormState\n 'form-devtools:form-submission-state-change': BroadcastFormSubmissionState\n 'form-devtools:form-unmounted': BroadcastFormUnmounted\n 'form-devtools:request-form-state': RequestFormState\n 'form-devtools:request-form-reset': RequestFormReset\n 'form-devtools:request-form-force-submit': RequestFormForceReset\n}\n\nexport type EventClientEventMap = keyof EventMap\n\nexport type EventClientEventNames = ExtractEventNames<EventClientEventMap>\n\nclass FormEventClient extends EventClient<EventMap> {\n constructor() {\n super({\n pluginId: 'form-devtools',\n })\n }\n}\n\nexport const formEventClient = new FormEventClient()\n"],"names":["EventClient"],"mappings":";;;AAgEA,MAAM,wBAAwBA,oBAAAA,YAAsB;AAAA,EAClD,cAAc;AACZ,UAAM;AAAA,MACJ,UAAU;AAAA,IAAA,CACX;AAAA,EACH;AACF;AAEO,MAAM,kBAAkB,IAAI,gBAAA;;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EventClient } from '@tanstack/devtools-event-client';
|
|
2
|
+
import { AnyFormOptions, AnyFormState } from './FormApi.cjs';
|
|
3
|
+
type ExtractEventNames<T> = T extends `${string}:${infer EventName}` ? EventName : never;
|
|
4
|
+
export type BroadcastFormState = {
|
|
5
|
+
id: string;
|
|
6
|
+
state: AnyFormState;
|
|
7
|
+
options: AnyFormOptions;
|
|
8
|
+
};
|
|
9
|
+
export type BroadcastFormSubmissionState = {
|
|
10
|
+
id: string;
|
|
11
|
+
submissionAttempt: number;
|
|
12
|
+
successful: false;
|
|
13
|
+
stage: 'validateAllFields' | 'validate';
|
|
14
|
+
errors: any[];
|
|
15
|
+
} | {
|
|
16
|
+
id: string;
|
|
17
|
+
submissionAttempt: number;
|
|
18
|
+
successful: false;
|
|
19
|
+
stage: 'inflight';
|
|
20
|
+
onError: unknown;
|
|
21
|
+
} | {
|
|
22
|
+
id: string;
|
|
23
|
+
submissionAttempt: number;
|
|
24
|
+
successful: true;
|
|
25
|
+
};
|
|
26
|
+
export type BroadcastFormUnmounted = {
|
|
27
|
+
id: string;
|
|
28
|
+
};
|
|
29
|
+
export type RequestFormState = {
|
|
30
|
+
id: string;
|
|
31
|
+
};
|
|
32
|
+
export type RequestFormReset = {
|
|
33
|
+
id: string;
|
|
34
|
+
};
|
|
35
|
+
export type RequestFormForceReset = {
|
|
36
|
+
id: string;
|
|
37
|
+
};
|
|
38
|
+
type EventMap = {
|
|
39
|
+
'form-devtools:form-state-change': BroadcastFormState;
|
|
40
|
+
'form-devtools:form-submission-state-change': BroadcastFormSubmissionState;
|
|
41
|
+
'form-devtools:form-unmounted': BroadcastFormUnmounted;
|
|
42
|
+
'form-devtools:request-form-state': RequestFormState;
|
|
43
|
+
'form-devtools:request-form-reset': RequestFormReset;
|
|
44
|
+
'form-devtools:request-form-force-submit': RequestFormForceReset;
|
|
45
|
+
};
|
|
46
|
+
export type EventClientEventMap = keyof EventMap;
|
|
47
|
+
export type EventClientEventNames = ExtractEventNames<EventClientEventMap>;
|
|
48
|
+
declare class FormEventClient extends EventClient<EventMap> {
|
|
49
|
+
constructor();
|
|
50
|
+
}
|
|
51
|
+
export declare const formEventClient: FormEventClient;
|
|
52
|
+
export {};
|
package/dist/cjs/FormApi.cjs
CHANGED
|
@@ -5,6 +5,7 @@ const utils = require("./utils.cjs");
|
|
|
5
5
|
const ValidationLogic = require("./ValidationLogic.cjs");
|
|
6
6
|
const standardSchemaValidator = require("./standardSchemaValidator.cjs");
|
|
7
7
|
const metaHelper = require("./metaHelper.cjs");
|
|
8
|
+
const EventClient = require("./EventClient.cjs");
|
|
8
9
|
function getDefaultFormState(defaultState) {
|
|
9
10
|
return {
|
|
10
11
|
values: defaultState.values ?? {},
|
|
@@ -39,9 +40,17 @@ class FormApi {
|
|
|
39
40
|
const cleanup = () => {
|
|
40
41
|
cleanupFieldMetaDerived();
|
|
41
42
|
cleanupStoreDerived();
|
|
43
|
+
EventClient.formEventClient.emit("form-unmounted", {
|
|
44
|
+
id: this._formId
|
|
45
|
+
});
|
|
42
46
|
};
|
|
43
47
|
this.options.listeners?.onMount?.({ formApi: this });
|
|
44
48
|
const { onMount } = this.options.validators || {};
|
|
49
|
+
EventClient.formEventClient.emit("form-state-change", {
|
|
50
|
+
id: this._formId,
|
|
51
|
+
state: this.store.state,
|
|
52
|
+
options: this.options
|
|
53
|
+
});
|
|
45
54
|
if (!onMount) return cleanup;
|
|
46
55
|
this.validateSync("mount");
|
|
47
56
|
return cleanup;
|
|
@@ -623,6 +632,8 @@ class FormApi {
|
|
|
623
632
|
listeners: {},
|
|
624
633
|
formListeners: {}
|
|
625
634
|
};
|
|
635
|
+
this._formId = opts?.formId ?? crypto.randomUUID();
|
|
636
|
+
this._devtoolsSubmissionOverride = false;
|
|
626
637
|
this.baseStore = new store.Store(
|
|
627
638
|
getDefaultFormState({
|
|
628
639
|
...opts?.defaultState,
|
|
@@ -772,12 +783,40 @@ class FormApi {
|
|
|
772
783
|
});
|
|
773
784
|
this.handleSubmit = this.handleSubmit.bind(this);
|
|
774
785
|
this.update(opts || {});
|
|
786
|
+
this.store.subscribe(() => {
|
|
787
|
+
EventClient.formEventClient.emit("form-state-change", {
|
|
788
|
+
id: this._formId,
|
|
789
|
+
state: this.store.state,
|
|
790
|
+
options: this.options
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
EventClient.formEventClient.on("request-form-state", (e) => {
|
|
794
|
+
if (e.payload.id === this._formId) {
|
|
795
|
+
EventClient.formEventClient.emit("form-state-change", {
|
|
796
|
+
id: this._formId,
|
|
797
|
+
state: this.store.state,
|
|
798
|
+
options: this.options
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
EventClient.formEventClient.on("request-form-reset", (e) => {
|
|
803
|
+
if (e.payload.id === this._formId) {
|
|
804
|
+
this.reset();
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
EventClient.formEventClient.on("request-form-force-submit", (e) => {
|
|
808
|
+
if (e.payload.id === this._formId) {
|
|
809
|
+
this._devtoolsSubmissionOverride = true;
|
|
810
|
+
this.handleSubmit();
|
|
811
|
+
this._devtoolsSubmissionOverride = false;
|
|
812
|
+
}
|
|
813
|
+
});
|
|
775
814
|
}
|
|
776
815
|
get state() {
|
|
777
816
|
return this.store.state;
|
|
778
817
|
}
|
|
779
|
-
|
|
780
|
-
return this.
|
|
818
|
+
formId() {
|
|
819
|
+
return this._formId;
|
|
781
820
|
}
|
|
782
821
|
/**
|
|
783
822
|
* @private
|
|
@@ -811,7 +850,7 @@ class FormApi {
|
|
|
811
850
|
}
|
|
812
851
|
);
|
|
813
852
|
});
|
|
814
|
-
if (!this.state.canSubmit) return;
|
|
853
|
+
if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) return;
|
|
815
854
|
const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
|
|
816
855
|
this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
|
|
817
856
|
const done = () => {
|
|
@@ -825,6 +864,13 @@ class FormApi {
|
|
|
825
864
|
formApi: this,
|
|
826
865
|
meta: submitMetaArg
|
|
827
866
|
});
|
|
867
|
+
EventClient.formEventClient.emit("form-submission-state-change", {
|
|
868
|
+
id: this._formId,
|
|
869
|
+
submissionAttempt: this.state.submissionAttempts,
|
|
870
|
+
successful: false,
|
|
871
|
+
stage: "validateAllFields",
|
|
872
|
+
errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
|
|
873
|
+
});
|
|
828
874
|
return;
|
|
829
875
|
}
|
|
830
876
|
await this.validate("submit");
|
|
@@ -835,6 +881,13 @@ class FormApi {
|
|
|
835
881
|
formApi: this,
|
|
836
882
|
meta: submitMetaArg
|
|
837
883
|
});
|
|
884
|
+
EventClient.formEventClient.emit("form-submission-state-change", {
|
|
885
|
+
id: this._formId,
|
|
886
|
+
submissionAttempt: this.state.submissionAttempts,
|
|
887
|
+
successful: false,
|
|
888
|
+
stage: "validate",
|
|
889
|
+
errors: this.state.errors
|
|
890
|
+
});
|
|
838
891
|
return;
|
|
839
892
|
}
|
|
840
893
|
store.batch(() => {
|
|
@@ -861,6 +914,11 @@ class FormApi {
|
|
|
861
914
|
isSubmitSuccessful: true
|
|
862
915
|
// Set isSubmitSuccessful to true on successful submission
|
|
863
916
|
}));
|
|
917
|
+
EventClient.formEventClient.emit("form-submission-state-change", {
|
|
918
|
+
id: this._formId,
|
|
919
|
+
submissionAttempt: this.state.submissionAttempts,
|
|
920
|
+
successful: true
|
|
921
|
+
});
|
|
864
922
|
done();
|
|
865
923
|
});
|
|
866
924
|
} catch (err) {
|
|
@@ -869,6 +927,13 @@ class FormApi {
|
|
|
869
927
|
isSubmitSuccessful: false
|
|
870
928
|
// Ensure isSubmitSuccessful is false if an error occurs
|
|
871
929
|
}));
|
|
930
|
+
EventClient.formEventClient.emit("form-submission-state-change", {
|
|
931
|
+
id: this._formId,
|
|
932
|
+
submissionAttempt: this.state.submissionAttempts,
|
|
933
|
+
successful: false,
|
|
934
|
+
stage: "inflight",
|
|
935
|
+
onError: err
|
|
936
|
+
});
|
|
872
937
|
done();
|
|
873
938
|
throw err;
|
|
874
939
|
}
|