@strictly/react-form 0.0.16 → 0.0.18

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.
@@ -7,12 +7,12 @@ $ tsup
7
7
  CLI Target: es6
8
8
  CJS Build start
9
9
  ESM Build start
10
- ESM dist/index.js 57.40 KB
11
- ESM ⚡️ Build success in 138ms
12
- CJS dist/index.cjs 61.39 KB
13
- CJS ⚡️ Build success in 139ms
10
+ ESM dist/index.js 58.27 KB
11
+ ESM ⚡️ Build success in 136ms
12
+ CJS dist/index.cjs 62.28 KB
13
+ CJS ⚡️ Build success in 137ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 9840ms
16
- DTS dist/index.d.cts 37.86 KB
17
- DTS dist/index.d.ts 37.86 KB
18
- Done in 10.97s.
15
+ DTS ⚡️ Build success in 10098ms
16
+ DTS dist/index.d.cts 38.06 KB
17
+ DTS dist/index.d.ts 38.06 KB
18
+ Done in 11.26s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 7.62s.
3
+ Done in 7.96s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ json -f package.json -f package.exports.json --merge > package.release.json
3
- Done in 0.11s.
3
+ Done in 0.14s.
@@ -118,6 +118,8 @@ export type ContextOf<TypePathsToAdapters extends Partial<Readonly<Record<string
118
118
  | {}
119
119
  >
120
120
 
121
+ export type FormMode = 'edit' | 'create'
122
+
121
123
  export abstract class FormModel<
122
124
  T extends Type,
123
125
  ValueToTypePaths extends Readonly<Record<string, string>>,
@@ -142,10 +144,11 @@ export abstract class FormModel<
142
144
 
143
145
  constructor(
144
146
  readonly type: T,
145
- value: ValueOfType<ReadonlyTypeOfType<T>>,
147
+ private readonly originalValue: ValueOfType<ReadonlyTypeOfType<T>>,
146
148
  protected readonly adapters: TypePathsToAdapters,
149
+ protected readonly mode: FormMode,
147
150
  ) {
148
- this.value = mobxCopy(type, value)
151
+ this.value = mobxCopy(type, originalValue)
149
152
  this.flattenedTypeDefs = flattenTypesOfType(type)
150
153
  // pre-populate field overrides for consistent behavior when default information is overwritten
151
154
  // then returned to
@@ -161,7 +164,7 @@ export abstract class FormModel<
161
164
  valuePath,
162
165
  ): AnnotatedFieldConversion<FieldOverride> | undefined => {
163
166
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
164
- const contextValue = this.toContext(value, valuePath as keyof ValuePathsToAdapters)
167
+ const contextValue = this.toContext(originalValue, valuePath as keyof ValuePathsToAdapters)
165
168
 
166
169
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
167
170
  const adapter = this.adapters[typePath as keyof TypePathsToAdapters]
@@ -191,6 +194,17 @@ export abstract class FormModel<
191
194
  valuePath: keyof ValuePathsToAdapters,
192
195
  ): ContextType
193
196
 
197
+ get forceMutableFields() {
198
+ switch (this.mode) {
199
+ case 'create':
200
+ return true
201
+ case 'edit':
202
+ return false
203
+ default:
204
+ return this.mode satisfies never
205
+ }
206
+ }
207
+
194
208
  @computed
195
209
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>> {
196
210
  return new Proxy<SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>>(
@@ -288,7 +302,7 @@ export abstract class FormModel<
288
302
  return {
289
303
  value: fieldOverride != null ? fieldOverride[0] : value,
290
304
  error,
291
- readonly,
305
+ readonly: readonly && !this.forceMutableFields,
292
306
  required,
293
307
  }
294
308
  }
@@ -646,11 +660,14 @@ export abstract class FormModel<
646
660
  })
647
661
  }
648
662
 
