@servicetitan/form 22.3.0 → 22.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/date-range-picker/date-range-picker.d.ts +1 -1
  3. package/dist/date-range-picker/date-range-picker.d.ts.map +1 -1
  4. package/dist/date-range-picker/date-range-picker.js.map +1 -1
  5. package/dist/demo/date-range-picker.js.map +1 -1
  6. package/dist/demo/index.d.ts +0 -1
  7. package/dist/demo/index.d.ts.map +1 -1
  8. package/dist/demo/index.js +0 -1
  9. package/dist/demo/index.js.map +1 -1
  10. package/dist/demo/input-date-mask.d.ts.map +1 -1
  11. package/dist/demo/input-date-mask.js.map +1 -1
  12. package/dist/form-state-error-banner/form-state-error-banner.js +1 -1
  13. package/dist/form-state-error-banner/form-state-error-banner.js.map +1 -1
  14. package/dist/index.d.ts +1 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -4
  17. package/dist/index.js.map +1 -1
  18. package/package.json +14 -15
  19. package/src/date-range-picker/date-range-picker.tsx +1 -1
  20. package/src/demo/date-range-picker.tsx +1 -1
  21. package/src/demo/index.ts +0 -1
  22. package/src/demo/input-date-mask.tsx +0 -1
  23. package/src/form-state-error-banner/form-state-error-banner.tsx +1 -1
  24. package/src/index.ts +2 -4
  25. package/dist/date-range.d.ts +0 -5
  26. package/dist/date-range.d.ts.map +0 -1
  27. package/dist/date-range.js +0 -2
  28. package/dist/date-range.js.map +0 -1
  29. package/dist/demo/dropdown-state.d.ts +0 -3
  30. package/dist/demo/dropdown-state.d.ts.map +0 -1
  31. package/dist/demo/dropdown-state.js +0 -133
  32. package/dist/demo/dropdown-state.js.map +0 -1
  33. package/dist/dropdown-state.d.ts +0 -42
  34. package/dist/dropdown-state.d.ts.map +0 -1
  35. package/dist/dropdown-state.js +0 -314
  36. package/dist/dropdown-state.js.map +0 -1
  37. package/dist/form-helpers.d.ts +0 -70
  38. package/dist/form-helpers.d.ts.map +0 -1
  39. package/dist/form-helpers.js +0 -232
  40. package/dist/form-helpers.js.map +0 -1
  41. package/dist/form-validators.d.ts +0 -30
  42. package/dist/form-validators.d.ts.map +0 -1
  43. package/dist/form-validators.js +0 -56
  44. package/dist/form-validators.js.map +0 -1
  45. package/dist/persistent-form-state/domain-storage.d.ts +0 -14
  46. package/dist/persistent-form-state/domain-storage.d.ts.map +0 -1
  47. package/dist/persistent-form-state/domain-storage.js +0 -42
  48. package/dist/persistent-form-state/domain-storage.js.map +0 -1
  49. package/dist/persistent-form-state/in-memory-storage.d.ts +0 -13
  50. package/dist/persistent-form-state/in-memory-storage.d.ts.map +0 -1
  51. package/dist/persistent-form-state/in-memory-storage.js +0 -30
  52. package/dist/persistent-form-state/in-memory-storage.js.map +0 -1
  53. package/dist/persistent-form-state/index.d.ts +0 -2
  54. package/dist/persistent-form-state/index.d.ts.map +0 -1
  55. package/dist/persistent-form-state/index.js +0 -2
  56. package/dist/persistent-form-state/index.js.map +0 -1
  57. package/dist/persistent-form-state/persistent-form-state.d.ts +0 -18
  58. package/dist/persistent-form-state/persistent-form-state.d.ts.map +0 -1
  59. package/dist/persistent-form-state/persistent-form-state.js +0 -93
  60. package/dist/persistent-form-state/persistent-form-state.js.map +0 -1
  61. package/src/__tests__/__snapshots__/form-helpers.test.ts.snap +0 -37
  62. package/src/__tests__/form-helpers.test.ts +0 -229
  63. package/src/__tests__/form-validators.test.ts +0 -55
  64. package/src/date-range.ts +0 -4
  65. package/src/demo/dropdown-state.tsx +0 -233
  66. package/src/dropdown-state.ts +0 -205
  67. package/src/form-helpers.ts +0 -259
  68. package/src/form-validators.ts +0 -106
  69. package/src/persistent-form-state/__tests__/domain-storage.test.ts +0 -81
  70. package/src/persistent-form-state/domain-storage.ts +0 -43
  71. package/src/persistent-form-state/in-memory-storage.ts +0 -32
  72. package/src/persistent-form-state/index.ts +0 -1
  73. package/src/persistent-form-state/persistent-form-state.ts +0 -68
