@homebound/form-state 2.18.1 → 2.20.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.
Files changed (39) hide show
  1. package/dist/FormStateApp.d.ts +2 -3
  2. package/dist/FormStateApp.js +8 -47
  3. package/dist/FormStateApp.test.js +14 -14
  4. package/dist/config.d.ts +6 -6
  5. package/dist/fields/fragmentField.js +3 -3
  6. package/dist/fields/listField.js +12 -12
  7. package/dist/fields/objectField.d.ts +4 -4
  8. package/dist/fields/objectField.js +10 -10
  9. package/dist/fields/valueField.d.ts +13 -0
  10. package/dist/fields/valueField.js +49 -14
  11. package/dist/formState.stories.d.ts +2 -4
  12. package/dist/formState.stories.js +1 -1
  13. package/dist/formState.test.js +171 -77
  14. package/dist/formStateDomain.js +1 -1
  15. package/dist/index.d.ts +3 -4
  16. package/dist/index.js +0 -11
  17. package/dist/proxies.d.ts +5 -0
  18. package/dist/proxies.js +21 -0
  19. package/dist/rules.d.ts +1 -1
  20. package/dist/rules.js +1 -1
  21. package/dist/setupTests.js +2 -2
  22. package/dist/useFormState.d.ts +4 -4
  23. package/dist/useFormState.js +13 -17
  24. package/dist/useFormState.test.js +141 -198
  25. package/dist/useFormStates.d.ts +3 -3
  26. package/dist/useFormStates.js +7 -11
  27. package/dist/useFormStates.test.js +56 -89
  28. package/dist/utils.d.ts +3 -3
  29. package/dist/utils.js +8 -8
  30. package/dist/utils.test.js +49 -49
  31. package/package.json +44 -39
  32. package/dist/AutoSaveStatus/AutoSaveStatusProvider.d.ts +0 -24
  33. package/dist/AutoSaveStatus/AutoSaveStatusProvider.js +0 -91
  34. package/dist/AutoSaveStatus/index.d.ts +0 -2
  35. package/dist/AutoSaveStatus/index.js +0 -9
  36. package/dist/AutoSaveStatus/useAutoSaveStatus.d.ts +0 -1
  37. package/dist/AutoSaveStatus/useAutoSaveStatus.js +0 -9
  38. package/dist/AutoSaveStatus/useAutoSaveStatus.test.d.ts +0 -1
  39. package/dist/AutoSaveStatus/useAutoSaveStatus.test.js +0 -152
@@ -13,7 +13,7 @@ var Color;
13
13
  Color["Red"] = "RED";
14
14
  Color["Blue"] = "BLUE";
15
15
  Color["Green"] = "GREEN";
