@strictly/react-form 0.0.7 → 0.0.9

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 (79) 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/hooks.d.ts +5 -1
  4. package/.out/core/mobx/hooks.js +13 -3
  5. package/.out/core/mobx/specs/sub_form_field_adapters.tests.js +56 -9
  6. package/.out/core/mobx/sub_form_field_adapters.d.ts +5 -5
  7. package/.out/core/mobx/sub_form_field_adapters.js +13 -10
  8. package/.out/field_converters/chain_field_converter.js +3 -3
  9. package/.out/field_converters/nullable_to_boolean_converter.d.ts +2 -2
  10. package/.out/mantine/create_checkbox.js +1 -0
  11. package/.out/mantine/create_fields_view.d.ts +1 -1
  12. package/.out/mantine/create_fields_view.js +4 -4
  13. package/.out/mantine/create_form.d.ts +1 -1
  14. package/.out/mantine/create_list.d.ts +1 -1
  15. package/.out/mantine/create_pill.d.ts +1 -1
  16. package/.out/mantine/create_radio.d.ts +1 -1
  17. package/.out/mantine/create_radio_group.js +1 -0
  18. package/.out/mantine/create_text_input.js +7 -2
  19. package/.out/mantine/create_value_input.js +1 -0
  20. package/.out/mantine/error_renderer.d.ts +7 -3
  21. package/.out/mantine/error_renderer.js +1 -1
  22. package/.out/mantine/hooks.d.ts +9 -9
  23. package/.out/mantine/specs/checkbox_hooks.stories.d.ts +2 -6
  24. package/.out/mantine/specs/checkbox_hooks.stories.js +4 -16
  25. package/.out/mantine/specs/fields_view_hooks.stories.d.ts +1 -1
  26. package/.out/mantine/specs/fields_view_hooks.stories.js +6 -3
  27. package/.out/mantine/specs/form_hooks.stories.d.ts +2 -2
  28. package/.out/mantine/specs/form_hooks.stories.js +4 -1
  29. package/.out/mantine/specs/radio_group_hooks.stories.d.ts +2 -6
  30. package/.out/mantine/specs/radio_group_hooks.stories.js +5 -17
  31. package/.out/mantine/specs/select_hooks.stories.d.ts +2 -6
  32. package/.out/mantine/specs/select_hooks.stories.js +4 -16
  33. package/.out/mantine/specs/text_input_hooks.stories.d.ts +2 -5
  34. package/.out/mantine/specs/text_input_hooks.stories.js +5 -5
  35. package/.out/mantine/specs/value_input_hooks.stories.d.ts +2 -5
  36. package/.out/mantine/specs/value_input_hooks.stories.js +5 -5
  37. package/.out/mantine/types.d.ts +4 -2
  38. package/.out/tsconfig.tsbuildinfo +1 -1
  39. package/.out/types/specs/{error_type_of_field.tests.js → error_of_field.tests.js} +1 -1
  40. package/.turbo/turbo-build.log +8 -8
  41. package/.turbo/turbo-check-types.log +1 -1
  42. package/core/mobx/field_adapter_builder.ts +71 -0
  43. package/core/mobx/hooks.ts +24 -6
  44. package/core/mobx/specs/sub_form_field_adapters.tests.ts +108 -15
  45. package/core/mobx/sub_form_field_adapters.ts +41 -25
  46. package/dist/index.cjs +108 -49
  47. package/dist/index.d.cts +35 -24
  48. package/dist/index.d.ts +35 -24
  49. package/dist/index.js +107 -49
  50. package/field_converters/chain_field_converter.ts +3 -3
  51. package/field_converters/nullable_to_boolean_converter.ts +2 -3
  52. package/mantine/create_checkbox.tsx +2 -1
  53. package/mantine/create_fields_view.tsx +17 -14
  54. package/mantine/create_form.tsx +2 -2
  55. package/mantine/create_list.tsx +1 -1
  56. package/mantine/create_pill.tsx +1 -1
  57. package/mantine/create_radio.tsx +1 -1
  58. package/mantine/create_radio_group.tsx +6 -2
  59. package/mantine/create_text_input.tsx +9 -3
  60. package/mantine/create_value_input.tsx +2 -1
  61. package/mantine/error_renderer.ts +13 -4
  62. package/mantine/hooks.tsx +19 -14
  63. package/mantine/specs/__snapshots__/checkbox_hooks.tests.tsx.snap +1 -64
  64. package/mantine/specs/__snapshots__/fields_view_hooks.tests.tsx.snap +52 -52
  65. package/mantine/specs/__snapshots__/radio_group_hooks.tests.tsx.snap +1 -179
  66. package/mantine/specs/__snapshots__/select_hooks.tests.tsx.snap +1 -83
  67. package/mantine/specs/__snapshots__/text_input_hooks.tests.tsx.snap +27 -27
  68. package/mantine/specs/__snapshots__/value_input_hooks.tests.tsx.snap +31 -31
  69. package/mantine/specs/checkbox_hooks.stories.tsx +5 -21
  70. package/mantine/specs/fields_view_hooks.stories.tsx +16 -4
  71. package/mantine/specs/form_hooks.stories.tsx +10 -3
  72. package/mantine/specs/radio_group_hooks.stories.tsx +6 -20
  73. package/mantine/specs/select_hooks.stories.tsx +5 -21
  74. package/mantine/specs/text_input_hooks.stories.tsx +5 -8
  75. package/mantine/specs/value_input_hooks.stories.tsx +5 -8
  76. package/mantine/types.ts +7 -3
  77. package/package.json +2 -1
  78. package/types/specs/{error_type_of_field.tests.ts → error_of_field.tests.ts} +1 -1
  79. /package/.out/types/specs/{error_type_of_field.tests.d.ts → error_of_field.tests.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -52,18 +52,18 @@ function chainAnnotatedFieldConverter(from, to) {
52
52
  return function(value, valuePath, context) {
53
53
  const {
54
54
  required: intermediateRequired,
55
- readonly: intermediateDisabled,
55
+ readonly: intermediateReadonly,
56
56
  value: intermediateValue
57
57
  } = from(value, valuePath, context);
58
58
  const {
59
59
  required: finalRequired,
60
- readonly: finalDisabled,
60
+ readonly: finalReadonly,
61
61
  value: finalValue
62
62
  } = to(intermediateValue, valuePath, context);
63
63
  return {
64
64
  value: finalValue,
65
65
  required: intermediateRequired || finalRequired,
66
- readonly: intermediateDisabled || finalDisabled
66
+ readonly: intermediateReadonly || finalReadonly
67
67
  };
68
68
  };
69
69
  }
@@ -102,6 +102,25 @@ var MaybeIdentityConverter = class {
102
102
  }
103
103
  };
