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