@strictly/react-form 0.0.11 → 0.0.13

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.
@@ -20,29 +20,9 @@ type FlattenedErrors<ValuePathsToAdapters extends Readonly<Record<string, FieldA
20
20
  export type ValuePathsToAdaptersOf<TypePathsToAdapters extends Partial<Readonly<Record<string, FieldAdapter>>>, ValuePathsToTypePaths extends Readonly<Record<string, string>>> = keyof TypePathsToAdapters extends ValueOf<ValuePathsToTypePaths> ? {
21
21
  readonly [K in keyof ValuePathsToTypePaths as unknown extends TypePathsToAdapters[ValuePathsToTypePaths[K]] ? never : K]: NonNullable<TypePathsToAdapters[ValuePathsToTypePaths[K]]>;
22
22
  } : never;
23
- export declare abstract class FormPresenter<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ValueOfType<ReadonlyTypeOfType<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
23
+ export declare class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ValueOfType<ReadonlyTypeOfType<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
24
24
  readonly type: T;
25
25
  protected readonly adapters: TypePathsToAdapters;
26
- constructor(type: T, adapters: TypePathsToAdapters);
27
- private maybeGetAdapterForValuePath;
28
- private getAdapterForValuePath;
29
- typePath<K extends keyof ValueToTypePaths>(valuePath: K): ValueToTypePaths[K];
30
- setFieldValueAndValidate<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
31
- setFieldValue<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
32
- addListItem<K extends keyof FlattenedListTypesOfType<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, elementValue?: Maybe<ElementOfArray<FlattenedValuesOfType<T>[K]>>, index?: number): void;
33
- removeListItem<K extends keyof FlattenedListTypesOfType<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, elementValuePath: `${K}.${number}`): void;
34
- private internalSetFieldValue;
35
- clearFieldError<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): void;
36
- clearFieldValue<K extends StringKeyOf<ValueToTypePaths>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): void;
37
- clearAll(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, value: ValueOfType<T>): void;
38
- isValuePathActive<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): boolean;
39
- validateField<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, ignoreDefaultValue?: boolean): boolean;
40
- validateAll(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>): boolean;
41
- abstract createModel(value: ValueOfType<ReadonlyTypeOfType<T>>): FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>;
42
- }
43
- export declare class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ValueOfType<ReadonlyTypeOfType<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
44
- private readonly type;
45
- private readonly adapters;
46
26
  accessor value: MobxValueOfType<T>;
47
27
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
48
28
  accessor errors: FlattenedErrors<ValuePathsToAdapters>;
@@ -54,5 +34,19 @@ export declare class FormModel<T extends Type, ValueToTypePaths extends Readonly
54
34
  private synthesizeFieldByPaths;
55
35
  getAccessorForValuePath(valuePath: keyof ValuePathsToAdapters): Accessor | undefined;
56
36
  get accessors(): Readonly<Record<string, Accessor>>;
