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