649
- validateAll(): boolean {
663
+ validateAll(force: boolean = this.mode === 'create'): boolean {
650
664
  // sort keys shortest to longest so parent changes don't overwrite child changes
651
665
  const accessors = toArray(this.accessors).toSorted(function ([a], [b]) {
652
666
  return a.length - b.length
653
667
  })
668
+
669
+ const flattenedOriginalValues = flattenValuesOfType(this.type, this.originalValue)
670
+
654
671
  return runInAction(() => {
655
672
  return accessors.reduce(
656
673
  (
@@ -684,26 +701,36 @@ export abstract class FormModel<
684
701
  const value = fieldOverride != null
685
702
  ? fieldOverride[0]
686
703
  : storedValue
687
- // TODO more nuanced comparison
704
+ // TODO customizable comparisons
688
705
  const dirty = fieldOverride != null && fieldOverride[0] !== storedValue
689
-
690
- const conversion = revert(value, valuePath, context)
691
- switch (conversion.type) {
692
- case UnreliableFieldConversionType.Failure:
693
- this.errors[adapterPath] = conversion.error
694
- if (conversion.value != null && dirty) {
695
- accessor.set(conversion.value[0])
696
- }
697
- return false
698
- case UnreliableFieldConversionType.Success:
699
- if (dirty) {
700
- accessor.set(conversion.value)
701
- }
702
- delete this.errors[adapterPath]
703
- return success
704
- default:
705
- throw new UnreachableError(conversion)
706
+ const needsValidation = force
707
+ || !(valuePath in flattenedOriginalValues)
708
+ || storedValue !== convert(
709
+ flattenedOriginalValues[valuePath],
710
+ valuePath,
711
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
712
+ this.toContext(this.originalValue, valuePath as keyof ValuePathsToAdapters),
713
+ ).value
714
+ if (needsValidation) {
715
+ const conversion = revert(value, valuePath, context)
716
+ switch (conversion.type) {
717
+ case UnreliableFieldConversionType.Failure:
718
+ this.errors[adapterPath] = conversion.error
719
+ if (conversion.value != null && dirty) {
720
+ accessor.set(conversion.value[0])
721
+ }
722
+ return false
723
+ case UnreliableFieldConversionType.Success:
724
+ if (dirty) {
725
+ accessor.set(conversion.value)
726
+ }
727
+ delete this.errors[adapterPath]
728
+ return success
729
+ default:
730
+ throw new UnreachableError(conversion)
731
+ }
706
732
  }
733
+ return success
707
734
  },
708
735
  true,
709
736
  )
@@ -2,6 +2,7 @@ import { expectDefinedAndReturn } from '@strictly/base'
2
2
  import {
3
3
  booleanType,
4
4
  type FlattenedValuesOfType,
5
+ flattenValidatorsOfValidatingType,
5
6
  list,
6
7
  nullType,
7
8
  numberType,
@@ -25,6 +26,7 @@ import {
25
26
  FormModel,
26
27
  type ValuePathsToAdaptersOf,
27
28
  } from 'core/mobx/form_model'
29
+ import { mergeAdaptersWithValidators } from 'core/mobx/merge_field_adapters_with_validators'
28
30
  import { IntegerToStringConverter } from 'field_converters/integer_to_string_converter'
29
31
  import { NullableToBooleanConverter } from 'field_converters/nullable_to_boolean_converter'
30
32
  import { SelectDiscriminatedUnionConverter } from 'field_converters/select_value_type_converter'
@@ -203,6 +205,7 @@ describe('all', function () {
203
205
  typeDef,
204
206
  originalValue,
205
207
  adapters,
208
+ 'create',
206
209
  )
207
210
  })
208
211
 
@@ -263,6 +266,7 @@ describe('all', function () {
263
266
  typeDef,
264
267
  originalValue,
265
268
  adapters,
269
+ 'create',
266
270
  )
267
271
  })
268
272
 
@@ -304,6 +308,7 @@ describe('all', function () {
304
308
  typeDef,
305
309
  value,
306
310
  adapters,
311
+ 'create',
307
312
  )
308
313
  })
309
314
 
@@ -382,6 +387,7 @@ describe('all', function () {
382
387
  typeDef,
383
388
  value,
384
389
  converters,
390
+ 'create',
385
391
  )
386
392
  })
387
393
 
@@ -452,6 +458,7 @@ describe('all', function () {
452
458
  typeDef,
453
459
  value,
454
460
  converters,
461
+ 'create',
455
462
  )
456
463
  })
457
464
 
@@ -517,6 +524,7 @@ describe('all', function () {
517
524
  typeDef,
518
525
  originalValue,
519
526
  adapters,
527
+ 'create',
520
528
  )
521
529
  })
