@strictly/react-form 0.0.1 → 0.0.2

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 (173) hide show
  1. package/.out/core/mobx/field_adapter.d.ts +7 -6
  2. package/.out/core/mobx/field_adapter_builder.d.ts +12 -13
  3. package/.out/core/mobx/field_adapter_builder.js +8 -12
  4. package/.out/core/mobx/field_adapters_of_values.d.ts +4 -0
  5. package/.out/core/mobx/flattened_adapters_of_fields.d.ts +2 -2
  6. package/.out/core/mobx/flattened_list_types_of_type.d.ts +8 -0
  7. package/.out/core/mobx/form_fields_of_field_adapters.d.ts +8 -0
  8. package/.out/core/mobx/form_presenter.d.ts +21 -24
  9. package/.out/core/mobx/form_presenter.js +64 -69
  10. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.d.ts +13 -0
  11. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.js +11 -0
  12. package/.out/core/mobx/merge_field_adapters_with_validators.d.ts +11 -0
  13. package/.out/core/mobx/merge_field_adapters_with_validators.js +45 -0
  14. package/.out/core/mobx/specs/fixtures.d.ts +7 -0
  15. package/.out/core/mobx/specs/fixtures.js +20 -0
  16. package/.out/core/mobx/specs/flattened_adapters_of_fields.tests.js +5 -2
  17. package/.out/core/mobx/specs/{flattened_list_type_defs_of.tests.js → flattened_list_types_of_types.tests.js} +7 -7
  18. package/.out/core/mobx/specs/form_presenter.tests.js +162 -60
  19. package/.out/core/mobx/specs/merge_field_adapters_with_two_way_converter.js +89 -0
  20. package/.out/core/mobx/specs/merge_field_adapters_with_validators.tests.js +172 -0
  21. package/.out/core/mobx/types.d.ts +2 -2
  22. package/.out/field_converters/chain_field_converter.d.ts +3 -3
  23. package/.out/field_converters/chain_field_converter.js +17 -12
  24. package/.out/field_converters/identity_converter.d.ts +3 -3
  25. package/.out/field_converters/identity_converter.js +10 -6
  26. package/.out/field_converters/integer_to_string_converter.d.ts +5 -4
  27. package/.out/field_converters/integer_to_string_converter.js +13 -6
  28. package/.out/field_converters/list_converter.d.ts +2 -2
  29. package/.out/field_converters/list_converter.js +6 -1
  30. package/.out/field_converters/maybe_identity_converter.d.ts +3 -3
  31. package/.out/field_converters/maybe_identity_converter.js +3 -1
  32. package/.out/field_converters/nullable_to_boolean_converter.d.ts +9 -8
  33. package/.out/field_converters/nullable_to_boolean_converter.js +13 -7
  34. package/.out/field_converters/select_value_type_converter.d.ts +20 -15
  35. package/.out/field_converters/select_value_type_converter.js +29 -14
  36. package/.out/field_converters/specs/chain_field_converter.tests.d.ts +1 -0
  37. package/.out/field_converters/specs/chain_field_converter.tests.js +251 -0
  38. package/.out/field_converters/trimming_string_converter.d.ts +3 -3
  39. package/.out/field_converters/trimming_string_converter.js +7 -3
  40. package/.out/field_converters/validating_converter.d.ts +3 -3
  41. package/.out/field_converters/validating_converter.js +7 -5
  42. package/.out/index.d.ts +9 -2
  43. package/.out/index.js +9 -2
  44. package/.out/mantine/create_checkbox.d.ts +2 -3
  45. package/.out/mantine/create_checkbox.js +6 -5
  46. package/.out/mantine/create_pill.js +2 -2
  47. package/.out/mantine/create_radio.js +1 -1
  48. package/.out/mantine/create_radio_group.d.ts +2 -3
  49. package/.out/mantine/create_radio_group.js +4 -3
  50. package/.out/mantine/create_text_input.d.ts +2 -3
  51. package/.out/mantine/create_text_input.js +6 -5
  52. package/.out/mantine/create_value_input.d.ts +2 -3
  53. package/.out/mantine/create_value_input.js +6 -5
  54. package/.out/mantine/error_renderer.d.ts +6 -0
  55. package/.out/mantine/error_renderer.js +5 -0
  56. package/.out/mantine/hooks.d.ts +9 -13
  57. package/.out/mantine/hooks.js +10 -15
  58. package/.out/mantine/specs/checkbox_hooks.stories.d.ts +7 -2
  59. package/.out/mantine/specs/checkbox_hooks.stories.js +33 -6
  60. package/.out/mantine/specs/list_hooks.stories.js +2 -2
  61. package/.out/mantine/specs/radio_group_hooks.stories.d.ts +7 -2
  62. package/.out/mantine/specs/radio_group_hooks.stories.js +33 -6
  63. package/.out/mantine/specs/select_hooks.stories.d.ts +8 -2
  64. package/.out/mantine/specs/select_hooks.stories.js +45 -8
  65. package/.out/mantine/specs/text_input_hooks.stories.d.ts +5 -1
  66. package/.out/mantine/specs/text_input_hooks.stories.js +23 -8
  67. package/.out/mantine/specs/value_input_hooks.stories.d.ts +7 -2
  68. package/.out/mantine/specs/value_input_hooks.stories.js +49 -15
  69. package/.out/mantine/types.d.ts +4 -1
  70. package/.out/tsconfig.tsbuildinfo +1 -1
  71. package/.out/types/error_of_field.d.ts +2 -0
  72. package/.out/types/error_of_field.js +1 -0
  73. package/.out/types/field.d.ts +1 -1
  74. package/.out/types/field_converters.d.ts +17 -10
  75. package/.out/types/field_converters.js +5 -5
  76. package/.out/types/flattened_validators_of_fields.d.ts +8 -0
  77. package/.out/types/flattened_validators_of_fields.js +1 -0
  78. package/.out/types/merge_validators.d.ts +7 -0
  79. package/.out/types/merge_validators.js +38 -0
  80. package/.out/types/specs/flattened_validators_of_fields.tests.d.ts +1 -0
  81. package/.out/types/specs/flattened_validators_of_fields.tests.js +16 -0
  82. package/.out/types/specs/merge_validators.tests.d.ts +1 -0
  83. package/.out/types/specs/merge_validators.tests.js +192 -0
  84. package/.out/util/partial.d.ts +11 -5
  85. package/.out/util/partial.js +55 -15
  86. package/.turbo/turbo-build.log +9 -9
  87. package/.turbo/turbo-check-types.log +1 -1
  88. package/.turbo/turbo-release$colon$exports.log +1 -1
  89. package/README.md +5 -1
  90. package/core/mobx/field_adapter.ts +15 -7
  91. package/core/mobx/field_adapter_builder.ts +39 -75
  92. package/core/mobx/field_adapters_of_values.ts +17 -0
  93. package/core/mobx/flattened_adapters_of_fields.ts +3 -3
  94. package/core/mobx/flattened_list_types_of_type.ts +17 -0
  95. package/core/mobx/form_fields_of_field_adapters.ts +16 -0
  96. package/core/mobx/form_presenter.ts +117 -104
  97. package/core/mobx/merge_field_adapters_with_two_way_converter.ts +68 -0
  98. package/core/mobx/merge_field_adapters_with_validators.ts +99 -0
  99. package/core/mobx/specs/fixtures.ts +73 -0
  100. package/core/mobx/specs/flattened_adapters_of_fields.tests.ts +23 -2
  101. package/core/mobx/specs/flattened_list_types_of_types.tests.ts +35 -0
  102. package/core/mobx/specs/form_presenter.tests.ts +248 -124
  103. package/core/mobx/specs/merge_field_adapters_with_two_way_converter.ts +140 -0
  104. package/core/mobx/specs/merge_field_adapters_with_validators.tests.ts +259 -0
  105. package/core/mobx/types.ts +3 -3
  106. package/dist/index.cjs +459 -211
  107. package/dist/index.d.cts +153 -111
  108. package/dist/index.d.ts +153 -111
  109. package/dist/index.js +453 -200
  110. package/field_converters/chain_field_converter.ts +37 -23
  111. package/field_converters/identity_converter.ts +14 -10
  112. package/field_converters/integer_to_string_converter.ts +15 -9
  113. package/field_converters/list_converter.ts +8 -3
  114. package/field_converters/maybe_identity_converter.ts +7 -4
  115. package/field_converters/nullable_to_boolean_converter.ts +23 -16
  116. package/field_converters/select_value_type_converter.ts +86 -26
  117. package/field_converters/specs/chain_field_converter.tests.ts +302 -0
  118. package/field_converters/trimming_string_converter.ts +11 -6
  119. package/field_converters/validating_converter.ts +21 -11
  120. package/index.ts +9 -2
  121. package/mantine/create_checkbox.tsx +15 -8
  122. package/mantine/create_list.tsx +1 -4
  123. package/mantine/create_pill.tsx +2 -2
  124. package/mantine/create_radio.tsx +1 -1
  125. package/mantine/create_radio_group.tsx +8 -6
  126. package/mantine/create_text_input.tsx +20 -8
  127. package/mantine/create_value_input.tsx +17 -8
  128. package/mantine/error_renderer.ts +15 -0
  129. package/mantine/hooks.tsx +25 -51
  130. package/mantine/specs/__snapshots__/checkbox_hooks.tests.tsx.snap +126 -0
  131. package/mantine/specs/__snapshots__/radio_group_hooks.tests.tsx.snap +356 -0
  132. package/mantine/specs/__snapshots__/select_hooks.tests.tsx.snap +208 -12
  133. package/mantine/specs/__snapshots__/text_input_hooks.tests.tsx.snap +45 -0
  134. package/mantine/specs/__snapshots__/value_input_hooks.tests.tsx.snap +194 -8
  135. package/mantine/specs/checkbox_hooks.stories.tsx +47 -7
  136. package/mantine/specs/list_hooks.stories.tsx +2 -2
  137. package/mantine/specs/radio_group_hooks.stories.tsx +47 -7
  138. package/mantine/specs/select_hooks.stories.tsx +55 -8
  139. package/mantine/specs/text_input_hooks.stories.tsx +32 -7
  140. package/mantine/specs/value_input_hooks.stories.tsx +57 -16
  141. package/mantine/types.ts +5 -1
  142. package/package.json +16 -4
  143. package/tsconfig.json +1 -0
  144. package/types/error_of_field.ts +3 -0
  145. package/types/field.ts +1 -1
  146. package/types/field_converters.ts +21 -10
  147. package/types/flattened_validators_of_fields.ts +34 -0
  148. package/types/merge_validators.ts +80 -0
  149. package/types/specs/error_type_of_field.tests.ts +2 -2
  150. package/types/specs/flattened_validators_of_fields.tests.ts +93 -0
  151. package/types/specs/merge_validators.tests.ts +267 -0
  152. package/util/partial.tsx +200 -16
  153. package/.out/core/mobx/flattened_list_type_defs_of.d.ts +0 -8
  154. package/.out/field_validators/minimum_string_length_field_validator.d.ts +0 -2
  155. package/.out/field_validators/minimum_string_length_field_validator.js +0 -8
  156. package/.out/types/error_type_of_field.d.ts +0 -2
  157. package/.out/types/field_validator.d.ts +0 -3
  158. package/.out/types/flattened_form_fields_of.d.ts +0 -9
  159. package/.out/types/specs/flattened_form_fields_of.tests.js +0 -13
  160. package/core/mobx/flattened_list_type_defs_of.ts +0 -17
  161. package/core/mobx/specs/flattened_list_type_defs_of.tests.ts +0 -35
  162. package/field_validators/minimum_string_length_field_validator.ts +0 -13
  163. package/mantine/specs/__snapshots__/check_box_hooks.tests.tsx.snap +0 -227
  164. package/types/error_type_of_field.ts +0 -3
  165. package/types/field_validator.ts +0 -7
  166. package/types/flattened_form_fields_of.ts +0 -16
  167. package/types/specs/flattened_form_fields_of.tests.ts +0 -43
  168. /package/.out/core/mobx/{flattened_list_type_defs_of.js → field_adapters_of_values.js} +0 -0
  169. /package/.out/core/mobx/{specs/flattened_list_type_defs_of.tests.d.ts → flattened_list_types_of_type.js} +0 -0
  170. /package/.out/{types/error_type_of_field.js → core/mobx/form_fields_of_field_adapters.js} +0 -0
  171. /package/.out/{types/field_validator.js → core/mobx/specs/flattened_list_types_of_types.tests.d.ts} +0 -0
  172. /package/.out/{types/flattened_form_fields_of.js → core/mobx/specs/merge_field_adapters_with_two_way_converter.d.ts} +0 -0
  173. /package/.out/{types/specs/flattened_form_fields_of.tests.d.ts → core/mobx/specs/merge_field_adapters_with_validators.tests.d.ts} +0 -0
