@strictly/react-form 0.0.13 → 0.0.15

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 (39) hide show
  1. package/.out/core/mobx/field_adapter.d.ts +1 -0
  2. package/.out/core/mobx/form_model.d.ts +8 -3
  3. package/.out/core/mobx/form_model.js +23 -15
  4. package/.out/core/mobx/hooks.d.ts +2 -2
  5. package/.out/core/mobx/merge_field_adapters_with_two_way_converter.d.ts +2 -2
  6. package/.out/core/mobx/merge_field_adapters_with_validators.d.ts +1 -1
  7. package/.out/core/mobx/specs/form_model.tests.js +26 -21
  8. package/.out/core/mobx/specs/sub_form_field_adapters.tests.js +14 -21
  9. package/.out/core/mobx/sub_form_field_adapters.d.ts +5 -6
  10. package/.out/core/mobx/sub_form_field_adapters.js +6 -11
  11. package/.out/core/mobx/types.d.ts +3 -3
  12. package/.out/index.d.ts +2 -0
  13. package/.out/index.js +2 -0
  14. package/.out/mantine/field_view.d.ts +18 -0
  15. package/.out/mantine/field_view.js +16 -0
  16. package/.out/tsconfig.tsbuildinfo +1 -1
  17. package/.out/types/merge_validators.d.ts +1 -1
  18. package/.out/util/empty.d.ts +1 -0
  19. package/.out/util/empty.js +3 -0
  20. package/.turbo/turbo-build.log +8 -8
  21. package/.turbo/turbo-check-types.log +1 -1
  22. package/core/mobx/field_adapter.ts +9 -0
  23. package/core/mobx/form_model.ts +35 -16
  24. package/core/mobx/hooks.tsx +2 -2
  25. package/core/mobx/merge_field_adapters_with_two_way_converter.ts +2 -1
  26. package/core/mobx/merge_field_adapters_with_validators.ts +1 -1
  27. package/core/mobx/specs/form_model.tests.ts +35 -20
  28. package/core/mobx/specs/sub_form_field_adapters.tests.ts +14 -34
  29. package/core/mobx/sub_form_field_adapters.ts +11 -26
  30. package/core/mobx/types.ts +10 -7
  31. package/dist/index.cjs +99 -67
  32. package/dist/index.d.cts +38 -15
  33. package/dist/index.d.ts +38 -15
  34. package/dist/index.js +77 -49
  35. package/index.ts +2 -0
  36. package/mantine/field_view.tsx +39 -0
  37. package/package.json +1 -1
  38. package/types/merge_validators.ts +2 -2
  39. package/util/empty.tsx +3 -0
package/dist/index.js CHANGED
@@ -326,8 +326,8 @@ import {
326
326
  observable,
327
327
  runInAction
328
328
  } from "mobx";
