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