@strictly/react-form 0.0.18 → 0.0.19

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 (37) hide show
  1. package/.out/core/mobx/form_model.d.ts +12 -9
  2. package/.out/core/mobx/form_model.js +103 -137
  3. package/.out/core/mobx/hooks.js +3 -4
  4. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.d.ts +1 -1
  5. package/.out/core/mobx/merge_field_adapters_with_validators.js +5 -1
  6. package/.out/core/mobx/specs/form_model.tests.js +28 -23
  7. package/.out/mantine/create_fields_view.d.ts +2 -1
  8. package/.out/mantine/hooks.d.ts +6 -5
  9. package/.out/mantine/specs/checkbox_hooks.stories.d.ts +5 -2
  10. package/.out/mantine/specs/checkbox_hooks.stories.js +3 -2
  11. package/.out/mantine/specs/text_input_hooks.stories.d.ts +3 -2
  12. package/.out/mantine/specs/text_input_hooks.stories.js +3 -2
  13. package/.out/mantine/types.d.ts +3 -3
  14. package/.out/tsconfig.tsbuildinfo +1 -1
  15. package/.out/util/partial.d.ts +5 -2
  16. package/.out/util/specs/partial.tests.d.ts +1 -0
  17. package/.out/util/specs/partial.tests.js +8 -0
  18. package/.turbo/turbo-build.log +8 -8
  19. package/.turbo/turbo-check-types.log +1 -1
  20. package/.turbo/turbo-release$colon$exports.log +1 -1
  21. package/core/mobx/form_model.ts +95 -157
  22. package/core/mobx/hooks.tsx +6 -5
  23. package/core/mobx/merge_field_adapters_with_two_way_converter.ts +2 -1
  24. package/core/mobx/merge_field_adapters_with_validators.ts +1 -1
  25. package/core/mobx/specs/form_model.tests.ts +39 -27
  26. package/dist/index.cjs +93 -139
  27. package/dist/index.d.cts +28 -21
  28. package/dist/index.d.ts +28 -21
  29. package/dist/index.js +92 -139
  30. package/mantine/create_fields_view.tsx +8 -4
  31. package/mantine/hooks.tsx +23 -15
  32. package/mantine/specs/checkbox_hooks.stories.tsx +7 -1
  33. package/mantine/specs/text_input_hooks.stories.tsx +8 -1
  34. package/mantine/types.ts +12 -4
  35. package/package.json +1 -1
  36. package/util/partial.tsx +8 -1
  37. package/util/specs/partial.tests.tsx +21 -0
@@ -1,7 +1,10 @@
1
1
  import { type FriendlyExhaustiveArrayOfUnion } from '@strictly/base';
2
- import { type ComponentProps, type ComponentType, type DependencyList, type ForwardRefExoticComponent, type PropsWithoutRef } from 'react';
2
+ import { type ComponentProps, type ComponentType, type DependencyList, type ForwardRefExoticComponent, type PropsWithoutRef, type Ref, type RefAttributes } from 'react';
3
+ export type RefOfProps<P, Fallback = unknown> = P extends RefAttributes<infer R> ? R : Fallback;
3
4
  export type PartialComponent<Component extends ComponentType<any>, CurriedProps, AdditionalProps = {}> = Exclude<keyof CurriedProps, keyof ComponentProps<Component>> extends never ? UnsafePartialComponent<Component, CurriedProps, AdditionalProps> : keyof CurriedProps extends (string | number) ? `unmatched prop: ${Exclude<keyof CurriedProps, keyof ComponentProps<Component>>}` : Exclude<keyof CurriedProps, keyof ComponentProps<Component>>;
4
- export type UnsafePartialComponent<Component extends ComponentType<any>, CurriedProps, AdditionalProps = {}> = ForwardRefExoticComponent<PropsWithoutRef<RemainingComponentProps<Component, CurriedProps> & AdditionalProps>>;
5
+ export type UnsafePartialComponent<Component extends ComponentType<any>, CurriedProps, AdditionalProps = {}, R = RefOfProps<ComponentProps<Component>>> = ForwardRefExoticComponent<PropsWithoutRef<RemainingComponentProps<Component, CurriedProps> & AdditionalProps> & {
6
+ ref?: Ref<R>;
7
+ }>;
5
8
  export declare function createSimplePartialComponent<Component extends ComponentType<any>, CurriedProps extends Partial<ComponentProps<Component>>>(Component: Component, curriedProps: CurriedProps): PartialComponent<Component, CurriedProps>;
6
9
  export declare function createPartialComponent<Component extends ComponentType<any>, CurriedProps>(Component: Component, curriedPropsSource: () => CurriedProps): PartialComponent<Component, CurriedProps, {}>;