104
104
 
105
+ // field_converters/trimming_string_converter.ts
106
+ var TrimmingStringConverter = class {
107
+ constructor() {
108
+ }
109
+ convert(to) {
110
+ return {
111
+ value: to.trim(),
112
+ required: false,
113
+ readonly: false
114
+ };
115
+ }
116
+ revert(from) {
117
+ return {
118
+ type: 0 /* Success */,
119
+ value: from.trim()
120
+ };
121
+ }
122
+ };
123
+
105
124
  // field_value_factories/prototyping_field_value_factory.ts
106
125
  function prototypingFieldValueFactory(prototype) {
107
126
  return function() {
@@ -136,6 +155,32 @@ var FieldAdapterBuilder = class _FieldAdapterBuilder {
136
155
  reverter
137
156
  );
138
157
  }
158
+ nullable() {
159
+ return this.or(null);
160
+ }
161
+ optional() {
162
+ return this.or(void 0);
163
+ }
164
+ or(proto) {
165
+ function isFrom(v) {
166
+ return v !== proto;
167
+ }
168
+ function isTo(v) {
169
+ return v !== proto;
170
+ }
171
+ return new _FieldAdapterBuilder(
172
+ (v, valuePath, context) => isFrom(v) ? this.convert(v, valuePath, context) : {
173
+ value: v,
174
+ readonly: false,
175
+ required: false
176
+ },
177
+ this.create,
178
+ (v, valuePath, context) => isTo(v) && this.revert ? this.revert(v, valuePath, context) : {
179
+ type: 0 /* Success */,
180
+ value: proto
181
+ }
182
+ );
183
+ }
139
184
  withIdentity(isFrom) {
140
185
  const identityConverter = new MaybeIdentityConverter({
141
186
  convert: this.convert,
@@ -173,6 +218,12 @@ function identityAdapter(prototype, required) {
173
218
  unreliableIdentityConverter()
174
219
  );
175
220
  }
221
+ function trimmingStringAdapter() {
222
+ return adapterFromTwoWayConverter(
223
+ new TrimmingStringConverter(),
224
+ prototypingFieldValueFactory("")
225
+ );
226
+ }
176
227
  function listAdapter() {
177
228
  return new FieldAdapterBuilder(
178
229
  annotatedIdentityConverter(false),
@@ -660,7 +711,10 @@ import {
660
711
  useCallback,
661
712
  useMemo
662
713
  } from "react";
663
- function useDefaultMobxFormHooks(presenter, value, onValidSubmit) {
714
+ function useDefaultMobxFormHooks(presenter, value, {
715
+ onValidFieldSubmit,
716
+ onValidFormSubmit
717
+ } = {}) {
664
718
  const model = useMemo(function() {
665
719
  return presenter.createModel(value);
666
720
  }, [
@@ -680,14 +734,14 @@ function useDefaultMobxFormHooks(presenter, value, onValidSubmit) {
680
734
  const onFieldSubmit = useCallback(
681
735
  function(valuePath) {
682
736
  if (presenter.validateField(model, valuePath)) {
683
- onValidSubmit?.(model, valuePath);
737
+ onValidFieldSubmit?.(model, valuePath);
684
738
  }
685
739
  return false;
686
740
  },
687
741
  [
688
742
  presenter,
689
743
  model,
690
- onValidSubmit
744
+ onValidFieldSubmit
691
745
  ]
692
746
  );
693
747
  const onFieldBlur = useCallback(
@@ -703,11 +757,24 @@ function useDefaultMobxFormHooks(presenter, value, onValidSubmit) {
703
757
  model
704
758
  ]
705
759
  );
760
+ const onFormSubmit = useCallback(
761
+ function() {
762
+ if (presenter.validateAll(model)) {
763
+ onValidFormSubmit?.(model, model.value);
764
+ }
765
+ },
766
+ [
767
+ presenter,
768
+ model,
769
+ onValidFormSubmit
770
+ ]
771
+ );
706
772
  return {
707
773
  model,
708
774
  onFieldValueChange,
709
775
  onFieldSubmit,
710
- onFieldBlur
776
+ onFieldBlur,
777
+ onFormSubmit
711
778
  };
712
779
  }
713
780
 
@@ -793,32 +860,34 @@ function mergeAdaptersWithValidators(adapters, validators) {
793
860
  import {
794
861
  flattenValuesOfType as flattenValuesOfType2
795
862
  } from "@strictly/define";
796
- function subFormFieldAdapters(subAdapters, prefix, contextType) {
863
+ function subFormFieldAdapters(subAdapters, parentTypePath, contextType) {
864
+ const dotCount = parentTypePath.split(".").length;
797
865
  function getSubValuePathAndContext(valuePath, context) {
798
- const subValuePath = valuePath.replace(prefix, "$");
799
- const subContext = flattenValuesOfType2(contextType, context)[prefix];
866
+ const parentValuePath = valuePath.split(".").slice(0, dotCount).join(".");
867
+ const subValuePath = valuePath.replace(parentValuePath, "$");
868
+ const subContext = flattenValuesOfType2(contextType, context)[parentValuePath];
800
869
  return [
801
870
  subValuePath,
802
871
  subContext
803
872
  ];
804
873
  }
805
874
  return Object.entries(subAdapters).reduce((acc, [
806
- subKey,
807
- subValue
875
+ subTypePath,
876
+ subAdapter
808
877
  ]) => {
809
- const key = subKey.replace("$", prefix);
878
+ const typePath = subTypePath.replace("$", parentTypePath);
810
879
  const adaptedAdapter = {
811
880
  convert: (from, valuePath, context) => {
812
- return subValue.convert(from, ...getSubValuePathAndContext(valuePath, context));
881
+ return subAdapter.convert(from, ...getSubValuePathAndContext(valuePath, context));
813
882
  },
814
883
  create: (valuePath, context) => {
815
- return subValue.create(...getSubValuePathAndContext(valuePath, context));
884
+ return subAdapter.create(...getSubValuePathAndContext(valuePath, context));
816
885
  },
817
- revert: subValue.revert && ((from, valuePath, context) => {
818
- return subValue.revert(from, ...getSubValuePathAndContext(valuePath, context));
886
+ revert: subAdapter.revert && ((from, valuePath, context) => {
887
+ return subAdapter.revert(from, ...getSubValuePathAndContext(valuePath, context));
819
888
  })
820
889
  };
821
- acc[key] = adaptedAdapter;
890
+ acc[typePath] = adaptedAdapter;
822
891
  return acc;
823
892
  }, {});
824
893
  }
@@ -988,25 +1057,6 @@ var SelectStringConverter = class extends AbstractSelectValueTypeConverter {
988
1057
  }
989
1058
  };
990
1059
 
991
- // field_converters/trimming_string_converter.ts
992
- var TrimmingStringConverter = class {
993
- constructor() {
994
- }
995
- convert(to) {
996
- return {
997
- value: to.trim(),
998
- required: false,
999
- readonly: false
1000
- };
1001
- }
1002
- revert(from) {
1003
- return {
1004
- type: 0 /* Success */,
1005
- value: from.trim()
1006
- };
1007
- }
1008
- };
1009
-
1010
1060
  // field_converters/validating_converter.ts
1011
1061
  import {
1012
1062
  validate as validate2
@@ -1040,7 +1090,7 @@ function DefaultErrorRenderer({
1040
1090
  error
1041
1091
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1042
1092
  }) {
1043
- return error;
1093
+ return JSON.stringify(error);
1044
1094
  }
1045
1095
 
1046
1096
  // mantine/hooks.tsx
@@ -1288,15 +1338,19 @@ function createFieldsView(valuePath, FieldsView, observableProps) {
1288
1338
  observableProps.onFieldSubmit?.(toKey(subKey));
1289
1339
  }
1290
1340
  return observer2(function(props) {
1291
- const subFields = Object.entries(observableProps.fields).reduce((acc, [
1292
- fieldKey,
1293
- fieldValue
1294
- ]) => {
1295
- if (fieldKey.startsWith(valuePath)) {
1296
- acc[toSubKey(fieldKey)] = fieldValue;
1297
- }
1298
- return acc;
1299
- }, {});
1341
+ const subFields = Object.entries(observableProps.fields).reduce(
1342
+ (acc, [
1343
+ fieldKey,
1344
+ fieldValue
1345
+ ]) => {
1346
+ if (fieldKey.startsWith(valuePath)) {
1347
+ acc[toSubKey(fieldKey)] = fieldValue;
1348
+ }
1349
+ return acc;
1350
+ },
1351
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1352
+ {}
1353
+ );
1300
1354
  return /* @__PURE__ */ jsx3(
1301
1355
  FieldsView,
1302
1356
  {
@@ -1454,13 +1508,16 @@ function createTextInput(valuePath, TextInput) {
1454
1508
  const propSource = ({
1455
1509
  ErrorRenderer = DefaultErrorRenderer
1456
1510
  }) => {
1511
+ const field = this.fields[valuePath];
1512
+ if (field == null) {
1513
+ throw new Error(`invalid field ${valuePath}`);
1514
+ }
1457
1515
  const {
1458
1516
  readonly,
1459
1517
  required,
1460
1518
  value,
1461
1519
  error
1462
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1463
- } = this.fields[valuePath];
1520
+ } = field;
1464
1521
  return {
1465
1522
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1466
1523
  name: valuePath,
@@ -1762,6 +1819,7 @@ export {
1762
1819
  mergeValidators,
1763
1820
  prototypingFieldValueFactory,
1764
1821
  subFormFieldAdapters,
1822
+ trimmingStringAdapter,
1765
1823
  useDefaultMobxFormHooks,
1766
1824
  useMantineFormFields,
1767
1825
  usePartialComponent,
@@ -71,18 +71,18 @@ export function chainAnnotatedFieldConverter<
71
71
  return function (value: From, valuePath: ValuePath, context: Context): AnnotatedFieldConversion {
72
72
  const {
73
73
  required: intermediateRequired,
74
- readonly: intermediateDisabled,
74
+ readonly: intermediateReadonly,
75
75
  value: intermediateValue,
76
76
  } = from(value, valuePath, context)
77
77
  const {
78
78
  required: finalRequired,
79
- readonly: finalDisabled,
79
+ readonly: finalReadonly,
80
80
  value: finalValue,
81
81
  } = to(intermediateValue, valuePath, context)
82
82
  return {
83
83
  value: finalValue,
84
84
  required: intermediateRequired || finalRequired,
85
- readonly: intermediateDisabled || finalDisabled,
85
+ readonly: intermediateReadonly || finalReadonly,
86
86
  }
87
87
  }
88
88
  }
@@ -13,14 +13,13 @@ import {
13
13
 
14
14
  export class NullableToBooleanConverter<
15
15
  T extends Type,
16
- E,
17
16
  ValuePath extends string,
18
17
  Context,
19
18
  NullType extends null | undefined,
20
19
  > implements TwoWayFieldConverterWithValueFactory<
21
20
  ValueOfType<ReadonlyTypeOfType<T>> | NullType,
22
21
  boolean,
23
- E,
22
+ never,
24
23
  ValuePath,
25
24
  Context
26
25
  > {
@@ -43,7 +42,7 @@ export class NullableToBooleanConverter<
43
42
  }
44
43
  }
45
44
 
46
- revert(from: boolean): UnreliableFieldConversion<ValueOfType<ReadonlyTypeOfType<T>> | NullType, E> {
45
+ revert(from: boolean): UnreliableFieldConversion<ValueOfType<ReadonlyTypeOfType<T>> | NullType, never> {
47
46
  if (from) {
48
47
  const value: ValueOfType<T> = copy(this.typeDef, this.prototype)
49
48
  return {
@@ -78,9 +78,10 @@ export function createCheckbox<
78
78
  onKeyUp,
79
79
  }
80
80
  }
81
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
81
82
  return createUnsafePartialObserverComponent(
82
83
  Checkbox,
83
84
  propSource,
84
85
  ['ErrorRenderer'],
85
- )
86
+ ) as MantineFieldComponent<SuppliedCheckboxProps, Props, ErrorOfField<F[K]>>
86
87
  }
@@ -18,7 +18,7 @@ export function createFieldsView<
18
18
  valuePath: K,
19
19
  FieldsView: ComponentType<P>,
20
20
  observableProps: FieldsViewProps<F>,
21
- ): MantineFieldComponent<FieldsViewProps<P['fields']>, P> {
21
+ ): MantineFieldComponent<FieldsViewProps<P['fields']>, P, never> {
22
22
  function toKey(subKey: string | number | symbol): string {
23
23
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
24
24
  return (subKey as string).replace('$', valuePath as string)
@@ -49,18 +49,22 @@ export function createFieldsView<
49
49
  }
50
50
 
51
51
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
- return observer(function (props: ComponentProps<MantineFieldComponent<FieldsViewProps<P['fields']>, P>>) {
52
+ return observer(function (props: ComponentProps<MantineFieldComponent<FieldsViewProps<P['fields']>, P, never>>) {
53
53
  // convert fields to sub-fields
54
- const subFields = Object.entries(observableProps.fields).reduce<Record<string, unknown>>((acc, [
55
- fieldKey,
56
- fieldValue,
57
- ]) => {
54
+ const subFields = Object.entries(observableProps.fields).reduce<Record<string, unknown>>(
55
+ (acc, [
56
+ fieldKey,
57
+ fieldValue,
58
+ ]) => {
59
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
60
+ if (fieldKey.startsWith(valuePath as string)) {
61
+ acc[toSubKey(fieldKey)] = fieldValue
62
+ }
63
+ return acc
64
+ },
58
65
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
59
- if (fieldKey.startsWith(valuePath as string)) {
60
- acc[toSubKey(fieldKey)] = fieldValue
61
- }
62
- return acc
63
- }, {})
66
+ {} as P['fields'],
67
+ )
64
68
 
65
69
  return (
66
70
  <FieldsView
@@ -69,13 +73,12 @@ export function createFieldsView<
69
73
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
70
74
  ...props as any
71
75
  }
72
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
73
- fields={subFields as P['fields']}
76
+ fields={subFields}
74
77
  onFieldBlur={onFieldBlur}
75
78
  onFieldFocus={onFieldFocus}
76
79
  onFieldSubmit={onFieldSubmit}
77
80
  onFieldValueChange={onFieldValueChange}
78
81
  />
79
82
  )
80
- }) as unknown as MantineFieldComponent<FieldsViewProps<P['fields']>, P>
83
+ }) as unknown as MantineFieldComponent<FieldsViewProps<P['fields']>, P, never>
81
84
  }
@@ -21,7 +21,7 @@ export function createForm<
21
21
  valuePath: K,
22
22
  Form: ComponentType<P>,
23
23
  observableProps: FieldsViewProps<F>,
24
- ): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P> {
24
+ ): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P, never> {
25
25
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
26
  return observer((props: ComponentProps<MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P>>) => {
27
27
  const { value } = observableProps.fields[valuePath]
@@ -39,5 +39,5 @@ export function createForm<
39
39
  value={value}
40
40
  />
41
41
  )
42
- }) as MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P>
42
+ }) as MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P, never>
43
43
  }
@@ -29,7 +29,7 @@ export function createList<
29
29
  this: MantineForm<F>,
30
30
  valuePath: K,
31
31
  List: ComponentType<Props>,
32
- ): MantineFieldComponent<SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>>, Props> {
32
+ ): MantineFieldComponent<SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>>, Props, never> {
33
33
  const propSource = () => {
34
34
  const values = [...this.fields[valuePath].value]
35
35
  return {
@@ -25,7 +25,7 @@ export function createPill<
25
25
  this: MantineForm<F>,
26
26
  valuePath: K,
27
27
  Pill: ComponentType<Props>,
28
- ): MantineFieldComponent<SuppliedPillProps, Props> {
28
+ ): MantineFieldComponent<SuppliedPillProps, Props, never> {
29
29
  const propSource = () => {
30
30
  const {
31
31
  readonly,
@@ -22,7 +22,7 @@ export function createRadio<
22
22
  valuePath: K,
23
23
  value: ValueTypeOfField<F[K]>,
24
24
  Radio: ComponentType<Props>,
25
- ): MantineFieldComponent<SuppliedRadioProps, Props> {
25
+ ): MantineFieldComponent<SuppliedRadioProps, Props, never> {
26
26
  const propSource = () => {
27
27
  return {
28
28
  disabled: this.fields[valuePath].readonly,
@@ -68,6 +68,10 @@ export function createRadioGroup<
68
68
  onKeyUp,
69
69
  }
70
70
  }
71
-
72
- return createUnsafePartialObserverComponent(RadioGroup, propSource, ['ErrorRenderer'])
71
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
72
+ return createUnsafePartialObserverComponent(RadioGroup, propSource, ['ErrorRenderer']) as MantineFieldComponent<
73
+ SuppliedRadioGroupProps,
74
+ Props,
75
+ ErrorOfField<F[K]>
76
+ >
73
77
  }
@@ -59,13 +59,18 @@ export function createTextInput<
59
59
  }: {
60
60
  ErrorRenderer?: ErrorRenderer<ErrorOfField<F[K]>>,
61
61
  }) => {
62
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63
+ const field = this.fields[valuePath as string]
64
+ if (field == null) {
65
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
66
+ throw new Error(`invalid field ${valuePath as string}`)
67
+ }
62
68
  const {
63
69
  readonly,
64
70
  required,
65
71
  value,
66
72
  error,
67
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
68
- } = this.fields[valuePath as string]
73
+ } = field
69
74
  return {
70
75
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
71
76
  name: valuePath as string,
@@ -79,6 +84,7 @@ export function createTextInput<
79
84
  onKeyUp,
80
85
  }
81
86
  }
87
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
82
88
  return createUnsafePartialObserverComponent<
83
89
  typeof TextInput,
84
90
  SuppliedTextInputProps,
@@ -88,5 +94,5 @@ export function createTextInput<
88
94
  TextInput,
89
95
  propSource,
90
96
  ['ErrorRenderer'],
91
- )
97
+ ) as MantineFieldComponent<SuppliedTextInputProps, Props, ErrorOfField<F[K]>>
92
98
  }
@@ -77,6 +77,7 @@ export function createValueInput<
77
77
  onKeyUp,
78
78
  }
79
79
  }
80
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
80
81
  return createUnsafePartialObserverComponent<
81
82
  typeof ValueInput,
82
83
  SuppliedValueInputProps<ValueTypeOfField<F[K]>>,
@@ -86,5 +87,5 @@ export function createValueInput<
86
87
  ValueInput,
87
88
  propSource,
88
89
  ['ErrorRenderer'],
89
- )
90
+ ) as MantineFieldComponent<SuppliedValueInputProps<ValueTypeOfField<F[K]>>, Props, ErrorOfField<F[K]>>
90
91
  }
@@ -1,15 +1,24 @@
1
1
  import { type ComponentType } from 'react'
2
+ import { type ErrorOfField } from 'types/error_of_field'
3
+ import { type Fields } from 'types/field'
2
4
 
3
- export type ErrorRendererProps<E> = {
5
+ type InternalErrorRendererProps<E> = {
4
6
  error: E,
5
7
  }
6
8
 
9
+ export type ErrorRendererProps<
10
+ F extends Fields,
11
+ K extends keyof Fields,
12
+ > = InternalErrorRendererProps<
13
+ ErrorOfField<F[K]>
14
+ >
15
+
7
16
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
- export type ErrorRenderer<E = any> = ComponentType<ErrorRendererProps<E>>
17
+ export type ErrorRenderer<E = any> = ComponentType<InternalErrorRendererProps<E>>
9
18
 
10
19
  export function DefaultErrorRenderer({
11
20
  error,
12
21
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- }: ErrorRendererProps<any>) {
14
- return error
22
+ }: InternalErrorRendererProps<any>) {
23
+ return JSON.stringify(error)
15
24
  }
package/mantine/hooks.tsx CHANGED
@@ -209,7 +209,7 @@ class MantineFormImpl<
209
209
 
210
210
  textInput<
211
211
  K extends keyof StringFieldsOfFields<F>,
212
- >(valuePath: K): MantineFieldComponent<SuppliedTextInputProps, TextInputProps>
212
+ >(valuePath: K): MantineFieldComponent<SuppliedTextInputProps, TextInputProps, ErrorOfField<F[K]>>
213
213
  textInput<
214
214
  K extends keyof StringFieldsOfFields<F>,
215
215
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -217,7 +217,7 @@ class MantineFormImpl<
217
217
  >(
218
218
  valuePath: K,
219
219
  TextInput?: ComponentType<P>,
220
- ): MantineFieldComponent<SuppliedTextInputProps, P>
220
+ ): MantineFieldComponent<SuppliedTextInputProps, P, ErrorOfField<F[K]>>
221
221
  textInput<
222
222
  K extends keyof StringFieldsOfFields<F>,
223
223
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -264,7 +264,7 @@ class MantineFormImpl<
264
264
 
265
265
  checkbox<
266
266
  K extends keyof BooleanFieldsOfFields<F>,
267
- >(valuePath: K): MantineFieldComponent<SuppliedCheckboxProps, CheckboxProps>
267
+ >(valuePath: K): MantineFieldComponent<SuppliedCheckboxProps, CheckboxProps, ErrorOfField<F[K]>>
268
268
  checkbox<
269
269
  K extends keyof BooleanFieldsOfFields<F>,
270
270
  P extends SuppliedCheckboxProps,
@@ -282,19 +282,21 @@ class MantineFormImpl<
282
282
  valuePath,
283
283
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
284
284
  Checkbox as ComponentType<SuppliedCheckboxProps>,
285
- ) as MantineFieldComponent<SuppliedCheckboxProps, P>
285
+ ) as MantineFieldComponent<SuppliedCheckboxProps, P, ErrorOfField<F[K]>>
286
286
  }
287
287
 
288
+ // this should work?
288
289
  radioGroup<
289
290
  K extends keyof StringFieldsOfFields<F>,
290
- >(valuePath: K): MantineFieldComponent<SuppliedRadioGroupProps, RadioGroupProps>
291
+ P extends RadioGroupProps = RadioGroupProps,
292
+ >(valuePath: K): MantineFieldComponent<SuppliedRadioGroupProps, P, ErrorOfField<F[K]>>
291
293
  radioGroup<
292
294
  K extends keyof StringFieldsOfFields<F>,
293
295
  P extends SuppliedRadioGroupProps,
294
296
  >(
295
297
  valuePath: K,
296
298
  RadioGroup: ComponentType<P>,
297
- ): MantineFieldComponent<SuppliedRadioGroupProps, P>
299
+ ): MantineFieldComponent<SuppliedRadioGroupProps, P, ErrorOfField<F[K]>>
298
300
  radioGroup<