522
530
 
@@ -643,6 +651,7 @@ describe('all', function () {
643
651
  typeDef,
644
652
  originalValue,
645
653
  converters,
654
+ 'create',
646
655
  )
647
656
  })
648
657
 
@@ -993,6 +1002,7 @@ describe('all', function () {
993
1002
  type,
994
1003
  originalValue,
995
1004
  adapters,
1005
+ 'create',
996
1006
  )
997
1007
  })
998
1008
 
@@ -1061,6 +1071,7 @@ describe('all', function () {
1061
1071
  a: 1,
1062
1072
  },
1063
1073
  adapters,
1074
+ 'create',
1064
1075
  )
1065
1076
  it.each([
1066
1077
  [
@@ -1093,6 +1104,7 @@ describe('all', function () {
1093
1104
  b: false,
1094
1105
  },
1095
1106
  adapters,
1107
+ 'create',
1096
1108
  )
1097
1109
  it.each([
1098
1110
  [
@@ -1142,6 +1154,7 @@ describe('all', function () {
1142
1154
  typeDef,
1143
1155
  originalValue,
1144
1156
  converters,
1157
+ 'create',
1145
1158
  )
1146
1159
  })
1147
1160
 
@@ -1167,5 +1180,95 @@ describe('all', function () {
1167
1180
  })
1168
1181
  })
1169
1182
  })
1183
+
1184
+ describe('interaction with create and edit modes', () => {
1185
+ const typeDef = object().readonlyField('n', numberType.enforce(n => n < 10 ? 'err' : null))
1186
+ const adapters = mergeAdaptersWithValidators(
1187
+ {
1188
+ $: identityAdapter({ n: 0 }),
1189
+ '$.n': integerToStringAdapter,
1190
+ } as const,
1191
+ flattenValidatorsOfValidatingType(typeDef),
1192
+ )
1193
+ type JsonPaths = {
1194
+ $: '$',
1195
+ '$.n': '$.n',
1196
+ }
1197
+ let originalValue: ValueOfType<typeof typeDef>
1198
+ beforeEach(() => {
1199
+ originalValue = {
1200
+ n: 1,
1201
+ }
1202
+ })
1203
+ describe('create mode', () => {
1204
+ let model: FormModel<
1205
+ typeof typeDef,
1206
+ JsonPaths,
1207
+ typeof adapters
1208
+ >
1209
+ beforeEach(() => {
1210
+ model = new TestFormModel<
1211
+ typeof typeDef,
1212
+ JsonPaths,
1213
+ typeof adapters
1214
+ >(
1215
+ typeDef,
1216
+ originalValue,
1217
+ adapters,
1218
+ 'create',
1219
+ )
1220
+ })
1221
+
1222
+ it('makes the field editable', () => {
1223
+ expect(model.fields['$.n'].readonly).toBeFalsy()
1224
+ })
1225
+
1226
+ it('fails validation', () => {
1227
+ expect(model.validateAll()).toBeFalsy()
1228
+ })
1229
+
1230
+ it('passes validation with valid data', () => {
1231
+ model.setFieldValue('$.n', '10')
1232
+ expect(model.validateAll()).toBeTruthy()
1233
+ })
1234
+ })
1235
+ describe('edit model', () => {
1236
+ let model: FormModel<
1237
+ typeof typeDef,
1238
+ JsonPaths,
1239
+ typeof adapters
1240
+ >
1241
+ beforeEach(function () {
1242
+ model = new TestFormModel<
1243
+ typeof typeDef,
1244
+ JsonPaths,
1245
+ typeof adapters
1246
+ >(
1247
+ typeDef,
1248
+ originalValue,
1249
+ adapters,
1250
+ 'edit',
1251
+ )
1252
+ })
1253
+
1254
+ it('respects the field being readonly', () => {
1255
+ expect(model.fields['$.n'].readonly).toBeTruthy()
1256
+ })
1257
+
1258
+ it('validates successfully with clean, but invalid data', () => {
1259
+ expect(model.validateAll()).toBeTruthy()
1260
+ })
1261
+
1262
+ it('fails validation with invalid, dirty data', () => {
1263
+ model.setFieldValue('$.n', '2')
1264
+ expect(model.validateAll()).toBeFalsy()
1265
+ })
1266
+
1267
+ it('passes validation with valid, dirty data', () => {
1268
+ model.setFieldValue('$.n', '10')
1269
+ expect(model.validateAll()).toBeTruthy()
1270
+ })
1271
+ })
1272
+ })
1170
1273
  })