329
- var _accessors_dec, _knownFields_dec, _fields_dec, _errors_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errors;
330
- _value_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _errors_dec = [observable.shallow], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed];
329
+ var _accessors_dec, _knownFields_dec, _fields_dec, _context_dec, _errors_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errors;
330
+ _value_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _errors_dec = [observable.shallow], _context_dec = [computed.struct], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed];
331
331
  var FormModel = class {
332
332
  constructor(type, value, adapters) {
333
333
  this.type = type;
@@ -339,6 +339,7 @@ var FormModel = class {
339
339
  __publicField(this, "flattenedTypeDefs");
340
340
  this.value = mobxCopy(type, value);
341
341
  this.flattenedTypeDefs = flattenTypesOfType(type);
342
+ const contextValue = this.toContext(value);
342
343
  const conversions = flattenValueTo(
343
344
  type,
344
345
  this.value,
@@ -356,13 +357,16 @@ var FormModel = class {
356
357
  if (revert == null) {
357
358
  return;
358
359
  }
359
- return convert(value2, valuePath, this.value);
360
+ return convert(value2, valuePath, contextValue);
360
361
  }
361
362
  );
362
363
  this.fieldOverrides = map(conversions, function(_k, v) {
363
364
  return v && [v.value];
364
365
  });
365
366
  }
367
+ get context() {
368
+ return this.toContext(this.value);
369
+ }
366
370
  get fields() {
367
371
  return new Proxy(
368
372
  this.knownFields,
@@ -430,11 +434,11 @@ var FormModel = class {
430
434
  accessor != null ? accessor.value : fieldTypeDef != null ? mobxCopy(
431
435
  fieldTypeDef,
432
436
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
433
- create(valuePath, this.value)
434
- ) : create(valuePath, this.value),
437
+ create(valuePath, this.context)
438
+ ) : create(valuePath, this.context),
435
439
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
436
440
  valuePath,
437
- this.value
441
+ this.context
438
442
  );
439
443
  const error = this.errors[valuePath];
440
444
  return {
@@ -492,7 +496,7 @@ var FormModel = class {
492
496
  const element = elementValue != null ? elementValue[0] : elementAdapter.create(
493
497
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
494
498
  elementTypePath,
495
- this.value
499
+ this.context
496
500
  );
497
501
  const originalList = accessor.value;
498
502
  const newList = [
@@ -610,7 +614,7 @@ var FormModel = class {
610
614
  internalSetFieldValue(valuePath, value, displayValidation) {
611
615
  const { revert } = this.getAdapterForValuePath(valuePath);
612
616
  assertExists(revert, "setting value not supported {}", valuePath);
613
- const conversion = revert(value, valuePath, this.value);
617
+ const conversion = revert(value, valuePath, this.context);
614
618
  const accessor = this.getAccessorForValuePath(valuePath);
615
619
  return runInAction(() => {
616
620
  this.fieldOverrides[valuePath] = [value];
@@ -650,10 +654,10 @@ var FormModel = class {
650
654
  convert,
651
655
  create
652
656
  } = adapter2;
653
- const value = create(valuePath, this.value);
657
+ const value = create(valuePath, this.context);
654
658
  const {
655
659
  value: displayValue
656
- } = convert(value, valuePath, this.value);
660
+ } = convert(value, valuePath, this.context);
657
661
  const key = valuePath;
658
662
  runInAction(() => {
659
663
  this.fieldOverrides[key] = [displayValue];
@@ -682,10 +686,10 @@ var FormModel = class {
682
686
  const {
683
687
  value: storedValue
684
688
  } = convert(
685
- accessor != null ? accessor.value : create(valuePath, this.value),
689
+ accessor != null ? accessor.value : create(valuePath, this.context),
686
690
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
687
691
  valuePath,
688
- this.value
692
+ this.context
689
693
  );
690
694
  const value = fieldOverride != null ? fieldOverride[0] : storedValue;
691
695
  const dirty = storedValue !== value;
@@ -693,12 +697,12 @@ var FormModel = class {
693
697
  if (ignoreDefaultValue) {
694
698
  const {
695
699
  value: defaultDisplayValue
696
- } = convert(create(valuePath, this.value), valuePath, this.value);
700
+ } = convert(create(valuePath, this.context), valuePath, this.context);
697
701
  if (defaultDisplayValue === value) {
698
702
  return true;
699
703
  }
700
704
  }
701
- const conversion = revert(value, valuePath, this.value);
705
+ const conversion = revert(value, valuePath, this.context);
702
706
  return runInAction(() => {
703
707
  switch (conversion.type) {
704
708
  case 1 /* Failure */:
@@ -743,10 +747,10 @@ var FormModel = class {
743
747
  const fieldOverride = this.fieldOverrides[adapterPath];
744
748
  const {
745
749
  value: storedValue
746
- } = convert(accessor.value, valuePath, this.value);
750
+ } = convert(accessor.value, valuePath, this.context);
747
751
  const value = fieldOverride != null ? fieldOverride[0] : storedValue;
748
752
  const dirty = fieldOverride != null && fieldOverride[0] !== storedValue;
749
- const conversion = revert(value, valuePath, this.value);
753
+ const conversion = revert(value, valuePath, this.context);
750
754
  switch (conversion.type) {
751
755
  case 1 /* Failure */:
752
756
  this.errors[adapterPath] = conversion.error;
@@ -776,6 +780,7 @@ _errors = new WeakMap();
776
780
  __decorateElement(_init, 4, "value", _value_dec, FormModel, _value);
777
781
  __decorateElement(_init, 4, "fieldOverrides", _fieldOverrides_dec, FormModel, _fieldOverrides);
778
782
  __decorateElement(_init, 4, "errors", _errors_dec, FormModel, _errors);
783
+ __decorateElement(_init, 2, "context", _context_dec, FormModel);
779
784
  __decorateElement(_init, 2, "fields", _fields_dec, FormModel);
780
785
  __decorateElement(_init, 2, "knownFields", _knownFields_dec, FormModel);
781
786
  __decorateElement(_init, 2, "accessors", _accessors_dec, FormModel);
@@ -915,19 +920,12 @@ function mergeAdaptersWithValidators(adapters, validators) {
915
920
  }
916
921
 
917
922
  // core/mobx/sub_form_field_adapters.ts
918
- import {
919
- flattenValuesOfType as flattenValuesOfType2
920
- } from "@strictly/define";
921
- function subFormFieldAdapters(subAdapters, parentTypePath, contextType) {
923
+ function subFormFieldAdapters(subAdapters, parentTypePath) {
922
924
  const dotCount = parentTypePath.split(".").length;
923
- function getSubValuePathAndContext(valuePath, context) {
925
+ function getSubValuePath(valuePath) {
924
926
  const parentValuePath = valuePath.split(".").slice(0, dotCount).join(".");
925
927
  const subValuePath = valuePath.replace(parentValuePath, "$");
926
- const subContext = flattenValuesOfType2(contextType, context)[parentValuePath];
927
- return [
928
- subValuePath,
929
- subContext
930
- ];
928
+ return subValuePath;
931
929
  }
932
930
  return Object.entries(subAdapters).reduce((acc, [
933
931
  subTypePath,
@@ -936,13 +934,13 @@ function subFormFieldAdapters(subAdapters, parentTypePath, contextType) {
936
934
  const typePath = subTypePath.replace("$", parentTypePath);
937
935
  const adaptedAdapter = {
938
936
  convert: (from, valuePath, context) => {
939
- return subAdapter.convert(from, ...getSubValuePathAndContext(valuePath, context));
937
+ return subAdapter.convert(from, getSubValuePath(valuePath), context);
940
938
  },
941
939
  create: (valuePath, context) => {
942
- return subAdapter.create(...getSubValuePathAndContext(valuePath, context));
940
+ return subAdapter.create(getSubValuePath(valuePath), context);
943
941
  },
944
942
  revert: subAdapter.revert && ((from, valuePath, context) => {
945
- return subAdapter.revert(from, ...getSubValuePathAndContext(valuePath, context));
943
+ return subAdapter.revert(from, getSubValuePath(valuePath), context);
946
944
  })
947
945
  };
948
946
  acc[typePath] = adaptedAdapter;
@@ -1151,6 +1149,34 @@ function DefaultErrorRenderer({
1151
1149
  return JSON.stringify(error);
1152
1150
  }
1153
1151
 
1152
+ // mantine/field_view.tsx
1153
+ import { Observer } from "mobx-react";
1154
+
1155
+ // util/empty.tsx
1156
+ function Empty() {
1157
+ return null;
1158
+ }
1159
+
1160
+ // mantine/field_view.tsx
1161
+ import { jsx } from "react/jsx-runtime";
1162
+ function FieldView({
1163
+ fields,
1164
+ valuePath,
1165
+ children
1166
+ }) {
1167
+ return /* @__PURE__ */ jsx(Observer, { children: () => {
1168
+ const {
1169
+ value,
1170
+ error
1171
+ } = fields[valuePath];
1172
+ return children({
1173
+ value,
1174
+ error,
1175
+ ErrorSink: Empty
1176
+ });
1177
+ } });
1178
+ }
1179
+
1154
1180
  // mantine/hooks.tsx
1155
1181
  import {
1156
1182
  Checkbox as CheckboxImpl,
@@ -1177,12 +1203,12 @@ import {
1177
1203
  forwardRef,
1178
1204
  useMemo
1179
1205
  } from "react";
1180
- import { jsx } from "react/jsx-runtime";
1206
+ import { jsx as jsx2 } from "react/jsx-runtime";
1181
1207
  function createSimplePartialComponent(Component, curriedProps) {
1182
1208
  return forwardRef(
1183
1209
  function(exposedProps, ref) {
1184
1210
  const C = Component;
1185
- return /* @__PURE__ */ jsx(
1211
+ return /* @__PURE__ */ jsx2(
1186
1212
  C,
1187
1213
  __spreadValues(__spreadValues({
1188
1214
  ref
@@ -1222,7 +1248,7 @@ function createPartialComponent(Component, curriedPropsSource, additionalPropKey
1222
1248
  ]
1223
1249
  );
1224
1250
  const curriedProps = curriedPropsSource(additionalProps);
1225
- return /* @__PURE__ */ jsx(
1251
+ return /* @__PURE__ */ jsx2(
1226
1252
  C,
1227
1253
  __spreadValues(__spreadValues({
1228
1254
  ref
@@ -1289,7 +1315,7 @@ function createUnsafePartialObserverComponent(Component, curriedPropsSource, add
1289
1315
  ]
1290
1316
  );
1291
1317
  const curriedProps = curriedPropsSource(additionalProps);
1292
- return /* @__PURE__ */ jsx(
1318
+ return /* @__PURE__ */ jsx2(
1293
1319
  C,
1294
1320
  __spreadValues(__spreadValues({
1295
1321
  ref
@@ -1320,7 +1346,7 @@ function usePartialObserverComponent(curriedPropsSource, deps, Component, additi
1320
1346
  }
1321
1347
 
1322
1348
  // mantine/create_checkbox.tsx
1323
- import { jsx as jsx2 } from "react/jsx-runtime";
1349
+ import { jsx as jsx3 } from "react/jsx-runtime";
1324
1350
  function createCheckbox(valuePath, Checkbox) {
1325
1351
  const onChange = (e) => {
1326
1352
  var _a;
@@ -1357,7 +1383,7 @@ function createCheckbox(valuePath, Checkbox) {
1357
1383
  checked: value,
1358
1384
  disabled: readonly,
1359
1385
  required,
1360
- error: error && /* @__PURE__ */ jsx2(ErrorRenderer, { error }),
1386
+ error: error && /* @__PURE__ */ jsx3(ErrorRenderer, { error }),
1361
1387
  onChange,
1362
1388
  onFocus,
1363
1389
  onBlur,
@@ -1377,7 +1403,7 @@ import {
1377
1403
  jsonPathUnprefix
1378
1404
  } from "@strictly/define";
1379
1405
  import { observer as observer2 } from "mobx-react";
1380
- import { jsx as jsx3 } from "react/jsx-runtime";
1406
+ import { jsx as jsx4 } from "react/jsx-runtime";
1381
1407
  function createFieldsView(valuePath, FieldsView, observableProps) {
1382
1408
  function toKey(subKey) {
1383
1409
  return jsonPathPrefix(valuePath, subKey);
@@ -1415,7 +1441,7 @@ function createFieldsView(valuePath, FieldsView, observableProps) {
1415
1441
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
1416
1442
  {}
1417
1443
  );
1418
- return /* @__PURE__ */ jsx3(
1444
+ return /* @__PURE__ */ jsx4(
1419
1445
  FieldsView,
1420
1446
  __spreadProps(__spreadValues({}, props), {
1421
1447
  fields: subFields,
@@ -1444,14 +1470,14 @@ import { observer as observer3 } from "mobx-react";
1444
1470
  import {
1445
1471
  useCallback as useCallback2
1446
1472
  } from "react";
1447
- import { jsx as jsx4 } from "react/jsx-runtime";
1473
+ import { jsx as jsx5 } from "react/jsx-runtime";
1448
1474
  function createForm(valuePath, Form, observableProps) {
1449
1475
  return observer3((props) => {
1450
1476
  const { value } = observableProps.fields[valuePath];
1451
1477
  const onValueChange = useCallback2((value2) => {
1452
1478
  observableProps.onFieldValueChange(valuePath, value2);
1453
1479
  }, []);
1454
- return /* @__PURE__ */ jsx4(
1480
+ return /* @__PURE__ */ jsx5(
1455
1481
  Form,
1456
1482
  __spreadProps(__spreadValues({}, props), {
1457
1483
  onValueChange,
@@ -1462,7 +1488,7 @@ function createForm(valuePath, Form, observableProps) {
1462
1488
  }
1463
1489
 
1464
1490
  // mantine/create_list.tsx
1465
- import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
1491
+ import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
1466
1492
  function createList(valuePath, List) {
1467
1493
  const propSource = () => {
1468
1494
  const values = [...this.fields[valuePath].value];
@@ -1478,7 +1504,7 @@ function DefaultList({
1478
1504
  listPath,
1479
1505
  children
1480
1506
  }) {
1481
- return /* @__PURE__ */ jsx5(Fragment, { children: values.map(function(value, index) {
1507
+ return /* @__PURE__ */ jsx6(Fragment, { children: values.map(function(value, index) {
1482
1508
  const valuePath = `${listPath}.${index}`;
1483
1509
  return children(valuePath, value, index);
1484
1510
  }) });
@@ -1517,7 +1543,7 @@ function createRadio(valuePath, value, Radio) {
1517
1543
  }
1518
1544
 
1519
1545
  // mantine/create_radio_group.tsx
1520
- import { jsx as jsx6 } from "react/jsx-runtime";
1546
+ import { jsx as jsx7 } from "react/jsx-runtime";
1521
1547
  function createRadioGroup(valuePath, RadioGroup) {
1522
1548
  const onChange = (value) => {
1523
1549
  var _a;
@@ -1549,7 +1575,7 @@ function createRadioGroup(valuePath, RadioGroup) {
1549
1575
  name: valuePath,
1550
1576
  value,
1551
1577
  required,
1552
- error: error && /* @__PURE__ */ jsx6(ErrorRenderer, { error }),
1578
+ error: error && /* @__PURE__ */ jsx7(ErrorRenderer, { error }),
1553
1579
  onChange,
1554
1580
  onFocus,
1555
1581
  onBlur,
@@ -1560,7 +1586,7 @@ function createRadioGroup(valuePath, RadioGroup) {
1560
1586
  }
1561
1587
 
1562
1588
  // mantine/create_text_input.tsx
1563
- import { jsx as jsx7 } from "react/jsx-runtime";
1589
+ import { jsx as jsx8 } from "react/jsx-runtime";
1564
1590
  function createTextInput(valuePath, TextInput) {
1565
1591
  const onChange = (e) => {
1566
1592
  var _a;
@@ -1601,7 +1627,7 @@ function createTextInput(valuePath, TextInput) {
1601
1627
  value,
1602
1628
  disabled: readonly,
1603
1629
  required,
1604
- error: error && /* @__PURE__ */ jsx7(ErrorRenderer, { error }),
1630
+ error: error && /* @__PURE__ */ jsx8(ErrorRenderer, { error }),
1605
1631
  onChange,
1606
1632
  onFocus,
1607
1633
  onBlur,
@@ -1616,7 +1642,7 @@ function createTextInput(valuePath, TextInput) {
1616
1642
  }
1617
1643
 
1618
1644
  // mantine/create_value_input.tsx
1619
- import { jsx as jsx8 } from "react/jsx-runtime";
1645
+ import { jsx as jsx9 } from "react/jsx-runtime";
1620
1646
  function createValueInput(valuePath, ValueInput) {
1621
1647
  const onChange = (value) => {
1622
1648
  var _a;
@@ -1654,7 +1680,7 @@ function createValueInput(valuePath, ValueInput) {
1654
1680
  value,
1655
1681
  disabled: readonly,
1656
1682
  required,
1657
- error: error && /* @__PURE__ */ jsx8(ErrorRenderer, { error }),
1683
+ error: error && /* @__PURE__ */ jsx9(ErrorRenderer, { error }),
1658
1684
  onChange,
1659
1685
  onFocus,
1660
1686
  onBlur,
@@ -1669,9 +1695,9 @@ function createValueInput(valuePath, ValueInput) {
1669
1695
  }
1670
1696
 
1671
1697
  // mantine/hooks.tsx
1672
- import { jsx as jsx9 } from "react/jsx-runtime";
1698
+ import { jsx as jsx10 } from "react/jsx-runtime";
1673
1699
  function SimpleSelect(props) {
1674
- return /* @__PURE__ */ jsx9(Select, __spreadValues({}, props));
1700
+ return /* @__PURE__ */ jsx10(Select, __spreadValues({}, props));
1675
1701
  }
1676
1702
  function useMantineFormFields({
1677
1703
  onFieldValueChange,
@@ -1880,6 +1906,8 @@ function mergeValidators(validators1, validators2) {
1880
1906
  export {
1881
1907
  AbstractSelectValueTypeConverter,
1882
1908
  DefaultErrorRenderer,
1909
+ Empty,
1910
+ FieldView,
1883
1911
  FormModel,
1884
1912
  IntegerToStringConverter,
1885
1913
  NullableToBooleanConverter,
package/index.ts CHANGED
@@ -17,9 +17,11 @@ export * from './field_converters/trimming_string_converter'
17
17
  export * from './field_converters/validating_converter'
18
18
  export * from './field_value_factories/prototyping_field_value_factory'
19
19
  export * from './mantine/error_renderer'
20
+ export * from './mantine/field_view'
20
21
  export * from './mantine/hooks'
21
22
  export * from './types/error_of_field'
22
23
  export * from './types/field'
23
24
  export * from './types/field_converters'
24
25
  export * from './types/merge_validators'
26
+ export * from './util/empty'
25
27
  export * from './util/partial'
@@ -0,0 +1,39 @@
1
+ import { Observer } from 'mobx-react'
2
+ import { type ComponentType } from 'react'
3
+ import { type ErrorOfField } from 'types/error_of_field'
4
+ import { type Fields } from 'types/field'
5
+ import { type ValueTypeOfField } from 'types/value_type_of_field'
6
+ import { Empty } from 'util/empty'
7
+
8
+ /**
9
+ * Displays current value and error of a field
10
+ */
11
+ export function FieldView<F extends Fields, K extends keyof F>({
12
+ fields,
13
+ valuePath,
14
+ children,
15
+ }: {
16
+ fields: F,
17
+ valuePath: K,
18
+ children: (props: {
19
+ value: ValueTypeOfField<F[K]>,
20
+ error: ErrorOfField<F[K]> | undefined,
21
+ ErrorSink: ComponentType<{ error: ErrorOfField<F[K]> }>,
22
+ }) => JSX.Element,
23
+ }) {
24
+ return (
25
+ <Observer>
26
+ {() => {
27
+ const {
28
+ value,
29
+ error,
30
+ } = fields[valuePath]
31
+ return children({
32
+ value,
33
+ error,
34
+ ErrorSink: Empty,
35
+ })
36
+ }}
37
+ </Observer>
38
+ )
39
+ }
package/package.json CHANGED
@@ -70,7 +70,7 @@
70
70
  "test:watch": "vitest"
71
71
  },
72
72
  "type": "module",
73
- "version": "0.0.13",
73
+ "version": "0.0.15",
74
74
  "exports": {
75
75
  ".": {
76
76
  "import": {
@@ -25,8 +25,8 @@ export type MergedOfValidators<
25
25
  export type MergedOfValidator<
26
26
  Validator1 extends Validator,
27
27
  Validator2 extends Validator,
28
- > = Validator1 extends Validator<infer V, infer E1, infer P, infer C>
29
- ? Validator2 extends Validator<V, infer E2, P, C> ? Validator<V, E1 | E2, P, C>
28
+ > = Validator1 extends Validator<infer V, infer E1, infer P, infer C1>
29
+ ? Validator2 extends Validator<V, infer E2, P, infer C2> ? Validator<V, E1 | E2, P, C1 & C2>
30
30
  : never
31
31
  : never
32
32
 
package/util/empty.tsx ADDED
@@ -0,0 +1,3 @@
1
+ export function Empty() {
2
+ return null
3
+ }