37
+ private maybeGetAdapterForValuePath;
38
+ private getAdapterForValuePath;
39
+ typePath<K extends keyof ValueToTypePaths>(valuePath: K): ValueToTypePaths[K];
40
+ setFieldValueAndValidate<K extends keyof ValuePathsToAdapters>(valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
41
+ setFieldValue<K extends keyof ValuePathsToAdapters>(valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
42
+ addListItem<K extends keyof FlattenedListTypesOfType<T>>(valuePath: K, elementValue?: Maybe<ElementOfArray<FlattenedValuesOfType<T>[K]>>, index?: number): void;
43
+ removeListItem<K extends keyof FlattenedListTypesOfType<T>>(...elementValuePaths: readonly `${K}.${number}`[]): void;
44
+ private internalSetFieldValue;
45
+ clearFieldError<K extends keyof ValuePathsToAdapters>(valuePath: K): void;
46
+ clearFieldValue<K extends StringKeyOf<ValueToTypePaths>>(valuePath: K): void;
47
+ clearAll(value: ValueOfType<T>): void;
48
+ isValuePathActive<K extends keyof ValuePathsToAdapters>(valuePath: K): boolean;
49
+ validateField<K extends keyof ValuePathsToAdapters>(valuePath: K, ignoreDefaultValue?: boolean): boolean;
50
+ validateAll(): boolean;
57
51
  }
58
52
  export {};
@@ -0,0 +1,513 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
36
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
37
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
38
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
39
+ };
40
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
41
+ if (kind === "m") throw new TypeError("Private method is not writable");
42
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
43
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
44
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
45
+ };
46
+ import { assertExists, assertExistsAndReturn, assertState, checkValidNumber, map, toArray, UnreachableError, } from '@strictly/base';
47
+ import { flattenAccessorsOfType, flattenTypesOfType, flattenValuesOfType, flattenValueTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
48
+ import { computed, observable, runInAction, } from 'mobx';
49
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
50
+ let FormModel = (() => {
51
+ var _a, _FormModel_value_accessor_storage, _FormModel_fieldOverrides_accessor_storage, _FormModel_errors_accessor_storage;
52
+ var _b, _c, _d;
53
+ let _instanceExtraInitializers = [];
54
+ let _value_decorators;
55
+ let _value_initializers = [];
56
+ let _value_extraInitializers = [];
57
+ let _fieldOverrides_decorators;
58
+ let _fieldOverrides_initializers = [];
59
+ let _fieldOverrides_extraInitializers = [];
60
+ let _errors_decorators;
61
+ let _errors_initializers = [];
62
+ let _errors_extraInitializers = [];
63
+ let _get_fields_decorators;
64
+ let _get_knownFields_decorators;
65
+ let _get_accessors_decorators;
66
+ return _a = class FormModel {
67
+ get value() { return __classPrivateFieldGet(this, _FormModel_value_accessor_storage, "f"); }
68
+ set value(value) { __classPrivateFieldSet(this, _FormModel_value_accessor_storage, value, "f"); }
69
+ get fieldOverrides() { return __classPrivateFieldGet(this, _FormModel_fieldOverrides_accessor_storage, "f"); }
70
+ set fieldOverrides(value) { __classPrivateFieldSet(this, _FormModel_fieldOverrides_accessor_storage, value, "f"); }
71
+ get errors() { return __classPrivateFieldGet(this, _FormModel_errors_accessor_storage, "f"); }
72
+ set errors(value) { __classPrivateFieldSet(this, _FormModel_errors_accessor_storage, value, "f"); }
73
+ constructor(type, value, adapters) {
74
+ Object.defineProperty(this, "type", {
75
+ enumerable: true,
76
+ configurable: true,
77
+ writable: true,
78
+ value: (__runInitializers(this, _instanceExtraInitializers), type)
79
+ });
80
+ Object.defineProperty(this, "adapters", {
81
+ enumerable: true,
82
+ configurable: true,
83
+ writable: true,
84
+ value: adapters
85
+ });
86
+ _FormModel_value_accessor_storage.set(this, __runInitializers(this, _value_initializers, void 0));
87
+ _FormModel_fieldOverrides_accessor_storage.set(this, (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _fieldOverrides_initializers, void 0)));
88
+ _FormModel_errors_accessor_storage.set(this, (__runInitializers(this, _fieldOverrides_extraInitializers), __runInitializers(this, _errors_initializers, {})));
89
+ Object.defineProperty(this, "flattenedTypeDefs", {
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true,
93
+ value: __runInitializers(this, _errors_extraInitializers)
94
+ });
95
+ this.value = mobxCopy(type, value);
96
+ this.flattenedTypeDefs = flattenTypesOfType(type);
97
+ // pre-populate field overrides for consistent behavior when default information is overwritten
98
+ // then returned to
99
+ const conversions = flattenValueTo(type, this.value, () => { }, (_t, value, _setter, typePath, valuePath) => {
100
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
+ const adapter = this.adapters[typePath];
102
+ if (adapter == null) {
103
+ return;
104
+ }
105
+ const { convert, revert, } = adapter;
106
+ if (revert == null) {
107
+ // no need to store a temporary value if the value cannot be written back
108
+ return;
109
+ }
110
+ return convert(value, valuePath, this.value);
111
+ });
112
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
113
+ this.fieldOverrides = map(conversions, function (_k, v) {
114
+ return v && [v.value];
115
+ });
116
+ }
117
+ get fields() {
118
+ return new Proxy(this.knownFields, {
119
+ get: (target, prop) => {
120
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
121
+ const field = target[prop];
122
+ if (field != null) {
123
+ return field;
124
+ }
125
+ if (typeof prop === 'string') {
126
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
127
+ return this.maybeSynthesizeFieldByValuePath(prop);
128
+ }
129
+ },
130
+ });
131
+ }
132
+ get knownFields() {
133
+ return flattenValueTo(this.type, this.value, () => { },
134
+ // TODO swap these to valuePath, typePath in flatten
135
+ (_t, _v, _setter, typePath, valuePath) => {
136
+ return this.synthesizeFieldByPaths(
137
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
138
+ valuePath,
139
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
140
+ typePath);
141
+ });
142
+ }
143
+ maybeSynthesizeFieldByValuePath(valuePath) {
144
+ let typePath;
145
+ try {
146
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
147
+ typePath = valuePathToTypePath(this.type,
148
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
149
+ valuePath, true);
150
+ }
151
+ catch (e) {
152
+ // TODO make jsonValuePathToTypePath return null in the event of an invalid
153
+ // value path instead of throwing an exception
154
+ // assume that the path was invalid
155
+ return;
156
+ }
157
+ return this.synthesizeFieldByPaths(valuePath, typePath);
158
+ }
159
+ synthesizeFieldByPaths(valuePath, typePath) {
160
+ const adapter = this.adapters[typePath];
161
+ if (adapter == null) {
162
+ // invalid path, which can happen
163
+ return;
164
+ }
165
+ const { convert, create, } = adapter;
166
+ const fieldOverride = this.fieldOverrides[valuePath];
167
+ const accessor = this.getAccessorForValuePath(valuePath);
168
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
169
+ const fieldTypeDef = this.flattenedTypeDefs[typePath];
170
+ const { value, required, readonly, } = convert(accessor != null
171
+ ? accessor.value
172
+ : fieldTypeDef != null
173
+ ? mobxCopy(fieldTypeDef,
174
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
175
+ create(valuePath, this.value))
176
+ // fake values can't be copied
177
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
178
+ : create(valuePath, this.value),
179
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
180
+ valuePath, this.value);
181
+ const error = this.errors[valuePath];
182
+ return {
183
+ value: fieldOverride != null ? fieldOverride[0] : value,
184
+ error,
185
+ readonly,
186
+ required,
187
+ };
188
+ }
189
+ getAccessorForValuePath(valuePath) {
190
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
191
+ return this.accessors[valuePath];
192
+ }
193
+ get accessors() {
194
+ return flattenAccessorsOfType(this.type, this.value, (value) => {
195
+ this.value = mobxCopy(this.type, value);
196
+ });
197
+ }
198
+ maybeGetAdapterForValuePath(valuePath) {
199
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
200
+ const typePath = valuePathToTypePath(this.type, valuePath, true);
201
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
202
+ return this.adapters[typePath];
203
+ }
204
+ getAdapterForValuePath(valuePath) {
205
+ return assertExistsAndReturn(this.maybeGetAdapterForValuePath(valuePath), 'expected adapter to be defined {}', valuePath);
206
+ }
207
+ typePath(valuePath) {
208
+ return valuePathToTypePath(this.type, valuePath, true);
209
+ }
210
+ setFieldValueAndValidate(valuePath, value) {
211
+ return this.internalSetFieldValue(valuePath, value, true);
212
+ }
213
+ setFieldValue(valuePath, value) {
214
+ return this.internalSetFieldValue(valuePath, value, false);
215
+ }
216
+ addListItem(valuePath,
217
+ // TODO can this type be simplified?
218
+ elementValue = null, index) {
219
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
220
+ const listValuePath = valuePath;
221
+ const accessor = this.accessors[valuePath];
222
+ const listTypePath = this.typePath(valuePath);
223
+ const definedIndex = index !== null && index !== void 0 ? index : accessor.value.length;
224
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
225
+ const elementTypePath = `${listTypePath}.*`;
226
+ const elementAdapter = assertExistsAndReturn(this.adapters[elementTypePath], 'no adapter specified for list {} ({})', elementTypePath, valuePath);
227
+ // TODO validation on new elements
228
+ const element = elementValue != null
229
+ ? elementValue[0]
230
+ : elementAdapter.create(
231
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
232
+ elementTypePath, this.value);
233
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
234
+ const originalList = accessor.value;
235
+ const newList = [
236
+ ...originalList.slice(0, definedIndex),
237
+ element,
238
+ ...originalList.slice(definedIndex),
239
+ ];
240
+ // shuffle the overrides around to account for new indices
241
+ // to so this we need to sort the array indices in descending order
242
+ const targetPaths = Object.keys(this.fieldOverrides).filter(function (v) {
243
+ return v.startsWith(`${listValuePath}.`);
244
+ }).map(function (v) {
245
+ const parts = v.substring(listValuePath.length + 1).split('.');
246
+ const index = parseInt(parts[0]);
247
+ return [
248
+ index,
249
+ parts.slice(1),
250
+ ];
251
+ }).filter(function ([index]) {
252
+ return index >= definedIndex;
253
+ }).sort(function ([a], [b]) {
254
+ // descending
255
+ return b - a;
256
+ });
257
+ runInAction(() => {
258
+ targetPaths.forEach(([index, postfix,]) => {
259
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
260
+ const fromJsonPath = [
261
+ listValuePath,
262
+ `${index}`,
263
+ ...postfix,
264
+ ].join('.');
265
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
266
+ const toJsonPath = [
267
+ listValuePath,
268
+ `${index + 1}`,
269
+ ...postfix,
270
+ ].join('.');
271
+ const fieldOverride = this.fieldOverrides[fromJsonPath];
272
+ delete this.fieldOverrides[fromJsonPath];
273
+ this.fieldOverrides[toJsonPath] = fieldOverride;
274
+ const error = this.errors[fromJsonPath];
275
+ delete this.errors[fromJsonPath];
276
+ this.errors[toJsonPath] = error;
277
+ });
278
+ accessor.set(newList);
279
+ // delete any value overrides so the new list isn't shadowed
280
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
281
+ delete this.fieldOverrides[listValuePath];
282
+ });
283
+ }
284
+ removeListItem(...elementValuePaths) {
285
+ // sort and reverse so we delete last to first so indices of sequential deletions are preserved
286
+ const orderedElementValuePaths = elementValuePaths.toSorted().reverse();
287
+ runInAction(() => {
288
+ orderedElementValuePaths.forEach(elementValuePath => {
289
+ const [listValuePath, elementIndexString,] = assertExistsAndReturn(jsonPathPop(elementValuePath), 'expected a path with two or more segments {}', elementValuePath);
290
+ const accessor = this.accessors[listValuePath];
291
+ const elementIndex = checkValidNumber(parseInt(elementIndexString), 'unexpected index {} ({})', elementIndexString, elementValuePath);
292
+ const newList = [...accessor.value];
293
+ assertState(elementIndex >= 0 && elementIndex < newList.length, 'invalid index from path {} ({})', elementIndex, elementValuePath);
294
+ newList.splice(elementIndex, 1);
295
+ // shuffle the overrides around to account for new indices
296
+ // to so this we need to sort the array indices in descending order
297
+ const targetPaths = Object.keys(this.fieldOverrides).filter(function (v) {
298
+ return v.startsWith(`${listValuePath}.`);
299
+ }).map(function (v) {
300
+ const parts = v.substring(listValuePath.length + 1).split('.');
301
+ const index = parseInt(parts[0]);
302
+ return [
303
+ index,
304
+ parts.slice(1),
305
+ ];
306
+ }).filter(function ([index]) {
307
+ return index > elementIndex;
308
+ }).sort(function ([a], [b]) {
309
+ // descending
310
+ return a - b;
311
+ });
312
+ targetPaths.forEach(([index, postfix,]) => {
313
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
314
+ const fromJsonPath = [
315
+ listValuePath,
316
+ `${index}`,
317
+ ...postfix,
318
+ ].join('.');
319
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
320
+ const toJsonPath = [
321
+ listValuePath,
322
+ `${index - 1}`,
323
+ ...postfix,
324
+ ].join('.');
325
+ const fieldOverride = this.fieldOverrides[fromJsonPath];
326
+ delete this.fieldOverrides[fromJsonPath];
327
+ this.fieldOverrides[toJsonPath] = fieldOverride;
328
+ const error = this.errors[fromJsonPath];
329
+ delete this.errors[fromJsonPath];
330
+ this.errors[toJsonPath] = error;
331
+ });
332
+ accessor.set(newList);
333
+ // delete any value overrides so the new list isn't shadowed
334
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
335
+ delete this.fieldOverrides[listValuePath];
336
+ });
337
+ });
338
+ }
339
+ internalSetFieldValue(valuePath, value, displayValidation) {
340
+ const { revert } = this.getAdapterForValuePath(valuePath);
341
+ assertExists(revert, 'setting value not supported {}', valuePath);
342
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
343
+ const conversion = revert(value, valuePath, this.value);
344
+ const accessor = this.getAccessorForValuePath(valuePath);
345
+ return runInAction(() => {
346
+ this.fieldOverrides[valuePath] = [value];
347
+ switch (conversion.type) {
348
+ case UnreliableFieldConversionType.Failure:
349
+ if (displayValidation) {
350
+ this.errors[valuePath] = conversion.error;
351
+ }
352
+ if (conversion.value != null && accessor != null) {
353
+ accessor.set(conversion.value[0]);
354
+ }
355
+ return false;
356
+ case UnreliableFieldConversionType.Success:
357
+ delete this.errors[valuePath];
358
+ accessor === null || accessor === void 0 ? void 0 : accessor.set(conversion.value);
359
+ return true;
360
+ default:
361
+ throw new UnreachableError(conversion);
362
+ }
363
+ });
364
+ }
365
+ clearFieldError(valuePath) {
366
+ const fieldOverride = this.fieldOverrides[valuePath];
367
+ if (fieldOverride != null) {
368
+ runInAction(() => {
369
+ delete this.errors[valuePath];
370
+ });
371
+ }
372
+ }
373
+ clearFieldValue(valuePath) {
374
+ const typePath = this.typePath(valuePath);
375
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
376
+ const adapter = this.adapters[typePath];
377
+ if (adapter == null) {
378
+ return;
379
+ }
380
+ const { convert, create, } = adapter;
381
+ const value = create(valuePath, this.value);
382
+ const { value: displayValue, } = convert(value, valuePath, this.value);
383
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
384
+ const key = valuePath;
385
+ runInAction(() => {
386
+ this.fieldOverrides[key] = [displayValue];
387
+ });
388
+ }
389
+ clearAll(value) {
390
+ runInAction(() => {
391
+ this.errors = {};
392
+ // TODO this isn't correct, should reload from value
393
+ this.fieldOverrides = {};
394
+ this.value = mobxCopy(this.type, value);
395
+ });
396
+ }
397
+ isValuePathActive(valuePath) {
398
+ const values = flattenValuesOfType(this.type, this.value);
399
+ const keys = new Set(Object.keys(values));
400
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
401
+ return keys.has(valuePath);
402
+ }
403
+ validateField(valuePath, ignoreDefaultValue = false) {
404
+ const { convert, revert, create, } = this.getAdapterForValuePath(valuePath);
405
+ const fieldOverride = this.fieldOverrides[valuePath];
406
+ const accessor = this.getAccessorForValuePath(valuePath);
407
+ const { value: storedValue, } = convert(accessor != null
408
+ ? accessor.value
409
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
410
+ : create(valuePath, this.value),
411
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
412
+ valuePath, this.value);
413
+ const value = fieldOverride != null
414
+ ? fieldOverride[0]
415
+ : storedValue;
416
+ const dirty = storedValue !== value;
417
+ assertExists(revert, 'changing field directly not supported {}', valuePath);
418
+ if (ignoreDefaultValue) {
419
+ const { value: defaultDisplayValue, } = convert(create(valuePath, this.value), valuePath, this.value);
420
+ if (defaultDisplayValue === value) {
421
+ return true;
422
+ }
423
+ }
424
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
425
+ const conversion = revert(value, valuePath, this.value);
426
+ return runInAction(() => {
427
+ switch (conversion.type) {
428
+ case UnreliableFieldConversionType.Failure:
429
+ this.errors[valuePath] = conversion.error;
430
+ if (conversion.value != null && accessor != null && dirty) {
431
+ accessor.set(conversion.value[0]);
432
+ }
433
+ return false;
434
+ case UnreliableFieldConversionType.Success:
435
+ delete this.errors[valuePath];
436
+ if (accessor != null && dirty) {
437
+ accessor.set(conversion.value);
438
+ }
439
+ return true;
440
+ default:
441
+ throw new UnreachableError(conversion);
442
+ }
443
+ });
444
+ }
445
+ validateAll() {
446
+ // sort keys shortest to longest so parent changes don't overwrite child changes
447
+ const accessors = toArray(this.accessors).toSorted(function ([a], [b]) {
448
+ return a.length - b.length;
449
+ });
450
+ return runInAction(() => {
451
+ return accessors.reduce((success, [valuePath, accessor,]) => {
452
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
453
+ const adapterPath = valuePath;
454
+ const adapter = this.maybeGetAdapterForValuePath(adapterPath);
455
+ if (adapter == null) {
456
+ // no adapter == there should be nothing specified for this field
457
+ return success;
458
+ }
459
+ const { convert, revert, } = adapter;
460
+ if (revert == null) {
461
+ // no convert method means this field is immutable
462
+ return success;
463
+ }
464
+ const fieldOverride = this.fieldOverrides[adapterPath];
465
+ const { value: storedValue, } = convert(accessor.value, valuePath, this.value);
466
+ const value = fieldOverride != null
467
+ ? fieldOverride[0]
468
+ : storedValue;
469
+ // TODO more nuanced comparison
470
+ const dirty = fieldOverride != null && fieldOverride[0] !== storedValue;
471
+ const conversion = revert(value, valuePath, this.value);
472
+ switch (conversion.type) {
473
+ case UnreliableFieldConversionType.Failure:
474
+ this.errors[adapterPath] = conversion.error;
475
+ if (conversion.value != null && dirty) {
476
+ accessor.set(conversion.value[0]);
477
+ }
478
+ return false;
479
+ case UnreliableFieldConversionType.Success:
480
+ if (dirty) {
481
+ accessor.set(conversion.value);
482
+ }
483
+ delete this.errors[adapterPath];
484
+ return success;
485
+ default:
486
+ throw new UnreachableError(conversion);
487
+ }
488
+ }, true);
489
+ });
490
+ }
491
+ },
492
+ _FormModel_value_accessor_storage = new WeakMap(),
493
+ _FormModel_fieldOverrides_accessor_storage = new WeakMap(),
494
+ _FormModel_errors_accessor_storage = new WeakMap(),
495
+ (() => {
496
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
497
+ _value_decorators = [(_b = observable).ref.bind(_b)];
498
+ _fieldOverrides_decorators = [(_c = observable).shallow.bind(_c)];
499
+ _errors_decorators = [(_d = observable).shallow.bind(_d)];
500
+ _get_fields_decorators = [computed];
501
+ _get_knownFields_decorators = [computed];
502
+ _get_accessors_decorators = [computed];
503
+ __esDecorate(_a, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
504
+ __esDecorate(_a, null, _fieldOverrides_decorators, { kind: "accessor", name: "fieldOverrides", static: false, private: false, access: { has: obj => "fieldOverrides" in obj, get: obj => obj.fieldOverrides, set: (obj, value) => { obj.fieldOverrides = value; } }, metadata: _metadata }, _fieldOverrides_initializers, _fieldOverrides_extraInitializers);
505
+ __esDecorate(_a, null, _errors_decorators, { kind: "accessor", name: "errors", static: false, private: false, access: { has: obj => "errors" in obj, get: obj => obj.errors, set: (obj, value) => { obj.errors = value; } }, metadata: _metadata }, _errors_initializers, _errors_extraInitializers);
506
+ __esDecorate(_a, null, _get_fields_decorators, { kind: "getter", name: "fields", static: false, private: false, access: { has: obj => "fields" in obj, get: obj => obj.fields }, metadata: _metadata }, null, _instanceExtraInitializers);
507
+ __esDecorate(_a, null, _get_knownFields_decorators, { kind: "getter", name: "knownFields", static: false, private: false, access: { has: obj => "knownFields" in obj, get: obj => obj.knownFields }, metadata: _metadata }, null, _instanceExtraInitializers);
508
+ __esDecorate(_a, null, _get_accessors_decorators, { kind: "getter", name: "accessors", static: false, private: false, access: { has: obj => "accessors" in obj, get: obj => obj.accessors }, metadata: _metadata }, null, _instanceExtraInitializers);
509
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
510
+ })(),
511
+ _a;
512
+ })();
513
+ export { FormModel };
@@ -1,30 +1,11 @@
1
1
  import { type ReadonlyTypeOfType, type ValueOfType } from '@strictly/define';
2
- import { type FieldsViewProps } from 'core/props';
3
- import { type ComponentType } from 'react';
4
- import { type UnsafePartialComponent } from 'util/partial';
5
- import { type FormPresenter } from './form_presenter';
6
- import { type FormFieldsOfPresenter, type ValuePathsOfPresenter } from './types';
7
- type ValueOfPresenter<P extends FormPresenter<any, any, any, any>> = P extends FormPresenter<infer T, any, any, any> ? ValueOfType<ReadonlyTypeOfType<T>> : never;
8
- type ModelOfPresenter<P extends FormPresenter<any, any, any, any>> = ReturnType<P['createModel']>;
9
- export declare function useDefaultMobxFormHooks<P extends FormPresenter<any, any, any, any>, C extends ComponentType<FieldsViewProps<F>>, F extends FormFieldsOfPresenter<P> = FormFieldsOfPresenter<P>>(presenter: P, value: ValueOfPresenter<P>, options?: {
10
- onValidFieldSubmit?: <Path extends ValuePathsOfPresenter<P>>(model: ModelOfPresenter<P>, valuePath: Path) => void;
11
- onValidFormSubmit?: (model: ModelOfPresenter<P>, value: ValueOfPresenter<P>) => void;
2
+ import { type FormModel } from './form_model';
3
+ import { type FormFieldsOfModel, type ValuePathsOfModel } from './types';
4
+ type ValueOfModel<M extends FormModel<any, any, any, any>> = M extends FormModel<infer T, any, any, any> ? ValueOfType<ReadonlyTypeOfType<T>> : never;
5
+ export declare function useDefaultMobxFormHooks<M extends FormModel<any, any, any, any>, F extends FormFieldsOfModel<M> = FormFieldsOfModel<M>>(model: M, { onValidFieldSubmit, onValidFormSubmit, }?: {
6
+ onValidFieldSubmit?: <Path extends ValuePathsOfModel<M>>(valuePath: Path) => void;
7
+ onValidFormSubmit?: (value: ValueOfModel<M>) => void;
12
8
  }): {
13
- model: ModelOfPresenter<P>;
14
- FormFields?: UnsafePartialComponent<C, FieldsViewProps<F>>;
15
- onFormSubmit: () => void;
16
- onFieldValueChange<K extends keyof F>(this: void, key: K, value: F[K]['value']): void;
17
- onFieldFocus?(this: void, key: keyof F): void;
18
- onFieldBlur?(this: void, key: keyof F): void;
19
- onFieldSubmit?(this: void, key: keyof F): boolean | void;
20
- };
21
- export declare function useDefaultMobxFormHooks<P extends FormPresenter<any, any, any, any>, C extends ComponentType<FieldsViewProps<F>>, F extends FormFieldsOfPresenter<P> = FormFieldsOfPresenter<P>>(presenter: P, value: ValueOfPresenter<P>, options: {
22
- onValidFieldSubmit?: <Path extends ValuePathsOfPresenter<P>>(model: ModelOfPresenter<P>, valuePath: Path) => void;
23
- onValidFormSubmit?: (model: ModelOfPresenter<P>, value: ValueOfPresenter<P>) => void;
24
- FormFieldsView: C;
25
- }): {
26
- model: ModelOfPresenter<P>;
27
- FormFields: UnsafePartialComponent<C, FieldsViewProps<F>>;
28
9
  onFormSubmit: () => void;
29
10
  onFieldValueChange<K extends keyof F>(this: void, key: K, value: F[K]['value']): void;
30
11
  onFieldFocus?(this: void, key: keyof F): void;