1171
1274
  })
package/dist/index.cjs CHANGED
@@ -359,15 +359,17 @@ var import_mobx = require("mobx");
359
359
  var _accessors_dec, _knownFields_dec, _fields_dec, _errors_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errors;
360
360
  _value_dec = [import_mobx.observable.ref], _fieldOverrides_dec = [import_mobx.observable.shallow], _errors_dec = [import_mobx.observable.shallow], _fields_dec = [import_mobx.computed], _knownFields_dec = [import_mobx.computed], _accessors_dec = [import_mobx.computed];
361
361
  var FormModel = class {
362
- constructor(type, value, adapters) {
362
+ constructor(type, originalValue, adapters, mode) {
363
363
  this.type = type;
364
+ this.originalValue = originalValue;
364
365
  this.adapters = adapters;
366
+ this.mode = mode;
365
367
  __runInitializers(_init, 5, this);
366
368
  __privateAdd(this, _value, __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
367
369
  __privateAdd(this, _fieldOverrides, __runInitializers(_init, 12, this)), __runInitializers(_init, 15, this);
368
370
  __privateAdd(this, _errors, __runInitializers(_init, 16, this, {})), __runInitializers(_init, 19, this);
369
371
  __publicField(this, "flattenedTypeDefs");
370
- this.value = (0, import_define.mobxCopy)(type, value);
372
+ this.value = (0, import_define.mobxCopy)(type, originalValue);
371
373
  this.flattenedTypeDefs = (0, import_define.flattenTypesOfType)(type);
372
374
  const conversions = (0, import_define.flattenValueTo)(
373
375
  type,
@@ -375,7 +377,7 @@ var FormModel = class {
375
377
  () => {
376
378
  },
377
379
  (_t, fieldValue, _setter, typePath, valuePath) => {
378
- const contextValue = this.toContext(value, valuePath);
380
+ const contextValue = this.toContext(originalValue, valuePath);
379
381
  const adapter2 = this.adapters[typePath];
380
382
  if (adapter2 == null) {
381
383
  return;
@@ -394,6 +396,16 @@ var FormModel = class {
394
396
  return v && [v.value];
395
397
  });
396
398
  }
399
+ get forceMutableFields() {
400
+ switch (this.mode) {
401
+ case "create":
402
+ return true;
403
+ case "edit":
404
+ return false;
405
+ default:
406
+ return this.mode;
407
+ }
408
+ }
397
409
  get fields() {
398
410
  return new Proxy(
399
411
  this.knownFields,
@@ -472,7 +484,7 @@ var FormModel = class {
472
484
  return {
473
485
  value: fieldOverride != null ? fieldOverride[0] : value,
474
486
  error,
475
- readonly,
487
+ readonly: readonly && !this.forceMutableFields,
476
488
  required
477
489
  };
478
490
  }
@@ -754,10 +766,11 @@ var FormModel = class {
754
766
  }
755
767
  });
756
768
  }
757
- validateAll() {
769
+ validateAll(force = this.mode === "create") {
758
770
  const accessors = (0, import_base2.toArray)(this.accessors).toSorted(function([a], [b]) {
759
771
  return a.length - b.length;
760
772
  });
773
+ const flattenedOriginalValues = (0, import_define.flattenValuesOfType)(this.type, this.originalValue);
761
774
  return (0, import_mobx.runInAction)(() => {
762
775
  return accessors.reduce(
763
776
  (success, [
@@ -783,23 +796,32 @@ var FormModel = class {
783
796
  } = convert(accessor.value, valuePath, context);
784
797
  const value = fieldOverride != null ? fieldOverride[0] : storedValue;
785
798
  const dirty = fieldOverride != null && fieldOverride[0] !== storedValue;
786
- const conversion = revert(value, valuePath, context);
787
- switch (conversion.type) {
788
- case 1 /* Failure */:
789
- this.errors[adapterPath] = conversion.error;
790
- if (conversion.value != null && dirty) {
791
- accessor.set(conversion.value[0]);
792
- }
793
- return false;
794
- case 0 /* Success */:
795
- if (dirty) {
796
- accessor.set(conversion.value);
797
- }
798
- delete this.errors[adapterPath];
799
- return success;
800
- default:
801
- throw new import_base2.UnreachableError(conversion);
799
+ const needsValidation = force || !(valuePath in flattenedOriginalValues) || storedValue !== convert(
800
+ flattenedOriginalValues[valuePath],
801
+ valuePath,
802
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
803
+ this.toContext(this.originalValue, valuePath)
804
+ ).value;
805
+ if (needsValidation) {
806
+ const conversion = revert(value, valuePath, context);
807
+ switch (conversion.type) {
808
+ case 1 /* Failure */:
809
+ this.errors[adapterPath] = conversion.error;
810
+ if (conversion.value != null && dirty) {
811
+ accessor.set(conversion.value[0]);
812
+ }
813
+ return false;
814
+ case 0 /* Success */:
815
+ if (dirty) {
816
+ accessor.set(conversion.value);
817
+ }
818
+ delete this.errors[adapterPath];
819
+ return success;
820
+ default:
821
+ throw new import_base2.UnreachableError(conversion);
822
+ }
802
823
  }
824
+ return success;
803
825
  },
804
826
  true
805
827
  );
@@ -1753,7 +1775,7 @@ function useMantineFormFields({
1753
1775
  function() {
1754
1776
  return new MantineFormImpl(fields);
1755
1777
  },
1756
- // handled separately below
1778
+ // fields handled separately below
1757
1779
  // eslint-disable-next-line react-hooks/exhaustive-deps
1758
1780
  []
1759
1781
  );
package/dist/index.d.cts CHANGED
@@ -121,15 +121,19 @@ type ValuePathsToAdaptersOf<TypePathsToAdapters extends Partial<Readonly<Record<
121
121
  type ContextOf<TypePathsToAdapters extends Partial<Readonly<Record<string, FieldAdapter>>>> = UnionToIntersection<{
122
122
  readonly [K in keyof TypePathsToAdapters]: TypePathsToAdapters[K] extends undefined ? undefined : unknown extends ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>> ? never : ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>>;
123
123
  }[keyof TypePathsToAdapters] | {}>;
124
+ type FormMode = 'edit' | 'create';
124
125
  declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ContextType>, ContextType = ContextOf<TypePathsToAdapters>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
125
126
  readonly type: T;
127
+ private readonly originalValue;
126
128
  protected readonly adapters: TypePathsToAdapters;
129
+ protected readonly mode: FormMode;
127
130
  accessor value: MobxValueOfType<T>;
128
131
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
129
132
  accessor errors: FlattenedErrors<ValuePathsToAdapters>;
130
133
  private readonly flattenedTypeDefs;
131
- constructor(type: T, value: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters);
134
+ constructor(type: T, originalValue: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters, mode: FormMode);
132
135
  protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>, valuePath: keyof ValuePathsToAdapters): ContextType;
136
+ get forceMutableFields(): boolean;
133
137
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>;
134
138
  private get knownFields();
135
139
  private maybeSynthesizeFieldByValuePath;
@@ -149,7 +153,7 @@ declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readon
149
153
  clearAll(value: ValueOfType<T>): void;
150
154
  isValuePathActive<K extends keyof ValuePathsToAdapters>(valuePath: K): boolean;
151
155
  validateField<K extends keyof ValuePathsToAdapters>(valuePath: K, ignoreDefaultValue?: boolean): boolean;
152
- validateAll(): boolean;
156
+ validateAll(force?: boolean): boolean;
153
157
  }
154
158
 
155
159
  /**
@@ -445,4 +449,4 @@ declare function mergeValidators<Validators1 extends Partial<Readonly<Record<Key
445
449
 
446
450
  declare function Empty(): null;
447
451
 
448
- export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormFieldsOfModel, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, type ToValueOfModelValuePath, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, type ValuePathOfFieldAdapter, type ValuePathsOfModel, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };
452
+ export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormFieldsOfModel, type FormMode, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, type ToValueOfModelValuePath, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, type ValuePathOfFieldAdapter, type ValuePathsOfModel, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };
package/dist/index.d.ts CHANGED
@@ -121,15 +121,19 @@ type ValuePathsToAdaptersOf<TypePathsToAdapters extends Partial<Readonly<Record<
121
121
  type ContextOf<TypePathsToAdapters extends Partial<Readonly<Record<string, FieldAdapter>>>> = UnionToIntersection<{
122
122
  readonly [K in keyof TypePathsToAdapters]: TypePathsToAdapters[K] extends undefined ? undefined : unknown extends ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>> ? never : ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>>;
123
123
  }[keyof TypePathsToAdapters] | {}>;
124
+ type FormMode = 'edit' | 'create';
124
125
  declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ContextType>, ContextType = ContextOf<TypePathsToAdapters>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
125
126
  readonly type: T;
127
+ private readonly originalValue;
126
128
  protected readonly adapters: TypePathsToAdapters;
129
+ protected readonly mode: FormMode;
127
130
  accessor value: MobxValueOfType<T>;
128
131
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
129
132
  accessor errors: FlattenedErrors<ValuePathsToAdapters>;
130
133
  private readonly flattenedTypeDefs;
131
- constructor(type: T, value: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters);
134
+ constructor(type: T, originalValue: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters, mode: FormMode);
132
135
  protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>, valuePath: keyof ValuePathsToAdapters): ContextType;
136
+ get forceMutableFields(): boolean;
133
137
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>;
134
138
  private get knownFields();
135
139
  private maybeSynthesizeFieldByValuePath;
@@ -149,7 +153,7 @@ declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readon
149
153
  clearAll(value: ValueOfType<T>): void;
150
154
  isValuePathActive<K extends keyof ValuePathsToAdapters>(valuePath: K): boolean;
151
155
  validateField<K extends keyof ValuePathsToAdapters>(valuePath: K, ignoreDefaultValue?: boolean): boolean;
152
- validateAll(): boolean;
156
+ validateAll(force?: boolean): boolean;
153
157
  }
154
158
 
155
159
  /**
@@ -445,4 +449,4 @@ declare function mergeValidators<Validators1 extends Partial<Readonly<Record<Key
445
449
 
446
450
  declare function Empty(): null;
447
451
 
448
- export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormFieldsOfModel, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, type ToValueOfModelValuePath, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, type ValuePathOfFieldAdapter, type ValuePathsOfModel, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };
452
+ export { AbstractSelectValueTypeConverter, type AnnotatedFieldConversion, type AnnotatedFieldConverter, type Annotation, type ContextOf, type ContextOfFieldAdapter, DefaultErrorRenderer, Empty, type ErrorOfField, type ErrorOfFieldAdapter, type ErrorRenderer, type ErrorRendererProps, type Field, type FieldAdapter, type FieldAdaptersOfValues, type FieldValueFactory, type Fields, type FieldsViewProps, type FlattenedAdaptersOfFields, type FlattenedConvertedFieldsOf, type FlattenedTypePathsToAdaptersOf, type FormFieldsOfFieldAdapters, type FormFieldsOfModel, type FormMode, FormModel, type FormProps, type FromOfFieldAdapter, IntegerToStringConverter, type MergedOfFieldAdaptersWithTwoWayConverter, type MergedOfFieldAdaptersWithValidators, type MergedOfValidator, type MergedOfValidators, NullableToBooleanConverter, type PartialComponent, SelectDiscriminatedUnionConverter, SelectLiteralConverter, SelectStringConverter, type ToOfFieldAdapter, type ToValueOfModelValuePath, TrimmingStringConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConversion, UnreliableFieldConversionType, type UnreliableFieldConverter, type UnsafePartialComponent, type ValuePathOfFieldAdapter, type ValuePathsOfModel, type ValuePathsToAdaptersOf, adapter, adapterFromPrototype, adapterFromTwoWayConverter, createPartialComponent, createPartialObserverComponent, createSimplePartialComponent, createUnsafePartialObserverComponent, identityAdapter, listAdapter, mergeAdaptersWithValidators, mergeFieldAdaptersWithTwoWayConverter, mergeValidators, prototypingFieldValueFactory, subFormFieldAdapters, trimmingStringAdapter, useDefaultMobxFormHooks, useMantineFormFields, usePartialComponent, usePartialObserverComponent, validatingConverter };