@dxos/react-ui-table 0.8.4-main.d05673bc65 → 0.8.4-main.d9fc60f731
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/LICENSE +102 -5
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PTHMYAAM.mjs → chunk-X7A7G6RR.mjs} +28 -83
- package/dist/lib/browser/chunk-X7A7G6RR.mjs.map +7 -0
- package/dist/lib/browser/{chunk-BF54SSNL.mjs → chunk-YURROGGF.mjs} +12 -15
- package/dist/lib/browser/chunk-YURROGGF.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +230 -280
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +10 -9
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/translations.mjs +36 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -1
- package/dist/lib/node-esm/{chunk-SIRDIPHZ.mjs → chunk-DLAGRBKD.mjs} +12 -15
- package/dist/lib/node-esm/chunk-DLAGRBKD.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-GI72MQSG.mjs → chunk-Q4HSBRJJ.mjs} +28 -83
- package/dist/lib/node-esm/chunk-Q4HSBRJJ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +230 -280
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +10 -9
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/translations.mjs +37 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -1
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +2 -2
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +3 -4
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +21 -22
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +83 -82
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +20 -21
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +85 -84
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +18 -0
- package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +22 -24
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +1 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +4 -5
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +19 -21
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +11 -5
- package/dist/types/src/types/Table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +6 -6
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts.map +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/src/util/signals.d.ts.map +1 -1
- package/dist/types/src/util/sort.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts +20 -20
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +4 -4
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/tag.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +55 -64
- package/src/components/Table/ColumnActionsMenu.tsx +7 -6
- package/src/components/Table/ColumnSettings.tsx +2 -2
- package/src/components/Table/DynamicTable.stories.tsx +19 -19
- package/src/components/Table/DynamicTable.tsx +13 -22
- package/src/components/Table/Relations.stories.tsx +76 -34
- package/src/components/Table/RowActionsMenu.tsx +3 -2
- package/src/components/Table/Table.stories.tsx +46 -51
- package/src/components/Table/Table.tsx +37 -426
- package/src/components/Table/TableContent.tsx +426 -0
- package/src/components/{TableToolbar → Table}/TableToolbar.tsx +34 -41
- package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -2
- package/src/components/TableCellEditor/FormCellEditor.tsx +7 -6
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +14 -12
- package/src/components/TableCellEditor/TableCellEditor.tsx +10 -8
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +11 -16
- package/src/hooks/useProjectionModel.ts +5 -6
- package/src/hooks/useTableModel.ts +1 -1
- package/src/index.ts +0 -4
- package/src/model/table-model.test.ts +4 -10
- package/src/model/table-model.ts +15 -15
- package/src/model/table-presentation.test.ts +4 -10
- package/src/model/table-presentation.ts +5 -7
- package/src/playwright/smoke.spec.ts +3 -3
- package/src/testing/useTestTableModel.ts +7 -8
- package/src/translations.ts +19 -21
- package/src/types/Table.ts +12 -13
- package/src/util/dynamic-table.test.ts +13 -20
- package/src/util/dynamic-table.ts +21 -20
- package/dist/lib/browser/chunk-BF54SSNL.mjs.map +0 -7
- package/dist/lib/browser/chunk-PTHMYAAM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-GI72MQSG.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +0 -7
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
- package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
- package/src/components/TableToolbar/index.ts +0 -5
|
@@ -25,16 +25,9 @@ import {
|
|
|
25
25
|
import { type FieldProjection } from '@dxos/schema';
|
|
26
26
|
|
|
27
27
|
import { type ModalController, type TableModel } from '../../model';
|
|
28
|
-
|
|
29
28
|
import { CellValidationMessage } from './CellValidationMessage';
|
|
30
29
|
import { FormCellEditor, type OnCreateHandler } from './FormCellEditor';
|
|
31
30
|
|
|
32
|
-
const editorSlots = {
|
|
33
|
-
scroll: {
|
|
34
|
-
className: '!py-(--dx-grid-cell-editor-padding-block)',
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
31
|
/**
|
|
39
32
|
* Option to create new object/value.
|
|
40
33
|
*/
|
|
@@ -250,7 +243,16 @@ export const TableCellEditor = ({
|
|
|
250
243
|
return (
|
|
251
244
|
<>
|
|
252
245
|
<CellValidationMessage validationError={validationError} variant={validationVariant} __gridScope={__gridScope} />
|
|
253
|
-
<GridCellEditor
|
|
246
|
+
<GridCellEditor
|
|
247
|
+
extensions={extensions}
|
|
248
|
+
slots={{
|
|
249
|
+
content: {
|
|
250
|
+
className: '!py-(--dx-grid-cell-editor-padding-block)',
|
|
251
|
+
},
|
|
252
|
+
}}
|
|
253
|
+
getCellContent={getCellContent}
|
|
254
|
+
onBlur={handleBlur}
|
|
255
|
+
/>
|
|
254
256
|
</>
|
|
255
257
|
);
|
|
256
258
|
};
|
package/src/components/index.ts
CHANGED
|
@@ -6,10 +6,10 @@ import { Atom } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { useEffect } from 'react';
|
|
8
8
|
|
|
9
|
-
import { Format, Type } from '@dxos/echo';
|
|
9
|
+
import { DXN, Format, Type } from '@dxos/echo';
|
|
10
10
|
import { TypeEnum } from '@dxos/echo/internal';
|
|
11
11
|
import { setValue } from '@dxos/effect';
|
|
12
|
-
import {
|
|
12
|
+
import { random } from '@dxos/random';
|
|
13
13
|
import { type ProjectionModel } from '@dxos/schema';
|
|
14
14
|
|
|
15
15
|
export const TestSchema = Schema.Struct({
|
|
@@ -17,12 +17,7 @@ export const TestSchema = Schema.Struct({
|
|
|
17
17
|
age: Schema.optional(Schema.Number),
|
|
18
18
|
active: Schema.optional(Schema.Boolean),
|
|
19
19
|
netWorth: Schema.optional(Schema.Number),
|
|
20
|
-
}).pipe(
|
|
21
|
-
Type.object({
|
|
22
|
-
typename: 'com.example.type.test',
|
|
23
|
-
version: '0.1.0',
|
|
24
|
-
}),
|
|
25
|
-
);
|
|
20
|
+
}).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
|
|
26
21
|
|
|
27
22
|
export type TestItem = {
|
|
28
23
|
name: string;
|
|
@@ -37,10 +32,10 @@ export type TestItem = {
|
|
|
37
32
|
export const createItemsAtom = (n: number) => {
|
|
38
33
|
return Atom.make<{ data: TestItem[] }>({
|
|
39
34
|
data: Array.from({ length: n }, () => ({
|
|
40
|
-
name:
|
|
41
|
-
age:
|
|
42
|
-
active:
|
|
43
|
-
netWorth:
|
|
35
|
+
name: random.person.fullName(),
|
|
36
|
+
age: random.number.int({ min: 20, max: 70 }),
|
|
37
|
+
active: random.datatype.boolean(),
|
|
38
|
+
netWorth: random.number.int(),
|
|
44
39
|
})),
|
|
45
40
|
}).pipe(Atom.keepAlive);
|
|
46
41
|
};
|
|
@@ -50,10 +45,10 @@ export const createItemsAtom = (n: number) => {
|
|
|
50
45
|
*/
|
|
51
46
|
export const createItems = (n: number): TestItem[] => {
|
|
52
47
|
return Array.from({ length: n }, () => ({
|
|
53
|
-
name:
|
|
54
|
-
age:
|
|
55
|
-
active:
|
|
56
|
-
netWorth:
|
|
48
|
+
name: random.person.fullName(),
|
|
49
|
+
age: random.number.int({ min: 20, max: 70 }),
|
|
50
|
+
active: random.datatype.boolean(),
|
|
51
|
+
netWorth: random.number.int(),
|
|
57
52
|
}));
|
|
58
53
|
};
|
|
59
54
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
import { useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { Type } from '@dxos/echo';
|
|
9
9
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
10
10
|
import { ProjectionModel, createEchoChangeCallback } from '@dxos/schema';
|
|
11
11
|
|
|
@@ -21,13 +21,12 @@ export const useProjectionModel = <S extends Type.AnyEntity>(
|
|
|
21
21
|
useAsyncEffect(async () => {
|
|
22
22
|
if (schema && table) {
|
|
23
23
|
const view = await table.view.load();
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : JsonSchema.toJsonSchema(schema);
|
|
24
|
+
// Use the live jsonSchema reference for reactivity.
|
|
25
|
+
const jsonSchema = schema.jsonSchema;
|
|
27
26
|
|
|
28
27
|
// Always use createEchoChangeCallback since the view is ECHO-backed.
|
|
29
|
-
// Pass
|
|
30
|
-
const change = createEchoChangeCallback(view, Type.
|
|
28
|
+
// Pass the type entity only when stored, to allow schema mutations.
|
|
29
|
+
const change = createEchoChangeCallback(view, Type.getDatabase(schema) != null ? schema : undefined);
|
|
31
30
|
|
|
32
31
|
const projection = new ProjectionModel({ registry, view, baseSchema: jsonSchema, change });
|
|
33
32
|
projection.normalizeView();
|
|
@@ -44,7 +44,7 @@ export const useTableModel = <T extends TableRow = TableRow>({
|
|
|
44
44
|
...props
|
|
45
45
|
}: UseTableModelProps<T>): TableModel<T> | undefined => {
|
|
46
46
|
const registry = useContext(RegistryContext);
|
|
47
|
-
const selected = useSelected(object && Obj.
|
|
47
|
+
const selected = useSelected(object && Obj.getURI(object), 'multi');
|
|
48
48
|
const initialSelection = useMemo(() => selected, [object]);
|
|
49
49
|
|
|
50
50
|
const [model, setModel] = useState<TableModel<T>>();
|
package/src/index.ts
CHANGED
|
@@ -6,12 +6,11 @@ import { Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { DXN, Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
11
|
import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
|
|
12
12
|
|
|
13
13
|
import { Table } from '../types';
|
|
14
|
-
|
|
15
14
|
import {
|
|
16
15
|
TableModel,
|
|
17
16
|
type TableModelProps,
|
|
@@ -119,15 +118,10 @@ describe('TableModel', () => {
|
|
|
119
118
|
const Test = Schema.Struct({
|
|
120
119
|
title: Schema.String,
|
|
121
120
|
completed: Schema.Boolean,
|
|
122
|
-
}).pipe(
|
|
123
|
-
Type.object({
|
|
124
|
-
typename: 'com.example.type.test',
|
|
125
|
-
version: '0.1.0',
|
|
126
|
-
}),
|
|
127
|
-
);
|
|
121
|
+
}).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
|
|
128
122
|
|
|
129
123
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
130
|
-
const schema = createEchoSchema(Test);
|
|
124
|
+
const schema = createEchoSchema(Type.getSchema(Test));
|
|
131
125
|
const view = ViewModel.make({
|
|
132
126
|
query: Query.select(Filter.type(schema)),
|
|
133
127
|
jsonSchema: schema.jsonSchema,
|
|
@@ -137,7 +131,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
137
131
|
registry,
|
|
138
132
|
view,
|
|
139
133
|
baseSchema: schema.jsonSchema,
|
|
140
|
-
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
134
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(Type.getSchema(schema))),
|
|
141
135
|
});
|
|
142
136
|
projection.normalizeView();
|
|
143
137
|
return new TableModel({
|
package/src/model/table-model.ts
CHANGED
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
|
|
7
7
|
import { Resource } from '@dxos/context';
|
|
8
|
-
import { type Database, Format, Obj, Order, Query, type QueryAST, Ref } from '@dxos/echo';
|
|
9
|
-
import { type View } from '@dxos/echo';
|
|
8
|
+
import { type Database, Format, Obj, Order, Query, type QueryAST, Ref, Type, type View } from '@dxos/echo';
|
|
10
9
|
import { type JsonProp, type JsonSchemaType, type Mutable, toEffectSchema } from '@dxos/echo/internal';
|
|
11
10
|
import { getSnapshot } from '@dxos/echo/internal';
|
|
12
11
|
import { getValue, setValue } from '@dxos/effect';
|
|
13
12
|
import { invariant } from '@dxos/invariant';
|
|
14
|
-
import {
|
|
13
|
+
import { EntityId } from '@dxos/keys';
|
|
15
14
|
import { type Label } from '@dxos/react-ui';
|
|
16
15
|
import { formatForEditing, parseValue } from '@dxos/react-ui-form';
|
|
17
16
|
import {
|
|
@@ -38,7 +37,7 @@ export type FieldSortType = {
|
|
|
38
37
|
import { type SelectionMode, SelectionModel } from './selection-model';
|
|
39
38
|
|
|
40
39
|
/**
|
|
41
|
-
* Callback type for wrapping mutations in Obj.
|
|
40
|
+
* Callback type for wrapping mutations in Obj.update().
|
|
42
41
|
* Contains separate callbacks for table object and row mutations.
|
|
43
42
|
*/
|
|
44
43
|
export type TableChangeCallback<T extends TableRow> = {
|
|
@@ -53,10 +52,10 @@ export type TableChangeCallback<T extends TableRow> = {
|
|
|
53
52
|
* Use this when the table and rows are stored in the ECHO database.
|
|
54
53
|
*/
|
|
55
54
|
export const createEchoChangeCallback = <T extends TableRow>(table: Table.Table): TableChangeCallback<T> => ({
|
|
56
|
-
table: (mutate) => Obj.
|
|
55
|
+
table: (mutate) => Obj.update(table, (table) => mutate(table as unknown as Table.Table)),
|
|
57
56
|
row: (row, mutate) => {
|
|
58
57
|
if (Obj.isObject(row)) {
|
|
59
|
-
Obj.
|
|
58
|
+
Obj.update(row, (row) => mutate(row as T));
|
|
60
59
|
} else {
|
|
61
60
|
mutate(row);
|
|
62
61
|
}
|
|
@@ -112,7 +111,7 @@ export type TableModelProps<T extends TableRow = TableRow> = {
|
|
|
112
111
|
projection: ProjectionModel;
|
|
113
112
|
db?: Database.Database;
|
|
114
113
|
/**
|
|
115
|
-
* Callbacks to wrap mutations in Obj.
|
|
114
|
+
* Callbacks to wrap mutations in Obj.update().
|
|
116
115
|
* Use createEchoChangeCallback() for ECHO-backed objects or createDirectChangeCallback() for plain objects.
|
|
117
116
|
*/
|
|
118
117
|
change?: TableChangeCallback<T>;
|
|
@@ -300,7 +299,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
300
299
|
}
|
|
301
300
|
|
|
302
301
|
public get id(): string {
|
|
303
|
-
return Obj.
|
|
302
|
+
return Obj.getURI(this._object);
|
|
304
303
|
}
|
|
305
304
|
|
|
306
305
|
public get view(): View.View {
|
|
@@ -524,7 +523,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
524
523
|
}
|
|
525
524
|
|
|
526
525
|
// NOTE(ZaymonFC): This is initialized with id because it's required in all schemata?
|
|
527
|
-
const draftData = { id:
|
|
526
|
+
const draftData = { id: EntityId.random() } as any as T;
|
|
528
527
|
const validationErrors = this.validateDraftRowData(draftData);
|
|
529
528
|
|
|
530
529
|
const draftRow: DraftRow<T> = {
|
|
@@ -695,8 +694,9 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
695
694
|
const snapshot = { ...getSnapshot(currentRow) };
|
|
696
695
|
setValue(snapshot, field.path, transformedValue);
|
|
697
696
|
|
|
698
|
-
const
|
|
699
|
-
invariant(
|
|
697
|
+
const type = Obj.getType(currentRow as unknown as Obj.Unknown);
|
|
698
|
+
invariant(type);
|
|
699
|
+
const schema = Type.getSchema(type);
|
|
700
700
|
|
|
701
701
|
const validationResult = validateSchema(schema, snapshot);
|
|
702
702
|
if (validationResult && validationResult.length > 0) {
|
|
@@ -894,14 +894,14 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
894
894
|
if (field) {
|
|
895
895
|
// Persist sort to view.query.ast
|
|
896
896
|
const newQuery = baseQuery.orderBy(Order.property<any>(field.path as string, inMemorySort.direction));
|
|
897
|
-
Obj.
|
|
898
|
-
|
|
897
|
+
Obj.update(view, (view) => {
|
|
898
|
+
view.query.ast = newQuery.ast as Mutable<typeof newQuery.ast>;
|
|
899
899
|
});
|
|
900
900
|
}
|
|
901
901
|
} else {
|
|
902
902
|
// Clear sort from view.query.ast
|
|
903
|
-
Obj.
|
|
904
|
-
|
|
903
|
+
Obj.update(view, (view) => {
|
|
904
|
+
view.query.ast = baseQuery.ast as Mutable<typeof baseQuery.ast>;
|
|
905
905
|
});
|
|
906
906
|
}
|
|
907
907
|
|
|
@@ -6,12 +6,11 @@ import { Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { DXN, Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
11
|
import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
|
|
12
12
|
|
|
13
13
|
import { Table } from '../types';
|
|
14
|
-
|
|
15
14
|
import { TableModel, type TableModelProps } from './table-model';
|
|
16
15
|
import { TablePresentation } from './table-presentation';
|
|
17
16
|
|
|
@@ -90,15 +89,10 @@ describe('TablePresentation', () => {
|
|
|
90
89
|
const Test = Schema.Struct({
|
|
91
90
|
title: Schema.String,
|
|
92
91
|
count: Schema.Number,
|
|
93
|
-
}).pipe(
|
|
94
|
-
Type.object({
|
|
95
|
-
typename: 'com.example.type.test',
|
|
96
|
-
version: '0.1.0',
|
|
97
|
-
}),
|
|
98
|
-
);
|
|
92
|
+
}).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
|
|
99
93
|
|
|
100
94
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
101
|
-
const schema = createEchoSchema(Test);
|
|
95
|
+
const schema = createEchoSchema(Type.getSchema(Test));
|
|
102
96
|
const view = ViewModel.make({
|
|
103
97
|
query: Query.select(Filter.type(schema)),
|
|
104
98
|
jsonSchema: schema.jsonSchema,
|
|
@@ -108,7 +102,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
108
102
|
registry,
|
|
109
103
|
view,
|
|
110
104
|
baseSchema: schema.jsonSchema,
|
|
111
|
-
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
105
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(Type.getSchema(schema))),
|
|
112
106
|
});
|
|
113
107
|
projection.normalizeView();
|
|
114
108
|
return new TableModel({ registry, object, projection, ...props });
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
import * as Predicate from 'effect/Predicate';
|
|
7
7
|
|
|
8
|
-
import { Obj } from '@dxos/echo';
|
|
9
|
-
import { type View } from '@dxos/echo';
|
|
8
|
+
import { Obj, type View } from '@dxos/echo';
|
|
10
9
|
import { Format, TypeEnum, getValue } from '@dxos/echo/internal';
|
|
11
10
|
import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
|
|
12
11
|
import {
|
|
@@ -20,7 +19,6 @@ import { VIEW_FIELD_LIMIT } from '@dxos/schema';
|
|
|
20
19
|
import { mx } from '@dxos/ui-theme';
|
|
21
20
|
|
|
22
21
|
import { tableButtons, tableControls } from '../util';
|
|
23
|
-
|
|
24
22
|
import { type SelectionMode } from './selection-model';
|
|
25
23
|
import { type TableModel, type TableRow } from './table-model';
|
|
26
24
|
|
|
@@ -210,8 +208,8 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
210
208
|
if (props.format === Format.TypeFormat.Ref && props.referenceSchema) {
|
|
211
209
|
const targetObj = getValue(obj, field.path)?.target;
|
|
212
210
|
if (targetObj) {
|
|
213
|
-
const
|
|
214
|
-
cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor
|
|
211
|
+
const uri = Obj.getURI(targetObj);
|
|
212
|
+
cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor uri=${uri} class="dx-button w-6 aspect-square min-h-0" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-anchor></div>`;
|
|
215
213
|
}
|
|
216
214
|
}
|
|
217
215
|
|
|
@@ -474,8 +472,8 @@ export const cellClassesForRowSelection = (selected: boolean, selectionMode: Sel
|
|
|
474
472
|
|
|
475
473
|
switch (selectionMode) {
|
|
476
474
|
case 'single':
|
|
477
|
-
return ['dx-grid__cell--no-focus-unfurl
|
|
475
|
+
return ['dx-grid__cell--no-focus-unfurl bg-current-surface! hover:bg-hover-surface cursor-pointer!'];
|
|
478
476
|
case 'multiple':
|
|
479
|
-
return ['
|
|
477
|
+
return ['bg-grid-cell-selected!'];
|
|
480
478
|
}
|
|
481
479
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { expect, test } from '@playwright/test';
|
|
6
6
|
|
|
7
7
|
import { type DxGrid } from '@dxos/lit-grid';
|
|
8
|
-
import {
|
|
8
|
+
import { random } from '@dxos/random';
|
|
9
9
|
import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
|
|
10
10
|
|
|
11
11
|
import { TableManager } from './TableManager';
|
|
@@ -13,7 +13,7 @@ import { TableManager } from './TableManager';
|
|
|
13
13
|
const storyUrl = storybookUrl('ui-react-ui-table-table--default', 9004);
|
|
14
14
|
const relationsStoryUrl = storybookUrl('ui-react-ui-table-relations--default', 9004);
|
|
15
15
|
|
|
16
|
-
// NOTE(ZaymonFC): This test suite relies on the
|
|
16
|
+
// NOTE(ZaymonFC): This test suite relies on the random seed being set to 0 in the story.
|
|
17
17
|
test.describe('Table', () => {
|
|
18
18
|
test('Loads', async ({ browser, browserName }) => {
|
|
19
19
|
test.skip(browserName === 'webkit');
|
|
@@ -310,7 +310,7 @@ test.describe('Table', () => {
|
|
|
310
310
|
dxGridElement.scrollToColumn(6);
|
|
311
311
|
});
|
|
312
312
|
|
|
313
|
-
const nonRefContent =
|
|
313
|
+
const nonRefContent = random.lorem.words(3);
|
|
314
314
|
const nonRefCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="6"]');
|
|
315
315
|
await nonRefCell.click();
|
|
316
316
|
await page.keyboard.press('Enter');
|
|
@@ -5,12 +5,11 @@
|
|
|
5
5
|
import { RegistryContext } from '@effect-atom/atom-react';
|
|
6
6
|
import { type RefObject, useCallback, useContext, useMemo, useRef } from 'react';
|
|
7
7
|
|
|
8
|
-
import { type Database,
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { Filter, useQuery, useSchema } from '@dxos/react-client/echo';
|
|
8
|
+
import { type Database, Filter, Type } from '@dxos/echo';
|
|
9
|
+
import { random } from '@dxos/random';
|
|
10
|
+
import { useQuery, useType } from '@dxos/react-client/echo';
|
|
12
11
|
import { useClientStory } from '@dxos/react-client/testing';
|
|
13
|
-
import { useGlobalFilteredObjects } from '@dxos/react-ui-
|
|
12
|
+
import { useGlobalFilteredObjects } from '@dxos/react-ui-search';
|
|
14
13
|
import { type ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
|
|
15
14
|
|
|
16
15
|
import { type TableController } from '../components';
|
|
@@ -18,7 +17,7 @@ import { useAddRow, useProjectionModel, useTableModel } from '../hooks';
|
|
|
18
17
|
import { type TableModel, TablePresentation } from '../model';
|
|
19
18
|
import { Table } from '../types';
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
random.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
|
|
22
21
|
|
|
23
22
|
export type TestTableModel<T extends Type.AnyObj = Type.AnyObj> = {
|
|
24
23
|
schema: T | undefined;
|
|
@@ -46,14 +45,14 @@ export const useTestTableModel = <T extends Type.AnyObj = Type.AnyObj>(): TestTa
|
|
|
46
45
|
const tables = useQuery(space?.db, Filter.type(Table.Table));
|
|
47
46
|
const table = tables.at(0);
|
|
48
47
|
const typename = table?.view.target?.query ? getTypenameFromQuery(table.view.target.query.ast) : undefined;
|
|
49
|
-
const schema =
|
|
48
|
+
const schema = useType<T>(space?.db, typename);
|
|
50
49
|
const projection = useProjectionModel(schema, table, registry);
|
|
51
50
|
|
|
52
51
|
const features = useMemo(
|
|
53
52
|
() => ({
|
|
54
53
|
selection: { enabled: true, mode: 'multiple' as const },
|
|
55
54
|
dataEditable: true,
|
|
56
|
-
schemaEditable: schema &&
|
|
55
|
+
schemaEditable: schema != null && Type.getDatabase(schema) != null,
|
|
57
56
|
}),
|
|
58
57
|
[schema],
|
|
59
58
|
);
|
package/src/translations.ts
CHANGED
|
@@ -10,27 +10,25 @@ export const translations = [
|
|
|
10
10
|
{
|
|
11
11
|
'en-US': {
|
|
12
12
|
[translationKey]: {
|
|
13
|
-
'object
|
|
14
|
-
'create
|
|
15
|
-
'table
|
|
16
|
-
'settings
|
|
17
|
-
'table
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'column
|
|
24
|
-
'column
|
|
25
|
-
'column
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'create new object label': 'Create new object “{{text}}”',
|
|
33
|
-
'save view label': 'Save changes to view',
|
|
13
|
+
'object.placeholder': 'New table',
|
|
14
|
+
'create-object.label': 'Create table',
|
|
15
|
+
'table-name.placeholder': 'Table name',
|
|
16
|
+
'settings.title': 'Table settings',
|
|
17
|
+
'table-schema.label': 'Type',
|
|
18
|
+
'continue.label': 'Continue',
|
|
19
|
+
'create-stack-section.label': 'Create table',
|
|
20
|
+
'add-row.label': 'Add row',
|
|
21
|
+
'column-action-sort-descending.menu': 'Sort Descending',
|
|
22
|
+
'column-action-sort-ascending.menu': 'Sort Ascending',
|
|
23
|
+
'column-action-clear-sorting.menu': 'Clear Sorting',
|
|
24
|
+
'column-action-settings.menu': 'Column Settings',
|
|
25
|
+
'column-action-delete.menu': 'Delete Column',
|
|
26
|
+
'delete-row.label': 'Delete row',
|
|
27
|
+
'bulk-delete-row.label': 'Delete selected rows',
|
|
28
|
+
'column-deleted.label': 'Column deleted',
|
|
29
|
+
'new-column-button.label': 'Create column',
|
|
30
|
+
'create-new-object.label': 'Create new object “{{text}}”',
|
|
31
|
+
'save-view.label': 'Save changes to view',
|
|
34
32
|
},
|
|
35
33
|
},
|
|
36
34
|
},
|
package/src/types/Table.ts
CHANGED
|
@@ -6,12 +6,15 @@ import * as Match from 'effect/Match';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import * as SchemaAST from 'effect/SchemaAST';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// QueryAST is referenced indirectly through `Type.InstanceType<typeof TableSchema>`
|
|
10
|
+
// (Ref.Ref(View.View) → View.View → QueryAST.Query) in the emitted .d.ts; the
|
|
11
|
+
// namespace import keeps the inferred types portable.
|
|
12
|
+
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
13
|
+
import { DXN, Annotation, JsonSchema, Obj, QueryAST, Ref, Type, View } from '@dxos/echo';
|
|
11
14
|
import { FormInputAnnotation, type JsonPath, type JsonSchemaType, LabelAnnotation } from '@dxos/echo/internal';
|
|
12
15
|
import { ViewAnnotation } from '@dxos/schema';
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
const TableSchema = Schema.Struct({
|
|
15
18
|
name: Schema.String.pipe(Schema.optional),
|
|
16
19
|
|
|
17
20
|
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
|
|
@@ -22,19 +25,15 @@ export const Table = Schema.Struct({
|
|
|
22
25
|
value: Schema.Number,
|
|
23
26
|
}).pipe(Schema.mutable, FormInputAnnotation.set(false)),
|
|
24
27
|
}).pipe(
|
|
25
|
-
Type.object({
|
|
26
|
-
typename: 'org.dxos.type.table',
|
|
27
|
-
version: '0.1.0',
|
|
28
|
-
}),
|
|
29
28
|
LabelAnnotation.set(['name']),
|
|
30
|
-
ViewAnnotation.set(
|
|
31
|
-
Annotation.IconAnnotation.set({
|
|
32
|
-
|
|
33
|
-
hue: 'green',
|
|
34
|
-
}),
|
|
29
|
+
ViewAnnotation.set(['view']),
|
|
30
|
+
Annotation.IconAnnotation.set({ icon: 'ph--table--regular', hue: 'green' }),
|
|
31
|
+
Type.makeObject(DXN.make('org.dxos.type.table', '0.1.0')),
|
|
35
32
|
);
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
// TODO(wittjosiah): Try to clean up this type inference.
|
|
35
|
+
export interface Table extends Type.InstanceType<typeof TableSchema> {}
|
|
36
|
+
export const Table = TableSchema;
|
|
38
37
|
|
|
39
38
|
type MakeProps = {
|
|
40
39
|
name?: string;
|
|
@@ -11,13 +11,14 @@ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '.
|
|
|
11
11
|
|
|
12
12
|
describe('makeDynamicTable', () => {
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* Confirms makeDynamicTable + setProperties (title) works with plain objects.
|
|
14
|
+
* Builds the Type entity from a JSON schema, then makes the table.
|
|
15
|
+
* Confirms makeDynamicTable + setProperties (title) works for the jsonSchema path.
|
|
17
16
|
*/
|
|
18
|
-
test('makeDynamicTable
|
|
17
|
+
test('makeDynamicTable from a jsonSchema with properties with title does not throw', () => {
|
|
19
18
|
const registry = Registry.make();
|
|
20
19
|
const jsonSchema = {
|
|
20
|
+
typename: 'com.example.type.dynamicTablePlain',
|
|
21
|
+
version: '0.1.0',
|
|
21
22
|
type: 'object' as const,
|
|
22
23
|
properties: {
|
|
23
24
|
id: { type: 'string' as const },
|
|
@@ -31,11 +32,8 @@ describe('makeDynamicTable', () => {
|
|
|
31
32
|
];
|
|
32
33
|
|
|
33
34
|
expect(() => {
|
|
34
|
-
const {
|
|
35
|
-
|
|
36
|
-
jsonSchema,
|
|
37
|
-
properties,
|
|
38
|
-
});
|
|
35
|
+
const { type } = getBaseSchema({ jsonSchema });
|
|
36
|
+
const { projection, object } = makeDynamicTable({ registry, type, properties });
|
|
39
37
|
expect(projection).toBeDefined();
|
|
40
38
|
expect(object).toBeDefined();
|
|
41
39
|
expect(projection.getFields().length).toBeGreaterThan(0);
|
|
@@ -43,25 +41,20 @@ describe('makeDynamicTable', () => {
|
|
|
43
41
|
});
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* cloned schema. This test ensures that flow does not throw.
|
|
44
|
+
* Builds the Type entity from property definitions, then makes the table.
|
|
45
|
+
* Confirms makeDynamicTable + setProperties (title) works for the property-definitions path.
|
|
49
46
|
*/
|
|
50
|
-
test('makeDynamicTable
|
|
47
|
+
test('makeDynamicTable from getBaseSchema(typename, properties) with properties with title does not throw', () => {
|
|
51
48
|
const registry = Registry.make();
|
|
52
|
-
const typename = 'com.example.type.
|
|
49
|
+
const typename = 'com.example.type.dynamicTableTest';
|
|
53
50
|
const properties: TablePropertyDefinition[] = [
|
|
54
51
|
{ name: 'id', format: Format.TypeFormat.String },
|
|
55
52
|
{ name: 'name', format: Format.TypeFormat.String, title: 'Name' },
|
|
56
53
|
];
|
|
57
|
-
const { jsonSchema } = getBaseSchema({ typename, properties });
|
|
58
54
|
|
|
59
55
|
expect(() => {
|
|
60
|
-
const {
|
|
61
|
-
|
|
62
|
-
jsonSchema,
|
|
63
|
-
properties,
|
|
64
|
-
});
|
|
56
|
+
const { type } = getBaseSchema({ typename, properties });
|
|
57
|
+
const { projection, object } = makeDynamicTable({ registry, type, properties });
|
|
65
58
|
expect(projection).toBeDefined();
|
|
66
59
|
expect(object).toBeDefined();
|
|
67
60
|
expect(projection.getFields().length).toBeGreaterThan(0);
|