16
- })(Color = exports.Color || (exports.Color = {}));
16
+ })(Color || (exports.Color = Color = {}));
17
17
  class DateOnly {
18
18
  constructor(date) {
19
19
  this.date = date;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  export { ObjectConfig } from "./config";
2
2
  export { ListFieldState } from "./fields/listField";
3
- export { createObjectState, ObjectState } from "./fields/objectField";
4
- export { FieldState } from "./fields/valueField";
5
- export { required, Rule } from "./rules";
3
+ export { ObjectState, createObjectState } from "./fields/objectField";
4
+ export { FieldState, ValueAdapter } from "./fields/valueField";
5
+ export { Rule, required } from "./rules";
6
6
  export { useFormState } from "./useFormState";
7
7
  export { useFormStates } from "./useFormStates";
8
- export * from "./AutoSaveStatus/index";
package/dist/index.js CHANGED
@@ -1,14 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
- };
12
2
  Object.defineProperty(exports, "__esModule", { value: true });
13
3
  exports.useFormStates = exports.useFormState = exports.required = exports.createObjectState = void 0;
14
4
  var objectField_1 = require("./fields/objectField");
@@ -19,4 +9,3 @@ var useFormState_1 = require("./useFormState");
19
9
  Object.defineProperty(exports, "useFormState", { enumerable: true, get: function () { return useFormState_1.useFormState; } });
20
10
  var useFormStates_1 = require("./useFormStates");
21
11
  Object.defineProperty(exports, "useFormStates", { enumerable: true, get: function () { return useFormStates_1.useFormStates; } });
22
- __exportStar(require("./AutoSaveStatus/index"), exports);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Creates a new combined object with keys in `overrides` taking precedence, and then
3
+ * any other keys falling back to `delegate`.
4
+ */
5
+ export declare function newDelegateProxy<T extends object, O extends object>(delegate: T, overrides: O): Omit<T, keyof O> & O;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newDelegateProxy = void 0;
4
+ /**
5
+ * Creates a new combined object with keys in `overrides` taking precedence, and then
6
+ * any other keys falling back to `delegate`.
7
+ */
8
+ function newDelegateProxy(delegate, overrides) {
9
+ function pickTarget(key) {
10
+ return Reflect.has(overrides, key) ? overrides : delegate;
11
+ }
12
+ return new Proxy(delegate, {
13
+ get(object, key) {
14
+ return Reflect.get(pickTarget(key), key);
15
+ },
16
+ set(object, key, value) {
17
+ return Reflect.set(pickTarget(key), key, value);
18
+ },
19
+ });
20
+ }
21
+ exports.newDelegateProxy = newDelegateProxy;
package/dist/rules.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** A validation rule, given the value and name, return the error string if valid, or undefined if valid. */
2
- export declare type Rule<V> = (opts: {
2
+ export type Rule<V> = (opts: {
3
3
  value: V;
4
4
  key: string;
5
5
  originalValue: V;
package/dist/rules.js CHANGED
@@ -5,7 +5,7 @@ const mobx_1 = require("mobx");
5
5
  /** A rule that validates `value` is not `undefined`, `null`, or empty string. */
6
6
  // We pre-emptively make this a mobx action so that it's identity doesn't change when proxied
7
7
  // and breaks our ability to do `rules.some(r => r === required)`.
8
- exports.required = mobx_1.action(({ value: v }) => {
8
+ exports.required = (0, mobx_1.action)(({ value: v }) => {
9
9
  const isEmptyString = typeof v === "string" ? v.trim() === "" : false;
10
10
  return v !== undefined && v !== null && !isEmptyString ? undefined : "Required";
11
11
  });
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  require("@testing-library/jest-dom");
4
4
  const mobx_1 = require("mobx");
5
5
  // formState doesn't use actions
6
- mobx_1.configure({ enforceActions: "never" });
6
+ (0, mobx_1.configure)({ enforceActions: "never" });
7
7
  beforeEach(() => {
8
- jest.useFakeTimers("modern");
8
+ jest.useFakeTimers();
9
9
  });
10
10
  afterEach(() => {
11
11
  jest.runOnlyPendingTimers();
@@ -1,21 +1,21 @@
1
1
  import { ObjectConfig } from "./config";
2
2
  import { ObjectState } from "./fields/objectField";
3
- export declare type Query<I> = {
3
+ export type Query<I> = {
4
4
  data: I;
5
5
  loading: boolean;
6
6
  error?: any;
7
7
  };
8
- export declare type InputAndMap<T, I> = {
8
+ export type InputAndMap<T, I> = {
9
9
  input: I;
10
10
  map: (input: Exclude<I, null | undefined>) => T;
11
11
  ifUndefined?: T;
12
12
  };
13
- export declare type QueryAndMap<T, I> = {
13
+ export type QueryAndMap<T, I> = {
14
14
  query: Query<I>;
15
15
  map: (input: Exclude<I, null | undefined>) => T;
16
16
  ifUndefined?: T;
17
17
  };
18
- export declare type UseFormStateOpts<T, I> = {
18
+ export type UseFormStateOpts<T, I> = {
19
19
  /** The form configuration, should be a module-level const or useMemo'd. */
20
20
  config: ObjectConfig<T>;
21
21
  /**
@@ -4,7 +4,6 @@ exports.useFormState = void 0;
4
4
  const is_plain_object_1 = require("is-plain-object");
5
5
  const react_1 = require("react");
6
6
  const objectField_1 = require("./fields/objectField");
7
- const AutoSaveStatus_1 = require("./AutoSaveStatus/index");
8
7
  const utils_1 = require("./utils");
9
8
  // If the user's autoSave hook makes some last-minute `.set` calls to sneak
10
9
  // in some business logic right before their GraphQL mutation call, ignore it
@@ -18,17 +17,16 @@ let pendingAutoSave = false;
18
17
  */
19
18
  function useFormState(opts) {
20
19
  const { config, init, addRules, readOnly = false, loading, autoSave } = opts;
21
- const autoSaveStatusContext = AutoSaveStatus_1.useAutoSaveStatus();
22
20
  // Use a ref so our memo'ized `onBlur` always see the latest value
23
- const autoSaveRef = react_1.useRef(autoSave);
21
+ const autoSaveRef = (0, react_1.useRef)(autoSave);
24
22
  autoSaveRef.current = autoSave;
25
- const firstRunRef = react_1.useRef(true);
23
+ const firstRunRef = (0, react_1.useRef)(true);
26
24
  // This is a little weird, but we need to know ahead of time, before the form useMemo, if we're working with classes/mobx proxies
27
- const [firstInitValue] = react_1.useState(() => utils_1.initValue(config, init));
28
- const isWrappingMobxProxy = !is_plain_object_1.isPlainObject(firstInitValue);
25
+ const [firstInitValue] = (0, react_1.useState)(() => (0, utils_1.initValue)(config, init));
26
+ const isWrappingMobxProxy = !(0, is_plain_object_1.isPlainObject)(firstInitValue);
29
27
  // If they're using init.input, useMemo on it (and it might be an array), otherwise allow the identity of init be unstable
30
- const dep = utils_1.isInput(init) ? makeArray(init.input) : utils_1.isQuery(init) ? [init.query.data, init.query.loading] : [];
31
- const form = react_1.useMemo(() => {
28
+ const dep = (0, utils_1.isInput)(init) ? makeArray(init.input) : (0, utils_1.isQuery)(init) ? [init.query.data, init.query.loading] : [];
29
+ const form = (0, react_1.useMemo)(() => {
32
30
  function maybeAutoSave() {
33
31
  if (isAutoSaving === "in-flight") {
34
32
  pendingAutoSave = true;
@@ -47,7 +45,6 @@ function useFormState(opts) {
47
45
  // user's autoSave function itself wants to call a .set.
48
46
  const promise = autoSaveRef.current(form);
49
47
  isAutoSaving = "in-flight";
50
- autoSaveStatusContext.triggerAutoSave();
51
48
  await promise;
52
49
  }
53
50
  catch (e) {
@@ -56,7 +53,6 @@ function useFormState(opts) {
56
53
  }
57
54
  finally {
58
55
  isAutoSaving = false;
59
- autoSaveStatusContext.resolveAutoSave(maybeError === null || maybeError === void 0 ? void 0 : maybeError.toString());
60
56
  if (pendingAutoSave) {
61
57
  pendingAutoSave = false;
62
58
  // Push out the follow-up by 1 tick to allow refreshes to happen to potentially
@@ -68,8 +64,8 @@ function useFormState(opts) {
68
64
  }, 0);
69
65
  }
70
66
  }
71
- const value = firstRunRef.current ? firstInitValue : utils_1.initValue(config, init);
72
- const form = objectField_1.createObjectState(config, value, { maybeAutoSave });
67
+ const value = firstRunRef.current ? firstInitValue : (0, utils_1.initValue)(config, init);
68
+ const form = (0, objectField_1.createObjectState)(config, value, { maybeAutoSave });
73
69
  form.readOnly = readOnly;
74
70
  setLoading(form, opts);
75
71
  // The identity of `addRules` is not stable, but assume that it is for better UX.
@@ -82,7 +78,7 @@ function useFormState(opts) {
82
78
  [config, ...(isWrappingMobxProxy ? dep : [])]);
83
79
  // We use useEffect so that any mutations to the proxies, which will call `setState`s on any observers to
84
80
  // queue their components' render), don't happen during our render, per https://fb.me/setstate-in-render.
85
- react_1.useEffect(() => {
81
+ (0, react_1.useEffect)(() => {
86
82
  // Ignore the 1st run b/c our 1st useMemo already initialized `form` with the current `init` value.
87
83
  // Also for mobx proxies, we recreate a new form-state every time init changes, so that our
88
84
  // fields fundamentally pointing to the right proxy. So just defer to the ^ useMemo.
@@ -97,10 +93,10 @@ function useFormState(opts) {
97
93
  // rows in the table that our side panel's form has open/is focused on" (which ideally would
98
94
  // be treated as a full component remount by having an `key` field somewhere in the parent
99
95
  // component, but it's unlikely the user will always remember to do this).
100
- form.set(utils_1.initValue(config, init), { refreshing: true });
96
+ form.set((0, utils_1.initValue)(config, init), { refreshing: true });
101
97
  }, [form, ...dep]);
102
98
  // Use useEffect so that we don't touch the form.init proxy during a render
103
- react_1.useEffect(() => {
99
+ (0, react_1.useEffect)(() => {
104
100
  form.readOnly = readOnly;
105
101
  if (loading !== undefined) {
106
102
  form.loading = loading;
@@ -115,11 +111,11 @@ function setLoading(form, opts) {
115
111
  // Prefer the explicit/top-level opts.loading if it's set
116
112
  form.loading = loading;
117
113
  }
118
- else if (utils_1.isInput(init) && !init.ifUndefined) {
114
+ else if ((0, utils_1.isInput)(init) && !init.ifUndefined) {
119
115
  // Otherwise, check for `init.input`
120
116
  form.loading = init.input === undefined;
121
117
  }
122
- else if (utils_1.isQuery(init)) {
118
+ else if ((0, utils_1.isQuery)(init)) {
123
119
  // Or `query.loading`
124
120
  form.loading = init.query.loading;
125
121
  }