@strictly/react-form 0.0.12 → 0.0.14

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/field_adapter.d.ts +1 -0
  2. package/.out/core/mobx/form_model.d.ts +3 -1
  3. package/.out/core/mobx/form_model.js +23 -15
  4. package/.out/core/mobx/hooks.d.ts +2 -2
  5. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.d.ts +2 -2
  6. package/.out/core/mobx/specs/form_model.tests.js +26 -21
  7. package/.out/core/mobx/specs/sub_form_field_adapters.tests.js +14 -21
  8. package/.out/core/mobx/sub_form_field_adapters.d.ts +5 -6
  9. package/.out/core/mobx/sub_form_field_adapters.js +6 -11
  10. package/.out/core/mobx/types.d.ts +3 -3
  11. package/.out/index.d.ts +2 -0
  12. package/.out/index.js +2 -0
  13. package/.out/mantine/create_fields_view.js +3 -2
  14. package/.out/mantine/field_view.d.ts +18 -0
  15. package/.out/mantine/field_view.js +16 -0
  16. package/.out/tsconfig.tsbuildinfo +1 -1
  17. package/.out/util/empty.d.ts +1 -0
  18. package/.out/util/empty.js +3 -0
  19. package/.turbo/turbo-build.log +8 -8
  20. package/.turbo/turbo-check-types.log +1 -1
  21. package/core/mobx/field_adapter.ts +9 -0
  22. package/core/mobx/form_model.ts +26 -16
  23. package/core/mobx/hooks.tsx +2 -2
  24. package/core/mobx/merge_field_adapters_with_two_way_converter.ts +2 -1
  25. package/core/mobx/specs/form_model.tests.ts +35 -20
  26. package/core/mobx/specs/sub_form_field_adapters.tests.ts +14 -34
  27. package/core/mobx/sub_form_field_adapters.ts +11 -26
  28. package/core/mobx/types.ts +10 -7
  29. package/dist/index.cjs +94 -61
  30. package/dist/index.d.cts +32 -12
  31. package/dist/index.d.ts +32 -12
  32. package/dist/index.js +83 -51
  33. package/index.ts +2 -0
  34. package/mantine/create_fields_view.tsx +6 -2
  35. package/mantine/field_view.tsx +39 -0
  36. package/package.json +1 -1
  37. package/util/empty.tsx +3 -0
@@ -0,0 +1 @@
1
+ export declare function Empty(): null;
@@ -0,0 +1,3 @@
1
+ export function Empty() {
2
+ return null;
3
+ }
@@ -7,12 +7,12 @@ $ tsup
7
7
  CLI Target: es6
8
8
  CJS Build start
9
9
  ESM Build start
10
- CJS dist/index.cjs 59.07 KB
11
- CJS ⚡️ Build success in 158ms
12
- ESM dist/index.js 55.30 KB
13
- ESM ⚡️ Build success in 159ms
10
+ CJS dist/index.cjs 59.76 KB
11
+ CJS ⚡️ Build success in 115ms
12
+ ESM dist/index.js 55.85 KB
13
+ ESM ⚡️ Build success in 122ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 9941ms
16
- DTS dist/index.d.cts 36.50 KB
17
- DTS dist/index.d.ts 36.50 KB
18
- Done in 11.06s.
15
+ DTS ⚡️ Build success in 9788ms
16
+ DTS dist/index.d.cts 37.25 KB
17
+ DTS dist/index.d.ts 37.25 KB
18
+ Done in 10.94s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 7.59s.
3
+ Done in 7.58s.
@@ -38,3 +38,12 @@ export type ValuePathOfFieldAdapter<C extends FieldAdapter> = C extends FieldAda
38
38
  infer ValuePath
39
39
  > ? ValuePath
40
40
  : never
