@strictly/react-form 0.0.4 → 0.0.6

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 (68) hide show
  1. package/.out/core/mobx/field_adapter_builder.d.ts +1 -1
  2. package/.out/core/mobx/field_adapter_builder.js +1 -2
  3. package/.out/core/mobx/hooks.d.ts +10 -0
  4. package/.out/core/mobx/hooks.js +47 -0
  5. package/.out/core/props.d.ts +2 -2
  6. package/.out/index.d.ts +1 -0
  7. package/.out/index.js +1 -0
  8. package/.out/mantine/create_fields_view.d.ts +7 -0
  9. package/.out/mantine/{create_sub_form.js → create_fields_view.js} +4 -5
  10. package/.out/mantine/create_form.d.ts +7 -0
  11. package/.out/mantine/create_form.js +13 -0
  12. package/.out/mantine/create_list.d.ts +5 -4
  13. package/.out/mantine/create_list.js +4 -2
  14. package/.out/mantine/hooks.d.ts +8 -5
  15. package/.out/mantine/hooks.js +17 -7
  16. package/.out/mantine/specs/checkbox_hooks.stories.d.ts +2 -2
  17. package/.out/mantine/specs/checkbox_hooks.stories.js +2 -2
  18. package/.out/mantine/specs/{sub_form_hooks.stories.d.ts → fields_view_hooks.stories.d.ts} +2 -2
  19. package/.out/mantine/specs/{sub_form_hooks.stories.js → fields_view_hooks.stories.js} +9 -8
  20. package/.out/mantine/specs/fields_view_hooks.tests.d.ts +1 -0
  21. package/.out/mantine/specs/fields_view_hooks.tests.js +12 -0
  22. package/.out/mantine/specs/form_hooks.stories.d.ts +12 -0
  23. package/.out/mantine/specs/form_hooks.stories.js +60 -0
  24. package/.out/mantine/specs/form_hooks.tests.d.ts +1 -0
  25. package/.out/mantine/specs/form_hooks.tests.js +12 -0
  26. package/.out/mantine/specs/list_hooks.stories.d.ts +2 -2
  27. package/.out/mantine/specs/list_hooks.stories.js +8 -8
  28. package/.out/mantine/specs/radio_group_hooks.stories.d.ts +2 -2
  29. package/.out/mantine/specs/radio_group_hooks.stories.js +2 -2
  30. package/.out/mantine/specs/select_hooks.stories.d.ts +2 -2
  31. package/.out/mantine/specs/select_hooks.stories.js +2 -2
  32. package/.out/mantine/specs/text_input_hooks.stories.d.ts +2 -2
  33. package/.out/mantine/specs/text_input_hooks.stories.js +2 -2
  34. package/.out/mantine/specs/value_input_hooks.stories.d.ts +2 -2
  35. package/.out/mantine/specs/value_input_hooks.stories.js +2 -2
  36. package/.out/tsconfig.tsbuildinfo +1 -1
  37. package/.turbo/turbo-build.log +7 -7
  38. package/.turbo/turbo-check-types.log +1 -1
  39. package/core/mobx/field_adapter_builder.ts +3 -4
  40. package/core/mobx/hooks.ts +94 -0
  41. package/core/props.ts +2 -2
  42. package/dist/index.cjs +175 -95
  43. package/dist/index.d.cts +48 -39
  44. package/dist/index.d.ts +48 -39
  45. package/dist/index.js +170 -86
  46. package/index.ts +1 -0
  47. package/mantine/{create_sub_form.tsx → create_fields_view.tsx} +27 -16
  48. package/mantine/create_form.tsx +43 -0
  49. package/mantine/create_list.tsx +10 -4
  50. package/mantine/hooks.tsx +51 -16
  51. package/mantine/specs/__snapshots__/fields_view_hooks.tests.tsx.snap +460 -0
  52. package/mantine/specs/__snapshots__/form_hooks.tests.tsx.snap +273 -0
  53. package/mantine/specs/__snapshots__/list_hooks.tests.tsx.snap +56 -8
  54. package/mantine/specs/checkbox_hooks.stories.tsx +4 -4
  55. package/mantine/specs/{sub_form_hooks.stories.tsx → fields_view_hooks.stories.tsx} +23 -11
  56. package/mantine/specs/fields_view_hooks.tests.tsx +15 -0
  57. package/mantine/specs/form_hooks.stories.tsx +107 -0
  58. package/mantine/specs/form_hooks.tests.tsx +15 -0
  59. package/mantine/specs/list_hooks.stories.tsx +20 -10
  60. package/mantine/specs/radio_group_hooks.stories.tsx +4 -4
  61. package/mantine/specs/select_hooks.stories.tsx +4 -4
  62. package/mantine/specs/text_input_hooks.stories.tsx +4 -4
  63. package/mantine/specs/value_input_hooks.stories.tsx +4 -4
  64. package/package.json +1 -1
  65. package/.out/field_converters/list_converter.d.ts +0 -2
  66. package/.out/field_converters/list_converter.js +0 -13
  67. package/.out/mantine/create_sub_form.d.ts +0 -6
  68. package/field_converters/list_converter.ts +0 -20
