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