41
+
42
+ export type ContextOfFieldAdapter<F extends FieldAdapter> = F extends FieldAdapter<
43
+ infer _From,
44
+ infer _To,
45
+ infer _E,
46
+ infer _P,
47
+ infer Context
48
+ > ? Context
49
+ : never
@@ -102,13 +102,14 @@ export type ValuePathsToAdaptersOf<
102
102
  }
103
103
  : never
104
104
 
105
- export class FormModel<
105
+ export abstract class FormModel<
106
106
  T extends Type,
107
107
  ValueToTypePaths extends Readonly<Record<string, string>>,
108
108
  TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<
109
109
  FlattenedValuesOfType<T, '*'>,
110
- ValueOfType<ReadonlyTypeOfType<T>>
110
+ ContextType
111
111
  >,
112
+ ContextType = {},
112
113
  ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<
113
114
  TypePathsToAdapters,
114
115
  ValueToTypePaths
@@ -130,6 +131,7 @@ export class FormModel<
130
131
  ) {
131
132
  this.value = mobxCopy(type, value)
132
133
  this.flattenedTypeDefs = flattenTypesOfType(type)
134
+ const contextValue = this.toContext(value)
133
135
  // pre-populate field overrides for consistent behavior when default information is overwritten
134
136
  // then returned to
135
137
  const conversions = flattenValueTo(
@@ -156,7 +158,8 @@ export class FormModel<
156
158
  // no need to store a temporary value if the value cannot be written back
157
159
  return
158
160
  }
159
- return convert(value, valuePath, this.value)
161
+ // cannot call this.context yet as the "this" pointer has not been fully created
162
+ return convert(value, valuePath, contextValue)
160
163
  },
161
164
  )
162
165
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -165,6 +168,13 @@ export class FormModel<
165
168
  }) as FlattenedFieldOverrides<ValuePathsToAdapters>
166
169
  }
167
170
 
171
+ @computed.struct
172
+ get context() {
173
+ return this.toContext(this.value)
174
+ }
175
+
176
+ protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>): ContextType
177
+
168
178
  @computed
