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