@dxos/react-ui-table 0.8.4-main.3c1ae3b → 0.8.4-main.3fbcb4aa9b
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-CJQ6T4LL.mjs → chunk-FBURZBPH.mjs} +19 -26
- package/dist/lib/browser/chunk-FBURZBPH.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/{chunk-V7A7ZA5E.mjs → chunk-YGC7LZJN.mjs} +611 -699
- package/dist/lib/browser/chunk-YGC7LZJN.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1105 -1032
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +23 -18
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/translations.mjs +36 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -1
- package/dist/lib/node-esm/{chunk-T6PXZQ6W.mjs → chunk-DKKMSVKP.mjs} +19 -26
- package/dist/lib/node-esm/chunk-DKKMSVKP.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-P73ALX3N.mjs → chunk-GKIWDEZ7.mjs} +611 -698
- package/dist/lib/node-esm/chunk-GKIWDEZ7.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1105 -1032
- 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 +23 -18
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/translations.mjs +37 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -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 +5 -4
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +21 -23
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +84 -84
- 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 +20 -21
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +86 -86
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +17 -0
- package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +3 -4
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +2 -2
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +23 -25
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.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/index.d.ts +0 -2
- package/dist/types/src/index.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 +18 -9
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +100 -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/playwright/playwright.config.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 +21 -23
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +13 -15
- package/dist/types/src/types/Table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +11 -8
- 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/schema.d.ts.map +1 -1
- package/dist/types/src/util/signals.d.ts.map +1 -1
- package/dist/types/src/util/sort.d.ts +12 -0
- package/dist/types/src/util/sort.d.ts.map +1 -0
- package/dist/types/src/util/table-buttons.d.ts +20 -20
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +4 -4
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/tag.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +66 -76
- package/src/components/Table/ColumnActionsMenu.tsx +13 -11
- package/src/components/Table/ColumnSettings.tsx +7 -7
- package/src/components/Table/DynamicTable.stories.tsx +24 -22
- package/src/components/Table/DynamicTable.tsx +28 -36
- package/src/components/Table/Relations.stories.tsx +95 -47
- package/src/components/Table/RowActionsMenu.tsx +6 -4
- package/src/components/Table/Table.stories.tsx +87 -64
- package/src/components/Table/Table.tsx +42 -419
- package/src/components/Table/TableContent.tsx +421 -0
- package/src/components/{TableToolbar → Table}/TableToolbar.tsx +44 -45
- package/src/components/TableCellEditor/CellValidationMessage.tsx +4 -5
- package/src/components/TableCellEditor/FormCellEditor.tsx +61 -70
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +14 -13
- package/src/components/TableCellEditor/TableCellEditor.tsx +14 -12
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +42 -16
- package/src/hooks/useAddRow.ts +8 -10
- package/src/hooks/useProjectionModel.ts +29 -9
- package/src/hooks/useTableModel.ts +27 -23
- package/src/index.ts +0 -4
- package/src/model/modal-controller.ts +23 -12
- package/src/model/selection-model.ts +75 -44
- package/src/model/table-model.test.ts +81 -54
- package/src/model/table-model.ts +411 -139
- package/src/model/table-presentation.test.ts +58 -49
- package/src/model/table-presentation.ts +34 -29
- package/src/playwright/TableManager.ts +10 -3
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +51 -7
- package/src/testing/useTestTableModel.ts +25 -22
- package/src/translations.ts +20 -22
- package/src/types/Table.ts +19 -30
- package/src/util/dynamic-table.test.ts +70 -0
- package/src/util/dynamic-table.ts +36 -17
- package/src/util/index.ts +2 -0
- package/src/util/query-ast.ts +22 -0
- package/src/util/sort.ts +90 -0
- package/src/util/table-buttons.ts +1 -1
- package/src/util/table-controls.ts +2 -2
- 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/components/TableToolbar/TableToolbar.d.ts +0 -21
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
- package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
- 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/components/TableToolbar/index.ts +0 -5
- package/src/model/table-sorting.ts +0 -234
|
@@ -1,85 +1,65 @@
|
|
|
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
|
+
if (queryAst.type === "from") {
|
|
10
|
+
return extractOrder(queryAst.query);
|
|
11
|
+
}
|
|
12
|
+
return void 0;
|
|
28
13
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
}
|
|
14
|
+
|
|
15
|
+
// src/util/sort.ts
|
|
16
|
+
import { Format } from "@dxos/echo";
|
|
17
|
+
var getSortValue = (value, format) => {
|
|
18
|
+
if (value === void 0 || value === null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const isDateFormat = format === Format.TypeFormat.DateTime || format === Format.TypeFormat.Date;
|
|
22
|
+
if (isDateFormat) {
|
|
23
|
+
const date = new Date(value);
|
|
24
|
+
if (!isNaN(date.getTime())) {
|
|
25
|
+
return date.getTime();
|
|
26
|
+
}
|
|
27
|
+
return String(value);
|
|
28
|
+
}
|
|
29
|
+
if (format === Format.TypeFormat.Number || format === Format.TypeFormat.Integer || format === Format.TypeFormat.Currency || format === Format.TypeFormat.Percent || format === Format.TypeFormat.Duration) {
|
|
30
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
31
|
+
if (!isNaN(num)) {
|
|
32
|
+
return num;
|
|
77
33
|
}
|
|
34
|
+
return String(value);
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === "string") {
|
|
37
|
+
return value;
|
|
78
38
|
}
|
|
39
|
+
if (typeof value === "number") {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
return String(value);
|
|
43
|
+
};
|
|
44
|
+
var compareValues = (aValue, bValue, format, direction) => {
|
|
45
|
+
if (aValue === void 0 || aValue === null) {
|
|
46
|
+
return bValue === void 0 || bValue === null ? 0 : 1;
|
|
47
|
+
}
|
|
48
|
+
if (bValue === void 0 || bValue === null) {
|
|
49
|
+
return -1;
|
|
50
|
+
}
|
|
51
|
+
const aSortValue = getSortValue(aValue, format);
|
|
52
|
+
const bSortValue = getSortValue(bValue, format);
|
|
53
|
+
let comparison = 0;
|
|
54
|
+
if (typeof aSortValue === "number" && typeof bSortValue === "number") {
|
|
55
|
+
comparison = aSortValue - bSortValue;
|
|
56
|
+
} else if (typeof aSortValue === "string" && typeof bSortValue === "string") {
|
|
57
|
+
comparison = aSortValue.localeCompare(bSortValue);
|
|
58
|
+
} else {
|
|
59
|
+
comparison = String(aSortValue).localeCompare(String(bSortValue));
|
|
60
|
+
}
|
|
61
|
+
return direction === "desc" ? -comparison : comparison;
|
|
79
62
|
};
|
|
80
|
-
|
|
81
|
-
// src/util/signals.ts
|
|
82
|
-
var touch = (value) => value;
|
|
83
63
|
|
|
84
64
|
// src/util/table-buttons.ts
|
|
85
65
|
var BUTTON_IDENTIFIERS = {
|
|
@@ -92,7 +72,7 @@ var BUTTON_IDENTIFIERS = {
|
|
|
92
72
|
};
|
|
93
73
|
var createButton = ({ attr, data, disabled = false, icon, testId, type: _type = "primary" }) => {
|
|
94
74
|
const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
95
|
-
return `<button ${attr} data-testid="${testId}" class="dx-button
|
|
75
|
+
return `<button ${attr} data-testid="${testId}" class="dx-button w-6 aspect-square px-0.5 min-h-0" ${dataAttrs} ${disabled ? "disabled" : ""} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
96
76
|
};
|
|
97
77
|
var addColumnButton = {
|
|
98
78
|
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
@@ -205,8 +185,8 @@ var CONTROL_IDENTIFIERS = {
|
|
|
205
185
|
switch: "data-table-switch"
|
|
206
186
|
};
|
|
207
187
|
var BASE_CLASSES = {
|
|
208
|
-
checkbox: "absolute inset-
|
|
209
|
-
switch: "absolute inset-
|
|
188
|
+
checkbox: "absolute inset-y-[.375rem] end-[.375rem] dx-checkbox",
|
|
189
|
+
switch: "absolute inset-y-[.25rem] end-[.25rem] dx-checkbox--switch"
|
|
210
190
|
};
|
|
211
191
|
var renderAttributes = (data) => {
|
|
212
192
|
return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
@@ -254,29 +234,15 @@ var tableControls = {
|
|
|
254
234
|
}
|
|
255
235
|
};
|
|
256
236
|
|
|
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
237
|
// src/model/table-model.ts
|
|
273
|
-
import {
|
|
238
|
+
import { Atom as Atom2 } from "@effect-atom/atom-react";
|
|
274
239
|
import { Resource as Resource2 } from "@dxos/context";
|
|
275
|
-
import { Format as Format2, Obj
|
|
276
|
-
import {
|
|
240
|
+
import { Format as Format2, Obj, Order, Query, Ref } from "@dxos/echo";
|
|
241
|
+
import { toEffectSchema } from "@dxos/echo/internal";
|
|
242
|
+
import { getSnapshot } from "@dxos/echo/internal";
|
|
243
|
+
import { getValue, setValue } from "@dxos/effect";
|
|
277
244
|
import { invariant } from "@dxos/invariant";
|
|
278
245
|
import { ObjectId } from "@dxos/keys";
|
|
279
|
-
import { getSnapshot, isLiveObject } from "@dxos/live-object";
|
|
280
246
|
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
281
247
|
import { validateSchema } from "@dxos/schema";
|
|
282
248
|
|
|
@@ -297,75 +263,99 @@ var extractTagIds = (value) => {
|
|
|
297
263
|
};
|
|
298
264
|
|
|
299
265
|
// src/model/selection-model.ts
|
|
300
|
-
import {
|
|
266
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
301
267
|
import { Resource } from "@dxos/context";
|
|
302
268
|
var SelectionModel = class extends Resource {
|
|
269
|
+
_registry;
|
|
303
270
|
_rows;
|
|
271
|
+
_selection;
|
|
272
|
+
_validSelectedIds;
|
|
273
|
+
_hasSelection;
|
|
274
|
+
_allSelected;
|
|
304
275
|
_selectionMode;
|
|
305
|
-
_initialSelection;
|
|
306
276
|
_onSelectionChanged;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
277
|
+
constructor(registry, rows, selectionMode, initialSelection, onSelectionChanged) {
|
|
278
|
+
super();
|
|
279
|
+
this._registry = registry;
|
|
280
|
+
this._rows = rows;
|
|
281
|
+
this._selectionMode = selectionMode;
|
|
282
|
+
this._onSelectionChanged = onSelectionChanged;
|
|
283
|
+
this._selection = Atom.make(new Set(initialSelection));
|
|
284
|
+
this._validSelectedIds = Atom.make((get) => {
|
|
285
|
+
const rows2 = get(this._rows);
|
|
286
|
+
if (!rows2) {
|
|
287
|
+
return /* @__PURE__ */ new Set();
|
|
288
|
+
}
|
|
289
|
+
const validIds = new Set(rows2.map((row) => row.id));
|
|
290
|
+
const selection = get(this._selection);
|
|
291
|
+
return new Set([
|
|
292
|
+
...selection
|
|
293
|
+
].filter((id) => validIds.has(id)));
|
|
294
|
+
});
|
|
295
|
+
this._hasSelection = Atom.make((get) => get(this._validSelectedIds).size > 0);
|
|
296
|
+
this._allSelected = Atom.make((get) => {
|
|
297
|
+
const rows2 = get(this._rows);
|
|
298
|
+
if (rows2.length === 0) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const selection = get(this._selection);
|
|
302
|
+
return rows2.every((row) => selection.has(row.id));
|
|
303
|
+
});
|
|
329
304
|
}
|
|
330
305
|
async _open() {
|
|
331
|
-
const
|
|
332
|
-
touch(this._selection.value);
|
|
306
|
+
const selectionUnsubscribe = this._registry.subscribe(this._selection, () => {
|
|
333
307
|
this._onSelectionChanged?.();
|
|
334
308
|
});
|
|
335
|
-
this._ctx.onDispose(
|
|
309
|
+
this._ctx.onDispose(selectionUnsubscribe);
|
|
336
310
|
}
|
|
337
311
|
//
|
|
338
312
|
// Getters
|
|
339
313
|
//
|
|
340
|
-
|
|
314
|
+
/** Get the selection atom for reactive access. */
|
|
315
|
+
get selectionAtom() {
|
|
341
316
|
return this._selection;
|
|
342
317
|
}
|
|
343
|
-
|
|
318
|
+
/** Get the current selection value. */
|
|
319
|
+
get selection() {
|
|
320
|
+
return this._registry.get(this._selection);
|
|
321
|
+
}
|
|
322
|
+
/** Get the hasSelection atom for reactive access. */
|
|
323
|
+
get hasSelectionAtom() {
|
|
344
324
|
return this._hasSelection;
|
|
345
325
|
}
|
|
346
|
-
|
|
326
|
+
/** Check if there is any selection. */
|
|
327
|
+
get hasSelection() {
|
|
328
|
+
return this._registry.get(this._hasSelection);
|
|
329
|
+
}
|
|
330
|
+
/** Get the allRowsSelected atom for reactive access. */
|
|
331
|
+
get allRowsSelectedAtom() {
|
|
347
332
|
return this._allSelected;
|
|
348
333
|
}
|
|
334
|
+
/** Check if all rows are selected. */
|
|
335
|
+
get allRowsSelected() {
|
|
336
|
+
return this._registry.get(this._allSelected);
|
|
337
|
+
}
|
|
349
338
|
get selectionMode() {
|
|
350
339
|
return this._selectionMode;
|
|
351
340
|
}
|
|
352
341
|
getSelectedRows = () => {
|
|
353
|
-
const selectedIds = this._validSelectedIds
|
|
354
|
-
return this._rows.
|
|
342
|
+
const selectedIds = this._registry.get(this._validSelectedIds);
|
|
343
|
+
return this._registry.get(this._rows).filter((row) => selectedIds.has(row.id));
|
|
355
344
|
};
|
|
356
345
|
isRowIndexSelected = (rowIndex) => {
|
|
357
|
-
const row = this._rows
|
|
358
|
-
return this._selection.
|
|
346
|
+
const row = this._registry.get(this._rows)[rowIndex];
|
|
347
|
+
return this._registry.get(this._selection).has(row.id);
|
|
359
348
|
};
|
|
360
349
|
isObjectSelected = (object) => {
|
|
361
|
-
return this._selection.
|
|
350
|
+
return this._registry.get(this._selection).has(object.id);
|
|
362
351
|
};
|
|
363
352
|
//
|
|
364
353
|
// Manipulation
|
|
365
354
|
//
|
|
366
355
|
toggleSelectionForRowIndex = (rowIndex) => {
|
|
367
|
-
const row = this._rows
|
|
368
|
-
const
|
|
356
|
+
const row = this._registry.get(this._rows)[rowIndex];
|
|
357
|
+
const currentSelection = this._registry.get(this._selection);
|
|
358
|
+
const newSelection = new Set(currentSelection);
|
|
369
359
|
if (newSelection.has(row.id)) {
|
|
370
360
|
newSelection.delete(row.id);
|
|
371
361
|
} else {
|
|
@@ -374,195 +364,38 @@ var SelectionModel = class extends Resource {
|
|
|
374
364
|
}
|
|
375
365
|
newSelection.add(row.id);
|
|
376
366
|
}
|
|
377
|
-
this._selection
|
|
367
|
+
this._registry.set(this._selection, newSelection);
|
|
378
368
|
};
|
|
379
369
|
setSelection = (mode) => {
|
|
380
370
|
switch (mode) {
|
|
381
371
|
case "all": {
|
|
382
|
-
this._selection
|
|
372
|
+
this._registry.set(this._selection, new Set(this._registry.get(this._rows).map((row) => row.id)));
|
|
383
373
|
break;
|
|
384
374
|
}
|
|
385
375
|
case "none": {
|
|
386
|
-
this._selection
|
|
376
|
+
this._registry.set(this._selection, /* @__PURE__ */ new Set());
|
|
387
377
|
break;
|
|
388
378
|
}
|
|
389
379
|
}
|
|
390
380
|
};
|
|
391
381
|
};
|
|
392
382
|
|
|
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
383
|
// src/model/table-model.ts
|
|
565
384
|
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
385
|
+
var createEchoChangeCallback = (table) => ({
|
|
386
|
+
table: (mutate) => Obj.update(table, (table2) => mutate(table2)),
|
|
387
|
+
row: (row, mutate) => {
|
|
388
|
+
if (Obj.isObject(row)) {
|
|
389
|
+
Obj.update(row, (row2) => mutate(row2));
|
|
390
|
+
} else {
|
|
391
|
+
mutate(row);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
var createDirectChangeCallback = (table) => ({
|
|
396
|
+
table: (mutate) => mutate(table),
|
|
397
|
+
row: (row, mutate) => mutate(row)
|
|
398
|
+
});
|
|
566
399
|
var defaultFeatures = {
|
|
567
400
|
selection: {
|
|
568
401
|
enabled: true,
|
|
@@ -572,86 +405,136 @@ var defaultFeatures = {
|
|
|
572
405
|
schemaEditable: false
|
|
573
406
|
};
|
|
574
407
|
var TableModel = class extends Resource2 {
|
|
408
|
+
_registry;
|
|
575
409
|
_object;
|
|
576
410
|
_projection;
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
col: 0
|
|
581
|
-
},
|
|
582
|
-
end: {
|
|
583
|
-
row: 0,
|
|
584
|
-
col: 0
|
|
585
|
-
}
|
|
586
|
-
});
|
|
411
|
+
_db;
|
|
412
|
+
_change;
|
|
413
|
+
_visibleRange;
|
|
587
414
|
_onInsertRow;
|
|
588
415
|
_onDeleteRows;
|
|
589
|
-
|
|
416
|
+
_onColumnDelete;
|
|
590
417
|
_onCellUpdate;
|
|
591
418
|
_onRowOrderChange;
|
|
592
419
|
_onRowAction;
|
|
593
420
|
_rowActions;
|
|
594
421
|
_features;
|
|
595
|
-
_rows
|
|
596
|
-
_draftRows
|
|
422
|
+
_rows;
|
|
423
|
+
_draftRows;
|
|
424
|
+
// In-memory sort state - changes are local until saved.
|
|
425
|
+
_inMemorySort;
|
|
426
|
+
// Derived atom for persisted sort from view.query.ast.
|
|
427
|
+
_persistedSort;
|
|
428
|
+
// Derived atom for current sort (in-memory takes precedence over persisted).
|
|
597
429
|
_sorting;
|
|
430
|
+
// Derived atom for sorted rows (used by rows getter and SelectionModel).
|
|
431
|
+
_sortedRows;
|
|
432
|
+
// Derived atom for viewDirty state.
|
|
433
|
+
_viewDirty;
|
|
598
434
|
_pinnedRows;
|
|
599
435
|
_selection;
|
|
600
436
|
_columnMeta;
|
|
601
|
-
|
|
437
|
+
// Counter atom that increments when cells are updated - allows UI to react to cell changes.
|
|
438
|
+
_cellUpdateCounter;
|
|
439
|
+
constructor({ registry, object, projection, db, change, features = {}, initialSelection = [], pinnedRows = {
|
|
602
440
|
top: [],
|
|
603
441
|
bottom: []
|
|
604
|
-
}, rowActions = [], onCellUpdate,
|
|
442
|
+
}, rowActions = [], onCellUpdate, onColumnDelete, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
|
|
605
443
|
super();
|
|
444
|
+
this._registry = registry;
|
|
606
445
|
this._object = object;
|
|
607
446
|
this._projection = projection;
|
|
608
447
|
this._projection.normalizeView();
|
|
448
|
+
this._db = db;
|
|
449
|
+
this._change = change ?? createEchoChangeCallback(object);
|
|
609
450
|
this._features = {
|
|
610
451
|
...defaultFeatures,
|
|
611
452
|
...features
|
|
612
453
|
};
|
|
613
|
-
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
454
|
+
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 94, S: this, A: ["!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')", "'Single selection is not compatible with editable tables.'"] });
|
|
455
|
+
this._visibleRange = Atom2.make({
|
|
456
|
+
start: {
|
|
457
|
+
row: 0,
|
|
458
|
+
col: 0
|
|
459
|
+
},
|
|
460
|
+
end: {
|
|
461
|
+
row: 0,
|
|
462
|
+
col: 0
|
|
463
|
+
}
|
|
621
464
|
});
|
|
622
|
-
this.
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
465
|
+
this._rows = Atom2.make([]);
|
|
466
|
+
this._draftRows = Atom2.make([]);
|
|
467
|
+
this._inMemorySort = Atom2.make(void 0);
|
|
468
|
+
this._cellUpdateCounter = Atom2.make(0);
|
|
469
|
+
this._persistedSort = Atom2.make((_get) => {
|
|
470
|
+
const viewSnapshot = Obj.getSnapshot(this.view);
|
|
471
|
+
const ast = viewSnapshot.query.ast;
|
|
472
|
+
const orders = extractOrder(ast);
|
|
473
|
+
if (orders && orders.length > 0) {
|
|
474
|
+
const firstOrder = orders[0];
|
|
475
|
+
if (firstOrder.kind === "property") {
|
|
476
|
+
const field = this._projection.getFields().find((f) => f.path === firstOrder.property);
|
|
477
|
+
if (field) {
|
|
478
|
+
return {
|
|
479
|
+
fieldId: field.id,
|
|
480
|
+
direction: firstOrder.direction
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return void 0;
|
|
486
|
+
});
|
|
487
|
+
this._sorting = Atom2.make((get) => {
|
|
488
|
+
const inMemorySort = get(this._inMemorySort);
|
|
489
|
+
return inMemorySort ?? get(this._persistedSort);
|
|
490
|
+
});
|
|
491
|
+
this._sortedRows = Atom2.make((get) => {
|
|
492
|
+
const rows = get(this._rows);
|
|
493
|
+
const sort = get(this._sorting);
|
|
494
|
+
if (!sort || rows.length === 0) {
|
|
495
|
+
return rows;
|
|
496
|
+
}
|
|
497
|
+
const field = this._projection.getFields().find((f) => f.id === sort.fieldId);
|
|
498
|
+
if (!field) {
|
|
499
|
+
return rows;
|
|
500
|
+
}
|
|
501
|
+
const fieldProjection = this._projection.getFieldProjection(field.id);
|
|
502
|
+
const sorted = [
|
|
503
|
+
...rows
|
|
504
|
+
].sort((a, b) => {
|
|
505
|
+
const aValue = getValue(a, field.path);
|
|
506
|
+
const bValue = getValue(b, field.path);
|
|
507
|
+
return compareValues(aValue, bValue, fieldProjection.props.format, sort.direction);
|
|
508
|
+
});
|
|
509
|
+
return sorted;
|
|
510
|
+
});
|
|
511
|
+
this._selection = new SelectionModel(this._registry, this._sortedRows, this._features.selection.mode ?? "multiple", initialSelection, () => this._onRowOrderChange?.());
|
|
512
|
+
this._viewDirty = Atom2.make((get) => {
|
|
513
|
+
const inMemorySort = get(this._inMemorySort);
|
|
514
|
+
if (!inMemorySort) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
const persisted = get(this._persistedSort);
|
|
518
|
+
if (!persisted) {
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
return inMemorySort.fieldId !== persisted.fieldId || inMemorySort.direction !== persisted.direction;
|
|
626
522
|
});
|
|
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
523
|
this._pinnedRows = pinnedRows;
|
|
633
524
|
this._rowActions = rowActions;
|
|
634
525
|
this._onInsertRow = onInsertRow;
|
|
635
526
|
this._onDeleteRows = onDeleteRows;
|
|
636
|
-
this.
|
|
527
|
+
this._onColumnDelete = onColumnDelete;
|
|
637
528
|
this._onCellUpdate = onCellUpdate;
|
|
638
529
|
this._onRowOrderChange = onRowOrderChange;
|
|
639
530
|
this._onRowAction = onRowAction;
|
|
640
531
|
}
|
|
641
532
|
get id() {
|
|
642
|
-
return
|
|
533
|
+
return Obj.getDXN(this._object).toString();
|
|
643
534
|
}
|
|
644
535
|
get view() {
|
|
645
536
|
const view = this._object.view.target;
|
|
646
|
-
invariant(view, "Table model not initialized", {
|
|
647
|
-
F: __dxlog_file,
|
|
648
|
-
L: 176,
|
|
649
|
-
S: this,
|
|
650
|
-
A: [
|
|
651
|
-
"view",
|
|
652
|
-
"'Table model not initialized'"
|
|
653
|
-
]
|
|
654
|
-
});
|
|
537
|
+
invariant(view, "Table model not initialized", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 186, S: this, A: ["view", "'Table model not initialized'"] });
|
|
655
538
|
return view;
|
|
656
539
|
}
|
|
657
540
|
get table() {
|
|
@@ -660,49 +543,63 @@ var TableModel = class extends Resource2 {
|
|
|
660
543
|
get projection() {
|
|
661
544
|
return this._projection;
|
|
662
545
|
}
|
|
546
|
+
get db() {
|
|
547
|
+
return this._db;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Atom for reactive access to rows with in-memory sorting applied.
|
|
551
|
+
*/
|
|
663
552
|
get rows() {
|
|
664
|
-
return this.
|
|
553
|
+
return this._sortedRows;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Gets rows with in-memory sorting applied.
|
|
557
|
+
* In-memory sort is local to this instance until saved.
|
|
558
|
+
*/
|
|
559
|
+
getRows() {
|
|
560
|
+
return this._registry.get(this._sortedRows);
|
|
561
|
+
}
|
|
562
|
+
/** Atom for reactive access to cell changes. */
|
|
563
|
+
get cellUpdate() {
|
|
564
|
+
return this._cellUpdateCounter;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Change a row using the configured change callback.
|
|
568
|
+
* Use this instead of directly mutating to ensure consistent mutation handling.
|
|
569
|
+
*/
|
|
570
|
+
changeRow(row, mutate) {
|
|
571
|
+
this._change.row(row, mutate);
|
|
665
572
|
}
|
|
666
573
|
get features() {
|
|
667
574
|
return this._features;
|
|
668
575
|
}
|
|
669
576
|
/**
|
|
670
|
-
*
|
|
577
|
+
* Gets the current sort state.
|
|
578
|
+
* Priority: in-memory sort (local changes) > persisted sort (from query AST).
|
|
671
579
|
*/
|
|
672
|
-
|
|
673
|
-
return this._sorting;
|
|
580
|
+
getSorting() {
|
|
581
|
+
return this._registry.get(this._sorting);
|
|
674
582
|
}
|
|
675
583
|
/**
|
|
676
584
|
* Gets the row data at the specified display index.
|
|
677
585
|
*/
|
|
678
586
|
getRowAt(displayIndex) {
|
|
679
|
-
|
|
587
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
588
|
+
if (displayIndex < 0 || displayIndex >= sortedRows.length) {
|
|
680
589
|
return void 0;
|
|
681
590
|
}
|
|
682
|
-
return
|
|
591
|
+
return sortedRows[displayIndex];
|
|
683
592
|
}
|
|
684
593
|
get pinnedRows() {
|
|
685
594
|
return this._pinnedRows;
|
|
686
595
|
}
|
|
687
596
|
get columnMeta() {
|
|
688
|
-
invariant(this._columnMeta, void 0, {
|
|
689
|
-
F: __dxlog_file,
|
|
690
|
-
L: 219,
|
|
691
|
-
S: this,
|
|
692
|
-
A: [
|
|
693
|
-
"this._columnMeta",
|
|
694
|
-
""
|
|
695
|
-
]
|
|
696
|
-
});
|
|
597
|
+
invariant(this._columnMeta, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 240, S: this, A: ["this._columnMeta", ""] });
|
|
697
598
|
return this._columnMeta;
|
|
698
599
|
}
|
|
699
600
|
get selection() {
|
|
700
601
|
return this._selection;
|
|
701
602
|
}
|
|
702
|
-
/** @reactive */
|
|
703
|
-
get isViewDirty() {
|
|
704
|
-
return this.sorting.isDirty;
|
|
705
|
-
}
|
|
706
603
|
get rowActions() {
|
|
707
604
|
return this._rowActions;
|
|
708
605
|
}
|
|
@@ -716,8 +613,9 @@ var TableModel = class extends Resource2 {
|
|
|
716
613
|
await this._selection.open(this._ctx);
|
|
717
614
|
}
|
|
718
615
|
initializeColumnMeta() {
|
|
719
|
-
this.
|
|
720
|
-
|
|
616
|
+
invariant(this._object.view.target, "View must be loaded before initializing column meta", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 259, S: this, A: ["this._object.view.target", "'View must be loaded before initializing column meta'"] });
|
|
617
|
+
this._columnMeta = Atom2.make((get) => {
|
|
618
|
+
const fields = get(this._projection.fields);
|
|
721
619
|
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
722
620
|
index,
|
|
723
621
|
{
|
|
@@ -743,49 +641,62 @@ var TableModel = class extends Resource2 {
|
|
|
743
641
|
});
|
|
744
642
|
}
|
|
745
643
|
initializeEffects() {
|
|
746
|
-
const
|
|
747
|
-
touch(this.sorting.sortedRows.value);
|
|
644
|
+
const rowsUnsubscribe = this._registry.subscribe(this._rows, () => {
|
|
748
645
|
this._onRowOrderChange?.();
|
|
749
646
|
});
|
|
750
|
-
this._ctx.onDispose(
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
647
|
+
this._ctx.onDispose(rowsUnsubscribe);
|
|
648
|
+
const rowSubscriptions = /* @__PURE__ */ new Map();
|
|
649
|
+
const visibleRangeUnsubscribe = this._registry.subscribe(this._visibleRange, () => {
|
|
650
|
+
for (const [id, unsub] of rowSubscriptions) {
|
|
651
|
+
unsub();
|
|
652
|
+
rowSubscriptions.delete(id);
|
|
653
|
+
}
|
|
654
|
+
const { start, end } = this._registry.get(this._visibleRange);
|
|
655
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
656
|
+
for (let row = start.row; row <= end.row && row < sortedRows.length; row++) {
|
|
657
|
+
const obj = sortedRows[row];
|
|
658
|
+
if (Obj.isObject(obj) && !rowSubscriptions.has(obj.id)) {
|
|
659
|
+
const unsub = Obj.subscribe(obj, () => {
|
|
660
|
+
this._registry.set(this._cellUpdateCounter, this._registry.get(this._cellUpdateCounter) + 1);
|
|
661
|
+
this._onCellUpdate?.({
|
|
662
|
+
row,
|
|
663
|
+
col: start.col,
|
|
664
|
+
plane: "grid"
|
|
665
|
+
});
|
|
762
666
|
});
|
|
763
|
-
|
|
667
|
+
rowSubscriptions.set(obj.id, unsub);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
this._ctx.onDispose(() => {
|
|
672
|
+
visibleRangeUnsubscribe();
|
|
673
|
+
for (const unsub of rowSubscriptions.values()) {
|
|
674
|
+
unsub();
|
|
764
675
|
}
|
|
765
|
-
return () => rowEffects.forEach((cleanup) => cleanup());
|
|
766
676
|
});
|
|
767
|
-
this.
|
|
768
|
-
const draftRowsWatcher = effect2(() => {
|
|
769
|
-
touch(this._draftRows.value);
|
|
677
|
+
const draftRowsUnsubscribe = this._registry.subscribe(this._draftRows, () => {
|
|
770
678
|
this._onRowOrderChange?.();
|
|
771
679
|
});
|
|
772
|
-
this._ctx.onDispose(
|
|
680
|
+
this._ctx.onDispose(draftRowsUnsubscribe);
|
|
773
681
|
}
|
|
774
682
|
//
|
|
775
683
|
// Data
|
|
776
684
|
//
|
|
777
685
|
setRows = (obj) => {
|
|
778
|
-
this._rows
|
|
686
|
+
this._registry.set(this._rows, obj);
|
|
779
687
|
};
|
|
780
|
-
getRowCount = () => this.
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
// TODO(ZaymonFC): Return .value instead of exposing the signal.
|
|
688
|
+
getRowCount = () => this._registry.get(this._sortedRows).length;
|
|
689
|
+
getDraftRowCount() {
|
|
690
|
+
return this._registry.get(this._draftRows).length;
|
|
691
|
+
}
|
|
692
|
+
/** Atom for reactive access to draft rows. */
|
|
786
693
|
get draftRows() {
|
|
787
694
|
return this._draftRows;
|
|
788
695
|
}
|
|
696
|
+
/** Gets the current draft rows. */
|
|
697
|
+
getDraftRows() {
|
|
698
|
+
return this._registry.get(this._draftRows);
|
|
699
|
+
}
|
|
789
700
|
/**
|
|
790
701
|
* Checks if a specific field path has validation errors for a given draft row.
|
|
791
702
|
* @param draftRowIndex - The index of the draft row to check
|
|
@@ -793,17 +704,17 @@ var TableModel = class extends Resource2 {
|
|
|
793
704
|
* @returns true if the field has validation errors, false otherwise
|
|
794
705
|
*/
|
|
795
706
|
hasDraftRowValidationError(draftRowIndex, fieldPath) {
|
|
796
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
707
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
797
708
|
return false;
|
|
798
709
|
}
|
|
799
|
-
const draftRow = this._draftRows
|
|
710
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
800
711
|
const validationErrors = draftRow.validationErrors || [];
|
|
801
712
|
return validationErrors.some((error) => error.path === fieldPath);
|
|
802
713
|
}
|
|
803
|
-
getColumnCount = () => this._projection?.
|
|
714
|
+
getColumnCount = () => this._projection?.getFields().length ?? 0;
|
|
804
715
|
insertRow = () => {
|
|
805
716
|
const result = this._onInsertRow?.();
|
|
806
|
-
if (result === "draft" && this._draftRows.
|
|
717
|
+
if (result === "draft" && this._registry.get(this._draftRows).length === 0) {
|
|
807
718
|
this.createDraftRow();
|
|
808
719
|
}
|
|
809
720
|
return result ?? "final";
|
|
@@ -821,16 +732,16 @@ var TableModel = class extends Resource2 {
|
|
|
821
732
|
valid: validationErrors.length === 0,
|
|
822
733
|
validationErrors
|
|
823
734
|
};
|
|
824
|
-
this._draftRows
|
|
825
|
-
...this._draftRows
|
|
735
|
+
this._registry.set(this._draftRows, [
|
|
736
|
+
...this._registry.get(this._draftRows),
|
|
826
737
|
draftRow
|
|
827
|
-
];
|
|
738
|
+
]);
|
|
828
739
|
}
|
|
829
740
|
validateDraftRow(draftRowIndex) {
|
|
830
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
741
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
831
742
|
return;
|
|
832
743
|
}
|
|
833
|
-
const draftRow = this._draftRows
|
|
744
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
834
745
|
const validationErrors = this.validateDraftRowData(draftRow.data);
|
|
835
746
|
const updatedDraftRow = {
|
|
836
747
|
...draftRow,
|
|
@@ -838,69 +749,71 @@ var TableModel = class extends Resource2 {
|
|
|
838
749
|
validationErrors
|
|
839
750
|
};
|
|
840
751
|
const newDraftRows = [
|
|
841
|
-
...this._draftRows
|
|
752
|
+
...this._registry.get(this._draftRows)
|
|
842
753
|
];
|
|
843
754
|
newDraftRows[draftRowIndex] = updatedDraftRow;
|
|
844
|
-
this._draftRows
|
|
755
|
+
this._registry.set(this._draftRows, newDraftRows);
|
|
845
756
|
}
|
|
846
757
|
validateDraftRowData(data) {
|
|
847
758
|
const schema = toEffectSchema(this._projection.baseSchema);
|
|
848
759
|
return validateSchema(schema, data) || [];
|
|
849
760
|
}
|
|
850
761
|
commitDraftRow = (draftRowIndex) => {
|
|
851
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.
|
|
762
|
+
if (draftRowIndex < 0 || draftRowIndex >= this._registry.get(this._draftRows).length) {
|
|
852
763
|
return false;
|
|
853
764
|
}
|
|
854
|
-
const draftRow = this._draftRows
|
|
765
|
+
const draftRow = this._registry.get(this._draftRows)[draftRowIndex];
|
|
855
766
|
if (!draftRow.valid) {
|
|
856
767
|
return false;
|
|
857
768
|
}
|
|
858
769
|
const insertRowResult = this._onInsertRow?.(draftRow.data);
|
|
859
770
|
if (insertRowResult === "final") {
|
|
860
|
-
const newDraftRows = this._draftRows.
|
|
861
|
-
this._draftRows
|
|
771
|
+
const newDraftRows = this._registry.get(this._draftRows).filter((_, index) => index !== draftRowIndex);
|
|
772
|
+
this._registry.set(this._draftRows, newDraftRows);
|
|
862
773
|
}
|
|
863
774
|
return insertRowResult === "final";
|
|
864
775
|
};
|
|
865
776
|
deleteRow = (rowIndex) => {
|
|
866
|
-
const
|
|
867
|
-
const obj =
|
|
777
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
778
|
+
const obj = sortedRows[rowIndex];
|
|
868
779
|
const objectsToDelete = [];
|
|
869
|
-
if (this.features.selection.enabled && this._selection.hasSelection
|
|
780
|
+
if (this.features.selection.enabled && this._selection.hasSelection) {
|
|
870
781
|
const selectedRows = this._selection.getSelectedRows();
|
|
871
782
|
objectsToDelete.push(...selectedRows);
|
|
872
|
-
} else {
|
|
783
|
+
} else if (obj) {
|
|
873
784
|
objectsToDelete.push(obj);
|
|
874
785
|
}
|
|
875
|
-
|
|
786
|
+
if (objectsToDelete.length > 0) {
|
|
787
|
+
this._onDeleteRows?.(rowIndex, objectsToDelete);
|
|
788
|
+
}
|
|
876
789
|
};
|
|
877
790
|
handleRowAction = (actionId, rowIndex) => {
|
|
878
791
|
if (!this._onRowAction) {
|
|
879
792
|
return;
|
|
880
793
|
}
|
|
881
|
-
const
|
|
882
|
-
const data =
|
|
794
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
795
|
+
const data = sortedRows[rowIndex];
|
|
883
796
|
if (data) {
|
|
884
797
|
this._onRowAction(actionId, data);
|
|
885
798
|
}
|
|
886
799
|
};
|
|
887
800
|
getCellData = (cell) => {
|
|
888
801
|
const { col, row, plane } = cell;
|
|
889
|
-
const fields = this._projection?.
|
|
802
|
+
const fields = this._projection?.getFields() ?? [];
|
|
890
803
|
if (col < 0 || col >= fields.length) {
|
|
891
804
|
return void 0;
|
|
892
805
|
}
|
|
893
806
|
const field = fields[col];
|
|
894
807
|
let value;
|
|
895
808
|
if (plane === "frozenRowsEnd") {
|
|
896
|
-
if (row >= 0 && row < this._draftRows.
|
|
897
|
-
value =
|
|
809
|
+
if (row >= 0 && row < this._registry.get(this._draftRows).length) {
|
|
810
|
+
value = getValue(this._registry.get(this._draftRows)[row].data, field.path);
|
|
898
811
|
} else {
|
|
899
812
|
return void 0;
|
|
900
813
|
}
|
|
901
814
|
} else {
|
|
902
|
-
const
|
|
903
|
-
value =
|
|
815
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
816
|
+
value = getValue(sortedRows[row], field.path);
|
|
904
817
|
}
|
|
905
818
|
if (value == null) {
|
|
906
819
|
return "";
|
|
@@ -911,7 +824,7 @@ var TableModel = class extends Resource2 {
|
|
|
911
824
|
if (!field.referencePath) {
|
|
912
825
|
return "";
|
|
913
826
|
}
|
|
914
|
-
return
|
|
827
|
+
return getValue(value.target, field.referencePath);
|
|
915
828
|
}
|
|
916
829
|
default: {
|
|
917
830
|
return formatForEditing({
|
|
@@ -923,7 +836,7 @@ var TableModel = class extends Resource2 {
|
|
|
923
836
|
}
|
|
924
837
|
};
|
|
925
838
|
validateCellData = async ({ col, row, plane }, value) => {
|
|
926
|
-
const fields = this._projection?.
|
|
839
|
+
const fields = this._projection?.getFields() ?? [];
|
|
927
840
|
if (col < 0 || col >= fields.length) {
|
|
928
841
|
return {
|
|
929
842
|
valid: false,
|
|
@@ -935,14 +848,14 @@ var TableModel = class extends Resource2 {
|
|
|
935
848
|
const transformedValue = editorTextToCellValue(props, value);
|
|
936
849
|
const isDraftRow = plane === "frozenRowsEnd";
|
|
937
850
|
if (isDraftRow) {
|
|
938
|
-
const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.
|
|
851
|
+
const isInvalidDraftRowIndex = row < 0 || row >= this._registry.get(this._draftRows).length;
|
|
939
852
|
if (isInvalidDraftRowIndex) {
|
|
940
853
|
return {
|
|
941
854
|
valid: false,
|
|
942
855
|
error: "Invalid draft row index"
|
|
943
856
|
};
|
|
944
857
|
}
|
|
945
|
-
const draftRow = this._draftRows
|
|
858
|
+
const draftRow = this._registry.get(this._draftRows)[row];
|
|
946
859
|
const snapshot = {
|
|
947
860
|
...draftRow.data
|
|
948
861
|
};
|
|
@@ -961,41 +874,18 @@ var TableModel = class extends Resource2 {
|
|
|
961
874
|
valid: true
|
|
962
875
|
};
|
|
963
876
|
} else {
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
S: this,
|
|
970
|
-
A: [
|
|
971
|
-
"currentRow",
|
|
972
|
-
"'Invalid row index'"
|
|
973
|
-
]
|
|
974
|
-
});
|
|
975
|
-
const snapshot = getSnapshot(currentRow);
|
|
877
|
+
const currentRow = this._registry.get(this._rows)[row];
|
|
878
|
+
invariant(currentRow, "Invalid row index", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 533, S: this, A: ["currentRow", "'Invalid row index'"] });
|
|
879
|
+
const snapshot = {
|
|
880
|
+
...getSnapshot(currentRow)
|
|
881
|
+
};
|
|
976
882
|
setValue(snapshot, field.path, transformedValue);
|
|
977
|
-
const schema =
|
|
978
|
-
invariant(schema, void 0, {
|
|
979
|
-
F: __dxlog_file,
|
|
980
|
-
L: 522,
|
|
981
|
-
S: this,
|
|
982
|
-
A: [
|
|
983
|
-
"schema",
|
|
984
|
-
""
|
|
985
|
-
]
|
|
986
|
-
});
|
|
883
|
+
const schema = Obj.getSchema(currentRow);
|
|
884
|
+
invariant(schema, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 539, S: this, A: ["schema", ""] });
|
|
987
885
|
const validationResult = validateSchema(schema, snapshot);
|
|
988
886
|
if (validationResult && validationResult.length > 0) {
|
|
989
887
|
const error = validationResult[0];
|
|
990
|
-
invariant(error.path === field.path, void 0, {
|
|
991
|
-
F: __dxlog_file,
|
|
992
|
-
L: 527,
|
|
993
|
-
S: this,
|
|
994
|
-
A: [
|
|
995
|
-
"error.path === field.path",
|
|
996
|
-
""
|
|
997
|
-
]
|
|
998
|
-
});
|
|
888
|
+
invariant(error.path === field.path, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 543, S: this, A: ["error.path === field.path", ""] });
|
|
999
889
|
return {
|
|
1000
890
|
valid: false,
|
|
1001
891
|
error: error.message
|
|
@@ -1008,24 +898,27 @@ var TableModel = class extends Resource2 {
|
|
|
1008
898
|
};
|
|
1009
899
|
setCellData = (cell, value) => {
|
|
1010
900
|
const { col, row, plane } = cell;
|
|
1011
|
-
const fields = this._projection?.
|
|
901
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1012
902
|
if (col < 0 || col >= fields.length) {
|
|
1013
903
|
return;
|
|
1014
904
|
}
|
|
1015
905
|
const field = fields[col];
|
|
1016
906
|
const { props } = this._projection.getFieldProjection(field.id);
|
|
1017
907
|
const transformedValue = editorTextToCellValue(props, value);
|
|
1018
|
-
if (props.format === Format2.TypeFormat.Ref && !
|
|
908
|
+
if (props.format === Format2.TypeFormat.Ref && !Obj.isObject(value)) {
|
|
1019
909
|
return;
|
|
1020
910
|
}
|
|
1021
911
|
if (plane === "frozenRowsEnd") {
|
|
1022
|
-
if (row >= 0 && row < this._draftRows.
|
|
1023
|
-
setValue(this._draftRows
|
|
912
|
+
if (row >= 0 && row < this._registry.get(this._draftRows).length) {
|
|
913
|
+
setValue(this._registry.get(this._draftRows)[row].data, field.path, transformedValue);
|
|
1024
914
|
this.validateDraftRow(row);
|
|
1025
915
|
}
|
|
1026
916
|
} else {
|
|
1027
|
-
const
|
|
1028
|
-
|
|
917
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
918
|
+
const rowData = sortedRows[row];
|
|
919
|
+
this._change.row(rowData, (mutableRow) => {
|
|
920
|
+
setValue(mutableRow, field.path, transformedValue);
|
|
921
|
+
});
|
|
1029
922
|
}
|
|
1030
923
|
};
|
|
1031
924
|
/**
|
|
@@ -1034,12 +927,15 @@ var TableModel = class extends Resource2 {
|
|
|
1034
927
|
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1035
928
|
*/
|
|
1036
929
|
updateCellData({ col, row }, update) {
|
|
1037
|
-
const
|
|
1038
|
-
const fields = this._projection?.fields ?? [];
|
|
930
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1039
931
|
const field = fields[col];
|
|
1040
|
-
const
|
|
932
|
+
const sortedRows = this._registry.get(this._sortedRows);
|
|
933
|
+
const rowData = sortedRows[row];
|
|
934
|
+
const value = getValue(rowData, field.path);
|
|
1041
935
|
const updatedValue = update(value);
|
|
1042
|
-
|
|
936
|
+
this._change.row(rowData, (mutableRow) => {
|
|
937
|
+
setValue(mutableRow, field.path, updatedValue);
|
|
938
|
+
});
|
|
1043
939
|
}
|
|
1044
940
|
/**
|
|
1045
941
|
* Gets the domain-appropriate cell type for a given cell position.
|
|
@@ -1073,21 +969,23 @@ var TableModel = class extends Resource2 {
|
|
|
1073
969
|
if (!this._projection) {
|
|
1074
970
|
return;
|
|
1075
971
|
}
|
|
1076
|
-
const field = this._projection?.
|
|
1077
|
-
if (field && this.
|
|
1078
|
-
this.
|
|
972
|
+
const field = this._projection?.getFields().find((field2) => field2.id === fieldId);
|
|
973
|
+
if (field && this._onColumnDelete) {
|
|
974
|
+
this._onColumnDelete(field.id);
|
|
1079
975
|
}
|
|
1080
976
|
}
|
|
1081
977
|
//
|
|
1082
978
|
// Resize
|
|
1083
979
|
//
|
|
1084
980
|
setColumnWidth(columnIndex, width) {
|
|
1085
|
-
const fields = this._projection?.
|
|
981
|
+
const fields = this._projection?.getFields() ?? [];
|
|
1086
982
|
if (columnIndex < fields.length) {
|
|
1087
983
|
const newWidth = Math.max(0, width);
|
|
1088
984
|
const field = fields[columnIndex];
|
|
1089
985
|
if (field) {
|
|
1090
|
-
this.table
|
|
986
|
+
this._change.table((mutableTable) => {
|
|
987
|
+
mutableTable.sizes[field.path] = newWidth;
|
|
988
|
+
});
|
|
1091
989
|
}
|
|
1092
990
|
}
|
|
1093
991
|
}
|
|
@@ -1103,17 +1001,87 @@ var TableModel = class extends Resource2 {
|
|
|
1103
1001
|
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1104
1002
|
}
|
|
1105
1003
|
//
|
|
1106
|
-
//
|
|
1004
|
+
// Sort operations
|
|
1107
1005
|
//
|
|
1006
|
+
/**
|
|
1007
|
+
* Sets the sort order for a field in-memory (local to this instance).
|
|
1008
|
+
* Use saveView() to persist the sort to the view query.
|
|
1009
|
+
*/
|
|
1010
|
+
setSort(fieldId, direction) {
|
|
1011
|
+
const field = this._projection.getFields().find((f) => f.id === fieldId);
|
|
1012
|
+
if (!field) {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
this._registry.set(this._inMemorySort, {
|
|
1016
|
+
fieldId,
|
|
1017
|
+
direction
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Toggles the sort direction for a field in-memory.
|
|
1022
|
+
*/
|
|
1023
|
+
toggleSort(fieldId) {
|
|
1024
|
+
const currentSort = this.getSorting();
|
|
1025
|
+
if (!currentSort || currentSort.fieldId !== fieldId) {
|
|
1026
|
+
this.setSort(fieldId, "asc");
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
const newDirection = currentSort.direction === "asc" ? "desc" : "asc";
|
|
1030
|
+
this.setSort(fieldId, newDirection);
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Clears the in-memory sort order.
|
|
1034
|
+
*/
|
|
1035
|
+
clearSort() {
|
|
1036
|
+
this._registry.set(this._inMemorySort, void 0);
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Saves the current in-memory sort to the view query AST.
|
|
1040
|
+
* This persists the sort so it becomes the default for all viewers.
|
|
1041
|
+
*/
|
|
1108
1042
|
saveView() {
|
|
1109
|
-
this.
|
|
1043
|
+
const view = this.view;
|
|
1044
|
+
const inMemorySort = this._registry.get(this._inMemorySort);
|
|
1045
|
+
const viewSnapshot = Obj.getSnapshot(view);
|
|
1046
|
+
const currentQuery = Query.fromAst(viewSnapshot.query.ast);
|
|
1047
|
+
const baseQuery = this._getBaseQuery(currentQuery);
|
|
1048
|
+
if (inMemorySort) {
|
|
1049
|
+
const field = this._projection.getFields().find((f) => f.id === inMemorySort.fieldId);
|
|
1050
|
+
if (field) {
|
|
1051
|
+
const newQuery = baseQuery.orderBy(Order.property(field.path, inMemorySort.direction));
|
|
1052
|
+
Obj.update(view, (view2) => {
|
|
1053
|
+
view2.query.ast = newQuery.ast;
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
} else {
|
|
1057
|
+
Obj.update(view, (view2) => {
|
|
1058
|
+
view2.query.ast = baseQuery.ast;
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
this._registry.set(this._inMemorySort, void 0);
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Extracts the base query without order clauses.
|
|
1065
|
+
*/
|
|
1066
|
+
_getBaseQuery(query) {
|
|
1067
|
+
const ast = query.ast;
|
|
1068
|
+
if (ast.type === "order") {
|
|
1069
|
+
return Query.fromAst(ast.query);
|
|
1070
|
+
}
|
|
1071
|
+
return query;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Checks if the view has unsaved changes (in-memory sort differs from persisted sort).
|
|
1075
|
+
*/
|
|
1076
|
+
getViewDirty() {
|
|
1077
|
+
return this._registry.get(this._viewDirty);
|
|
1110
1078
|
}
|
|
1111
1079
|
};
|
|
1112
1080
|
var editorTextToCellValue = (props, value) => {
|
|
1113
1081
|
switch (props.format) {
|
|
1114
1082
|
case Format2.TypeFormat.Ref: {
|
|
1115
|
-
if (
|
|
1116
|
-
return
|
|
1083
|
+
if (Obj.isObject(value)) {
|
|
1084
|
+
return Ref.make(value);
|
|
1117
1085
|
} else {
|
|
1118
1086
|
return value;
|
|
1119
1087
|
}
|
|
@@ -1140,104 +1108,40 @@ var editorTextToCellValue = (props, value) => {
|
|
|
1140
1108
|
}
|
|
1141
1109
|
};
|
|
1142
1110
|
|
|
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
1111
|
// src/model/table-presentation.ts
|
|
1210
|
-
import {
|
|
1112
|
+
import { Atom as Atom3 } from "@effect-atom/atom-react";
|
|
1211
1113
|
import * as Predicate from "effect/Predicate";
|
|
1212
|
-
import { Obj as
|
|
1213
|
-
import { Format as Format3, TypeEnum
|
|
1214
|
-
import { cellClassesForFieldType, formatForDisplay
|
|
1114
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
1115
|
+
import { Format as Format3, TypeEnum, getValue as getValue2 } from "@dxos/echo/internal";
|
|
1116
|
+
import { cellClassesForFieldType, formatForDisplay } from "@dxos/react-ui-form";
|
|
1215
1117
|
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
1216
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
1217
1118
|
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1119
|
+
import { mx } from "@dxos/ui-theme";
|
|
1218
1120
|
var TablePresentation = class {
|
|
1219
1121
|
model;
|
|
1122
|
+
_registry;
|
|
1220
1123
|
_visibleRange;
|
|
1221
1124
|
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
|
-
})) {
|
|
1125
|
+
constructor(registry, model) {
|
|
1232
1126
|
this.model = model;
|
|
1233
|
-
this.
|
|
1127
|
+
this._registry = registry;
|
|
1128
|
+
this._visibleRange = Atom3.make({
|
|
1129
|
+
start: {
|
|
1130
|
+
row: 0,
|
|
1131
|
+
col: 0
|
|
1132
|
+
},
|
|
1133
|
+
end: {
|
|
1134
|
+
row: 0,
|
|
1135
|
+
col: 0
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1234
1138
|
}
|
|
1235
1139
|
getCells(range, plane) {
|
|
1236
1140
|
this.fieldProjectionCache.clear();
|
|
1237
1141
|
let cells;
|
|
1238
1142
|
switch (plane) {
|
|
1239
1143
|
case "grid":
|
|
1240
|
-
this._visibleRange
|
|
1144
|
+
this._registry.set(this._visibleRange, range);
|
|
1241
1145
|
cells = this.getMainGridCells(range);
|
|
1242
1146
|
break;
|
|
1243
1147
|
case "frozenRowsStart":
|
|
@@ -1289,7 +1193,7 @@ var TablePresentation = class {
|
|
|
1289
1193
|
const { props } = this.getFieldProjection(field.id);
|
|
1290
1194
|
const cell = {
|
|
1291
1195
|
get value() {
|
|
1292
|
-
const value =
|
|
1196
|
+
const value = getValue2(obj, field.path);
|
|
1293
1197
|
if (value == null) {
|
|
1294
1198
|
return "";
|
|
1295
1199
|
}
|
|
@@ -1306,10 +1210,10 @@ var TablePresentation = class {
|
|
|
1306
1210
|
if (!field.referencePath) {
|
|
1307
1211
|
return "";
|
|
1308
1212
|
}
|
|
1309
|
-
return
|
|
1213
|
+
return getValue2(value.target, field.referencePath);
|
|
1310
1214
|
}
|
|
1311
1215
|
default: {
|
|
1312
|
-
return
|
|
1216
|
+
return formatForDisplay({
|
|
1313
1217
|
type: props.type,
|
|
1314
1218
|
format: props.format,
|
|
1315
1219
|
value
|
|
@@ -1328,8 +1232,8 @@ var TablePresentation = class {
|
|
|
1328
1232
|
classes.push(rowSelectionClasses);
|
|
1329
1233
|
}
|
|
1330
1234
|
cell.className = mx(classes);
|
|
1331
|
-
if (props.type ===
|
|
1332
|
-
const targetArray =
|
|
1235
|
+
if (props.type === TypeEnum.Array) {
|
|
1236
|
+
const targetArray = getValue2(obj, field.path);
|
|
1333
1237
|
if (targetArray && Array.isArray(targetArray)) {
|
|
1334
1238
|
const getLabel = (value) => {
|
|
1335
1239
|
if (!value) {
|
|
@@ -1356,14 +1260,14 @@ var TablePresentation = class {
|
|
|
1356
1260
|
}
|
|
1357
1261
|
}
|
|
1358
1262
|
if (props.format === Format3.TypeFormat.Ref && props.referenceSchema) {
|
|
1359
|
-
const targetObj =
|
|
1263
|
+
const targetObj = getValue2(obj, field.path)?.target;
|
|
1360
1264
|
if (targetObj) {
|
|
1361
|
-
const dxn =
|
|
1362
|
-
cell.accessoryHtml = `<div role="none" class="absolute
|
|
1265
|
+
const dxn = Obj2.getDXN(targetObj)?.toString();
|
|
1266
|
+
cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor dxn=${dxn} class="dx-button w-6 aspect-square min-h-0" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-anchor></div>`;
|
|
1363
1267
|
}
|
|
1364
1268
|
}
|
|
1365
1269
|
if (props.format === Format3.TypeFormat.Boolean) {
|
|
1366
|
-
const value =
|
|
1270
|
+
const value = getValue2(obj, field.path);
|
|
1367
1271
|
cell.accessoryHtml = tableControls.switch.render({
|
|
1368
1272
|
colIndex,
|
|
1369
1273
|
rowIndex: displayIndex,
|
|
@@ -1372,7 +1276,7 @@ var TablePresentation = class {
|
|
|
1372
1276
|
cell.readonly = "no-text-select";
|
|
1373
1277
|
}
|
|
1374
1278
|
if (props.format === Format3.TypeFormat.SingleSelect) {
|
|
1375
|
-
const value =
|
|
1279
|
+
const value = getValue2(obj, field.path);
|
|
1376
1280
|
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1377
1281
|
if (options) {
|
|
1378
1282
|
const option = options.find((o) => o.id === value);
|
|
@@ -1382,7 +1286,7 @@ var TablePresentation = class {
|
|
|
1382
1286
|
}
|
|
1383
1287
|
}
|
|
1384
1288
|
if (props.format === Format3.TypeFormat.MultiSelect) {
|
|
1385
|
-
const values =
|
|
1289
|
+
const values = getValue2(obj, field.path);
|
|
1386
1290
|
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1387
1291
|
if (options && values && values.length > 0) {
|
|
1388
1292
|
const tags = values.map((value) => {
|
|
@@ -1405,22 +1309,22 @@ var TablePresentation = class {
|
|
|
1405
1309
|
}
|
|
1406
1310
|
getMainGridCells(range) {
|
|
1407
1311
|
const cells = {};
|
|
1408
|
-
const fields = this.model.projection?.
|
|
1312
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1409
1313
|
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1410
1314
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1411
1315
|
const field = fields[col];
|
|
1412
1316
|
if (!field) {
|
|
1413
1317
|
continue;
|
|
1414
1318
|
}
|
|
1415
|
-
this.createDataCell(cells, this.model.
|
|
1319
|
+
this.createDataCell(cells, this.model.getRows()[row], field, col, row);
|
|
1416
1320
|
}
|
|
1417
1321
|
}
|
|
1418
1322
|
return cells;
|
|
1419
1323
|
}
|
|
1420
1324
|
getDraftRowCells(range) {
|
|
1421
1325
|
const cells = {};
|
|
1422
|
-
const fields = this.model.projection?.
|
|
1423
|
-
const draftRows = this.model.
|
|
1326
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1327
|
+
const draftRows = this.model.getDraftRows();
|
|
1424
1328
|
if (draftRows.length === 0) {
|
|
1425
1329
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1426
1330
|
cells[toPlaneCellIndex({
|
|
@@ -1460,11 +1364,11 @@ var TablePresentation = class {
|
|
|
1460
1364
|
}
|
|
1461
1365
|
getHeaderCells(range) {
|
|
1462
1366
|
const cells = {};
|
|
1463
|
-
const fields = this.model.projection?.
|
|
1367
|
+
const fields = this.model.projection?.getFields() ?? [];
|
|
1368
|
+
const currentSort = this.model.getSorting();
|
|
1464
1369
|
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1465
1370
|
const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
|
|
1466
|
-
const
|
|
1467
|
-
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1371
|
+
const direction = currentSort?.fieldId === field.id ? currentSort.direction : void 0;
|
|
1468
1372
|
cells[toPlaneCellIndex({
|
|
1469
1373
|
col,
|
|
1470
1374
|
row: 0
|
|
@@ -1473,7 +1377,7 @@ var TablePresentation = class {
|
|
|
1473
1377
|
value: "",
|
|
1474
1378
|
resizeHandle: "col",
|
|
1475
1379
|
accessoryHtml: `
|
|
1476
|
-
<span class="grow min-
|
|
1380
|
+
<span class="grow min-w-0 truncate">${props.title ?? field.path}</span>
|
|
1477
1381
|
${direction !== void 0 ? tableButtons.sort.render({
|
|
1478
1382
|
fieldId: field.id,
|
|
1479
1383
|
direction
|
|
@@ -1482,7 +1386,7 @@ var TablePresentation = class {
|
|
|
1482
1386
|
fieldId: field.id
|
|
1483
1387
|
})}
|
|
1484
1388
|
`,
|
|
1485
|
-
className: "!bg-
|
|
1389
|
+
className: "!bg-toolbar-surface text-description! [&>div]:flex [&>div]:items-stretch"
|
|
1486
1390
|
};
|
|
1487
1391
|
}
|
|
1488
1392
|
return cells;
|
|
@@ -1533,7 +1437,7 @@ var TablePresentation = class {
|
|
|
1533
1437
|
col: 0,
|
|
1534
1438
|
row: 0
|
|
1535
1439
|
})]: {
|
|
1536
|
-
className: "!bg-
|
|
1440
|
+
className: "!bg-toolbar-surface",
|
|
1537
1441
|
readonly: true,
|
|
1538
1442
|
value: ""
|
|
1539
1443
|
}
|
|
@@ -1547,9 +1451,9 @@ var TablePresentation = class {
|
|
|
1547
1451
|
accessoryHtml: tableControls.checkbox.render({
|
|
1548
1452
|
rowIndex: 0,
|
|
1549
1453
|
header: true,
|
|
1550
|
-
checked: this.model.selection.
|
|
1454
|
+
checked: this.model.selection.allRowsSelected
|
|
1551
1455
|
}),
|
|
1552
|
-
className: "!bg-
|
|
1456
|
+
className: "!bg-toolbar-surface",
|
|
1553
1457
|
readonly: true,
|
|
1554
1458
|
value: ""
|
|
1555
1459
|
}
|
|
@@ -1562,9 +1466,9 @@ var TablePresentation = class {
|
|
|
1562
1466
|
row: 0
|
|
1563
1467
|
})]: {
|
|
1564
1468
|
accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
|
|
1565
|
-
disabled: (this.model.projection?.
|
|
1469
|
+
disabled: (this.model.projection?.getFields()?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1566
1470
|
}) : void 0,
|
|
1567
|
-
className: "!bg-
|
|
1471
|
+
className: "!bg-toolbar-surface",
|
|
1568
1472
|
readonly: true,
|
|
1569
1473
|
value: ""
|
|
1570
1474
|
}
|
|
@@ -1572,7 +1476,7 @@ var TablePresentation = class {
|
|
|
1572
1476
|
}
|
|
1573
1477
|
getDraftActionCells(range) {
|
|
1574
1478
|
const cells = {};
|
|
1575
|
-
const draftRows = this.model.
|
|
1479
|
+
const draftRows = this.model.getDraftRows();
|
|
1576
1480
|
if (draftRows.length === 0) {
|
|
1577
1481
|
cells[toPlaneCellIndex({
|
|
1578
1482
|
col: 0,
|
|
@@ -1603,7 +1507,7 @@ var TablePresentation = class {
|
|
|
1603
1507
|
}
|
|
1604
1508
|
getDraftIconCells(range) {
|
|
1605
1509
|
const cells = {};
|
|
1606
|
-
const draftRows = this.model.
|
|
1510
|
+
const draftRows = this.model.getDraftRows();
|
|
1607
1511
|
for (let row = range.start.row; row <= range.end.row; row++) {
|
|
1608
1512
|
cells[toPlaneCellIndex({
|
|
1609
1513
|
col: 0,
|
|
@@ -1622,7 +1526,7 @@ var cellClassesForRowSelection = (selected, selectionMode) => {
|
|
|
1622
1526
|
if (!selected) {
|
|
1623
1527
|
if (selectionMode === "single") {
|
|
1624
1528
|
return [
|
|
1625
|
-
"
|
|
1529
|
+
"cursor-pointer!"
|
|
1626
1530
|
];
|
|
1627
1531
|
} else {
|
|
1628
1532
|
return void 0;
|
|
@@ -1631,23 +1535,23 @@ var cellClassesForRowSelection = (selected, selectionMode) => {
|
|
|
1631
1535
|
switch (selectionMode) {
|
|
1632
1536
|
case "single":
|
|
1633
1537
|
return [
|
|
1634
|
-
"
|
|
1538
|
+
"dx-grid__cell--no-focus-unfurl !bg-current-surface hover:bg-hover-surface cursor-pointer!"
|
|
1635
1539
|
];
|
|
1636
1540
|
case "multiple":
|
|
1637
1541
|
return [
|
|
1638
|
-
"!bg-
|
|
1542
|
+
"!bg-grid-cell-selected"
|
|
1639
1543
|
];
|
|
1640
1544
|
}
|
|
1641
1545
|
};
|
|
1642
1546
|
|
|
1643
1547
|
// src/hooks/useAddRow.ts
|
|
1644
1548
|
import { useCallback } from "react";
|
|
1645
|
-
import { Obj as
|
|
1646
|
-
var useAddRow = ({
|
|
1549
|
+
import { Obj as Obj3 } from "@dxos/echo";
|
|
1550
|
+
var useAddRow = ({ db, schema }) => {
|
|
1647
1551
|
return useCallback((data) => {
|
|
1648
|
-
if (
|
|
1552
|
+
if (db && schema) {
|
|
1649
1553
|
try {
|
|
1650
|
-
|
|
1554
|
+
db.add(Obj3.make(schema, data ?? {}));
|
|
1651
1555
|
return "final";
|
|
1652
1556
|
} catch (error) {
|
|
1653
1557
|
return "draft";
|
|
@@ -1655,129 +1559,137 @@ var useAddRow = ({ space, schema }) => {
|
|
|
1655
1559
|
}
|
|
1656
1560
|
return "final";
|
|
1657
1561
|
}, [
|
|
1658
|
-
|
|
1562
|
+
db,
|
|
1659
1563
|
schema
|
|
1660
1564
|
]);
|
|
1661
1565
|
};
|
|
1662
1566
|
|
|
1663
1567
|
// src/hooks/useProjectionModel.ts
|
|
1664
|
-
import {
|
|
1665
|
-
import { Type
|
|
1666
|
-
import {
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1568
|
+
import { useState } from "react";
|
|
1569
|
+
import { JsonSchema, Type } from "@dxos/echo";
|
|
1570
|
+
import { useAsyncEffect } from "@dxos/react-ui";
|
|
1571
|
+
import { ProjectionModel, createEchoChangeCallback as createEchoChangeCallback2 } from "@dxos/schema";
|
|
1572
|
+
var useProjectionModel = (schema, table, registry) => {
|
|
1573
|
+
const [projection, setProjection] = useState();
|
|
1574
|
+
useAsyncEffect(async () => {
|
|
1575
|
+
if (schema && table) {
|
|
1576
|
+
const view = await table.view.load();
|
|
1577
|
+
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : JsonSchema.toJsonSchema(schema);
|
|
1578
|
+
const change = createEchoChangeCallback2(view, Type.isMutable(schema) ? schema : void 0);
|
|
1579
|
+
const projection2 = new ProjectionModel({
|
|
1580
|
+
registry,
|
|
1581
|
+
view,
|
|
1582
|
+
baseSchema: jsonSchema,
|
|
1583
|
+
change
|
|
1584
|
+
});
|
|
1585
|
+
projection2.normalizeView();
|
|
1586
|
+
setProjection(projection2);
|
|
1587
|
+
}
|
|
1588
|
+
}, [
|
|
1589
|
+
schema,
|
|
1590
|
+
table,
|
|
1591
|
+
registry
|
|
1592
|
+
]);
|
|
1593
|
+
return projection;
|
|
1594
|
+
};
|
|
1677
1595
|
|
|
1678
1596
|
// 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";
|
|
1597
|
+
import { RegistryContext } from "@effect-atom/atom-react";
|
|
1598
|
+
import { useContext, useEffect, useMemo, useState as useState2 } from "react";
|
|
1599
|
+
import { Obj as Obj4 } from "@dxos/echo";
|
|
1684
1600
|
import { useSelected, useSelectionActions } from "@dxos/react-ui-attention";
|
|
1685
1601
|
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);
|
|
1602
|
+
var useTableModel = ({ object, projection, db, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
1603
|
+
const registry = useContext(RegistryContext);
|
|
1604
|
+
const selected = useSelected(object && Obj4.getDXN(object).toString(), "multi");
|
|
1605
|
+
const initialSelection = useMemo(() => selected, [
|
|
1606
|
+
object
|
|
1607
|
+
]);
|
|
1608
|
+
const [model, setModel] = useState2();
|
|
1609
|
+
useEffect(() => {
|
|
1610
|
+
if (!object || !projection) {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
let model2;
|
|
1614
|
+
const t = setTimeout(async () => {
|
|
1615
|
+
model2 = new TableModel({
|
|
1616
|
+
registry,
|
|
1617
|
+
object,
|
|
1618
|
+
projection,
|
|
1619
|
+
db,
|
|
1620
|
+
change: createEchoChangeCallback(object),
|
|
1621
|
+
features,
|
|
1622
|
+
rowActions,
|
|
1623
|
+
initialSelection,
|
|
1624
|
+
onRowAction,
|
|
1625
|
+
...props
|
|
1749
1626
|
});
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1627
|
+
await model2.open();
|
|
1628
|
+
setModel(model2);
|
|
1629
|
+
});
|
|
1630
|
+
return () => {
|
|
1631
|
+
clearTimeout(t);
|
|
1632
|
+
void model2?.close();
|
|
1633
|
+
};
|
|
1634
|
+
}, [
|
|
1635
|
+
registry,
|
|
1636
|
+
object,
|
|
1637
|
+
projection,
|
|
1638
|
+
features,
|
|
1639
|
+
rowActions,
|
|
1640
|
+
initialSelection
|
|
1641
|
+
]);
|
|
1642
|
+
useEffect(() => {
|
|
1643
|
+
if (rows && model) {
|
|
1644
|
+
model.setRows(rows);
|
|
1645
|
+
}
|
|
1646
|
+
}, [
|
|
1647
|
+
model,
|
|
1648
|
+
rows
|
|
1649
|
+
]);
|
|
1650
|
+
const { multiSelect, clear } = useSelectionActions([
|
|
1651
|
+
model?.id
|
|
1652
|
+
].filter(isNonNullable));
|
|
1653
|
+
useEffect(() => {
|
|
1654
|
+
if (!model) {
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
const unsubscribe = registry.subscribe(model.selection.selectionAtom, () => {
|
|
1658
|
+
const selectedItems = [
|
|
1659
|
+
...model.selection.selection
|
|
1660
|
+
];
|
|
1661
|
+
multiSelect(selectedItems);
|
|
1662
|
+
onSelectionChanged?.(selectedItems);
|
|
1663
|
+
});
|
|
1664
|
+
return () => {
|
|
1665
|
+
clear();
|
|
1666
|
+
unsubscribe();
|
|
1667
|
+
};
|
|
1668
|
+
}, [
|
|
1669
|
+
registry,
|
|
1670
|
+
model,
|
|
1671
|
+
onSelectionChanged
|
|
1672
|
+
]);
|
|
1673
|
+
return model;
|
|
1762
1674
|
};
|
|
1763
1675
|
|
|
1764
1676
|
export {
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1677
|
+
extractOrder,
|
|
1678
|
+
getSortValue,
|
|
1679
|
+
compareValues,
|
|
1768
1680
|
BUTTON_IDENTIFIERS,
|
|
1769
1681
|
tableButtons,
|
|
1770
1682
|
CONTROL_IDENTIFIERS,
|
|
1771
1683
|
CheckboxStory,
|
|
1772
1684
|
SwitchStory,
|
|
1773
1685
|
tableControls,
|
|
1774
|
-
|
|
1686
|
+
createEchoChangeCallback,
|
|
1687
|
+
createDirectChangeCallback,
|
|
1775
1688
|
TableModel,
|
|
1776
|
-
ModalController,
|
|
1777
1689
|
TablePresentation,
|
|
1778
1690
|
cellClassesForRowSelection,
|
|
1779
1691
|
useAddRow,
|
|
1780
1692
|
useProjectionModel,
|
|
1781
1693
|
useTableModel
|
|
1782
1694
|
};
|
|
1783
|
-
//# sourceMappingURL=chunk-
|
|
1695
|
+
//# sourceMappingURL=chunk-YGC7LZJN.mjs.map
|