169
179
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>> {
170
180
  return new Proxy<SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>>(
@@ -248,14 +258,14 @@ export class FormModel<
248
258
  ? mobxCopy(
249
259
  fieldTypeDef,
250
260
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
251
- create(valuePath as string, this.value),
261
+ create(valuePath as string, this.context),
252
262
  )
253
263
  // fake values can't be copied
254
264
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
255
- : create(valuePath as string, this.value),
265
+ : create(valuePath as string, this.context),
256
266
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
257
267
  valuePath as string,
258
- this.value,
268
+ this.context,
259
269
  )
260
270
  const error = this.errors[valuePath]
261
271
  return {
@@ -341,7 +351,7 @@ export class FormModel<
341
351
  : elementAdapter.create(
342
352
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
343
353
  elementTypePath as string,
344
- this.value,
354
+ this.context,
345
355
  )
346
356
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
347
357
  const originalList: any[] = accessor.value
@@ -486,7 +496,7 @@ export class FormModel<
486
496
  assertExists(revert, 'setting value not supported {}', valuePath)
487
497
 
488
498
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
489
- const conversion = revert(value, valuePath as any, this.value)
499
+ const conversion = revert(value, valuePath as any, this.context)
490
500
  const accessor = this.getAccessorForValuePath(valuePath)
491
501
  return runInAction(() => {
492
502
  this.fieldOverrides[valuePath] = [value]
@@ -529,10 +539,10 @@ export class FormModel<
529
539
  convert,
530
540
  create,
531
541
  } = adapter
532
- const value = create(valuePath, this.value)
542
+ const value = create(valuePath, this.context)
533
543
  const {
534
544
  value: displayValue,
535
- } = convert(value, valuePath, this.value)
545
+ } = convert(value, valuePath, this.context)
536
546
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
537
547
  const key = valuePath as unknown as keyof ValuePathsToAdapters
538
548
  runInAction(() => {
@@ -573,10 +583,10 @@ export class FormModel<
573
583
  accessor != null
574
584
  ? accessor.value
575
585
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
576
- : create(valuePath as string, this.value),
586
+ : create(valuePath as string, this.context),
577
587
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
578
588
  valuePath as string,
579
- this.value,
589
+ this.context,
580
590
  )
581
591
  const value = fieldOverride != null
582
592
  ? fieldOverride[0]
@@ -586,13 +596,13 @@ export class FormModel<
586
596
  if (ignoreDefaultValue) {
587
597
  const {
588
598
  value: defaultDisplayValue,
589
- } = convert(create(valuePath, this.value), valuePath, this.value)
599
+ } = convert(create(valuePath, this.context), valuePath, this.context)
590
600
  if (defaultDisplayValue === value) {
591
601
  return true
592
602
  }
593
603
  }
594
604
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
595
- const conversion = revert(value, valuePath as string, this.value)
605
+ const conversion = revert(value, valuePath as string, this.context)
596
606
  return runInAction(() => {
597
607
  switch (conversion.type) {
598
608
  case UnreliableFieldConversionType.Failure:
@@ -645,14 +655,14 @@ export class FormModel<
645
655
  const fieldOverride = this.fieldOverrides[adapterPath]
646
656
  const {
647
657
  value: storedValue,
648
- } = convert(accessor.value, valuePath, this.value)
658
+ } = convert(accessor.value, valuePath, this.context)
649
659
  const value = fieldOverride != null
650
660
  ? fieldOverride[0]
651
661
  : storedValue
652
662
  // TODO more nuanced comparison
653
663
  const dirty = fieldOverride != null && fieldOverride[0] !== storedValue
654
664
 
655
- const conversion = revert(value, valuePath, this.value)
665
+ const conversion = revert(value, valuePath, this.context)
656
666
  switch (conversion.type) {
657
667
  case UnreliableFieldConversionType.Failure:
658
668
  this.errors[adapterPath] = conversion.error
@@ -13,13 +13,13 @@ import {
13
13
  } from './types'
14
14
 
15
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- type ValueOfModel<M extends FormModel<any, any, any, any>> = M extends FormModel<infer T, any, any, any>
16
+ type ValueOfModel<M extends FormModel<any, any, any, any, any>> = M extends FormModel<infer T, any, any, any, any>
17
17
  ? ValueOfType<ReadonlyTypeOfType<T>>
18
18
  : never
19
19
 
20
20
  export function useDefaultMobxFormHooks<
21
21
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- M extends FormModel<any, any, any, any>,
22
+ M extends FormModel<any, any, any, any, any>,
23
23
  F extends FormFieldsOfModel<M> = FormFieldsOfModel<M>,
24
24
  >(
25
25
  model: M,
@@ -5,6 +5,7 @@ import {
5
5
  } from 'field_converters/chain_field_converter'
6
6
  import { type TwoWayFieldConverter } from 'types/field_converters'
7
7
  import {
8
+ type ContextOfFieldAdapter,
8
9
  type ErrorOfFieldAdapter,
9
10
  type FieldAdapter,
10
11
  type FromOfFieldAdapter,
@@ -22,7 +23,7 @@ export type MergedOfFieldAdaptersWithTwoWayConverter<
22
23
  ToOfFieldAdapter<FieldAdapters[K]>,
23
24
  ErrorOfFieldAdapter<FieldAdapters[K]> | E,
24
25
  ValuePathOfFieldAdapter<FieldAdapters[K]>,
25
- Context
26
+ ContextOfFieldAdapter<FieldAdapters[K]> & Context
26
27
  >
27
28
  }
28
29
 
@@ -8,6 +8,7 @@ import {
8
8
  object,
9
9
  record,
10
10
  stringType,
11
+ type Type,
11
12
  union,
12
13
  type ValueOfType,
13
14
  type ValueToTypePathsOfType,
@@ -45,6 +46,21 @@ const originalIntegerToStringAdapter = adapterFromTwoWayConverter(
45
46
 
46
47
  const originalBooleanToBooleanAdapter = identityAdapter(false)
47
48
 
49
+ class TestFormModel<
50
+ T extends Type,
51
+ ValueToTypePaths extends Readonly<Record<string, string>>,
52
+ TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<
53
+ FlattenedValuesOfType<T, '*'>,
54
+ {}
55
+ >,
56
+ > extends FormModel<T, ValueToTypePaths, TypePathsToAdapters, {}> {
57
+ override toContext() {
58
+ return {
59
+ ctx: true,
60
+ }
61
+ }
62
+ }
63
+
48
64
  describe('all', function () {
49
65
  const integerToStringAdapter = createMockedAdapter(
50
66
  originalIntegerToStringAdapter,
@@ -171,7 +187,7 @@ describe('all', function () {
171
187
  >
172
188
  beforeEach(function () {
173
189
  originalValue = 5
174
- model = new FormModel<
190
+ model = new TestFormModel<
175
191
  typeof typeDef,
176
192
  ValueToTypePathsOfType<typeof typeDef>,
177
193
  typeof adapters
@@ -231,7 +247,7 @@ describe('all', function () {
231
247
  readonly: false,
232
248
  })
233
249
  originalValue = 5
234
- model = new FormModel<
250
+ model = new TestFormModel<
235
251
  typeof typeDef,
236
252
  ValueToTypePathsOfType<typeof typeDef>,
237
253
  typeof adapters
@@ -272,7 +288,7 @@ describe('all', function () {
272
288
  4,
273
289
  17,
274
290
  ]
275
- model = new FormModel<
291
+ model = new TestFormModel<
276
292
  typeof typeDef,
277
293
  ValueToTypePathsOfType<typeof typeDef>,
278
294
  typeof adapters
@@ -350,7 +366,7 @@ describe('all', function () {
350
366
  a: 1,
351
367
  b: 2,
352
368
  }
353
- model = new FormModel<
369
+ model = new TestFormModel<
354
370
  typeof typeDef,
355
371
  ValueToTypePathsOfType<typeof typeDef>,
356
372
  typeof converters
@@ -420,7 +436,7 @@ describe('all', function () {
420
436
  a: 1,
421
437
  b: true,
422
438
  }
423
- model = new FormModel<
439
+ model = new TestFormModel<
424
440
  typeof typeDef,
425
441
  ValueToTypePathsOfType<typeof typeDef>,
426
442
  typeof converters
@@ -485,7 +501,7 @@ describe('all', function () {
485
501
  typeof adapters
486
502
  >
487
503
  beforeEach(function () {
488
- model = new FormModel<
504
+ model = new TestFormModel<
489
505
  typeof typeDef,
490
506
  ValueToTypePathsOfType<typeof typeDef>,
491
507
  typeof adapters
@@ -611,7 +627,7 @@ describe('all', function () {
611
627
  3,
612
628
  7,
613
629
  ]
614
- model = new FormModel<
630
+ model = new TestFormModel<
615
631
  typeof typeDef,
616
632
  ValueToTypePathsOfType<typeof typeDef>,
617
633
  typeof converters
@@ -727,7 +743,7 @@ describe('all', function () {
727
743
  let contextCopy: number[]
728
744
  beforeEach(function () {
729
745
  integerToStringAdapter.revert.mockImplementationOnce(function (_value, _path, context) {
730
- contextCopy = [...context]
746
+ contextCopy = { ...context }
731
747
  return {
732
748
  type: UnreliableFieldConversionType.Success,
733
749
  value: 1,
@@ -742,17 +758,16 @@ describe('all', function () {
742
758
  expect(integerToStringAdapter.revert).toHaveBeenCalledWith(
743
759
  '4',
744
760
  '$.2',
745
- // uses the same pointer
746
- model.value,
761
+ {
762
+ ctx: true,
763
+ },
747
764
  )
748
765
  })
749
766
 
750
- it('supplies the context as it is at the time call', function () {
751
- expect(contextCopy).toEqual([
752
- 1,
753
- 3,
754
- 7,
755
- ])
767
+ it('supplies the context', function () {
768
+ expect(contextCopy).toEqual({
769
+ ctx: true,
770
+ })
756
771
  })
757
772
  })
758
773
 
@@ -953,7 +968,7 @@ describe('all', function () {
953
968
  >
954
969
  beforeEach(function () {
955
970
  originalValue = null
956
- model = new FormModel<
971
+ model = new TestFormModel<
957
972
  typeof type,
958
973
  ValueToTypePaths,
959
974
  typeof adapters
@@ -1018,7 +1033,7 @@ describe('all', function () {
1018
1033
 
1019
1034
  describe('isValuePathActive', function () {
1020
1035
  describe('discriminator x', function () {
1021
- const model = new FormModel<
1036
+ const model = new TestFormModel<
1022
1037
  typeof type,
1023
1038
  ValueToTypePaths,
1024
1039
  typeof adapters
@@ -1050,7 +1065,7 @@ describe('all', function () {
1050
1065
  })
1051
1066
 
1052
1067
  describe('discriminator y', function () {
1053
- const model = new FormModel<
1068
+ const model = new TestFormModel<
1054
1069
  typeof type,
1055
1070
  ValueToTypePaths,
1056
1071
  typeof adapters
@@ -1102,7 +1117,7 @@ describe('all', function () {
1102
1117
  >
1103
1118
  beforeEach(function () {
1104
1119
  originalValue = 1
1105
- model = new FormModel<
1120
+ model = new TestFormModel<
1106
1121
  typeof typeDef,
1107
1122
  JsonPaths,
1108
1123
  typeof converters
@@ -1,9 +1,3 @@
1
- import {
2
- list,
3
- numberType,
4
- object,
5
- stringType,
6
- } from '@strictly/define'
7
1
  import { type FieldAdapter } from 'core/mobx/field_adapter'
8
2
  import {
9
3
  subFormFieldAdapters,
@@ -19,7 +13,6 @@ describe('subFormFieldAdapters', () => {
19
13
  const adapters = subFormFieldAdapters(
20
14
  {},
21
15
  '$.a',
22
- stringType,
23
16
  )
24
17
 
25
18
  it('equals expected type', () => {
@@ -35,19 +28,16 @@ describe('subFormFieldAdapters', () => {
35
28
  const mockedFieldAdapter1 = mockDeep<Required<FieldAdapter<string, boolean, number, '$', string>>>()
36
29
  const fieldAdapter1: FieldAdapter<string, boolean, number, '$', string> = mockedFieldAdapter1
37
30
 
38
- const type = object().field('a', stringType)
39
31
  const subAdapters = {
40
32
  $: fieldAdapter1,
41
33
  } as const
42
34
  const adapters = subFormFieldAdapters<
43
35
  typeof subAdapters,
44
36
  '$.a',
45
- { '$.a': '$.a' },
46
- typeof type
37
+ { '$.a': '$.a' }
47
38
  >(
48
39
  subAdapters,
49
40
  '$.a',
50
- type,
51
41
  )
52
42
 
53
43
  beforeEach(() => {
@@ -58,9 +48,7 @@ describe('subFormFieldAdapters', () => {
58
48
  // TODO toEqualTypeOf (cannot reason about revert optionality, seems to be a TS issue as they
59
49
  // are both optional AFAICT)
60
50
  expectTypeOf(adapters).toMatchTypeOf<{
61
- '$.a': FieldAdapter<string, boolean, number, '$.a', {
62
- a: string,
63
- }>,
51
+ '$.a': FieldAdapter<string, boolean, number, '$.a', string>,
64
52
  }>()
65
53
  })
66
54
 
@@ -76,7 +64,7 @@ describe('subFormFieldAdapters', () => {
76
64
  }
77
65
  mockedFieldAdapter1.convert.mockReturnValue(mockedReturnedValue)
78
66
 
79
- const returnedValue = adapters['$.a'].convert('x', '$.a', { a: 'y' })
67
+ const returnedValue = adapters['$.a'].convert('x', '$.a', 'y')
80
68
  expect(fieldAdapter1.convert).toHaveBeenCalledWith('x', '$', 'y')
81
69
  expect(returnedValue).toEqual(mockedReturnedValue)
82
70
  })
@@ -88,7 +76,7 @@ describe('subFormFieldAdapters', () => {
88
76
  } as const
89
77
  mockedFieldAdapter1.revert.mockReturnValue(mockedReturnedValue)
90
78
 
91
- const returnedValue = adapters['$.a'].revert?.(true, '$.a', { a: 'y' })
79
+ const returnedValue = adapters['$.a'].revert?.(true, '$.a', 'y')
92
80
  expect(fieldAdapter1.revert).toHaveBeenCalledWith(true, '$', 'y')
93
81
  expect(returnedValue).toEqual(mockedReturnedValue)
94
82
  })
@@ -97,7 +85,7 @@ describe('subFormFieldAdapters', () => {
97
85
  const mockedReturnedValue = 'x'
98
86
  mockedFieldAdapter1.create.mockReturnValue(mockedReturnedValue)
99
87
 
100
- const returnedValue = adapters['$.a'].create('$.a', { a: 'y' })
88
+ const returnedValue = adapters['$.a'].create('$.a', 'y')
101
89
  expect(fieldAdapter1.create).toHaveBeenCalledWith('$', 'y')
102
90
  expect(returnedValue).toEqual(mockedReturnedValue)
103
91
  })
@@ -109,15 +97,12 @@ describe('subFormFieldAdapters', () => {
109
97
  const mockedFieldAdapter2 = mockDeep<FieldAdapter<number, boolean>>()
110
98
  const fieldAdapter2: FieldAdapter<number, boolean> = mockedFieldAdapter2
111
99
 
112
- const type = object()
113
- .field('a', object().field('x', stringType).field('y', numberType))
114
100
  const adapters = subFormFieldAdapters(
115
101
  {
116
102
  '$.x': fieldAdapter1,
117
103
  '$.y': fieldAdapter2,
118
104
  },
119
105
  '$.a',
120
- type,
121
106
  )
122
107
 
123
108
  beforeEach(() => {
@@ -141,12 +126,11 @@ describe('subFormFieldAdapters', () => {
141
126
  })
142
127
 
143
128
  describe('calls convert with correct paths and values', () => {
144
- const subContext = {
145
- x: 'a',
146
- y: 1,
147
- } as const
148
129
  const context = {
149
- a: subContext,
130
+ a: {
131
+ x: 'a',
132
+ y: 1,
133
+ },
150
134
  }
151
135
 
152
136
  it('calls $.a.x', () => {
@@ -158,7 +142,7 @@ describe('subFormFieldAdapters', () => {
158
142
  mockedFieldAdapter1.convert.mockReturnValue(mockedReturnedValue)
159
143
 
160
144
  const returnedValue = adapters['$.a.x'].convert('b', '$.a.x', context)
161
- expect(fieldAdapter1.convert).toHaveBeenCalledWith('b', '$.x', subContext)
145
+ expect(fieldAdapter1.convert).toHaveBeenCalledWith('b', '$.x', context)
162
146
  expect(returnedValue).toEqual(mockedReturnedValue)
163
147
  })
164
148
 
@@ -171,7 +155,7 @@ describe('subFormFieldAdapters', () => {
171
155
  mockedFieldAdapter2.convert.mockReturnValue(mockedReturnedValue)
172
156
 
173
157
  const returnedValue = adapters['$.a.y'].convert(2, '$.a.y', context)
174
- expect(fieldAdapter2.convert).toHaveBeenCalledWith(2, '$.y', subContext)
158
+ expect(fieldAdapter2.convert).toHaveBeenCalledWith(2, '$.y', context)
175
159
  expect(returnedValue).toEqual(mockedReturnedValue)
176
160
  })
177
161
  })
@@ -180,7 +164,6 @@ describe('subFormFieldAdapters', () => {
180
164
  describe('list adapter', () => {
181
165
  const mockedFieldAdapter1 = mockDeep<Required<FieldAdapter<string, boolean, number, '$', string>>>()
182
166
  const fieldAdapter1: FieldAdapter<string, boolean, number, '$', string> = mockedFieldAdapter1
183
- const type = list(stringType)
184
167
  const subAdapters = {
185
168
  $: fieldAdapter1,
186
169
  }
@@ -189,12 +172,10 @@ describe('subFormFieldAdapters', () => {
189
172
  '$.*',
190
173
  {
191
174
  '$.*': `$.${number}`,
192
- },
193
- typeof type
175
+ }
194
176
  >(
195
177
  subAdapters,
196
178
  '$.*',
197
- type,
198
179
  )
199
180
 
200
181
  beforeEach(() => {
@@ -204,7 +185,7 @@ describe('subFormFieldAdapters', () => {
204
185
  it('equals expected type', () => {
205
186
  // TODO toEqualTypeOf (seems to be a TS error)
206
187
  expectTypeOf(adapters).toMatchTypeOf<{
207
- '$.*': FieldAdapter<string, boolean, number, `$.${number}`, string[]>,
188
+ '$.*': FieldAdapter<string, boolean, number, `$.${number}`, string>,
208
189
  }>()
209
190
  })
210
191
 
@@ -216,7 +197,6 @@ describe('subFormFieldAdapters', () => {
216
197
 
217
198
  describe('calls convert with correct paths and values', () => {
218
199
  const subContext = 'a'
219
- const context = [subContext]
220
200
 
221
201
  it('calls $.*', () => {
222
202
  const mockedReturnedValue = {
@@ -226,7 +206,7 @@ describe('subFormFieldAdapters', () => {
226
206
  }
227
207
  mockedFieldAdapter1.convert.mockReturnValue(mockedReturnedValue)
228
208
 
229
- const returnedValue = adapters['$.*'].convert('b', '$.0', context)
209
+ const returnedValue = adapters['$.*'].convert('b', '$.0', subContext)
230
210
  expect(fieldAdapter1.convert).toHaveBeenCalledWith('b', '$', subContext)
231
211
  expect(returnedValue).toEqual(mockedReturnedValue)
232
212
  })
@@ -1,11 +1,6 @@
1
1
  import { type StringConcatOf } from '@strictly/base'
2
2
  import {
3
- flattenValuesOfType,
4
- type ReadonlyTypeOfType,
5
- type Type,
6
- type ValueOfType,
7
- } from '@strictly/define'
8
- import {
3
+ type ContextOfFieldAdapter,
9
4
  type ErrorOfFieldAdapter,
10
5
  type FieldAdapter,
11
6
  type FromOfFieldAdapter,
@@ -13,29 +8,27 @@ import {
13
8
  type ValuePathOfFieldAdapter,
14
9
  } from './field_adapter'
15
10
 
16
- type SubFormFieldAdapter<F extends FieldAdapter, ValuePath extends string, Context> = FieldAdapter<
11
+ type SubFormFieldAdapter<F extends FieldAdapter, ValuePath extends string> = FieldAdapter<
17
12
  FromOfFieldAdapter<F>,
18
13
  ToOfFieldAdapter<F>,
19
14
  ErrorOfFieldAdapter<F>,
20
15
  ValuePathOfFieldAdapter<F> extends StringConcatOf<'$', infer ValuePathSuffix> ? `${ValuePath}${ValuePathSuffix}`
21
16
  // assume string (they don't care about the value path as a type) if there the path doesn't have a $ prefix
22
17
  : string,
23
- Context
18
+ ContextOfFieldAdapter<F>
24
19
  >
25
20
 
26
21
  type SubFormFieldAdapters<
27
22
  SubAdapters extends Record<string, FieldAdapter>,
28
23
  TypePath extends string,
29
24
  ValuePath extends string,
30
- Context,
31
25
  > = {
32
26
  [
33
27
  K in keyof SubAdapters as K extends StringConcatOf<'$', infer TypePathSuffix> ? `${TypePath}${TypePathSuffix}`
34
28
  : never
35
29
  ]: SubFormFieldAdapter<
36
30
  SubAdapters[K],
37
- ValuePath,
38
- Context
31
+ ValuePath
39
32
  >
40
33
  }
41
34
 
@@ -43,27 +36,20 @@ export function subFormFieldAdapters<
43
36
  SubAdapters extends Record<string, FieldAdapter>,
44
37
  TypePath extends string,
45
38
  TypePathsToValuePaths extends Record<TypePath, string>,
46
- ContextType extends Type,
47
39
  >(
48
40
  subAdapters: SubAdapters,
49
41
  parentTypePath: TypePath,
50
- contextType: ContextType,
51
42
  ): SubFormFieldAdapters<
52
43
  SubAdapters,
53
44
  TypePath,
54
- TypePathsToValuePaths[TypePath],
55
- ValueOfType<ReadonlyTypeOfType<ContextType>>
45
+ TypePathsToValuePaths[TypePath]
56
46
  > {
57
47
  // assume the number of '.' in the type path will correspond to the number of '.' in the value path
58
48
  const dotCount = parentTypePath.split('.').length
59
- function getSubValuePathAndContext(valuePath: string, context: ValueOfType<ReadonlyTypeOfType<ContextType>>) {
49
+ function getSubValuePath(valuePath: string) {
60
50
  const parentValuePath = valuePath.split('.').slice(0, dotCount).join('.')
61
51
  const subValuePath = valuePath.replace(parentValuePath, '$')
62
- const subContext = flattenValuesOfType(contextType, context)[parentValuePath]
63
- return [
64
- subValuePath,
65
- subContext,
66
- ] as const
52
+ return subValuePath
67
53
  }
68
54
 
69
55
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -75,13 +61,13 @@ export function subFormFieldAdapters<
75
61
  // adapt field adapter with new path and context
76
62
  const adaptedAdapter: FieldAdapter = {
77
63
  convert: (from, valuePath, context) => {
78
- return subAdapter.convert(from, ...getSubValuePathAndContext(valuePath, context))
64
+ return subAdapter.convert(from, getSubValuePath(valuePath), context)
79
65
  },
80
66
  create: (valuePath, context) => {
81
- return subAdapter.create(...getSubValuePathAndContext(valuePath, context))
67
+ return subAdapter.create(getSubValuePath(valuePath), context)
82
68
  },
83
69
  revert: subAdapter.revert && ((from, valuePath, context) => {
84
- return subAdapter.revert!(from, ...getSubValuePathAndContext(valuePath, context))
70
+ return subAdapter.revert!(from, getSubValuePath(valuePath), context)
85
71
  }),
86
72
  }
87
73
  acc[typePath] = adaptedAdapter
@@ -89,7 +75,6 @@ export function subFormFieldAdapters<
89
75
  }, {}) as SubFormFieldAdapters<
90
76
  SubAdapters,
91
77
  TypePath,
92
- TypePathsToValuePaths[TypePath],
93
- ValueOfType<ReadonlyTypeOfType<ContextType>>
78
+ TypePathsToValuePaths[TypePath]
94
79
  >
95
80
  }