@@ -1,259 +0,0 @@
1
- import { SyntheticEvent, ChangeEvent, Key, ReactNode } from 'react';
2
- import { FieldState, FormState, ValidatableMapOrArray, ComposibleValidatable } from 'formstate';
3
- import { toJS, isObservableMap, runInAction, transaction, computed, comparer } from 'mobx';
4
-
5
- export class CheckboxFieldState extends FieldState<boolean> {
6
- onChangeHandler = (_0: any, checked: boolean) => {
7
- this.onChange(checked);
8
- };
9
- // eslint-disable-next-line @typescript-eslint/naming-convention
10
- DEPRECATED_onChangeHandler = (
11
- _0: SyntheticEvent<HTMLInputElement>,
12
- data: { checked?: boolean }
13
- ) => {
14
- this.onChange(!!data.checked);
15
- };
16
- }
17
-
18
- export class InputFieldState<T> extends FieldState<T> {
19
- onChangeHandler = (_0: SyntheticEvent<HTMLInputElement>, data: { value: T }) => {
20
- this.onChange(data.value);
21
- };
22
- onChangeNativeHandler = (event: ChangeEvent<HTMLInputElement>) => {
23
- this.onChange(event.currentTarget.value as unknown as T);
24
- };
25
- }
26
-
27
- export class TextAreaFieldState<T> extends FieldState<T> {
28
- /**
29
- * react-semantic type for onChange event of TextArea component seems to have a bug with data object type
30
- * so declaring data as any
31
- */
32
- onChangeHandler = (_0: SyntheticEvent<HTMLTextAreaElement>, data: any) => {
33
- this.onChange(data.value);
34
- };
35
- }
36
-
37
- export class DropdownFieldState<T> extends FieldState<T> {
38
- /**
39
- * react-semantic type for onChange event of Dropdown component seems to have a bug with data object type
40
- * so declaring data as any
41
- */
42
- onChangeHandler = (_0: SyntheticEvent<HTMLElement>, data: any) => {
43
- this.onChange(data.value);
44
- };
45
- }
46
-
47
- export class DropdownSearchFieldState<T> extends FieldState<T> {
48
- onChangeHandler = (_0: SyntheticEvent<HTMLElement>, data: { searchQuery: T }) => {
49
- this.onChange(data.searchQuery);
50
- };
51
- }
52
-
53
- export class DatetimeFieldState extends FieldState<Date | null> {
54
- onChangeHandler = (event: { target: { value: Date | null } }) => {
55
- this.onChange(event.target.value);
56
- };
57
- }
58
-
59
- export interface Option<T> {
60
- key: Key;
61
- text: ReactNode;
62
- value: T;
63
- }
64
-
65
- export function enumToOptions<T>(
66
- enumObject: T,
67
- nameProvider?: (value: T[keyof T]) => Option<T[keyof T]>['text']
68
- ): Option<T[keyof T]>[] {
69
- return getEnumKeys(enumObject).map(k => ({
70
- key: k as string,
71
- text: nameProvider ? nameProvider(enumObject[k]) : k,
72
- value: enumObject[k],
73
- }));
74
- }
75
-
76
- export function getEnumKeys<T>(enumObject: T) {
77
- let keys = Object.keys(enumObject) as (keyof T)[];
78
-
79
- if (keys.some(k => typeof enumObject[k] === 'number')) {
80
- keys = keys.filter(k => typeof enumObject[k] === 'number');
81
- }
82
-
83
- return keys;
84
- }
85
-
86
- export function getEnumValues<T>(enumObject: T) {
87
- return getEnumKeys(enumObject).map(k => enumObject[k]);
88
- }
89
-
90
- export type FormValues = string | number | boolean | (string | number | boolean)[];
91
- export interface FormStateAsJS {
92
- [index: string]: FormValues | Map<any, any> | Set<any> | FormStateAsJS;
93
- }
94
-
95
- export function traverseFormState<T extends ValidatableMapOrArray>(
96
- recursive: boolean,
97
- formState: FormState<T>,
98
- onFormVisit?: (key: string, form: FormState<any>) => void,
99
- onFieldVisit?: (key: string, field: FieldState<any>) => void
100
- ) {
101
- const visitChild = (key: string, child: ComposibleValidatable<any>) => {
102
- if (child instanceof FormState) {
103
- if (recursive) {
104
- traverseFormState(recursive, child, onFormVisit, onFieldVisit);
105
- }
106
- if (onFormVisit) {
107
- onFormVisit(key, child);
108
- }
109
- } else if (onFieldVisit) {
110
- onFieldVisit(key, child as FieldState<any>);
111
- }
112
- };
113
-
114
- if (Array.isArray(formState.$)) {
115
- formState.$.forEach((child, index) => visitChild(index.toString(), child));
116
- } else {
117
- (isObservableMap(formState.$)
118
- ? Array.from(formState.$ as Map<any, ComposibleValidatable<any>>)
119
- : Object.entries(formState.$ as Record<string, ComposibleValidatable<any>>)
120
- ).forEach(([key, child]) => visitChild(key, child));
121
- }
122
- }
123
-
124
- // eslint-disable-next-line @typescript-eslint/naming-convention
125
- export function BAD_formStateToJS<T extends ValidatableMapOrArray>(formState: FormState<T>) {
126
- const formValues = {} as any;
127
- traverseFormState(
128
- false,
129
- formState,
130
- (key: any, form: FormState<any>) => (formValues[key] = BAD_formStateToJS(form)),
131
- (key: any, field: FieldState<any>) => (formValues[key] = toJS(field.value))
132
- );
133
- return formValues as unknown as FormStateAsJS;
134
- }
135
-
136
- export type FormStateShape<T> = T extends FormState<infer U>[]
137
- ? FormStateMapOrObject<U>[]
138
- : FormStateMapOrObject<T>;
139
-
140
- type FormStateMapOrObject<T> = T extends Map<infer K, infer V>
141
- ? FormStateObject<Record<K & (string | number | symbol), V>>
142
- : FormStateObject<T>;
143
-
144
- type FormStateObject<T> = {
145
- [P in keyof T]: T[P] extends FieldState<infer U>
146
- ? U
147
- : T[P] extends FormState<infer U>
148
- ? FormStateShape<U>
149
- : never;
150
- };
151
-
152
- export function formStateToJS<T extends ValidatableMapOrArray>(
153
- formState: FormState<T>
154
- ): FormStateShape<T> {
155
- const formValues = Array.isArray(formState.$) ? [] : ({} as any);
156
- traverseFormState(
157
- false,
158
- formState,
159
- (key: any, form: FormState<any>) => (formValues[key] = formStateToJS(form)),
160
- (key: any, field: FieldState<any>) => (formValues[key] = toJS(field.$))
161
- );
162
- return formValues as unknown as FormStateShape<T>;
163
- }
164
-
165
- export type RecursivePartial<T> = T extends (infer U)[]
166
- ? RecursivePartialObject<U>[]
167
- : RecursivePartialObject<T>;
168
-
169
- type RecursivePartialObject<T> = {
170
- [P in keyof T]?: T[P] extends Record<any, any> ? RecursivePartial<T[P]> : T[P];
171
- };
172
-
173
- export function setFormStateValues<T extends ValidatableMapOrArray>(
174
- formState: FormState<T>,
175
- data: RecursivePartial<FormStateShape<T>>,
176
- triggerValidation = false
177
- ): FormState<T> {
178
- if (Array.isArray(formState.$) && (data as any[]).length !== formState.$.length) {
179
- throw new Error(
180
- 'Number of elements in data object node is different from number of element in form.' +
181
- ' All array nodes should match in size before values can be applied to form.'
182
- );
183
- }
184
- transaction(() => {
185
- traverseFormState(
186
- false,
187
- formState,
188
- (key: string, form: FormState<any>) => {
189
- if (data instanceof Map || isObservableMap(data)) {
190
- if (data.has(key)) {
191
- setFormStateValues(form, data.get(key));
192
- }
193
- } else {
194
- if (Object.prototype.hasOwnProperty.call(data, key)) {
195
- setFormStateValues(form, data[key as keyof typeof data]);
196
- }
197
- }
198
- },
199
- (key: string, field: FieldState<any>) => {
200
- if (data instanceof Map || isObservableMap(data)) {
201
- if (data.has(key)) {
202
- runInAction(() => {
203
- field.value = data.get(key);
204
- field.$ = data.get(key);
205
- });
206
- }
207
- } else {
208
- if (Object.prototype.hasOwnProperty.call(data, key)) {
209
- runInAction(() => {
210
- field.value = data[key as keyof typeof data];
211
- field.$ = data[key as keyof typeof data];
212
- });
213
- }
214
- }
215
- }
216
- );
217
- if (triggerValidation) {
218
- const setValidatedSubFields = (form: FormState<any>) => {
219
- form.validatedSubFields = (form as any).getValues();
220
- };
221
- traverseFormState(true, formState, (_0: string, form: FormState<any>) => {
222
- setValidatedSubFields(form);
223
- });
224
- setValidatedSubFields(formState);
225
- formState.validate();
226
- }
227
- });
228
- return formState;
229
- }
230
-
231
- export function commitFormState<T extends ValidatableMapOrArray>(formState: FormState<T>) {
232
- traverseFormState(true, formState, undefined, (_0: string, field: FieldState<any>) => {
233
- field.dirty = false;
234
- (field as any)._initValue = field.value;
235
- });
236
- }
237
-
238
- export function camelCaseToTitleCase(value: string) {
239
- const regexp = /[A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[A-Za-z](?=[^A-Za-z])/g;
240
- return value.replace(regexp, '$& ');
241
- }
242
-
243
- export function isFormStateChanged<T extends ValidatableMapOrArray>(formState: FormState<T>) {
244
- return computed(() => {
245
- let isChanged = false;
246
- traverseFormState(true, formState, undefined, (_0: string, field: FieldState<any>) => {
247
- const isValueChanged = () => {
248
- if (field instanceof InputFieldState) {
249
- if ((field as any)._initValue === undefined && field.value === '') {
250
- return false;
251
- }
252
- }
253
- return !comparer.structural((field as any)._initValue, field.value);
254
- };
255
- isChanged = isChanged || (field.dirty === true && isValueChanged());
256
- });
257
- return isChanged;
258
- });
259
- }
@@ -1,106 +0,0 @@
1
- import { DatetimeFieldState, FormValues } from './form-helpers';
2
- import { isObservableArray } from 'mobx';
3
- import { DateRange } from './date-range';
4
-
5
- interface DateRangeFieldStates {
6
- startDate: DatetimeFieldState;
7
- endDate: DatetimeFieldState;
8
- }
9
-
10
- const isDefined = (value: FormValues | undefined) => {
11
- if (value === undefined) {
12
- return false;
13
- }
14
-
15
- if (Array.isArray(value) || isObservableArray(value)) {
16
- return !!value.length;
17
- }
18
-
19
- return typeof value === 'string' ? !!value.trim() : !!value;
20
- };
21
-
22
- export const FormValidators = {
23
- required: (value?: FormValues) =>
24
- FormValidators.requiredWithCustomMessage('Value is required')(value),
25
-
26
- requiredWithCustomMessage: (errorMessage: string) => (value?: FormValues) =>
27
- !isDefined(value) && errorMessage,
28
-
29
- hasLowerCase: (str: string) => /[a-z]/.test(str),
30
-
31
- hasUpperCase: (str: string) => /[A-Z]/.test(str),
32
-
33
- hasNumber: (str: string) => /\d/.test(str),
34
-
35
- passwordIsValidFormat: (password: string) =>
36
- password.length > 7 &&
37
- FormValidators.hasLowerCase(password) &&
38
- FormValidators.hasUpperCase(password) &&
39
- FormValidators.hasNumber(password),
40
-
41
- emailFormatIsValid: (email: string) => {
42
- /* tslint:disable: ter-max-len */
43
- const regex =
44
- /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
45
- return email.length !== 0 && regex.test(email);
46
- },
47
-
48
- website: (errorMessage = 'Enter valid website') => {
49
- return (value: string) =>
50
- !/^(https?:\/\/)?(www\.)?([a-zA-Z0-9]+(-?[a-zA-Z0-9])*\.)+[\w]{2,}(\/\S*)?$/i.test(
51
- value
52
- ) && errorMessage;
53
- },
54
-
55
- minDate: new Date(1900, 0, 1),
56
-
57
- maxDate: new Date(2099, 11, 31),
58
-
59
- isDateValid: (date: Date | null) =>
60
- (!date || date > FormValidators.maxDate || date < FormValidators.minDate) &&
61
- 'Please provide a valid date',
62
-
63
- isDateRangeValid: (dateRange: DateRangeFieldStates) =>
64
- dateRange.startDate.$ &&
65
- dateRange.endDate.$ &&
66
- dateRange.startDate.$ > dateRange.endDate.$ &&
67
- 'Start Date should not be after End Date',
68
-
69
- dateRangeRequired:
70
- (errorMessage = 'Date Range is required') =>
71
- (dateRange: DateRange | undefined) =>
72
- (!dateRange || !dateRange.from || !dateRange.to) && errorMessage,
73
-
74
- dateRangeValid:
75
- (errorMessage = 'Start cannot be after End') =>
76
- (dateRange: DateRange | undefined) =>
77
- !!dateRange &&
78
- !!dateRange.from &&
79
- !!dateRange.to &&
80
- dateRange.from > dateRange.to &&
81
- errorMessage,
82
-
83
- isDateRangeLessThanMaxLength: (maxDays: number) => (val: DateRange | undefined) => {
84
- const dayInMillseconds = 1000 * 60 * 60 * 24;
85
- return (
86
- val?.from &&
87
- val.to &&
88
- (val.to.getTime() - val.from.getTime()) / dayInMillseconds >= maxDays &&
89
- `Only ${maxDays} days can be displayed at time`
90
- );
91
- },
92
-
93
- isAlphaNumeric: (str: string) => /^(\w+,?)*$/.test(str),
94
-
95
- isMatchingRegex: (regexp: RegExp, entity: string) => (str: string) =>
96
- !regexp.test(str) && `Invalid format for ${entity}`,
97
-
98
- minLength: (minLength: number) => (value: string | any[] | undefined) =>
99
- value && value.length < minLength ? `Value's min length is ${minLength}` : false,
100
-
101
- maxLength: (maxLength: number) => (value: string | any[] | undefined) =>
102
- value && value.length > maxLength ? `Value's max length is ${maxLength}` : false,
103
-
104
- exactLength: (exactLength: number) => (value: string | any[] | undefined) =>
105
- value && value.length !== exactLength ? `Value's length must be ${exactLength}` : false,
106
- };
@@ -1,81 +0,0 @@
1
- import { DomainStorage } from '../domain-storage';
2
-
3
- const newData = {
4
- string: 'value',
5
- number: 1,
6
- simpleObject: {
7
- name: 'name value',
8
- deepObject: {
9
- name2: 'name2 value',
10
- },
11
- },
12
- };
13
-
14
- describe('domain-storage', () => {
15
- test('getItem returns null if the key does not exist', function () {
16
- const storage = new DomainStorage({ cacheKey: 'test', version: 1 });
17
-
18
- const data = storage.getItem();
19
-
20
- expect(data).toBe(null);
21
- });
22
-
23
- test('getItem returns value from storage', function () {
24
- const existingValue = JSON.stringify({ value: newData, version: 1 });
25
- localStorage.setItem('test', existingValue);
26
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
27
-
28
- const data = storage.getItem();
29
-
30
- expect(data).toEqual(newData);
31
- });
32
-
33
- test('getItem returns null when the version does not match', function () {
34
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
35
-
36
- storage.setItem('', newData);
37
- const data = storage.getItem();
38
- expect(data).toEqual(newData);
39
-
40
- const newStorage = new DomainStorage({ cacheKey: 'test', version: 2 });
41
- const newStorageData = newStorage.getItem();
42
- expect(newStorageData).toEqual(null);
43
- });
44
-
45
- test('getItem returns null when there is invalid formStateCache in storage', function () {
46
- localStorage.setItem('test', '{}');
47
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
48
-
49
- const data = storage.getItem();
50
-
51
- expect(data).toEqual(null);
52
- expect(localStorage.removeItem).toHaveBeenCalledWith('test');
53
- });
54
-
55
- test('getItem returns null when there is invalid json in storage', function () {
56
- localStorage.setItem('test', '{{}');
57
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
58
-
59
- const data = storage.getItem();
60
-
61
- expect(data).toEqual(null);
62
- });
63
-
64
- test('setItem adds value to storage', function () {
65
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
66
-
67
- storage.setItem('', newData);
68
-
69
- const expectedValue = JSON.stringify({ value: newData, version: 1 });
70
- expect(localStorage.getItem('test')).toEqual(expectedValue);
71
- });
72
-
73
- test('removeItem removes value from storage', function () {
74
- localStorage.setItem('test', '{}');
75
- const storage = new DomainStorage<any>({ cacheKey: 'test', version: 1 });
76
-
77
- storage.removeItem();
78
-
79
- expect(localStorage.length).toEqual(0);
80
- });
81
- });
@@ -1,43 +0,0 @@
1
- import { FormStateShape } from '../form-helpers';
2
- import { ValidatableMapOrArray } from 'formstate';
3
-
4
- interface FormStateCache<T> {
5
- version: number;
6
- value: FormStateShape<T>;
7
- }
8
-
9
- export class DomainStorage<T extends ValidatableMapOrArray> {
10
- private readonly version: number;
11
- private readonly cacheKey: string;
12
-
13
- constructor({ cacheKey, version }: { cacheKey: string; version: number }) {
14
- this.version = version;
15
- this.cacheKey = cacheKey;
16
- }
17
-
18
- getItem(): FormStateShape<T> | null {
19
- try {
20
- const cachedData = localStorage.getItem(this.cacheKey);
21
- if (cachedData) {
22
- const formData: FormStateCache<T> = JSON.parse(cachedData);
23
- if (formData.version === this.version) {
24
- return formData.value;
25
- }
26
- this.removeItem();
27
- }
28
- } catch (e) {
29
- this.removeItem();
30
- }
31
-
32
- return null;
33
- }
34
-
35
- removeItem(): void {
36
- localStorage.removeItem(this.cacheKey);
37
- }
38
-
39
- setItem(_: string, value: FormStateShape<T>): void {
40
- const formData = { value, version: this.version };
41
- localStorage.setItem(this.cacheKey, JSON.stringify(formData));
42
- }
43
- }
@@ -1,32 +0,0 @@
1
- import { FormStateShape } from '../form-helpers';
2
- import { ValidatableMapOrArray } from 'formstate';
3
-
4
- export class InMemoryStorage<T extends ValidatableMapOrArray> {
5
- private storage = new Map<string, FormStateShape<T>>();
6
-
7
- get length() {
8
- return this.storage.size;
9
- }
10
-
11
- clear(): void {
12
- this.storage.clear();
13
- }
14
-
15
- getItem(key: string): FormStateShape<T> | null {
16
- return this.storage.get(key) !== undefined ? this.storage.get(key)! : null;
17
- }
18
-
19
- key(index: number): string | null {
20
- return this.length < index ? null : Array.from(this.storage.keys())[index];
21
- }
22
-
23
- removeItem(key: string): void {
24
- this.storage.delete(key);
25
- }
26
-
27
- setItem(key: string, value: FormStateShape<T>): void {
28
- this.storage.set(key, value);
29
- }
30
- }
31
-
32
- export const MemoryStorage = new InMemoryStorage<any>();
@@ -1 +0,0 @@
1
- export * from './persistent-form-state';
@@ -1,68 +0,0 @@
1
- import { autorun } from 'mobx';
2
- import { FormState, ValidatableMapOrArray } from 'formstate';
3
- import { InMemoryStorage, MemoryStorage } from './in-memory-storage';
4
- import {
5
- RecursivePartial,
6
- FormStateShape,
7
- setFormStateValues,
8
- formStateToJS,
9
- } from '../form-helpers';
10
- import { DomainStorage } from './domain-storage';
11
-
12
- export enum PersistenceMode {
13
- Session,
14
- Domain,
15
- InMemory,
16
- }
17
-
18
- export class PersistentFormState<T extends ValidatableMapOrArray> extends FormState<T> {
19
- private storageSystem!: InMemoryStorage<T> | DomainStorage<T>;
20
- private resetFormSuper = this.reset;
21
-
22
- constructor(
23
- $: T,
24
- private cacheKey: string,
25
- private persistenceMode: PersistenceMode,
26
- autoSave?: boolean,
27
- version?: number
28
- ) {
29
- super($);
30
-
31
- if (PersistenceMode.Domain === this.persistenceMode) {
32
- if (!version) {
33
- throw 'Set a data structure version.';
34
- }
35
- this.storageSystem = new DomainStorage<T>({ cacheKey, version });
36
- } else if (PersistenceMode.Session === this.persistenceMode) {
37
- throw 'Use of Session storage is currently unsafe';
38
- } else {
39
- this.storageSystem = MemoryStorage;
40
- }
41
-
42
- this.getCached();
43
- if (autoSave) {
44
- this.trackChange();
45
- }
46
- }
47
-
48
- save = () => {
49
- this.storageSystem.setItem(this.cacheKey, formStateToJS(this));
50
- };
51
-
52
- resetForm = () => {
53
- this.resetFormSuper();
54
- this.storageSystem.removeItem(this.cacheKey);
55
- };
56
-
57
- private trackChange = () => {
58
- autorun(() => this.save(), { delay: 500 });
59
- };
60
-
61
- private getCached = () => {
62
- const data = this.storageSystem.getItem(this.cacheKey);
63
-
64
- if (data) {
65
- setFormStateValues(this, data as unknown as RecursivePartial<FormStateShape<T>>);
66
- }
67
- };
68
- }