@homebound/form-state 2.8.0 → 2.9.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/FormStateApp.d.ts
CHANGED
package/dist/FormStateApp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FormStateApp = void 0;
|
|
3
|
+
exports.TextField = exports.FormStateApp = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const mobx_react_1 = require("mobx-react");
|
|
6
6
|
const index_1 = require("./index");
|
|
@@ -91,3 +91,4 @@ function TextField(props) {
|
|
|
91
91
|
jsx_runtime_1.jsx("td", Object.assign({ "data-testid": `${field.key}_errors` }, { children: field.errors }), void 0),
|
|
92
92
|
jsx_runtime_1.jsx("td", Object.assign({ "data-testid": `${field.key}_original` }, { children: field.originalValue }), void 0)] }, void 0) }, void 0)] }), void 0)] }, void 0)) }, void 0));
|
|
93
93
|
}
|
|
94
|
+
exports.TextField = TextField;
|
package/dist/useFormState.js
CHANGED
|
@@ -12,7 +12,6 @@ let isAutoSaving = false;
|
|
|
12
12
|
// `pendingAutoSave` is a flag for determining if we need to immediately call `maybeAutoSave` again after the initial Promise finishes
|
|
13
13
|
// This could happen if a field triggers auto-save while another field's auto-save is already in progress.
|
|
14
14
|
let pendingAutoSave = false;
|
|
15
|
-
let timerId;
|
|
16
15
|
/**
|
|
17
16
|
* Creates a formState instance for editing in a form.
|
|
18
17
|
*/
|
|
@@ -39,7 +38,7 @@ function useFormState(opts) {
|
|
|
39
38
|
if (autoSaveRef.current && form.dirty && form.valid && !isAutoSaving) {
|
|
40
39
|
isAutoSaving = "queued";
|
|
41
40
|
// We use setTimeout as a cheap way to wait until the end of the current event listener
|
|
42
|
-
|
|
41
|
+
setTimeout(async () => {
|
|
43
42
|
try {
|
|
44
43
|
// We technically don't flip to in-flight until after the call in case the
|
|
45
44
|
// user's autoSave function itself wants to call a .set.
|
|
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
4
|
const rtl_utils_1 = require("@homebound/rtl-utils");
|
|
5
5
|
const react_1 = require("@testing-library/react");
|
|
6
|
+
const mobx_1 = require("mobx");
|
|
6
7
|
const mobx_react_1 = require("mobx-react");
|
|
7
8
|
const react_2 = require("react");
|
|
9
|
+
const FormStateApp_1 = require("./FormStateApp");
|
|
8
10
|
const formState_1 = require("./formState");
|
|
9
11
|
const useFormState_1 = require("./useFormState");
|
|
10
12
|
describe("useFormState", () => {
|
|
@@ -425,6 +427,33 @@ describe("useFormState", () => {
|
|
|
425
427
|
expect(autoSaveStub).toBeCalledWith({ id: "a:1", firstName: "Foo" });
|
|
426
428
|
expect(autoSaveStub).toBeCalledWith({ id: "a:1", lastName: "Bar" });
|
|
427
429
|
});
|
|
430
|
+
it("calls autoSave with results of calculations in addRules", async () => {
|
|
431
|
+
const autoSaveStub = jest.fn();
|
|
432
|
+
const config = {
|
|
433
|
+
id: { type: "value" },
|
|
434
|
+
firstName: { type: "value" },
|
|
435
|
+
lastName: { type: "value" },
|
|
436
|
+
};
|
|
437
|
+
// Given a component that is using autoSave
|
|
438
|
+
function TestComponent() {
|
|
439
|
+
const fs = useFormState_1.useFormState({
|
|
440
|
+
config,
|
|
441
|
+
addRules(fs) {
|
|
442
|
+
// And also has calculated values
|
|
443
|
+
mobx_1.reaction(() => fs.firstName.value, (curr) => (fs.lastName.value = curr));
|
|
444
|
+
},
|
|
445
|
+
autoSave: (fs) => autoSaveStub(fs.changedValue),
|
|
446
|
+
init: { id: "a:1" },
|
|
447
|
+
});
|
|
448
|
+
return jsx_runtime_1.jsx(FormStateApp_1.TextField, { field: fs.firstName }, void 0);
|
|
449
|
+
}
|
|
450
|
+
const r = await rtl_utils_1.render(jsx_runtime_1.jsx(TestComponent, {}, void 0));
|
|
451
|
+
// When the user sets one field
|
|
452
|
+
await rtl_utils_1.typeAndWait(r.firstName, "first");
|
|
453
|
+
// Then we only called autoSave once
|
|
454
|
+
expect(autoSaveStub).toBeCalledTimes(1);
|
|
455
|
+
expect(autoSaveStub).toBeCalledWith({ id: "a:1", firstName: "first", lastName: "first" });
|
|
456
|
+
});
|
|
428
457
|
});
|
|
429
458
|
const authorConfig = {
|
|
430
459
|
id: { type: "value" },
|
package/dist/useFormStates.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ declare type UseFormStatesOpts<T, I> = {
|
|
|
35
35
|
*/
|
|
36
36
|
map?: (input: Exclude<I, null | undefined>) => T;
|
|
37
37
|
};
|
|
38
|
-
export declare function useFormStates<T, I>(opts: UseFormStatesOpts<T, I>): {
|
|
38
|
+
export declare function useFormStates<T, I = T>(opts: UseFormStatesOpts<T, I>): {
|
|
39
39
|
getFormState: (input: I) => ObjectState<T>;
|
|
40
40
|
};
|
|
41
41
|
export {};
|
package/dist/useFormStates.js
CHANGED
|
@@ -23,6 +23,13 @@ function useFormStates(opts) {
|
|
|
23
23
|
if (autoSaveRef.current && form.dirty && form.valid && !isAutoSaving) {
|
|
24
24
|
try {
|
|
25
25
|
isAutoSaving = true;
|
|
26
|
+
// See if we have any reactions that want to run (i.e. added by addRules hooks)
|
|
27
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
28
|
+
// If a reaction re-queued our form during the ^ wait, remove it
|
|
29
|
+
let i = -1;
|
|
30
|
+
while ((i = pendingAutoSaves.current.indexOf(form)) !== -1) {
|
|
31
|
+
pendingAutoSaves.current.splice(i, 1);
|
|
32
|
+
}
|
|
26
33
|
await autoSaveRef.current(form);
|
|
27
34
|
}
|
|
28
35
|
finally {
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
4
|
const rtl_utils_1 = require("@homebound/rtl-utils");
|
|
5
|
+
const mobx_1 = require("mobx");
|
|
5
6
|
const react_1 = require("react");
|
|
6
7
|
const formState_1 = require("./formState");
|
|
8
|
+
const FormStateApp_1 = require("./FormStateApp");
|
|
7
9
|
const useFormStates_1 = require("./useFormStates");
|
|
8
10
|
describe("useFormStates", () => {
|
|
9
11
|
it("can lazily create form states", async () => {
|
|
@@ -99,10 +101,9 @@ describe("useFormStates", () => {
|
|
|
99
101
|
rtl_utils_1.click(r.focusSetAndSaveField2());
|
|
100
102
|
// Awaits the promises for all methods triggered above
|
|
101
103
|
await rtl_utils_1.wait();
|
|
102
|
-
// Then expect the auto save to only have been called
|
|
103
|
-
expect(autoSaveStub).toBeCalledTimes(
|
|
104
|
-
expect(autoSaveStub).toBeCalledWith({ id: "a:1", firstName: "Foo" });
|
|
105
|
-
expect(autoSaveStub).toBeCalledWith({ id: "a:1", lastName: "Bar" });
|
|
104
|
+
// Then expect the auto save to only have been called two times. Once with each set of changedValues.
|
|
105
|
+
expect(autoSaveStub).toBeCalledTimes(2);
|
|
106
|
+
expect(autoSaveStub).toBeCalledWith({ id: "a:1", firstName: "Foo", lastName: "Bar" });
|
|
106
107
|
expect(autoSaveStub).toBeCalledWith({ id: "a:2", lastName: "Bar" });
|
|
107
108
|
});
|
|
108
109
|
it("clears out cache if configuration changes", async () => {
|
|
@@ -151,6 +152,39 @@ describe("useFormStates", () => {
|
|
|
151
152
|
// Then addRules was only called once
|
|
152
153
|
expect(addRules).toHaveBeenCalledTimes(1);
|
|
153
154
|
});
|
|
155
|
+
it("calls autoSave with results of calculations in addRules", async () => {
|
|
156
|
+
// Given a user wants to use auto save
|
|
157
|
+
const autoSave = jest.fn();
|
|
158
|
+
function TestComponent() {
|
|
159
|
+
const config = {
|
|
160
|
+
id: { type: "value" },
|
|
161
|
+
firstName: { type: "value" },
|
|
162
|
+
lastName: { type: "value" },
|
|
163
|
+
};
|
|
164
|
+
const { getFormState } = useFormStates_1.useFormStates({
|
|
165
|
+
config,
|
|
166
|
+
getId: (o) => o.id,
|
|
167
|
+
addRules(fs) {
|
|
168
|
+
// And they have a reactive true that calculates last name
|
|
169
|
+
mobx_1.reaction(() => fs.firstName.value, (curr) => {
|
|
170
|
+
console.log({ curr });
|
|
171
|
+
fs.lastName.set(curr);
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
async autoSave(fs) {
|
|
175
|
+
autoSave(fs.changedValue);
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
return jsx_runtime_1.jsx(FormStateApp_1.TextField, { field: getFormState({ id: "a:1", firstName: "Brandon" }).firstName }, void 0);
|
|
179
|
+
}
|
|
180
|
+
// When we render
|
|
181
|
+
const r = await rtl_utils_1.render(jsx_runtime_1.jsx(TestComponent, {}, void 0));
|
|
182
|
+
// And update the firstName
|
|
183
|
+
await rtl_utils_1.typeAndWait(r.firstName(), "first");
|
|
184
|
+
// Then autoSave was called once with both input+calc'd values
|
|
185
|
+
expect(autoSave).toHaveBeenCalledTimes(1);
|
|
186
|
+
expect(autoSave).toHaveBeenCalledWith({ id: "a:1", firstName: "first", lastName: "first" });
|
|
187
|
+
});
|
|
154
188
|
});
|
|
155
189
|
function ChildComponent({ os }) {
|
|
156
190
|
return jsx_runtime_1.jsx("div", Object.assign({ "data-testid": "firstName" }, { children: os.firstName.value }), void 0);
|