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