@dxos/react-ui-table 0.8.3 → 0.8.4-main.c1de068
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-5XLSHLOG.mjs +1751 -0
- package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +7 -0
- package/dist/lib/browser/chunk-L2LSB6KV.mjs +18 -0
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +240 -1639
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +121 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +3 -5
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +20 -0
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Y66YLSTC.mjs +1752 -0
- package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +240 -1639
- 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 +122 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +3 -5
- package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/relations.stories.d.ts +1 -1
- package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +2 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +2 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -2
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -40
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +13 -0
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +7 -6
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +2 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +56 -20
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +8 -0
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +2 -2
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts +3 -0
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/useTestTableModel.d.ts +41 -0
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +3 -4
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +8 -0
- package/dist/types/src/types/schema.d.ts.map +1 -0
- package/dist/types/src/util/dynamic-table.d.ts +3 -4
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts +15 -1
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table.d.ts +8 -11
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +48 -40
- package/src/components/Table/ColumnSettings.tsx +14 -10
- package/src/components/Table/CreateRefPanel.tsx +5 -3
- package/src/components/Table/DynamicTable.stories.tsx +2 -2
- package/src/components/Table/DynamicTable.tsx +13 -7
- package/src/components/Table/Table.stories.tsx +104 -148
- package/src/components/Table/Table.tsx +50 -32
- package/src/components/Table/relations.stories.tsx +27 -35
- package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -1
- package/src/components/TableCellEditor/FormCellEditor.tsx +30 -21
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +24 -28
- package/src/components/TableCellEditor/TableCellEditor.tsx +79 -21
- package/src/components/testing.ts +7 -24
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAddRow.ts +36 -0
- package/src/hooks/useTableModel.ts +20 -16
- package/src/index.ts +1 -2
- package/src/model/selection-model.ts +4 -2
- package/src/model/table-model.test.ts +7 -8
- package/src/model/table-model.ts +267 -78
- package/src/model/table-presentation.test.ts +6 -7
- package/src/model/table-presentation.ts +215 -132
- package/src/model/table-sorting.ts +9 -9
- package/src/playwright/playwright.config.ts +17 -0
- package/src/playwright/smoke.spec.ts +21 -20
- package/src/testing/index.ts +5 -0
- package/src/testing/useTestTableModel.ts +122 -0
- package/src/translations.ts +5 -3
- package/src/types/index.ts +2 -2
- package/src/types/schema.ts +16 -0
- package/src/util/dynamic-table.ts +19 -17
- package/src/util/table-buttons.ts +24 -1
- package/src/util/table.ts +33 -111
- package/dist/lib/browser/chunk-TL7CKQQV.mjs +0 -27
- package/dist/lib/browser/chunk-TL7CKQQV.mjs.map +0 -7
- package/dist/lib/node/chunk-O2VPBNS5.cjs +0 -50
- package/dist/lib/node/chunk-O2VPBNS5.cjs.map +0 -7
- package/dist/lib/node/index.cjs +0 -2739
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/types/index.cjs +0 -31
- package/dist/lib/node/types/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-GBT6GD4G.mjs +0 -29
- package/dist/lib/node-esm/chunk-GBT6GD4G.mjs.map +0 -7
- package/dist/types/src/types/table.d.ts +0 -56
- package/dist/types/src/types/table.d.ts.map +0 -1
- package/src/playwright/playwright.config.cts +0 -18
- package/src/types/table.ts +0 -27
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
BUTTON_IDENTIFIERS,
|
|
4
|
+
CONTROL_IDENTIFIERS,
|
|
5
|
+
CheckboxStory,
|
|
6
|
+
ModalController,
|
|
7
|
+
SwitchStory,
|
|
8
|
+
TableModel,
|
|
9
|
+
TablePresentation,
|
|
10
|
+
cellClassesForRowSelection,
|
|
11
|
+
createTable,
|
|
12
|
+
getBaseSchema,
|
|
13
|
+
makeDynamicTable,
|
|
14
|
+
narrowSchema,
|
|
15
|
+
tableButtons,
|
|
16
|
+
tableControls,
|
|
17
|
+
touch,
|
|
18
|
+
useAddRow,
|
|
19
|
+
useTableModel
|
|
20
|
+
} from "./chunk-Y66YLSTC.mjs";
|
|
21
|
+
import "./chunk-NXZ4CJYX.mjs";
|
|
6
22
|
|
|
7
|
-
//
|
|
8
|
-
var translationKey = "table";
|
|
9
|
-
var
|
|
23
|
+
// src/translations.ts
|
|
24
|
+
var translationKey = "react-ui-table";
|
|
25
|
+
var translations = [
|
|
10
26
|
{
|
|
11
27
|
"en-US": {
|
|
12
28
|
[translationKey]: {
|
|
@@ -36,19 +52,20 @@ var translations_default = [
|
|
|
36
52
|
}
|
|
37
53
|
];
|
|
38
54
|
|
|
39
|
-
//
|
|
55
|
+
// src/components/Table/Table.tsx
|
|
40
56
|
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
41
|
-
import React8, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
57
|
+
import React8, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as useState4, useMemo as useMemo5, useEffect as useEffect4 } from "react";
|
|
58
|
+
import { Filter } from "@dxos/echo";
|
|
59
|
+
import { getValue } from "@dxos/echo-schema";
|
|
60
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
61
|
+
import { getSpace as getSpace2 } from "@dxos/react-client/echo";
|
|
45
62
|
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
46
63
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
47
64
|
import { closestCell, Grid, gridSeparatorInlineEnd, gridSeparatorBlockEnd } from "@dxos/react-ui-grid";
|
|
48
|
-
import { mx
|
|
65
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
49
66
|
import { isNotFalsy, safeParseInt } from "@dxos/util";
|
|
50
67
|
|
|
51
|
-
//
|
|
68
|
+
// src/components/Table/ColumnActionsMenu.tsx
|
|
52
69
|
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
53
70
|
import React from "react";
|
|
54
71
|
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
@@ -89,17 +106,16 @@ var ColumnActionsMenu = ({ model, modals }) => {
|
|
|
89
106
|
}
|
|
90
107
|
};
|
|
91
108
|
|
|
92
|
-
//
|
|
109
|
+
// src/components/Table/ColumnSettings.tsx
|
|
93
110
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
94
111
|
import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
95
112
|
import { Popover } from "@dxos/react-ui";
|
|
96
113
|
import { FieldEditor } from "@dxos/react-ui-form";
|
|
97
|
-
var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
114
|
+
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
98
115
|
var _effect = _useSignals2();
|
|
99
116
|
try {
|
|
100
117
|
const [newField, setNewField] = useState();
|
|
101
118
|
const state = modals.state.value;
|
|
102
|
-
const space = model?.space;
|
|
103
119
|
useEffect(() => {
|
|
104
120
|
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
105
121
|
setNewField(model.projection.createFieldProjection());
|
|
@@ -117,12 +133,12 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
|
117
133
|
if (state?.type === "columnSettings") {
|
|
118
134
|
const { mode } = state;
|
|
119
135
|
if (mode.type === "edit") {
|
|
120
|
-
return model?.
|
|
136
|
+
return model?.projection?.fields.find((f) => f.id === mode.fieldId);
|
|
121
137
|
}
|
|
122
138
|
}
|
|
123
139
|
return void 0;
|
|
124
140
|
}, [
|
|
125
|
-
model?.
|
|
141
|
+
model?.projection?.fields,
|
|
126
142
|
state
|
|
127
143
|
]);
|
|
128
144
|
const field = existingField ?? newField;
|
|
@@ -133,14 +149,14 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
|
133
149
|
]);
|
|
134
150
|
const handleCancel = useCallback(() => {
|
|
135
151
|
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
136
|
-
model?.projection
|
|
152
|
+
model?.projection.deleteFieldProjection(newField.id);
|
|
137
153
|
}
|
|
138
154
|
}, [
|
|
139
155
|
model?.projection,
|
|
140
156
|
state,
|
|
141
157
|
newField
|
|
142
158
|
]);
|
|
143
|
-
if (!model?.
|
|
159
|
+
if (!model?.projection || !field) {
|
|
144
160
|
return null;
|
|
145
161
|
}
|
|
146
162
|
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
@@ -151,10 +167,9 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
|
151
167
|
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
152
168
|
classNames: "md:is-64"
|
|
153
169
|
}, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
|
|
154
|
-
view: model.view,
|
|
155
170
|
projection: model.projection,
|
|
156
171
|
field,
|
|
157
|
-
registry
|
|
172
|
+
registry,
|
|
158
173
|
onSave: handleSave,
|
|
159
174
|
onCancel: handleCancel
|
|
160
175
|
})), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
|
|
@@ -163,11 +178,12 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
|
163
178
|
}
|
|
164
179
|
};
|
|
165
180
|
|
|
166
|
-
//
|
|
181
|
+
// src/components/Table/CreateRefPanel.tsx
|
|
167
182
|
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
168
183
|
import { Schema } from "effect";
|
|
169
184
|
import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
170
|
-
import { live } from "@dxos/
|
|
185
|
+
import { live } from "@dxos/live-object";
|
|
186
|
+
import { getSpace } from "@dxos/react-client/echo";
|
|
171
187
|
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
172
188
|
import { Form } from "@dxos/react-ui-form";
|
|
173
189
|
import { useGridContext } from "@dxos/react-ui-grid";
|
|
@@ -175,7 +191,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
|
175
191
|
var _effect = _useSignals3();
|
|
176
192
|
try {
|
|
177
193
|
const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
|
|
178
|
-
const space = model?.
|
|
194
|
+
const space = model && getSpace(model?.view);
|
|
179
195
|
const state = modals.state.value;
|
|
180
196
|
const schema = useMemo2(() => {
|
|
181
197
|
if (!space || state?.type !== "createRefPanel") {
|
|
@@ -216,7 +232,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
|
216
232
|
}, [
|
|
217
233
|
modals
|
|
218
234
|
]);
|
|
219
|
-
if (!model?.
|
|
235
|
+
if (!model?.projection) {
|
|
220
236
|
return null;
|
|
221
237
|
}
|
|
222
238
|
return /* @__PURE__ */ React3.createElement(Popover2.Root, {
|
|
@@ -243,7 +259,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
|
243
259
|
}
|
|
244
260
|
};
|
|
245
261
|
|
|
246
|
-
//
|
|
262
|
+
// src/components/Table/RowActionsMenu.tsx
|
|
247
263
|
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
248
264
|
import React4 from "react";
|
|
249
265
|
import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
@@ -278,1445 +294,32 @@ var RowActionsMenu = ({ model, modals }) => {
|
|
|
278
294
|
}
|
|
279
295
|
};
|
|
280
296
|
|
|
281
|
-
//
|
|
282
|
-
import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
|
|
283
|
-
import { Resource as Resource2 } from "@dxos/context";
|
|
284
|
-
import { FormatEnum as FormatEnum3, getValue as getValue2, setValue, getSnapshot, getSchema } from "@dxos/echo-schema";
|
|
285
|
-
import { invariant } from "@dxos/invariant";
|
|
286
|
-
import { isLiveObject, makeRef } from "@dxos/live-object";
|
|
287
|
-
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
288
|
-
import { validateSchema } from "@dxos/schema";
|
|
289
|
-
|
|
290
|
-
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
291
|
-
import { computed, effect, signal } from "@preact/signals-core";
|
|
292
|
-
import { Resource } from "@dxos/context";
|
|
293
|
-
|
|
294
|
-
// packages/ui/react-ui-table/src/util/dynamic-table.ts
|
|
295
|
-
import { Obj, Ref } from "@dxos/echo";
|
|
296
|
-
import { getTypename, toJsonSchema } from "@dxos/echo-schema";
|
|
297
|
-
import { createView, getSchemaFromPropertyDefinitions, ViewProjection } from "@dxos/schema";
|
|
298
|
-
var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
|
|
299
|
-
if (typename && properties) {
|
|
300
|
-
const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
|
|
301
|
-
return {
|
|
302
|
-
typename: schema2.typename,
|
|
303
|
-
jsonSchema: schema2.jsonSchema
|
|
304
|
-
};
|
|
305
|
-
} else if (schema) {
|
|
306
|
-
return {
|
|
307
|
-
typename: getTypename(schema),
|
|
308
|
-
jsonSchema: toJsonSchema(schema)
|
|
309
|
-
};
|
|
310
|
-
} else if (typename && jsonSchema) {
|
|
311
|
-
return {
|
|
312
|
-
typename,
|
|
313
|
-
jsonSchema
|
|
314
|
-
};
|
|
315
|
-
} else {
|
|
316
|
-
throw new Error("invalid properties");
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
|
|
320
|
-
const view = createView({
|
|
321
|
-
name: "dynamic-table",
|
|
322
|
-
typename,
|
|
323
|
-
jsonSchema,
|
|
324
|
-
...properties && {
|
|
325
|
-
fields: properties.map((property) => property.name)
|
|
326
|
-
}
|
|
327
|
-
});
|
|
328
|
-
const table = Obj.make(TableType, {
|
|
329
|
-
name: "dynamic-table",
|
|
330
|
-
view: Ref.make(view)
|
|
331
|
-
});
|
|
332
|
-
const projection = new ViewProjection(jsonSchema, view);
|
|
333
|
-
if (properties && view.fields) {
|
|
334
|
-
setProperties(view, projection, properties);
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
table,
|
|
338
|
-
projection
|
|
339
|
-
};
|
|
340
|
-
};
|
|
341
|
-
var setProperties = (view, projection, properties) => {
|
|
342
|
-
for (const property of properties) {
|
|
343
|
-
const field = view.fields.find((field2) => field2.path === property.name);
|
|
344
|
-
if (field) {
|
|
345
|
-
if (property.size !== void 0) {
|
|
346
|
-
field.size = property.size;
|
|
347
|
-
}
|
|
348
|
-
if (property.title !== void 0) {
|
|
349
|
-
const fieldProjection = projection.getFieldProjection(field.id);
|
|
350
|
-
projection.setFieldProjection({
|
|
351
|
-
...fieldProjection,
|
|
352
|
-
props: {
|
|
353
|
-
...fieldProjection.props,
|
|
354
|
-
title: property.title
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
if (property.sort) {
|
|
359
|
-
const fieldId = field.id;
|
|
360
|
-
view.query.sort = [
|
|
361
|
-
{
|
|
362
|
-
fieldId,
|
|
363
|
-
direction: property.sort
|
|
364
|
-
}
|
|
365
|
-
];
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
// packages/ui/react-ui-table/src/util/signals.ts
|
|
372
|
-
var touch = (value) => value;
|
|
373
|
-
|
|
374
|
-
// packages/ui/react-ui-table/src/util/table.ts
|
|
375
|
-
import { Schema as Schema2 } from "effect";
|
|
376
|
-
import { Format, FormatEnum, Ref as Ref2, TypedObject, TypeEnum } from "@dxos/echo-schema";
|
|
377
|
-
import { PublicKey } from "@dxos/react-client";
|
|
378
|
-
import { live as live2 } from "@dxos/react-client/echo";
|
|
379
|
-
import { createFieldId, createView as createView2, getSchemaProperties, ViewProjection as ViewProjection2 } from "@dxos/schema";
|
|
380
|
-
var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
|
|
381
|
-
if (typename) {
|
|
382
|
-
const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
|
|
383
|
-
if (!schema) {
|
|
384
|
-
throw new Error(`Schema not found: ${typename}`);
|
|
385
|
-
}
|
|
386
|
-
const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
|
|
387
|
-
table.view = Ref2.make(createView2({
|
|
388
|
-
// TODO(ZaymonFC): Don't hardcode name?
|
|
389
|
-
name: "View",
|
|
390
|
-
typename: schema.typename,
|
|
391
|
-
jsonSchema: schema.jsonSchema,
|
|
392
|
-
fields
|
|
393
|
-
}));
|
|
394
|
-
return schema;
|
|
395
|
-
} else {
|
|
396
|
-
const [schema] = await space.db.schemaRegistry.register([
|
|
397
|
-
createContactSchema()
|
|
398
|
-
]);
|
|
399
|
-
const fields = ContactFields;
|
|
400
|
-
table.view = Ref2.make(createView2({
|
|
401
|
-
name: "View",
|
|
402
|
-
typename: schema.typename,
|
|
403
|
-
jsonSchema: schema.jsonSchema,
|
|
404
|
-
fields
|
|
405
|
-
}));
|
|
406
|
-
createProjection(schema, table.view.target);
|
|
407
|
-
if (initialRow) {
|
|
408
|
-
space.db.add(live2(schema, {}));
|
|
409
|
-
}
|
|
410
|
-
return schema;
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
var createContactSchema = () => TypedObject({
|
|
414
|
-
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
415
|
-
version: "0.1.0"
|
|
416
|
-
})({
|
|
417
|
-
name: Schema2.optional(Schema2.String).annotations({
|
|
418
|
-
title: "Name"
|
|
419
|
-
}),
|
|
420
|
-
active: Schema2.optional(Schema2.Boolean).annotations({
|
|
421
|
-
title: "Active"
|
|
422
|
-
}),
|
|
423
|
-
email: Schema2.optional(Format.Email),
|
|
424
|
-
salary: Schema2.optional(Format.Currency()).annotations({
|
|
425
|
-
title: "Salary"
|
|
426
|
-
})
|
|
427
|
-
});
|
|
428
|
-
var ContactFields = [
|
|
429
|
-
"name",
|
|
430
|
-
"email",
|
|
431
|
-
"salary",
|
|
432
|
-
"active"
|
|
433
|
-
];
|
|
434
|
-
var createProjection = (schema, view) => {
|
|
435
|
-
const projection = new ViewProjection2(schema.jsonSchema, view);
|
|
436
|
-
projection.setFieldProjection({
|
|
437
|
-
field: {
|
|
438
|
-
id: view.fields.find((f) => f.path === "salary").id,
|
|
439
|
-
path: "salary",
|
|
440
|
-
size: 150
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
projection.setFieldProjection({
|
|
444
|
-
field: {
|
|
445
|
-
id: view.fields.find((f) => f.path === "active").id,
|
|
446
|
-
path: "active",
|
|
447
|
-
size: 100
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
projection.setFieldProjection({
|
|
451
|
-
field: {
|
|
452
|
-
id: createFieldId(),
|
|
453
|
-
path: "manager",
|
|
454
|
-
referencePath: "name"
|
|
455
|
-
},
|
|
456
|
-
props: {
|
|
457
|
-
property: "manager",
|
|
458
|
-
type: TypeEnum.Ref,
|
|
459
|
-
format: FormatEnum.Ref,
|
|
460
|
-
referenceSchema: schema.typename,
|
|
461
|
-
title: "Manager"
|
|
462
|
-
}
|
|
463
|
-
});
|
|
464
|
-
return projection;
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
// packages/ui/react-ui-table/src/util/table-buttons.ts
|
|
468
|
-
var BUTTON_IDENTIFIERS = {
|
|
469
|
-
columnSettings: "data-table-column-settings-button",
|
|
470
|
-
newColumn: "data-table-new-column-button",
|
|
471
|
-
referencedCell: "data-table-ref-cell-button",
|
|
472
|
-
rowMenu: "data-table-row-menu-button",
|
|
473
|
-
sort: "data-table-sort-button"
|
|
474
|
-
};
|
|
475
|
-
var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
|
|
476
|
-
const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
477
|
-
const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
|
|
478
|
-
return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? "disabled" : ""}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
479
|
-
};
|
|
480
|
-
var addColumnButton = {
|
|
481
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
482
|
-
icon: "ph--plus--regular",
|
|
483
|
-
render: ({ disabled }) => {
|
|
484
|
-
return createButton({
|
|
485
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
486
|
-
icon: addColumnButton.icon,
|
|
487
|
-
disabled,
|
|
488
|
-
data: {},
|
|
489
|
-
testId: "table-new-column-button"
|
|
490
|
-
});
|
|
491
|
-
},
|
|
492
|
-
getData: (_el) => ({
|
|
493
|
-
type: "newColumn"
|
|
494
|
-
})
|
|
495
|
-
};
|
|
496
|
-
var columnSettingsButton = {
|
|
497
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
498
|
-
icon: "ph--caret-down--regular",
|
|
499
|
-
render: ({ fieldId }) => {
|
|
500
|
-
return createButton({
|
|
501
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
502
|
-
icon: columnSettingsButton.icon,
|
|
503
|
-
data: {
|
|
504
|
-
"data-field-id": fieldId
|
|
505
|
-
},
|
|
506
|
-
testId: "table-column-settings-button"
|
|
507
|
-
});
|
|
508
|
-
},
|
|
509
|
-
getData: (el) => ({
|
|
510
|
-
type: "columnSettings",
|
|
511
|
-
fieldId: el.getAttribute("data-field-id")
|
|
512
|
-
})
|
|
513
|
-
};
|
|
514
|
-
var rowMenuButton = {
|
|
515
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
516
|
-
icon: "ph--dots-three--regular",
|
|
517
|
-
render: ({ rowIndex }) => {
|
|
518
|
-
return createButton({
|
|
519
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
520
|
-
icon: rowMenuButton.icon,
|
|
521
|
-
data: {
|
|
522
|
-
"data-row-index": rowIndex.toString()
|
|
523
|
-
},
|
|
524
|
-
testId: "table-row-menu-button"
|
|
525
|
-
});
|
|
526
|
-
},
|
|
527
|
-
getData: (el) => ({
|
|
528
|
-
type: "rowMenu",
|
|
529
|
-
rowIndex: Number(el.getAttribute("data-row-index"))
|
|
530
|
-
})
|
|
531
|
-
};
|
|
532
|
-
var sortButton = {
|
|
533
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
534
|
-
icon: "ph--sort-ascending--regular",
|
|
535
|
-
render: ({ fieldId, direction }) => {
|
|
536
|
-
return createButton({
|
|
537
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
538
|
-
icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
|
|
539
|
-
data: {
|
|
540
|
-
"data-field-id": fieldId,
|
|
541
|
-
"data-direction": direction ?? ""
|
|
542
|
-
},
|
|
543
|
-
testId: "table-sort-button",
|
|
544
|
-
// TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
|
|
545
|
-
// This is a bit hacky.
|
|
546
|
-
type: "secondary"
|
|
547
|
-
});
|
|
548
|
-
},
|
|
549
|
-
getData: (el) => ({
|
|
550
|
-
type: "sort",
|
|
551
|
-
fieldId: el.getAttribute("data-field-id"),
|
|
552
|
-
direction: el.getAttribute("data-direction")
|
|
553
|
-
})
|
|
554
|
-
};
|
|
555
|
-
var tableButtons = {
|
|
556
|
-
addColumn: addColumnButton,
|
|
557
|
-
columnSettings: columnSettingsButton,
|
|
558
|
-
rowMenu: rowMenuButton,
|
|
559
|
-
sort: sortButton
|
|
560
|
-
};
|
|
561
|
-
|
|
562
|
-
// packages/ui/react-ui-table/src/util/table-controls.ts
|
|
563
|
-
var CONTROL_IDENTIFIERS = {
|
|
564
|
-
checkbox: "data-table-checkbox",
|
|
565
|
-
switch: "data-table-switch"
|
|
566
|
-
};
|
|
567
|
-
var BASE_CLASSES = {
|
|
568
|
-
checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
|
|
569
|
-
switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
|
|
570
|
-
};
|
|
571
|
-
var renderAttributes = (data) => {
|
|
572
|
-
return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
573
|
-
};
|
|
574
|
-
var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
|
|
575
|
-
return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
|
|
576
|
-
};
|
|
577
|
-
var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
|
|
578
|
-
const attrs = {
|
|
579
|
-
[CONTROL_IDENTIFIERS.checkbox]: "",
|
|
580
|
-
"data-row-index": rowIndex.toString(),
|
|
581
|
-
...header && {
|
|
582
|
-
"data-header": ""
|
|
583
|
-
}
|
|
584
|
-
};
|
|
585
|
-
return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
|
|
586
|
-
};
|
|
587
|
-
var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
|
|
588
|
-
const attrs = {
|
|
589
|
-
[CONTROL_IDENTIFIERS.switch]: "",
|
|
590
|
-
"data-row-index": rowIndex.toString(),
|
|
591
|
-
"data-col-index": colIndex.toString()
|
|
592
|
-
};
|
|
593
|
-
return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
|
|
594
|
-
};
|
|
595
|
-
var tableControls = {
|
|
596
|
-
checkbox: {
|
|
597
|
-
attr: CONTROL_IDENTIFIERS.checkbox,
|
|
598
|
-
render: CheckboxStory,
|
|
599
|
-
getData: (el) => ({
|
|
600
|
-
type: "checkbox",
|
|
601
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
602
|
-
header: el.hasAttribute("data-header")
|
|
603
|
-
})
|
|
604
|
-
},
|
|
605
|
-
switch: {
|
|
606
|
-
attr: CONTROL_IDENTIFIERS.switch,
|
|
607
|
-
render: SwitchStory,
|
|
608
|
-
getData: (el) => ({
|
|
609
|
-
type: "switch",
|
|
610
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
611
|
-
colIndex: Number(el.getAttribute("data-col-index"))
|
|
612
|
-
})
|
|
613
|
-
}
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
// packages/ui/react-ui-table/src/util/schema.ts
|
|
617
|
-
import { Schema as Schema3 } from "effect";
|
|
618
|
-
import { isTypeLiteral, TypeLiteral } from "effect/SchemaAST";
|
|
619
|
-
var narrowSchema = (schema, paths) => {
|
|
620
|
-
const ast = schema?.ast;
|
|
621
|
-
if (isTypeLiteral(ast)) {
|
|
622
|
-
const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
|
|
623
|
-
if (propertySignatures.length > 0) {
|
|
624
|
-
const narrowType = new TypeLiteral(propertySignatures, []);
|
|
625
|
-
return Schema3.make(narrowType);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
return void 0;
|
|
629
|
-
};
|
|
630
|
-
|
|
631
|
-
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
632
|
-
var SelectionModel = class extends Resource {
|
|
633
|
-
constructor(_rows, _selectionMode, _onSelectionChanged) {
|
|
634
|
-
super(), this._rows = _rows, this._selectionMode = _selectionMode, this._onSelectionChanged = _onSelectionChanged, this._selection = signal(/* @__PURE__ */ new Set()), this._validSelectedIds = computed(() => {
|
|
635
|
-
const rows = this._rows.value;
|
|
636
|
-
if (!rows) {
|
|
637
|
-
return /* @__PURE__ */ new Set();
|
|
638
|
-
}
|
|
639
|
-
const validIds = new Set(rows.map((row) => row.id));
|
|
640
|
-
return new Set([
|
|
641
|
-
...this._selection.value
|
|
642
|
-
].filter((id) => validIds.has(id)));
|
|
643
|
-
}), this._hasSelection = computed(() => this._validSelectedIds.value.size > 0), this._allSelected = computed(() => {
|
|
644
|
-
const rows = this._rows.value;
|
|
645
|
-
if (rows.length === 0) {
|
|
646
|
-
return false;
|
|
647
|
-
}
|
|
648
|
-
return rows.every((row) => this._selection.value.has(row.id));
|
|
649
|
-
}), this.getSelectedRows = () => {
|
|
650
|
-
const selectedIds = this._validSelectedIds.value;
|
|
651
|
-
return this._rows.value.filter((row) => selectedIds.has(row.id));
|
|
652
|
-
}, this.isRowIndexSelected = (rowIndex) => {
|
|
653
|
-
const row = this._rows.value[rowIndex];
|
|
654
|
-
return this._selection.value.has(row.id);
|
|
655
|
-
}, this.isObjectSelected = (object) => {
|
|
656
|
-
return this._selection.value.has(object.id);
|
|
657
|
-
}, this.toggleSelectionForRowIndex = (rowIndex) => {
|
|
658
|
-
const row = this._rows.value[rowIndex];
|
|
659
|
-
const newSelection = new Set(this._selection.value);
|
|
660
|
-
if (newSelection.has(row.id)) {
|
|
661
|
-
newSelection.delete(row.id);
|
|
662
|
-
} else {
|
|
663
|
-
if (this._selectionMode === "single") {
|
|
664
|
-
newSelection.clear();
|
|
665
|
-
}
|
|
666
|
-
newSelection.add(row.id);
|
|
667
|
-
}
|
|
668
|
-
this._selection.value = newSelection;
|
|
669
|
-
}, this.setSelection = (mode) => {
|
|
670
|
-
switch (mode) {
|
|
671
|
-
case "all": {
|
|
672
|
-
this._selection.value = new Set(this._rows.value.map((row) => row.id));
|
|
673
|
-
break;
|
|
674
|
-
}
|
|
675
|
-
case "none": {
|
|
676
|
-
this._selection.value = /* @__PURE__ */ new Set();
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
async _open() {
|
|
683
|
-
const selectionWatcher = effect(() => {
|
|
684
|
-
touch(this._selection.value);
|
|
685
|
-
this._onSelectionChanged?.();
|
|
686
|
-
});
|
|
687
|
-
this._ctx.onDispose(selectionWatcher);
|
|
688
|
-
}
|
|
689
|
-
//
|
|
690
|
-
// Getters
|
|
691
|
-
//
|
|
692
|
-
get selection() {
|
|
693
|
-
return this._selection;
|
|
694
|
-
}
|
|
695
|
-
get hasSelection() {
|
|
696
|
-
return this._hasSelection;
|
|
697
|
-
}
|
|
698
|
-
get allRowsSeleted() {
|
|
699
|
-
return this._allSelected;
|
|
700
|
-
}
|
|
701
|
-
get selectionMode() {
|
|
702
|
-
return this._selectionMode;
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
// packages/ui/react-ui-table/src/model/table-sorting.ts
|
|
707
|
-
import { computed as computed2, signal as signal2 } from "@preact/signals-core";
|
|
708
|
-
import orderBy from "lodash.orderby";
|
|
709
|
-
import { getValue, FormatEnum as FormatEnum2, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
710
|
-
import { formatForDisplay } from "@dxos/react-ui-form";
|
|
711
|
-
var TableSorting = class {
|
|
712
|
-
constructor(rows, _view, _projection) {
|
|
713
|
-
this._view = _view;
|
|
714
|
-
this._projection = _projection;
|
|
715
|
-
this._displayToDataIndex = /* @__PURE__ */ new Map();
|
|
716
|
-
this._localSort = signal2(void 0);
|
|
717
|
-
this._rows = rows;
|
|
718
|
-
this._isDirty = computed2(() => {
|
|
719
|
-
const local = this._localSort.value;
|
|
720
|
-
const viewSort = this._view?.query.sort?.[0];
|
|
721
|
-
if (local?.type === "cleared") {
|
|
722
|
-
return viewSort !== void 0;
|
|
723
|
-
}
|
|
724
|
-
if (local?.type === "active") {
|
|
725
|
-
if (!viewSort) {
|
|
726
|
-
return true;
|
|
727
|
-
}
|
|
728
|
-
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
729
|
-
}
|
|
730
|
-
return false;
|
|
731
|
-
});
|
|
732
|
-
this.sortedRows = this.initialiseSortedRows();
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* @reactive
|
|
736
|
-
* @returns Local sort if present, falls back to view sort.
|
|
737
|
-
*/
|
|
738
|
-
get sorting() {
|
|
739
|
-
const local = this._localSort.value;
|
|
740
|
-
if (local?.type === "cleared") {
|
|
741
|
-
return void 0;
|
|
742
|
-
}
|
|
743
|
-
if (local?.type === "active") {
|
|
744
|
-
return local.sort;
|
|
745
|
-
}
|
|
746
|
-
return this._view?.query.sort?.[0];
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* @reactive
|
|
750
|
-
* @returns Whether local sort differs from view sort.
|
|
751
|
-
*/
|
|
752
|
-
get isDirty() {
|
|
753
|
-
return this._isDirty.value;
|
|
754
|
-
}
|
|
755
|
-
getDataIndex(displayIndex) {
|
|
756
|
-
return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
|
|
757
|
-
}
|
|
758
|
-
setSort(fieldId, direction) {
|
|
759
|
-
this._localSort.value = {
|
|
760
|
-
type: "active",
|
|
761
|
-
sort: {
|
|
762
|
-
fieldId,
|
|
763
|
-
direction
|
|
764
|
-
}
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
toggleSort(fieldId) {
|
|
768
|
-
if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
switch (this.sorting.direction) {
|
|
772
|
-
case "asc": {
|
|
773
|
-
this.setSort(fieldId, "desc");
|
|
774
|
-
break;
|
|
775
|
-
}
|
|
776
|
-
case "desc": {
|
|
777
|
-
this.setSort(fieldId, "asc");
|
|
778
|
-
break;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
clearSort() {
|
|
783
|
-
this._localSort.value = {
|
|
784
|
-
type: "cleared"
|
|
785
|
-
};
|
|
786
|
-
}
|
|
787
|
-
save() {
|
|
788
|
-
if (this._view && this._localSort.value !== void 0) {
|
|
789
|
-
if (this._localSort.value.type === "active") {
|
|
790
|
-
this._view.query.sort = [
|
|
791
|
-
this._localSort.value.sort
|
|
792
|
-
];
|
|
793
|
-
} else {
|
|
794
|
-
this._view.query.sort = [];
|
|
795
|
-
}
|
|
796
|
-
this._localSort.value = void 0;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
//
|
|
800
|
-
// Initialisation.
|
|
801
|
-
//
|
|
802
|
-
initialiseSortedRows() {
|
|
803
|
-
return computed2(() => {
|
|
804
|
-
this._displayToDataIndex.clear();
|
|
805
|
-
const sort = this.sorting;
|
|
806
|
-
if (!sort || !this._view) {
|
|
807
|
-
return this._rows.value;
|
|
808
|
-
}
|
|
809
|
-
const field = this._view.fields.find((f) => f.id === sort.fieldId);
|
|
810
|
-
if (!field) {
|
|
811
|
-
return this._rows.value;
|
|
812
|
-
}
|
|
813
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
814
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
815
|
-
const sortValue = this.getSortValue(props, field, item);
|
|
816
|
-
const isEmpty = !(props.type === TypeEnum2.Boolean) && (sortValue == null || sortValue === "");
|
|
817
|
-
return {
|
|
818
|
-
item,
|
|
819
|
-
index,
|
|
820
|
-
value: sortValue,
|
|
821
|
-
isEmpty
|
|
822
|
-
};
|
|
823
|
-
});
|
|
824
|
-
const ordered = orderBy(dataWithIndices, [
|
|
825
|
-
"isEmpty",
|
|
826
|
-
"value"
|
|
827
|
-
], [
|
|
828
|
-
"asc",
|
|
829
|
-
sort.direction
|
|
830
|
-
]);
|
|
831
|
-
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
832
|
-
if (displayIndex !== dataIndex) {
|
|
833
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
834
|
-
}
|
|
835
|
-
});
|
|
836
|
-
return ordered.map(({ item }) => item);
|
|
837
|
-
});
|
|
838
|
-
}
|
|
839
|
-
getSortValue(props, field, item) {
|
|
840
|
-
const { type, format } = props;
|
|
841
|
-
const value = getValue(item, field.path);
|
|
842
|
-
if (type === TypeEnum2.Boolean) {
|
|
843
|
-
return !!value;
|
|
844
|
-
}
|
|
845
|
-
if (type === TypeEnum2.Number) {
|
|
846
|
-
return value;
|
|
847
|
-
}
|
|
848
|
-
if (value == null) {
|
|
849
|
-
return value;
|
|
850
|
-
}
|
|
851
|
-
if (format === FormatEnum2.SingleSelect) {
|
|
852
|
-
const options = props.options;
|
|
853
|
-
if (!options) {
|
|
854
|
-
return void 0;
|
|
855
|
-
}
|
|
856
|
-
const option = options.find((option2) => option2.id === value);
|
|
857
|
-
return option ? options.indexOf(option) : void 0;
|
|
858
|
-
}
|
|
859
|
-
if (format === FormatEnum2.Ref && field.referencePath) {
|
|
860
|
-
const refValue = getValue(value.target, field.referencePath);
|
|
861
|
-
return refValue;
|
|
862
|
-
}
|
|
863
|
-
return formatForDisplay({
|
|
864
|
-
type,
|
|
865
|
-
format,
|
|
866
|
-
value
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
|
|
871
|
-
// packages/ui/react-ui-table/src/util/tag.ts
|
|
872
|
-
var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
873
|
-
var extractTagIds = (value) => {
|
|
874
|
-
if (typeof value !== "string") {
|
|
875
|
-
return void 0;
|
|
876
|
-
}
|
|
877
|
-
const ids = [];
|
|
878
|
-
let match;
|
|
879
|
-
while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
|
|
880
|
-
if (match[2]) {
|
|
881
|
-
ids.push(match[2]);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
return ids.length > 0 ? ids : void 0;
|
|
885
|
-
};
|
|
886
|
-
|
|
887
|
-
// packages/ui/react-ui-table/src/model/table-model.ts
|
|
888
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
889
|
-
var defaultFeatures = {
|
|
890
|
-
selection: {
|
|
891
|
-
enabled: true,
|
|
892
|
-
mode: "multiple"
|
|
893
|
-
},
|
|
894
|
-
dataEditable: false,
|
|
895
|
-
schemaEditable: false
|
|
896
|
-
};
|
|
897
|
-
var TableModel = class extends Resource2 {
|
|
898
|
-
constructor({ id, space, view, projection, features = {}, sorting = [], pinnedRows = {
|
|
899
|
-
top: [],
|
|
900
|
-
bottom: []
|
|
901
|
-
}, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
|
|
902
|
-
super();
|
|
903
|
-
this._visibleRange = signal3({
|
|
904
|
-
start: {
|
|
905
|
-
row: 0,
|
|
906
|
-
col: 0
|
|
907
|
-
},
|
|
908
|
-
end: {
|
|
909
|
-
row: 0,
|
|
910
|
-
col: 0
|
|
911
|
-
}
|
|
912
|
-
});
|
|
913
|
-
this._rows = signal3([]);
|
|
914
|
-
//
|
|
915
|
-
// Data
|
|
916
|
-
//
|
|
917
|
-
this.setRows = (obj) => {
|
|
918
|
-
this._rows.value = obj;
|
|
919
|
-
};
|
|
920
|
-
this.getRowCount = () => this._rows.value.length;
|
|
921
|
-
this.getColumnCount = () => this._view?.fields.length ?? 0;
|
|
922
|
-
this.insertRow = (rowIndex) => {
|
|
923
|
-
const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
|
|
924
|
-
this._onInsertRow?.(row);
|
|
925
|
-
};
|
|
926
|
-
this.deleteRow = (rowIndex) => {
|
|
927
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
928
|
-
const obj = this._rows.value[row];
|
|
929
|
-
const objectsToDelete = [];
|
|
930
|
-
if (this.features.selection.enabled && this._selection.hasSelection.value) {
|
|
931
|
-
const selectedRows = this._selection.getSelectedRows();
|
|
932
|
-
objectsToDelete.push(...selectedRows);
|
|
933
|
-
} else {
|
|
934
|
-
objectsToDelete.push(obj);
|
|
935
|
-
}
|
|
936
|
-
this._onDeleteRows?.(row, objectsToDelete);
|
|
937
|
-
};
|
|
938
|
-
this.handleRowAction = (actionId, rowIndex) => {
|
|
939
|
-
if (!this._onRowAction) {
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
943
|
-
const data = this._rows.value[row];
|
|
944
|
-
if (data) {
|
|
945
|
-
this._onRowAction(actionId, data);
|
|
946
|
-
}
|
|
947
|
-
};
|
|
948
|
-
this.getCellData = ({ col, row }) => {
|
|
949
|
-
const fields = this._view?.fields ?? [];
|
|
950
|
-
if (col < 0 || col >= fields.length) {
|
|
951
|
-
return void 0;
|
|
952
|
-
}
|
|
953
|
-
const field = fields[col];
|
|
954
|
-
const dataIndex = this._sorting.getDataIndex(row);
|
|
955
|
-
const value = getValue2(this._rows.value[dataIndex], field.path);
|
|
956
|
-
if (value == null) {
|
|
957
|
-
return "";
|
|
958
|
-
}
|
|
959
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
960
|
-
switch (props.format) {
|
|
961
|
-
case FormatEnum3.Ref: {
|
|
962
|
-
if (!field.referencePath) {
|
|
963
|
-
return "";
|
|
964
|
-
}
|
|
965
|
-
return getValue2(value.target, field.referencePath);
|
|
966
|
-
}
|
|
967
|
-
default: {
|
|
968
|
-
return formatForEditing({
|
|
969
|
-
type: props.type,
|
|
970
|
-
format: props.format,
|
|
971
|
-
value
|
|
972
|
-
});
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
};
|
|
976
|
-
this.validateCellData = async ({ col, row }, value) => {
|
|
977
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
978
|
-
const fields = this._view?.fields ?? [];
|
|
979
|
-
if (col < 0 || col >= fields.length) {
|
|
980
|
-
return {
|
|
981
|
-
valid: false,
|
|
982
|
-
error: "Invalid column index"
|
|
983
|
-
};
|
|
984
|
-
}
|
|
985
|
-
const field = fields[col];
|
|
986
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
987
|
-
const currentRow = this._rows.value[rowIdx];
|
|
988
|
-
invariant(currentRow, "Invalid row index", {
|
|
989
|
-
F: __dxlog_file,
|
|
990
|
-
L: 355,
|
|
991
|
-
S: this,
|
|
992
|
-
A: [
|
|
993
|
-
"currentRow",
|
|
994
|
-
"'Invalid row index'"
|
|
995
|
-
]
|
|
996
|
-
});
|
|
997
|
-
const snapshot = getSnapshot(currentRow);
|
|
998
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
999
|
-
setValue(snapshot, field.path, transformedValue);
|
|
1000
|
-
const schema = getSchema(currentRow);
|
|
1001
|
-
invariant(schema, void 0, {
|
|
1002
|
-
F: __dxlog_file,
|
|
1003
|
-
L: 365,
|
|
1004
|
-
S: this,
|
|
1005
|
-
A: [
|
|
1006
|
-
"schema",
|
|
1007
|
-
""
|
|
1008
|
-
]
|
|
1009
|
-
});
|
|
1010
|
-
const validationResult = validateSchema(schema, snapshot);
|
|
1011
|
-
if (validationResult && validationResult.length > 0) {
|
|
1012
|
-
const error = validationResult[0];
|
|
1013
|
-
invariant(error.path === field.path, void 0, {
|
|
1014
|
-
F: __dxlog_file,
|
|
1015
|
-
L: 370,
|
|
1016
|
-
S: this,
|
|
1017
|
-
A: [
|
|
1018
|
-
"error.path === field.path",
|
|
1019
|
-
""
|
|
1020
|
-
]
|
|
1021
|
-
});
|
|
1022
|
-
return {
|
|
1023
|
-
valid: false,
|
|
1024
|
-
error: error.message
|
|
1025
|
-
};
|
|
1026
|
-
}
|
|
1027
|
-
return {
|
|
1028
|
-
valid: true
|
|
1029
|
-
};
|
|
1030
|
-
};
|
|
1031
|
-
this.setCellData = ({ col, row }, value) => {
|
|
1032
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
1033
|
-
const fields = this._view?.fields ?? [];
|
|
1034
|
-
if (col < 0 || col >= fields.length) {
|
|
1035
|
-
return;
|
|
1036
|
-
}
|
|
1037
|
-
const field = fields[col];
|
|
1038
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1039
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
1040
|
-
if (props.format === FormatEnum3.Ref && !isLiveObject(value)) {
|
|
1041
|
-
return;
|
|
1042
|
-
}
|
|
1043
|
-
setValue(this._rows.value[rowIdx], field.path, transformedValue);
|
|
1044
|
-
};
|
|
1045
|
-
this._id = id;
|
|
1046
|
-
this._space = space;
|
|
1047
|
-
this._view = view;
|
|
1048
|
-
this._projection = projection;
|
|
1049
|
-
this._features = {
|
|
1050
|
-
...defaultFeatures,
|
|
1051
|
-
...features
|
|
1052
|
-
};
|
|
1053
|
-
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
|
|
1054
|
-
F: __dxlog_file,
|
|
1055
|
-
L: 126,
|
|
1056
|
-
S: this,
|
|
1057
|
-
A: [
|
|
1058
|
-
"!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
|
|
1059
|
-
"'Single selection is not compatible with editable tables.'"
|
|
1060
|
-
]
|
|
1061
|
-
});
|
|
1062
|
-
this._sorting = new TableSorting(this._rows, this._view, projection);
|
|
1063
|
-
if (sorting.length > 0) {
|
|
1064
|
-
const [sort] = sorting;
|
|
1065
|
-
this._sorting.setSort(sort.fieldId, sort.direction);
|
|
1066
|
-
}
|
|
1067
|
-
this._pinnedRows = pinnedRows;
|
|
1068
|
-
this._rowActions = rowActions;
|
|
1069
|
-
this._onInsertRow = onInsertRow;
|
|
1070
|
-
this._onDeleteRows = onDeleteRows;
|
|
1071
|
-
this._onDeleteColumn = onDeleteColumn;
|
|
1072
|
-
this._onCellUpdate = onCellUpdate;
|
|
1073
|
-
this._onRowOrderChange = onRowOrderChange;
|
|
1074
|
-
this._onRowAction = onRowAction;
|
|
1075
|
-
}
|
|
1076
|
-
get id() {
|
|
1077
|
-
return this._id;
|
|
1078
|
-
}
|
|
1079
|
-
get space() {
|
|
1080
|
-
return this._space;
|
|
1081
|
-
}
|
|
1082
|
-
get view() {
|
|
1083
|
-
return this._view;
|
|
1084
|
-
}
|
|
1085
|
-
get projection() {
|
|
1086
|
-
return this._projection;
|
|
1087
|
-
}
|
|
1088
|
-
get rows() {
|
|
1089
|
-
return this._sorting.sortedRows;
|
|
1090
|
-
}
|
|
1091
|
-
get features() {
|
|
1092
|
-
return this._features;
|
|
1093
|
-
}
|
|
1094
|
-
/**
|
|
1095
|
-
* @reactive
|
|
1096
|
-
*/
|
|
1097
|
-
get sorting() {
|
|
1098
|
-
return this._sorting;
|
|
1099
|
-
}
|
|
1100
|
-
/**
|
|
1101
|
-
* Gets the row data at the specified display index.
|
|
1102
|
-
*/
|
|
1103
|
-
getRowAt(displayIndex) {
|
|
1104
|
-
if (displayIndex < 0 || displayIndex >= this._sorting.sortedRows.value.length) {
|
|
1105
|
-
return void 0;
|
|
1106
|
-
}
|
|
1107
|
-
return this._sorting.sortedRows.value[displayIndex];
|
|
1108
|
-
}
|
|
1109
|
-
get pinnedRows() {
|
|
1110
|
-
return this._pinnedRows;
|
|
1111
|
-
}
|
|
1112
|
-
get columnMeta() {
|
|
1113
|
-
invariant(this._columnMeta, void 0, {
|
|
1114
|
-
F: __dxlog_file,
|
|
1115
|
-
L: 195,
|
|
1116
|
-
S: this,
|
|
1117
|
-
A: [
|
|
1118
|
-
"this._columnMeta",
|
|
1119
|
-
""
|
|
1120
|
-
]
|
|
1121
|
-
});
|
|
1122
|
-
return this._columnMeta;
|
|
1123
|
-
}
|
|
1124
|
-
get selection() {
|
|
1125
|
-
return this._selection;
|
|
1126
|
-
}
|
|
1127
|
-
/** @reactive */
|
|
1128
|
-
get isViewDirty() {
|
|
1129
|
-
return this._sorting.isDirty;
|
|
1130
|
-
}
|
|
1131
|
-
get rowActions() {
|
|
1132
|
-
return this._rowActions;
|
|
1133
|
-
}
|
|
1134
|
-
//
|
|
1135
|
-
// Initialisation
|
|
1136
|
-
//
|
|
1137
|
-
async _open() {
|
|
1138
|
-
this.initializeColumnMeta();
|
|
1139
|
-
this.initializeEffects();
|
|
1140
|
-
this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", () => this._onRowOrderChange?.());
|
|
1141
|
-
await this._selection.open(this._ctx);
|
|
1142
|
-
}
|
|
1143
|
-
initializeColumnMeta() {
|
|
1144
|
-
this._columnMeta = computed3(() => {
|
|
1145
|
-
const fields = this._view?.fields ?? [];
|
|
1146
|
-
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
1147
|
-
index,
|
|
1148
|
-
{
|
|
1149
|
-
size: field?.size ?? 256,
|
|
1150
|
-
resizeable: true
|
|
1151
|
-
}
|
|
1152
|
-
]));
|
|
1153
|
-
return {
|
|
1154
|
-
grid: meta,
|
|
1155
|
-
frozenColsStart: {
|
|
1156
|
-
0: {
|
|
1157
|
-
size: 30,
|
|
1158
|
-
resizeable: false
|
|
1159
|
-
}
|
|
1160
|
-
},
|
|
1161
|
-
frozenColsEnd: {
|
|
1162
|
-
0: {
|
|
1163
|
-
size: 40,
|
|
1164
|
-
resizeable: false
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
};
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
initializeEffects() {
|
|
1171
|
-
const rowOrderWatcher = effect2(() => {
|
|
1172
|
-
touch(this._sorting.sortedRows.value);
|
|
1173
|
-
this._onRowOrderChange?.();
|
|
1174
|
-
});
|
|
1175
|
-
this._ctx.onDispose(rowOrderWatcher);
|
|
1176
|
-
const rowEffectManager = effect2(() => {
|
|
1177
|
-
const { start, end } = touch(this._visibleRange.value);
|
|
1178
|
-
const rowEffects = [];
|
|
1179
|
-
for (let row = start.row; row <= end.row; row++) {
|
|
1180
|
-
rowEffects.push(effect2(() => {
|
|
1181
|
-
const obj = this._sorting.sortedRows.value[row];
|
|
1182
|
-
this._view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
|
|
1183
|
-
this._onCellUpdate?.({
|
|
1184
|
-
row,
|
|
1185
|
-
col: start.col,
|
|
1186
|
-
plane: "grid"
|
|
1187
|
-
});
|
|
1188
|
-
}));
|
|
1189
|
-
}
|
|
1190
|
-
return () => rowEffects.forEach((cleanup) => cleanup());
|
|
1191
|
-
});
|
|
1192
|
-
this._ctx.onDispose(rowEffectManager);
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* Updates a cell's value using a transform function.
|
|
1196
|
-
* @param {DxGridPlanePosition} position - The position of the cell to update.
|
|
1197
|
-
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1198
|
-
*/
|
|
1199
|
-
updateCellData({ col, row }, update) {
|
|
1200
|
-
const dataRow = this._sorting.getDataIndex(row);
|
|
1201
|
-
const fields = this._view?.fields ?? [];
|
|
1202
|
-
const field = fields[col];
|
|
1203
|
-
const value = getValue2(this._rows.value[dataRow], field.path);
|
|
1204
|
-
const updatedValue = update(value);
|
|
1205
|
-
setValue(this._rows.value[dataRow], field.path, updatedValue);
|
|
1206
|
-
}
|
|
1207
|
-
//
|
|
1208
|
-
// Column Operations
|
|
1209
|
-
//
|
|
1210
|
-
deleteColumn(fieldId) {
|
|
1211
|
-
if (!this._view) {
|
|
1212
|
-
return;
|
|
1213
|
-
}
|
|
1214
|
-
const field = this._view?.fields.find((field2) => field2.id === fieldId);
|
|
1215
|
-
if (field && this._onDeleteColumn) {
|
|
1216
|
-
this._onDeleteColumn(field.id);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
//
|
|
1220
|
-
// Resize
|
|
1221
|
-
//
|
|
1222
|
-
setColumnWidth(columnIndex, width) {
|
|
1223
|
-
const fields = this._view?.fields ?? [];
|
|
1224
|
-
if (columnIndex < fields.length) {
|
|
1225
|
-
const newWidth = Math.max(0, width);
|
|
1226
|
-
const field = fields[columnIndex];
|
|
1227
|
-
if (field) {
|
|
1228
|
-
field.size = newWidth;
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
//
|
|
1233
|
-
// Pinning
|
|
1234
|
-
//
|
|
1235
|
-
// TODO(burdon): Change to setPinned(on/off).
|
|
1236
|
-
pinRow(rowIndex, side) {
|
|
1237
|
-
this._pinnedRows[side].push(rowIndex);
|
|
1238
|
-
}
|
|
1239
|
-
unpinRow(rowIndex) {
|
|
1240
|
-
this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
|
|
1241
|
-
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1242
|
-
}
|
|
1243
|
-
//
|
|
1244
|
-
// View operations
|
|
1245
|
-
//
|
|
1246
|
-
saveView() {
|
|
1247
|
-
this._sorting.save();
|
|
1248
|
-
}
|
|
1249
|
-
};
|
|
1250
|
-
var editorTextToCellValue = (props, value) => {
|
|
1251
|
-
switch (props.format) {
|
|
1252
|
-
case FormatEnum3.Ref: {
|
|
1253
|
-
if (isLiveObject(value)) {
|
|
1254
|
-
return makeRef(value);
|
|
1255
|
-
} else {
|
|
1256
|
-
return value;
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
case FormatEnum3.SingleSelect: {
|
|
1260
|
-
const ids = extractTagIds(value);
|
|
1261
|
-
if (ids && ids.length > 0) {
|
|
1262
|
-
return ids[0];
|
|
1263
|
-
} else {
|
|
1264
|
-
return value;
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
case FormatEnum3.MultiSelect: {
|
|
1268
|
-
const ids = extractTagIds(value);
|
|
1269
|
-
return ids || value;
|
|
1270
|
-
}
|
|
1271
|
-
default: {
|
|
1272
|
-
return parseValue({
|
|
1273
|
-
type: props.type,
|
|
1274
|
-
format: props.format,
|
|
1275
|
-
value
|
|
1276
|
-
});
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
};
|
|
1280
|
-
|
|
1281
|
-
// packages/ui/react-ui-table/src/model/modal-controller.ts
|
|
1282
|
-
import { signal as signal4 } from "@preact/signals-core";
|
|
1283
|
-
import { log } from "@dxos/log";
|
|
1284
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
|
|
1285
|
-
var ModalController = class {
|
|
1286
|
-
constructor() {
|
|
1287
|
-
this._state = signal4({
|
|
1288
|
-
type: "closed"
|
|
1289
|
-
});
|
|
1290
|
-
this._triggerRef = {
|
|
1291
|
-
current: null
|
|
1292
|
-
};
|
|
1293
|
-
this.setTrigger = (trigger) => {
|
|
1294
|
-
this._triggerRef.current = trigger;
|
|
1295
|
-
};
|
|
1296
|
-
this.showRowMenu = (rowIndex) => {
|
|
1297
|
-
this._state.value = {
|
|
1298
|
-
type: "row",
|
|
1299
|
-
rowIndex
|
|
1300
|
-
};
|
|
1301
|
-
};
|
|
1302
|
-
this.showColumnMenu = (fieldId) => {
|
|
1303
|
-
this._state.value = {
|
|
1304
|
-
type: "column",
|
|
1305
|
-
fieldId
|
|
1306
|
-
};
|
|
1307
|
-
};
|
|
1308
|
-
this.showColumnCreator = () => {
|
|
1309
|
-
this._state.value = {
|
|
1310
|
-
type: "columnSettings",
|
|
1311
|
-
mode: {
|
|
1312
|
-
type: "create"
|
|
1313
|
-
}
|
|
1314
|
-
};
|
|
1315
|
-
};
|
|
1316
|
-
this.showReferencePanel = (targetId, schemaId) => {
|
|
1317
|
-
this._state.value = {
|
|
1318
|
-
type: "refPanel",
|
|
1319
|
-
targetId,
|
|
1320
|
-
typename: schemaId
|
|
1321
|
-
};
|
|
1322
|
-
};
|
|
1323
|
-
this.openColumnSettings = () => {
|
|
1324
|
-
if (this._state.value.type === "column") {
|
|
1325
|
-
const fieldId = this._state.value.fieldId;
|
|
1326
|
-
requestAnimationFrame(() => {
|
|
1327
|
-
this._state.value = {
|
|
1328
|
-
type: "columnSettings",
|
|
1329
|
-
mode: {
|
|
1330
|
-
type: "edit",
|
|
1331
|
-
fieldId
|
|
1332
|
-
}
|
|
1333
|
-
};
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
};
|
|
1337
|
-
this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
|
|
1338
|
-
if (anchorCell) {
|
|
1339
|
-
this._triggerRef.current = anchorCell;
|
|
1340
|
-
this._state.value = {
|
|
1341
|
-
type: "createRefPanel",
|
|
1342
|
-
typename,
|
|
1343
|
-
initialValues,
|
|
1344
|
-
onCreate
|
|
1345
|
-
};
|
|
1346
|
-
} else {
|
|
1347
|
-
log.warn("anchor cell not found while creating new ref", void 0, {
|
|
1348
|
-
F: __dxlog_file2,
|
|
1349
|
-
L: 86,
|
|
1350
|
-
S: this,
|
|
1351
|
-
C: (f, a) => f(...a)
|
|
1352
|
-
});
|
|
1353
|
-
}
|
|
1354
|
-
};
|
|
1355
|
-
this.close = () => {
|
|
1356
|
-
this._state.value = {
|
|
1357
|
-
type: "closed"
|
|
1358
|
-
};
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
get state() {
|
|
1362
|
-
return this._state;
|
|
1363
|
-
}
|
|
1364
|
-
get trigger() {
|
|
1365
|
-
return this._triggerRef;
|
|
1366
|
-
}
|
|
1367
|
-
};
|
|
1368
|
-
|
|
1369
|
-
// packages/ui/react-ui-table/src/model/table-presentation.ts
|
|
1370
|
-
import { signal as signal5 } from "@preact/signals-core";
|
|
1371
|
-
import { isNotNullable } from "effect/Predicate";
|
|
1372
|
-
import { FormatEnum as FormatEnum4, getObjectDXN, getValue as getValue3, TypeEnum as TypeEnum3 } from "@dxos/echo-schema";
|
|
1373
|
-
import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
|
|
1374
|
-
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
1375
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
1376
|
-
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1377
|
-
var TablePresentation = class {
|
|
1378
|
-
constructor(model, _visibleRange = signal5({
|
|
1379
|
-
start: {
|
|
1380
|
-
row: 0,
|
|
1381
|
-
col: 0
|
|
1382
|
-
},
|
|
1383
|
-
end: {
|
|
1384
|
-
row: 0,
|
|
1385
|
-
col: 0
|
|
1386
|
-
}
|
|
1387
|
-
})) {
|
|
1388
|
-
this.model = model;
|
|
1389
|
-
this._visibleRange = _visibleRange;
|
|
1390
|
-
}
|
|
1391
|
-
getCells(range, plane) {
|
|
1392
|
-
let cells;
|
|
1393
|
-
switch (plane) {
|
|
1394
|
-
case "grid":
|
|
1395
|
-
this._visibleRange.value = range;
|
|
1396
|
-
cells = this.getMainGridCells(range);
|
|
1397
|
-
break;
|
|
1398
|
-
case "frozenRowsStart":
|
|
1399
|
-
cells = this.getHeaderCells(range);
|
|
1400
|
-
break;
|
|
1401
|
-
case "frozenColsStart":
|
|
1402
|
-
cells = this.getSelectionColumnCells(range);
|
|
1403
|
-
break;
|
|
1404
|
-
case "frozenColsEnd":
|
|
1405
|
-
cells = this.getActionColumnCells(range);
|
|
1406
|
-
break;
|
|
1407
|
-
case "fixedStartStart":
|
|
1408
|
-
cells = this.getSelectAllCell();
|
|
1409
|
-
break;
|
|
1410
|
-
case "fixedStartEnd":
|
|
1411
|
-
cells = this.getNewColumnCell();
|
|
1412
|
-
break;
|
|
1413
|
-
default:
|
|
1414
|
-
cells = {};
|
|
1415
|
-
}
|
|
1416
|
-
if (plane === "grid" && this.model.features.dataEditable === false) {
|
|
1417
|
-
Object.values(cells).forEach((cell) => {
|
|
1418
|
-
cell.readonly = "text-select";
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
return cells;
|
|
1422
|
-
}
|
|
1423
|
-
getMainGridCells(range) {
|
|
1424
|
-
const cells = {};
|
|
1425
|
-
const fields = this.model.view?.fields ?? [];
|
|
1426
|
-
const addCell = (obj, field, colIndex, displayIndex) => {
|
|
1427
|
-
const { props } = this.model.projection.getFieldProjection(field.id);
|
|
1428
|
-
const cell = {
|
|
1429
|
-
get value() {
|
|
1430
|
-
const value = getValue3(obj, field.path);
|
|
1431
|
-
if (value == null) {
|
|
1432
|
-
return "";
|
|
1433
|
-
}
|
|
1434
|
-
if (props.type === "array") {
|
|
1435
|
-
return "";
|
|
1436
|
-
}
|
|
1437
|
-
switch (props.format) {
|
|
1438
|
-
case FormatEnum4.Boolean:
|
|
1439
|
-
case FormatEnum4.SingleSelect:
|
|
1440
|
-
case FormatEnum4.MultiSelect: {
|
|
1441
|
-
return "";
|
|
1442
|
-
}
|
|
1443
|
-
case FormatEnum4.Ref: {
|
|
1444
|
-
if (!field.referencePath) {
|
|
1445
|
-
return "";
|
|
1446
|
-
}
|
|
1447
|
-
return getValue3(value.target, field.referencePath);
|
|
1448
|
-
}
|
|
1449
|
-
default: {
|
|
1450
|
-
return formatForDisplay2({
|
|
1451
|
-
type: props.type,
|
|
1452
|
-
format: props.format,
|
|
1453
|
-
value
|
|
1454
|
-
});
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
};
|
|
1459
|
-
const classes = [];
|
|
1460
|
-
const formatClasses = cellClassesForFieldType({
|
|
1461
|
-
type: props.type,
|
|
1462
|
-
format: props.format
|
|
1463
|
-
});
|
|
1464
|
-
if (formatClasses) {
|
|
1465
|
-
classes.push(formatClasses);
|
|
1466
|
-
}
|
|
1467
|
-
const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj), this.model.selection.selectionMode);
|
|
1468
|
-
if (rowSelectionClasses) {
|
|
1469
|
-
classes.push(rowSelectionClasses);
|
|
1470
|
-
}
|
|
1471
|
-
if (classes.length > 0) {
|
|
1472
|
-
cell.className = mx(classes.flat());
|
|
1473
|
-
}
|
|
1474
|
-
if (props.type === TypeEnum3.Array) {
|
|
1475
|
-
const targetArray = getValue3(obj, field.path);
|
|
1476
|
-
if (targetArray && Array.isArray(targetArray)) {
|
|
1477
|
-
const getLabel = (value) => {
|
|
1478
|
-
if (!value) {
|
|
1479
|
-
return void 0;
|
|
1480
|
-
}
|
|
1481
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1482
|
-
return String(value);
|
|
1483
|
-
}
|
|
1484
|
-
if (Array.isArray(value)) {
|
|
1485
|
-
return "Array";
|
|
1486
|
-
}
|
|
1487
|
-
if (typeof value === "object" && value.name) {
|
|
1488
|
-
return value.name;
|
|
1489
|
-
}
|
|
1490
|
-
if (typeof value === "object" && value.value) {
|
|
1491
|
-
return `${value.value}`;
|
|
1492
|
-
}
|
|
1493
|
-
return "Object";
|
|
1494
|
-
};
|
|
1495
|
-
const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
|
|
1496
|
-
return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
|
|
1497
|
-
}).join("");
|
|
1498
|
-
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
if (props.format === FormatEnum4.Ref && props.referenceSchema) {
|
|
1502
|
-
const targetObj = getValue3(obj, field.path)?.target;
|
|
1503
|
-
if (targetObj) {
|
|
1504
|
-
const dxn = getObjectDXN(targetObj)?.toString();
|
|
1505
|
-
cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button is-6 pli-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
if (props.format === FormatEnum4.Boolean) {
|
|
1509
|
-
const value = getValue3(obj, field.path);
|
|
1510
|
-
cell.accessoryHtml = tableControls.switch.render({
|
|
1511
|
-
colIndex,
|
|
1512
|
-
rowIndex: displayIndex,
|
|
1513
|
-
checked: value ?? false
|
|
1514
|
-
});
|
|
1515
|
-
cell.readonly = "no-text-select";
|
|
1516
|
-
}
|
|
1517
|
-
if (props.format === FormatEnum4.SingleSelect) {
|
|
1518
|
-
const value = getValue3(obj, field.path);
|
|
1519
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1520
|
-
if (options) {
|
|
1521
|
-
const option = options.find((o) => o.id === value);
|
|
1522
|
-
if (option) {
|
|
1523
|
-
cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
if (props.format === FormatEnum4.MultiSelect) {
|
|
1528
|
-
const values = getValue3(obj, field.path);
|
|
1529
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1530
|
-
if (options && values && values.length > 0) {
|
|
1531
|
-
const tags = values.map((value) => {
|
|
1532
|
-
const option = options.find((o) => o.id === value);
|
|
1533
|
-
if (option) {
|
|
1534
|
-
return `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1535
|
-
}
|
|
1536
|
-
return null;
|
|
1537
|
-
}).filter(Boolean).join(" ");
|
|
1538
|
-
if (tags) {
|
|
1539
|
-
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1">${tags}</div>`;
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
const idx = toPlaneCellIndex({
|
|
1544
|
-
col: colIndex,
|
|
1545
|
-
row: displayIndex
|
|
1546
|
-
});
|
|
1547
|
-
cells[idx] = cell;
|
|
1548
|
-
};
|
|
1549
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1550
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1551
|
-
const field = fields[col];
|
|
1552
|
-
if (!field) {
|
|
1553
|
-
continue;
|
|
1554
|
-
}
|
|
1555
|
-
addCell(this.model.rows.value[row], field, col, row);
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
return cells;
|
|
1559
|
-
}
|
|
1560
|
-
getHeaderCells(range) {
|
|
1561
|
-
const cells = {};
|
|
1562
|
-
const fields = this.model.view?.fields ?? [];
|
|
1563
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1564
|
-
const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
|
|
1565
|
-
const sorting = this.model.sorting?.sorting;
|
|
1566
|
-
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1567
|
-
cells[toPlaneCellIndex({
|
|
1568
|
-
col,
|
|
1569
|
-
row: 0
|
|
1570
|
-
})] = {
|
|
1571
|
-
// TODO(burdon): Use same logic as form for fallback title.
|
|
1572
|
-
value: props.title ?? field.path,
|
|
1573
|
-
readonly: true,
|
|
1574
|
-
resizeHandle: "col",
|
|
1575
|
-
accessoryHtml: `
|
|
1576
|
-
${direction !== void 0 ? tableButtons.sort.render({
|
|
1577
|
-
fieldId: field.id,
|
|
1578
|
-
direction
|
|
1579
|
-
}) : ""}
|
|
1580
|
-
${tableButtons.columnSettings.render({
|
|
1581
|
-
fieldId: field.id
|
|
1582
|
-
})}
|
|
1583
|
-
`,
|
|
1584
|
-
className: "!bg-toolbarSurface"
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
return cells;
|
|
1588
|
-
}
|
|
1589
|
-
getSelectionColumnCells(range) {
|
|
1590
|
-
const cells = {};
|
|
1591
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1592
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1593
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1594
|
-
cells[toPlaneCellIndex({
|
|
1595
|
-
col: 0,
|
|
1596
|
-
row
|
|
1597
|
-
})] = {
|
|
1598
|
-
value: "",
|
|
1599
|
-
readonly: "no-text-select",
|
|
1600
|
-
className: classes ? mx(classes) : void 0,
|
|
1601
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1602
|
-
rowIndex: row,
|
|
1603
|
-
checked: isSelected
|
|
1604
|
-
})
|
|
1605
|
-
};
|
|
1606
|
-
}
|
|
1607
|
-
return cells;
|
|
1608
|
-
}
|
|
1609
|
-
getActionColumnCells(range) {
|
|
1610
|
-
const cells = {};
|
|
1611
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1612
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1613
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1614
|
-
cells[toPlaneCellIndex({
|
|
1615
|
-
col: 0,
|
|
1616
|
-
row
|
|
1617
|
-
})] = {
|
|
1618
|
-
value: "",
|
|
1619
|
-
readonly: true,
|
|
1620
|
-
className: classes ? mx(classes) : void 0,
|
|
1621
|
-
accessoryHtml: tableButtons.rowMenu.render({
|
|
1622
|
-
rowIndex: row
|
|
1623
|
-
})
|
|
1624
|
-
};
|
|
1625
|
-
}
|
|
1626
|
-
return cells;
|
|
1627
|
-
}
|
|
1628
|
-
getSelectAllCell() {
|
|
1629
|
-
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === "single") {
|
|
1630
|
-
return {
|
|
1631
|
-
[toPlaneCellIndex({
|
|
1632
|
-
col: 0,
|
|
1633
|
-
row: 0
|
|
1634
|
-
})]: {
|
|
1635
|
-
className: "!bg-toolbarSurface",
|
|
1636
|
-
readonly: true,
|
|
1637
|
-
value: ""
|
|
1638
|
-
}
|
|
1639
|
-
};
|
|
1640
|
-
}
|
|
1641
|
-
return {
|
|
1642
|
-
[toPlaneCellIndex({
|
|
1643
|
-
col: 0,
|
|
1644
|
-
row: 0
|
|
1645
|
-
})]: {
|
|
1646
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1647
|
-
rowIndex: 0,
|
|
1648
|
-
header: true,
|
|
1649
|
-
checked: this.model.selection.allRowsSeleted.value
|
|
1650
|
-
}),
|
|
1651
|
-
className: "!bg-toolbarSurface",
|
|
1652
|
-
readonly: true,
|
|
1653
|
-
value: ""
|
|
1654
|
-
}
|
|
1655
|
-
};
|
|
1656
|
-
}
|
|
1657
|
-
getNewColumnCell() {
|
|
1658
|
-
return {
|
|
1659
|
-
[toPlaneCellIndex({
|
|
1660
|
-
col: 0,
|
|
1661
|
-
row: 0
|
|
1662
|
-
})]: {
|
|
1663
|
-
accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
|
|
1664
|
-
disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1665
|
-
}) : void 0,
|
|
1666
|
-
className: "!bg-toolbarSurface",
|
|
1667
|
-
readonly: true,
|
|
1668
|
-
value: ""
|
|
1669
|
-
}
|
|
1670
|
-
};
|
|
1671
|
-
}
|
|
1672
|
-
};
|
|
1673
|
-
var cellClassesForRowSelection = (selected, selectionMode) => {
|
|
1674
|
-
if (!selected) {
|
|
1675
|
-
if (selectionMode === "single") {
|
|
1676
|
-
return [
|
|
1677
|
-
"!cursor-pointer"
|
|
1678
|
-
];
|
|
1679
|
-
} else {
|
|
1680
|
-
return void 0;
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
switch (selectionMode) {
|
|
1684
|
-
case "single":
|
|
1685
|
-
return [
|
|
1686
|
-
"!bg-currentRelated hover:bg-hoverSurface",
|
|
1687
|
-
"!cursor-pointer"
|
|
1688
|
-
];
|
|
1689
|
-
case "multiple":
|
|
1690
|
-
return [
|
|
1691
|
-
"!bg-gridCellSelected"
|
|
1692
|
-
];
|
|
1693
|
-
}
|
|
1694
|
-
};
|
|
1695
|
-
|
|
1696
|
-
// packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
|
|
297
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
1697
298
|
import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
|
|
1698
|
-
import React7, { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef2, useState as
|
|
1699
|
-
import { FormatEnum
|
|
1700
|
-
import { invariant as
|
|
299
|
+
import React7, { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef2, useState as useState3 } from "react";
|
|
300
|
+
import { FormatEnum, TypeEnum } from "@dxos/echo-schema";
|
|
301
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1701
302
|
import { useThemeContext } from "@dxos/react-ui";
|
|
1702
303
|
import { createMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
1703
304
|
import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext4, GridCellEditor } from "@dxos/react-ui-grid";
|
|
1704
|
-
import {
|
|
305
|
+
import { tagPicker, createLinks } from "@dxos/react-ui-tag-picker";
|
|
1705
306
|
|
|
1706
|
-
//
|
|
307
|
+
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
1707
308
|
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
1708
309
|
import React5 from "react";
|
|
1709
310
|
import { useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
1710
|
-
var CellValidationMessage = ({ validationError, __gridScope }) => {
|
|
311
|
+
var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
|
|
1711
312
|
var _effect = _useSignals5();
|
|
1712
313
|
try {
|
|
1713
314
|
const { editing, editBox: box } = useGridContext2("GridSheetCellEditor", __gridScope);
|
|
1714
315
|
if (!editing || !validationError) {
|
|
1715
316
|
return null;
|
|
1716
317
|
}
|
|
318
|
+
const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
|
|
319
|
+
const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
|
|
1717
320
|
return /* @__PURE__ */ React5.createElement("div", {
|
|
1718
321
|
role: "none",
|
|
1719
|
-
className:
|
|
322
|
+
className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
|
|
1720
323
|
style: {
|
|
1721
324
|
...{
|
|
1722
325
|
"--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
|
|
@@ -1732,27 +335,32 @@ var CellValidationMessage = ({ validationError, __gridScope }) => {
|
|
|
1732
335
|
}
|
|
1733
336
|
};
|
|
1734
337
|
|
|
1735
|
-
//
|
|
338
|
+
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
1736
339
|
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
1737
|
-
import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
|
|
1738
|
-
import { getSnapshot
|
|
1739
|
-
import { invariant
|
|
340
|
+
import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef, useState as useState2 } from "react";
|
|
341
|
+
import { getSnapshot } from "@dxos/echo-schema";
|
|
342
|
+
import { invariant } from "@dxos/invariant";
|
|
1740
343
|
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
1741
344
|
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
1742
345
|
import { parseCellIndex, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
1743
346
|
import { getDeep, setDeep } from "@dxos/util";
|
|
1744
|
-
var
|
|
1745
|
-
var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
347
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
348
|
+
var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) => {
|
|
1746
349
|
var _effect = _useSignals6();
|
|
1747
350
|
try {
|
|
1748
|
-
const { editing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
|
|
1749
|
-
const
|
|
351
|
+
const { editing: contextEditing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
|
|
352
|
+
const [editing, setLocalEditing] = useState2(false);
|
|
353
|
+
const anchorRef = useRef(null);
|
|
1750
354
|
useEffect2(() => {
|
|
1751
|
-
if (
|
|
1752
|
-
|
|
355
|
+
if (contextEditing && contextEditing.cellElement) {
|
|
356
|
+
anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
|
|
357
|
+
setLocalEditing(true);
|
|
358
|
+
} else {
|
|
359
|
+
anchorRef.current = null;
|
|
360
|
+
setLocalEditing(false);
|
|
1753
361
|
}
|
|
1754
362
|
}, [
|
|
1755
|
-
|
|
363
|
+
contextEditing
|
|
1756
364
|
]);
|
|
1757
365
|
const narrowedSchema = useMemo3(() => {
|
|
1758
366
|
if (!schema) {
|
|
@@ -1766,12 +374,12 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1766
374
|
fieldProjection.field.path
|
|
1767
375
|
]);
|
|
1768
376
|
const originalRow = useMemo3(() => {
|
|
1769
|
-
if (model &&
|
|
1770
|
-
const cell = parseCellIndex(
|
|
377
|
+
if (model && contextEditing) {
|
|
378
|
+
const cell = parseCellIndex(contextEditing.index);
|
|
1771
379
|
const row = model.getRowAt(cell.row);
|
|
1772
|
-
|
|
1773
|
-
F:
|
|
1774
|
-
L:
|
|
380
|
+
invariant(row, void 0, {
|
|
381
|
+
F: __dxlog_file,
|
|
382
|
+
L: 55,
|
|
1775
383
|
S: void 0,
|
|
1776
384
|
A: [
|
|
1777
385
|
"row",
|
|
@@ -1783,11 +391,11 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1783
391
|
return void 0;
|
|
1784
392
|
}, [
|
|
1785
393
|
model,
|
|
1786
|
-
|
|
394
|
+
contextEditing
|
|
1787
395
|
]);
|
|
1788
396
|
const formValues = useMemo3(() => {
|
|
1789
397
|
if (originalRow) {
|
|
1790
|
-
return
|
|
398
|
+
return getSnapshot(originalRow);
|
|
1791
399
|
}
|
|
1792
400
|
}, [
|
|
1793
401
|
originalRow
|
|
@@ -1801,6 +409,8 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1801
409
|
path
|
|
1802
410
|
], value);
|
|
1803
411
|
setEditing(null);
|
|
412
|
+
setLocalEditing(false);
|
|
413
|
+
onSave?.();
|
|
1804
414
|
}, [
|
|
1805
415
|
fieldProjection.field.path,
|
|
1806
416
|
originalRow
|
|
@@ -1808,21 +418,21 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1808
418
|
const handleOpenChange = useCallback3((nextOpen) => {
|
|
1809
419
|
if (nextOpen === false) {
|
|
1810
420
|
setEditing(null);
|
|
421
|
+
onSave?.();
|
|
1811
422
|
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
]);
|
|
423
|
+
setLocalEditing(nextOpen);
|
|
424
|
+
}, []);
|
|
1815
425
|
if (!editing) {
|
|
1816
426
|
return null;
|
|
1817
427
|
}
|
|
1818
428
|
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
1819
|
-
open: editing
|
|
429
|
+
open: editing,
|
|
1820
430
|
onOpenChange: handleOpenChange
|
|
1821
431
|
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
1822
|
-
virtualRef:
|
|
432
|
+
virtualRef: anchorRef
|
|
1823
433
|
}), /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
1824
434
|
tabIndex: -1,
|
|
1825
|
-
classNames: "popover-card-width"
|
|
435
|
+
classNames: "popover-card-width density-fine"
|
|
1826
436
|
}, /* @__PURE__ */ React6.createElement(Popover3.Arrow, null), /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, /* @__PURE__ */ React6.createElement(Form2, {
|
|
1827
437
|
values: formValues,
|
|
1828
438
|
schema: narrowedSchema,
|
|
@@ -1833,7 +443,7 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1833
443
|
}
|
|
1834
444
|
};
|
|
1835
445
|
|
|
1836
|
-
//
|
|
446
|
+
// src/components/TableCellEditor/extension.ts
|
|
1837
447
|
import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
|
|
1838
448
|
import { EditorView } from "@codemirror/view";
|
|
1839
449
|
var completion = ({ debug, onQuery, onMatch }) => {
|
|
@@ -1872,15 +482,15 @@ var completion = ({ debug, onQuery, onMatch }) => {
|
|
|
1872
482
|
];
|
|
1873
483
|
};
|
|
1874
484
|
|
|
1875
|
-
//
|
|
1876
|
-
var
|
|
485
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
486
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
1877
487
|
var newValue = Symbol.for("newValue");
|
|
1878
488
|
var createOption = (text) => ({
|
|
1879
489
|
[newValue]: true,
|
|
1880
490
|
text
|
|
1881
491
|
});
|
|
1882
492
|
var isCreateOption = (data) => typeof data === "object" && data[newValue];
|
|
1883
|
-
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gridScope }) => {
|
|
493
|
+
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQuery, __gridScope }) => {
|
|
1884
494
|
var _effect = _useSignals7();
|
|
1885
495
|
try {
|
|
1886
496
|
const { editing } = useGridContext4("TableValueEditor", __gridScope);
|
|
@@ -1889,11 +499,11 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
|
|
|
1889
499
|
return;
|
|
1890
500
|
}
|
|
1891
501
|
const { col } = parseCellIndex2(editing.index);
|
|
1892
|
-
const field = model.projection.
|
|
502
|
+
const field = model.projection.fields[col];
|
|
1893
503
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1894
|
-
|
|
1895
|
-
F:
|
|
1896
|
-
L:
|
|
504
|
+
invariant2(fieldProjection2, void 0, {
|
|
505
|
+
F: __dxlog_file2,
|
|
506
|
+
L: 76,
|
|
1897
507
|
S: void 0,
|
|
1898
508
|
A: [
|
|
1899
509
|
"fieldProjection",
|
|
@@ -1905,12 +515,13 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
|
|
|
1905
515
|
model,
|
|
1906
516
|
editing
|
|
1907
517
|
]);
|
|
1908
|
-
if (fieldProjection?.props.type ===
|
|
518
|
+
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect) {
|
|
1909
519
|
return /* @__PURE__ */ React7.createElement(FormCellEditor, {
|
|
1910
520
|
fieldProjection,
|
|
1911
521
|
model,
|
|
1912
522
|
schema,
|
|
1913
|
-
__gridScope
|
|
523
|
+
__gridScope,
|
|
524
|
+
onSave
|
|
1914
525
|
});
|
|
1915
526
|
}
|
|
1916
527
|
return /* @__PURE__ */ React7.createElement(TableCellEditor, {
|
|
@@ -1919,29 +530,36 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
|
|
|
1919
530
|
onEnter,
|
|
1920
531
|
onFocus,
|
|
1921
532
|
onQuery,
|
|
533
|
+
onSave,
|
|
1922
534
|
__gridScope
|
|
1923
535
|
});
|
|
1924
536
|
} finally {
|
|
1925
537
|
_effect.f();
|
|
1926
538
|
}
|
|
1927
539
|
};
|
|
1928
|
-
var
|
|
540
|
+
var editorSlots = {
|
|
541
|
+
scroller: {
|
|
542
|
+
className: "!plb-[--dx-grid-cell-editor-padding-block]"
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gridScope }) => {
|
|
1929
546
|
var _effect = _useSignals7();
|
|
1930
547
|
try {
|
|
1931
548
|
const { id: gridId, editing, setEditing } = useGridContext4("TableCellEditor", __gridScope);
|
|
1932
549
|
const suppressNextBlur = useRef2(false);
|
|
1933
550
|
const { themeMode } = useThemeContext();
|
|
1934
|
-
const [_validationError, setValidationError] =
|
|
551
|
+
const [_validationError, setValidationError] = useState3(null);
|
|
552
|
+
const [_validationVariant, setValidationVariant] = useState3("error");
|
|
1935
553
|
const fieldProjection = useMemo4(() => {
|
|
1936
554
|
if (!model || !editing) {
|
|
1937
555
|
return;
|
|
1938
556
|
}
|
|
1939
557
|
const { col } = parseCellIndex2(editing.index);
|
|
1940
|
-
const field = model.projection.
|
|
558
|
+
const field = model.projection.fields[col];
|
|
1941
559
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1942
|
-
|
|
1943
|
-
F:
|
|
1944
|
-
L:
|
|
560
|
+
invariant2(fieldProjection2, void 0, {
|
|
561
|
+
F: __dxlog_file2,
|
|
562
|
+
L: 135,
|
|
1945
563
|
S: void 0,
|
|
1946
564
|
A: [
|
|
1947
565
|
"fieldProjection",
|
|
@@ -1953,20 +571,53 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1953
571
|
model,
|
|
1954
572
|
editing
|
|
1955
573
|
]);
|
|
574
|
+
useEffect3(() => {
|
|
575
|
+
if (!model || !editing || !fieldProjection) {
|
|
576
|
+
setValidationError(null);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const cell = parseCellIndex2(editing.index);
|
|
580
|
+
const { row, col } = cell;
|
|
581
|
+
if (model.isDraftCell(cell)) {
|
|
582
|
+
const field = model.projection.fields[col];
|
|
583
|
+
const hasValidationError = model.hasDraftRowValidationError(row, field.path);
|
|
584
|
+
if (hasValidationError) {
|
|
585
|
+
const draftRows = model.draftRows.value;
|
|
586
|
+
if (row >= 0 && row < draftRows.length) {
|
|
587
|
+
const draftRow = draftRows[row];
|
|
588
|
+
const validationError = draftRow.validationErrors?.find((error) => error.path === field.path);
|
|
589
|
+
if (validationError) {
|
|
590
|
+
setValidationError(validationError.message);
|
|
591
|
+
setValidationVariant("warning");
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
} else {
|
|
595
|
+
setValidationError(null);
|
|
596
|
+
}
|
|
597
|
+
} else {
|
|
598
|
+
setValidationError(null);
|
|
599
|
+
}
|
|
600
|
+
}, [
|
|
601
|
+
model,
|
|
602
|
+
editing,
|
|
603
|
+
fieldProjection
|
|
604
|
+
]);
|
|
1956
605
|
const handleEnter = useCallback4(async (value) => {
|
|
1957
606
|
if (!model || !editing) {
|
|
1958
607
|
return;
|
|
1959
608
|
}
|
|
1960
609
|
const cell = parseCellIndex2(editing.index);
|
|
1961
|
-
const
|
|
1962
|
-
if (
|
|
610
|
+
const validationResult = await model.validateCellData(cell, value);
|
|
611
|
+
if (validationResult.valid) {
|
|
1963
612
|
setValidationError(null);
|
|
1964
613
|
model.setCellData(cell, value);
|
|
1965
614
|
onEnter?.(cell);
|
|
1966
615
|
onFocus?.();
|
|
1967
616
|
setEditing(null);
|
|
617
|
+
onSave?.();
|
|
1968
618
|
} else {
|
|
1969
|
-
setValidationError(
|
|
619
|
+
setValidationError(validationResult.error);
|
|
620
|
+
setValidationVariant("error");
|
|
1970
621
|
}
|
|
1971
622
|
}, [
|
|
1972
623
|
model,
|
|
@@ -1997,16 +648,19 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1997
648
|
setValidationError(null);
|
|
1998
649
|
model.setCellData(cell, value);
|
|
1999
650
|
setEditing(null);
|
|
651
|
+
onSave?.();
|
|
2000
652
|
onEnter?.(cell);
|
|
2001
653
|
if (event && onFocus) {
|
|
2002
654
|
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2003
655
|
}
|
|
2004
656
|
} else {
|
|
2005
657
|
setValidationError(result.error);
|
|
658
|
+
setValidationVariant("error");
|
|
2006
659
|
}
|
|
2007
660
|
} else {
|
|
2008
661
|
setValidationError(null);
|
|
2009
662
|
setEditing(null);
|
|
663
|
+
onSave?.();
|
|
2010
664
|
if (event && onFocus) {
|
|
2011
665
|
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2012
666
|
}
|
|
@@ -2017,7 +671,8 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2017
671
|
onFocus,
|
|
2018
672
|
onEnter,
|
|
2019
673
|
fieldProjection,
|
|
2020
|
-
setEditing
|
|
674
|
+
setEditing,
|
|
675
|
+
onSave
|
|
2021
676
|
]);
|
|
2022
677
|
const extension = useMemo4(() => {
|
|
2023
678
|
if (!fieldProjection) {
|
|
@@ -2032,15 +687,15 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2032
687
|
})
|
|
2033
688
|
];
|
|
2034
689
|
const format = fieldProjection.props.format;
|
|
2035
|
-
if (format ===
|
|
690
|
+
if (format === FormatEnum.SingleSelect || format === FormatEnum.MultiSelect) {
|
|
2036
691
|
extension2.push(createMarkdownExtensions({
|
|
2037
692
|
themeMode
|
|
2038
693
|
}));
|
|
2039
694
|
const options = fieldProjection.props.options || [];
|
|
2040
|
-
const mode = format ===
|
|
2041
|
-
extension2.push(
|
|
695
|
+
const mode = format === FormatEnum.SingleSelect ? "single-select" : "multi-select";
|
|
696
|
+
extension2.push(tagPicker({
|
|
2042
697
|
mode,
|
|
2043
|
-
|
|
698
|
+
keymap: false,
|
|
2044
699
|
onSearch: (text, selectedIds) => {
|
|
2045
700
|
return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
|
|
2046
701
|
id: option.id,
|
|
@@ -2064,7 +719,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2064
719
|
}
|
|
2065
720
|
if (onQuery) {
|
|
2066
721
|
switch (fieldProjection.props.format) {
|
|
2067
|
-
case
|
|
722
|
+
case FormatEnum.Ref: {
|
|
2068
723
|
extension2.push([
|
|
2069
724
|
completion({
|
|
2070
725
|
onQuery: (text) => onQuery(fieldProjection, text),
|
|
@@ -2104,14 +759,14 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2104
759
|
if (model && editing) {
|
|
2105
760
|
const cell = parseCellIndex2(editing.index);
|
|
2106
761
|
const { col } = cell;
|
|
2107
|
-
const field = model.projection.
|
|
762
|
+
const field = model.projection.fields[col];
|
|
2108
763
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
2109
|
-
if (fieldProjection2?.props.format ===
|
|
764
|
+
if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
|
|
2110
765
|
const value2 = model.getCellData(cell);
|
|
2111
766
|
if (value2 !== void 0) {
|
|
2112
767
|
const options = fieldProjection2.props.options || [];
|
|
2113
|
-
if (fieldProjection2.props.format ===
|
|
2114
|
-
const tagItems = value2.map((id) => {
|
|
768
|
+
if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
|
|
769
|
+
const tagItems = value2.split(",").map((id) => {
|
|
2115
770
|
const option = options.find((o) => o.id === id);
|
|
2116
771
|
if (option) {
|
|
2117
772
|
return {
|
|
@@ -2148,11 +803,13 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2148
803
|
]);
|
|
2149
804
|
return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(CellValidationMessage, {
|
|
2150
805
|
validationError: _validationError,
|
|
806
|
+
variant: _validationVariant,
|
|
2151
807
|
__gridScope
|
|
2152
808
|
}), /* @__PURE__ */ React7.createElement(GridCellEditor, {
|
|
2153
809
|
extension,
|
|
2154
810
|
getCellContent,
|
|
2155
|
-
onBlur: handleBlur
|
|
811
|
+
onBlur: handleBlur,
|
|
812
|
+
slots: editorSlots
|
|
2156
813
|
}));
|
|
2157
814
|
} finally {
|
|
2158
815
|
_effect.f();
|
|
@@ -2183,14 +840,21 @@ var determineNavigationDelta = ({ key, shift }) => {
|
|
|
2183
840
|
return shift ? -1 : 1;
|
|
2184
841
|
};
|
|
2185
842
|
|
|
2186
|
-
//
|
|
2187
|
-
var
|
|
2188
|
-
var TableRoot = ({ children, role }) => {
|
|
843
|
+
// src/components/Table/Table.tsx
|
|
844
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
|
|
845
|
+
var TableRoot = ({ children, role = "article" }) => {
|
|
2189
846
|
var _effect = _useSignals8();
|
|
2190
847
|
try {
|
|
2191
848
|
return /* @__PURE__ */ React8.createElement("div", {
|
|
2192
849
|
role: "none",
|
|
2193
|
-
className:
|
|
850
|
+
className: mx("relative !border-separator [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]", role === "card--popover" && "popover-card-height", role === "section" && "attention-surface", role === "card--intrinsic" && "[&_.dx-grid]:bs-[--dx-grid-content-block-size]", [
|
|
851
|
+
"card--popover",
|
|
852
|
+
"section",
|
|
853
|
+
"card--extrinsic"
|
|
854
|
+
].includes(role) && "overflow-hidden", [
|
|
855
|
+
"article",
|
|
856
|
+
"slide"
|
|
857
|
+
].includes(role) && "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:bs-0")
|
|
2194
858
|
}, children);
|
|
2195
859
|
} finally {
|
|
2196
860
|
_effect.f();
|
|
@@ -2199,24 +863,27 @@ var TableRoot = ({ children, role }) => {
|
|
|
2199
863
|
var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
|
|
2200
864
|
var _effect = _useSignals8();
|
|
2201
865
|
try {
|
|
2202
|
-
const [dxGrid, setDxGrid] =
|
|
866
|
+
const [dxGrid, setDxGrid] = useState4(null);
|
|
2203
867
|
const { hasAttention } = useAttention(model?.id ?? "table");
|
|
2204
868
|
const { t } = useTranslation3(translationKey);
|
|
2205
869
|
const modals = useMemo5(() => new ModalController(), []);
|
|
870
|
+
const draftRowCount = model?.getDraftRowCount() ?? 0;
|
|
2206
871
|
const frozen = useMemo5(() => {
|
|
2207
872
|
const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
|
|
2208
873
|
return {
|
|
2209
874
|
frozenRowsStart: 1,
|
|
875
|
+
frozenRowsEnd: draftRowCount,
|
|
2210
876
|
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
2211
877
|
frozenColsEnd: noActionColumn ? 0 : 1
|
|
2212
878
|
};
|
|
2213
879
|
}, [
|
|
2214
|
-
model
|
|
880
|
+
model,
|
|
881
|
+
draftRowCount
|
|
2215
882
|
]);
|
|
2216
883
|
const getCells = useCallback5((range, plane) => presentation?.getCells(range, plane) ?? {}, [
|
|
2217
884
|
presentation
|
|
2218
885
|
]);
|
|
2219
|
-
|
|
886
|
+
useEffect4(() => {
|
|
2220
887
|
if (!presentation || !dxGrid) {
|
|
2221
888
|
return;
|
|
2222
889
|
}
|
|
@@ -2233,7 +900,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2233
900
|
return {
|
|
2234
901
|
update: (cell) => {
|
|
2235
902
|
if (cell) {
|
|
2236
|
-
dxGrid.updateIfWithinBounds(cell);
|
|
903
|
+
dxGrid.updateIfWithinBounds(cell, true);
|
|
2237
904
|
} else {
|
|
2238
905
|
dxGrid.updateCells(true);
|
|
2239
906
|
dxGrid.requestUpdate();
|
|
@@ -2245,7 +912,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2245
912
|
dxGrid
|
|
2246
913
|
]);
|
|
2247
914
|
const handleGridClick = useCallback5((event) => {
|
|
2248
|
-
const rowIndex = safeParseInt(event.target.ariaRowIndex ?? "");
|
|
915
|
+
const rowIndex = safeParseInt(event.target.closest("[aria-rowindex]")?.ariaRowIndex ?? "");
|
|
2249
916
|
if (rowIndex != null) {
|
|
2250
917
|
if (onRowClick) {
|
|
2251
918
|
const row = model?.getRowAt(rowIndex);
|
|
@@ -2284,6 +951,17 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2284
951
|
model?.sorting?.toggleSort(data.fieldId);
|
|
2285
952
|
break;
|
|
2286
953
|
}
|
|
954
|
+
case "saveDraftRow": {
|
|
955
|
+
if (model) {
|
|
956
|
+
const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
|
|
957
|
+
if (dxGrid && didCommitSuccessfully) {
|
|
958
|
+
requestAnimationFrame(() => {
|
|
959
|
+
dxGrid.scrollToEndRow();
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
2287
965
|
}
|
|
2288
966
|
return;
|
|
2289
967
|
}
|
|
@@ -2317,7 +995,8 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2317
995
|
}
|
|
2318
996
|
}, [
|
|
2319
997
|
model,
|
|
2320
|
-
modals
|
|
998
|
+
modals,
|
|
999
|
+
dxGrid
|
|
2321
1000
|
]);
|
|
2322
1001
|
const handleFocus = useCallback5((increment, delta) => {
|
|
2323
1002
|
if (dxGrid) {
|
|
@@ -2331,7 +1010,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2331
1010
|
return;
|
|
2332
1011
|
}
|
|
2333
1012
|
if (model && cell.row === model.getRowCount() - 1) {
|
|
2334
|
-
model.insertRow(
|
|
1013
|
+
model.insertRow();
|
|
2335
1014
|
if (dxGrid) {
|
|
2336
1015
|
requestAnimationFrame(() => {
|
|
2337
1016
|
dxGrid?.scrollToRow(cell.row + 1);
|
|
@@ -2388,10 +1067,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2388
1067
|
]);
|
|
2389
1068
|
const handleQuery = useCallback5(async ({ field, props }, text) => {
|
|
2390
1069
|
if (model && props.referenceSchema && field.referencePath) {
|
|
2391
|
-
const space = model.
|
|
2392
|
-
|
|
2393
|
-
F:
|
|
2394
|
-
L:
|
|
1070
|
+
const space = getSpace2(model.view);
|
|
1071
|
+
invariant3(space, void 0, {
|
|
1072
|
+
F: __dxlog_file3,
|
|
1073
|
+
L: 325,
|
|
2395
1074
|
S: void 0,
|
|
2396
1075
|
A: [
|
|
2397
1076
|
"space",
|
|
@@ -2408,7 +1087,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2408
1087
|
if (schema2) {
|
|
2409
1088
|
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
2410
1089
|
const options = objects.map((obj) => {
|
|
2411
|
-
const value =
|
|
1090
|
+
const value = getValue(obj, field.referencePath);
|
|
2412
1091
|
if (!value || typeof value !== "string") {
|
|
2413
1092
|
return void 0;
|
|
2414
1093
|
}
|
|
@@ -2434,6 +1113,11 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2434
1113
|
client,
|
|
2435
1114
|
t
|
|
2436
1115
|
]);
|
|
1116
|
+
const handleSave = useCallback5(() => {
|
|
1117
|
+
dxGrid?.updateCells(true);
|
|
1118
|
+
}, [
|
|
1119
|
+
dxGrid
|
|
1120
|
+
]);
|
|
2437
1121
|
if (!model || !modals) {
|
|
2438
1122
|
return /* @__PURE__ */ React8.createElement("span", {
|
|
2439
1123
|
role: "none",
|
|
@@ -2448,14 +1132,14 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2448
1132
|
schema,
|
|
2449
1133
|
onEnter: handleEnter,
|
|
2450
1134
|
onFocus: handleFocus,
|
|
2451
|
-
onQuery: handleQuery
|
|
1135
|
+
onQuery: handleQuery,
|
|
1136
|
+
onSave: handleSave
|
|
2452
1137
|
}), /* @__PURE__ */ React8.createElement(Grid.Content, {
|
|
2453
|
-
className:
|
|
1138
|
+
className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
2454
1139
|
frozen,
|
|
2455
|
-
// getCells={getCells}
|
|
2456
1140
|
columns: model.columnMeta.value,
|
|
2457
1141
|
limitRows: model.getRowCount() ?? 0,
|
|
2458
|
-
limitColumns: model.
|
|
1142
|
+
limitColumns: model.projection.fields.length,
|
|
2459
1143
|
overscroll: "trap",
|
|
2460
1144
|
onAxisResize: handleAxisResize,
|
|
2461
1145
|
onClick: handleGridClick,
|
|
@@ -2485,116 +1169,33 @@ var Table = {
|
|
|
2485
1169
|
Main: TableMain
|
|
2486
1170
|
};
|
|
2487
1171
|
|
|
2488
|
-
//
|
|
2489
|
-
import { useSignals as
|
|
1172
|
+
// src/components/Table/DynamicTable.tsx
|
|
1173
|
+
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
2490
1174
|
import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
|
|
2491
1175
|
import { useDefaultValue } from "@dxos/react-ui";
|
|
2492
|
-
import { mx as
|
|
2493
|
-
|
|
2494
|
-
// packages/ui/react-ui-table/src/hooks/useTableModel.ts
|
|
2495
|
-
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
2496
|
-
import { effect as effect3 } from "@preact/signals-core";
|
|
2497
|
-
import orderBy2 from "lodash.orderby";
|
|
2498
|
-
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
2499
|
-
import { fullyQualifiedId, getSpace } from "@dxos/react-client/echo";
|
|
2500
|
-
import { useSelectionActions } from "@dxos/react-ui-attention";
|
|
2501
|
-
import { isNonNullable } from "@dxos/util";
|
|
2502
|
-
var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
1176
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1177
|
+
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2503
1178
|
var _effect = _useSignals9();
|
|
2504
1179
|
try {
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
const t = setTimeout(async () => {
|
|
2512
|
-
model2 = new TableModel({
|
|
2513
|
-
id: fullyQualifiedId(table),
|
|
2514
|
-
space: getSpace(table),
|
|
2515
|
-
view: table.view?.target,
|
|
2516
|
-
projection,
|
|
2517
|
-
features,
|
|
2518
|
-
rowActions,
|
|
2519
|
-
onRowAction,
|
|
2520
|
-
...props
|
|
2521
|
-
});
|
|
2522
|
-
await model2.open();
|
|
2523
|
-
setModel(model2);
|
|
2524
|
-
});
|
|
2525
|
-
return () => {
|
|
2526
|
-
clearTimeout(t);
|
|
2527
|
-
void model2?.close();
|
|
2528
|
-
};
|
|
2529
|
-
}, [
|
|
2530
|
-
table,
|
|
2531
|
-
projection,
|
|
2532
|
-
table?.view?.target,
|
|
2533
|
-
features,
|
|
2534
|
-
rowActions
|
|
2535
|
-
]);
|
|
2536
|
-
useEffect4(() => {
|
|
2537
|
-
if (rows) {
|
|
2538
|
-
const sortedRows = orderBy2(rows, [
|
|
2539
|
-
(row) => String(row.id)
|
|
2540
|
-
], [
|
|
2541
|
-
"asc"
|
|
2542
|
-
]);
|
|
2543
|
-
model?.setRows(sortedRows);
|
|
2544
|
-
}
|
|
2545
|
-
}, [
|
|
2546
|
-
model,
|
|
2547
|
-
rows
|
|
2548
|
-
]);
|
|
2549
|
-
const { multiSelect, clear } = useSelectionActions([
|
|
2550
|
-
table?.id,
|
|
2551
|
-
table?.view?.target?.query.typename
|
|
2552
|
-
].filter(isNonNullable));
|
|
2553
|
-
useEffect4(() => {
|
|
2554
|
-
if (!model) {
|
|
2555
|
-
return;
|
|
2556
|
-
}
|
|
2557
|
-
const unsubscribe = effect3(() => {
|
|
2558
|
-
const selectedItems = [
|
|
2559
|
-
...model.selection.selection.value
|
|
2560
|
-
];
|
|
2561
|
-
multiSelect(selectedItems);
|
|
2562
|
-
onSelectionChanged?.(selectedItems);
|
|
2563
|
-
});
|
|
2564
|
-
return () => {
|
|
2565
|
-
clear();
|
|
2566
|
-
unsubscribe();
|
|
2567
|
-
};
|
|
2568
|
-
}, [
|
|
2569
|
-
model,
|
|
2570
|
-
onSelectionChanged
|
|
2571
|
-
]);
|
|
2572
|
-
return model;
|
|
2573
|
-
} finally {
|
|
2574
|
-
_effect.f();
|
|
2575
|
-
}
|
|
2576
|
-
};
|
|
2577
|
-
|
|
2578
|
-
// packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
|
|
2579
|
-
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2580
|
-
var _effect = _useSignals10();
|
|
2581
|
-
try {
|
|
2582
|
-
const { table, projection } = useMemo6(() => {
|
|
2583
|
-
const props2 = getBaseSchema({
|
|
2584
|
-
typename: name,
|
|
2585
|
-
properties,
|
|
2586
|
-
jsonSchema,
|
|
2587
|
-
schema
|
|
2588
|
-
});
|
|
2589
|
-
return makeDynamicTable({
|
|
2590
|
-
...props2,
|
|
2591
|
-
properties
|
|
2592
|
-
});
|
|
2593
|
-
}, [
|
|
1180
|
+
const { typename, jsonSchema } = useMemo6(() => getBaseSchema({
|
|
1181
|
+
typename: name,
|
|
1182
|
+
properties,
|
|
1183
|
+
jsonSchema: _jsonSchema,
|
|
1184
|
+
schema
|
|
1185
|
+
}), [
|
|
2594
1186
|
name,
|
|
2595
1187
|
properties,
|
|
2596
|
-
|
|
2597
|
-
|
|
1188
|
+
_jsonSchema,
|
|
1189
|
+
schema
|
|
1190
|
+
]);
|
|
1191
|
+
const { projection, view } = useMemo6(() => makeDynamicTable({
|
|
1192
|
+
typename,
|
|
1193
|
+
jsonSchema,
|
|
1194
|
+
properties
|
|
1195
|
+
}), [
|
|
1196
|
+
typename,
|
|
1197
|
+
jsonSchema,
|
|
1198
|
+
properties
|
|
2598
1199
|
]);
|
|
2599
1200
|
const tableRef = useRef3(null);
|
|
2600
1201
|
const handleCellUpdate = useCallback6((cell) => {
|
|
@@ -2610,8 +1211,9 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2610
1211
|
dataEditable: false
|
|
2611
1212
|
}));
|
|
2612
1213
|
const model = useTableModel({
|
|
2613
|
-
table,
|
|
2614
1214
|
rows,
|
|
1215
|
+
view,
|
|
1216
|
+
schema: jsonSchema,
|
|
2615
1217
|
projection,
|
|
2616
1218
|
features,
|
|
2617
1219
|
rowActions,
|
|
@@ -2628,7 +1230,7 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2628
1230
|
]);
|
|
2629
1231
|
return /* @__PURE__ */ React9.createElement("div", {
|
|
2630
1232
|
role: "none",
|
|
2631
|
-
className:
|
|
1233
|
+
className: mx2("is-full bs-full grow grid", classNames)
|
|
2632
1234
|
}, /* @__PURE__ */ React9.createElement("div", {
|
|
2633
1235
|
role: "none",
|
|
2634
1236
|
className: "grid min-bs-0 overflow-hidden"
|
|
@@ -2644,11 +1246,11 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2644
1246
|
}
|
|
2645
1247
|
};
|
|
2646
1248
|
|
|
2647
|
-
//
|
|
2648
|
-
import { useSignals as
|
|
1249
|
+
// src/components/TableToolbar/TableToolbar.tsx
|
|
1250
|
+
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2649
1251
|
import { Rx } from "@effect-rx/rx-react";
|
|
2650
1252
|
import React10, { useMemo as useMemo7 } from "react";
|
|
2651
|
-
import { live as
|
|
1253
|
+
import { live as live2 } from "@dxos/live-object";
|
|
2652
1254
|
import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
|
|
2653
1255
|
import { rxFromSignal } from "@dxos/react-ui-menu";
|
|
2654
1256
|
var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
|
|
@@ -2697,9 +1299,9 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
|
|
|
2697
1299
|
};
|
|
2698
1300
|
});
|
|
2699
1301
|
var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
|
|
2700
|
-
var _effect =
|
|
1302
|
+
var _effect = _useSignals10();
|
|
2701
1303
|
try {
|
|
2702
|
-
const state = useMemo7(() =>
|
|
1304
|
+
const state = useMemo7(() => live2({
|
|
2703
1305
|
viewDirty
|
|
2704
1306
|
}), []);
|
|
2705
1307
|
const actionsCreator = useMemo7(() => createTableToolbarActions({
|
|
@@ -2734,18 +1336,17 @@ export {
|
|
|
2734
1336
|
Table,
|
|
2735
1337
|
TableModel,
|
|
2736
1338
|
TablePresentation,
|
|
2737
|
-
TableSchema,
|
|
2738
1339
|
TableToolbar,
|
|
2739
|
-
TableType,
|
|
2740
1340
|
cellClassesForRowSelection,
|
|
1341
|
+
createTable,
|
|
2741
1342
|
getBaseSchema,
|
|
2742
|
-
initializeTable,
|
|
2743
1343
|
makeDynamicTable,
|
|
2744
1344
|
narrowSchema,
|
|
2745
1345
|
tableButtons,
|
|
2746
1346
|
tableControls,
|
|
2747
1347
|
touch,
|
|
2748
|
-
|
|
1348
|
+
translations,
|
|
1349
|
+
useAddRow,
|
|
2749
1350
|
useTableModel
|
|
2750
1351
|
};
|
|
2751
1352
|
//# sourceMappingURL=index.mjs.map
|