@@ -1,9 +1,10 @@
1
- import { type FieldConverter, type FieldValueFactory, type SafeFieldConverter } from 'types/field_converters';
1
+ import { type AnnotatedFieldConverter, type FieldValueFactory, type UnreliableFieldConverter } from 'types/field_converters';
2
2
  export type FieldAdapter<From = any, To = any, E = any, ValuePath extends string = any, Context = any> = {
3
- readonly convert: SafeFieldConverter<From, To, ValuePath, Context>;
3
+ readonly convert: AnnotatedFieldConverter<From, To, ValuePath, Context>;
4
4
  readonly create: FieldValueFactory<From, ValuePath, Context>;
5
- readonly revert?: FieldConverter<To, From, E, ValuePath, Context>;
5
+ readonly revert?: UnreliableFieldConverter<To, From, E, ValuePath, Context>;
6
6
  };
7
- export type FromTypeOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer From> ? From : never;
8
- export type ToTypeOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer _F, infer To> ? To : never;
9
- export type ErrorTypeOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer _From, infer _To, infer E> ? NonNullable<E> : never;
7
+ export type FromOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer From> ? From : never;
8
+ export type ToOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer _F, infer To> ? To : never;
9
+ export type ErrorOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer _From, infer _To, infer E> ? NonNullable<E> : never;
10
+ export type ValuePathOfFieldAdapter<C extends FieldAdapter> = C extends FieldAdapter<infer _From, infer _To, infer _E, infer ValuePath> ? ValuePath : never;
@@ -1,22 +1,21 @@
1
- import { type FieldConverter, type FieldValueFactory, type SafeFieldConverter, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory } from 'types/field_converters';
2
- import { type FieldValidator } from 'types/field_validator';
1
+ import { type AnnotatedFieldConverter, type FieldValueFactory, type TwoWayFieldConverter, type TwoWayFieldConverterWithValueFactory, type UnreliableFieldConverter } from 'types/field_converters';
2
+ import { type FieldAdapter } from './field_adapter';
3
3
  declare class FieldAdapterBuilder<From, To, E, ValuePath extends string, Context> {
4
- readonly convert: SafeFieldConverter<From, To, ValuePath, Context>;
4
+ readonly convert: AnnotatedFieldConverter<From, To, ValuePath, Context>;
5
5
  readonly create: FieldValueFactory<From, ValuePath, Context>;
6
- readonly revert?: FieldConverter<To, From, E, ValuePath, Context> | undefined;
7
- constructor(convert: SafeFieldConverter<From, To, ValuePath, Context>, create: FieldValueFactory<From, ValuePath, Context>, revert?: FieldConverter<To, From, E, ValuePath, Context> | undefined);
8
- validateFrom<E2>(...validators: readonly FieldValidator<From, E2, ValuePath, Context>[]): FieldAdapterBuilder<From, To, E | E2, ValuePath, Context>;
9
- validateTo<E2>(...validators: readonly FieldValidator<To, E2, ValuePath, Context>[]): FieldAdapterBuilder<From, To, E | E2, ValuePath, Context>;
10
- chain<To2, E2 = E>(converter: SafeFieldConverter<To, To2, ValuePath, Context>, reverter?: FieldConverter<To2, To, E2, ValuePath, Context>): FieldAdapterBuilder<From, To2, E | E2, ValuePath, Context>;
11
- withReverter(reverter: FieldConverter<To, From, E, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
6
+ readonly revert?: UnreliableFieldConverter<To, From, E, ValuePath, Context> | undefined;
7
+ constructor(convert: AnnotatedFieldConverter<From, To, ValuePath, Context>, create: FieldValueFactory<From, ValuePath, Context>, revert?: UnreliableFieldConverter<To, From, E, ValuePath, Context> | undefined);
8
+ chain<To2, E2 = E>(converter: AnnotatedFieldConverter<To, To2, ValuePath, Context>, reverter?: UnreliableFieldConverter<To2, To, E2, ValuePath, Context>): FieldAdapterBuilder<From, To2, E | E2, ValuePath, Context>;
9
+ withReverter(reverter: UnreliableFieldConverter<To, From, E, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
12
10
  withIdentity(isFrom: (from: To | From) => from is From): FieldAdapterBuilder<From, To | From, E, ValuePath, Context>;
11
+ get narrow(): FieldAdapter<From, To, E, ValuePath, Context>;
13
12
  }
14
- export declare function adapter<From, To, ValuePath extends string, Context>(converter: SafeFieldConverter<From, To, ValuePath, Context>, valueFactory: FieldValueFactory<From, ValuePath, Context>): FieldAdapterBuilder<From, To, never, ValuePath, Context>;
15
- export declare function adapter<From, To, E, ValuePath extends string, Context>(converter: SafeFieldConverter<From, To, ValuePath, Context>, valueFactory: FieldValueFactory<From, ValuePath, Context>, reverter: FieldConverter<To, From, E, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
13
+ export declare function adapter<From, To, ValuePath extends string, Context>(converter: AnnotatedFieldConverter<From, To, ValuePath, Context>, valueFactory: FieldValueFactory<From, ValuePath, Context>): FieldAdapterBuilder<From, To, never, ValuePath, Context>;
14
+ export declare function adapter<From, To, E, ValuePath extends string, Context>(converter: AnnotatedFieldConverter<From, To, ValuePath, Context>, valueFactory: FieldValueFactory<From, ValuePath, Context>, reverter: UnreliableFieldConverter<To, From, E, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
16
15
  export declare function adapterFromTwoWayConverter<From, To, E, ValuePath extends string, Context>(converter: TwoWayFieldConverter<From, To, E, ValuePath, Context>, valueFactory: FieldValueFactory<From, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
17
16
  export declare function adapterFromTwoWayConverter<From, To, E, ValuePath extends string, Context>(converter: TwoWayFieldConverterWithValueFactory<From, To, E, ValuePath, Context>): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
18
- export declare function adapterFromPrototype<From, To, ValuePath extends string, Context>(converter: SafeFieldConverter<From, To, ValuePath, Context>, prototype: From): FieldAdapterBuilder<From, To, never, ValuePath, Context>;
17
+ export declare function adapterFromPrototype<From, To, ValuePath extends string, Context>(converter: AnnotatedFieldConverter<From, To, ValuePath, Context>, prototype: From): FieldAdapterBuilder<From, To, never, ValuePath, Context>;
19
18
  export declare function adapterFromPrototype<From, To, E, ValuePath extends string, Context>(converter: TwoWayFieldConverter<From, To, E, ValuePath, Context>, prototype: From): FieldAdapterBuilder<From, To, E, ValuePath, Context>;
20
- export declare function identityAdapter<V, ValuePath extends string, Context>(prototype: V): FieldAdapterBuilder<V, V, never, ValuePath, Context>;
19
+ export declare function identityAdapter<V, ValuePath extends string, Context>(prototype: V, required?: boolean): FieldAdapterBuilder<V, V, never, ValuePath, Context>;
21
20
  export declare function listAdapter<E, K extends string, ValuePath extends string, Context>(): FieldAdapterBuilder<readonly E[], readonly K[], never, ValuePath, Context>;
22
21
  export {};
@@ -1,8 +1,7 @@
1
- import { chainFieldConverter, chainSafeFieldConverter, } from 'field_converters/chain_field_converter';
2
- import { identityConverter, safeIdentityConverter, } from 'field_converters/identity_converter';
1
+ import { chainAnnotatedFieldConverter, chainUnreliableFieldConverter, } from 'field_converters/chain_field_converter';
2
+ import { annotatedIdentityConverter, unreliableIdentityConverter, } from 'field_converters/identity_converter';
3
3
  import { listConverter } from 'field_converters/list_converter';
4
4
  import { MaybeIdentityConverter } from 'field_converters/maybe_identity_converter';
5
- import { validatingConverter, } from 'field_converters/validating_converter';
6
5
  import { prototypingFieldValueFactory } from 'field_value_factories/prototyping_field_value_factory';
7
6
  class FieldAdapterBuilder {
8
7
  convert;
@@ -13,14 +12,8 @@ class FieldAdapterBuilder {
13
12
  this.create = create;
14
13
  this.revert = revert;
15
14
  }
16
- validateFrom(...validators) {
17
- return new FieldAdapterBuilder(this.convert, this.create, this.revert && chainFieldConverter(this.revert, validatingConverter(validators)));
18
- }
19
- validateTo(...validators) {
20
- return new FieldAdapterBuilder(this.convert, this.create, this.revert && chainFieldConverter(validatingConverter(validators), this.revert));
21
- }
22
15
  chain(converter, reverter) {
23
- return new FieldAdapterBuilder(chainSafeFieldConverter(this.convert, converter), this.create, this.revert && reverter && chainFieldConverter(reverter, this.revert));
16
+ return new FieldAdapterBuilder(chainAnnotatedFieldConverter(this.convert, converter), this.create, this.revert && reverter && chainUnreliableFieldConverter(reverter, this.revert));
24
17
  }
25
18
  withReverter(reverter) {
26
19
  return new FieldAdapterBuilder(this.convert, this.create, reverter);
@@ -33,6 +26,9 @@ class FieldAdapterBuilder {
33
26
  }, isFrom);
34
27
  return new FieldAdapterBuilder(identityConverter.convert.bind(identityConverter), this.create, this.revert && identityConverter.revert.bind(identityConverter));
35
28
  }
29
+ get narrow() {
30
+ return this;
31
+ }
36
32
  }
37
33
  export function adapter(converter, valueFactory, reverter) {
38
34
  return new FieldAdapterBuilder(converter, valueFactory, reverter);
@@ -48,8 +44,8 @@ export function adapterFromPrototype(converter, prototype) {
48
44
  ? new FieldAdapterBuilder(converter, factory)
49
45
  : new FieldAdapterBuilder(converter.convert.bind(converter), factory, converter.revert.bind(converter));
50
46
  }
51
- export function identityAdapter(prototype) {
52
- return new FieldAdapterBuilder(safeIdentityConverter(), prototypingFieldValueFactory(prototype), identityConverter());
47
+ export function identityAdapter(prototype, required) {
48
+ return new FieldAdapterBuilder(annotatedIdentityConverter(required), prototypingFieldValueFactory(prototype), unreliableIdentityConverter());
53
49
  }
54
50
  export function listAdapter() {
55
51
  return new FieldAdapterBuilder(listConverter(), prototypingFieldValueFactory([]));
@@ -0,0 +1,4 @@
1
+ import { type FieldAdapter } from './field_adapter';
2
+ export type FieldAdaptersOfValues<FlattenedValues extends Readonly<Record<string, any>>, TypePathsToValuePaths extends Readonly<Record<keyof FlattenedValues, string>> = Readonly<Record<keyof FlattenedValues, any>>, Context = any> = {
3
+ readonly [K in keyof FlattenedValues]: FieldAdapter<FlattenedValues[K], any, any, TypePathsToValuePaths[K], Context>;
4
+ };
@@ -1,9 +1,9 @@
1
- import { type ReadonlyTypeDefOf, type Type, type ValueTypeOf } from '@strictly/define';
1
+ import { type ReadonlyTypeOfType, type Type, type ValueOfType } from '@strictly/define';
2
2
  import { type FieldAdapter } from 'core/mobx/field_adapter';
3
3
  import { type SimplifyDeep, type ValueOf } from 'type-fest';
4
4
  import { type Field } from 'types/field';
5
5
  export type FlattenedAdaptersOfFields<ValuePathsToTypePaths extends Readonly<Record<string, string>>, FlattenedTypeDefs extends Partial<Readonly<Record<ValueOf<ValuePathsToTypePaths>, Type>>>, FormFields extends Partial<Readonly<Record<keyof ValuePathsToTypePaths, Field>>>> = SimplifyDeep<{
6
6
  readonly [K in keyof ValuePathsToTypePaths as FormFields[K] extends Field ? ValuePathsToTypePaths[K] : never]: AdapterOfField<NonNullable<FormFields[K]>, FlattenedTypeDefs[ValuePathsToTypePaths[K]], K>;
7
7
  }>;
8
- type AdapterOfField<F extends Field, T extends Type | undefined, ValuePath extends string | number | symbol> = ValuePath extends string ? F extends Field<infer V, infer E> ? undefined extends T ? FieldAdapter<V, V, E, ValuePath> : FieldAdapter<ValueTypeOf<ReadonlyTypeDefOf<NonNullable<T>>>, V, E, ValuePath> : never : never;
8
+ type AdapterOfField<F extends Field, T extends Type | undefined, ValuePath extends string | number | symbol> = ValuePath extends string ? F extends Field<infer V, infer E> ? undefined extends T ? FieldAdapter<V, V, E, ValuePath> : FieldAdapter<ValueOfType<ReadonlyTypeOfType<NonNullable<T>>>, V, E, ValuePath> : never : never;
9
9
  export {};
@@ -0,0 +1,8 @@
1
+ import { type FlattenedTypesOfType, type ListTypeDef, type Type } from '@strictly/define';
2
+ import { type SimplifyDeep } from 'type-fest';
3
+ export type ListValuePathsOfType<T extends Type> = keyof FlattenedListTypesOfType<T>;
4
+ export type FlattenedListTypesOfType<T extends Type> = FlattenedListTypesOfTypes<SimplifyDeep<FlattenedTypesOfType<T, null>>>;
5
+ type FlattenedListTypesOfTypes<T extends Readonly<Record<string, Type>>> = {
6
+ [K in keyof T as T[K]['definition'] extends ListTypeDef ? K : never]: T[K];
7
+ };
8
+ export {};
@@ -0,0 +1,8 @@
1
+ import { type ValueOf } from 'type-fest';
2
+ import { type Field } from 'types/field';
3
+ import { type FieldAdapter } from './field_adapter';
4
+ export type FormFieldsOfFieldAdapters<ValuePathsToTypePaths extends Readonly<Record<string, string>>, FieldAdapters extends Partial<Readonly<Record<ValueOf<ValuePathsToTypePaths>, FieldAdapter>>>> = {
5
+ [K in keyof ValuePathsToTypePaths as undefined extends FieldAdapters[ValuePathsToTypePaths[K]] ? never : K]: FormFieldOfFieldAdapter<FieldAdapters[ValuePathsToTypePaths[K]]>;
6
+ };
7
+ type FormFieldOfFieldAdapter<F extends FieldAdapter | undefined> = F extends FieldAdapter<infer _From, infer To, infer E> ? Field<To, E> : never;
8
+ export {};
@@ -1,61 +1,58 @@
1
1
  import { type ElementOfArray, type Maybe } from '@strictly/base';
2
- import { type Accessor, type FlattenedValueTypesOf, type MobxValueTypeOf, type ReadonlyTypeDefOf, type Type, type ValueTypeOf } from '@strictly/define';
2
+ import { type Accessor, type FlattenedValuesOfType, type MobxValueOfType, type ReadonlyTypeOfType, type Type, type ValueOfType } from '@strictly/define';
3
3
  import { type ReadonlyDeep, type SimplifyDeep, type StringKeyOf, type ValueOf } from 'type-fest';
4
4
  import { type Field } from 'types/field';
5
- import { type ErrorTypeOfFieldAdapter, type FieldAdapter, type ToTypeOfFieldAdapter } from './field_adapter';
6
- import { type FlattenedListTypeDefsOf } from './flattened_list_type_defs_of';
5
+ import { type ErrorOfFieldAdapter, type FieldAdapter, type ToOfFieldAdapter } from './field_adapter';
6
+ import { type FlattenedListTypesOfType } from './flattened_list_types_of_type';
7
7
  export type FlattenedConvertedFieldsOf<ValuePathsToAdapters extends Readonly<Record<string, FieldAdapter>>> = {
8
- readonly [K in keyof ValuePathsToAdapters]: Field<ToTypeOfFieldAdapter<ValuePathsToAdapters[K]>, ErrorTypeOfFieldAdapter<ValuePathsToAdapters[K]>>;
8
+ readonly [K in keyof ValuePathsToAdapters]: Field<ToOfFieldAdapter<ValuePathsToAdapters[K]>, ErrorOfFieldAdapter<ValuePathsToAdapters[K]>>;
9
9
  };
10
10
  export type FlattenedTypePathsToAdaptersOf<FlattenedValues extends Readonly<Record<string, any>>, Context> = {
11
11
  readonly [K in keyof FlattenedValues]?: FieldAdapter<ReadonlyDeep<FlattenedValues[K]>, any, any, any, Context>;
12
12
  };
13
- type FieldOverride<V = any> = {
14
- value: V;
15
- };
13
+ type FieldOverride<V = any> = Maybe<V>;
16
14
  type FlattenedFieldOverrides<ValuePathsToAdapters extends Readonly<Record<string, FieldAdapter>>> = {
17
- -readonly [K in keyof ValuePathsToAdapters]?: FieldOverride<ToTypeOfFieldAdapter<ValuePathsToAdapters[K]>>;
15
+ -readonly [K in keyof ValuePathsToAdapters]?: FieldOverride<ToOfFieldAdapter<ValuePathsToAdapters[K]>>;
18
16
  };
19
17
  type FlattenedErrors<ValuePathsToAdapters extends Readonly<Record<string, FieldAdapter>>> = {
20
- -readonly [K in keyof ValuePathsToAdapters]?: ErrorTypeOfFieldAdapter<ValuePathsToAdapters[K]>;
18
+ -readonly [K in keyof ValuePathsToAdapters]?: ErrorOfFieldAdapter<ValuePathsToAdapters[K]>;
21
19
  };
22
20
  export type ValuePathsToAdaptersOf<TypePathsToAdapters extends Partial<Readonly<Record<string, FieldAdapter>>>, ValuePathsToTypePaths extends Readonly<Record<string, string>>> = keyof TypePathsToAdapters extends ValueOf<ValuePathsToTypePaths> ? {
23
21
  readonly [K in keyof ValuePathsToTypePaths as unknown extends TypePathsToAdapters[ValuePathsToTypePaths[K]] ? never : K]: NonNullable<TypePathsToAdapters[ValuePathsToTypePaths[K]]>;
24
22
  } : never;
25
- export declare class FormPresenter<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValueTypesOf<T, '*'>, ValueTypeOf<ReadonlyTypeDefOf<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
26
- readonly typeDef: T;
23
+ export declare class FormPresenter<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ValueOfType<ReadonlyTypeOfType<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
24
+ readonly type: T;
27
25
  private readonly adapters;
28
- constructor(typeDef: T, adapters: TypePathsToAdapters);
26
+ constructor(type: T, adapters: TypePathsToAdapters);
29
27
  private maybeGetAdapterForValuePath;
30
28
  private getAdapterForValuePath;
31
29
  typePath<K extends keyof ValueToTypePaths>(valuePath: K): ValueToTypePaths[K];
32
- setFieldValueAndValidate<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToTypeOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
33
- setFieldValue<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToTypeOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
34
- addListItem<K extends keyof FlattenedListTypeDefsOf<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, elementValue: Maybe<ElementOfArray<FlattenedValueTypesOf<T>[K]>>, index?: number): void;
35
- removeListItem<K extends keyof FlattenedListTypeDefsOf<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, elementValuePath: `${K}.${number}`): void;
30
+ setFieldValueAndValidate<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
31
+ setFieldValue<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>): boolean;
32
+ addListItem<K extends keyof FlattenedListTypesOfType<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K, elementValue?: Maybe<ElementOfArray<FlattenedValuesOfType<T>[K]>>, index?: number): void;
33
+ removeListItem<K extends keyof FlattenedListTypesOfType<T>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, elementValuePath: `${K}.${number}`): void;
36
34
  private internalSetFieldValue;
37
35
  clearFieldError<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): void;
38
36
  clearFieldValue<K extends StringKeyOf<ValuePathsToAdapters>>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): void;