7
10
  export declare function createPartialComponent<Component extends ComponentType<any>, CurriedProps, AdditionalProps, AllAdditionalPropKeys extends readonly (keyof AdditionalProps)[]>(Component: Component, curriedPropsSource: (additionalProps: AdditionalProps) => CurriedProps, additionalPropKeys: FriendlyExhaustiveArrayOfUnion<keyof AdditionalProps, AllAdditionalPropKeys>): PartialComponent<Component, CurriedProps, AdditionalProps>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ describe('partial', () => {
2
+ describe('UnsafePartialComponent', () => {
3
+ it('allows a ref of a specific type to be passed', () => {
4
+ expectTypeOf().toEqualTypeOf();
5
+ });
6
+ });
7
+ });
8
+ export {};
@@ -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 58.27 KB
11
- ESM ⚡️ Build success in 136ms
12
- CJS dist/index.cjs 62.28 KB
13
- CJS ⚡️ Build success in 137ms
10
+ CJS dist/index.cjs 60.71 KB
11
+ CJS ⚡️ Build success in 113ms
12
+ ESM dist/index.js 56.70 KB
13
+ ESM ⚡️ Build success in 113ms
14
14
  DTS Build start
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.
15
+ DTS ⚡️ Build success in 9852ms
16
+ DTS dist/index.d.cts 38.50 KB
17
+ DTS dist/index.d.ts 38.50 KB
18
+ Done in 10.92s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 7.96s.
3
+ Done in 7.61s.
@@ -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.14s.
3
+ Done in 0.11s.
@@ -88,10 +88,15 @@ type FlattenedFieldOverrides<
88
88
  >
89
89
  }
90
90
 
91
- type FlattenedErrors<
91
+ export enum Validation {
92
+ Changed = 1,
93
+ Always = 2,
94
+ }
95
+
96
+ type FlattenedValidation<
92
97
  ValuePathsToAdapters extends Readonly<Record<string, FieldAdapter>>,
93
98
  > = {
94
- -readonly [K in keyof ValuePathsToAdapters]?: ErrorOfFieldAdapter<ValuePathsToAdapters[K]>
99
+ -readonly [K in keyof ValuePathsToAdapters]?: Validation
95
100
  }
96
101
 
97
102
  export type ValuePathsToAdaptersOf<
@@ -138,16 +143,21 @@ export abstract class FormModel<
138
143
  @observable.shallow
139
144
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>
140
145
  @observable.shallow
141
- accessor errors: FlattenedErrors<ValuePathsToAdapters> = {}
146
+ accessor validation: FlattenedValidation<ValuePathsToAdapters> = {}
142
147
 
143
148
  private readonly flattenedTypeDefs: Readonly<Record<string, Type>>
144
149
 