299
301
  K extends keyof StringFieldsOfFields<F>,
300
302
  P extends SuppliedRadioGroupProps,
@@ -340,7 +342,7 @@ class MantineFormImpl<
340
342
  value,
341
343
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
342
344
  Radio as ComponentType<SuppliedRadioProps>,
343
- ) as MantineFieldComponent<SuppliedRadioProps, P>
345
+ ) as MantineFieldComponent<SuppliedRadioProps, P, ErrorOfField<F[K]>>
344
346
  }
345
347
 
346
348
  pill<
@@ -352,7 +354,7 @@ class MantineFormImpl<
352
354
  >(
353
355
  valuePath: K,
354
356
  Pill: ComponentType<P>,
355
- ): MantineFieldComponent<SuppliedPillProps, P>
357
+ ): MantineFieldComponent<SuppliedPillProps, P, ErrorOfField<F[K]>>
356
358
  pill<
357
359
  K extends keyof AllFieldsOfFields<F>,
358
360
  P extends SuppliedPillProps,
@@ -373,7 +375,8 @@ class MantineFormImpl<
373
375
  K extends keyof ListFieldsOfFields<F>,
374
376
  >(valuePath: K): MantineFieldComponent<
375
377
  SuppliedListProps<`${K}.${number}`>,
376
- ComponentProps<typeof DefaultList<ElementOfArray<F[K]['value']>, K>>
378
+ ComponentProps<typeof DefaultList<ElementOfArray<F[K]['value']>, K>>,
379
+ never
377
380
  > {
378
381
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
379
382
  return this.listCache.retrieveOrCreate(
@@ -382,7 +385,7 @@ class MantineFormImpl<
382
385
  ) as MantineFieldComponent<
383
386
  SuppliedListProps<`${K}.${number}`>,
384
387
  ComponentProps<typeof DefaultList<ElementOfArray<F[K]['value']>, K>>,
385
- ErrorOfField<F[K]>
388
+ never
386
389
  >
387
390
  }