39
- clearAll(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, value: ValueTypeOf<T>): void;
37
+ clearAll(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, value: ValueOfType<T>): void;
38
+ isValuePathActive<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): boolean;
40
39
  validateField<K extends keyof ValuePathsToAdapters>(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>, valuePath: K): boolean;
41
40
  validateAll(model: FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>): boolean;
42
- createModel(value: ValueTypeOf<ReadonlyTypeDefOf<T>>): FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>;
41
+ createModel(value: ValueOfType<ReadonlyTypeOfType<T>>): FormModel<T, ValueToTypePaths, TypePathsToAdapters, ValuePathsToAdapters>;
43
42
  }
44
- export declare class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValueTypesOf<T, '*'>, ValueTypeOf<ReadonlyTypeDefOf<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
45
- private readonly typeDef;
43
+ export declare class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ValueOfType<ReadonlyTypeOfType<T>>>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
44
+ private readonly type;
46
45
  private readonly adapters;
47
- accessor value: MobxValueTypeOf<T>;
46
+ accessor value: MobxValueOfType<T>;
48
47
  accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
49
48
  accessor errors: FlattenedErrors<ValuePathsToAdapters>;
50
49
  private readonly flattenedTypeDefs;
51
- constructor(typeDef: T, value: ValueTypeOf<ReadonlyTypeDefOf<T>>, adapters: TypePathsToAdapters);
50
+ constructor(type: T, value: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters);
52
51
  get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>;