150
+ // cannot be type safe
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
+ private readonly originalValues: Record<string, any>
153
+
145
154
  constructor(
146
155
  readonly type: T,
147
- private readonly originalValue: ValueOfType<ReadonlyTypeOfType<T>>,
156
+ originalValue: ValueOfType<ReadonlyTypeOfType<T>>,
148
157
  protected readonly adapters: TypePathsToAdapters,
149
158
  protected readonly mode: FormMode,
150
159
  ) {
160
+ this.originalValues = flattenValuesOfType<ReadonlyTypeOfType<T>>(type, originalValue)
151
161
  this.value = mobxCopy(type, originalValue)
152
162
  this.flattenedTypeDefs = flattenTypesOfType(type)
153
163
  // pre-populate field overrides for consistent behavior when default information is overwritten
@@ -271,6 +281,7 @@ export abstract class FormModel<
271
281
  const {
272
282
  convert,
273
283
  create,
284
+ revert,
274
285
  } = adapter
275
286
 
276
287
  const fieldOverride = this.fieldOverrides[valuePath]
@@ -278,6 +289,9 @@ export abstract class FormModel<
278
289
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
279
290
  const fieldTypeDef = this.flattenedTypeDefs[typePath as string]
280
291
  const context = this.toContext(this.value, valuePath)
292
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
293
+ const defaultValue = create(valuePath as string, context)
294
+
281
295
  const {
282
296
  value,
283
297
  required,
@@ -288,17 +302,50 @@ export abstract class FormModel<
288
302
  : fieldTypeDef != null
289
303
  ? mobxCopy(
290
304
  fieldTypeDef,
291
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
292
- create(valuePath as string, context),
305
+ defaultValue,
293
306
  )
294
307
  // fake values can't be copied
295
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
296
- : create(valuePath as string, context),
308
+ : defaultValue,
297
309
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
298
310
  valuePath as string,
299
311
  context,
300
312
  )
301
- const error = this.errors[valuePath]
313
+ // const error = this.errors[valuePath]
314
+ let error: unknown = undefined
315
+ const displayedValue = fieldOverride != null ? fieldOverride[0] : value
316
+ const validation = this.validation[valuePath]
317
+ switch (validation) {
318
+ case undefined:
319
+ // skip validation
320
+ break
321
+ case Validation.Changed:
322
+ if (revert != null) {
323
+ const originalValue = valuePath in this.originalValues
324
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
325
+ ? this.originalValues[valuePath as string]
326
+ : defaultValue
327
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
328
+ const { value: originalDisplayedValue } = convert(originalValue, valuePath as string, context)
329
+ // TODO better comparisons, displayed values can still be complex
330
+ if (displayedValue !== originalDisplayedValue) {
331
+ const revertResult = revert(displayedValue, valuePath, context)
332
+ if (revertResult?.type === UnreliableFieldConversionType.Failure) {
333
+ ;({ error } = revertResult)
334
+ }
335
+ }
336
+ }
337
+ break
338
+ case Validation.Always:
339
+ {
340
+ const revertResult = revert?.(displayedValue, valuePath, context)
341
+ if (revertResult?.type === UnreliableFieldConversionType.Failure) {
342
+ ;({ error } = revertResult)
343
+ }
344
+ }
345
+ break
346
+ default:
347
+ throw new UnreachableError(validation)
348
+ }
302
349
  return {
303
350
  value: fieldOverride != null ? fieldOverride[0] : value,
304
351
  error,
@@ -343,18 +390,12 @@ export abstract class FormModel<
343
390
  return valuePathToTypePath<ValueToTypePaths, K>(this.type, valuePath, true)
344
391
  }
345
392
 
346
- setFieldValueAndValidate<K extends keyof ValuePathsToAdapters>(
347
- valuePath: K,
348
- value: ToOfFieldAdapter<ValuePathsToAdapters[K]>,
349
- ): boolean {
350
- return this.internalSetFieldValue(valuePath, value, true)
351
- }
352
-
353
393
  setFieldValue<K extends keyof ValuePathsToAdapters>(
354
394
  valuePath: K,
355
395
  value: ToOfFieldAdapter<ValuePathsToAdapters[K]>,
396
+ validation: Validation | undefined | null = this.validation[valuePath],
356
397
  ): boolean {
357
- return this.internalSetFieldValue(valuePath, value, false)
398
+ return this.internalSetFieldValue(valuePath, value, validation)
358
399
  }
359
400
 
360
401
  addListItem<K extends keyof FlattenedListTypesOfType<T>>(
@@ -430,9 +471,9 @@ export abstract class FormModel<
430
471
  const fieldOverride = this.fieldOverrides[fromJsonPath]
431
472
  delete this.fieldOverrides[fromJsonPath]
432
473
  this.fieldOverrides[toJsonPath] = fieldOverride
433
- const error = this.errors[fromJsonPath]
434
- delete this.errors[fromJsonPath]
435
- this.errors[toJsonPath] = error
474
+ const validation = this.validation[fromJsonPath]
475
+ delete this.validation[fromJsonPath]
476
+ this.validation[toJsonPath] = validation
436
477
  })
437
478
  accessor.set(newList)
438
479
  // delete any value overrides so the new list isn't shadowed
@@ -507,9 +548,9 @@ export abstract class FormModel<
507
548
  const fieldOverride = this.fieldOverrides[fromJsonPath]
508
549
  delete this.fieldOverrides[fromJsonPath]
509
550
  this.fieldOverrides[toJsonPath] = fieldOverride
510
- const error = this.errors[fromJsonPath]
511
- delete this.errors[fromJsonPath]
512
- this.errors[toJsonPath] = error
551
+ const validation = this.validation[fromJsonPath]
552
+ delete this.validation[fromJsonPath]
553
+ this.validation[toJsonPath] = validation
513
554
  })
514
555
  accessor.set(newList)
515
556
  // delete any value overrides so the new list isn't shadowed