388
391
 
@@ -391,7 +394,8 @@ class MantineFormImpl<
391
394
  P extends FieldsViewProps<Fields> = FieldsViewProps<SubFormFields<F, K>>,
392
395
  >(valuePath: K, FieldsView: ComponentType<P>): MantineFieldComponent<
393
396
  FieldsViewProps<P['fields']>,
394
- P
397
+ P,
398
+ never
395
399
  > {
396
400
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
397
401
  return this.fieldsViewCache.retrieveOrCreate(
@@ -402,7 +406,8 @@ class MantineFormImpl<
402
406
  this,
403
407
  ) as unknown as MantineFieldComponent<
404
408
  FieldsViewProps<P['fields']>,
405
- P
409
+ P,
410
+ never
406
411
  >
407
412
  }
408
413
 
@@ -412,7 +417,7 @@ class MantineFormImpl<
412
417
  >(
413
418
  valuePath: K,
414
419
  Form: ComponentType<P>,
415
- ): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P> {
420
+ ): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P, never> {
416
421
  // strip props from component since we lose information in the cache
417
422
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
418
423
  return this.formCache.retrieveOrCreate(
@@ -421,6 +426,6 @@ class MantineFormImpl<
421
426
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
422
427
  Form as ComponentType,
423
428
  this,
424
- ) as unknown as MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P>
429
+ ) as unknown as MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P, never>
425
430
  }
426
431
  }