53
52
  private get knownFields();
54
53
  private maybeSynthesizeFieldByValuePath;
55
54
  private synthesizeFieldByPaths;
56
55
  getAccessorForValuePath(valuePath: keyof ValuePathsToAdapters): Accessor | undefined;
57
56
  get accessors(): Readonly<Record<string, Accessor>>;
58
- protected isDisabled(_valuePath: keyof ValuePathsToAdapters): boolean;
59
- protected isRequired(_valuePath: keyof ValuePathsToAdapters): boolean;
60
57
  }
61
58
  export {};
@@ -1,17 +1,17 @@
1
- import { assertExists, assertExistsAndReturn, assertState, checkValidNumber, toArray, UnreachableError, } from '@strictly/base';
2
- import { flattenAccessorsOf, flattenTypeDefsOf, flattenValueTypeTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
1
+ import { assertExists, assertExistsAndReturn, assertState, checkValidNumber, map, toArray, UnreachableError, } from '@strictly/base';
2
+ import { flattenAccessorsOfType, flattenTypesOfType, flattenValuesOfType, flattenValueTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
3
3
  import { computed, observable, runInAction, } from 'mobx';
4
- import { FieldConversionResult, } from 'types/field_converters';
4
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
5
5
  export class FormPresenter {
6
- typeDef;
6
+ type;
7
7
  adapters;
8
- constructor(typeDef, adapters) {
9
- this.typeDef = typeDef;
8
+ constructor(type, adapters) {
9
+ this.type = type;
10
10
  this.adapters = adapters;
11
11
  }
12
12
  maybeGetAdapterForValuePath(valuePath) {
13
13
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
14
- const typePath = valuePathToTypePath(this.typeDef, valuePath, true);
14
+ const typePath = valuePathToTypePath(this.type, valuePath, true);
15
15
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
16
16
  return this.adapters[typePath];
17
17
  }
@@ -19,7 +19,7 @@ export class FormPresenter {
19
19
  return assertExistsAndReturn(this.maybeGetAdapterForValuePath(valuePath), 'expected adapter to be defined {}', valuePath);
20
20
  }
21
21
  typePath(valuePath) {
22
- return valuePathToTypePath(this.typeDef, valuePath, true);
22
+ return valuePathToTypePath(this.type, valuePath, true);
23
23
  }
24
24
  setFieldValueAndValidate(model, valuePath, value) {
25
25
  return this.internalSetFieldValue(model, valuePath, value, true);
@@ -27,7 +27,9 @@ export class FormPresenter {
27
27
  setFieldValue(model, valuePath, value) {
28
28
  return this.internalSetFieldValue(model, valuePath, value, false);
29
29
  }
30
- addListItem(model, valuePath, elementValue, index) {
30
+ addListItem(model, valuePath,
31
+ // TODO can this type be simplified?
32
+ elementValue = null, index) {
31
33
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
32
34
  const listValuePath = valuePath;
33
35
  const accessor = model.accessors[valuePath];
@@ -151,11 +153,9 @@ export class FormPresenter {
151
153
  const conversion = revert(value, valuePath, model.value);
152
154
  const accessor = model.getAccessorForValuePath(valuePath);
153
155
  return runInAction(() => {
154
- model.fieldOverrides[valuePath] = {
155
- value,
156
- };
156
+ model.fieldOverrides[valuePath] = [value];
157
157
  switch (conversion.type) {
158
- case FieldConversionResult.Failure:
158
+ case UnreliableFieldConversionType.Failure:
159
159
  if (displayValidation) {
160
160
  model.errors[valuePath] = conversion.error;
161
161
  }
@@ -163,7 +163,7 @@ export class FormPresenter {
163
163
  accessor.set(conversion.value[0]);
164
164
  }
165
165
  return false;
166
- case FieldConversionResult.Success:
166
+ case UnreliableFieldConversionType.Success:
167
167
  delete model.errors[valuePath];
168
168
  accessor?.set(conversion.value);
169
169
  return true;
@@ -190,12 +190,11 @@ export class FormPresenter {
190
190
  const { convert, create, } = adapter;
191
191
  const accessor = model.accessors[valuePath];
192
192
  const value = accessor == null ? create(valuePath, model.value) : accessor.value;
193
- const displayValue = convert(value, valuePath, model.value);
193
+ const { value: displayValue, } = convert(value, valuePath, model.value);
194
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
195
+ const key = valuePath;
194
196
  runInAction(function () {
195
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
196
- model.fieldOverrides[valuePath] = {
197
- value: displayValue,
198
- };
197
+ model.fieldOverrides[key] = [displayValue];
199
198
  });
200
199
  }
201
200
  clearAll(model, value) {
@@ -203,21 +202,27 @@ export class FormPresenter {
203
202
  model.errors = {};
204
203
  // TODO this isn't correct, should reload from value
205
204
  model.fieldOverrides = {};
206
- model.value = mobxCopy(this.typeDef, value);
205
+ model.value = mobxCopy(this.type, value);
207
206
  });
208
207
  }
208
+ isValuePathActive(model, valuePath) {
209
+ const values = flattenValuesOfType(this.type, model.value);
210
+ const keys = new Set(Object.keys(values));
211
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
212
+ return keys.has(valuePath);
213
+ }
209
214
  validateField(model, valuePath) {
210
215
  const { convert, revert, create, } = this.getAdapterForValuePath(valuePath);
211
216
  const fieldOverride = model.fieldOverrides[valuePath];
212
217
  const accessor = model.getAccessorForValuePath(valuePath);
213
- const storedValue = convert(accessor != null
218
+ const { value: storedValue, } = convert(accessor != null
214
219
  ? accessor.value
215
220
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
216
221
  : create(valuePath, model.value),
217
222
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
218
223
  valuePath, model.value);
219
224
  const value = fieldOverride != null
220
- ? fieldOverride.value
225
+ ? fieldOverride[0]
221
226
  : storedValue;
222
227
  const dirty = storedValue !== value;
223
228
  assertExists(revert, 'changing field directly not supported {}', valuePath);
@@ -225,13 +230,13 @@ export class FormPresenter {
225
230
  const conversion = revert(value, valuePath, model.value);
226
231
  return runInAction(function () {
227
232
  switch (conversion.type) {
228
- case FieldConversionResult.Failure:
233
+ case UnreliableFieldConversionType.Failure:
229
234
  model.errors[valuePath] = conversion.error;
230
235
  if (conversion.value != null && accessor != null && dirty) {
231
236
  accessor.set(conversion.value[0]);
232
237
  }
233
238
  return false;
234
- case FieldConversionResult.Success:
239
+ case UnreliableFieldConversionType.Success:
235
240
  delete model.errors[valuePath];
236
241
  if (accessor != null && dirty) {
237
242
  accessor.set(conversion.value);
@@ -262,21 +267,21 @@ export class FormPresenter {
262
267
  return success;
263
268
  }
264
269
  const fieldOverride = model.fieldOverrides[adapterPath];
265
- const storedValue = convert(accessor.value, valuePath, model.value);
270
+ const { value: storedValue, } = convert(accessor.value, valuePath, model.value);
266
271
  const value = fieldOverride != null
267
- ? fieldOverride.value
272
+ ? fieldOverride[0]
268
273
  : storedValue;
269
274
  // TODO more nuanced comparison
270
- const dirty = fieldOverride != null && fieldOverride.value !== storedValue;
275
+ const dirty = fieldOverride != null && fieldOverride[0] !== storedValue;
271
276
  const conversion = revert(value, valuePath, model.value);
272
277
  switch (conversion.type) {
273
- case FieldConversionResult.Failure:
278
+ case UnreliableFieldConversionType.Failure:
274
279
  model.errors[adapterPath] = conversion.error;
275
280
  if (conversion.value != null && dirty) {
276
281
  accessor.set(conversion.value[0]);
277
282
  }
278
283
  return false;
279
- case FieldConversionResult.Success:
284
+ case UnreliableFieldConversionType.Success:
280
285
  if (dirty) {
281
286
  accessor.set(conversion.value);
282
287
  }
@@ -289,11 +294,11 @@ export class FormPresenter {
289
294
  });
290
295
  }
291
296
  createModel(value) {
292
- return new FormModel(this.typeDef, value, this.adapters);
297
+ return new FormModel(this.type, value, this.adapters);
293
298
  }
294
299
  }
295
300
  export class FormModel {
296
- typeDef;
301
+ type;
297
302
  adapters;
298
303
  @observable.ref
299
304
  accessor value;
@@ -302,14 +307,14 @@ export class FormModel {
302
307
  @observable.shallow
303
308
  accessor errors = {};
304
309
  flattenedTypeDefs;
305
- constructor(typeDef, value, adapters) {
306
- this.typeDef = typeDef;
310
+ constructor(type, value, adapters) {
311
+ this.type = type;
307
312
  this.adapters = adapters;
308
- this.value = mobxCopy(typeDef, value);
309
- this.flattenedTypeDefs = flattenTypeDefsOf(typeDef);
313
+ this.value = mobxCopy(type, value);
314
+ this.flattenedTypeDefs = flattenTypesOfType(type);
310
315
  // pre-populate field overrides for consistent behavior when default information is overwritten
311
316
  // then returned to
312
- this.fieldOverrides = flattenValueTypeTo(typeDef, this.value, () => { }, (_t, value, _setter, typePath, valuePath) => {
317
+ const conversions = flattenValueTo(type, this.value, () => { }, (_t, value, _setter, typePath, valuePath) => {
313
318
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
314
319
  const adapter = this.adapters[typePath];
315
320
  if (adapter == null) {
@@ -320,10 +325,11 @@ export class FormModel {
320
325
  // no need to store a temporary value if the value cannot be written back
321
326
  return;
322
327
  }
323
- const displayValue = convert(value, valuePath, this.value);
324
- return {
325
- value: displayValue,
326
- };
328
+ return convert(value, valuePath, this.value);
329
+ });
330
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
331
+ this.fieldOverrides = map(conversions, function (_k, v) {
332
+ return v && [v.value];
327
333
  });
328
334
  }
329
335
  @computed
@@ -344,7 +350,7 @@ export class FormModel {
344
350
  }
345
351
  @computed
346
352
  get knownFields() {
347
- return flattenValueTypeTo(this.typeDef, this.value, () => { },
353
+ return flattenValueTo(this.type, this.value, () => { },
348
354
  // TODO swap these to valuePath, typePath in flatten
349
355
  (_t, _v, _setter, typePath, valuePath) => {
350
356
  return this.synthesizeFieldByPaths(
@@ -358,7 +364,7 @@ export class FormModel {
358
364
  let typePath;
359
365
  try {
360
366
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
361
- typePath = valuePathToTypePath(this.typeDef,
367
+ typePath = valuePathToTypePath(this.type,
362
368
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
363
369
  valuePath, true);
364
370
  }
@@ -381,26 +387,23 @@ export class FormModel {
381
387
  const accessor = this.getAccessorForValuePath(valuePath);
382
388
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
383
389
  const fieldTypeDef = this.flattenedTypeDefs[typePath];
384
- const value = fieldOverride
385
- ? fieldOverride.value
386
- : convert(accessor != null
387
- ? accessor.value
388
- : fieldTypeDef != null
389
- ? mobxCopy(fieldTypeDef,
390
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
391
- create(valuePath, this.value))
392
- // fake values can't be copied
393
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
394
- : create(valuePath, this.value),
395
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
396
- valuePath, this.value);
390
+ const { value, required, readonly, } = convert(accessor != null
391
+ ? accessor.value
392
+ : fieldTypeDef != null
393
+ ? mobxCopy(fieldTypeDef,
394
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
395
+ create(valuePath, this.value))
396
+ // fake values can't be copied
397
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
398
+ : create(valuePath, this.value),
399
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
400
+ valuePath, this.value);
397
401
  const error = this.errors[valuePath];
398
402
  return {
399
- value,
403
+ value: fieldOverride != null ? fieldOverride[0] : value,
400
404
  error,
401
- // if we can't write it back, then we have to disable it
402
- disabled: this.isDisabled(valuePath),
403
- required: this.isRequired(valuePath),
405
+ readonly,
406
+ required,
404
407
  };
405
408
  }
406
409
  getAccessorForValuePath(valuePath) {
@@ -410,16 +413,8 @@ export class FormModel {
410
413
  @computed
411
414
  // should only be referenced internally, so loosely typed
412
415
  get accessors() {
413
- return flattenAccessorsOf(this.typeDef, this.value, (value) => {
414
- this.value = mobxCopy(this.typeDef, value);
416
+ return flattenAccessorsOfType(this.type, this.value, (value) => {
417
+ this.value = mobxCopy(this.type, value);
415
418
  });
416
419
  }
417
- isDisabled(_valuePath) {
418
- // TODO infer from types
419
- return false;
420
- }
421
- isRequired(_valuePath) {
422
- // TODO infer from types
423
- return false;
424
- }
425
420
  }
@@ -0,0 +1,13 @@
1
+ import { type TwoWayFieldConverter } from 'types/field_converters';
2
+ import { type ErrorOfFieldAdapter, type FieldAdapter, type FromOfFieldAdapter, type ToOfFieldAdapter, type ValuePathOfFieldAdapter } from './field_adapter';
3
+ export type MergedOfFieldAdaptersWithTwoWayConverter<FieldAdapters extends Readonly<Record<string, FieldAdapter>>, E, Context> = {
4
+ [K in keyof FieldAdapters]: FieldAdapter<FromOfFieldAdapter<FieldAdapters[K]>, ToOfFieldAdapter<FieldAdapters[K]>, ErrorOfFieldAdapter<FieldAdapters[K]> | E, ValuePathOfFieldAdapter<FieldAdapters[K]>, Context>;
5
+ };
6
+ type ValuePathsOfFieldAdapters<FieldAdapters extends Readonly<Record<string, FieldAdapter>>> = {
7
+ [K in keyof FieldAdapters]: ValuePathOfFieldAdapter<FieldAdapters[K]>;
8
+ }[keyof FieldAdapters];
9
+ type TosOfFieldAdapters<FieldAdapters extends Readonly<Record<string, FieldAdapter>>> = {
10
+ [K in keyof FieldAdapters]: ToOfFieldAdapter<FieldAdapters[K]>;
11
+ }[keyof FieldAdapters];
12
+ export declare function mergeFieldAdaptersWithTwoWayConverter<FieldAdapters extends Readonly<Record<string, FieldAdapter>>, E, Context>(fieldAdapters: FieldAdapters, converter: TwoWayFieldConverter<TosOfFieldAdapters<FieldAdapters>, TosOfFieldAdapters<FieldAdapters>, E, ValuePathsOfFieldAdapters<FieldAdapters>, Context>): MergedOfFieldAdaptersWithTwoWayConverter<FieldAdapters, E, Context>;
13
+ export {};
@@ -0,0 +1,11 @@
1
+ import { map } from '@strictly/base';
2
+ import { chainAnnotatedFieldConverter, chainUnreliableFieldConverter, } from 'field_converters/chain_field_converter';
3
+ export function mergeFieldAdaptersWithTwoWayConverter(fieldAdapters, converter) {
4
+ return map(fieldAdapters, function (_key, adapter) {
5
+ return {
6
+ convert: chainAnnotatedFieldConverter(adapter.convert.bind(adapter), converter.convert.bind(converter)),
7
+ revert: adapter.revert && chainUnreliableFieldConverter(converter.revert.bind(converter), adapter.revert.bind(adapter)),
8
+ create: adapter.create.bind(adapter),
9
+ };
10
+ });
11
+ }
@@ -0,0 +1,11 @@
1
+ import { type Validator } from '@strictly/define';
2
+ import { type Simplify } from 'type-fest';
3
+ import { type FieldAdapter } from './field_adapter';
4
+ export type MergedOfFieldAdaptersWithValidators<FieldAdapters extends Readonly<Record<Key, FieldAdapter>>, Validators extends Partial<Readonly<Record<string, Validator>>>, Key extends keyof Validators = keyof Validators> = Simplify<{
5
+ readonly [K in Key]: MergedOfFieldAdapterWithValidator<FieldAdapters[K], Validators[K]>;
6
+ } & {
7
+ readonly [K in Exclude<keyof FieldAdapters, Key>]: FieldAdapters[K];
8
+ }>;
9
+ type MergedOfFieldAdapterWithValidator<A extends FieldAdapter, V extends Validator | undefined> = undefined extends V ? A : A extends FieldAdapter<infer From, infer To, infer E1, infer P1, infer C1> ? V extends Validator<From, infer E2, infer P2, infer C2> ? FieldAdapter<From, To, E1 | E2, P1 | P2, C1 | C2> : never : never;
10
+ export declare function mergeAdaptersWithValidators<FieldAdapters extends Readonly<Record<Key, FieldAdapter>>, Validators extends Readonly<Record<string, Validator>>, Key extends keyof Validators = keyof Validators>(adapters: FieldAdapters, validators: Validators): MergedOfFieldAdaptersWithValidators<FieldAdapters, Validators, Key>;
11
+ export {};
@@ -0,0 +1,45 @@
1
+ import { reduce } from '@strictly/base';
2
+ import { annotations, validate, } from '@strictly/define';
3
+ import { UnreliableFieldConversionType, } from 'types/field_converters';
4
+ export function mergeAdaptersWithValidators(adapters, validators) {
5
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6
+ return reduce(adapters, function (acc, key, adapter) {
7
+ const validator = validators[key];
8
+ if (validator == null) {
9
+ acc[key] = adapter;
10
+ return acc;
11
+ }
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ function revert(to, ...params) {
14
+ const result = adapter.revert(to, ...params);
15
+ if (result.type === UnreliableFieldConversionType.Failure) {
16
+ return result;
17
+ }
18
+ const validationError = validate(validator, result.value, ...params);
19
+ if (validationError == null) {
20
+ return result;
21
+ }
22
+ return {
23
+ type: UnreliableFieldConversionType.Failure,
24
+ value: [result.value],
25
+ error: validationError,
26
+ };
27
+ }
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ function convert(from, ...params) {
30
+ const { required: required1, readonly: readonly1, value, } = adapter.convert(from, ...params);
31
+ const { required: required2, readonly: readonly2, } = annotations(validator, ...params);
32
+ return {
33
+ value,
34
+ required: required1 || required2,
35
+ readonly: readonly1 || readonly2,
36
+ };
37
+ }
38
+ acc[key] = {
39
+ ...adapter,
40
+ convert,
41
+ revert: adapter.revert && revert,
42
+ };
43
+ return acc;
44
+ }, {});
45
+ }
@@ -0,0 +1,7 @@
1
+ import { type FieldAdapter } from 'core/mobx/field_adapter';
2
+ import { type TwoWayFieldConverter } from 'types/field_converters';
3
+ import { type Mocked } from 'vitest';
4
+ export declare function createMockedAdapter<E, To, From, ValuePath extends string>(_original: FieldAdapter<From, To, E, ValuePath>): Mocked<Required<FieldAdapter<From, To, E, ValuePath>>>;
5
+ export declare function resetMockAdapter<E, To, From, ValuePath extends string>({ convert, revert, create, }: FieldAdapter<From, To, E, ValuePath>, mockedAdapter: Mocked<Required<FieldAdapter<From, To, E, ValuePath>>>): void;
6
+ export declare function createMockTwoWayFieldConverter<From, To, E, ValuePath extends string, Context>(_original: TwoWayFieldConverter<From, To, E, ValuePath, Context>): Mocked<TwoWayFieldConverter<From, To, E, ValuePath, Context>>;
7
+ export declare function resetMockTwoWayFieldConverter<From, To, E, ValuePath extends string, Context>({ convert, revert, }: TwoWayFieldConverter<From, To, E, ValuePath, Context>, mockedConverter: Mocked<TwoWayFieldConverter<From, To, E, ValuePath, Context>>): void;