@@ -522,7 +563,7 @@ export abstract class FormModel<
522
563
  private internalSetFieldValue<K extends keyof ValuePathsToAdapters>(
523
564
  valuePath: K,
524
565
  value: ToOfFieldAdapter<ValuePathsToAdapters[K]>,
525
- displayValidation: boolean,
566
+ validation: Validation | undefined | null,
526
567
  ): boolean {
527
568
  const { revert } = this.getAdapterForValuePath(valuePath)
528
569
 
@@ -533,17 +574,18 @@ export abstract class FormModel<
533
574
  const accessor = this.getAccessorForValuePath(valuePath)
534
575
  return runInAction(() => {
535
576
  this.fieldOverrides[valuePath] = [value]
577
+ if (validation != null) {
578
+ this.validation[valuePath] = validation
579
+ } else {
580
+ delete this.validation[valuePath]
581
+ }
536
582
  switch (conversion.type) {
537
583
  case UnreliableFieldConversionType.Failure:
538
- if (displayValidation) {
539
- this.errors[valuePath] = conversion.error
540
- }
541
584
  if (conversion.value != null && accessor != null) {
542
585
  accessor.set(conversion.value[0])
543
586
  }
544
587
  return false
545
588
  case UnreliableFieldConversionType.Success:
546
- delete this.errors[valuePath]
547
589
  accessor?.set(conversion.value)
548
590
  return true
549
591
  default:
@@ -556,12 +598,12 @@ export abstract class FormModel<
556
598
  const fieldOverride = this.fieldOverrides[valuePath]
557
599
  if (fieldOverride != null) {
558
600
  runInAction(() => {
559
- delete this.errors[valuePath]
601
+ delete this.validation[valuePath]
560
602
  })
561
603
  }
562
604
  }
563
605
 
564
- clearFieldValue<K extends StringKeyOf<ValueToTypePaths>>(valuePath: K) {
606
+ clearFieldValue<K extends StringKeyOf<ValuePathsToAdapters>>(valuePath: K) {
565
607
  const typePath = this.typePath(valuePath)
566
608
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
567
609
  const adapter = this.adapters[typePath as keyof TypePathsToAdapters]
@@ -582,12 +624,13 @@ export abstract class FormModel<
582
624
  const key = valuePath as unknown as keyof ValuePathsToAdapters
583
625
  runInAction(() => {
584
626
  this.fieldOverrides[key] = [displayValue]
627
+ delete this.validation[key]
585
628
  })
586
629
  }
587
630
 
588
631
  clearAll(value: ValueOfType<T>): void {
589
632
  runInAction(() => {
590
- this.errors = {}
633
+ this.validation = {}
591
634
  // TODO this isn't correct, should reload from value
592
635
  this.fieldOverrides = {}
593
636
  this.value = mobxCopy(this.type, value)
@@ -603,137 +646,32 @@ export abstract class FormModel<
603
646
 
604
647
  validateField<K extends keyof ValuePathsToAdapters>(
605
648
  valuePath: K,
606
- ignoreDefaultValue = false,
649
+ validation: Validation = Math.max(
650
+ this.mode === 'create' ? Validation.Always : Validation.Changed,
651
+ this.validation[valuePath] ?? Validation.Changed,
652
+ ),
607
653
  ): boolean {
608
- const {
609
- convert,
610
- revert,
611
- create,
612
- } = this.getAdapterForValuePath(valuePath)
613
- const fieldOverride = this.fieldOverrides[valuePath]
614
- const accessor = this.getAccessorForValuePath(valuePath)
615
- const context = this.toContext(this.value, valuePath)
616
-
617
- const {
618
- value: storedValue,
619
- } = convert(
620
- accessor != null
621
- ? accessor.value
622
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
623
- : create(valuePath as string, context),
624
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
625
- valuePath as string,
626
- context,
627
- )
628
- const value = fieldOverride != null
629
- ? fieldOverride[0]
630
- : storedValue
631
- const dirty = storedValue !== value
632
- assertExists(revert, 'changing field directly not supported {}', valuePath)
633
- if (ignoreDefaultValue) {
634
- const {
635
- value: defaultDisplayValue,
636
- } = convert(create(valuePath, context), valuePath, context)
637
- if (defaultDisplayValue === value) {
638
- return true
639
- }
640
- }
641
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
642
- const conversion = revert(value, valuePath as string, context)
643
- return runInAction(() => {
644
- switch (conversion.type) {
645
- case UnreliableFieldConversionType.Failure:
646
- this.errors[valuePath] = conversion.error
647
- if (conversion.value != null && accessor != null && dirty) {
648
- accessor.set(conversion.value[0])
649
- }
650
- return false
651
- case UnreliableFieldConversionType.Success:
652
- delete this.errors[valuePath]
653
- if (accessor != null && dirty) {
654
- accessor.set(conversion.value)
655
- }
656
- return true
657
- default:
658
- throw new UnreachableError(conversion)
659
- }
654
+ runInAction(() => {
655
+ this.validation[valuePath] = validation
660
656
  })
657
+ return this.fields[valuePath].error == null
661
658
  }
662
659
 
663
- validateAll(force: boolean = this.mode === 'create'): boolean {
664
- // sort keys shortest to longest so parent changes don't overwrite child changes
665
- const accessors = toArray(this.accessors).toSorted(function ([a], [b]) {
666
- return a.length - b.length
667
- })
668
-
669
- const flattenedOriginalValues = flattenValuesOfType(this.type, this.originalValue)
660
+ validateAll(validation: Validation = this.mode === 'create' ? Validation.Always : Validation.Changed): boolean {
661
+ const accessors = toArray(this.accessors)
670
662
 
671
- return runInAction(() => {
672
- return accessors.reduce(
673
- (
674
- success,
675
- [
676
- valuePath,
677
- accessor,
678
- ],
679
- ): boolean => {
680
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
681
- const adapterPath = valuePath as keyof ValuePathsToAdapters
682
- const adapter = this.maybeGetAdapterForValuePath(adapterPath)
683
- if (adapter == null) {
684
- // no adapter == there should be nothing specified for this field
685
- return success
686
- }
687
- const {
688
- convert,
689
- revert,
690
- } = adapter
691
- if (revert == null) {
692
- // no convert method means this field is immutable
693
- return success
694
- }
695
- const fieldOverride = this.fieldOverrides[adapterPath]
696
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
697
- const context = this.toContext(this.value, valuePath as keyof ValuePathsToAdapters)
698
- const {
699
- value: storedValue,
700
- } = convert(accessor.value, valuePath, context)
701
- const value = fieldOverride != null
702
- ? fieldOverride[0]
703
- : storedValue
704
- // TODO customizable comparisons
705
- const dirty = fieldOverride != null && fieldOverride[0] !== storedValue
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
- }
732
- }
733
- return success
734
- },
735
- true,
736
- )
663
+ runInAction(() => {
664
+ accessors.forEach(([valuePath]) => {
665
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
666
+ this.validation[valuePath as keyof ValuePathsToAdapters] = validation
667
+ })
737
668
  })
669
+ return accessors.every(
670
+ ([valuePath]): boolean => {
671
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
672
+ const field = this.fields[valuePath as keyof ValuePathsToAdapters]
673
+ return field?.error == null
674
+ },
675
+ )
738
676
  }
739
677
  }
@@ -5,7 +5,9 @@ import {
5
5
  import {
6
6
  useCallback,
7
7
  } from 'react'
8
- import { type FormModel } from './form_model'
8
+ import {
9
+ type FormModel,
10
+ } from './form_model'
9
11
  import {
10
12
  type FormFieldsOfModel,
11
13
  type ToValueOfModelValuePath,
@@ -42,9 +44,8 @@ export function useDefaultMobxFormHooks<
42
44
  path: Path,
43
45
  value: ToValueOfModelValuePath<M, Path>,
44
46
  ) {
45
- // TODO do in one action
46
- model.clearFieldError(path)
47
- model.setFieldValue<Path>(path, value)
47
+ // clear any validation
48
+ model.setFieldValue<Path>(path, value, null)
48
49
  },
49
50
  [model],
50
51
  )
@@ -69,7 +70,7 @@ export function useDefaultMobxFormHooks<
69
70
  // TODO debounce?
70
71
  setTimeout(function () {
71
72
  if (model.isValuePathActive(path)) {
72
- model.validateField(path, true)
73
+ model.validateField(path)
73
74
  }
74
75
  }, 100)
75
76
  },
@@ -40,13 +40,14 @@ export function mergeFieldAdaptersWithTwoWayConverter<
40
40
  FieldAdapters extends Readonly<Record<string, FieldAdapter>>,
41
41
  E,
42
42
  Context,
43
+ P extends ValuePathsOfFieldAdapters<FieldAdapters>,
43
44
  >(
44
45
  fieldAdapters: FieldAdapters,
45
46
  converter: TwoWayFieldConverter<
46
47
  TosOfFieldAdapters<FieldAdapters>,
47
48
  TosOfFieldAdapters<FieldAdapters>,
48
49
  E,
49
- ValuePathsOfFieldAdapters<FieldAdapters>,
50
+ P,
50
51
  Context
51
52
  >,
52
53
  ): MergedOfFieldAdaptersWithTwoWayConverter<FieldAdapters, E, Context> {
@@ -88,7 +88,7 @@ export function mergeAdaptersWithValidators<
88
88
  }
89
89
  }
90
90
  acc[key] = {
91
- ...adapter,
91
+ create: adapter.create.bind(adapter),
92
92
  convert,
93
93
  revert: adapter.revert && revert,
94
94
  }