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