@dxos/react-ui-table 0.8.3 → 0.8.4-main.5acf9ea
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 +246 -1641
- 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 +246 -1641
- 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 +55 -43
- 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 +57 -34
- 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);
|
|
@@ -2353,7 +1032,11 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2353
1032
|
switch (event.key) {
|
|
2354
1033
|
case "Backspace":
|
|
2355
1034
|
case "Delete": {
|
|
2356
|
-
|
|
1035
|
+
try {
|
|
1036
|
+
model.setCellData(cell, void 0);
|
|
1037
|
+
event.preventDefault();
|
|
1038
|
+
} catch {
|
|
1039
|
+
}
|
|
2357
1040
|
break;
|
|
2358
1041
|
}
|
|
2359
1042
|
}
|
|
@@ -2387,10 +1070,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2387
1070
|
]);
|
|
2388
1071
|
const handleQuery = useCallback5(async ({ field, props }, text) => {
|
|
2389
1072
|
if (model && props.referenceSchema && field.referencePath) {
|
|
2390
|
-
const space = model.
|
|
2391
|
-
|
|
2392
|
-
F:
|
|
2393
|
-
L:
|
|
1073
|
+
const space = getSpace2(model.view);
|
|
1074
|
+
invariant3(space, void 0, {
|
|
1075
|
+
F: __dxlog_file3,
|
|
1076
|
+
L: 330,
|
|
2394
1077
|
S: void 0,
|
|
2395
1078
|
A: [
|
|
2396
1079
|
"space",
|
|
@@ -2407,7 +1090,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2407
1090
|
if (schema2) {
|
|
2408
1091
|
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
2409
1092
|
const options = objects.map((obj) => {
|
|
2410
|
-
const value =
|
|
1093
|
+
const value = getValue(obj, field.referencePath);
|
|
2411
1094
|
if (!value || typeof value !== "string") {
|
|
2412
1095
|
return void 0;
|
|
2413
1096
|
}
|
|
@@ -2433,6 +1116,11 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2433
1116
|
client,
|
|
2434
1117
|
t
|
|
2435
1118
|
]);
|
|
1119
|
+
const handleSave = useCallback5(() => {
|
|
1120
|
+
dxGrid?.updateCells(true);
|
|
1121
|
+
}, [
|
|
1122
|
+
dxGrid
|
|
1123
|
+
]);
|
|
2436
1124
|
if (!model || !modals) {
|
|
2437
1125
|
return /* @__PURE__ */ React8.createElement("span", {
|
|
2438
1126
|
role: "none",
|
|
@@ -2447,18 +1135,18 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2447
1135
|
schema,
|
|
2448
1136
|
onEnter: handleEnter,
|
|
2449
1137
|
onFocus: handleFocus,
|
|
2450
|
-
onQuery: handleQuery
|
|
1138
|
+
onQuery: handleQuery,
|
|
1139
|
+
onSave: handleSave
|
|
2451
1140
|
}), /* @__PURE__ */ React8.createElement(Grid.Content, {
|
|
2452
|
-
className:
|
|
1141
|
+
className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
2453
1142
|
frozen,
|
|
2454
|
-
// getCells={getCells}
|
|
2455
1143
|
columns: model.columnMeta.value,
|
|
2456
1144
|
limitRows: model.getRowCount() ?? 0,
|
|
2457
|
-
limitColumns: model.
|
|
1145
|
+
limitColumns: model.projection.fields.length,
|
|
2458
1146
|
overscroll: "trap",
|
|
2459
1147
|
onAxisResize: handleAxisResize,
|
|
2460
1148
|
onClick: handleGridClick,
|
|
2461
|
-
|
|
1149
|
+
onKeyDownCapture: handleKeyDown,
|
|
2462
1150
|
onWheelCapture: handleWheel,
|
|
2463
1151
|
ref: setDxGrid
|
|
2464
1152
|
}), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
|
|
@@ -2484,116 +1172,33 @@ var Table = {
|
|
|
2484
1172
|
Main: TableMain
|
|
2485
1173
|
};
|
|
2486
1174
|
|
|
2487
|
-
//
|
|
2488
|
-
import { useSignals as
|
|
1175
|
+
// src/components/Table/DynamicTable.tsx
|
|
1176
|
+
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
2489
1177
|
import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
|
|
2490
1178
|
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 }) => {
|
|
1179
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1180
|
+
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2502
1181
|
var _effect = _useSignals9();
|
|
2503
1182
|
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
|
-
}, [
|
|
1183
|
+
const { typename, jsonSchema } = useMemo6(() => getBaseSchema({
|
|
1184
|
+
typename: name,
|
|
1185
|
+
properties,
|
|
1186
|
+
jsonSchema: _jsonSchema,
|
|
1187
|
+
schema
|
|
1188
|
+
}), [
|
|
2593
1189
|
name,
|
|
2594
1190
|
properties,
|
|
2595
|
-
|
|
2596
|
-
|
|
1191
|
+
_jsonSchema,
|
|
1192
|
+
schema
|
|
1193
|
+
]);
|
|
1194
|
+
const { projection, view } = useMemo6(() => makeDynamicTable({
|
|
1195
|
+
typename,
|
|
1196
|
+
jsonSchema,
|
|
1197
|
+
properties
|
|
1198
|
+
}), [
|
|
1199
|
+
typename,
|
|
1200
|
+
jsonSchema,
|
|
1201
|
+
properties
|
|
2597
1202
|
]);
|
|
2598
1203
|
const tableRef = useRef3(null);
|
|
2599
1204
|
const handleCellUpdate = useCallback6((cell) => {
|
|
@@ -2609,8 +1214,9 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2609
1214
|
dataEditable: false
|
|
2610
1215
|
}));
|
|
2611
1216
|
const model = useTableModel({
|
|
2612
|
-
table,
|
|
2613
1217
|
rows,
|
|
1218
|
+
view,
|
|
1219
|
+
schema: jsonSchema,
|
|
2614
1220
|
projection,
|
|
2615
1221
|
features,
|
|
2616
1222
|
rowActions,
|
|
@@ -2627,7 +1233,7 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2627
1233
|
]);
|
|
2628
1234
|
return /* @__PURE__ */ React9.createElement("div", {
|
|
2629
1235
|
role: "none",
|
|
2630
|
-
className:
|
|
1236
|
+
className: mx2("is-full bs-full grow grid", classNames)
|
|
2631
1237
|
}, /* @__PURE__ */ React9.createElement("div", {
|
|
2632
1238
|
role: "none",
|
|
2633
1239
|
className: "grid min-bs-0 overflow-hidden"
|
|
@@ -2643,11 +1249,11 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2643
1249
|
}
|
|
2644
1250
|
};
|
|
2645
1251
|
|
|
2646
|
-
//
|
|
2647
|
-
import { useSignals as
|
|
1252
|
+
// src/components/TableToolbar/TableToolbar.tsx
|
|
1253
|
+
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2648
1254
|
import { Rx } from "@effect-rx/rx-react";
|
|
2649
1255
|
import React10, { useMemo as useMemo7 } from "react";
|
|
2650
|
-
import { live as
|
|
1256
|
+
import { live as live2 } from "@dxos/live-object";
|
|
2651
1257
|
import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
|
|
2652
1258
|
import { rxFromSignal } from "@dxos/react-ui-menu";
|
|
2653
1259
|
var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
|
|
@@ -2696,9 +1302,9 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
|
|
|
2696
1302
|
};
|
|
2697
1303
|
});
|
|
2698
1304
|
var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
|
|
2699
|
-
var _effect =
|
|
1305
|
+
var _effect = _useSignals10();
|
|
2700
1306
|
try {
|
|
2701
|
-
const state = useMemo7(() =>
|
|
1307
|
+
const state = useMemo7(() => live2({
|
|
2702
1308
|
viewDirty
|
|
2703
1309
|
}), []);
|
|
2704
1310
|
const actionsCreator = useMemo7(() => createTableToolbarActions({
|
|
@@ -2733,18 +1339,17 @@ export {
|
|
|
2733
1339
|
Table,
|
|
2734
1340
|
TableModel,
|
|
2735
1341
|
TablePresentation,
|
|
2736
|
-
TableSchema,
|
|
2737
1342
|
TableToolbar,
|
|
2738
|
-
TableType,
|
|
2739
1343
|
cellClassesForRowSelection,
|
|
1344
|
+
createTable,
|
|
2740
1345
|
getBaseSchema,
|
|
2741
|
-
initializeTable,
|
|
2742
1346
|
makeDynamicTable,
|
|
2743
1347
|
narrowSchema,
|
|
2744
1348
|
tableButtons,
|
|
2745
1349
|
tableControls,
|
|
2746
1350
|
touch,
|
|
2747
|
-
|
|
1351
|
+
translations,
|
|
1352
|
+
useAddRow,
|
|
2748
1353
|
useTableModel
|
|
2749
1354
|
};
|
|
2750
1355
|
//# sourceMappingURL=index.mjs.map
|