@dxos/react-ui-form 0.8.2-staging.7ac8446 → 0.8.3-main.672df60

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 (115) hide show
  1. package/dist/lib/browser/index.mjs +1817 -1309
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +1773 -1273
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +1817 -1309
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/{ControlSection.d.ts → ControlSection/ControlSection.d.ts} +9 -6
  11. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -0
  12. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +8 -0
  13. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -0
  14. package/dist/types/src/components/ControlSection/index.d.ts +2 -0
  15. package/dist/types/src/components/ControlSection/index.d.ts.map +1 -0
  16. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  17. package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts +2 -0
  18. package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts.map +1 -0
  19. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/Defaults.d.ts +4 -4
  21. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/Form.d.ts +6 -4
  23. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/Form.stories.d.ts +38 -36
  25. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/FormActions.d.ts +1 -1
  27. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/FormContent.d.ts +16 -12
  29. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/FormContext.d.ts +2 -2
  31. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  32. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  33. package/dist/types/src/components/Form/RefField.d.ts +12 -0
  34. package/dist/types/src/components/Form/RefField.d.ts.map +1 -0
  35. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  36. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  37. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  39. package/dist/types/src/components/Form/factory.d.ts +1 -1
  40. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  41. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  42. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  43. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  44. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  45. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +5 -3
  46. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/ViewEditor/ViewEditor.test.d.ts +2 -0
  48. package/dist/types/src/components/ViewEditor/ViewEditor.test.d.ts.map +1 -0
  49. package/dist/types/src/components/deprecated/Form.d.ts +2 -2
  50. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  51. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  53. package/dist/types/src/components/index.d.ts.map +1 -1
  54. package/dist/types/src/components/testing.d.ts.map +1 -1
  55. package/dist/types/src/hooks/index.d.ts +2 -0
  56. package/dist/types/src/hooks/index.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useForm.d.ts +2 -2
  58. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
  60. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
  61. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
  62. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
  63. package/dist/types/src/translations.d.ts +5 -0
  64. package/dist/types/src/translations.d.ts.map +1 -1
  65. package/dist/types/src/util/field.d.ts.map +1 -1
  66. package/dist/types/src/util/formatting.d.ts.map +1 -1
  67. package/dist/types/src/util/index.d.ts +2 -0
  68. package/dist/types/src/util/index.d.ts.map +1 -1
  69. package/dist/types/src/util/refs.d.ts +9 -0
  70. package/dist/types/src/util/refs.d.ts.map +1 -0
  71. package/dist/types/src/util/schema.d.ts +3 -0
  72. package/dist/types/src/util/schema.d.ts.map +1 -0
  73. package/dist/types/src/vitest-setup.d.ts +2 -0
  74. package/dist/types/src/vitest-setup.d.ts.map +1 -0
  75. package/dist/types/tsconfig.tsbuildinfo +1 -1
  76. package/package.json +28 -25
  77. package/src/components/ControlSection/ControlSection.stories.tsx +29 -0
  78. package/src/components/{ControlSection.tsx → ControlSection/ControlSection.tsx} +40 -16
  79. package/src/components/ControlSection/index.ts +5 -0
  80. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  81. package/src/components/FieldEditor/FieldEditor.test.tsx +49 -0
  82. package/src/components/FieldEditor/FieldEditor.tsx +3 -2
  83. package/src/components/Form/ArrayField.tsx +63 -50
  84. package/src/components/Form/Defaults.tsx +77 -48
  85. package/src/components/Form/Form.stories.tsx +134 -109
  86. package/src/components/Form/Form.tsx +8 -5
  87. package/src/components/Form/FormActions.tsx +15 -18
  88. package/src/components/Form/FormContent.tsx +116 -46
  89. package/src/components/Form/FormContext.tsx +24 -10
  90. package/src/components/Form/Input.tsx +4 -10
  91. package/src/components/Form/RefField.tsx +217 -0
  92. package/src/components/Form/custom/GeoPointInput.tsx +2 -2
  93. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
  94. package/src/components/Form/custom/SelectOptionsInput.tsx +2 -2
  95. package/src/components/Form/factory.tsx +1 -1
  96. package/src/components/Form/index.ts +0 -1
  97. package/src/components/ViewEditor/ViewEditor.stories.tsx +19 -9
  98. package/src/components/ViewEditor/ViewEditor.test.tsx +166 -0
  99. package/src/components/ViewEditor/ViewEditor.tsx +63 -30
  100. package/src/components/deprecated/Form.stories.tsx +6 -6
  101. package/src/components/deprecated/Form.tsx +6 -6
  102. package/src/components/deprecated/FormInput.tsx +1 -1
  103. package/src/components/index.ts +1 -0
  104. package/src/components/testing.tsx +5 -9
  105. package/src/hooks/index.ts +3 -1
  106. package/src/hooks/useForm.ts +4 -3
  107. package/src/hooks/useQueryRefOptions.ts +53 -0
  108. package/src/hooks/useRefQueryLookupHandler.ts +39 -0
  109. package/src/translations.ts +9 -2
  110. package/src/util/formatting.ts +15 -3
  111. package/src/util/index.ts +3 -1
  112. package/src/util/refs.ts +38 -0
  113. package/src/util/schema.ts +14 -0
  114. package/src/vitest-setup.ts +11 -0
  115. package/dist/types/src/components/ControlSection.d.ts.map +0 -1
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useEffect, useState } from 'react';
6
+
7
+ import { type TypeAnnotation } from '@dxos/echo-schema';
8
+ import { type DXN } from '@dxos/keys';
9
+ import { log } from '@dxos/log';
10
+ import { type TagPickerItemData } from '@dxos/react-ui-tag-picker';
11
+ import { type MaybePromise } from '@dxos/util';
12
+
13
+ export type RefOption = { dxn: DXN; label?: string };
14
+ export type QueryRefOptions = (type: TypeAnnotation) => MaybePromise<RefOption[]>;
15
+
16
+ type UseQueryRefOptionsProps = { refTypeInfo: TypeAnnotation | undefined; onQueryRefOptions?: QueryRefOptions };
17
+
18
+ /**
19
+ * Hook to query reference options based on type information.
20
+ * Used internally within forms to fetch and format reference options for reference fields.
21
+ */
22
+ export const useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }: UseQueryRefOptionsProps) => {
23
+ const [options, setOptions] = useState<TagPickerItemData[]>([]);
24
+ const [loading, setLoading] = useState(false);
25
+
26
+ useEffect(() => {
27
+ if (!refTypeInfo || !onQueryRefOptions) {
28
+ return;
29
+ }
30
+
31
+ const fetchOptions = async () => {
32
+ setLoading(true);
33
+ try {
34
+ const fetchedOptions = await onQueryRefOptions(refTypeInfo);
35
+ setOptions(
36
+ fetchedOptions.map((option) => {
37
+ const dxn = option.dxn.toString() as string;
38
+ return { id: dxn, label: option.label ?? dxn, hue: 'neutral' as any };
39
+ }),
40
+ );
41
+ } catch (error) {
42
+ log.error('Failed to fetch ref options:', error);
43
+ setOptions([]);
44
+ } finally {
45
+ setLoading(false);
46
+ }
47
+ };
48
+
49
+ void fetchOptions();
50
+ }, [refTypeInfo, onQueryRefOptions]);
51
+
52
+ return { options, loading };
53
+ };
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useCallback } from 'react';
6
+
7
+ import { getObjectDXN, type TypeAnnotation } from '@dxos/echo-schema';
8
+ import { Filter, type Space } from '@dxos/react-client/echo';
9
+ import { isNonNullable } from '@dxos/util';
10
+
11
+ import { type QueryRefOptions } from './useQueryRefOptions';
12
+
13
+ type UseRefQueryLookupProps = { space?: Space };
14
+
15
+ export const useRefQueryLookupHandler = ({ space }: UseRefQueryLookupProps): QueryRefOptions => {
16
+ return useCallback(
17
+ async (typeInfo: TypeAnnotation) => {
18
+ if (!space) {
19
+ return [];
20
+ }
21
+ const query = space.db.query(Filter.typename(typeInfo.typename));
22
+ const { objects } = await query.run();
23
+
24
+ return objects
25
+ .map((object) => {
26
+ const dxn = getObjectDXN(object);
27
+ if (!dxn) {
28
+ return undefined;
29
+ }
30
+
31
+ // TODO(Zaymon): Better fallback object names?
32
+ const item = { dxn, label: object?.name ?? object?.id ?? '' };
33
+ return item;
34
+ })
35
+ .filter(isNonNullable);
36
+ },
37
+ [space],
38
+ );
39
+ };
@@ -10,6 +10,7 @@ export default [
10
10
  [translationKey]: {
11
11
  'fields label': 'Fields',
12
12
  'hidden fields label': 'Hidden Fields',
13
+ 'empty readonly ref field label': '(none)',
13
14
 
14
15
  // TODO(burdon): Standardize field/property.
15
16
  'button add property': 'Add property',
@@ -20,6 +21,8 @@ export default [
20
21
  'add field': 'Add field',
21
22
  'delete field': 'Delete field',
22
23
  'field limit reached': 'Maximum number of fields reached',
24
+ 'boolean input true value': 'Yes',
25
+ 'boolean input false value': 'No',
23
26
 
24
27
  // TODO(burdon): Factor out?
25
28
  'button cancel': 'Cancel',
@@ -52,16 +55,20 @@ export default [
52
55
  'format uri': 'URI',
53
56
  'format uuid': 'UUID',
54
57
 
55
- // Placeholders
58
+ // Placeholders.
56
59
  'placeholder latitude': 'Latitude',
57
60
  'placeholder longitude': 'Longitude',
58
61
 
59
- // SelectOptionsInput
62
+ // SelectOptionsInput.
60
63
  'select option label': 'Label',
61
64
  'select option label placeholder': 'Option label',
62
65
  'select option color': 'Color',
63
66
  'select option delete': 'Delete',
64
67
  'select option add': 'Add option',
68
+
69
+ // System schema message.
70
+ 'system schema title': 'System Schema',
71
+ 'system schema description': 'This schema is managed by the system and cannot be modified.',
65
72
  },
66
73
  },
67
74
  },
@@ -64,13 +64,25 @@ export const formatForDisplay = ({ type, format, value, locale = undefined }: Va
64
64
  });
