@dxos/react-ui-table 0.8.4-main.28f8d3d → 0.8.4-main.406dc2a
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-4K7JPALT.mjs +66 -0
- package/dist/lib/browser/chunk-4K7JPALT.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZAOSIG3L.mjs → chunk-OZTXLZGM.mjs} +526 -536
- package/dist/lib/browser/chunk-OZTXLZGM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +373 -481
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +11 -8
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/types/index.mjs +3 -3
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs +67 -0
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ZOFFI3JJ.mjs → chunk-S56Z4V4X.mjs} +526 -536
- package/dist/lib/node-esm/chunk-S56Z4V4X.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +373 -481
- 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 +11 -8
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/types/index.mjs +3 -3
- 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 +51 -3
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +104 -5
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +8 -5
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +41 -3
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -6
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -13
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -4
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -3
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +3 -2
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +0 -7
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +7 -6
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +1 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +1 -2
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +3 -22
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +25 -5
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +4 -5
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -1
- package/dist/types/src/util/index.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/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +51 -50
- package/src/components/Table/DynamicTable.stories.tsx +12 -9
- package/src/components/Table/DynamicTable.tsx +4 -7
- package/src/components/Table/Relations.stories.tsx +162 -38
- package/src/components/Table/Table.stories.tsx +59 -52
- package/src/components/Table/Table.tsx +109 -90
- package/src/components/TableCellEditor/FormCellEditor.tsx +153 -42
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +22 -63
- package/src/components/TableCellEditor/TableCellEditor.tsx +62 -208
- package/src/components/TableCellEditor/index.ts +1 -0
- package/src/components/testing.ts +2 -2
- package/src/hooks/useAddRow.ts +7 -5
- package/src/hooks/useTableModel.ts +1 -1
- package/src/model/modal-controller.ts +0 -28
- package/src/model/table-model.test.ts +18 -10
- package/src/model/table-model.ts +26 -17
- package/src/model/table-presentation.test.ts +21 -20
- package/src/model/table-presentation.ts +58 -39
- package/src/model/table-sorting.ts +15 -6
- package/src/playwright/smoke.spec.ts +46 -46
- package/src/testing/useTestTableModel.ts +9 -6
- package/src/types/index.ts +1 -1
- package/src/types/schema.ts +63 -6
- package/src/util/dynamic-table.ts +11 -11
- package/src/util/index.ts +0 -1
- package/src/util/schema.ts +4 -4
- package/src/util/table-buttons.ts +3 -3
- package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +0 -7
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/util/table.d.ts +0 -12
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/Table/CreateRefPanel.tsx +0 -86
- package/src/components/TableCellEditor/extension.ts +0 -61
- package/src/util/table.ts +0 -53
package/src/model/table-model.ts
CHANGED
|
@@ -7,19 +7,17 @@ import { type ReadonlySignal, computed, effect, signal } from '@preact/signals-c
|
|
|
7
7
|
import { Resource } from '@dxos/context';
|
|
8
8
|
import { Obj, Ref } from '@dxos/echo';
|
|
9
9
|
import {
|
|
10
|
-
type FieldSortType,
|
|
11
10
|
FormatEnum,
|
|
12
11
|
type JsonProp,
|
|
13
12
|
type JsonSchemaType,
|
|
14
13
|
getSchema,
|
|
15
|
-
getSnapshot,
|
|
16
14
|
getValue,
|
|
17
15
|
setValue,
|
|
18
16
|
toEffectSchema,
|
|
19
|
-
} from '@dxos/echo
|
|
17
|
+
} from '@dxos/echo/internal';
|
|
20
18
|
import { invariant } from '@dxos/invariant';
|
|
21
19
|
import { ObjectId } from '@dxos/keys';
|
|
22
|
-
import { isLiveObject } from '@dxos/live-object';
|
|
20
|
+
import { getSnapshot, isLiveObject } from '@dxos/live-object';
|
|
23
21
|
import { fullyQualifiedId } from '@dxos/react-client/echo';
|
|
24
22
|
import { type Label } from '@dxos/react-ui';
|
|
25
23
|
import { formatForEditing, parseValue } from '@dxos/react-ui-form';
|
|
@@ -29,9 +27,16 @@ import {
|
|
|
29
27
|
type DxGridPlaneRange,
|
|
30
28
|
type DxGridPosition,
|
|
31
29
|
} from '@dxos/react-ui-grid';
|
|
32
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
type DataType,
|
|
32
|
+
type FieldSortType,
|
|
33
|
+
ProjectionModel,
|
|
34
|
+
type PropertyType,
|
|
35
|
+
type ValidationError,
|
|
36
|
+
validateSchema,
|
|
37
|
+
} from '@dxos/schema';
|
|
33
38
|
|
|
34
|
-
import {
|
|
39
|
+
import { Table } from '../types';
|
|
35
40
|
import { touch } from '../util';
|
|
36
41
|
import { extractTagIds } from '../util/tag';
|
|
37
42
|
|
|
@@ -70,6 +75,8 @@ const defaultFeatures: TableFeatures = {
|
|
|
70
75
|
schemaEditable: false,
|
|
71
76
|
};
|
|
72
77
|
|
|
78
|
+
export type InsertRowResult = 'draft' | 'final';
|
|
79
|
+
|
|
73
80
|
export type TableModelProps<T extends TableRow = TableRow> = {
|
|
74
81
|
view: DataType.View;
|
|
75
82
|
schema: JsonSchemaType;
|
|
@@ -80,7 +87,7 @@ export type TableModelProps<T extends TableRow = TableRow> = {
|
|
|
80
87
|
pinnedRows?: { top: number[]; bottom: number[] };
|
|
81
88
|
rowActions?: TableRowAction[];
|
|
82
89
|
onResolveSchema?: (typename: string) => Promise<JsonSchemaType>;
|
|
83
|
-
onInsertRow?: (data?: any) =>
|
|
90
|
+
onInsertRow?: (data?: any) => InsertRowResult;
|
|
84
91
|
onDeleteRows?: (index: number, obj: T[]) => void;
|
|
85
92
|
onDeleteColumn?: (fieldId: string) => void;
|
|
86
93
|
onCellUpdate?: (cell: DxGridPosition) => void;
|
|
@@ -91,14 +98,14 @@ export type TableModelProps<T extends TableRow = TableRow> = {
|
|
|
91
98
|
export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
92
99
|
private readonly _view: DataType.View;
|
|
93
100
|
private readonly _projection: ProjectionModel;
|
|
94
|
-
private _table?:
|
|
101
|
+
private _table?: Table.Table;
|
|
95
102
|
|
|
96
103
|
private readonly _visibleRange = signal<DxGridPlaneRange>({
|
|
97
104
|
start: { row: 0, col: 0 },
|
|
98
105
|
end: { row: 0, col: 0 },
|
|
99
106
|
});
|
|
100
107
|
|
|
101
|
-
private readonly _onInsertRow?: (data?: any) =>
|
|
108
|
+
private readonly _onInsertRow?: (data?: any) => InsertRowResult;
|
|
102
109
|
private readonly _onDeleteRows?: TableModelProps<T>['onDeleteRows'];
|
|
103
110
|
private readonly _onDeleteColumn?: TableModelProps<T>['onDeleteColumn'];
|
|
104
111
|
private readonly _onCellUpdate?: TableModelProps<T>['onCellUpdate'];
|
|
@@ -134,6 +141,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
134
141
|
super();
|
|
135
142
|
this._view = view;
|
|
136
143
|
this._projection = projection ?? new ProjectionModel(schema, view.projection);
|
|
144
|
+
this._projection.normalizeView();
|
|
137
145
|
|
|
138
146
|
// TODO(ZaymonFC): Use our more robust config merging module?
|
|
139
147
|
this._features = { ...defaultFeatures, ...features };
|
|
@@ -175,7 +183,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
175
183
|
return this._view;
|
|
176
184
|
}
|
|
177
185
|
|
|
178
|
-
public get table():
|
|
186
|
+
public get table(): Table.Table {
|
|
179
187
|
invariant(this._table, 'Model not initialized');
|
|
180
188
|
return this._table;
|
|
181
189
|
}
|
|
@@ -238,7 +246,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
238
246
|
|
|
239
247
|
protected override async _open(): Promise<void> {
|
|
240
248
|
const presentation = this._view.presentation.target ?? (await this._view.presentation.load());
|
|
241
|
-
invariant(Obj.instanceOf(
|
|
249
|
+
invariant(Obj.instanceOf(Table.Table, presentation));
|
|
242
250
|
this._table = presentation;
|
|
243
251
|
|
|
244
252
|
this.initializeColumnMeta();
|
|
@@ -256,7 +264,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
256
264
|
return {
|
|
257
265
|
grid: meta,
|
|
258
266
|
frozenColsStart: { 0: { size: 30, resizeable: false } },
|
|
259
|
-
frozenColsEnd: { 0: { size:
|
|
267
|
+
frozenColsEnd: { 0: { size: 32, resizeable: false } },
|
|
260
268
|
};
|
|
261
269
|
});
|
|
262
270
|
}
|
|
@@ -336,11 +344,12 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
336
344
|
|
|
337
345
|
public getColumnCount = (): number => this._projection?.fields.length ?? 0;
|
|
338
346
|
|
|
339
|
-
public insertRow = ():
|
|
347
|
+
public insertRow = (): InsertRowResult => {
|
|
340
348
|
const result = this._onInsertRow?.();
|
|
341
|
-
if (result ===
|
|
349
|
+
if (result === 'draft' && this._draftRows.value.length === 0) {
|
|
342
350
|
this.createDraftRow();
|
|
343
351
|
}
|
|
352
|
+
return result ?? 'final';
|
|
344
353
|
};
|
|
345
354
|
|
|
346
355
|
private createDraftRow(): void {
|
|
@@ -395,14 +404,14 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
395
404
|
return false;
|
|
396
405
|
}
|
|
397
406
|
|
|
398
|
-
const
|
|
407
|
+
const insertRowResult = this._onInsertRow?.(draftRow.data);
|
|
399
408
|
|
|
400
|
-
if (
|
|
409
|
+
if (insertRowResult === 'final') {
|
|
401
410
|
const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
|
|
402
411
|
this._draftRows.value = newDraftRows;
|
|
403
412
|
}
|
|
404
413
|
|
|
405
|
-
return
|
|
414
|
+
return insertRowResult === 'final';
|
|
406
415
|
};
|
|
407
416
|
|
|
408
417
|
public deleteRow = (rowIndex: number): void => {
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import { TypedObject } from '@dxos/echo
|
|
8
|
+
import { Filter, Query } from '@dxos/echo';
|
|
9
|
+
import { TypedObject } from '@dxos/echo/internal';
|
|
10
|
+
import { createEchoSchema } from '@dxos/echo/testing';
|
|
10
11
|
import { live } from '@dxos/live-object';
|
|
11
|
-
import { createEchoSchema } from '@dxos/live-object/testing';
|
|
12
12
|
import { createView } from '@dxos/schema';
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { Table } from '../types';
|
|
15
15
|
|
|
16
16
|
import { TableModel, type TableModelProps } from './table-model';
|
|
17
17
|
import { TablePresentation } from './table-presentation';
|
|
@@ -27,8 +27,8 @@ describe('TablePresentation', () => {
|
|
|
27
27
|
updateCount = 0;
|
|
28
28
|
({ data } = live({
|
|
29
29
|
data: [
|
|
30
|
-
{
|
|
31
|
-
{
|
|
30
|
+
{ title: 'A', count: 1 },
|
|
31
|
+
{ title: 'B', count: 2 },
|
|
32
32
|
],
|
|
33
33
|
}));
|
|
34
34
|
|
|
@@ -45,8 +45,8 @@ describe('TablePresentation', () => {
|
|
|
45
45
|
presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 1, col: 2 } }, 'grid');
|
|
46
46
|
|
|
47
47
|
// Trigger a row update.
|
|
48
|
-
data[0].
|
|
49
|
-
expect(updateCount).toBe(
|
|
48
|
+
data[0].title = 'New Value';
|
|
49
|
+
expect(updateCount).toBe(2);
|
|
50
50
|
|
|
51
51
|
// Verify the new value through getCells.
|
|
52
52
|
const cells = presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 0, col: 0 } }, 'grid');
|
|
@@ -57,15 +57,14 @@ describe('TablePresentation', () => {
|
|
|
57
57
|
// Set up visible range to include our test data.
|
|
58
58
|
presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 2, col: 2 } }, 'grid');
|
|
59
59
|
|
|
60
|
-
data.push({
|
|
61
|
-
expect(updateCount).toBe(
|
|
60
|
+
data.push({ title: 'C', count: 3 });
|
|
61
|
+
expect(updateCount).toBe(2);
|
|
62
62
|
|
|
63
63
|
const cells = presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 2, col: 2 } }, 'grid');
|
|
64
64
|
|
|
65
65
|
// Verify the new row's data.
|
|
66
66
|
expect(cells['0,2']?.value).toBe('C');
|
|
67
67
|
expect(cells['1,2']?.value).toBe('3');
|
|
68
|
-
expect(cells['2,2']?.value).toBe('true');
|
|
69
68
|
});
|
|
70
69
|
|
|
71
70
|
it('should handle combined operations reactively', () => {
|
|
@@ -73,32 +72,34 @@ describe('TablePresentation', () => {
|
|
|
73
72
|
presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 2, col: 2 } }, 'grid');
|
|
74
73
|
|
|
75
74
|
// Multiple operations.
|
|
76
|
-
data[0].
|
|
77
|
-
data.push({
|
|
75
|
+
data[0].title = 'Updated A';
|
|
76
|
+
data.push({ title: 'C', count: 3, completed: true });
|
|
78
77
|
data.splice(1, 1);
|
|
79
78
|
|
|
80
79
|
// We expect one update per operation affecting visible rows.
|
|
81
|
-
expect(updateCount).toBe(
|
|
80
|
+
expect(updateCount).toBe(4);
|
|
82
81
|
|
|
83
82
|
const cells = presentation.getCells({ start: { row: 0, col: 0 }, end: { row: 1, col: 2 } }, 'grid');
|
|
84
83
|
|
|
85
84
|
// Verify final state.
|
|
86
85
|
expect(cells['0,0']?.value).toBe('Updated A');
|
|
87
86
|
expect(cells['0,1']?.value).toBe('C');
|
|
88
|
-
expect(cells['1,1']?.value).toBe('3');
|
|
89
|
-
expect(cells['2,1']?.value).toBe('true');
|
|
90
87
|
});
|
|
91
88
|
});
|
|
92
89
|
});
|
|
93
90
|
|
|
94
91
|
class Test extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
95
92
|
title: Schema.String,
|
|
96
|
-
|
|
93
|
+
count: Schema.Number,
|
|
97
94
|
}) {}
|
|
98
95
|
|
|
99
96
|
const createTableModel = (props: Partial<TableModelProps> = {}): TableModel => {
|
|
100
97
|
const schema = createEchoSchema(Test);
|
|
101
|
-
const table =
|
|
102
|
-
const view = createView({
|
|
98
|
+
const table = Table.make();
|
|
99
|
+
const view = createView({
|
|
100
|
+
query: Query.select(Filter.type(schema)),
|
|
101
|
+
jsonSchema: schema.jsonSchema,
|
|
102
|
+
presentation: table,
|
|
103
|
+
});
|
|
103
104
|
return new TableModel({ view, schema: schema.jsonSchema, ...props });
|
|
104
105
|
};
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { signal } from '@preact/signals-core';
|
|
6
|
-
import
|
|
6
|
+
import * as Predicate from 'effect/Predicate';
|
|
7
7
|
|
|
8
8
|
import { Obj } from '@dxos/echo';
|
|
9
|
-
import { FormatEnum, TypeEnum, getValue } from '@dxos/echo
|
|
9
|
+
import { FormatEnum, TypeEnum, getValue } from '@dxos/echo/internal';
|
|
10
10
|
import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
|
|
11
11
|
import {
|
|
12
12
|
type DxGridCellValue,
|
|
@@ -69,7 +69,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
69
69
|
cells = this.getDraftRowCells(range);
|
|
70
70
|
break;
|
|
71
71
|
case 'fixedEndStart':
|
|
72
|
-
cells = this.
|
|
72
|
+
cells = this.getDraftIconCells(range);
|
|
73
73
|
break;
|
|
74
74
|
case 'fixedEndEnd':
|
|
75
75
|
cells = this.getDraftActionCells(range);
|
|
@@ -141,20 +141,22 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
const classes = [];
|
|
144
|
-
const formatClasses = cellClassesForFieldType(
|
|
144
|
+
const formatClasses = cellClassesForFieldType(props);
|
|
145
|
+
|
|
145
146
|
if (formatClasses) {
|
|
146
147
|
classes.push(formatClasses);
|
|
147
148
|
}
|
|
149
|
+
|
|
148
150
|
const rowSelectionClasses = cellClassesForRowSelection(
|
|
149
151
|
this.model.selection.isObjectSelected(obj),
|
|
150
152
|
this.model.selection.selectionMode,
|
|
151
153
|
);
|
|
154
|
+
|
|
152
155
|
if (rowSelectionClasses) {
|
|
153
156
|
classes.push(rowSelectionClasses);
|
|
154
157
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
+
|
|
159
|
+
cell.className = mx(classes);
|
|
158
160
|
|
|
159
161
|
// Arrays.
|
|
160
162
|
if (props.type === TypeEnum.Array) {
|
|
@@ -188,7 +190,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
188
190
|
|
|
189
191
|
const tags = targetArray
|
|
190
192
|
.map(getLabel)
|
|
191
|
-
.filter(isNotNullable)
|
|
193
|
+
.filter(Predicate.isNotNullable)
|
|
192
194
|
.map((title) => {
|
|
193
195
|
return `<span class="dx-tag" data-hue="neutral">${title}</span>`;
|
|
194
196
|
})
|
|
@@ -203,7 +205,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
203
205
|
const targetObj = getValue(obj, field.path)?.target;
|
|
204
206
|
if (targetObj) {
|
|
205
207
|
const dxn = Obj.getDXN(targetObj)?.toString();
|
|
206
|
-
cell.accessoryHtml = `<dx-
|
|
208
|
+
cell.accessoryHtml = `<div role="none" class="absolute inline-end-0 inset-block-0 p-[--dx-grid-cell-content-padding-block]"><dx-anchor refId=${dxn} class="dx-button is-6 aspect-square min-bs-0" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-anchor></div>`;
|
|
207
209
|
}
|
|
208
210
|
}
|
|
209
211
|
|
|
@@ -279,27 +281,36 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
279
281
|
const fields = this.model.projection?.fields ?? [];
|
|
280
282
|
const draftRows = this.model.draftRows.value;
|
|
281
283
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
+
// Return cells of the CTA row if no draft row is active
|
|
285
|
+
if (draftRows.length === 0) {
|
|
284
286
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
287
|
+
cells[toPlaneCellIndex({ col, row: 0 })] = {
|
|
288
|
+
value: '',
|
|
289
|
+
readonly: true,
|
|
290
|
+
className: 'dx-grid__row--cta__cell',
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
|
|
295
|
+
const draftRow = draftRows[row];
|
|
296
|
+
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
297
|
+
const cellIndex = toPlaneCellIndex({ col, row });
|
|
298
|
+
const field = fields[col];
|
|
299
|
+
if (!field) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
290
302
|
|
|
291
|
-
|
|
303
|
+
this.createDataCell(cells, draftRow.data, field, col, row);
|
|
292
304
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
305
|
+
if (this.model.hasDraftRowValidationError(row, field.path)) {
|
|
306
|
+
const cellValue = cells[cellIndex];
|
|
307
|
+
if (cellValue) {
|
|
308
|
+
const existingClasses = cellValue.className || '';
|
|
309
|
+
const draftClasses = 'dx-grid__cell--flagged';
|
|
310
|
+
cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
|
|
311
|
+
}
|
|
299
312
|
}
|
|
300
313
|
}
|
|
301
|
-
|
|
302
|
-
cells[cellIndex].className += ' !bg-toolbarSurface';
|
|
303
314
|
}
|
|
304
315
|
}
|
|
305
316
|
|
|
@@ -316,14 +327,14 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
316
327
|
|
|
317
328
|
cells[toPlaneCellIndex({ col, row: 0 })] = {
|
|
318
329
|
// TODO(burdon): Use same logic as form for fallback title.
|
|
319
|
-
value:
|
|
320
|
-
readonly: true,
|
|
330
|
+
value: '',
|
|
321
331
|
resizeHandle: 'col',
|
|
322
332
|
accessoryHtml: `
|
|
333
|
+
<span class="grow min-is-0 truncate">${props.title ?? field.path}</span>
|
|
323
334
|
${direction !== undefined ? tableButtons.sort.render({ fieldId: field.id, direction }) : ''}
|
|
324
335
|
${tableButtons.columnSettings.render({ fieldId: field.id })}
|
|
325
336
|
`,
|
|
326
|
-
className: '!bg-toolbarSurface',
|
|
337
|
+
className: '!bg-toolbarSurface !text-description [&>div]:flex [&>div]:items-stretch',
|
|
327
338
|
};
|
|
328
339
|
}
|
|
329
340
|
|
|
@@ -406,30 +417,39 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
406
417
|
const cells: DxGridPlaneCells = {};
|
|
407
418
|
const draftRows = this.model.draftRows.value;
|
|
408
419
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
cells[toPlaneCellIndex({ col: 0, row })] = {
|
|
420
|
+
// Return cells of the CTA row if no draft row is active
|
|
421
|
+
if (draftRows.length === 0) {
|
|
422
|
+
cells[toPlaneCellIndex({ col: 0, row: 0 })] = {
|
|
414
423
|
value: '',
|
|
424
|
+
className: 'dx-grid__row--cta__cell',
|
|
415
425
|
readonly: true,
|
|
416
|
-
accessoryHtml: tableButtons.saveDraftRow.render({ rowIndex: row, disabled }),
|
|
417
|
-
className: '!bg-toolbarSurface',
|
|
418
426
|
};
|
|
427
|
+
} else {
|
|
428
|
+
for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
|
|
429
|
+
const draftRow = draftRows[row];
|
|
430
|
+
const disabled = !draftRow.valid;
|
|
431
|
+
|
|
432
|
+
cells[toPlaneCellIndex({ col: 0, row })] = {
|
|
433
|
+
value: '',
|
|
434
|
+
readonly: true,
|
|
435
|
+
accessoryHtml: tableButtons.saveDraftRow.render({ rowIndex: row, disabled }),
|
|
436
|
+
};
|
|
437
|
+
}
|
|
419
438
|
}
|
|
420
439
|
|
|
421
440
|
return cells;
|
|
422
441
|
}
|
|
423
442
|
|
|
424
|
-
private
|
|
443
|
+
private getDraftIconCells(range: DxGridPlaneRange): DxGridPlaneCells {
|
|
425
444
|
const cells: DxGridPlaneCells = {};
|
|
426
445
|
const draftRows = this.model.draftRows.value;
|
|
427
446
|
|
|
428
|
-
for (let row = range.start.row; row <= range.end.row
|
|
447
|
+
for (let row = range.start.row; row <= range.end.row; row++) {
|
|
429
448
|
cells[toPlaneCellIndex({ col: 0, row })] = {
|
|
430
449
|
value: '',
|
|
431
450
|
readonly: true,
|
|
432
|
-
|
|
451
|
+
accessoryHtml: '<dx-icon icon="ph--plus--regular" class="contents"></dx-icon>',
|
|
452
|
+
className: mx('[&>div]:grid [&>div]:place-content-center', draftRows.length < 1 && 'dx-grid__row--cta__cell'),
|
|
433
453
|
};
|
|
434
454
|
}
|
|
435
455
|
|
|
@@ -448,7 +468,6 @@ export const cellClassesForRowSelection = (selected: boolean, selectionMode: Sel
|
|
|
448
468
|
|
|
449
469
|
switch (selectionMode) {
|
|
450
470
|
case 'single':
|
|
451
|
-
// TODO(ZaymonFC): @thure, do we need a grid version of 'currentRelated'?
|
|
452
471
|
return ['!bg-currentRelated dx-grid__cell--no-focus-unfurl hover:bg-hoverSurface !cursor-pointer'];
|
|
453
472
|
case 'multiple':
|
|
454
473
|
return ['!bg-gridCellSelected'];
|
|
@@ -5,12 +5,21 @@
|
|
|
5
5
|
import { type ReadonlySignal, type Signal, computed, signal } from '@preact/signals-core';
|
|
6
6
|
import orderBy from 'lodash.orderby';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { FormatEnum, TypeEnum, getValue } from '@dxos/echo/internal';
|
|
9
9
|
import { formatForDisplay } from '@dxos/react-ui-form';
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
DataType,
|
|
12
|
+
FieldSortType,
|
|
13
|
+
FieldType,
|
|
14
|
+
ProjectionModel,
|
|
15
|
+
PropertyType,
|
|
16
|
+
SortDirectionType,
|
|
17
|
+
} from '@dxos/schema';
|
|
11
18
|
|
|
12
19
|
import { type TableRow } from './table-model';
|
|
13
20
|
|
|
21
|
+
// TODO(wittjosiah): Remove. Use ordering in queries instead.
|
|
22
|
+
|
|
14
23
|
/**
|
|
15
24
|
* Represents the local sort state.
|
|
16
25
|
* - undefined: No local sort set, fallback to view sort.
|
|
@@ -55,7 +64,7 @@ export class TableSorting<T extends TableRow> {
|
|
|
55
64
|
this._rows = rows;
|
|
56
65
|
this._isDirty = computed(() => {
|
|
57
66
|
const local = this._localSort.value;
|
|
58
|
-
const viewSort = this._view.
|
|
67
|
+
const viewSort = this._view.sort?.[0];
|
|
59
68
|
if (local?.type === 'cleared') {
|
|
60
69
|
return viewSort !== undefined;
|
|
61
70
|
}
|
|
@@ -83,7 +92,7 @@ export class TableSorting<T extends TableRow> {
|
|
|
83
92
|
return local.sort;
|
|
84
93
|
}
|
|
85
94
|
|
|
86
|
-
return this._view.
|
|
95
|
+
return this._view.sort?.[0];
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
/**
|
|
@@ -129,9 +138,9 @@ export class TableSorting<T extends TableRow> {
|
|
|
129
138
|
public save(): void {
|
|
130
139
|
if (this._localSort.value !== undefined) {
|
|
131
140
|
if (this._localSort.value.type === 'active') {
|
|
132
|
-
this._view.
|
|
141
|
+
this._view.sort = [this._localSort.value.sort];
|
|
133
142
|
} else {
|
|
134
|
-
this._view.
|
|
143
|
+
this._view.sort = [];
|
|
135
144
|
}
|
|
136
145
|
this._localSort.value = undefined;
|
|
137
146
|
}
|