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