@dxos/react-ui-table 0.8.4-main.ae835ea → 0.8.4-main.bc674ce
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-G7MGPBSR.mjs → chunk-I5IFW7UF.mjs} +633 -663
- package/dist/lib/browser/chunk-I5IFW7UF.mjs.map +7 -0
- package/dist/lib/browser/chunk-OZBLY7XM.mjs +76 -0
- package/dist/lib/browser/chunk-OZBLY7XM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1131 -999
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +29 -41
- 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-LD5JEBA6.mjs → chunk-DDJKYJFY.mjs} +633 -662
- package/dist/lib/node-esm/chunk-DDJKYJFY.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-WNZSKIRF.mjs +77 -0
- package/dist/lib/node-esm/chunk-WNZSKIRF.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1131 -999
- 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 +29 -41
- 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/ColumnActionsMenu.d.ts +1 -2
- 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 +4 -5
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +4 -18
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +12 -9
- 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 +8 -8
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +71 -5
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +10 -12
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +5 -7
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +4 -4
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +4 -4
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +22 -15
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +5 -6
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +8 -8
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +5 -1
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +17 -8
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +102 -23
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +3 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/playwright/TableManager.d.ts +1 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +18 -15
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -4
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +31 -0
- package/dist/types/src/types/Table.d.ts.map +1 -0
- 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/util/dynamic-table.d.ts +13 -11
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts +7 -0
- package/dist/types/src/util/query-ast.d.ts.map +1 -0
- package/dist/types/src/util/sort.d.ts +12 -0
- package/dist/types/src/util/sort.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +53 -53
- package/src/components/Table/ColumnActionsMenu.tsx +10 -6
- package/src/components/Table/ColumnSettings.tsx +6 -6
- package/src/components/Table/DynamicTable.stories.tsx +12 -13
- package/src/components/Table/DynamicTable.tsx +21 -14
- package/src/components/Table/Relations.stories.tsx +35 -39
- package/src/components/Table/RowActionsMenu.tsx +24 -15
- package/src/components/Table/Table.stories.tsx +71 -75
- package/src/components/Table/Table.tsx +335 -305
- package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
- package/src/components/TableCellEditor/FormCellEditor.tsx +110 -133
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +16 -12
- package/src/components/TableCellEditor/TableCellEditor.tsx +31 -31
- package/src/components/TableToolbar/TableToolbar.tsx +44 -31
- package/src/components/testing.ts +38 -12
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useAddRow.ts +8 -10
- package/src/hooks/useProjectionModel.ts +39 -0
- package/src/hooks/useTableModel.ts +35 -33
- package/src/model/modal-controller.ts +23 -12
- package/src/model/selection-model.ts +75 -44
- package/src/model/table-model.test.ts +82 -54
- package/src/model/table-model.ts +428 -163
- package/src/model/table-presentation.test.ts +59 -49
- package/src/model/table-presentation.ts +31 -26
- package/src/playwright/TableManager.ts +5 -5
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +8 -5
- package/src/testing/useTestTableModel.ts +44 -37
- package/src/translations.ts +3 -3
- package/src/types/Table.ts +90 -0
- package/src/types/index.ts +1 -1
- package/src/util/dynamic-table.ts +39 -27
- package/src/util/index.ts +2 -0
- package/src/util/query-ast.ts +19 -0
- package/src/util/sort.ts +90 -0
- package/dist/lib/browser/chunk-4K7JPALT.mjs +0 -66
- package/dist/lib/browser/chunk-4K7JPALT.mjs.map +0 -7
- package/dist/lib/browser/chunk-G7MGPBSR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-LD5JEBA6.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs +0 -67
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +0 -7
- package/dist/types/src/model/table-sorting.d.ts +0 -52
- package/dist/types/src/model/table-sorting.d.ts.map +0 -1
- package/dist/types/src/types/schema.d.ts +0 -28
- package/dist/types/src/types/schema.d.ts.map +0 -1
- package/src/model/table-sorting.ts +0 -225
- package/src/types/schema.ts +0 -73
|
@@ -1,86 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// src/util/dynamic-table.ts
|
|
6
|
-
import { Filter, Obj, Query } from "@dxos/echo";
|
|
7
|
-
import { getTypename, toJsonSchema } from "@dxos/echo/internal";
|
|
8
|
-
import { ProjectionModel, createView, getSchemaFromPropertyDefinitions } from "@dxos/schema";
|
|
9
|
-
var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
|
|
10
|
-
if (typename && properties) {
|
|
11
|
-
const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
|
|
12
|
-
return {
|
|
13
|
-
typename: schema2.typename,
|
|
14
|
-
jsonSchema: schema2.jsonSchema
|
|
15
|
-
};
|
|
16
|
-
} else if (schema) {
|
|
17
|
-
return {
|
|
18
|
-
typename: getTypename(schema),
|
|
19
|
-
jsonSchema: toJsonSchema(schema)
|
|
20
|
-
};
|
|
21
|
-
} else if (typename && jsonSchema) {
|
|
22
|
-
return {
|
|
23
|
-
typename,
|
|
24
|
-
jsonSchema
|
|
25
|
-
};
|
|
26
|
-
} else {
|
|
27
|
-
throw new Error("invalid properties");
|
|
1
|
+
// src/util/query-ast.ts
|
|
2
|
+
var extractOrder = (queryAst) => {
|
|
3
|
+
if (queryAst.type === "order") {
|
|
4
|
+
return queryAst.order;
|
|
28
5
|
}
|
|
6
|
+
if (queryAst.type === "options") {
|
|
7
|
+
return extractOrder(queryAst.query);
|
|
8
|
+
}
|
|
9
|
+
return void 0;
|
|
29
10
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
view
|
|
50
|
-
};
|
|
51
|
-
};
|
|
52
|
-
var setProperties = (view, projection, table, properties) => {
|
|
53
|
-
for (const property of properties) {
|
|
54
|
-
const field = projection.fields.find((field2) => field2.path === property.name);
|
|
55
|
-
if (field) {
|
|
56
|
-
if (property.size !== void 0) {
|
|
57
|
-
table.sizes[field.path] = property.size;
|
|
58
|
-
}
|
|
59
|
-
if (property.title !== void 0) {
|
|
60
|
-
const fieldProjection = projection.getFieldProjection(field.id);
|
|
61
|
-
projection.setFieldProjection({
|
|
62
|
-
...fieldProjection,
|
|
63
|
-
props: {
|
|
64
|
-
...fieldProjection.props,
|
|
65
|
-
title: property.title
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
if (property.sort) {
|
|
70
|
-
const fieldId = field.id;
|
|
71
|
-
view.sort = [
|
|
72
|
-
{
|
|
73
|
-
fieldId,
|
|
74
|
-
direction: property.sort
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
}
|
|
11
|
+
|
|
12
|
+
// src/util/sort.ts
|
|
13
|
+
import { Format } from "@dxos/echo";
|
|
14
|
+
var getSortValue = (value, format) => {
|
|
15
|
+
if (value === void 0 || value === null) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const isDateFormat = format === Format.TypeFormat.DateTime || format === Format.TypeFormat.Date;
|
|
19
|
+
if (isDateFormat) {
|
|
20
|
+
const date = new Date(value);
|
|
21
|
+
if (!isNaN(date.getTime())) {
|
|
22
|
+
return date.getTime();
|
|
23
|
+
}
|
|
24
|
+
return String(value);
|
|
25
|
+
}
|
|
26
|
+
if (format === Format.TypeFormat.Number || format === Format.TypeFormat.Integer || format === Format.TypeFormat.Currency || format === Format.TypeFormat.Percent || format === Format.TypeFormat.Duration) {
|
|
27
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
28
|
+
if (!isNaN(num)) {
|
|
29
|
+
return num;
|
|
78
30
|
}
|
|
31
|
+
return String(value);
|
|
79
32
|
}
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === "number") {
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
return String(value);
|
|
40
|
+
};
|
|
41
|
+
var compareValues = (aValue, bValue, format, direction) => {
|
|
42
|
+
if (aValue === void 0 || aValue === null) {
|
|
43
|
+
return bValue === void 0 || bValue === null ? 0 : 1;
|
|
44
|
+
}
|
|
45
|
+
if (bValue === void 0 || bValue === null) {
|
|
46
|
+
return -1;
|
|
47
|
+
}
|
|
48
|
+
const aSortValue = getSortValue(aValue, format);
|
|
49
|
+
const bSortValue = getSortValue(bValue, format);
|
|
50
|
+
let comparison = 0;
|
|
51
|
+
if (typeof aSortValue === "number" && typeof bSortValue === "number") {
|
|
52
|
+
comparison = aSortValue - bSortValue;
|
|
53
|
+
} else if (typeof aSortValue === "string" && typeof bSortValue === "string") {
|
|
54
|
+
comparison = aSortValue.localeCompare(bSortValue);
|
|
55
|
+
} else {
|
|
56
|
+
comparison = String(aSortValue).localeCompare(String(bSortValue));
|
|
57
|
+
}
|
|
58
|
+
return direction === "desc" ? -comparison : comparison;
|
|
80
59
|
};
|
|
81
|
-
|
|
82
|
-
// src/util/signals.ts
|
|
83
|
-
var touch = (value) => value;
|
|
84
60
|
|
|
85
61
|
// src/util/table-buttons.ts
|
|
86
62
|
var BUTTON_IDENTIFIERS = {
|
|
@@ -255,32 +231,17 @@ var tableControls = {
|
|
|
255
231
|
}
|
|
256
232
|
};
|
|
257
233
|
|
|
258
|
-
// src/util/schema.ts
|
|
259
|
-
import * as Schema from "effect/Schema";
|
|
260
|
-
import * as SchemaAST from "effect/SchemaAST";
|
|
261
|
-
var narrowSchema = (schema, paths) => {
|
|
262
|
-
const ast = schema?.ast;
|
|
263
|
-
if (SchemaAST.isTypeLiteral(ast)) {
|
|
264
|
-
const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
|
|
265
|
-
if (propertySignatures.length > 0) {
|
|
266
|
-
const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
|
|
267
|
-
return Schema.make(narrowType);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return void 0;
|
|
271
|
-
};
|
|
272
|
-
|
|
273
234
|
// src/model/table-model.ts
|
|
274
|
-
import {
|
|
235
|
+
import { Atom as Atom2 } from "@effect-atom/atom-react";
|
|
275
236
|
import { Resource as Resource2 } from "@dxos/context";
|
|
276
|
-
import {
|
|
277
|
-
import {
|
|
237
|
+
import { Format as Format2, Obj, Order, Query, Ref } from "@dxos/echo";
|
|
238
|
+
import { toEffectSchema } from "@dxos/echo/internal";
|
|
239
|
+
import { getSnapshot } from "@dxos/echo/internal";
|
|
240
|
+
import { getValue, setValue } from "@dxos/effect";
|
|
278
241
|
import { invariant } from "@dxos/invariant";
|
|
279
242
|
import { ObjectId } from "@dxos/keys";
|
|
280
|
-
import { getSnapshot, isLiveObject } from "@dxos/live-object";
|
|
281
|
-
import { fullyQualifiedId } from "@dxos/react-client/echo";
|
|
282
243
|
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
283
|
-
import {
|
|
244
|
+
import { validateSchema } from "@dxos/schema";
|
|
284
245
|
|
|
285
246
|
// src/util/tag.ts
|
|
286
247
|
var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
@@ -299,75 +260,99 @@ var extractTagIds = (value) => {
|
|
|
299
260
|
};
|
|
300
261
|
|
|
301
262
|
// src/model/selection-model.ts
|
|
302
|
-
import {
|
|
263
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
303
264
|
import { Resource } from "@dxos/context";
|
|
304
265
|
var SelectionModel = class extends Resource {
|
|
266
|
+
_registry;
|
|
305
267
|
_rows;
|
|
268
|
+
_selection;
|
|
269
|
+
_validSelectedIds;
|
|
270
|
+
_hasSelection;
|
|
271
|
+
_allSelected;
|
|
306
272
|
_selectionMode;
|
|
307
|
-
_initialSelection;
|
|
308
273
|
_onSelectionChanged;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
274
|
+
constructor(registry, rows, selectionMode, initialSelection, onSelectionChanged) {
|
|
275
|
+
super();
|
|
276
|
+
this._registry = registry;
|
|
277
|
+
this._rows = rows;
|
|
278
|
+
this._selectionMode = selectionMode;
|
|
279
|
+
this._onSelectionChanged = onSelectionChanged;
|
|
280
|
+
this._selection = Atom.make(new Set(initialSelection));
|
|
281
|
+
this._validSelectedIds = Atom.make((get) => {
|
|
282
|
+
const rows2 = get(this._rows);
|
|
283
|
+
if (!rows2) {
|
|
284
|
+
return /* @__PURE__ */ new Set();
|
|
285
|
+
}
|
|
286
|
+
const validIds = new Set(rows2.map((row) => row.id));
|
|
287
|
+
const selection = get(this._selection);
|
|
288
|
+
return new Set([
|
|
289
|
+
...selection
|
|
290
|
+
].filter((id) => validIds.has(id)));
|
|
291
|
+
});
|
|
292
|
+
this._hasSelection = Atom.make((get) => get(this._validSelectedIds).size > 0);
|
|
293
|
+
this._allSelected = Atom.make((get) => {
|
|
294
|
+
const rows2 = get(this._rows);
|
|
295
|
+
if (rows2.length === 0) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
const selection = get(this._selection);
|
|
299
|
+
return rows2.every((row) => selection.has(row.id));
|
|
300
|
+
});
|
|
331
301
|
}
|
|
332
302
|
async _open() {
|
|
333
|
-
const
|
|
334
|
-
touch(this._selection.value);
|
|
303
|
+
const selectionUnsubscribe = this._registry.subscribe(this._selection, () => {
|
|
335
304
|
this._onSelectionChanged?.();
|
|
336
305
|
});
|
|
337
|
-
this._ctx.onDispose(
|
|
306
|
+
this._ctx.onDispose(selectionUnsubscribe);
|
|
338
307
|
}
|
|
339
308
|
//
|
|
340
309
|
// Getters
|
|
341
310
|
//
|
|
342
|
-
|
|
311
|
+
/** Get the selection atom for reactive access. */
|
|
312
|
+
get selectionAtom() {
|
|
343
313
|
return this._selection;
|
|
344
314
|
}
|
|
345
|
-
|
|
315
|
+
/** Get the current selection value. */
|
|
316
|
+
get selection() {
|
|
317
|
+
return this._registry.get(this._selection);
|
|
318
|
+
}
|
|
319
|
+
/** Get the hasSelection atom for reactive access. */
|
|
320
|
+
get hasSelectionAtom() {
|
|
346
321
|
return this._hasSelection;
|
|
347
322
|
}
|
|
348
|
-
|
|
323
|
+
/** Check if there is any selection. */
|
|
324
|
+
get hasSelection() {
|
|
325
|
+
return this._registry.get(this._hasSelection);
|
|
326
|
+
}
|
|
327
|
+
/** Get the allRowsSelected atom for reactive access. */
|
|
328
|
+
get allRowsSelectedAtom() {
|
|
349
329
|
return this._allSelected;
|
|
350
330
|
}
|
|
331
|
+
/** Check if all rows are selected. */
|
|
332
|
+
get allRowsSelected() {
|
|
333
|
+
return this._registry.get(this._allSelected);
|
|
334
|
+
}
|
|
351
335
|
get selectionMode() {
|
|
352
336
|
return this._selectionMode;
|
|
353
337
|
}
|
|
354
338
|
getSelectedRows = () => {
|
|
355
|
-
const selectedIds = this._validSelectedIds
|
|
356
|
-
return this._rows.
|
|
339
|
+
const selectedIds = this._registry.get(this._validSelectedIds);
|
|
340
|
+
return this._registry.get(this._rows).filter((row) => selectedIds.has(row.id));
|
|
357
341
|
};
|
|
358
342
|
isRowIndexSelected = (rowIndex) => {
|
|
359
|
-
const row = this._rows
|
|
360
|
-
return this._selection.
|
|
343
|
+
const row = this._registry.get(this._rows)[rowIndex];
|
|
344
|
+
return this._registry.get(this._selection).has(row.id);
|
|
361
345
|
};
|
|
362
346
|
isObjectSelected = (object) => {
|
|
363
|
-
return this._selection.
|
|
347
|
+
return this._registry.get(this._selection).has(object.id);
|
|
364
348
|
};
|
|
365
349
|
//
|
|
366
350
|
// Manipulation
|
|
367
351
|
//
|
|
368
352
|
toggleSelectionForRowIndex = (rowIndex) => {
|
|
369
|
-
const row = this._rows
|
|
370
|
-
const
|
|
353
|
+
const row = this._registry.get(this._rows)[rowIndex];
|
|
354
|
+
const currentSelection = this._registry.get(this._selection);
|
|
355
|
+
const newSelection = new Set(currentSelection);
|
|
371
356
|
if (newSelection.has(row.id)) {
|
|
372
357
|
newSelection.delete(row.id);
|
|
373
358
|
} else {
|
|
@@ -376,194 +361,38 @@ var SelectionModel = class extends Resource {
|
|
|
376
361
|
}
|
|
377
362
|
newSelection.add(row.id);
|
|
378
363
|
}
|
|
379
|
-
this._selection
|
|
364
|
+
this._registry.set(this._selection, newSelection);
|
|
380
365
|
};
|
|
381
366
|
setSelection = (mode) => {
|
|
382
367
|
switch (mode) {
|
|
383
368
|
case "all": {
|
|
384
|
-
this._selection
|
|
369
|
+
this._registry.set(this._selection, new Set(this._registry.get(this._rows).map((row) => row.id)));
|
|
385
370
|
break;
|
|
386
371
|
}
|
|
387
372
|
case "none": {
|
|
388
|
-
this._selection
|
|
373
|
+
this._registry.set(this._selection, /* @__PURE__ */ new Set());
|
|
389
374
|
break;
|
|
390
375
|
}
|
|
391
376
|
}
|
|
392
377
|
};
|
|
393
378
|
};
|
|
394
379
|
|
|
395
|
-
// src/model/table-sorting.ts
|
|
396
|
-
import { computed as computed2, signal as signal2 } from "@preact/signals-core";
|
|
397
|
-
import orderBy from "lodash.orderby";
|
|
398
|
-
import { FormatEnum, TypeEnum, getValue } from "@dxos/echo/internal";
|
|
399
|
-
import { formatForDisplay } from "@dxos/react-ui-form";
|
|
400
|
-
var TableSorting = class {
|
|
401
|
-
_view;
|
|
402
|
-
_projection;
|
|
403
|
-
_displayToDataIndex = /* @__PURE__ */ new Map();
|
|
404
|
-
_rows;
|
|
405
|
-
_localSort = signal2(void 0);
|
|
406
|
-
_isDirty;
|
|
407
|
-
sortedRows;
|
|
408
|
-
constructor(rows, _view, _projection) {
|
|
409
|
-
this._view = _view;
|
|
410
|
-
this._projection = _projection;
|
|
411
|
-
this._rows = rows;
|
|
412
|
-
this._isDirty = computed2(() => {
|
|
413
|
-
const local = this._localSort.value;
|
|
414
|
-
const viewSort = this._view.sort?.[0];
|
|
415
|
-
if (local?.type === "cleared") {
|
|
416
|
-
return viewSort !== void 0;
|
|
417
|
-
}
|
|
418
|
-
if (local?.type === "active") {
|
|
419
|
-
if (!viewSort) {
|
|
420
|
-
return true;
|
|
421
|
-
}
|
|
422
|
-
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
423
|
-
}
|
|
424
|
-
return false;
|
|
425
|
-
});
|
|
426
|
-
this.sortedRows = this.initialiseSortedRows();
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* @reactive
|
|
430
|
-
* @returns Local sort if present, falls back to view sort.
|
|
431
|
-
*/
|
|
432
|
-
get sorting() {
|
|
433
|
-
const local = this._localSort.value;
|
|
434
|
-
if (local?.type === "cleared") {
|
|
435
|
-
return void 0;
|
|
436
|
-
}
|
|
437
|
-
if (local?.type === "active") {
|
|
438
|
-
return local.sort;
|
|
439
|
-
}
|
|
440
|
-
return this._view.sort?.[0];
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* @reactive
|
|
444
|
-
* @returns Whether local sort differs from view sort.
|
|
445
|
-
*/
|
|
446
|
-
get isDirty() {
|
|
447
|
-
return this._isDirty.value;
|
|
448
|
-
}
|
|
449
|
-
getDataIndex(displayIndex) {
|
|
450
|
-
return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
|
|
451
|
-
}
|
|
452
|
-
setSort(fieldId, direction) {
|
|
453
|
-
this._localSort.value = {
|
|
454
|
-
type: "active",
|
|
455
|
-
sort: {
|
|
456
|
-
fieldId,
|
|
457
|
-
direction
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
toggleSort(fieldId) {
|
|
462
|
-
if (!this.sorting || this.sorting.fieldId !== fieldId) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
switch (this.sorting.direction) {
|
|
466
|
-
case "asc": {
|
|
467
|
-
this.setSort(fieldId, "desc");
|
|
468
|
-
break;
|
|
469
|
-
}
|
|
470
|
-
case "desc": {
|
|
471
|
-
this.setSort(fieldId, "asc");
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
clearSort() {
|
|
477
|
-
this._localSort.value = {
|
|
478
|
-
type: "cleared"
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
save() {
|
|
482
|
-
if (this._localSort.value !== void 0) {
|
|
483
|
-
if (this._localSort.value.type === "active") {
|
|
484
|
-
this._view.sort = [
|
|
485
|
-
this._localSort.value.sort
|
|
486
|
-
];
|
|
487
|
-
} else {
|
|
488
|
-
this._view.sort = [];
|
|
489
|
-
}
|
|
490
|
-
this._localSort.value = void 0;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
//
|
|
494
|
-
// Initialisation.
|
|
495
|
-
//
|
|
496
|
-
initialiseSortedRows() {
|
|
497
|
-
return computed2(() => {
|
|
498
|
-
this._displayToDataIndex.clear();
|
|
499
|
-
const sort = this.sorting;
|
|
500
|
-
if (!sort) {
|
|
501
|
-
return this._rows.value;
|
|
502
|
-
}
|
|
503
|
-
const field = this._projection.fields.find((f) => f.id === sort.fieldId);
|
|
504
|
-
if (!field) {
|
|
505
|
-
return this._rows.value;
|
|
506
|
-
}
|
|
507
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
508
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
509
|
-
const sortValue = this.getSortValue(props, field, item);
|
|
510
|
-
const isEmpty = !(props.type === TypeEnum.Boolean) && (sortValue == null || sortValue === "");
|
|
511
|
-
return {
|
|
512
|
-
item,
|
|
513
|
-
index,
|
|
514
|
-
value: sortValue,
|
|
515
|
-
isEmpty
|
|
516
|
-
};
|
|
517
|
-
});
|
|
518
|
-
const ordered = orderBy(dataWithIndices, [
|
|
519
|
-
"isEmpty",
|
|
520
|
-
"value"
|
|
521
|
-
], [
|
|
522
|
-
"asc",
|
|
523
|
-
sort.direction
|
|
524
|
-
]);
|
|
525
|
-
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
526
|
-
if (displayIndex !== dataIndex) {
|
|
527
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
528
|
-
}
|
|
529
|
-
});
|
|
530
|
-
return ordered.map(({ item }) => item);
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
getSortValue(props, field, item) {
|
|
534
|
-
const { type, format } = props;
|
|
535
|
-
const value = getValue(item, field.path);
|
|
536
|
-
if (type === TypeEnum.Boolean) {
|
|
537
|
-
return !!value;
|
|
538
|
-
}
|
|
539
|
-
if (type === TypeEnum.Number) {
|
|
540
|
-
return value;
|
|
541
|
-
}
|
|
542
|
-
if (value == null) {
|
|
543
|
-
return value;
|
|
544
|
-
}
|
|
545
|
-
if (format === FormatEnum.SingleSelect) {
|
|
546
|
-
const options = props.options;
|
|
547
|
-
if (!options) {
|
|
548
|
-
return void 0;
|
|
549
|
-
}
|
|
550
|
-
const option = options.find((option2) => option2.id === value);
|
|
551
|
-
return option ? options.indexOf(option) : void 0;
|
|
552
|
-
}
|
|
553
|
-
if (format === FormatEnum.Ref && field.referencePath) {
|
|
554
|
-
const refValue = getValue(value.target, field.referencePath);
|
|
555
|
-
return refValue;
|
|
556
|
-
}
|
|
557
|
-
return formatForDisplay({
|
|
558
|
-
type,
|
|
559
|
-
format,
|
|
560
|
-
value
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
|
|
565
380
|
// src/model/table-model.ts
|
|
566
381
|
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
382
|
+
var createEchoChangeCallback = (table) => ({
|
|
383
|
+
table: (mutate) => Obj.change(table, (mutableTable) => mutate(mutableTable)),
|
|
384
|
+
row: (row, mutate) => {
|
|
385
|
+
if (Obj.isObject(row)) {
|
|
386
|
+
Obj.change(row, (mutableRow) => mutate(mutableRow));
|
|
387
|
+
} else {
|
|
388
|
+
mutate(row);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
var createDirectChangeCallback = (table) => ({
|
|
393
|
+
table: (mutate) => mutate(table),
|
|
394
|
+
row: (row, mutate) => mutate(row)
|
|
395
|
+
});
|
|
567
396
|
var defaultFeatures = {
|
|
568
397
|
selection: {
|
|
569
398
|
enabled: true,
|
|
@@ -573,19 +402,12 @@ var defaultFeatures = {
|
|
|
573
402
|
schemaEditable: false
|
|
574
403
|
};
|
|
575
404
|
var TableModel = class extends Resource2 {
|
|
576
|
-
|
|
405
|
+
_registry;
|
|
406
|
+
_object;
|
|
577
407
|
_projection;
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
row: 0,
|
|
582
|
-
col: 0
|
|
583
|
-
},
|
|
584
|
-
end: {
|
|
585
|
-
row: 0,
|
|
586
|
-
col: 0
|
|
587
|
-
}
|
|
588
|
-
});
|
|
408
|
+
_db;
|
|
409
|
+
_change;
|
|
410
|
+
_visibleRange;
|
|
589
411
|
_onInsertRow;
|
|
590
412
|
_onDeleteRows;
|
|
591
413
|
_onDeleteColumn;
|
|
@@ -594,39 +416,115 @@ var TableModel = class extends Resource2 {
|
|
|
594
416
|
_onRowAction;
|
|
595
417
|
_rowActions;
|
|
596
418
|
_features;
|
|
597
|
-
_rows
|
|
598
|
-
_draftRows
|
|
419
|
+
_rows;
|
|
420
|
+
_draftRows;
|
|
421
|
+
// In-memory sort state - changes are local until saved.
|
|
422
|
+
_inMemorySort;
|
|
423
|
+
// Derived atom for persisted sort from view.query.ast.
|
|
424
|
+
_persistedSort;
|
|
425
|
+
// Derived atom for current sort (in-memory takes precedence over persisted).
|
|
599
426
|
_sorting;
|
|
427
|
+
// Derived atom for sorted rows (used by rows getter and SelectionModel).
|
|
428
|
+
_sortedRows;
|
|
429
|
+
// Derived atom for viewDirty state.
|
|
430
|
+
_viewDirty;
|
|
600
431
|
_pinnedRows;
|
|
601
432
|
_selection;
|
|
602
433
|
_columnMeta;
|
|
603
|
-
|
|
434
|
+
// Counter atom that increments when cells are updated - allows UI to react to cell changes.
|
|
435
|
+
_cellUpdateCounter;
|
|
436
|
+
constructor({ registry, object, projection, db, change, features = {}, initialSelection = [], pinnedRows = {
|
|
604
437
|
top: [],
|
|
605
438
|
bottom: []
|
|
606
439
|
}, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
|
|
607
440
|
super();
|
|
608
|
-
this.
|
|
609
|
-
this.
|
|
441
|
+
this._registry = registry;
|
|
442
|
+
this._object = object;
|
|
443
|
+
this._projection = projection;
|
|
610
444
|
this._projection.normalizeView();
|
|
445
|
+
this._db = db;
|
|
446
|
+
this._change = change ?? createEchoChangeCallback(object);
|
|
611
447
|
this._features = {
|
|
612
448
|
...defaultFeatures,
|
|
613
449
|
...features
|
|
614
450
|
};
|
|
615
451
|
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
|
|
616
452
|
F: __dxlog_file,
|
|
617
|
-
L:
|
|
453
|
+
L: 196,
|
|
618
454
|
S: this,
|
|
619
455
|
A: [
|
|
620
456
|
"!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
|
|
621
457
|
"'Single selection is not compatible with editable tables.'"
|
|
622
458
|
]
|
|
623
459
|
});
|
|
624
|
-
this.
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
460
|
+
this._visibleRange = Atom2.make({
|
|
461
|
+
start: {
|
|
462
|
+
row: 0,
|
|
463
|
+
col: 0
|
|
464
|
+
},
|
|
465
|
+
end: {
|
|
466
|
+
row: 0,
|
|
467
|
+
col: 0
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
this._rows = Atom2.make([]);
|
|
471
|
+
this._draftRows = Atom2.make([]);
|
|
472
|
+
this._inMemorySort = Atom2.make(void 0);
|
|
473
|
+
this._cellUpdateCounter = Atom2.make(0);
|
|
474
|
+
this._persistedSort = Atom2.make((_get) => {
|
|
475
|
+
const viewSnapshot = Obj.getSnapshot(this.view);
|
|
476
|
+
const ast = viewSnapshot.query.ast;
|
|
477
|
+
const orders = extractOrder(ast);
|
|
478
|
+
if (orders && orders.length > 0) {
|
|
479
|
+
const firstOrder = orders[0];
|
|
480
|
+
if (firstOrder.kind === "property") {
|
|
481
|
+
const field = this._projection.getFields().find((f) => f.path === firstOrder.property);
|
|
482
|
+
if (field) {
|
|
483
|
+
return {
|
|
484
|
+
fieldId: field.id,
|
|
485
|
+
direction: firstOrder.direction
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return void 0;
|
|
491
|
+
});
|
|
492
|
+
this._sorting = Atom2.make((get) => {
|
|
493
|
+
const inMemorySort = get(this._inMemorySort);
|
|
494
|
+
return inMemorySort ?? get(this._persistedSort);
|
|
495
|
+
});
|
|
496
|
+
this._sortedRows = Atom2.make((get) => {
|
|
497
|
+
const rows = get(this._rows);
|
|
498
|
+
const sort = get(this._sorting);
|
|
499
|
+
if (!sort || rows.length === 0) {
|
|
500
|
+
return rows;
|
|
501
|
+
}
|
|
502
|
+
const field = this._projection.getFields().find((f) => f.id === sort.fieldId);
|
|
503
|
+
if (!field) {
|
|
504
|
+
return rows;
|
|
505
|
+
}
|
|
506
|
+
const fieldProjection = this._projection.getFieldProjection(field.id);
|
|
507
|
+
const sorted = [
|
|
508
|
+
...rows
|
|
509
|
+
].sort((a, b) => {
|
|
510
|
+
const aValue = getValue(a, field.path);
|
|
511
|
+
const bValue = getValue(b, field.path);
|
|
512
|
+
return compareValues(aValue, bValue, fieldProjection.props.format, sort.direction);
|
|
513
|
+
});
|
|
514
|
+
return sorted;
|
|
515
|
+
});
|
|
516
|
+
this._selection = new SelectionModel(this._registry, this._sortedRows, this._features.selection.mode ?? "multiple", initialSelection, () => this._onRowOrderChange?.());
|
|
517
|
+
this._viewDirty = Atom2.make((get) => {
|
|
518
|
+
const inMemorySort = get(this._inMemorySort);
|
|
519
|
+
if (!inMemorySort) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
const persisted = get(this._persistedSort);
|
|
523
|
+
if (!persisted) {
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
return inMemorySort.fieldId !== persisted.fieldId || inMemorySort.direction !== persisted.direction;
|
|
527
|
+
});
|
|
630
528
|
this._pinnedRows = pinnedRows;
|
|
631
529
|
this._rowActions = rowActions;
|
|
632
530
|
this._onInsertRow = onInsertRow;
|
|
@@ -637,46 +535,73 @@ var TableModel = class extends Resource2 {
|
|
|
637
535
|
this._onRowAction = onRowAction;
|
|
638
536
|
}
|
|
639
537
|
get id() {
|
|
640
|
-
return
|
|
538
|
+
return Obj.getDXN(this._object).toString();
|
|
641
539
|
}
|
|
642
540
|
get view() {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
get table() {
|
|
646
|
-
invariant(this._table, "Model not initialized", {
|
|
541
|
+
const view = this._object.view.target;
|
|
542
|
+
invariant(view, "Table model not initialized", {
|
|
647
543
|
F: __dxlog_file,
|
|
648
|
-
L:
|
|
544
|
+
L: 307,
|
|
649
545
|
S: this,
|
|
650
546
|
A: [
|
|
651
|
-
"
|
|
652
|
-
"'
|
|
547
|
+
"view",
|
|
548
|
+
"'Table model not initialized'"
|
|
653
549
|
]
|
|
654
550
|
});
|
|
655
|
-
return
|
|
551
|
+
return view;
|
|
552
|
+
}
|
|
553
|
+
get table() {
|
|
554
|
+
return this._object;
|
|
656
555
|
}
|
|
657
556
|
get projection() {
|
|
658
557
|
return this._projection;
|
|
659
558
|
}
|
|
559
|
+
get db() {
|
|
560
|
+
return this._db;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Atom for reactive access to rows with in-memory sorting applied.
|
|
564
|
+
*/
|
|
660
565
|
get rows() {
|
|
661
|
-
return this.
|
|
566
|
+
return this._sortedRows;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Gets rows with in-memory sorting applied.
|
|
570
|
+
* In-memory sort is local to this instance until saved.
|
|
571
|
+
*/
|
|
572
|
+
getRows() {
|
|
573
|
+
return this._registry.get(this._sortedRows);
|
|
574
|
+
}
|
|
575
|
+
/** Atom for reactive access to cell changes. */
|
|
576
|
+
get cellUpdate() {
|
|
577
|
+
return this._cellUpdateCounter;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Change a row using the configured change callback.
|
|
581
|
+
* Use this instead of directly mutating to ensure consistent mutation handling.
|
|
582
|
+
*/
|
|
583
|
+
changeRow(row, mutate) {
|
|
584
|
+
this._change.row(row, mutate);
|
|
662
585
|
}
|
|
663
586
|
get features() {
|
|
664
587
|
return this._features;
|
|
665
588
|
}
|
|
666
589
|
/**
|
|
667
|
-
*
|
|
590
|
+
* Gets the current sort state.
|
|
591
|
+
* Priority: in-memory sort (local changes) > persisted sort (from query AST).
|
|
668
592
|
*/
|
|
669
|
-
|
|
670
|
-
return this._sorting;
|
|
593
|
+
getSorting() {
|
|
594
|
+
return this._registry.get(this._sorting);
|
|
671
595
|
}
|
|
672
596
|
/**
|
|
673
597
|
* Gets the row data at the specified display index.
|
|
674
598
|
*/
|
|
675
599
|
getRowAt(displayIndex) {
|
|
676
|
-
|
|
600
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
601
|
+
if (displayIndex < 0 || displayIndex >= sortedRows.length) {
|
|
677
602
|
return void 0;
|
|
678
603
|
}
|
|
679
|
-
return
|
|
604
|
+
return sortedRows[displayIndex];
|
|
680
605
|
}
|
|
681
606
|
get pinnedRows() {
|
|
682
607
|
return this._pinnedRows;
|
|
@@ -684,7 +609,7 @@ var TableModel = class extends Resource2 {
|
|
|
684
609
|
get columnMeta() {
|
|
685
610
|
invariant(this._columnMeta, void 0, {
|
|
686
611
|
F: __dxlog_file,
|
|
687
|
-
L:
|
|
612
|
+
L: 380,
|
|
688
613
|
S: this,
|
|
689
614
|
A: [
|
|
690
615
|
"this._columnMeta",
|
|
@@ -696,10 +621,6 @@ var TableModel = class extends Resource2 {
|
|
|
696
621
|
get selection() {
|
|
697
622
|
return this._selection;
|
|
698
623
|
}
|
|
699
|
-
/** @reactive */
|
|
700
|
-
get isViewDirty() {
|
|
701
|
-
return this.sorting.isDirty;
|
|
702
|
-
}
|
|
703
624
|
get rowActions() {
|
|
704
625
|
return this._rowActions;
|
|
705
626
|
}
|
|
@@ -707,24 +628,23 @@ var TableModel = class extends Resource2 {
|
|
|
707
628
|
// Initialisation
|
|
708
629
|
//
|
|
709
630
|
async _open() {
|
|
710
|
-
|
|
711
|
-
invariant(Obj2.instanceOf(schema_exports.Table, presentation), void 0, {
|
|
712
|
-
F: __dxlog_file,
|
|
713
|
-
L: 249,
|
|
714
|
-
S: this,
|
|
715
|
-
A: [
|
|
716
|
-
"Obj.instanceOf(Table.Table, presentation)",
|
|
717
|
-
""
|
|
718
|
-
]
|
|
719
|
-
});
|
|
720
|
-
this._table = presentation;
|
|
631
|
+
await this._object.view.load();
|
|
721
632
|
this.initializeColumnMeta();
|
|
722
633
|
this.initializeEffects();
|
|
723
634
|
await this._selection.open(this._ctx);
|
|
724
635
|
}
|
|
725
636
|
initializeColumnMeta() {
|
|
726
|
-
this.
|
|
727
|
-
|
|
637
|
+
invariant(this._object.view.target, "View must be loaded before initializing column meta", {
|
|
638
|
+
F: __dxlog_file,
|
|
639
|
+
L: 404,
|
|
640
|
+
S: this,
|
|
641
|
+
A: [
|
|
642
|
+
"this._object.view.target",
|
|
643
|
+
"'View must be loaded before initializing column meta'"
|
|
644
|
+
]
|
|
645
|
+
});
|
|
646
|
+
this._columnMeta = Atom2.make((get) => {
|
|
647
|
+
const fields = get(this._projection.fields);
|
|
728
648
|
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
729
649
|
index,
|
|
730
650
|
{
|
|
@@ -750,49 +670,62 @@ var TableModel = class extends Resource2 {
|
|
|
750
670
|
});
|
|
751
671
|
}
|
|
752
672
|
initializeEffects() {
|
|
753
|
-
const
|
|
754
|
-
touch(this.sorting.sortedRows.value);
|
|
673
|
+
const rowsUnsubscribe = this._registry.subscribe(this._rows, () => {
|
|
755
674
|
this._onRowOrderChange?.();
|
|
756
675
|
});
|
|
757
|
-
this._ctx.onDispose(
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
676
|
+
this._ctx.onDispose(rowsUnsubscribe);
|
|
677
|
+
const rowSubscriptions = /* @__PURE__ */ new Map();
|
|
678
|
+
const visibleRangeUnsubscribe = this._registry.subscribe(this._visibleRange, () => {
|
|
679
|
+
for (const [id, unsub] of rowSubscriptions) {
|
|
680
|
+
unsub();
|
|
681
|
+
rowSubscriptions.delete(id);
|
|
682
|
+
}
|
|
683
|
+
const { start, end } = this._registry.get(this._visibleRange);
|
|
684
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
685
|
+
for (let row = start.row; row <= end.row && row < sortedRows.length; row++) {
|
|
686
|
+
const obj = sortedRows[row];
|
|
687
|
+
if (Obj.isObject(obj) && !rowSubscriptions.has(obj.id)) {
|
|
688
|
+
const unsub = Obj.subscribe(obj, () => {
|
|
689
|
+
this._registry.set(this._cellUpdateCounter, this._registry.get(this._cellUpdateCounter) + 1);
|
|
690
|
+
this._onCellUpdate?.({
|
|
691
|
+
row,
|
|
692
|
+
col: start.col,
|
|
693
|
+
plane: "grid"
|
|
694
|
+
});
|
|
769
695
|
});
|
|
770
|
-
|
|
696
|
+
rowSubscriptions.set(obj.id, unsub);
|
|
697
|
+
}
|
|
771
698
|
}
|
|
772
|
-
return () => rowEffects.forEach((cleanup) => cleanup());
|
|
773
699
|
});
|
|
774
|
-
this._ctx.onDispose(
|
|
775
|
-
|
|
776
|
-
|
|
700
|
+
this._ctx.onDispose(() => {
|
|
701
|
+
visibleRangeUnsubscribe();
|
|
702
|
+
for (const unsub of rowSubscriptions.values()) {
|
|
703
|
+
unsub();
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
const draftRowsUnsubscribe = this._registry.subscribe(this._draftRows, () => {
|
|
777
707
|
this._onRowOrderChange?.();
|
|
778
708
|
});
|
|
779
|
-
this._ctx.onDispose(
|
|
709
|
+
this._ctx.onDispose(draftRowsUnsubscribe);
|
|
780
710
|
}
|
|
781
711
|
//
|
|
782
712
|
// Data
|
|
783
713
|
//
|
|
784
714
|
setRows = (obj) => {
|
|
785
|
-
this._rows
|
|
715
|
+
this._registry.set(this._rows, obj);
|
|
786
716
|
};
|
|
787
|
-
getRowCount = () => this.
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
// TODO(ZaymonFC): Return .value instead of exposing the signal.
|
|
717
|
+
getRowCount = () => this._registry.get(this._sortedRows).length;
|
|
718
|
+
getDraftRowCount() {
|
|
719
|
+
return this._registry.get(this._draftRows).length;
|
|
720
|
+
}
|
|
721
|
+
/** Atom for reactive access to draft rows. */
|
|
793
722
|
get draftRows() {
|
|
794
723
|
return this._draftRows;
|
|
795
724
|
}
|
|
725
|
+
/** Gets the current draft rows. */
|
|
726
|
+
getDraftRows() {
|
|
727
|
+
return this._registry.get(this._draftRows);
|
|
728
|
+
}
|
|
796
729
|
/**
|
|
797
730
|
* Checks if a specific field path has validation errors for a given draft row.
|
|
798
731
|
* @param draftRowIndex - The index of the draft row to check
|
|
@@ -800,17 +733,17 @@ var TableModel = class extends Resource2 {
|
|
|
800
733
|
* @returns true if the field has validation errors, false otherwise
|
|
801
734
|
*/
|
|
802
735
|
hasDraftRowValidationError(draftRowIndex, fieldPath) {
|
|
803
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
736
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
804
737
|
return false;
|
|
805
738
|
}
|
|
806
|
-
const draftRow = this._draftRows
|
|
739
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
807
740
|
const validationErrors = draftRow.validationErrors || [];
|
|
808
741
|
return validationErrors.some((error) => error.path === fieldPath);
|
|
809
742
|
}
|
|
810
|
-
getColumnCount = () => this._projection?.
|
|
743
|
+
getColumnCount = () => this._projection?.getFields().length ?? 0;
|
|
811
744
|
insertRow = () => {
|
|
812
745
|
const result = this._onInsertRow?.();
|
|
813
|
-
if (result === "draft" && this._draftRows.
|
|
746
|
+
if (result === "draft" && this._registry.get(this._draftRows).length === 0) {
|
|
814
747
|
this.createDraftRow();
|
|
815
748
|
}
|
|
816
749
|
return result ?? "final";
|
|
@@ -828,16 +761,16 @@ var TableModel = class extends Resource2 {
|
|
|
828
761
|
valid: validationErrors.length === 0,
|
|
829
762
|
validationErrors
|
|
830
763
|
};
|
|
831
|
-
this._draftRows
|
|
832
|
-
...this._draftRows
|
|
764
|
+
this._registry.set(this._draftRows, [
|
|
765
|
+
...this._registry.get(this._draftRows),
|
|
833
766
|
draftRow
|
|
834
|
-
];
|
|
767
|
+
]);
|
|
835
768
|
}
|
|
836
769
|
validateDraftRow(draftRowIndex) {
|
|
837
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
770
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
838
771
|
return;
|
|
839
772
|
}
|
|
840
|
-
const draftRow = this._draftRows
|
|
773
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
841
774
|
const validationErrors = this.validateDraftRowData(draftRow.data);
|
|
842
775
|
const updatedDraftRow = {
|
|
843
776
|
...draftRow,
|
|
@@ -845,80 +778,82 @@ var TableModel = class extends Resource2 {
|
|
|
845
778
|
validationErrors
|
|
846
779
|
};
|
|
847
780
|
const newDraftRows = [
|
|
848
|
-
...this._draftRows
|
|
781
|
+
...this._registry.get(this._draftRows)
|
|
849
782
|
];
|
|
850
783
|
newDraftRows[draftRowIndex] = updatedDraftRow;
|
|
851
|
-
this._draftRows
|
|
784
|
+
this._registry.set(this._draftRows, newDraftRows);
|
|
852
785
|
}
|
|
853
786
|
validateDraftRowData(data) {
|
|
854
787
|
const schema = toEffectSchema(this._projection.baseSchema);
|
|
855
788
|
return validateSchema(schema, data) || [];
|
|
856
789
|
}
|
|
857
790
|
commitDraftRow = (draftRowIndex) => {
|
|
858
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
791
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
859
792
|
return false;
|
|
860
793
|
}
|
|
861
|
-
const draftRow = this._draftRows
|
|
794
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
862
795
|
if (!draftRow.valid) {
|
|
863
796
|
return false;
|
|
864
797
|
}
|
|
865
798
|
const insertRowResult = this._onInsertRow?.(draftRow.data);
|
|
866
799
|
if (insertRowResult === "final") {
|
|
867
|
-
const newDraftRows = this._draftRows.
|
|
868
|
-
this._draftRows
|
|
800
|
+
const newDraftRows = this._registry.get(this._draftRows).filter((_, index) => index !== draftRowIndex);
|
|
801
|
+
this._registry.set(this._draftRows, newDraftRows);
|
|
869
802
|
}
|
|
870
803
|
return insertRowResult === "final";
|
|
871
804
|
};
|
|
872
805
|
deleteRow = (rowIndex) => {
|
|
873
|
-
const
|
|
874
|
-
const obj =
|
|
806
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
807
|
+
const obj = sortedRows[rowIndex];
|
|
875
808
|
const objectsToDelete = [];
|
|
876
|
-
if (this.features.selection.enabled && this._selection.hasSelection
|
|
809
|
+
if (this.features.selection.enabled && this._selection.hasSelection) {
|
|
877
810
|
const selectedRows = this._selection.getSelectedRows();
|
|
878
811
|
objectsToDelete.push(...selectedRows);
|
|
879
|
-
} else {
|
|
812
|
+
} else if (obj) {
|
|
880
813
|
objectsToDelete.push(obj);
|
|
881
814
|
}
|
|
882
|
-
|
|
815
|
+
if (objectsToDelete.length > 0) {
|
|
816
|
+
this._onDeleteRows?.(rowIndex, objectsToDelete);
|
|
817
|
+
}
|
|
883
818
|
};
|
|
884
819
|
handleRowAction = (actionId, rowIndex) => {
|
|
885
820
|
if (!this._onRowAction) {
|
|
886
821
|
return;
|
|
887
822
|
}
|
|
888
|
-
const
|
|
889
|
-
const data =
|
|
823
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
824
|
+
const data = sortedRows[rowIndex];
|
|
890
825
|
if (data) {
|
|
891
826
|
this._onRowAction(actionId, data);
|
|
892
827
|
}
|
|
893
828
|
};
|
|
894
829
|
getCellData = (cell) => {
|
|
895
830
|
const { col, row, plane } = cell;
|
|
896
|
-
const fields = this._projection?.
|
|
831
|
+
const fields = this._projection?.getFields() ?? [];
|
|
897
832
|
if (col < 0 || col >= fields.length) {
|
|
898
833
|
return void 0;
|
|
899
834
|
}
|
|
900
835
|
const field = fields[col];
|
|
901
836
|
let value;
|
|
902
837
|
if (plane === "frozenRowsEnd") {
|
|
903
|
-
if (row >= 0 && row < this._draftRows.
|
|
904
|
-
value =
|
|
838
|
+
if (row >= 0 && row < this._registry.get(this._draftRows).length) {
|
|
839
|
+
value = getValue(this._registry.get(this._draftRows)[row].data, field.path);
|
|
905
840
|
} else {
|
|
906
841
|
return void 0;
|
|
907
842
|
}
|
|
908
843
|
} else {
|
|
909
|
-
const
|
|
910
|
-
value =
|
|
844
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
845
|
+
value = getValue(sortedRows[row], field.path);
|
|
911
846
|
}
|
|
912
847
|
if (value == null) {
|
|
913
848
|
return "";
|
|
914
849
|
}
|
|
915
850
|
const { props } = this._projection.getFieldProjection(field.id);
|
|
916
851
|
switch (props.format) {
|
|
917
|
-
case
|
|
852
|
+
case Format2.TypeFormat.Ref: {
|
|
918
853
|
if (!field.referencePath) {
|
|
919
854
|
return "";
|
|
920
855
|
}
|
|
921
|
-
return
|
|
856
|
+
return getValue(value.target, field.referencePath);
|
|
922
857
|
}
|
|
923
858
|
default: {
|
|
924
859
|
return formatForEditing({
|
|
@@ -930,7 +865,7 @@ var TableModel = class extends Resource2 {
|
|
|
930
865
|
}
|
|
931
866
|
};
|
|
932
867
|
validateCellData = async ({ col, row, plane }, value) => {
|
|
933
|
-
const fields = this._projection?.
|
|
868
|
+
const fields = this._projection?.getFields() ?? [];
|
|
934
869
|
if (col < 0 || col >= fields.length) {
|
|
935
870
|
return {
|
|
936
871
|
valid: false,
|
|
@@ -942,14 +877,14 @@ var TableModel = class extends Resource2 {
|
|
|
942
877
|
const transformedValue = editorTextToCellValue(props, value);
|
|
943
878
|
const isDraftRow = plane === "frozenRowsEnd";
|
|
944
879
|
if (isDraftRow) {
|
|
945
|
-
const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.
|
|
880
|
+
const isInvalidDraftRowIndex = row < 0 || row >= this._registry.get(this._draftRows).length;
|
|
946
881
|
if (isInvalidDraftRowIndex) {
|
|
947
882
|
return {
|
|
948
883
|
valid: false,
|
|
949
884
|
error: "Invalid draft row index"
|
|
950
885
|
};
|
|
951
886
|
}
|
|
952
|
-
const draftRow = this._draftRows
|
|
887
|
+
const draftRow = this._registry.get(this._draftRows)[row];
|
|
953
888
|
const snapshot = {
|
|
954
889
|
...draftRow.data
|
|
955
890
|
};
|
|
@@ -968,11 +903,10 @@ var TableModel = class extends Resource2 {
|
|
|
968
903
|
valid: true
|
|
969
904
|
};
|
|
970
905
|
} else {
|
|
971
|
-
const
|
|
972
|
-
const currentRow = this._rows.value[rowIdx];
|
|
906
|
+
const currentRow = this._registry.get(this._rows)[row];
|
|
973
907
|
invariant(currentRow, "Invalid row index", {
|
|
974
908
|
F: __dxlog_file,
|
|
975
|
-
L:
|
|
909
|
+
L: 692,
|
|
976
910
|
S: this,
|
|
977
911
|
A: [
|
|
978
912
|
"currentRow",
|
|
@@ -981,10 +915,10 @@ var TableModel = class extends Resource2 {
|
|
|
981
915
|
});
|
|
982
916
|
const snapshot = getSnapshot(currentRow);
|
|
983
917
|
setValue(snapshot, field.path, transformedValue);
|
|
984
|
-
const schema = getSchema(currentRow);
|
|
918
|
+
const schema = Obj.getSchema(currentRow);
|
|
985
919
|
invariant(schema, void 0, {
|
|
986
920
|
F: __dxlog_file,
|
|
987
|
-
L:
|
|
921
|
+
L: 698,
|
|
988
922
|
S: this,
|
|
989
923
|
A: [
|
|
990
924
|
"schema",
|
|
@@ -996,7 +930,7 @@ var TableModel = class extends Resource2 {
|
|
|
996
930
|
const error = validationResult[0];
|
|
997
931
|
invariant(error.path === field.path, void 0, {
|
|
998
932
|
F: __dxlog_file,
|
|
999
|
-
L:
|
|
933
|
+
L: 703,
|
|
1000
934
|
S: this,
|
|
1001
935
|
A: [
|
|
1002
936
|
"error.path === field.path",
|
|
@@ -1015,24 +949,27 @@ var TableModel = class extends Resource2 {
|
|
|
1015
949
|
};
|
|
1016
950
|
setCellData = (cell, value) => {
|
|
1017
951
|
const { col, row, plane } = cell;
|
|
1018
|
-
const fields = this._projection?.
|
|
952
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1019
953
|
if (col < 0 || col >= fields.length) {
|
|
1020
954
|
return;
|
|
1021
955
|
}
|
|
1022
956
|
const field = fields[col];
|
|
1023
957
|
const { props } = this._projection.getFieldProjection(field.id);
|
|
1024
958
|
const transformedValue = editorTextToCellValue(props, value);
|
|
1025
|
-
if (props.format ===
|
|
959
|
+
if (props.format === Format2.TypeFormat.Ref && !Obj.isObject(value)) {
|
|
1026
960
|
return;
|
|
1027
961
|
}
|
|
1028
962
|
if (plane === "frozenRowsEnd") {
|
|
1029
|
-
if (row >= 0 && row < this._draftRows.
|
|
1030
|
-
setValue(this._draftRows
|
|
963
|
+
if (row >= 0 && row < this._registry.get(this._draftRows).length) {
|
|
964
|
+
setValue(this._registry.get(this._draftRows)[row].data, field.path, transformedValue);
|
|
1031
965
|
this.validateDraftRow(row);
|
|
1032
966
|
}
|
|
1033
967
|
} else {
|
|
1034
|
-
const
|
|
1035
|
-
|
|
968
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
969
|
+
const rowData = sortedRows[row];
|
|
970
|
+
this._change.row(rowData, (mutableRow) => {
|
|
971
|
+
setValue(mutableRow, field.path, transformedValue);
|
|
972
|
+
});
|
|
1036
973
|
}
|
|
1037
974
|
};
|
|
1038
975
|
/**
|
|
@@ -1041,12 +978,15 @@ var TableModel = class extends Resource2 {
|
|
|
1041
978
|
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1042
979
|
*/
|
|
1043
980
|
updateCellData({ col, row }, update) {
|
|
1044
|
-
const
|
|
1045
|
-
const fields = this._projection?.fields ?? [];
|
|
981
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1046
982
|
const field = fields[col];
|
|
1047
|
-
const
|
|
983
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
984
|
+
const rowData = sortedRows[row];
|
|
985
|
+
const value = getValue(rowData, field.path);
|
|
1048
986
|
const updatedValue = update(value);
|
|
1049
|
-
|
|
987
|
+
this._change.row(rowData, (mutableRow) => {
|
|
988
|
+
setValue(mutableRow, field.path, updatedValue);
|
|
989
|
+
});
|
|
1050
990
|
}
|
|
1051
991
|
/**
|
|
1052
992
|
* Gets the domain-appropriate cell type for a given cell position.
|
|
@@ -1080,7 +1020,7 @@ var TableModel = class extends Resource2 {
|
|
|
1080
1020
|
if (!this._projection) {
|
|
1081
1021
|
return;
|
|
1082
1022
|
}
|
|
1083
|
-
const field = this._projection?.
|
|
1023
|
+
const field = this._projection?.getFields().find((field2) => field2.id === fieldId);
|
|
1084
1024
|
if (field && this._onDeleteColumn) {
|
|
1085
1025
|
this._onDeleteColumn(field.id);
|
|
1086
1026
|
}
|
|
@@ -1089,12 +1029,14 @@ var TableModel = class extends Resource2 {
|
|
|
1089
1029
|
// Resize
|
|
1090
1030
|
//
|
|
1091
1031
|
setColumnWidth(columnIndex, width) {
|
|
1092
|
-
const fields = this._projection?.
|
|
1032
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1093
1033
|
if (columnIndex < fields.length) {
|
|
1094
1034
|
const newWidth = Math.max(0, width);
|
|
1095
1035
|
const field = fields[columnIndex];
|
|
1096
1036
|
if (field) {
|
|
1097
|
-
this.table
|
|
1037
|
+
this._change.table((mutableTable) => {
|
|
1038
|
+
mutableTable.sizes[field.path] = newWidth;
|
|
1039
|
+
});
|
|
1098
1040
|
}
|
|
1099
1041
|
}
|
|
1100
1042
|
}
|
|
@@ -1110,22 +1052,92 @@ var TableModel = class extends Resource2 {
|
|
|
1110
1052
|
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1111
1053
|
}
|
|
1112
1054
|
//
|
|
1113
|
-
//
|
|
1055
|
+
// Sort operations
|
|
1114
1056
|
//
|
|
1057
|
+
/**
|
|
1058
|
+
* Sets the sort order for a field in-memory (local to this instance).
|
|
1059
|
+
* Use saveView() to persist the sort to the view query.
|
|
1060
|
+
*/
|
|
1061
|
+
setSort(fieldId, direction) {
|
|
1062
|
+
const field = this._projection.getFields().find((f) => f.id === fieldId);
|
|
1063
|
+
if (!field) {
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
this._registry.set(this._inMemorySort, {
|
|
1067
|
+
fieldId,
|
|
1068
|
+
direction
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Toggles the sort direction for a field in-memory.
|
|
1073
|
+
*/
|
|
1074
|
+
toggleSort(fieldId) {
|
|
1075
|
+
const currentSort = this.getSorting();
|
|
1076
|
+
if (!currentSort || currentSort.fieldId !== fieldId) {
|
|
1077
|
+
this.setSort(fieldId, "asc");
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
const newDirection = currentSort.direction === "asc" ? "desc" : "asc";
|
|
1081
|
+
this.setSort(fieldId, newDirection);
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Clears the in-memory sort order.
|
|
1085
|
+
*/
|
|
1086
|
+
clearSort() {
|
|
1087
|
+
this._registry.set(this._inMemorySort, void 0);
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Saves the current in-memory sort to the view query AST.
|
|
1091
|
+
* This persists the sort so it becomes the default for all viewers.
|
|
1092
|
+
*/
|
|
1115
1093
|
saveView() {
|
|
1116
|
-
this.
|
|
1094
|
+
const view = this.view;
|
|
1095
|
+
const inMemorySort = this._registry.get(this._inMemorySort);
|
|
1096
|
+
const viewSnapshot = Obj.getSnapshot(view);
|
|
1097
|
+
const currentQuery = Query.fromAst(viewSnapshot.query.ast);
|
|
1098
|
+
const baseQuery = this._getBaseQuery(currentQuery);
|
|
1099
|
+
if (inMemorySort) {
|
|
1100
|
+
const field = this._projection.getFields().find((f) => f.id === inMemorySort.fieldId);
|
|
1101
|
+
if (field) {
|
|
1102
|
+
const newQuery = baseQuery.orderBy(Order.property(field.path, inMemorySort.direction));
|
|
1103
|
+
Obj.change(view, (v) => {
|
|
1104
|
+
v.query.ast = newQuery.ast;
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
} else {
|
|
1108
|
+
Obj.change(view, (v) => {
|
|
1109
|
+
v.query.ast = baseQuery.ast;
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
this._registry.set(this._inMemorySort, void 0);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Extracts the base query without order clauses.
|
|
1116
|
+
*/
|
|
1117
|
+
_getBaseQuery(query) {
|
|
1118
|
+
const ast = query.ast;
|
|
1119
|
+
if (ast.type === "order") {
|
|
1120
|
+
return Query.fromAst(ast.query);
|
|
1121
|
+
}
|
|
1122
|
+
return query;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Checks if the view has unsaved changes (in-memory sort differs from persisted sort).
|
|
1126
|
+
*/
|
|
1127
|
+
getViewDirty() {
|
|
1128
|
+
return this._registry.get(this._viewDirty);
|
|
1117
1129
|
}
|
|
1118
1130
|
};
|
|
1119
1131
|
var editorTextToCellValue = (props, value) => {
|
|
1120
1132
|
switch (props.format) {
|
|
1121
|
-
case
|
|
1122
|
-
if (
|
|
1133
|
+
case Format2.TypeFormat.Ref: {
|
|
1134
|
+
if (Obj.isObject(value)) {
|
|
1123
1135
|
return Ref.make(value);
|
|
1124
1136
|
} else {
|
|
1125
1137
|
return value;
|
|
1126
1138
|
}
|
|
1127
1139
|
}
|
|
1128
|
-
case
|
|
1140
|
+
case Format2.TypeFormat.SingleSelect: {
|
|
1129
1141
|
const ids = extractTagIds(value);
|
|
1130
1142
|
if (ids && ids.length > 0) {
|
|
1131
1143
|
return ids[0];
|
|
@@ -1133,7 +1145,7 @@ var editorTextToCellValue = (props, value) => {
|
|
|
1133
1145
|
return value;
|
|
1134
1146
|
}
|
|
1135
1147
|
}
|
|
1136
|
-
case
|
|
1148
|
+
case Format2.TypeFormat.MultiSelect: {
|
|
1137
1149
|
const ids = extractTagIds(value);
|
|
1138
1150
|
return ids || value;
|
|
1139
1151
|
}
|
|
@@ -1147,104 +1159,40 @@ var editorTextToCellValue = (props, value) => {
|
|
|
1147
1159
|
}
|
|
1148
1160
|
};
|
|
1149
1161
|
|
|
1150
|
-
// src/model/modal-controller.ts
|
|
1151
|
-
import { signal as signal4 } from "@preact/signals-core";
|
|
1152
|
-
var ModalController = class {
|
|
1153
|
-
_state = signal4({
|
|
1154
|
-
type: "closed"
|
|
1155
|
-
});
|
|
1156
|
-
_triggerRef = {
|
|
1157
|
-
current: null
|
|
1158
|
-
};
|
|
1159
|
-
get state() {
|
|
1160
|
-
return this._state;
|
|
1161
|
-
}
|
|
1162
|
-
get trigger() {
|
|
1163
|
-
return this._triggerRef;
|
|
1164
|
-
}
|
|
1165
|
-
setTrigger = (trigger) => {
|
|
1166
|
-
this._triggerRef.current = trigger;
|
|
1167
|
-
};
|
|
1168
|
-
showRowMenu = (rowIndex) => {
|
|
1169
|
-
this._state.value = {
|
|
1170
|
-
type: "row",
|
|
1171
|
-
rowIndex
|
|
1172
|
-
};
|
|
1173
|
-
};
|
|
1174
|
-
showColumnMenu = (fieldId) => {
|
|
1175
|
-
this._state.value = {
|
|
1176
|
-
type: "column",
|
|
1177
|
-
fieldId
|
|
1178
|
-
};
|
|
1179
|
-
};
|
|
1180
|
-
showColumnCreator = () => {
|
|
1181
|
-
this._state.value = {
|
|
1182
|
-
type: "columnSettings",
|
|
1183
|
-
mode: {
|
|
1184
|
-
type: "create"
|
|
1185
|
-
}
|
|
1186
|
-
};
|
|
1187
|
-
};
|
|
1188
|
-
showReferencePanel = (targetId, schemaId) => {
|
|
1189
|
-
this._state.value = {
|
|
1190
|
-
type: "refPanel",
|
|
1191
|
-
targetId,
|
|
1192
|
-
typename: schemaId
|
|
1193
|
-
};
|
|
1194
|
-
};
|
|
1195
|
-
openColumnSettings = () => {
|
|
1196
|
-
if (this._state.value.type === "column") {
|
|
1197
|
-
const fieldId = this._state.value.fieldId;
|
|
1198
|
-
requestAnimationFrame(() => {
|
|
1199
|
-
this._state.value = {
|
|
1200
|
-
type: "columnSettings",
|
|
1201
|
-
mode: {
|
|
1202
|
-
type: "edit",
|
|
1203
|
-
fieldId
|
|
1204
|
-
}
|
|
1205
|
-
};
|
|
1206
|
-
});
|
|
1207
|
-
}
|
|
1208
|
-
};
|
|
1209
|
-
close = () => {
|
|
1210
|
-
this._state.value = {
|
|
1211
|
-
type: "closed"
|
|
1212
|
-
};
|
|
1213
|
-
};
|
|
1214
|
-
};
|
|
1215
|
-
|
|
1216
1162
|
// src/model/table-presentation.ts
|
|
1217
|
-
import {
|
|
1163
|
+
import { Atom as Atom3 } from "@effect-atom/atom-react";
|
|
1218
1164
|
import * as Predicate from "effect/Predicate";
|
|
1219
|
-
import { Obj as
|
|
1220
|
-
import {
|
|
1221
|
-
import { cellClassesForFieldType, formatForDisplay
|
|
1165
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
1166
|
+
import { Format as Format3, TypeEnum, getValue as getValue2 } from "@dxos/echo/internal";
|
|
1167
|
+
import { cellClassesForFieldType, formatForDisplay } from "@dxos/react-ui-form";
|
|
1222
1168
|
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
1223
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
1224
1169
|
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1170
|
+
import { mx } from "@dxos/ui-theme";
|
|
1225
1171
|
var TablePresentation = class {
|
|
1226
1172
|
model;
|
|
1173
|
+
_registry;
|
|
1227
1174
|
_visibleRange;
|
|
1228
1175
|
fieldProjectionCache = /* @__PURE__ */ new Map();
|
|
1229
|
-
constructor(
|
|
1230
|
-
start: {
|
|
1231
|
-
row: 0,
|
|
1232
|
-
col: 0
|
|
1233
|
-
},
|
|
1234
|
-
end: {
|
|
1235
|
-
row: 0,
|
|
1236
|
-
col: 0
|
|
1237
|
-
}
|
|
1238
|
-
})) {
|
|
1176
|
+
constructor(registry, model) {
|
|
1239
1177
|
this.model = model;
|
|
1240
|
-
this.
|
|
1178
|
+
this._registry = registry;
|
|
1179
|
+
this._visibleRange = Atom3.make({
|
|
1180
|
+
start: {
|
|
1181
|
+
row: 0,
|
|
1182
|
+
col: 0
|
|
1183
|
+
},
|
|
1184
|
+
end: {
|
|
1185
|
+
row: 0,
|
|
1186
|
+
col: 0
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1241
1189
|
}
|
|
1242
1190
|
getCells(range, plane) {
|
|
1243
1191
|
this.fieldProjectionCache.clear();
|
|
1244
1192
|
let cells;
|
|
1245
1193
|
switch (plane) {
|
|
1246
1194
|
case "grid":
|
|
1247
|
-
this._visibleRange
|
|
1195
|
+
this._registry.set(this._visibleRange, range);
|
|
1248
1196
|
cells = this.getMainGridCells(range);
|
|
1249
1197
|
break;
|
|
1250
1198
|
case "frozenRowsStart":
|
|
@@ -1296,7 +1244,7 @@ var TablePresentation = class {
|
|
|
1296
1244
|
const { props } = this.getFieldProjection(field.id);
|
|
1297
1245
|
const cell = {
|
|
1298
1246
|
get value() {
|
|
1299
|
-
const value =
|
|
1247
|
+
const value = getValue2(obj, field.path);
|
|
1300
1248
|
if (value == null) {
|
|
1301
1249
|
return "";
|
|
1302
1250
|
}
|
|
@@ -1304,19 +1252,19 @@ var TablePresentation = class {
|
|
|
1304
1252
|
return "";
|
|
1305
1253
|
}
|
|
1306
1254
|
switch (props.format) {
|
|
1307
|
-
case
|
|
1308
|
-
case
|
|
1309
|
-
case
|
|
1255
|
+
case Format3.TypeFormat.Boolean:
|
|
1256
|
+
case Format3.TypeFormat.SingleSelect:
|
|
1257
|
+
case Format3.TypeFormat.MultiSelect: {
|
|
1310
1258
|
return "";
|
|
1311
1259
|
}
|
|
1312
|
-
case
|
|
1260
|
+
case Format3.TypeFormat.Ref: {
|
|
1313
1261
|
if (!field.referencePath) {
|
|
1314
1262
|
return "";
|
|
1315
1263
|
}
|
|
1316
|
-
return
|
|
1264
|
+
return getValue2(value.target, field.referencePath);
|
|
1317
1265
|
}
|
|
1318
1266
|
default: {
|
|
1319
|
-
return
|
|
1267
|
+
return formatForDisplay({
|
|
1320
1268
|
type: props.type,
|
|
1321
1269
|
format: props.format,
|
|
1322
1270
|
value
|
|
@@ -1335,8 +1283,8 @@ var TablePresentation = class {
|
|
|
1335
1283
|
classes.push(rowSelectionClasses);
|
|
1336
1284
|
}
|
|
1337
1285
|
cell.className = mx(classes);
|
|
1338
|
-
if (props.type ===
|
|
1339
|
-
const targetArray =
|
|
1286
|
+
if (props.type === TypeEnum.Array) {
|
|
1287
|
+
const targetArray = getValue2(obj, field.path);
|
|
1340
1288
|
if (targetArray && Array.isArray(targetArray)) {
|
|
1341
1289
|
const getLabel = (value) => {
|
|
1342
1290
|
if (!value) {
|
|
@@ -1362,15 +1310,15 @@ var TablePresentation = class {
|
|
|
1362
1310
|
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
|
|
1363
1311
|
}
|
|
1364
1312
|
}
|
|
1365
|
-
if (props.format ===
|
|
1366
|
-
const targetObj =
|
|
1313
|
+
if (props.format === Format3.TypeFormat.Ref && props.referenceSchema) {
|
|
1314
|
+
const targetObj = getValue2(obj, field.path)?.target;
|
|
1367
1315
|
if (targetObj) {
|
|
1368
|
-
const dxn =
|
|
1316
|
+
const dxn = Obj2.getDXN(targetObj)?.toString();
|
|
1369
1317
|
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>`;
|
|
1370
1318
|
}
|
|
1371
1319
|
}
|
|
1372
|
-
if (props.format ===
|
|
1373
|
-
const value =
|
|
1320
|
+
if (props.format === Format3.TypeFormat.Boolean) {
|
|
1321
|
+
const value = getValue2(obj, field.path);
|
|
1374
1322
|
cell.accessoryHtml = tableControls.switch.render({
|
|
1375
1323
|
colIndex,
|
|
1376
1324
|
rowIndex: displayIndex,
|
|
@@ -1378,8 +1326,8 @@ var TablePresentation = class {
|
|
|
1378
1326
|
});
|
|
1379
1327
|
cell.readonly = "no-text-select";
|
|
1380
1328
|
}
|
|
1381
|
-
if (props.format ===
|
|
1382
|
-
const value =
|
|
1329
|
+
if (props.format === Format3.TypeFormat.SingleSelect) {
|
|
1330
|
+
const value = getValue2(obj, field.path);
|
|
1383
1331
|
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1384
1332
|
if (options) {
|
|
1385
1333
|
const option = options.find((o) => o.id === value);
|
|
@@ -1388,8 +1336,8 @@ var TablePresentation = class {
|
|
|
1388
1336
|
}
|
|
1389
1337
|
}
|
|
1390
1338
|
}
|
|
1391
|
-
if (props.format ===
|
|
1392
|
-
const values =
|
|
1339
|
+
if (props.format === Format3.TypeFormat.MultiSelect) {
|
|
1340
|
+
const values = getValue2(obj, field.path);
|
|
1393
1341
|
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1394
1342
|
if (options && values && values.length > 0) {
|
|
1395
1343
|
const tags = values.map((value) => {
|
|
@@ -1412,22 +1360,22 @@ var TablePresentation = class {
|
|
|
1412
1360
|
}
|
|
1413
1361
|
getMainGridCells(range) {
|
|
1414
1362
|
const cells = {};
|
|
1415
|
-
const fields = this.model.projection?.
|
|
1363
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1416
1364
|
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1417
1365
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1418
1366
|
const field = fields[col];
|
|
1419
1367
|
if (!field) {
|
|
1420
1368
|
continue;
|
|
1421
1369
|
}
|
|
1422
|
-
this.createDataCell(cells, this.model.
|
|
1370
|
+
this.createDataCell(cells, this.model.getRows()[row], field, col, row);
|
|
1423
1371
|
}
|
|
1424
1372
|
}
|
|
1425
1373
|
return cells;
|
|
1426
1374
|
}
|
|
1427
1375
|
getDraftRowCells(range) {
|
|
1428
1376
|
const cells = {};
|
|
1429
|
-
const fields = this.model.projection?.
|
|
1430
|
-
const draftRows = this.model.
|
|
1377
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1378
|
+
const draftRows = this.model.getDraftRows();
|
|
1431
1379
|
if (draftRows.length === 0) {
|
|
1432
1380
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1433
1381
|
cells[toPlaneCellIndex({
|
|
@@ -1467,11 +1415,11 @@ var TablePresentation = class {
|
|
|
1467
1415
|
}
|
|
1468
1416
|
getHeaderCells(range) {
|
|
1469
1417
|
const cells = {};
|
|
1470
|
-
const fields = this.model.projection?.
|
|
1418
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1419
|
+
const currentSort = this.model.getSorting();
|
|
1471
1420
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1472
1421
|
const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
|
|
1473
|
-
const
|
|
1474
|
-
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1422
|
+
const direction = currentSort?.fieldId === field.id ? currentSort.direction : void 0;
|
|
1475
1423
|
cells[toPlaneCellIndex({
|
|
1476
1424
|
col,
|
|
1477
1425
|
row: 0
|
|
@@ -1554,7 +1502,7 @@ var TablePresentation = class {
|
|
|
1554
1502
|
accessoryHtml: tableControls.checkbox.render({
|
|
1555
1503
|
rowIndex: 0,
|
|
1556
1504
|
header: true,
|
|
1557
|
-
checked: this.model.selection.
|
|
1505
|
+
checked: this.model.selection.allRowsSelected
|
|
1558
1506
|
}),
|
|
1559
1507
|
className: "!bg-toolbarSurface",
|
|
1560
1508
|
readonly: true,
|
|
@@ -1569,7 +1517,7 @@ var TablePresentation = class {
|
|
|
1569
1517
|
row: 0
|
|
1570
1518
|
})]: {
|
|
1571
1519
|
accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
|
|
1572
|
-
disabled: (this.model.projection?.
|
|
1520
|
+
disabled: (this.model.projection?.getFields()?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1573
1521
|
}) : void 0,
|
|
1574
1522
|
className: "!bg-toolbarSurface",
|
|
1575
1523
|
readonly: true,
|
|
@@ -1579,7 +1527,7 @@ var TablePresentation = class {
|
|
|
1579
1527
|
}
|
|
1580
1528
|
getDraftActionCells(range) {
|
|
1581
1529
|
const cells = {};
|
|
1582
|
-
const draftRows = this.model.
|
|
1530
|
+
const draftRows = this.model.getDraftRows();
|
|
1583
1531
|
if (draftRows.length === 0) {
|
|
1584
1532
|
cells[toPlaneCellIndex({
|
|
1585
1533
|
col: 0,
|
|
@@ -1610,7 +1558,7 @@ var TablePresentation = class {
|
|
|
1610
1558
|
}
|
|
1611
1559
|
getDraftIconCells(range) {
|
|
1612
1560
|
const cells = {};
|
|
1613
|
-
const draftRows = this.model.
|
|
1561
|
+
const draftRows = this.model.getDraftRows();
|
|
1614
1562
|
for (let row = range.start.row; row <= range.end.row; row++) {
|
|
1615
1563
|
cells[toPlaneCellIndex({
|
|
1616
1564
|
col: 0,
|
|
@@ -1647,102 +1595,14 @@ var cellClassesForRowSelection = (selected, selectionMode) => {
|
|
|
1647
1595
|
}
|
|
1648
1596
|
};
|
|
1649
1597
|
|
|
1650
|
-
// src/hooks/useTableModel.ts
|
|
1651
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
1652
|
-
import { effect as effect3 } from "@preact/signals-core";
|
|
1653
|
-
import orderBy2 from "lodash.orderby";
|
|
1654
|
-
import { useEffect, useMemo, useState } from "react";
|
|
1655
|
-
import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
|
|
1656
|
-
import { useSelected, useSelectionActions } from "@dxos/react-ui-attention";
|
|
1657
|
-
import { isNonNullable } from "@dxos/util";
|
|
1658
|
-
var useTableModel = ({ view, schema, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
1659
|
-
var _effect = _useSignals();
|
|
1660
|
-
try {
|
|
1661
|
-
const selected = useSelected(view && fullyQualifiedId2(view), "multi");
|
|
1662
|
-
const initialSelection = useMemo(() => selected, [
|
|
1663
|
-
view
|
|
1664
|
-
]);
|
|
1665
|
-
const [model, setModel] = useState();
|
|
1666
|
-
useEffect(() => {
|
|
1667
|
-
if (!view || !schema) {
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
let model2;
|
|
1671
|
-
const t = setTimeout(async () => {
|
|
1672
|
-
model2 = new TableModel({
|
|
1673
|
-
view,
|
|
1674
|
-
schema,
|
|
1675
|
-
projection,
|
|
1676
|
-
features,
|
|
1677
|
-
rowActions,
|
|
1678
|
-
initialSelection,
|
|
1679
|
-
onRowAction,
|
|
1680
|
-
...props
|
|
1681
|
-
});
|
|
1682
|
-
await model2.open();
|
|
1683
|
-
setModel(model2);
|
|
1684
|
-
});
|
|
1685
|
-
return () => {
|
|
1686
|
-
clearTimeout(t);
|
|
1687
|
-
void model2?.close();
|
|
1688
|
-
};
|
|
1689
|
-
}, [
|
|
1690
|
-
view,
|
|
1691
|
-
schema,
|
|
1692
|
-
projection,
|
|
1693
|
-
features,
|
|
1694
|
-
rowActions,
|
|
1695
|
-
initialSelection
|
|
1696
|
-
]);
|
|
1697
|
-
useEffect(() => {
|
|
1698
|
-
if (rows) {
|
|
1699
|
-
const sortedRows = orderBy2(rows, [
|
|
1700
|
-
(row) => String(row.id)
|
|
1701
|
-
], [
|
|
1702
|
-
"asc"
|
|
1703
|
-
]);
|
|
1704
|
-
model?.setRows(sortedRows);
|
|
1705
|
-
}
|
|
1706
|
-
}, [
|
|
1707
|
-
model,
|
|
1708
|
-
rows
|
|
1709
|
-
]);
|
|
1710
|
-
const { multiSelect, clear } = useSelectionActions([
|
|
1711
|
-
model?.id
|
|
1712
|
-
].filter(isNonNullable));
|
|
1713
|
-
useEffect(() => {
|
|
1714
|
-
if (!model) {
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
const unsubscribe = effect3(() => {
|
|
1718
|
-
const selectedItems = [
|
|
1719
|
-
...model.selection.selection.value
|
|
1720
|
-
];
|
|
1721
|
-
multiSelect(selectedItems);
|
|
1722
|
-
onSelectionChanged?.(selectedItems);
|
|
1723
|
-
});
|
|
1724
|
-
return () => {
|
|
1725
|
-
clear();
|
|
1726
|
-
unsubscribe();
|
|
1727
|
-
};
|
|
1728
|
-
}, [
|
|
1729
|
-
model,
|
|
1730
|
-
onSelectionChanged
|
|
1731
|
-
]);
|
|
1732
|
-
return model;
|
|
1733
|
-
} finally {
|
|
1734
|
-
_effect.f();
|
|
1735
|
-
}
|
|
1736
|
-
};
|
|
1737
|
-
|
|
1738
1598
|
// src/hooks/useAddRow.ts
|
|
1739
1599
|
import { useCallback } from "react";
|
|
1740
|
-
import { Obj as
|
|
1741
|
-
var useAddRow = ({
|
|
1600
|
+
import { Obj as Obj3 } from "@dxos/echo";
|
|
1601
|
+
var useAddRow = ({ db, schema }) => {
|
|
1742
1602
|
return useCallback((data) => {
|
|
1743
|
-
if (
|
|
1603
|
+
if (db && schema) {
|
|
1744
1604
|
try {
|
|
1745
|
-
|
|
1605
|
+
db.add(Obj3.make(schema, data ?? {}));
|
|
1746
1606
|
return "final";
|
|
1747
1607
|
} catch (error) {
|
|
1748
1608
|
return "draft";
|
|
@@ -1750,27 +1610,137 @@ var useAddRow = ({ space, schema }) => {
|
|
|
1750
1610
|
}
|
|
1751
1611
|
return "final";
|
|
1752
1612
|
}, [
|
|
1753
|
-
|
|
1613
|
+
db,
|
|
1754
1614
|
schema
|
|
1755
1615
|
]);
|
|
1756
1616
|
};
|
|
1757
1617
|
|
|
1618
|
+
// src/hooks/useProjectionModel.ts
|
|
1619
|
+
import { useState } from "react";
|
|
1620
|
+
import { Type } from "@dxos/echo";
|
|
1621
|
+
import { useAsyncEffect } from "@dxos/react-ui";
|
|
1622
|
+
import { ProjectionModel, createEchoChangeCallback as createEchoChangeCallback2 } from "@dxos/schema";
|
|
1623
|
+
var useProjectionModel = (schema, table, registry) => {
|
|
1624
|
+
const [projection, setProjection] = useState();
|
|
1625
|
+
useAsyncEffect(async () => {
|
|
1626
|
+
if (schema && table) {
|
|
1627
|
+
const view = await table.view.load();
|
|
1628
|
+
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : Type.toJsonSchema(schema);
|
|
1629
|
+
const change = createEchoChangeCallback2(view, Type.isMutable(schema) ? schema : void 0);
|
|
1630
|
+
const projection2 = new ProjectionModel({
|
|
1631
|
+
registry,
|
|
1632
|
+
view,
|
|
1633
|
+
baseSchema: jsonSchema,
|
|
1634
|
+
change
|
|
1635
|
+
});
|
|
1636
|
+
projection2.normalizeView();
|
|
1637
|
+
setProjection(projection2);
|
|
1638
|
+
}
|
|
1639
|
+
}, [
|
|
1640
|
+
schema,
|
|
1641
|
+
table,
|
|
1642
|
+
registry
|
|
1643
|
+
]);
|
|
1644
|
+
return projection;
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
// src/hooks/useTableModel.ts
|
|
1648
|
+
import { RegistryContext } from "@effect-atom/atom-react";
|
|
1649
|
+
import { useContext, useEffect, useMemo, useState as useState2 } from "react";
|
|
1650
|
+
import { Obj as Obj4 } from "@dxos/echo";
|
|
1651
|
+
import { useSelected, useSelectionActions } from "@dxos/react-ui-attention";
|
|
1652
|
+
import { isNonNullable } from "@dxos/util";
|
|
1653
|
+
var useTableModel = ({ object, projection, db, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
1654
|
+
const registry = useContext(RegistryContext);
|
|
1655
|
+
const selected = useSelected(object && Obj4.getDXN(object).toString(), "multi");
|
|
1656
|
+
const initialSelection = useMemo(() => selected, [
|
|
1657
|
+
object
|
|
1658
|
+
]);
|
|
1659
|
+
const [model, setModel] = useState2();
|
|
1660
|
+
useEffect(() => {
|
|
1661
|
+
if (!object || !projection) {
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
let model2;
|
|
1665
|
+
const t = setTimeout(async () => {
|
|
1666
|
+
model2 = new TableModel({
|
|
1667
|
+
registry,
|
|
1668
|
+
object,
|
|
1669
|
+
projection,
|
|
1670
|
+
db,
|
|
1671
|
+
change: createEchoChangeCallback(object),
|
|
1672
|
+
features,
|
|
1673
|
+
rowActions,
|
|
1674
|
+
initialSelection,
|
|
1675
|
+
onRowAction,
|
|
1676
|
+
...props
|
|
1677
|
+
});
|
|
1678
|
+
await model2.open();
|
|
1679
|
+
setModel(model2);
|
|
1680
|
+
});
|
|
1681
|
+
return () => {
|
|
1682
|
+
clearTimeout(t);
|
|
1683
|
+
void model2?.close();
|
|
1684
|
+
};
|
|
1685
|
+
}, [
|
|
1686
|
+
registry,
|
|
1687
|
+
object,
|
|
1688
|
+
projection,
|
|
1689
|
+
features,
|
|
1690
|
+
rowActions,
|
|
1691
|
+
initialSelection
|
|
1692
|
+
]);
|
|
1693
|
+
useEffect(() => {
|
|
1694
|
+
if (rows && model) {
|
|
1695
|
+
model.setRows(rows);
|
|
1696
|
+
}
|
|
1697
|
+
}, [
|
|
1698
|
+
model,
|
|
1699
|
+
rows
|
|
1700
|
+
]);
|
|
1701
|
+
const { multiSelect, clear } = useSelectionActions([
|
|
1702
|
+
model?.id
|
|
1703
|
+
].filter(isNonNullable));
|
|
1704
|
+
useEffect(() => {
|
|
1705
|
+
if (!model) {
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
const unsubscribe = registry.subscribe(model.selection.selectionAtom, () => {
|
|
1709
|
+
const selectedItems = [
|
|
1710
|
+
...model.selection.selection
|
|
1711
|
+
];
|
|
1712
|
+
multiSelect(selectedItems);
|
|
1713
|
+
onSelectionChanged?.(selectedItems);
|
|
1714
|
+
});
|
|
1715
|
+
return () => {
|
|
1716
|
+
clear();
|
|
1717
|
+
unsubscribe();
|
|
1718
|
+
};
|
|
1719
|
+
}, [
|
|
1720
|
+
registry,
|
|
1721
|
+
model,
|
|
1722
|
+
onSelectionChanged
|
|
1723
|
+
]);
|
|
1724
|
+
return model;
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1758
1727
|
export {
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1728
|
+
extractOrder,
|
|
1729
|
+
getSortValue,
|
|
1730
|
+
compareValues,
|
|
1762
1731
|
BUTTON_IDENTIFIERS,
|
|
1763
1732
|
tableButtons,
|
|
1764
1733
|
CONTROL_IDENTIFIERS,
|
|
1765
1734
|
CheckboxStory,
|
|
1766
1735
|
SwitchStory,
|
|
1767
1736
|
tableControls,
|
|
1768
|
-
|
|
1737
|
+
createEchoChangeCallback,
|
|
1738
|
+
createDirectChangeCallback,
|
|
1769
1739
|
TableModel,
|
|
1770
|
-
ModalController,
|
|
1771
1740
|
TablePresentation,
|
|
1772
1741
|
cellClassesForRowSelection,
|
|
1773
|
-
|
|
1774
|
-
|
|
1742
|
+
useAddRow,
|
|
1743
|
+
useProjectionModel,
|
|
1744
|
+
useTableModel
|
|
1775
1745
|
};
|
|
1776
|
-
//# sourceMappingURL=chunk-
|
|
1746
|
+
//# sourceMappingURL=chunk-I5IFW7UF.mjs.map
|