@dxos/react-ui-table 0.8.4-main.3eb6e50203 → 0.8.4-main.3fbcb4aa9b
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/{chunk-OZBLY7XM.mjs → chunk-FBURZBPH.mjs} +17 -23
- package/dist/lib/browser/chunk-FBURZBPH.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GTGYBRJA.mjs → chunk-YGC7LZJN.mjs} +31 -84
- package/dist/lib/browser/chunk-YGC7LZJN.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +195 -235
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +6 -5
- 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-WNZSKIRF.mjs → chunk-DKKMSVKP.mjs} +17 -23
- package/dist/lib/node-esm/chunk-DKKMSVKP.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-DPNSZHU5.mjs → chunk-GKIWDEZ7.mjs} +31 -84
- package/dist/lib/node-esm/chunk-GKIWDEZ7.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/index.mjs +195 -235
- 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 +6 -5
- 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.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +2 -2
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +20 -22
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +82 -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 +84 -84
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +17 -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 +3 -3
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +2 -2
- 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 +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +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 +5 -4
- 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 +2 -2
- 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 +1 -6
- package/dist/types/src/types/Table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +2 -2
- 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 +50 -59
- package/src/components/Table/ColumnActionsMenu.tsx +7 -6
- package/src/components/Table/ColumnSettings.tsx +3 -4
- package/src/components/Table/DynamicTable.stories.tsx +15 -15
- package/src/components/Table/DynamicTable.tsx +10 -18
- package/src/components/Table/Relations.stories.tsx +77 -33
- package/src/components/Table/RowActionsMenu.tsx +3 -2
- package/src/components/Table/Table.stories.tsx +58 -51
- package/src/components/Table/Table.tsx +41 -435
- package/src/components/Table/TableContent.tsx +421 -0
- package/src/components/{TableToolbar → Table}/TableToolbar.tsx +36 -43
- package/src/components/TableCellEditor/CellValidationMessage.tsx +4 -5
- package/src/components/TableCellEditor/FormCellEditor.tsx +14 -7
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +12 -11
- package/src/components/TableCellEditor/TableCellEditor.tsx +12 -10
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +10 -10
- package/src/hooks/useAddRow.ts +1 -1
- package/src/hooks/useProjectionModel.ts +3 -3
- package/src/index.ts +0 -4
- package/src/model/table-model.test.ts +5 -6
- package/src/model/table-model.ts +11 -10
- package/src/model/table-presentation.test.ts +5 -6
- package/src/model/table-presentation.ts +12 -12
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +3 -3
- package/src/testing/useTestTableModel.ts +5 -5
- package/src/translations.ts +19 -21
- package/src/types/Table.ts +12 -23
- package/src/util/dynamic-table.test.ts +4 -4
- package/src/util/dynamic-table.ts +11 -10
- package/src/util/query-ast.ts +3 -0
- package/src/util/table-buttons.ts +1 -1
- package/src/util/table-controls.ts +2 -2
- package/dist/lib/browser/chunk-GTGYBRJA.mjs.map +0 -7
- package/dist/lib/browser/chunk-OZBLY7XM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DPNSZHU5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WNZSKIRF.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: '!plb-[--dx-grid-cell-editor-padding-block]',
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
31
|
/**
|
|
39
32
|
* Option to create new object/value.
|
|
40
33
|
*/
|
|
@@ -42,7 +35,7 @@ export type QueryResult = Pick<Completion, 'label'> & {
|
|
|
42
35
|
data: any;
|
|
43
36
|
};
|
|
44
37
|
|
|
45
|
-
export type TableCellEditorProps<T extends Type.
|
|
38
|
+
export type TableCellEditorProps<T extends Type.AnyEntity = Type.AnyEntity> = {
|
|
46
39
|
schema?: T;
|
|
47
40
|
model?: TableModel;
|
|
48
41
|
modals?: ModalController;
|
|
@@ -51,7 +44,7 @@ export type TableCellEditorProps<T extends Type.Entity.Any = Type.Entity.Any> =
|
|
|
51
44
|
onSave?: () => void;
|
|
52
45
|
};
|
|
53
46
|
|
|
54
|
-
export const TableValueEditor = <T extends Type.
|
|
47
|
+
export const TableValueEditor = <T extends Type.AnyEntity = Type.AnyEntity>({
|
|
55
48
|
__gridScope,
|
|
56
49
|
schema,
|
|
57
50
|
model,
|
|
@@ -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
|
@@ -9,7 +9,7 @@ import { useEffect } from 'react';
|
|
|
9
9
|
import { 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({
|
|
@@ -19,7 +19,7 @@ export const TestSchema = Schema.Struct({
|
|
|
19
19
|
netWorth: Schema.optional(Schema.Number),
|
|
20
20
|
}).pipe(
|
|
21
21
|
Type.object({
|
|
22
|
-
typename: 'example.
|
|
22
|
+
typename: 'com.example.type.test',
|
|
23
23
|
version: '0.1.0',
|
|
24
24
|
}),
|
|
25
25
|
);
|
|
@@ -37,10 +37,10 @@ export type TestItem = {
|
|
|
37
37
|
export const createItemsAtom = (n: number) => {
|
|
38
38
|
return Atom.make<{ data: TestItem[] }>({
|
|
39
39
|
data: Array.from({ length: n }, () => ({
|
|
40
|
-
name:
|
|
41
|
-
age:
|
|
42
|
-
active:
|
|
43
|
-
netWorth:
|
|
40
|
+
name: random.person.fullName(),
|
|
41
|
+
age: random.number.int({ min: 20, max: 70 }),
|
|
42
|
+
active: random.datatype.boolean(),
|
|
43
|
+
netWorth: random.number.int(),
|
|
44
44
|
})),
|
|
45
45
|
}).pipe(Atom.keepAlive);
|
|
46
46
|
};
|
|
@@ -50,10 +50,10 @@ export const createItemsAtom = (n: number) => {
|
|
|
50
50
|
*/
|
|
51
51
|
export const createItems = (n: number): TestItem[] => {
|
|
52
52
|
return Array.from({ length: n }, () => ({
|
|
53
|
-
name:
|
|
54
|
-
age:
|
|
55
|
-
active:
|
|
56
|
-
netWorth:
|
|
53
|
+
name: random.person.fullName(),
|
|
54
|
+
age: random.number.int({ min: 20, max: 70 }),
|
|
55
|
+
active: random.datatype.boolean(),
|
|
56
|
+
netWorth: random.number.int(),
|
|
57
57
|
}));
|
|
58
58
|
};
|
|
59
59
|
|
package/src/hooks/useAddRow.ts
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
import { type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
import { useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { Type } from '@dxos/echo';
|
|
8
|
+
import { JsonSchema, Type } from '@dxos/echo';
|
|
9
9
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
10
10
|
import { ProjectionModel, createEchoChangeCallback } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { type Table } from '../types';
|
|
13
13
|
|
|
14
|
-
export const useProjectionModel = <S extends Type.
|
|
14
|
+
export const useProjectionModel = <S extends Type.AnyEntity>(
|
|
15
15
|
schema: S | undefined,
|
|
16
16
|
table: Table.Table | undefined,
|
|
17
17
|
registry: Registry.Registry,
|
|
@@ -23,7 +23,7 @@ export const useProjectionModel = <S extends Type.Entity.Any>(
|
|
|
23
23
|
const view = await table.view.load();
|
|
24
24
|
// For mutable schemas (EchoSchema), use the live jsonSchema reference for reactivity.
|
|
25
25
|
// For immutable schemas, create a snapshot.
|
|
26
|
-
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema :
|
|
26
|
+
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : JsonSchema.toJsonSchema(schema);
|
|
27
27
|
|
|
28
28
|
// Always use createEchoChangeCallback since the view is ECHO-backed.
|
|
29
29
|
// Pass schema only when mutable to allow schema mutations.
|
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, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
|
-
import { ProjectionModel,
|
|
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,
|
|
@@ -121,14 +120,14 @@ const Test = Schema.Struct({
|
|
|
121
120
|
completed: Schema.Boolean,
|
|
122
121
|
}).pipe(
|
|
123
122
|
Type.object({
|
|
124
|
-
typename: 'example.
|
|
123
|
+
typename: 'com.example.type.test',
|
|
125
124
|
version: '0.1.0',
|
|
126
125
|
}),
|
|
127
126
|
);
|
|
128
127
|
|
|
129
128
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
130
129
|
const schema = createEchoSchema(Test);
|
|
131
|
-
const view =
|
|
130
|
+
const view = ViewModel.make({
|
|
132
131
|
query: Query.select(Filter.type(schema)),
|
|
133
132
|
jsonSchema: schema.jsonSchema,
|
|
134
133
|
});
|
|
@@ -137,7 +136,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
137
136
|
registry,
|
|
138
137
|
view,
|
|
139
138
|
baseSchema: schema.jsonSchema,
|
|
140
|
-
change: createDirectChangeCallback(view.projection,
|
|
139
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
141
140
|
});
|
|
142
141
|
projection.normalizeView();
|
|
143
142
|
return new TableModel({
|
package/src/model/table-model.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
|
|
7
7
|
import { Resource } from '@dxos/context';
|
|
8
8
|
import { type Database, Format, Obj, Order, Query, type QueryAST, Ref } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
9
10
|
import { type JsonProp, type JsonSchemaType, type Mutable, toEffectSchema } from '@dxos/echo/internal';
|
|
10
11
|
import { getSnapshot } from '@dxos/echo/internal';
|
|
11
12
|
import { getValue, setValue } from '@dxos/effect';
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
type DxGridPlaneRange,
|
|
20
21
|
type DxGridPosition,
|
|
21
22
|
} from '@dxos/react-ui-grid';
|
|
22
|
-
import { type ProjectionModel, type PropertyType, type ValidationError,
|
|
23
|
+
import { type ProjectionModel, type PropertyType, type ValidationError, validateSchema } from '@dxos/schema';
|
|
23
24
|
|
|
24
25
|
import { type Table } from '../types';
|
|
25
26
|
import { extractOrder } from '../util';
|
|
@@ -37,7 +38,7 @@ export type FieldSortType = {
|
|
|
37
38
|
import { type SelectionMode, SelectionModel } from './selection-model';
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
|
-
* Callback type for wrapping mutations in Obj.
|
|
41
|
+
* Callback type for wrapping mutations in Obj.update().
|
|
41
42
|
* Contains separate callbacks for table object and row mutations.
|
|
42
43
|
*/
|
|
43
44
|
export type TableChangeCallback<T extends TableRow> = {
|
|
@@ -52,10 +53,10 @@ export type TableChangeCallback<T extends TableRow> = {
|
|
|
52
53
|
* Use this when the table and rows are stored in the ECHO database.
|
|
53
54
|
*/
|
|
54
55
|
export const createEchoChangeCallback = <T extends TableRow>(table: Table.Table): TableChangeCallback<T> => ({
|
|
55
|
-
table: (mutate) => Obj.
|
|
56
|
+
table: (mutate) => Obj.update(table, (table) => mutate(table as unknown as Table.Table)),
|
|
56
57
|
row: (row, mutate) => {
|
|
57
58
|
if (Obj.isObject(row)) {
|
|
58
|
-
Obj.
|
|
59
|
+
Obj.update(row, (row) => mutate(row as T));
|
|
59
60
|
} else {
|
|
60
61
|
mutate(row);
|
|
61
62
|
}
|
|
@@ -111,7 +112,7 @@ export type TableModelProps<T extends TableRow = TableRow> = {
|
|
|
111
112
|
projection: ProjectionModel;
|
|
112
113
|
db?: Database.Database;
|
|
113
114
|
/**
|
|
114
|
-
* Callbacks to wrap mutations in Obj.
|
|
115
|
+
* Callbacks to wrap mutations in Obj.update().
|
|
115
116
|
* Use createEchoChangeCallback() for ECHO-backed objects or createDirectChangeCallback() for plain objects.
|
|
116
117
|
*/
|
|
117
118
|
change?: TableChangeCallback<T>;
|
|
@@ -694,7 +695,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
694
695
|
const snapshot = { ...getSnapshot(currentRow) };
|
|
695
696
|
setValue(snapshot, field.path, transformedValue);
|
|
696
697
|
|
|
697
|
-
const schema = Obj.getSchema(currentRow);
|
|
698
|
+
const schema = Obj.getSchema(currentRow as unknown as Obj.Unknown);
|
|
698
699
|
invariant(schema);
|
|
699
700
|
|
|
700
701
|
const validationResult = validateSchema(schema, snapshot);
|
|
@@ -893,14 +894,14 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
893
894
|
if (field) {
|
|
894
895
|
// Persist sort to view.query.ast
|
|
895
896
|
const newQuery = baseQuery.orderBy(Order.property<any>(field.path as string, inMemorySort.direction));
|
|
896
|
-
Obj.
|
|
897
|
-
|
|
897
|
+
Obj.update(view, (view) => {
|
|
898
|
+
view.query.ast = newQuery.ast as Mutable<typeof newQuery.ast>;
|
|
898
899
|
});
|
|
899
900
|
}
|
|
900
901
|
} else {
|
|
901
902
|
// Clear sort from view.query.ast
|
|
902
|
-
Obj.
|
|
903
|
-
|
|
903
|
+
Obj.update(view, (view) => {
|
|
904
|
+
view.query.ast = baseQuery.ast as Mutable<typeof baseQuery.ast>;
|
|
904
905
|
});
|
|
905
906
|
}
|
|
906
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, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
|
-
import { ProjectionModel,
|
|
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
|
|
|
@@ -92,14 +91,14 @@ const Test = Schema.Struct({
|
|
|
92
91
|
count: Schema.Number,
|
|
93
92
|
}).pipe(
|
|
94
93
|
Type.object({
|
|
95
|
-
typename: 'example.
|
|
94
|
+
typename: 'com.example.type.test',
|
|
96
95
|
version: '0.1.0',
|
|
97
96
|
}),
|
|
98
97
|
);
|
|
99
98
|
|
|
100
99
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
101
100
|
const schema = createEchoSchema(Test);
|
|
102
|
-
const view =
|
|
101
|
+
const view = ViewModel.make({
|
|
103
102
|
query: Query.select(Filter.type(schema)),
|
|
104
103
|
jsonSchema: schema.jsonSchema,
|
|
105
104
|
});
|
|
@@ -108,7 +107,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
108
107
|
registry,
|
|
109
108
|
view,
|
|
110
109
|
baseSchema: schema.jsonSchema,
|
|
111
|
-
change: createDirectChangeCallback(view.projection,
|
|
110
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
112
111
|
});
|
|
113
112
|
projection.normalizeView();
|
|
114
113
|
return new TableModel({ registry, object, projection, ...props });
|
|
@@ -6,6 +6,7 @@ import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Predicate from 'effect/Predicate';
|
|
7
7
|
|
|
8
8
|
import { Obj } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
9
10
|
import { Format, TypeEnum, getValue } from '@dxos/echo/internal';
|
|
10
11
|
import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
|
|
11
12
|
import {
|
|
@@ -15,11 +16,10 @@ import {
|
|
|
15
16
|
type DxGridPlaneRange,
|
|
16
17
|
toPlaneCellIndex,
|
|
17
18
|
} from '@dxos/react-ui-grid';
|
|
18
|
-
import {
|
|
19
|
+
import { VIEW_FIELD_LIMIT } from '@dxos/schema';
|
|
19
20
|
import { mx } from '@dxos/ui-theme';
|
|
20
21
|
|
|
21
22
|
import { tableButtons, tableControls } from '../util';
|
|
22
|
-
|
|
23
23
|
import { type SelectionMode } from './selection-model';
|
|
24
24
|
import { type TableModel, type TableRow } from './table-model';
|
|
25
25
|
|
|
@@ -107,7 +107,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
107
107
|
private createDataCell(
|
|
108
108
|
cells: DxGridPlaneCells,
|
|
109
109
|
obj: T,
|
|
110
|
-
field: FieldType,
|
|
110
|
+
field: View.FieldType,
|
|
111
111
|
colIndex: number,
|
|
112
112
|
displayIndex: number,
|
|
113
113
|
): void {
|
|
@@ -210,7 +210,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
210
210
|
const targetObj = getValue(obj, field.path)?.target;
|
|
211
211
|
if (targetObj) {
|
|
212
212
|
const dxn = Obj.getDXN(targetObj)?.toString();
|
|
213
|
-
cell.accessoryHtml = `<div role="none" class="absolute
|
|
213
|
+
cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor dxn=${dxn} 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>`;
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
@@ -335,11 +335,11 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
335
335
|
value: '',
|
|
336
336
|
resizeHandle: 'col',
|
|
337
337
|
accessoryHtml: `
|
|
338
|
-
<span class="grow min-
|
|
338
|
+
<span class="grow min-w-0 truncate">${props.title ?? field.path}</span>
|
|
339
339
|
${direction !== undefined ? tableButtons.sort.render({ fieldId: field.id, direction }) : ''}
|
|
340
340
|
${tableButtons.columnSettings.render({ fieldId: field.id })}
|
|
341
341
|
`,
|
|
342
|
-
className: '!bg-
|
|
342
|
+
className: '!bg-toolbar-surface text-description! [&>div]:flex [&>div]:items-stretch',
|
|
343
343
|
};
|
|
344
344
|
}
|
|
345
345
|
|
|
@@ -382,7 +382,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
382
382
|
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === 'single') {
|
|
383
383
|
return {
|
|
384
384
|
[toPlaneCellIndex({ col: 0, row: 0 })]: {
|
|
385
|
-
className: '!bg-
|
|
385
|
+
className: '!bg-toolbar-surface',
|
|
386
386
|
readonly: true,
|
|
387
387
|
value: '',
|
|
388
388
|
},
|
|
@@ -396,7 +396,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
396
396
|
header: true,
|
|
397
397
|
checked: this.model.selection.allRowsSelected,
|
|
398
398
|
}),
|
|
399
|
-
className: '!bg-
|
|
399
|
+
className: '!bg-toolbar-surface',
|
|
400
400
|
readonly: true,
|
|
401
401
|
value: '',
|
|
402
402
|
},
|
|
@@ -411,7 +411,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
411
411
|
disabled: (this.model.projection?.getFields()?.length ?? 0) >= VIEW_FIELD_LIMIT,
|
|
412
412
|
})
|
|
413
413
|
: undefined,
|
|
414
|
-
className: '!bg-
|
|
414
|
+
className: '!bg-toolbar-surface',
|
|
415
415
|
readonly: true,
|
|
416
416
|
value: '',
|
|
417
417
|
},
|
|
@@ -465,7 +465,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
465
465
|
export const cellClassesForRowSelection = (selected: boolean, selectionMode: SelectionMode) => {
|
|
466
466
|
if (!selected) {
|
|
467
467
|
if (selectionMode === 'single') {
|
|
468
|
-
return ['
|
|
468
|
+
return ['cursor-pointer!'];
|
|
469
469
|
} else {
|
|
470
470
|
return undefined;
|
|
471
471
|
}
|
|
@@ -473,8 +473,8 @@ export const cellClassesForRowSelection = (selected: boolean, selectionMode: Sel
|
|
|
473
473
|
|
|
474
474
|
switch (selectionMode) {
|
|
475
475
|
case 'single':
|
|
476
|
-
return ['
|
|
476
|
+
return ['dx-grid__cell--no-focus-unfurl !bg-current-surface hover:bg-hover-surface cursor-pointer!'];
|
|
477
477
|
case 'multiple':
|
|
478
|
-
return ['!bg-
|
|
478
|
+
return ['!bg-grid-cell-selected'];
|
|
479
479
|
}
|
|
480
480
|
};
|
|
@@ -10,7 +10,7 @@ export default defineConfig({
|
|
|
10
10
|
...e2ePreset(import.meta.dirname),
|
|
11
11
|
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
12
|
webServer: {
|
|
13
|
-
command: '
|
|
13
|
+
command: 'pnpm storybook dev --ci --quiet --port=9004 --config-dir=.storybook',
|
|
14
14
|
port: 9004,
|
|
15
15
|
reuseExistingServer: false,
|
|
16
16
|
},
|
|
@@ -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');
|
|
@@ -7,10 +7,10 @@ import { type RefObject, useCallback, useContext, useMemo, useRef } from 'react'
|
|
|
7
7
|
|
|
8
8
|
import { type Database, type Type } from '@dxos/echo';
|
|
9
9
|
import { isMutable } from '@dxos/echo/internal';
|
|
10
|
-
import {
|
|
10
|
+
import { random } from '@dxos/random';
|
|
11
11
|
import { Filter, useQuery, useSchema } from '@dxos/react-client/echo';
|
|
12
12
|
import { useClientStory } from '@dxos/react-client/testing';
|
|
13
|
-
import { useGlobalFilteredObjects } from '@dxos/react-ui-
|
|
13
|
+
import { useGlobalFilteredObjects } from '@dxos/react-ui-search';
|
|
14
14
|
import { type ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
|
|
15
15
|
|
|
16
16
|
import { type TableController } from '../components';
|
|
@@ -18,9 +18,9 @@ import { useAddRow, useProjectionModel, useTableModel } from '../hooks';
|
|
|
18
18
|
import { type TableModel, TablePresentation } from '../model';
|
|
19
19
|
import { Table } from '../types';
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
random.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
|
|
22
22
|
|
|
23
|
-
export type TestTableModel<T extends Type.
|
|
23
|
+
export type TestTableModel<T extends Type.AnyObj = Type.AnyObj> = {
|
|
24
24
|
schema: T | undefined;
|
|
25
25
|
table: Table.Table | undefined;
|
|
26
26
|
projection: ProjectionModel | undefined;
|
|
@@ -38,7 +38,7 @@ export type TestTableModel<T extends Type.Obj.Any = Type.Obj.Any> = {
|
|
|
38
38
|
* Custom hook to create and manage a test table model for storybook demonstrations.
|
|
39
39
|
* Provides table data, schema, and handlers for table operations.
|
|
40
40
|
*/
|
|
41
|
-
export const useTestTableModel = <T extends Type.
|
|
41
|
+
export const useTestTableModel = <T extends Type.AnyObj = Type.AnyObj>(): TestTableModel<T> => {
|
|
42
42
|
const registry = useContext(RegistryContext);
|
|
43
43
|
const { space } = useClientStory();
|
|
44
44
|
const db = space?.db;
|
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,14 +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
|
-
import { Obj, Ref, Type } from '@dxos/echo';
|
|
9
|
+
import { Annotation, JsonSchema, Obj, Ref, Type } from '@dxos/echo';
|
|
10
|
+
import { View } from '@dxos/echo';
|
|
10
11
|
import { FormInputAnnotation, type JsonPath, type JsonSchemaType, LabelAnnotation } from '@dxos/echo/internal';
|
|
11
|
-
import {
|
|
12
|
+
import { ViewAnnotation } from '@dxos/schema';
|
|
12
13
|
|
|
13
14
|
export const Table = Schema.Struct({
|
|
14
15
|
name: Schema.String.pipe(Schema.optional),
|
|
15
16
|
|
|
16
|
-
view:
|
|
17
|
+
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
|
|
17
18
|
|
|
18
19
|
sizes: Schema.Record({
|
|
19
20
|
// TODO(wittjosiah): Should be JsonPath.
|
|
@@ -22,11 +23,15 @@ export const Table = Schema.Struct({
|
|
|
22
23
|
}).pipe(Schema.mutable, FormInputAnnotation.set(false)),
|
|
23
24
|
}).pipe(
|
|
24
25
|
Type.object({
|
|
25
|
-
typename: 'dxos.
|
|
26
|
-
version: '0.
|
|
26
|
+
typename: 'org.dxos.type.table',
|
|
27
|
+
version: '0.1.0',
|
|
27
28
|
}),
|
|
28
29
|
LabelAnnotation.set(['name']),
|
|
29
|
-
ViewAnnotation.set(
|
|
30
|
+
ViewAnnotation.set(['view']),
|
|
31
|
+
Annotation.IconAnnotation.set({
|
|
32
|
+
icon: 'ph--table--regular',
|
|
33
|
+
hue: 'green',
|
|
34
|
+
}),
|
|
30
35
|
);
|
|
31
36
|
|
|
32
37
|
export interface Table extends Schema.Schema.Type<typeof Table> {}
|
|
@@ -47,7 +52,7 @@ export const make = ({ name, sizes = {}, view, jsonSchema }: MakeProps): Table =
|
|
|
47
52
|
|
|
48
53
|
// Preset sizes.
|
|
49
54
|
if (jsonSchema) {
|
|
50
|
-
const schema =
|
|
55
|
+
const schema = JsonSchema.toEffectSchema(jsonSchema);
|
|
51
56
|
const properties = SchemaAST.getPropertySignatures(schema.ast);
|
|
52
57
|
for (const property of properties) {
|
|
53
58
|
const name = property.name.toString() as JsonPath;
|
|
@@ -72,19 +77,3 @@ export const make = ({ name, sizes = {}, view, jsonSchema }: MakeProps): Table =
|
|
|
72
77
|
|
|
73
78
|
return table;
|
|
74
79
|
};
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
// V1
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
export const TableV1 = Schema.Struct({
|
|
81
|
-
sizes: Schema.Record({
|
|
82
|
-
key: Schema.String,
|
|
83
|
-
value: Schema.Number,
|
|
84
|
-
}).pipe(Schema.mutable),
|
|
85
|
-
}).pipe(
|
|
86
|
-
Type.object({
|
|
87
|
-
typename: 'dxos.org/type/Table',
|
|
88
|
-
version: '0.1.0',
|
|
89
|
-
}),
|
|
90
|
-
);
|
|
@@ -11,8 +11,8 @@ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '.
|
|
|
11
11
|
|
|
12
12
|
describe('makeDynamicTable', () => {
|
|
13
13
|
/**
|
|
14
|
-
* Base case: plain jsonSchema (not from Echo /
|
|
15
|
-
* where projection or schema are reactive, so this does not reproduce the Obj.
|
|
14
|
+
* Base case: plain jsonSchema (not from Echo / JsonSchema.toJsonSchema). Does not exercise the path
|
|
15
|
+
* where projection or schema are reactive, so this does not reproduce the Obj.update regression.
|
|
16
16
|
* Confirms makeDynamicTable + setProperties (title) works with plain objects.
|
|
17
17
|
*/
|
|
18
18
|
test('makeDynamicTable with plain jsonSchema and properties with title does not throw', () => {
|
|
@@ -44,12 +44,12 @@ describe('makeDynamicTable', () => {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Regression test for the path where jsonSchema comes from getBaseSchema(typename, properties).
|
|
47
|
-
* That path uses Echo (
|
|
47
|
+
* That path uses Echo (ViewModel.make, JsonSchema.toJsonSchema); mutations must run inside Obj.update and on a
|
|
48
48
|
* cloned schema. This test ensures that flow does not throw.
|
|
49
49
|
*/
|
|
50
50
|
test('makeDynamicTable with jsonSchema from getBaseSchema(typename, properties) and properties with title does not throw', () => {
|
|
51
51
|
const registry = Registry.make();
|
|
52
|
-
const typename = 'example.
|
|
52
|
+
const typename = 'com.example.type.dynamicTableTest';
|
|
53
53
|
const properties: TablePropertyDefinition[] = [
|
|
54
54
|
{ name: 'id', format: Format.TypeFormat.String },
|
|
55
55
|
{ name: 'name', format: Format.TypeFormat.String, title: 'Name' },
|