65
65
  }
66
66
  case FormatEnum.Date: {
67
- return formatDate(new Date(value as number), 'yyyy-MM-dd');
67
+ try {
68
+ return formatDate(new Date(value as number), 'yyyy-MM-dd');
69
+ } catch (error) {
70
+ return 'Invalid Date';
71
+ }
68
72
  }
69
73
  case FormatEnum.Time: {
70
- return formatDate(new Date(value as number), 'HH:mm:ss');
74
+ try {
75
+ return formatDate(new Date(value as number), 'HH:mm:ss');
76
+ } catch (error) {
77
+ return 'Invalid Time';
78
+ }
71
79
  }
72
80
  case FormatEnum.DateTime: {
73
- return formatDate(new Date(value as number), 'yyyy-MM-dd HH:mm:ss');
81
+ try {
82
+ return formatDate(new Date(value as number), 'yyyy-MM-dd HH:mm:ss');
83
+ } catch (error) {
84
+ return 'Invalid DateTime';
85
+ }
74
86
  }
75
87
  case FormatEnum.GeoPoint: {
76
88
  if (value === null || value === undefined) {
package/src/util/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  //
2
- // Copyright 2024 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
5
  export * from './field';
6
6
  export * from './formatting';
7
+ export * from './refs';
8
+ export * from './schema';
@@ -0,0 +1,38 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type SchemaAST } from 'effect';
6
+
7
+ import { FormatEnum, ReferenceAnnotationId } from '@dxos/echo-schema';
8
+ import { findAnnotation } from '@dxos/effect';
9
+ import { type SchemaProperty } from '@dxos/schema';
10
+
11
+ import { findArrayElementType } from './schema';
12
+
13
+ type RefProps = {
14
+ ast: SchemaAST.AST;
15
+ isArray: boolean;
16
+ };
17
+
18
+ export const getRefProps = (property: SchemaProperty<any>): RefProps | undefined => {
19
+ const { ast, format, array } = property;
20
+
21
+ // Direct reference.
22
+ if (format === FormatEnum.Ref) {
23
+ return { ast, isArray: false };
24
+ }
25
+
26
+ // Array of references.
27
+ if (array) {
28
+ const elementType = findArrayElementType(ast);
29
+ if (elementType) {
30
+ const annotation = findAnnotation(elementType, ReferenceAnnotationId);
31
+ if (annotation) {
32
+ return { ast: elementType, isArray: true };
33
+ }
34
+ }
35
+ }
36
+
37
+ return undefined;
38
+ };
@@ -0,0 +1,14 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { SchemaAST } from 'effect';
6
+
7
+ import { findNode } from '@dxos/effect';
8
+
9
+ export const findArrayElementType = (ast: SchemaAST.AST) => {
10
+ const tupleType = findNode(ast, SchemaAST.isTupleType);
11
+ const elementType = (tupleType as SchemaAST.TupleType | undefined)?.rest[0]?.type;
12
+
13
+ return elementType;
14
+ };
@@ -0,0 +1,11 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // https://github.com/testing-library/jest-dom#with-vitest
6
+ import '@testing-library/jest-dom/vitest';
7
+
8
+ // https://github.com/jsdom/jsdom/issues/3368#issuecomment-1396749033
9
+ import ResizeObserver from 'resize-observer-polyfill';
10
+
11
+ global.ResizeObserver = ResizeObserver;
@@ -1 +0,0 @@
1
- {"version":3,"file":"ControlSection.d.ts","sourceRoot":"","sources":["../../../../src/components/ControlSection.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAE,KAAK,KAAK,EAA4C,MAAM,gBAAgB,CAAC;AAMtF,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;IAClD,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,KAAK,CAAC;CACrB,CAAC,CAAC;AAEH,eAAO,MAAM,qBAAqB,2BAA4B,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,sBAUlG,CAAC;AAEF,eAAO,MAAM,cAAc,qCAAsC,mBAAmB,sBAOnF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;AAEtD,eAAO,MAAM,YAAY,iBAAkB,iBAAiB,sBAI3D,CAAC;AAEF,eAAO,MAAM,YAAY,iBAAkB,iBAAiB,sBAO3D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;IAC/C,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,KAAK,CAAC;CACrB,CAAC,CAAC;AAEH,eAAO,MAAM,kBAAkB,iHACiF,CAAC;AAKjH,eAAO,MAAM,WAAW,qCAAsC,gBAAgB,sBAY7E,CAAC;AAEF,eAAO,MAAM,gBAAgB,qCAAsC,gBAAgB,sBAoBlF,CAAC;AAEF,eAAO,MAAM,gBAAgB,qCAAsC,gBAAgB,sBAUlF,CAAC"}