package/dist/index.js CHANGED
@@ -87,20 +87,6 @@ function unreliableIdentityConverter() {
87
87
  };
88
88
  }
89
89
 
90
- // field_converters/list_converter.ts
91
- function listConverter() {
92
- return function(from, valuePath) {
93
- const value = from.map(function(_v, i) {
94
- return `${valuePath}.${i}`;
95
- });
96
- return {
97
- value,
98
- required: false,
99
- readonly: false
100
- };
101
- };
102
- }
103
-
104
90
  // field_converters/maybe_identity_converter.ts
105
91
  var MaybeIdentityConverter = class {
106
92
  constructor(converter, isFrom) {
@@ -189,8 +175,9 @@ function identityAdapter(prototype, required) {
189
175
  }
190
176
  function listAdapter() {
191
177
  return new FieldAdapterBuilder(
192
- listConverter(),
193
- prototypingFieldValueFactory([])
178
+ annotatedIdentityConverter(false),
179
+ prototypingFieldValueFactory([]),
180
+ unreliableIdentityConverter()
194
181
  );
195
182
  }
196
183
 
@@ -668,6 +655,62 @@ var FormModel = class {
668
655
  }
669
656
  };
670
657
 
658
+ // core/mobx/hooks.ts
659
+ import {
660
+ useCallback,
661
+ useMemo
662
+ } from "react";
663
+ function useDefaultMobxFormHooks(presenter, value, onValidSubmit) {
664
+ const model = useMemo(function() {
665
+ return presenter.createModel(value);
666
+ }, [
667
+ presenter,
668
+ value
669
+ ]);
670
+ const onFieldValueChange = useCallback(
671
+ function(path, value2) {
672
+ presenter.clearFieldError(model, path);
673
+ presenter.setFieldValue(model, path, value2);
674
+ },
675
+ [
676
+ presenter,
677
+ model
678
+ ]
679
+ );
680
+ const onFieldSubmit = useCallback(
681
+ function(valuePath) {
682
+ if (presenter.validateField(model, valuePath)) {
683
+ onValidSubmit?.(model, valuePath);
684
+ }
685
+ return false;
686
+ },
687
+ [
688
+ presenter,
689
+ model,
690
+ onValidSubmit
691
+ ]
692
+ );
693
+ const onFieldBlur = useCallback(
694
+ function(path) {
695
+ setTimeout(function() {
696
+ if (presenter.isValuePathActive(model, path)) {
697
+ presenter.validateField(model, path);
698
+ }
699
+ }, 100);
700
+ },
701
+ [
702
+ presenter,
703
+ model
704
+ ]
705
+ );
706
+ return {
707
+ model,
708
+ onFieldValueChange,
709
+ onFieldSubmit,
710
+ onFieldBlur
711
+ };
712
+ }
713
+
671
714
  // core/mobx/merge_field_adapters_with_two_way_converter.ts
672
715
  import { map as map2 } from "@strictly/base";
673
716
  function mergeFieldAdaptersWithTwoWayConverter(fieldAdapters, converter) {
@@ -995,14 +1038,14 @@ import {
995
1038
  } from "mobx";
996
1039
  import {
997
1040
  useEffect,
998
- useMemo as useMemo2
1041
+ useMemo as useMemo3
999
1042
  } from "react";
1000
1043
 
1001
1044
  // util/partial.tsx
1002
1045
  import { observer } from "mobx-react";
1003
1046
  import {
1004
1047
  forwardRef,
1005
- useMemo
1048
+ useMemo as useMemo2
1006
1049
  } from "react";
1007
1050
  import { jsx } from "react/jsx-runtime";
1008
1051
  function createSimplePartialComponent(Component, curriedProps) {
@@ -1063,7 +1106,7 @@ function createPartialComponent(Component, curriedPropsSource, additionalPropKey
1063
1106
  );
1064
1107
  }
1065
1108
  function usePartialComponent(curriedPropsSource, deps, Component, additionalPropKeys = []) {
1066
- return useMemo(
1109
+ return useMemo2(
1067
1110
  function() {
1068
1111
  return createPartialComponent(
1069
1112
  Component,
@@ -1133,7 +1176,7 @@ function createUnsafePartialObserverComponent(Component, curriedPropsSource, add
1133
1176
  );
1134
1177
  }
1135
1178
  function usePartialObserverComponent(curriedPropsSource, deps, Component, additionalPropKeys = []) {
1136
- return useMemo(
1179
+ return useMemo2(
1137
1180
  function() {
1138
1181
  return createPartialObserverComponent(
1139
1182
  Component,
@@ -1200,23 +1243,99 @@ function createCheckbox(valuePath, Checkbox) {
1200
1243
  );
1201
1244
  }
1202
1245
 
1246
+ // mantine/create_fields_view.tsx
1247
+ import { observer as observer2 } from "mobx-react";
1248
+ import { jsx as jsx3 } from "react/jsx-runtime";
1249
+ function createFieldsView(valuePath, FieldsView, observableProps) {
1250
+ function toKey(subKey) {
1251
+ return subKey.replace("$", valuePath);
1252
+ }
1253
+ function toSubKey(key) {
1254
+ return key.replace(valuePath, "$");
1255
+ }
1256
+ function onFieldValueChange(subKey, value) {
1257
+ observableProps.onFieldValueChange(toKey(subKey), value);
1258
+ }
1259
+ function onFieldBlur(subKey) {
1260
+ observableProps.onFieldBlur?.(toKey(subKey));
1261
+ }
1262
+ function onFieldFocus(subKey) {
1263
+ observableProps.onFieldFocus?.(toKey(subKey));
1264
+ }
1265
+ function onFieldSubmit(subKey) {
1266
+ observableProps.onFieldSubmit?.(toKey(subKey));
1267
+ }
1268
+ return observer2(function(props) {
1269
+ const subFields = Object.entries(observableProps.fields).reduce((acc, [
1270
+ fieldKey,
1271
+ fieldValue
1272
+ ]) => {
1273
+ if (fieldKey.startsWith(valuePath)) {
1274
+ acc[toSubKey(fieldKey)] = fieldValue;
1275
+ }
1276
+ return acc;
1277
+ }, {});
1278
+ return /* @__PURE__ */ jsx3(
1279
+ FieldsView,
1280
+ {
1281
+ // maybe we can do this in a more type safe way
1282
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
1283
+ ...props,
1284
+ fields: subFields,
1285
+ onFieldBlur,
1286
+ onFieldFocus,
1287
+ onFieldSubmit,
1288
+ onFieldValueChange
1289
+ }
1290
+ );
1291
+ });
1292
+ }
1293
+
1294
+ // mantine/create_form.tsx
1295
+ import { observer as observer3 } from "mobx-react";
1296
+ import {
1297
+ useCallback as useCallback2
1298
+ } from "react";
1299
+ import { jsx as jsx4 } from "react/jsx-runtime";
1300
+ function createForm(valuePath, Form, observableProps) {
1301
+ return observer3((props) => {
1302
+ const { value } = observableProps.fields[valuePath];
1303
+ const onValueChange = useCallback2((value2) => {
1304
+ observableProps.onFieldValueChange(valuePath, value2);
1305
+ }, []);
1306
+ return /* @__PURE__ */ jsx4(
1307
+ Form,
1308
+ {
1309
+ // maybe we can do this in a more type safe way
1310
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
1311
+ ...props,
1312
+ onValueChange,
1313
+ value
1314
+ }
1315
+ );
1316
+ });
1317
+ }
1318
+
1203
1319
  // mantine/create_list.tsx
1204
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
1320
+ import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
1205
1321
  function createList(valuePath, List) {
1206
1322
  const propSource = () => {
1207
1323
  const values = [...this.fields[valuePath].value];
1208
1324
  return {
1209
- values
1325
+ values,
1326
+ listPath: valuePath
1210
1327
  };
1211
1328
  };
1212
1329
  return createUnsafePartialObserverComponent(List, propSource);
1213
1330
  }
1214
1331
  function DefaultList({
1215
1332
  values,
1333
+ listPath,
1216
1334
  children
1217
1335
  }) {
1218
- return /* @__PURE__ */ jsx3(Fragment, { children: values.map(function(value, index) {
1219
- return children(value, index);
1336
+ return /* @__PURE__ */ jsx5(Fragment, { children: values.map(function(value, index) {
1337
+ const valuePath = `${listPath}.${index}`;
1338
+ return children(valuePath, value, index);
1220
1339
  }) });
1221
1340
  }
1222
1341
 
@@ -1253,7 +1372,7 @@ function createRadio(valuePath, value, Radio) {
1253
1372
  }
1254
1373
 
1255
1374
  // mantine/create_radio_group.tsx
1256
- import { jsx as jsx4 } from "react/jsx-runtime";
1375
+ import { jsx as jsx6 } from "react/jsx-runtime";
1257
1376
  function createRadioGroup(valuePath, RadioGroup) {
1258
1377
  const onChange = (value) => {
1259
1378
  this.onFieldValueChange?.(valuePath, value);
@@ -1281,7 +1400,7 @@ function createRadioGroup(valuePath, RadioGroup) {
1281
1400
  name: valuePath,
1282
1401
  value,
1283
1402
  required,
1284
- error: error && /* @__PURE__ */ jsx4(ErrorRenderer, { error }),
1403
+ error: error && /* @__PURE__ */ jsx6(ErrorRenderer, { error }),
1285
1404
  onChange,
1286
1405
  onFocus,
1287
1406
  onBlur,
@@ -1291,53 +1410,8 @@ function createRadioGroup(valuePath, RadioGroup) {
1291
1410
  return createUnsafePartialObserverComponent(RadioGroup, propSource, ["ErrorRenderer"]);
1292
1411
  }
1293
1412
 
1294
- // mantine/create_sub_form.tsx
1295
- import { observer as observer2 } from "mobx-react";
1296
- import { jsx as jsx5 } from "react/jsx-runtime";
1297
- function createSubForm(valuePath, SubForm, observableProps) {
1298
- function toKey(subKey) {
1299
- return subKey.replace("$", valuePath);
1300
- }
1301
- function toSubKey(key) {
1302
- return key.replace(valuePath, "$");
1303
- }
1304
- function onFieldValueChange(subKey, value) {
1305
- observableProps.onFieldValueChange(toKey(subKey), value);
1306
- }
1307
- function onFieldBlur(subKey) {
1308
- observableProps.onFieldBlur?.(toKey(subKey));
1309
- }
1310
- function onFieldFocus(subKey) {
1311
- observableProps.onFieldFocus?.(toKey(subKey));
1312
- }
1313
- function onFieldSubmit(subKey) {
1314
- observableProps.onFieldSubmit?.(toKey(subKey));
1315
- }
1316
- return observer2(function() {
1317
- const subFields = Object.entries(observableProps.fields).reduce((acc, [
1318
- fieldKey,
1319
- fieldValue
1320
- ]) => {
1321
- if (fieldKey.startsWith(valuePath)) {
1322
- acc[toSubKey(fieldKey)] = fieldValue;
1323
- }
1324
- return acc;
1325
- }, {});
1326
- return /* @__PURE__ */ jsx5(
1327
- SubForm,
1328
- {
1329
- fields: subFields,
1330
- onFieldBlur,
1331
- onFieldFocus,
1332
- onFieldSubmit,
1333
- onFieldValueChange
1334
- }
1335
- );
1336
- });
1337
- }
1338
-
1339
1413
  // mantine/create_text_input.tsx
1340
- import { jsx as jsx6 } from "react/jsx-runtime";
1414
+ import { jsx as jsx7 } from "react/jsx-runtime";
1341
1415
  function createTextInput(valuePath, TextInput) {
1342
1416
  const onChange = (e) => {
1343
1417
  this.onFieldValueChange?.(valuePath, e.target.value);
@@ -1371,7 +1445,7 @@ function createTextInput(valuePath, TextInput) {
1371
1445
  value,
1372
1446
  disabled: readonly,
1373
1447
  required,
1374
- error: error && /* @__PURE__ */ jsx6(ErrorRenderer, { error }),
1448
+ error: error && /* @__PURE__ */ jsx7(ErrorRenderer, { error }),
1375
1449
  onChange,
1376
1450
  onFocus,
1377
1451
  onBlur,
@@ -1386,7 +1460,7 @@ function createTextInput(valuePath, TextInput) {
1386
1460
  }
1387
1461
 
1388
1462
  // mantine/create_value_input.tsx
1389
- import { jsx as jsx7 } from "react/jsx-runtime";
1463
+ import { jsx as jsx8 } from "react/jsx-runtime";
1390
1464
  function createValueInput(valuePath, ValueInput) {
1391
1465
  const onChange = (value) => {
1392
1466
  this.onFieldValueChange?.(valuePath, value);
@@ -1420,7 +1494,7 @@ function createValueInput(valuePath, ValueInput) {
1420
1494
  value,
1421
1495
  disabled: readonly,
1422
1496
  required,
1423
- error: error && /* @__PURE__ */ jsx7(ErrorRenderer, { error }),
1497
+ error: error && /* @__PURE__ */ jsx8(ErrorRenderer, { error }),
1424
1498
  onChange,
1425
1499
  onFocus,
1426
1500
  onBlur,
@@ -1435,18 +1509,18 @@ function createValueInput(valuePath, ValueInput) {
1435
1509
  }
1436
1510
 
1437
1511
  // mantine/hooks.tsx
1438
- import { jsx as jsx8 } from "react/jsx-runtime";
1512
+ import { jsx as jsx9 } from "react/jsx-runtime";
1439
1513
  function SimpleSelect(props) {
1440
- return /* @__PURE__ */ jsx8(Select, { ...props });
1514
+ return /* @__PURE__ */ jsx9(Select, { ...props });
1441
1515
  }
1442
- function useMantineForm({
1516
+ function useMantineFormFields({
1443
1517
  onFieldValueChange,
1444
1518
  onFieldBlur,
1445
1519
  onFieldFocus,
1446
1520
  onFieldSubmit,
1447
1521
  fields
1448
1522
  }) {
1449
- const form = useMemo2(
1523
+ const form = useMemo3(
1450
1524
  function() {
1451
1525
  return new MantineFormImpl(fields);
1452
1526
  },
@@ -1510,9 +1584,10 @@ var MantineFormImpl = class {
1510
1584
  listCache = new Cache(
1511
1585
  createList.bind(this)
1512
1586
  );
1513
- subFormCache = new Cache(
1514
- createSubForm.bind(this)
1587
+ fieldsViewCache = new Cache(
1588
+ createFieldsView.bind(this)
1515
1589
  );
1590
+ formCache = new Cache(createForm.bind(this));
1516
1591
  @observable2.ref
1517
1592
  accessor fields;
1518
1593
  onFieldValueChange;
@@ -1578,13 +1653,21 @@ var MantineFormImpl = class {
1578
1653
  DefaultList
1579
1654
  );
1580
1655
  }
1581
- // TODO have the returned component take any non-overlapping props as props
1582
- subForm(valuePath, SubForm) {
1583
- return this.subFormCache.retrieveOrCreate(
1656
+ fieldsView(valuePath, FieldsView) {
1657
+ return this.fieldsViewCache.retrieveOrCreate(
1658
+ valuePath,
1659
+ // strip props from component since we lose information in the cache
1660
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1661
+ FieldsView,
1662
+ this
1663
+ );
1664
+ }
1665
+ form(valuePath, Form) {
1666
+ return this.formCache.retrieveOrCreate(
1584
1667
  valuePath,
1585
1668
  // strip props from component since we lose information in the cache
1586
1669
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1587
- SubForm,
1670
+ Form,
1588
1671
  this
1589
1672
  );
1590
1673
  }
@@ -1657,7 +1740,8 @@ export {
1657
1740
  mergeValidators,
1658
1741
  prototypingFieldValueFactory,
1659
1742
  subFormFieldAdapters,
1660
- useMantineForm,
1743
+ useDefaultMobxFormHooks,
1744
+ useMantineFormFields,
1661
1745
  usePartialComponent,
1662
1746
  usePartialObserverComponent,
1663
1747
  validatingConverter
package/index.ts CHANGED
@@ -4,6 +4,7 @@ export * from './core/mobx/field_adapters_of_values'
4
4
  export * from './core/mobx/flattened_adapters_of_fields'
5
5
  export * from './core/mobx/form_fields_of_field_adapters'
6
6
  export * from './core/mobx/form_presenter'
7
+ export * from './core/mobx/hooks'
7
8
  export * from './core/mobx/merge_field_adapters_with_two_way_converter'
8
9
  export * from './core/mobx/merge_field_adapters_with_validators'
9
10
  export * from './core/mobx/sub_form_field_adapters'
@@ -1,20 +1,24 @@
1
- import type { FormProps } from 'core/props'
1
+ import type { FieldsViewProps } from 'core/props'
2
2
  import { observer } from 'mobx-react'
3
- import type { ComponentType } from 'react'
3
+ import type {
4
+ ComponentProps,
5
+ ComponentType,
6
+ } from 'react'
4
7
  import type { AllFieldsOfFields } from 'types/all_fields_of_fields'
5
8
  import type { Fields } from 'types/field'
6
9
  import type { SubFormFields } from 'types/sub_form_fields'
7
10
  import type { ValueTypeOfField } from 'types/value_type_of_field'
11
+ import type { MantineFieldComponent } from './types'
8
12
 
9
- export function createSubForm<
13
+ export function createFieldsView<
10
14
  F extends Fields,
11
15
  K extends keyof AllFieldsOfFields<F>,
12
- S extends Fields = SubFormFields<F, K>,
16
+ P extends FieldsViewProps<Fields> = FieldsViewProps<SubFormFields<F, K>>,
13
17
  >(
14
18
  valuePath: K,
15
- SubForm: ComponentType<FormProps<S>>,
16
- observableProps: FormProps<F>,
17
- ) {
19
+ FieldsView: ComponentType<P>,
20
+ observableProps: FieldsViewProps<F>,
21
+ ): MantineFieldComponent<FieldsViewProps<P['fields']>, P> {
18
22
  function toKey(subKey: string | number | symbol): string {
19
23
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
20
24
  return (subKey as string).replace('$', valuePath as string)
@@ -25,25 +29,27 @@ export function createSubForm<
25
29
  return (key as string).replace(valuePath as string, '$')
26
30
  }
27
31
 
28
- function onFieldValueChange<SubK extends keyof S>(
32
+ function onFieldValueChange<SubK extends keyof P['fields']>(
29
33
  subKey: SubK,
30
- value: ValueTypeOfField<S[SubK]>,
34
+ value: ValueTypeOfField<P['fields'][SubK]>,
31
35
  ) {
32
36
  // convert from subKey to key
33
37
  observableProps.onFieldValueChange(toKey(subKey), value)
34
38
  }
35
- function onFieldBlur(subKey: keyof S) {
39
+ function onFieldBlur(subKey: keyof P['fields']) {
36
40
  observableProps.onFieldBlur?.(toKey(subKey))
37
41
  }
38
42
 
39
- function onFieldFocus(subKey: keyof S) {
43
+ function onFieldFocus(subKey: keyof P['fields']) {
40
44
  observableProps.onFieldFocus?.(toKey(subKey))
41
45
  }
42
46
 
43
- function onFieldSubmit(subKey: keyof S) {
47
+ function onFieldSubmit(subKey: keyof P['fields']) {
44
48
  observableProps.onFieldSubmit?.(toKey(subKey))
45
49
  }
46
- return observer(function () {
50
+
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
+ return observer(function (props: ComponentProps<MantineFieldComponent<FieldsViewProps<P['fields']>, P>>) {
47
53
  // convert fields to sub-fields
48
54
  const subFields = Object.entries(observableProps.fields).reduce<Record<string, unknown>>((acc, [
49
55
  fieldKey,
@@ -57,14 +63,19 @@ export function createSubForm<
57
63
  }, {})
58
64
 
59
65
  return (
60
- <SubForm
66
+ <FieldsView
67
+ {
68
+ // maybe we can do this in a more type safe way
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
70
+ ...props as any
71
+ }
61
72
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
62
- fields={subFields as S}
73
+ fields={subFields as P['fields']}
63
74
  onFieldBlur={onFieldBlur}
64
75
  onFieldFocus={onFieldFocus}
65
76
  onFieldSubmit={onFieldSubmit}
66
77
  onFieldValueChange={onFieldValueChange}
67
78
  />
68
79
  )
69
- })
80
+ }) as unknown as MantineFieldComponent<FieldsViewProps<P['fields']>, P>
70
81
  }
@@ -0,0 +1,43 @@
1
+ import {
2
+ type FieldsViewProps,
3
+ type FormProps,
4
+ } from 'core/props'
5
+ import { observer } from 'mobx-react'
6
+ import {
7
+ type ComponentProps,
8
+ type ComponentType,
9
+ useCallback,
10
+ } from 'react'
11
+ import { type AllFieldsOfFields } from 'types/all_fields_of_fields'
12
+ import { type Fields } from 'types/field'
13
+ import { type ValueTypeOfField } from 'types/value_type_of_field'
14
+ import { type MantineFieldComponent } from './types'
15
+
16
+ export function createForm<
17
+ F extends Fields,
18
+ K extends keyof AllFieldsOfFields<F>,
19
+ P extends FormProps<ValueTypeOfField<F[K]>> = FormProps<ValueTypeOfField<F[K]>>,
20
+ >(
21
+ valuePath: K,
22
+ Form: ComponentType<P>,
23
+ observableProps: FieldsViewProps<F>,
24
+ ): MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P> {
25
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
26
+ return observer((props: ComponentProps<MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P>>) => {
27
+ const { value } = observableProps.fields[valuePath]
28
+ const onValueChange = useCallback((value: ValueTypeOfField<F[K]>) => {
29
+ observableProps.onFieldValueChange(valuePath, value)
30
+ }, [])
31
+ return (
32
+ <Form
33
+ {
34
+ // maybe we can do this in a more type safe way
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/consistent-type-assertions
36
+ ...props as any
37
+ }
38
+ onValueChange={onValueChange}
39
+ value={value}
40
+ />
41
+ )
42
+ }) as MantineFieldComponent<FormProps<ValueTypeOfField<F[K]>>, P>
43
+ }
@@ -10,8 +10,9 @@ import {
10
10
  } from './types'
11
11
 
12
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- export type SuppliedListProps<Value = any> = {
13
+ export type SuppliedListProps<Value = any, ListPath extends string = string> = {
14
14
  values: readonly Value[],
15
+ listPath: ListPath,
15
16
  }
16
17
 
17
18
  export function createList<
@@ -19,6 +20,7 @@ export function createList<
19
20
  K extends keyof ListFieldsOfFields<F>,
20
21
  Props extends SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>> & {
21
22
  children: (
23
+ valuePath: `${K}.${number}`,
22
24
  value: ElementOfArray<ValueTypeOfField<F[K]>>,
23
25
  index: number,
24
26
  ) => React.ReactNode,
@@ -32,6 +34,7 @@ export function createList<
32
34
  const values = [...this.fields[valuePath].value]
33
35
  return {
34
36
  values,
37
+ listPath: valuePath,
35
38
  }
36
39
  }
37
40
  return createUnsafePartialObserverComponent(List, propSource)
@@ -39,16 +42,19 @@ export function createList<
39
42
 
40
43
  export function DefaultList<
41
44
  Value,
45
+ ListPath extends string,
42
46
  >({
43
47
  values,
48
+ listPath,
44
49
  children,
45
- }: SuppliedListProps<Value> & {
46
- children: (value: Value, index: number) => React.ReactNode,
50
+ }: SuppliedListProps<Value, ListPath> & {
51
+ children: (valuePath: `${ListPath}.${number}`, value: Value, index: number) => React.ReactNode,
47
52
  }) {
48
53
  return (
49
54
  <>
50
55
  {values.map(function (value, index) {
51
- return children(value, index)
56
+ const valuePath: `${ListPath}.${number}` = `${listPath}.${index}`
57
+ return children(valuePath, value, index)
52
58
  })}
53
59
  </>
54
60
  )