@strictly/react-form 0.0.8 → 0.0.10

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 (44) hide show
  1. package/.out/core/mobx/field_adapter_builder.d.ts +4 -0
  2. package/.out/core/mobx/field_adapter_builder.js +31 -0
  3. package/.out/core/mobx/form_presenter.d.ts +5 -5
  4. package/.out/core/mobx/form_presenter.js +8 -6
  5. package/.out/core/mobx/hooks.d.ts +24 -4
  6. package/.out/core/mobx/hooks.js +24 -3
  7. package/.out/core/mobx/specs/form_presenter.tests.js +10 -5
  8. package/.out/core/mobx/sub_form_field_adapters.d.ts +2 -2
  9. package/.out/field_converters/chain_field_converter.js +3 -3
  10. package/.out/mantine/create_fields_view.d.ts +9 -1
  11. package/.out/mantine/create_fields_view.js +13 -1
  12. package/.out/mantine/error_renderer.d.ts +7 -3
  13. package/.out/mantine/hooks.d.ts +2 -1
  14. package/.out/mantine/hooks.js +1 -1
  15. package/.out/mantine/specs/create_fields_view.tests.js +17 -0
  16. package/.out/mantine/specs/fields_view_hooks.stories.d.ts +6 -2
  17. package/.out/mantine/specs/fields_view_hooks.stories.js +26 -7
  18. package/.out/mantine/specs/fields_view_hooks.tests.js +21 -1
  19. package/.out/tsconfig.tsbuildinfo +1 -1
  20. package/.out/types/specs/error_of_field.tests.d.ts +1 -0
  21. package/.out/types/specs/{error_type_of_field.tests.js → error_of_field.tests.js} +1 -1
  22. package/.turbo/turbo-build.log +8 -8
  23. package/.turbo/turbo-check-types.log +1 -1
  24. package/core/mobx/field_adapter_builder.ts +71 -0
  25. package/core/mobx/form_presenter.ts +15 -14
  26. package/core/mobx/hooks.tsx +196 -0
  27. package/core/mobx/specs/form_presenter.tests.ts +24 -5
  28. package/core/mobx/sub_form_field_adapters.ts +14 -3
  29. package/dist/index.cjs +290 -220
  30. package/dist/index.d.cts +63 -32
  31. package/dist/index.d.ts +63 -32
  32. package/dist/index.js +288 -219
  33. package/field_converters/chain_field_converter.ts +3 -3
  34. package/mantine/create_fields_view.tsx +66 -31
  35. package/mantine/error_renderer.ts +12 -3
  36. package/mantine/hooks.tsx +9 -6
  37. package/mantine/specs/__snapshots__/fields_view_hooks.tests.tsx.snap +194 -197
  38. package/mantine/specs/create_fields_view.tests.ts +29 -0
  39. package/mantine/specs/fields_view_hooks.stories.tsx +58 -15
  40. package/mantine/specs/fields_view_hooks.tests.tsx +26 -0
  41. package/package.json +1 -1
  42. package/types/specs/{error_type_of_field.tests.ts → error_of_field.tests.ts} +1 -1
  43. package/core/mobx/hooks.ts +0 -112
  44. /package/.out/{types/specs/error_type_of_field.tests.d.ts → mantine/specs/create_fields_view.tests.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- describe('ErrorTypeOfField', function () {
1
+ describe('ErrorOfField', function () {
2
2
  it('equals expected type', function () {
3
3
  const e = Symbol();
4
4
  expectTypeOf().toEqualTypeOf();
@@ -7,12 +7,12 @@ $ tsup
7
7
  CLI Target: esnext
8
8
  CJS Build start
9
9
  ESM Build start
10
- CJS dist/index.cjs 50.73 KB
11
- CJS ⚡️ Build success in 112ms
12
- ESM dist/index.js 46.84 KB
13
- ESM ⚡️ Build success in 113ms
10
+ CJS dist/index.cjs 52.48 KB
11
+ CJS ⚡️ Build success in 120ms
12
+ ESM dist/index.js 48.52 KB
13
+ ESM ⚡️ Build success in 120ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 9662ms
16
- DTS dist/index.d.cts 36.94 KB
17
- DTS dist/index.d.ts 36.94 KB
18
- Done in 10.73s.
15
+ DTS ⚡️ Build success in 9937ms
16
+ DTS dist/index.d.cts 39.16 KB
17
+ DTS dist/index.d.ts 39.16 KB
18
+ Done in 11.10s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 7.38s.
3
+ Done in 7.83s.
@@ -7,12 +7,14 @@ import {
7
7
  unreliableIdentityConverter,
8
8
  } from 'field_converters/identity_converter'
9
9
  import { MaybeIdentityConverter } from 'field_converters/maybe_identity_converter'
10
+ import { TrimmingStringConverter } from 'field_converters/trimming_string_converter'
10
11
  import { prototypingFieldValueFactory } from 'field_value_factories/prototyping_field_value_factory'
11
12
  import {
12
13
  type AnnotatedFieldConverter,
13
14
  type FieldValueFactory,
14
15
  type TwoWayFieldConverter,
15
16
  type TwoWayFieldConverterWithValueFactory,
17
+ UnreliableFieldConversionType,
16
18
  type UnreliableFieldConverter,
17
19
  } from 'types/field_converters'
18
20
  import { type FieldAdapter } from './field_adapter'
@@ -82,6 +84,65 @@ class FieldAdapterBuilder<
82
84
  )
83
85
  }
84
86
 
87
+ nullable(): FieldAdapterBuilder<
88
+ From | null,
89
+ To | null,
90
+ E,
91
+ ValuePath,
92
+ Context
93
+ > {
94
+ return this.or(null)
95
+ }
96
+
97
+ optional(): FieldAdapterBuilder<
98
+ From | undefined,
99
+ To | undefined,
100
+ E,
101
+ ValuePath,
102
+ Context
103
+ > {
104
+ return this.or(undefined)
105
+ }
106
+
107
+ private or<V>(proto: V): FieldAdapterBuilder<
108
+ From | V,
109
+ To | V,
110
+ E,
111
+ ValuePath,
112
+ Context
113
+ > {
114
+ function isFrom(v: From | V): v is From {
115
+ return v !== proto
116
+ }
117
+ function isTo(v: To | V): v is To {
118
+ return v !== proto
119
+ }
120
+ return new FieldAdapterBuilder<
121
+ From | V,
122
+ To | V,
123
+ E,
124
+ ValuePath,
125
+ Context
126
+ >(
127
+ (v, valuePath, context) =>
128
+ isFrom(v)
129
+ ? this.convert(v, valuePath, context)
130
+ : {
131
+ value: v,
132
+ readonly: false,
133
+ required: false,
134
+ },
135
+ this.create,
136
+ (v, valuePath, context) =>
137
+ isTo(v) && this.revert
138
+ ? this.revert(v, valuePath, context)
139
+ : {
140
+ type: UnreliableFieldConversionType.Success,
141
+ value: proto,
142
+ },
143
+ )
144
+ }
145
+
85
146
  withIdentity(isFrom: (from: To | From) => from is From): FieldAdapterBuilder<
86
147
  From,
87
148
  To | From,
@@ -263,6 +324,16 @@ export function identityAdapter<
263
324
  )
264
325
  }
265
326
 
327
+ export function trimmingStringAdapter<
328
+ ValuePath extends string,
329
+ Context,
330
+ >() {
331
+ return adapterFromTwoWayConverter<string, string, never, ValuePath, Context>(
332
+ new TrimmingStringConverter<ValuePath, Context>(),
333
+ prototypingFieldValueFactory<string, ValuePath, Context>(''),
334
+ )
335
+ }
336
+
266
337
  export function listAdapter<
267
338
  E,
268
339
  ValuePath extends string,
@@ -102,7 +102,7 @@ export type ValuePathsToAdaptersOf<
102
102
  }
103
103
  : never
104
104
 
105
- export class FormPresenter<
105
+ export abstract class FormPresenter<
106
106
  T extends Type,
107
107
  ValueToTypePaths extends Readonly<Record<string, string>>,
108
108
  TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<
@@ -116,7 +116,7 @@ export class FormPresenter<
116
116
  > {
117
117
  constructor(
118
118
  readonly type: T,
119
- private readonly adapters: TypePathsToAdapters,
119
+ protected readonly adapters: TypePathsToAdapters,
120
120
  ) {
121
121
  }
122
122
 
@@ -361,7 +361,7 @@ export class FormPresenter<
361
361
  }
362
362
  }
363
363
 
364
- clearFieldValue<K extends StringKeyOf<ValuePathsToAdapters>>(
364
+ clearFieldValue<K extends StringKeyOf<ValueToTypePaths>>(
365
365
  model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>,
366
366
  valuePath: K,
367
367
  ) {
@@ -375,8 +375,7 @@ export class FormPresenter<
375
375
  convert,
376
376
  create,
377
377
  } = adapter
378
- const accessor = model.accessors[valuePath]
379
- const value = accessor == null ? create(valuePath, model.value) : accessor.value
378
+ const value = create(valuePath, model.value)
380
379
  const {
381
380
  value: displayValue,
382
381
  } = convert(value, valuePath, model.value)
@@ -412,6 +411,7 @@ export class FormPresenter<
412
411
  validateField<K extends keyof ValuePathsToAdapters>(
413
412
  model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>,
414
413
  valuePath: K,
414
+ ignoreDefaultValue = false,
415
415
  ): boolean {
416
416
  const {
417
417
  convert,
@@ -436,7 +436,14 @@ export class FormPresenter<
436
436
  : storedValue
437
437
  const dirty = storedValue !== value
438
438
  assertExists(revert, 'changing field directly not supported {}', valuePath)
439
-
439
+ if (ignoreDefaultValue) {
440
+ const {
441
+ value: defaultDisplayValue,
442
+ } = convert(create(valuePath, model.value), valuePath, model.value)
443
+ if (defaultDisplayValue === value) {
444
+ return true
445
+ }
446
+ }
440
447
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
441
448
  const conversion = revert(value, valuePath as string, model.value)
442
449
  return runInAction(function () {
@@ -521,18 +528,12 @@ export class FormPresenter<
521
528
  })
522
529
  }
523
530
 
524
- createModel(value: ValueOfType<ReadonlyTypeOfType<T>>): FormModel<
531
+ abstract createModel(value: ValueOfType<ReadonlyTypeOfType<T>>): FormModel<
525
532
  T,
526
533
  ValueToTypePaths,
527
534
  TypePathsToAdapters,
528
535
  ValuePathsToAdapters
529
- > {
530
- return new FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>(
531
- this.type,
532
- value,
533
- this.adapters,
534
- )
535
- }
536
+ >
536
537
  }
537
538
 
538
539
  export class FormModel<
@@ -0,0 +1,196 @@
1
+ import {
2
+ type ReadonlyTypeOfType,
3
+ type ValueOfType,
4
+ } from '@strictly/define'
5
+ import {
6
+ type FieldsViewProps,
7
+ } from 'core/props'
8
+ import {
9
+ type ComponentType,
10
+ useCallback,
11
+ useMemo,
12
+ } from 'react'
13
+ import {
14
+ createUnsafePartialObserverComponent,
15
+ type UnsafePartialComponent,
16
+ } from 'util/partial'
17
+ import { type FormPresenter } from './form_presenter'
18
+ import {
19
+ type FormFieldsOfPresenter,
20
+ type ToValueOfPresenterValuePath,
21
+ type ValuePathsOfPresenter,
22
+ } from './types'
23
+
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ type ValueOfPresenter<P extends FormPresenter<any, any, any, any>> = P extends FormPresenter<infer T, any, any, any>
26
+ ? ValueOfType<ReadonlyTypeOfType<T>>
27
+ : never
28
+
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ type ModelOfPresenter<P extends FormPresenter<any, any, any, any>> = ReturnType<P['createModel']>
31
+
32
+ export function useDefaultMobxFormHooks<
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ P extends FormPresenter<any, any, any, any>,
35
+ C extends ComponentType<FieldsViewProps<F>>,
36
+ F extends FormFieldsOfPresenter<P> = FormFieldsOfPresenter<P>,
37
+ >(
38
+ presenter: P,
39
+ value: ValueOfPresenter<P>,
40
+ options?: {
41
+ onValidFieldSubmit?: <Path extends ValuePathsOfPresenter<P>>(model: ModelOfPresenter<P>, valuePath: Path) => void,
42
+ onValidFormSubmit?: (model: ModelOfPresenter<P>, value: ValueOfPresenter<P>) => void,
43
+ },
44
+ ): {
45
+ model: ModelOfPresenter<P>,
46
+ FormFields?: UnsafePartialComponent<C, FieldsViewProps<F>>,
47
+ onFormSubmit: () => void,
48
+ onFieldValueChange<K extends keyof F>(this: void, key: K, value: F[K]['value']): void,
49
+ onFieldFocus?(this: void, key: keyof F): void,
50
+ onFieldBlur?(this: void, key: keyof F): void,
51
+ onFieldSubmit?(this: void, key: keyof F): boolean | void,
52
+ }
53
+ export function useDefaultMobxFormHooks<
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ P extends FormPresenter<any, any, any, any>,
56
+ C extends ComponentType<FieldsViewProps<F>>,
57
+ F extends FormFieldsOfPresenter<P> = FormFieldsOfPresenter<P>,
58
+ >(
59
+ presenter: P,
60
+ value: ValueOfPresenter<P>,
61
+ options: {
62
+ onValidFieldSubmit?: <Path extends ValuePathsOfPresenter<P>>(model: ModelOfPresenter<P>, valuePath: Path) => void,
63
+ onValidFormSubmit?: (model: ModelOfPresenter<P>, value: ValueOfPresenter<P>) => void,
64
+ FormFieldsView: C,
65
+ },
66
+ ): {
67
+ model: ModelOfPresenter<P>,
68
+ FormFields: UnsafePartialComponent<C, FieldsViewProps<F>>,
69
+ onFormSubmit: () => void,
70
+ onFieldValueChange<K extends keyof F>(this: void, key: K, value: F[K]['value']): void,
71
+ onFieldFocus?(this: void, key: keyof F): void,
72
+ onFieldBlur?(this: void, key: keyof F): void,
73
+ onFieldSubmit?(this: void, key: keyof F): boolean | void,
74
+ }
75
+ export function useDefaultMobxFormHooks<
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ P extends FormPresenter<any, any, any, any>,
78
+ C extends FieldsViewProps<F>,
79
+ F extends FormFieldsOfPresenter<P> = FormFieldsOfPresenter<P>,
80
+ >(
81
+ presenter: P,
82
+ value: ValueOfPresenter<P>,
83
+ {
84
+ onValidFieldSubmit,
85
+ onValidFormSubmit,
86
+ FormFieldsView,
87
+ }: {
88
+ onValidFieldSubmit?: <Path extends ValuePathsOfPresenter<P>>(model: ModelOfPresenter<P>, valuePath: Path) => void,
89
+ onValidFormSubmit?: (model: ModelOfPresenter<P>, value: ValueOfPresenter<P>) => void,
90
+ FormFieldsView?: ComponentType<C>,
91
+ } = {},
92
+ ): {
93
+ model: ModelOfPresenter<P>,
94
+ FormFields?: UnsafePartialComponent<ComponentType<C>, FieldsViewProps<F>> | undefined,
95
+ onFormSubmit: () => void,
96
+ onFieldValueChange<K extends keyof F>(this: void, key: K, value: F[K]['value']): void,
97
+ onFieldFocus?(this: void, key: keyof F): void,
98
+ onFieldBlur?(this: void, key: keyof F): void,
99
+ onFieldSubmit?(this: void, key: keyof F): boolean | void,
100
+ } {
101
+ const model = useMemo(function () {
102
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
103
+ return presenter.createModel(value) as ReturnType<P['createModel']>
104
+ }, [
105
+ presenter,
106
+ value,
107
+ ])
108
+
109
+ const onFieldValueChange = useCallback(
110
+ function<Path extends ValuePathsOfPresenter<P>> (
111
+ path: Path,
112
+ value: ToValueOfPresenterValuePath<P, Path>,
113
+ ) {
114
+ presenter.clearFieldError(model, path)
115
+ presenter.setFieldValue<Path>(model, path, value)
116
+ },
117
+ [
118
+ presenter,
119
+ model,
120
+ ],
121
+ )
122
+
123
+ const onFieldSubmit = useCallback(
124
+ function<Path extends ValuePathsOfPresenter<P>> (valuePath: Path) {
125
+ if (presenter.validateField(model, valuePath)) {
126
+ onValidFieldSubmit?.(model, valuePath)
127
+ }
128
+ return false
129
+ },
130
+ [
131
+ presenter,
132
+ model,
133
+ onValidFieldSubmit,
134
+ ],
135
+ )
136
+
137
+ const onFieldBlur = useCallback(
138
+ function<Path extends ValuePathsOfPresenter<P>> (path: Path) {
139
+ // work around potential loss of focus prior to state potentially invalidating change triggering
140
+ // (e.g. changing a discriminator)
141
+ // TODO debounce?
142
+ setTimeout(function () {
143
+ if (presenter.isValuePathActive(model, path)) {
144
+ presenter.validateField(model, path, true)
145
+ }
146
+ }, 100)
147
+ },
148
+ [
149
+ presenter,
150
+ model,
151
+ ],
152
+ )
153
+
154
+ const onFormSubmit = useCallback(
155
+ function () {
156
+ if (presenter.validateAll(model)) {
157
+ onValidFormSubmit?.(model, model.value)
158
+ }
159
+ },
160
+ [
161
+ presenter,
162
+ model,
163
+ onValidFormSubmit,
164
+ ],
165
+ )
166
+
167
+ const FormFields = useMemo(() => {
168
+ if (FormFieldsView == null) {
169
+ return undefined
170
+ }
171
+ return createUnsafePartialObserverComponent(FormFieldsView, (): FieldsViewProps<F> => {
172
+ return {
173
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
174
+ fields: model.fields as C['fields'],
175
+ onFieldBlur,
176
+ onFieldSubmit,
177
+ onFieldValueChange,
178
+ }
179
+ })
180
+ }, [
181
+ model,
182
+ FormFieldsView,
183
+ onFieldBlur,
184
+ onFieldSubmit,
185
+ onFieldValueChange,
186
+ ])
187
+
188
+ return {
189
+ model,
190
+ onFieldValueChange,
191
+ onFieldSubmit,
192
+ onFieldBlur,
193
+ onFormSubmit,
194
+ FormFields,
195
+ }
196
+ }
@@ -6,10 +6,14 @@ import {
6
6
  nullType,
7
7
  numberType,
8
8
  object,
9
+ type ReadonlyOfTypeDef,
10
+ type ReadonlyTypeOfType,
9
11
  record,
10
12
  stringType,
13
+ type Type,
11
14
  union,
12
15
  type ValueOfType,
16
+ type ValueOfTypeDef,
13
17
  type ValueToTypePathsOfType,
14
18
  } from '@strictly/define'
15
19
  import { type FieldAdapter } from 'core/mobx/field_adapter'
@@ -39,6 +43,21 @@ import {
39
43
 
40
44
  const IS_NAN_ERROR = 1
41
45
 
46
+ class TestFormPresenter<
47
+ T extends Type,
48
+ ValueToTypePaths extends Readonly<Record<string, string>>,
49
+ TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<
50
+ FlattenedValuesOfType<T, '*'>,
51
+ ValueOfType<ReadonlyTypeOfType<T>>
52
+ >,
53
+ > extends FormPresenter<T, ValueToTypePaths, TypePathsToAdapters> {
54
+ override createModel(value: ValueOfTypeDef<ReadonlyOfTypeDef<T['definition']>, {}>): FormModel<T, ValueToTypePaths,
55
+ TypePathsToAdapters, ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>>
56
+ {
57
+ return new FormModel(this.type, value, this.adapters)
58
+ }
59
+ }
60
+
42
61
  const originalIntegerToStringAdapter = adapterFromTwoWayConverter(
43
62
  new IntegerToStringConverter(IS_NAN_ERROR),
44
63
  prototypingFieldValueFactory(0),
@@ -479,7 +498,7 @@ describe('all', function () {
479
498
  const adapters = {
480
499
  $: integerToStringAdapter,
481
500
  } as const
482
- const presenter = new FormPresenter<
501
+ const presenter = new TestFormPresenter<
483
502
  typeof typeDef,
484
503
  ValueToTypePathsOfType<typeof typeDef>,
485
504
  typeof adapters
@@ -600,7 +619,7 @@ describe('all', function () {
600
619
  const converters = {
601
620
  '$.*': integerToStringAdapter,
602
621
  } as const
603
- const presenter = new FormPresenter<
622
+ const presenter = new TestFormPresenter<
604
623
  typeof typeDef,
605
624
  ValueToTypePathsOfType<typeof typeDef>,
606
625
  typeof converters
@@ -927,7 +946,7 @@ describe('all', function () {
927
946
  '$.*': integerToStringAdapter,
928
947
  } as const
929
948
  type ValueToTypePaths = ValueToTypePathsOfType<typeof type>
930
- const presenter = new FormPresenter<
949
+ const presenter = new TestFormPresenter<
931
950
  typeof type,
932
951
  ValueToTypePaths,
933
952
  typeof adapters
@@ -997,7 +1016,7 @@ describe('all', function () {
997
1016
  '$.x:a': identityAdapter(0).narrow,
998
1017
  '$.y:b': identityAdapter(false).narrow,
999
1018
  } as const
1000
- const presenter = new FormPresenter<
1019
+ const presenter = new TestFormPresenter<
1001
1020
  typeof type,
1002
1021
  ValueToTypePaths,
1003
1022
  typeof adapters
@@ -1068,7 +1087,7 @@ describe('all', function () {
1068
1087
  $: '$',
1069
1088
  '$.fake': '$.fake',
1070
1089
  }
1071
- const presenter = new FormPresenter<
1090
+ const presenter = new TestFormPresenter<
1072
1091
  typeof typeDef,
1073
1092
  JsonPaths,
1074
1093
  typeof converters
@@ -1,6 +1,7 @@
1
1
  import { type StringConcatOf } from '@strictly/base'
2
2
  import {
3
3
  flattenValuesOfType,
4
+ type ReadonlyTypeOfType,
4
5
  type Type,
5
6
  type ValueOfType,
6
7
  } from '@strictly/define'
@@ -47,10 +48,15 @@ export function subFormFieldAdapters<
47
48
  subAdapters: SubAdapters,
48
49
  parentTypePath: TypePath,
49
50
  contextType: ContextType,
50
- ): SubFormFieldAdapters<SubAdapters, TypePath, TypePathsToValuePaths[TypePath], ValueOfType<ContextType>> {
51
+ ): SubFormFieldAdapters<
52
+ SubAdapters,
53
+ TypePath,
54
+ TypePathsToValuePaths[TypePath],
55
+ ValueOfType<ReadonlyTypeOfType<ContextType>>
56
+ > {
51
57
  // assume the number of '.' in the type path will correspond to the number of '.' in the value path
52
58
  const dotCount = parentTypePath.split('.').length
53
- function getSubValuePathAndContext(valuePath: string, context: ValueOfType<ContextType>) {
59
+ function getSubValuePathAndContext(valuePath: string, context: ValueOfType<ReadonlyTypeOfType<ContextType>>) {
54
60
  const parentValuePath = valuePath.split('.').slice(0, dotCount).join('.')
55
61
  const subValuePath = valuePath.replace(parentValuePath, '$')
56
62
  const subContext = flattenValuesOfType(contextType, context)[parentValuePath]
@@ -80,5 +86,10 @@ export function subFormFieldAdapters<
80
86
  }
81
87
  acc[typePath] = adaptedAdapter
82
88
  return acc
83
- }, {}) as SubFormFieldAdapters<SubAdapters, TypePath, TypePathsToValuePaths[TypePath], ValueOfType<ContextType>>
89
+ }, {}) as SubFormFieldAdapters<
90
+ SubAdapters,
91
+ TypePath,
92
+ TypePathsToValuePaths[TypePath],
93
+ ValueOfType<ReadonlyTypeOfType<ContextType>>
94
+ >
84
95
  }