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