@dxos/react-ui-form 0.8.4-main.dedc0f3 → 0.8.4-main.e8ec1fe
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.
- package/dist/lib/browser/index.mjs +480 -300
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +480 -300
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +5 -5
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +5 -5
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +4 -3
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +15 -15
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts +5 -5
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +2 -2
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +1 -1
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/RefField.d.ts +10 -6
- package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +5 -5
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/factory.d.ts +1 -1
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +41 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +81 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +20 -7
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +10 -10
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +2 -2
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +9 -3
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -1
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -4
- package/dist/types/src/util/field.d.ts +1 -1
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/refs.d.ts +1 -1
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -39
- package/src/components/ControlSection/ControlSection.stories.tsx +4 -5
- package/src/components/ControlSection/ControlSection.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.stories.tsx +6 -5
- package/src/components/FieldEditor/FieldEditor.tsx +5 -2
- package/src/components/Form/ArrayField.tsx +4 -3
- package/src/components/Form/Defaults.tsx +1 -1
- package/src/components/Form/Form.stories.tsx +35 -35
- package/src/components/Form/Form.tsx +16 -6
- package/src/components/Form/FormActions.tsx +2 -2
- package/src/components/Form/FormContent.tsx +82 -22
- package/src/components/Form/FormContext.tsx +3 -3
- package/src/components/Form/Input.tsx +1 -1
- package/src/components/Form/RefField.tsx +48 -64
- package/src/components/Form/custom/GeoPointInput.tsx +1 -1
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +5 -6
- package/src/components/Form/custom/SelectOptionsInput.tsx +2 -2
- package/src/components/Form/factory.tsx +1 -1
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +207 -0
- package/src/components/ObjectPicker/ObjectPicker.tsx +161 -0
- package/src/components/ObjectPicker/index.ts +5 -0
- package/src/components/ViewEditor/ViewEditor.stories.tsx +107 -59
- package/src/components/ViewEditor/ViewEditor.test.tsx +6 -5
- package/src/components/ViewEditor/ViewEditor.tsx +275 -231
- package/src/components/index.ts +1 -0
- package/src/components/testing.tsx +2 -2
- package/src/hooks/useForm.ts +7 -4
- package/src/hooks/useQueryRefOptions.ts +15 -6
- package/src/hooks/useRefQueryLookupHandler.ts +3 -3
- package/src/translations.ts +4 -4
- package/src/util/field.ts +1 -1
- package/src/util/formatting.ts +1 -1
- package/src/util/refs.ts +7 -7
- package/src/util/schema.ts +2 -4
|
@@ -2,107 +2,142 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
|
-
import
|
|
9
|
-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
10
8
|
|
|
11
|
-
import { Filter, Obj, Query, Type } from '@dxos/echo';
|
|
12
|
-
import { type EchoSchema, Format
|
|
13
|
-
import {
|
|
14
|
-
import { withClientProvider } from '@dxos/react-client/testing';
|
|
9
|
+
import { DXN, Filter, Obj, Query, type QueryAST, Tag, Type } from '@dxos/echo';
|
|
10
|
+
import { type EchoSchema, Format } from '@dxos/echo/internal';
|
|
11
|
+
import { useQuery } from '@dxos/react-client/echo';
|
|
12
|
+
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
15
13
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
16
|
-
import {
|
|
17
|
-
import { type
|
|
18
|
-
import {
|
|
14
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
15
|
+
import { type ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
|
|
16
|
+
import { Employer, Organization, Person, Project } from '@dxos/types';
|
|
19
17
|
|
|
20
18
|
import { translations } from '../../translations';
|
|
21
19
|
import { TestLayout, TestPanel, VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
|
|
22
20
|
|
|
23
21
|
import { ViewEditor, type ViewEditorProps } from './ViewEditor';
|
|
24
22
|
|
|
23
|
+
const types = [
|
|
24
|
+
// TODO(burdon): Get label from annotation.
|
|
25
|
+
{ value: Organization.Organization.typename, label: 'Organization' },
|
|
26
|
+
{ value: Person.Person.typename, label: 'Person' },
|
|
27
|
+
{ value: Type.getTypename(Project.Project), label: 'Project' },
|
|
28
|
+
{ value: Employer.Employer.typename, label: 'Employer' },
|
|
29
|
+
];
|
|
30
|
+
|
|
25
31
|
// Type definition for debug objects exposed to tests.
|
|
26
32
|
export type ViewEditorDebugObjects = {
|
|
27
33
|
schema: EchoSchema;
|
|
28
|
-
view:
|
|
34
|
+
view: View.View;
|
|
29
35
|
projection: ProjectionModel;
|
|
30
36
|
};
|
|
31
37
|
|
|
32
|
-
type StoryProps = Pick<ViewEditorProps, 'readonly' | '
|
|
38
|
+
type StoryProps = Pick<ViewEditorProps, 'readonly' | 'mode'>;
|
|
33
39
|
|
|
34
40
|
const DefaultStory = (props: StoryProps) => {
|
|
35
|
-
const space =
|
|
41
|
+
const { space } = useClientProvider();
|
|
36
42
|
const [schema, setSchema] = useState<EchoSchema>();
|
|
37
|
-
const [view, setView] = useState<
|
|
38
|
-
const
|
|
43
|
+
const [view, setView] = useState<View.View>();
|
|
44
|
+
const projectionRef = useRef<ProjectionModel>(null);
|
|
45
|
+
|
|
46
|
+
const tags = useQuery(space, Filter.type(Tag.Tag));
|
|
47
|
+
|
|
39
48
|
useAsyncEffect(async () => {
|
|
40
49
|
if (space) {
|
|
41
|
-
|
|
50
|
+
const TestSchema = Schema.Struct({
|
|
42
51
|
name: Schema.String,
|
|
43
52
|
email: Format.Email,
|
|
44
53
|
salary: Format.Currency(),
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
}).pipe(
|
|
55
|
+
Type.Obj({
|
|
56
|
+
typename: 'example.com/type/Test',
|
|
57
|
+
version: '0.1.0',
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const AlternateSchema = Schema.Struct({
|
|
62
|
+
title: Schema.String,
|
|
63
|
+
description: Schema.String,
|
|
64
|
+
completed: Schema.Boolean,
|
|
65
|
+
}).pipe(
|
|
66
|
+
Type.Obj({
|
|
67
|
+
typename: 'example.com/type/Alternate',
|
|
68
|
+
version: '0.1.0',
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const [testSchema] = await space.db.schemaRegistry.register([TestSchema, AlternateSchema]);
|
|
73
|
+
const view = View.make({
|
|
49
74
|
name: 'Test',
|
|
50
|
-
|
|
51
|
-
jsonSchema: toJsonSchema(TestSchema),
|
|
75
|
+
query: Query.select(Filter.type(TestSchema)),
|
|
76
|
+
jsonSchema: Type.toJsonSchema(TestSchema),
|
|
52
77
|
presentation: Obj.make(Type.Expando, {}),
|
|
53
78
|
});
|
|
54
|
-
const projection = new ProjectionModel(schema.jsonSchema, view.projection);
|
|
55
79
|
|
|
56
|
-
setSchema(
|
|
80
|
+
setSchema(testSchema);
|
|
57
81
|
setView(view);
|
|
58
|
-
setProjection(projection);
|
|
59
82
|
}
|
|
60
83
|
}, [space]);
|
|
61
84
|
|
|
62
85
|
const updateViewQuery = useCallback(
|
|
63
|
-
(
|
|
64
|
-
if (!schema || !view) {
|
|
86
|
+
async (newQuery: QueryAST.Query, target?: string) => {
|
|
87
|
+
if (!schema || !view || !space) {
|
|
65
88
|
return;
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
if (props.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
if (props.mode === 'query') {
|
|
92
|
+
const queue = target && DXN.tryParse(target) ? target : undefined;
|
|
93
|
+
const query = queue ? Query.fromAst(newQuery).options({ queues: [queue] }) : Query.fromAst(newQuery);
|
|
94
|
+
view.query.ast = query.ast;
|
|
95
|
+
|
|
96
|
+
const typename = getTypenameFromQuery(query.ast);
|
|
97
|
+
const [newSchema] = await space.db.schemaRegistry.query({ typename }).run();
|
|
98
|
+
if (!newSchema) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const newView = View.make({
|
|
103
|
+
query,
|
|
104
|
+
jsonSchema: newSchema.jsonSchema,
|
|
105
|
+
presentation: Obj.make(Type.Expando, {}),
|
|
106
|
+
});
|
|
107
|
+
view.projection = Obj.getSnapshot(newView).projection;
|
|
108
|
+
setSchema(() => newSchema);
|
|
80
109
|
} else {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
schema.updateTypename(typename);
|
|
110
|
+
console.log('updateViewQuery', { newQuery });
|
|
111
|
+
view.query.ast = newQuery;
|
|
112
|
+
schema.updateTypename(getTypenameFromQuery(newQuery));
|
|
85
113
|
}
|
|
86
114
|
},
|
|
87
115
|
[view, schema],
|
|
88
116
|
);
|
|
89
117
|
|
|
90
|
-
const handleDelete = useCallback(
|
|
118
|
+
const handleDelete = useCallback(
|
|
119
|
+
(property: string) => projectionRef.current?.deleteFieldProjection(property),
|
|
120
|
+
[projectionRef],
|
|
121
|
+
);
|
|
91
122
|
|
|
92
123
|
// Expose objects on window for test access.
|
|
93
124
|
useEffect(() => {
|
|
94
|
-
if (typeof window !== 'undefined' && schema && view &&
|
|
95
|
-
(window as any)[VIEW_EDITOR_DEBUG_SYMBOL] = {
|
|
125
|
+
if (typeof window !== 'undefined' && schema && view && projectionRef.current) {
|
|
126
|
+
(window as any)[VIEW_EDITOR_DEBUG_SYMBOL] = {
|
|
127
|
+
schema,
|
|
128
|
+
view,
|
|
129
|
+
projection: projectionRef.current,
|
|
130
|
+
} satisfies ViewEditorDebugObjects;
|
|
96
131
|
}
|
|
97
|
-
}, [schema, view
|
|
132
|
+
}, [schema, view]);
|
|
98
133
|
|
|
99
134
|
// NOTE(ZaymonFC): This looks awkward but it resolves an infinite parsing issue with sb.
|
|
100
135
|
const json = useMemo(
|
|
101
|
-
() => JSON.parse(JSON.stringify({ schema, view, projection })),
|
|
102
|
-
[JSON.stringify(schema), JSON.stringify(view)
|
|
136
|
+
() => JSON.parse(JSON.stringify({ schema, view, projection: projectionRef.current })),
|
|
137
|
+
[JSON.stringify(schema), JSON.stringify(view)],
|
|
103
138
|
);
|
|
104
139
|
|
|
105
|
-
if (!schema || !view
|
|
140
|
+
if (!schema || !view) {
|
|
106
141
|
return <div />;
|
|
107
142
|
}
|
|
108
143
|
|
|
@@ -110,11 +145,14 @@ const DefaultStory = (props: StoryProps) => {
|
|
|
110
145
|
<TestLayout json={json}>
|
|
111
146
|
<TestPanel>
|
|
112
147
|
<ViewEditor
|
|
148
|
+
ref={projectionRef}
|
|
113
149
|
schema={schema}
|
|
114
150
|
view={view}
|
|
115
151
|
registry={space?.db.schemaRegistry}
|
|
116
|
-
|
|
152
|
+
mode={props.mode}
|
|
117
153
|
readonly={props.readonly}
|
|
154
|
+
types={types}
|
|
155
|
+
tags={tags}
|
|
118
156
|
onQueryChanged={updateViewQuery}
|
|
119
157
|
onDelete={handleDelete}
|
|
120
158
|
/>
|
|
@@ -129,13 +167,19 @@ const meta = {
|
|
|
129
167
|
decorators: [
|
|
130
168
|
withClientProvider({
|
|
131
169
|
createSpace: true,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
170
|
+
types: [Tag.Tag],
|
|
171
|
+
onCreateSpace: ({ space }) => {
|
|
172
|
+
space.db.add(Tag.make({ label: 'Important' }));
|
|
173
|
+
space.db.add(Tag.make({ label: 'Investor' }));
|
|
174
|
+
space.db.add(Tag.make({ label: 'New' }));
|
|
175
|
+
},
|
|
135
176
|
}),
|
|
136
177
|
withTheme,
|
|
137
178
|
],
|
|
138
|
-
parameters: {
|
|
179
|
+
parameters: {
|
|
180
|
+
layout: 'fullscreen',
|
|
181
|
+
translations,
|
|
182
|
+
},
|
|
139
183
|
} satisfies Meta<typeof DefaultStory>;
|
|
140
184
|
|
|
141
185
|
export default meta;
|
|
@@ -145,9 +189,13 @@ type Story = StoryObj<typeof meta>;
|
|
|
145
189
|
export const Default: Story = {};
|
|
146
190
|
|
|
147
191
|
export const Readonly: Story = {
|
|
148
|
-
args: {
|
|
192
|
+
args: {
|
|
193
|
+
readonly: true,
|
|
194
|
+
},
|
|
149
195
|
};
|
|
150
196
|
|
|
151
|
-
export const
|
|
152
|
-
args: {
|
|
197
|
+
export const QueryMode: Story = {
|
|
198
|
+
args: {
|
|
199
|
+
mode: 'query',
|
|
200
|
+
},
|
|
153
201
|
};
|
|
@@ -6,8 +6,8 @@ import { composeStories } from '@storybook/react';
|
|
|
6
6
|
import { cleanup, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
7
7
|
import { afterEach, describe, expect, test } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { EchoSchema, isInstanceOf } from '@dxos/echo
|
|
10
|
-
import {
|
|
9
|
+
import { EchoSchema, isInstanceOf } from '@dxos/echo/internal';
|
|
10
|
+
import { ProjectionModel, View } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
|
|
13
13
|
|
|
@@ -20,7 +20,7 @@ const getViewEditorDebugObjects = (): ViewEditorDebugObjects => {
|
|
|
20
20
|
const debugObjects = (window as any)[VIEW_EDITOR_DEBUG_SYMBOL] as ViewEditorDebugObjects;
|
|
21
21
|
expect(debugObjects).toBeDefined();
|
|
22
22
|
expect(debugObjects.schema).toBeInstanceOf(EchoSchema);
|
|
23
|
-
expect(isInstanceOf(
|
|
23
|
+
expect(isInstanceOf(View.View, debugObjects.view)).toBeTruthy();
|
|
24
24
|
expect(debugObjects.projection).toBeInstanceOf(ProjectionModel);
|
|
25
25
|
return debugObjects;
|
|
26
26
|
};
|
|
@@ -134,7 +134,8 @@ describe('ViewEditor', () => {
|
|
|
134
134
|
expect(addedPropertyProjection!.props.property).toBe('added_property');
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
// TODO(mykola): Fix flaky test.
|
|
138
|
+
test('delete property', { retry: 2 }, async () => {
|
|
138
139
|
await Default.run();
|
|
139
140
|
await waitForViewEditor();
|
|
140
141
|
|
|
@@ -200,4 +201,4 @@ describe('ViewEditor', () => {
|
|
|
200
201
|
// Also verify that the field is back in the visible fields list.
|
|
201
202
|
expect(debugObjects.view.projection.fields.filter(({ visible }) => visible !== false).length).toBeGreaterThan(0);
|
|
202
203
|
});
|
|
203
|
-
});
|
|
204
|
+
}, 30_000);
|