@dxos/react-ui-table 0.7.4 → 0.7.5-labs.071a3e2
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-IYCSJDMB.mjs → chunk-3FR6NHPD.mjs} +7 -5
- package/dist/lib/browser/chunk-3FR6NHPD.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1424 -1067
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{chunk-MHBMVCFZ.cjs → chunk-NB3SFHGA.cjs} +9 -7
- package/dist/lib/node/chunk-NB3SFHGA.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1429 -1052
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +3 -3
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs → chunk-RLVVOZW5.mjs} +7 -5
- package/dist/lib/node-esm/chunk-RLVVOZW5.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1424 -1067
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts +1 -1
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +4 -3
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -2
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +3 -2
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/RefPanel.d.ts +4 -3
- package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +3 -2
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +2 -1
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +1 -4
- package/dist/types/src/components/Table/Table.stories.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.map +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +18 -0
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableToolbar/index.d.ts +2 -0
- package/dist/types/src/components/TableToolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +31 -71
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +1 -0
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +6 -2
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +19 -31
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +22 -0
- package/dist/types/src/model/table-presentation.d.ts.map +1 -0
- package/dist/types/src/model/table-presentation.test.d.ts +2 -0
- package/dist/types/src/model/table-presentation.test.d.ts.map +1 -0
- package/dist/types/src/model/table-sorting.d.ts +53 -0
- package/dist/types/src/model/table-sorting.d.ts.map +1 -0
- package/dist/types/src/playwright/TableManager.d.ts +2 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/table.d.ts +46 -154
- package/dist/types/src/types/table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts +63 -19
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +32 -9
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/table.d.ts +3 -2
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +35 -34
- package/src/_deprecated/schema/Schema.stories.tsx +1 -1
- package/src/components/Table/ColumnActionsMenu.tsx +12 -12
- package/src/components/Table/ColumnSettings.tsx +11 -11
- package/src/components/Table/CreateRefPanel.tsx +13 -14
- package/src/components/Table/RefPanel.tsx +9 -9
- package/src/components/Table/RowActionsMenu.tsx +6 -7
- package/src/components/Table/Table.stories.tsx +85 -56
- package/src/components/Table/Table.tsx +239 -148
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +13 -12
- package/src/components/TableCellEditor/TableCellEditor.tsx +6 -4
- package/src/components/TableToolbar/TableToolbar.tsx +72 -0
- package/src/components/{Toolbar → TableToolbar}/index.ts +1 -1
- package/src/components/index.ts +1 -1
- package/src/components/testing.ts +10 -8
- package/src/index.ts +2 -0
- package/src/model/index.ts +1 -0
- package/src/model/modal-controller.ts +15 -48
- package/src/model/selection-model.ts +12 -1
- package/src/model/table-model.test.ts +4 -76
- package/src/model/table-model.ts +73 -304
- package/src/model/table-presentation.test.ts +102 -0
- package/src/model/table-presentation.ts +235 -0
- package/src/model/table-sorting.ts +215 -0
- package/src/playwright/TableManager.ts +5 -1
- package/src/playwright/smoke.spec.ts +94 -9
- package/src/translations.ts +2 -1
- package/src/types/table.ts +4 -4
- package/src/util/index.ts +1 -0
- package/src/util/table-buttons.ts +127 -48
- package/src/util/table-controls.ts +71 -7
- package/src/util/table.ts +93 -52
- package/dist/lib/browser/chunk-IYCSJDMB.mjs.map +0 -7
- package/dist/lib/node/chunk-MHBMVCFZ.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-BMWGPXPL.mjs.map +0 -7
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -21
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/common.d.ts +0 -14
- package/dist/types/src/components/Toolbar/common.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/index.d.ts +0 -2
- package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
- package/src/components/Toolbar/Toolbar.tsx +0 -87
- package/src/components/Toolbar/common.tsx +0 -71
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TableSchema,
|
|
3
3
|
TableType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3FR6NHPD.mjs";
|
|
5
5
|
|
|
6
6
|
// packages/ui/react-ui-table/src/translations.ts
|
|
7
7
|
var translationKey = "table";
|
|
@@ -17,7 +17,7 @@ var translations_default = [
|
|
|
17
17
|
"new schema": "New schema",
|
|
18
18
|
"continue label": "Continue",
|
|
19
19
|
"create stack section label": "Create table",
|
|
20
|
-
"add row": "Add row",
|
|
20
|
+
"add row label": "Add row",
|
|
21
21
|
"create comment": "Create thread",
|
|
22
22
|
"column action sort descending": "Sort Descending",
|
|
23
23
|
"column action sort ascending": "Sort Ascending",
|
|
@@ -28,55 +28,56 @@ var translations_default = [
|
|
|
28
28
|
"bulk delete row label": "Delete selected rows",
|
|
29
29
|
"column deleted label": "Column deleted",
|
|
30
30
|
"new column button label": "Create column",
|
|
31
|
-
"create new object label": "Create new object \u201C{{text}}\u201D"
|
|
31
|
+
"create new object label": "Create new object \u201C{{text}}\u201D",
|
|
32
|
+
"save view label": "Save changes to view"
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
];
|
|
36
37
|
|
|
37
38
|
// packages/ui/react-ui-table/src/components/Table/Table.tsx
|
|
38
|
-
import React7, { forwardRef, useCallback as useCallback4, useImperativeHandle, useState as useState2 } from "react";
|
|
39
|
-
import { getValue } from "@dxos/echo-schema";
|
|
40
|
-
import { invariant as
|
|
39
|
+
import React7, { forwardRef, useCallback as useCallback4, useImperativeHandle, useState as useState2, useMemo as useMemo4 } from "react";
|
|
40
|
+
import { getValue as getValue4 } from "@dxos/echo-schema";
|
|
41
|
+
import { invariant as invariant3 } from "@dxos/invariant";
|
|
41
42
|
import { Filter, getSpace as getSpace4, fullyQualifiedId } from "@dxos/react-client/echo";
|
|
42
43
|
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
43
44
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
44
45
|
import { Grid, closestCell } from "@dxos/react-ui-grid";
|
|
45
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
46
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
46
47
|
import { isNotFalsy } from "@dxos/util";
|
|
47
48
|
|
|
48
49
|
// packages/ui/react-ui-table/src/components/Table/ColumnActionsMenu.tsx
|
|
49
50
|
import React from "react";
|
|
50
51
|
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
51
|
-
var ColumnActionsMenu = ({ model }) => {
|
|
52
|
+
var ColumnActionsMenu = ({ model, modals }) => {
|
|
52
53
|
const { t } = useTranslation(translationKey);
|
|
53
|
-
const state =
|
|
54
|
-
if (
|
|
54
|
+
const state = modals.state.value;
|
|
55
|
+
if (state?.type !== "column") {
|
|
55
56
|
return null;
|
|
56
57
|
}
|
|
57
|
-
const currentSort = model.sorting;
|
|
58
|
+
const currentSort = model.sorting?.sorting;
|
|
58
59
|
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
59
60
|
return /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
|
|
60
61
|
modal: false,
|
|
61
|
-
open:
|
|
62
|
-
onOpenChange:
|
|
62
|
+
open: true,
|
|
63
|
+
onOpenChange: modals.close
|
|
63
64
|
}, /* @__PURE__ */ React.createElement(DropdownMenu.VirtualTrigger, {
|
|
64
|
-
virtualRef:
|
|
65
|
+
virtualRef: modals.trigger
|
|
65
66
|
}), /* @__PURE__ */ React.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React.createElement(DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
66
67
|
"data-testid": "column-sort-descending",
|
|
67
|
-
onClick: () => model.setSort(state.fieldId, "desc")
|
|
68
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
68
69
|
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
69
70
|
"data-testid": "column-sort-ascending",
|
|
70
|
-
onClick: () => model.setSort(state.fieldId, "asc")
|
|
71
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
71
72
|
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
72
73
|
"data-testid": "column-clear-sort",
|
|
73
|
-
onClick: () => model.clearSort()
|
|
74
|
+
onClick: () => model.sorting?.clearSort()
|
|
74
75
|
}, t("column action clear sorting")), model.getColumnCount() > 1 && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
75
76
|
"data-testid": "column-delete",
|
|
76
77
|
onClick: () => model.deleteColumn(state.fieldId)
|
|
77
78
|
}, t("column action delete")), /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
78
79
|
"data-testid": "column-settings",
|
|
79
|
-
onClick: () =>
|
|
80
|
+
onClick: () => modals.openColumnSettings()
|
|
80
81
|
}, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
|
|
81
82
|
};
|
|
82
83
|
|
|
@@ -85,9 +86,9 @@ import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
85
86
|
import { getSpace } from "@dxos/react-client/echo";
|
|
86
87
|
import { DropdownMenu as DropdownMenu2 } from "@dxos/react-ui";
|
|
87
88
|
import { FieldEditor } from "@dxos/react-ui-form";
|
|
88
|
-
var ColumnSettings = ({ model, onNewColumn }) => {
|
|
89
|
+
var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
89
90
|
const [newField, setNewField] = useState();
|
|
90
|
-
const state =
|
|
91
|
+
const state = modals.state.value;
|
|
91
92
|
const space = getSpace(model?.table);
|
|
92
93
|
useEffect(() => {
|
|
93
94
|
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
@@ -106,19 +107,19 @@ var ColumnSettings = ({ model, onNewColumn }) => {
|
|
|
106
107
|
if (state?.type === "columnSettings") {
|
|
107
108
|
const { mode } = state;
|
|
108
109
|
if (mode.type === "edit") {
|
|
109
|
-
return model?.table?.view?.fields.find((f) => f.id === mode.fieldId);
|
|
110
|
+
return model?.table?.view?.target?.fields.find((f) => f.id === mode.fieldId);
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
return void 0;
|
|
113
114
|
}, [
|
|
114
|
-
model?.table?.view?.fields,
|
|
115
|
+
model?.table?.view?.target?.fields,
|
|
115
116
|
state
|
|
116
117
|
]);
|
|
117
118
|
const field = existingField ?? newField;
|
|
118
119
|
const handleSave = useCallback(() => {
|
|
119
|
-
|
|
120
|
+
modals.close();
|
|
120
121
|
}, [
|
|
121
|
-
|
|
122
|
+
modals
|
|
122
123
|
]);
|
|
123
124
|
const handleCancel = useCallback(() => {
|
|
124
125
|
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
@@ -129,18 +130,18 @@ var ColumnSettings = ({ model, onNewColumn }) => {
|
|
|
129
130
|
state,
|
|
130
131
|
newField
|
|
131
132
|
]);
|
|
132
|
-
if (!model?.table?.view || !model.projection || !field) {
|
|
133
|
+
if (!model?.table?.view?.target || !model.projection || !field) {
|
|
133
134
|
return null;
|
|
134
135
|
}
|
|
135
136
|
return /* @__PURE__ */ React2.createElement(DropdownMenu2.Root, {
|
|
136
137
|
modal: false,
|
|
137
138
|
open: state?.type === "columnSettings"
|
|
138
139
|
}, /* @__PURE__ */ React2.createElement(DropdownMenu2.VirtualTrigger, {
|
|
139
|
-
virtualRef:
|
|
140
|
+
virtualRef: modals.trigger
|
|
140
141
|
}), /* @__PURE__ */ React2.createElement(DropdownMenu2.Portal, null, /* @__PURE__ */ React2.createElement(DropdownMenu2.Content, {
|
|
141
142
|
classNames: "md:is-64"
|
|
142
143
|
}, /* @__PURE__ */ React2.createElement(DropdownMenu2.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
|
|
143
|
-
view: model.table.view,
|
|
144
|
+
view: model.table.view.target,
|
|
144
145
|
projection: model.projection,
|
|
145
146
|
field,
|
|
146
147
|
registry: space?.db.schemaRegistry,
|
|
@@ -156,15 +157,17 @@ import { create, getSpace as getSpace2 } from "@dxos/react-client/echo";
|
|
|
156
157
|
import { Popover } from "@dxos/react-ui";
|
|
157
158
|
import { Form } from "@dxos/react-ui-form";
|
|
158
159
|
import { useGridContext } from "@dxos/react-ui-grid";
|
|
159
|
-
var CreateRefPanel = ({ model, __gridScope }) => {
|
|
160
|
+
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
160
161
|
const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
|
|
161
162
|
const space = getSpace2(model?.table);
|
|
162
|
-
const state =
|
|
163
|
+
const state = modals.state.value;
|
|
163
164
|
const schema = useMemo2(() => {
|
|
164
165
|
if (!space || state?.type !== "createRefPanel") {
|
|
165
166
|
return;
|
|
166
167
|
}
|
|
167
|
-
const schema2 = space.db.schemaRegistry.
|
|
168
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
169
|
+
typename: state.typename
|
|
170
|
+
}).runSync();
|
|
168
171
|
if (schema2) {
|
|
169
172
|
const omit = S.omit("id");
|
|
170
173
|
return omit(schema2);
|
|
@@ -177,23 +180,25 @@ var CreateRefPanel = ({ model, __gridScope }) => {
|
|
|
177
180
|
if (!model || !space || state?.type !== "createRefPanel") {
|
|
178
181
|
return;
|
|
179
182
|
}
|
|
180
|
-
const schema2 = space.db.schemaRegistry.
|
|
183
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
184
|
+
typename: state.typename
|
|
185
|
+
}).runSync();
|
|
181
186
|
if (schema2) {
|
|
182
187
|
const obj = space.db.add(create(schema2, values));
|
|
183
188
|
state.onCreate?.(obj);
|
|
184
189
|
}
|
|
185
|
-
void
|
|
190
|
+
void modals.close();
|
|
186
191
|
}, [
|
|
187
|
-
|
|
192
|
+
modals,
|
|
188
193
|
space,
|
|
189
194
|
state
|
|
190
195
|
]);
|
|
191
196
|
const handleCancel = useCallback2(() => {
|
|
192
197
|
if (model) {
|
|
193
|
-
|
|
198
|
+
modals.close();
|
|
194
199
|
}
|
|
195
200
|
}, [
|
|
196
|
-
|
|
201
|
+
modals
|
|
197
202
|
]);
|
|
198
203
|
if (!model?.table?.view || !model.projection) {
|
|
199
204
|
return null;
|
|
@@ -203,11 +208,11 @@ var CreateRefPanel = ({ model, __gridScope }) => {
|
|
|
203
208
|
open: state?.type === "createRefPanel" && !!schema,
|
|
204
209
|
onOpenChange: (nextOpen) => {
|
|
205
210
|
if (model && !nextOpen) {
|
|
206
|
-
return
|
|
211
|
+
return modals.close();
|
|
207
212
|
}
|
|
208
213
|
}
|
|
209
214
|
}, /* @__PURE__ */ React3.createElement(Popover.VirtualTrigger, {
|
|
210
|
-
virtualRef:
|
|
215
|
+
virtualRef: modals.trigger
|
|
211
216
|
}), /* @__PURE__ */ React3.createElement(Popover.Portal, null, /* @__PURE__ */ React3.createElement(Popover.Content, {
|
|
212
217
|
classNames: "md:is-64",
|
|
213
218
|
"data-grid": gridId
|
|
@@ -231,24 +236,24 @@ var getRefTargetObj = (space, id) => {
|
|
|
231
236
|
return void 0;
|
|
232
237
|
}
|
|
233
238
|
};
|
|
234
|
-
var RefPanel = ({ model }) => {
|
|
235
|
-
const state =
|
|
236
|
-
const space = getSpace3(model
|
|
239
|
+
var RefPanel = ({ model, modals }) => {
|
|
240
|
+
const state = modals.state.value;
|
|
241
|
+
const space = getSpace3(model.table);
|
|
237
242
|
const targetObj = getRefTargetObj(space, state?.type === "refPanel" ? state.targetId : void 0);
|
|
238
243
|
const schema = space && state?.type === "refPanel" ? space.db.schemaRegistry.getSchema(state.typename) : void 0;
|
|
239
|
-
if (!model
|
|
244
|
+
if (!model.table?.view || !model.projection) {
|
|
240
245
|
return null;
|
|
241
246
|
}
|
|
242
247
|
return /* @__PURE__ */ React4.createElement(Popover2.Root, {
|
|
243
248
|
modal: false,
|
|
244
249
|
open: state?.type === "refPanel" && !!targetObj && !!schema,
|
|
245
250
|
onOpenChange: (nextOpen) => {
|
|
246
|
-
if (
|
|
247
|
-
return
|
|
251
|
+
if (!nextOpen) {
|
|
252
|
+
return modals.close();
|
|
248
253
|
}
|
|
249
254
|
}
|
|
250
255
|
}, /* @__PURE__ */ React4.createElement(Popover2.VirtualTrigger, {
|
|
251
|
-
virtualRef:
|
|
256
|
+
virtualRef: modals.trigger
|
|
252
257
|
}), /* @__PURE__ */ React4.createElement(Popover2.Portal, null, /* @__PURE__ */ React4.createElement(Popover2.Content, {
|
|
253
258
|
classNames: "md:is-64"
|
|
254
259
|
}, targetObj && schema && /* @__PURE__ */ React4.createElement(Form2, {
|
|
@@ -261,762 +266,319 @@ var RefPanel = ({ model }) => {
|
|
|
261
266
|
// packages/ui/react-ui-table/src/components/Table/RowActionsMenu.tsx
|
|
262
267
|
import React5 from "react";
|
|
263
268
|
import { DropdownMenu as DropdownMenu3, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
264
|
-
var RowActionsMenu = ({ model }) => {
|
|
269
|
+
var RowActionsMenu = ({ model, modals }) => {
|
|
265
270
|
const { t } = useTranslation2(translationKey);
|
|
266
271
|
const hasSelection = model.selection.hasSelection.value;
|
|
267
|
-
const state =
|
|
272
|
+
const state = modals.state.value;
|
|
268
273
|
if (state?.type !== "row") {
|
|
269
274
|
return null;
|
|
270
275
|
}
|
|
271
276
|
return /* @__PURE__ */ React5.createElement(DropdownMenu3.Root, {
|
|
272
277
|
modal: false,
|
|
273
278
|
open: true,
|
|
274
|
-
onOpenChange:
|
|
279
|
+
onOpenChange: modals.close
|
|
275
280
|
}, /* @__PURE__ */ React5.createElement(DropdownMenu3.VirtualTrigger, {
|
|
276
|
-
virtualRef:
|
|
281
|
+
virtualRef: modals.trigger
|
|
277
282
|
}), /* @__PURE__ */ React5.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Viewport, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Item, {
|
|
278
283
|
"data-testid": "row-menu-delete",
|
|
279
284
|
onClick: () => model.deleteRow(state.rowIndex)
|
|
280
285
|
}, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React5.createElement(DropdownMenu3.Arrow, null)));
|
|
281
286
|
};
|
|
282
287
|
|
|
283
|
-
// packages/ui/react-ui-table/src/
|
|
284
|
-
import
|
|
285
|
-
import {
|
|
288
|
+
// packages/ui/react-ui-table/src/model/table-model.ts
|
|
289
|
+
import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
|
|
290
|
+
import { Resource as Resource2 } from "@dxos/context";
|
|
291
|
+
import { FormatEnum as FormatEnum3, getValue as getValue2, setValue } from "@dxos/echo-schema";
|
|
286
292
|
import { invariant } from "@dxos/invariant";
|
|
287
|
-
import {
|
|
293
|
+
import { isReactiveObject, makeRef as makeRef2 } from "@dxos/live-object";
|
|
294
|
+
import { PublicKey as PublicKey2 } from "@dxos/react-client";
|
|
295
|
+
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
288
296
|
|
|
289
|
-
// packages/ui/react-ui-table/src/
|
|
290
|
-
import {
|
|
291
|
-
import {
|
|
292
|
-
var completion = ({ debug, onQuery, onMatch }) => {
|
|
293
|
-
return [
|
|
294
|
-
EditorView.theme({
|
|
295
|
-
".cm-completionDialog": {
|
|
296
|
-
width: "var(--dx-gridCellWidth)"
|
|
297
|
-
}
|
|
298
|
-
}),
|
|
299
|
-
autocompletion({
|
|
300
|
-
icons: false,
|
|
301
|
-
activateOnTyping: true,
|
|
302
|
-
closeOnBlur: !debug,
|
|
303
|
-
override: [
|
|
304
|
-
async (context) => {
|
|
305
|
-
const text = context.state.doc.toString();
|
|
306
|
-
return {
|
|
307
|
-
from: 0,
|
|
308
|
-
options: await onQuery(text)
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
],
|
|
312
|
-
// TODO(burdon): Consts from grid (to line-up with grid).
|
|
313
|
-
tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
|
|
314
|
-
optionClass: () => "flex h-[33px] items-center"
|
|
315
|
-
}),
|
|
316
|
-
// Check for accepted completion metadata in the transaction.
|
|
317
|
-
EditorView.updateListener.of((update) => {
|
|
318
|
-
update.transactions.forEach((tr) => {
|
|
319
|
-
const completion2 = tr.annotation(pickedCompletion);
|
|
320
|
-
if (completion2) {
|
|
321
|
-
onMatch(completion2.data);
|
|
322
|
-
}
|
|
323
|
-
});
|
|
324
|
-
})
|
|
325
|
-
];
|
|
326
|
-
};
|
|
297
|
+
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
298
|
+
import { computed, effect, signal } from "@preact/signals-core";
|
|
299
|
+
import { Resource } from "@dxos/context";
|
|
327
300
|
|
|
328
|
-
// packages/ui/react-ui-table/src/
|
|
329
|
-
var
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
var
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
301
|
+
// packages/ui/react-ui-table/src/util/signals.ts
|
|
302
|
+
var touch = (value) => value;
|
|
303
|
+
|
|
304
|
+
// packages/ui/react-ui-table/src/util/table.ts
|
|
305
|
+
import { AST, Format, FormatEnum, S as S2, TypedObject, TypeEnum } from "@dxos/echo-schema";
|
|
306
|
+
import { PublicKey } from "@dxos/react-client";
|
|
307
|
+
import { create as create2, makeRef } from "@dxos/react-client/echo";
|
|
308
|
+
import { createFieldId, createView, getSchemaProperties, ViewProjection } from "@dxos/schema";
|
|
309
|
+
var initializeTable = async ({ space, table, initialRow = true, initialSchema }) => {
|
|
310
|
+
if (initialSchema) {
|
|
311
|
+
const schema = await space.db.schemaRegistry.query({
|
|
312
|
+
typename: initialSchema
|
|
313
|
+
}).firstOrUndefined();
|
|
314
|
+
if (!schema) {
|
|
315
|
+
throw new Error(`Schema not found: ${initialSchema}`);
|
|
342
316
|
}
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
317
|
+
const fields = getSchemaProperties(schema.ast).filter((prop) => prop.type !== "object" || prop.format === FormatEnum.Ref).map((prop) => prop.name);
|
|
318
|
+
table.view = makeRef(createView({
|
|
319
|
+
// TODO(ZaymonFC): Don't hardcode name?
|
|
320
|
+
name: "View",
|
|
321
|
+
typename: schema.typename,
|
|
322
|
+
jsonSchema: schema.jsonSchema,
|
|
323
|
+
fields
|
|
324
|
+
}));
|
|
325
|
+
return schema;
|
|
326
|
+
} else {
|
|
327
|
+
const ContactSchema = TypedObject({
|
|
328
|
+
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
329
|
+
version: "0.1.0"
|
|
330
|
+
})({
|
|
331
|
+
name: S2.optional(S2.String).annotations({
|
|
332
|
+
[AST.TitleAnnotationId]: "Name"
|
|
333
|
+
}),
|
|
334
|
+
active: S2.optional(S2.Boolean),
|
|
335
|
+
email: S2.optional(Format.Email),
|
|
336
|
+
salary: S2.optional(Format.Currency()).annotations({
|
|
337
|
+
[AST.TitleAnnotationId]: "Salary"
|
|
338
|
+
})
|
|
339
|
+
});
|
|
340
|
+
const [contactSchema] = await space.db.schemaRegistry.register([
|
|
341
|
+
ContactSchema
|
|
342
|
+
]);
|
|
343
|
+
table.view = makeRef(createView({
|
|
344
|
+
name: "View",
|
|
345
|
+
typename: contactSchema.typename,
|
|
346
|
+
jsonSchema: contactSchema.jsonSchema,
|
|
347
|
+
fields: [
|
|
348
|
+
"name",
|
|
349
|
+
"email",
|
|
350
|
+
"salary",
|
|
351
|
+
"active"
|
|
353
352
|
]
|
|
353
|
+
}));
|
|
354
|
+
const projection = new ViewProjection(contactSchema, table.view.target);
|
|
355
|
+
projection.setFieldProjection({
|
|
356
|
+
field: {
|
|
357
|
+
id: table.view.target.fields.find((f) => f.path === "salary").id,
|
|
358
|
+
path: "salary",
|
|
359
|
+
size: 150
|
|
360
|
+
}
|
|
354
361
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const handleEnter = useCallback3((value) => {
|
|
361
|
-
if (!model || !editing) {
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
const cell = parseCellIndex(editing.index);
|
|
365
|
-
model.setCellData(cell, value);
|
|
366
|
-
onEnter?.(cell);
|
|
367
|
-
onFocus?.();
|
|
368
|
-
setEditing(null);
|
|
369
|
-
}, [
|
|
370
|
-
model,
|
|
371
|
-
editing
|
|
372
|
-
]);
|
|
373
|
-
const handleBlur = useCallback3((value) => {
|
|
374
|
-
if (!model || !editing) {
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
if (suppressNextBlur.current) {
|
|
378
|
-
suppressNextBlur.current = false;
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
const cell = parseCellIndex(editing.index);
|
|
382
|
-
if (value !== void 0) {
|
|
383
|
-
model.setCellData(cell, value);
|
|
384
|
-
}
|
|
385
|
-
}, [
|
|
386
|
-
model,
|
|
387
|
-
editing
|
|
388
|
-
]);
|
|
389
|
-
const handleClose = useCallback3((value, event) => {
|
|
390
|
-
if (!model || !editing || !fieldProjection) {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
const cell = parseCellIndex(editing.index);
|
|
394
|
-
onEnter?.(cell);
|
|
395
|
-
if (event && onFocus) {
|
|
396
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
397
|
-
}
|
|
398
|
-
}, [
|
|
399
|
-
model,
|
|
400
|
-
editing,
|
|
401
|
-
onFocus,
|
|
402
|
-
onEnter,
|
|
403
|
-
fieldProjection,
|
|
404
|
-
determineNavigationAxis,
|
|
405
|
-
determineNavigationDelta
|
|
406
|
-
]);
|
|
407
|
-
const extension = useMemo3(() => {
|
|
408
|
-
if (!fieldProjection) {
|
|
409
|
-
return [];
|
|
410
|
-
}
|
|
411
|
-
const extension2 = [
|
|
412
|
-
editorKeys({
|
|
413
|
-
onClose: handleClose,
|
|
414
|
-
...editing?.initialContent && {
|
|
415
|
-
onNav: handleClose
|
|
416
|
-
}
|
|
417
|
-
})
|
|
418
|
-
];
|
|
419
|
-
if (onQuery) {
|
|
420
|
-
switch (fieldProjection.props.format) {
|
|
421
|
-
case FormatEnum.Ref: {
|
|
422
|
-
extension2.push([
|
|
423
|
-
completion({
|
|
424
|
-
onQuery: (text) => onQuery(fieldProjection, text),
|
|
425
|
-
onMatch: (data) => {
|
|
426
|
-
if (model && editing) {
|
|
427
|
-
if (isCreateOption(data)) {
|
|
428
|
-
const { field, props } = fieldProjection;
|
|
429
|
-
if (props.referenceSchema) {
|
|
430
|
-
suppressNextBlur.current = true;
|
|
431
|
-
model.modalController.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
|
|
432
|
-
[field.referencePath]: data.text
|
|
433
|
-
}, (data2) => {
|
|
434
|
-
handleEnter(data2);
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
} else {
|
|
438
|
-
handleEnter(data);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
})
|
|
443
|
-
]);
|
|
444
|
-
break;
|
|
445
|
-
}
|
|
362
|
+
projection.setFieldProjection({
|
|
363
|
+
field: {
|
|
364
|
+
id: table.view.target.fields.find((f) => f.path === "active").id,
|
|
365
|
+
path: "active",
|
|
366
|
+
size: 100
|
|
446
367
|
}
|
|
368
|
+
});
|
|
369
|
+
projection.setFieldProjection({
|
|
370
|
+
field: {
|
|
371
|
+
id: createFieldId(),
|
|
372
|
+
path: "manager",
|
|
373
|
+
referencePath: "name"
|
|
374
|
+
},
|
|
375
|
+
props: {
|
|
376
|
+
property: "manager",
|
|
377
|
+
type: TypeEnum.Ref,
|
|
378
|
+
format: FormatEnum.Ref,
|
|
379
|
+
referenceSchema: contactSchema.typename,
|
|
380
|
+
title: "Manager"
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
if (initialRow) {
|
|
384
|
+
space.db.add(create2(contactSchema, {}));
|
|
447
385
|
}
|
|
448
|
-
return
|
|
449
|
-
}, [
|
|
450
|
-
model,
|
|
451
|
-
editing,
|
|
452
|
-
fieldProjection,
|
|
453
|
-
handleClose
|
|
454
|
-
]);
|
|
455
|
-
const getCellContent = useCallback3(() => {
|
|
456
|
-
if (model && editing) {
|
|
457
|
-
const value = model.getCellData(parseCellIndex(editing.index));
|
|
458
|
-
return value !== void 0 ? String(value) : "";
|
|
459
|
-
}
|
|
460
|
-
}, [
|
|
461
|
-
model,
|
|
462
|
-
editing
|
|
463
|
-
]);
|
|
464
|
-
return /* @__PURE__ */ React6.createElement(GridCellEditor, {
|
|
465
|
-
extension,
|
|
466
|
-
getCellContent,
|
|
467
|
-
onBlur: handleBlur
|
|
468
|
-
});
|
|
469
|
-
};
|
|
470
|
-
var determineNavigationAxis = ({ key }) => {
|
|
471
|
-
switch (key) {
|
|
472
|
-
case "ArrowUp":
|
|
473
|
-
case "ArrowDown":
|
|
474
|
-
case "Enter": {
|
|
475
|
-
return "row";
|
|
476
|
-
}
|
|
477
|
-
case "ArrowLeft":
|
|
478
|
-
case "ArrowRight":
|
|
479
|
-
case "Tab":
|
|
480
|
-
return "col";
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
var determineNavigationDelta = ({ key, shift }) => {
|
|
484
|
-
switch (key) {
|
|
485
|
-
case "ArrowUp":
|
|
486
|
-
case "ArrowLeft":
|
|
487
|
-
return -1;
|
|
488
|
-
case "ArrowDown":
|
|
489
|
-
case "ArrowRight":
|
|
490
|
-
return 1;
|
|
386
|
+
return contactSchema;
|
|
491
387
|
}
|
|
492
|
-
return shift ? -1 : 1;
|
|
493
388
|
};
|
|
494
389
|
|
|
495
|
-
// packages/ui/react-ui-table/src/
|
|
496
|
-
var
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
frozenColsEnd: 1
|
|
390
|
+
// packages/ui/react-ui-table/src/util/table-buttons.ts
|
|
391
|
+
var BUTTON_IDENTIFIERS = {
|
|
392
|
+
columnSettings: "data-table-column-settings-button",
|
|
393
|
+
newColumn: "data-table-new-column-button",
|
|
394
|
+
referencedCell: "data-table-ref-cell-button",
|
|
395
|
+
rowMenu: "data-table-row-menu-button",
|
|
396
|
+
sort: "data-table-sort-button"
|
|
503
397
|
};
|
|
504
|
-
var
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}, children);
|
|
398
|
+
var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
|
|
399
|
+
const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
400
|
+
const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
|
|
401
|
+
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><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
509
402
|
};
|
|
510
|
-
var
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
update: (cell) => {
|
|
521
|
-
if (cell) {
|
|
522
|
-
dxGrid.updateIfWithinBounds(cell);
|
|
523
|
-
} else {
|
|
524
|
-
dxGrid.updateCells(true);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
}, [
|
|
529
|
-
model,
|
|
530
|
-
dxGrid
|
|
531
|
-
]);
|
|
532
|
-
const handleFocus = useCallback4((increment, delta) => {
|
|
533
|
-
if (dxGrid) {
|
|
534
|
-
dxGrid.refocus(increment, delta);
|
|
535
|
-
}
|
|
536
|
-
}, [
|
|
537
|
-
dxGrid
|
|
538
|
-
]);
|
|
539
|
-
const handleEnter = useCallback4((cell) => {
|
|
540
|
-
if (model && cell.row === model.getRowCount() - 1) {
|
|
541
|
-
model.insertRow(cell.row);
|
|
542
|
-
if (dxGrid) {
|
|
543
|
-
requestAnimationFrame(() => {
|
|
544
|
-
dxGrid?.scrollToRow(cell.row + 1);
|
|
545
|
-
dxGrid?.refocus("row", 1);
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}, [
|
|
550
|
-
model,
|
|
551
|
-
dxGrid
|
|
552
|
-
]);
|
|
553
|
-
const handleKeyDown = useCallback4((event) => {
|
|
554
|
-
const cell = closestCell(event.target);
|
|
555
|
-
if (!model || !cell) {
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
switch (event.key) {
|
|
559
|
-
case "Backspace":
|
|
560
|
-
case "Delete": {
|
|
561
|
-
model.setCellData(cell, void 0);
|
|
562
|
-
break;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}, [
|
|
566
|
-
model
|
|
567
|
-
]);
|
|
568
|
-
const handleAxisResize = useCallback4((event) => {
|
|
569
|
-
if (event.axis === "col") {
|
|
570
|
-
const columnIndex = parseInt(event.index, 10);
|
|
571
|
-
model?.setColumnWidth(columnIndex, event.size);
|
|
572
|
-
}
|
|
573
|
-
}, [
|
|
574
|
-
model
|
|
575
|
-
]);
|
|
576
|
-
const handleWheel = useCallback4((event) => {
|
|
577
|
-
if (!ignoreAttention && !hasAttention) {
|
|
578
|
-
event.stopPropagation();
|
|
579
|
-
}
|
|
580
|
-
}, [
|
|
581
|
-
hasAttention,
|
|
582
|
-
ignoreAttention
|
|
583
|
-
]);
|
|
584
|
-
const handleNewColumn = useCallback4(() => {
|
|
585
|
-
const columns = model?.getColumnCount();
|
|
586
|
-
if (dxGrid && columns) {
|
|
587
|
-
dxGrid.scrollToColumn(columns - 1);
|
|
588
|
-
}
|
|
589
|
-
}, [
|
|
590
|
-
model,
|
|
591
|
-
dxGrid
|
|
592
|
-
]);
|
|
593
|
-
const handleQuery = useCallback4(async ({ field, props }, text) => {
|
|
594
|
-
if (model && props.referenceSchema && field.referencePath) {
|
|
595
|
-
const space = getSpace4(model.table);
|
|
596
|
-
invariant2(space, void 0, {
|
|
597
|
-
F: __dxlog_file2,
|
|
598
|
-
L: 180,
|
|
599
|
-
S: void 0,
|
|
600
|
-
A: [
|
|
601
|
-
"space",
|
|
602
|
-
""
|
|
603
|
-
]
|
|
604
|
-
});
|
|
605
|
-
const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
|
|
606
|
-
if (schema) {
|
|
607
|
-
const { objects } = await space.db.query(Filter.schema(schema)).run();
|
|
608
|
-
const options = objects.map((obj) => {
|
|
609
|
-
const value = getValue(obj, field.referencePath);
|
|
610
|
-
if (!value || typeof value !== "string") {
|
|
611
|
-
return void 0;
|
|
612
|
-
}
|
|
613
|
-
return {
|
|
614
|
-
label: value,
|
|
615
|
-
data: obj
|
|
616
|
-
};
|
|
617
|
-
}).filter(isNotFalsy);
|
|
618
|
-
return [
|
|
619
|
-
...options,
|
|
620
|
-
{
|
|
621
|
-
label: t("create new object label", {
|
|
622
|
-
text
|
|
623
|
-
}),
|
|
624
|
-
data: createOption(text)
|
|
625
|
-
}
|
|
626
|
-
];
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
return [];
|
|
630
|
-
}, [
|
|
631
|
-
model
|
|
632
|
-
]);
|
|
633
|
-
if (!model) {
|
|
634
|
-
return /* @__PURE__ */ React7.createElement("span", {
|
|
635
|
-
role: "none",
|
|
636
|
-
className: "attention-surface"
|
|
403
|
+
var addColumnButton = {
|
|
404
|
+
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
405
|
+
icon: "ph--plus--regular",
|
|
406
|
+
render: ({ disabled }) => {
|
|
407
|
+
return createButton({
|
|
408
|
+
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
409
|
+
icon: addColumnButton.icon,
|
|
410
|
+
disabled,
|
|
411
|
+
data: {},
|
|
412
|
+
testId: "table-new-column-button"
|
|
637
413
|
});
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
642
|
-
model,
|
|
643
|
-
onEnter: handleEnter,
|
|
644
|
-
onFocus: handleFocus,
|
|
645
|
-
onQuery: handleQuery
|
|
646
|
-
}), /* @__PURE__ */ React7.createElement(Grid.Content, {
|
|
647
|
-
onWheelCapture: handleWheel,
|
|
648
|
-
className: mx("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
|
|
649
|
-
frozen,
|
|
650
|
-
columns: model.columnMeta.value,
|
|
651
|
-
limitRows: model.getRowCount() ?? 0,
|
|
652
|
-
limitColumns: model.table.view?.fields?.length ?? 0,
|
|
653
|
-
onAxisResize: handleAxisResize,
|
|
654
|
-
onClick: model?.handleGridClick,
|
|
655
|
-
onKeyDown: handleKeyDown,
|
|
656
|
-
overscroll: "trap",
|
|
657
|
-
ref: setDxGrid
|
|
658
|
-
}), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
|
|
659
|
-
model
|
|
660
|
-
}), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
|
|
661
|
-
model
|
|
662
|
-
}), /* @__PURE__ */ React7.createElement(ColumnSettings, {
|
|
663
|
-
model,
|
|
664
|
-
onNewColumn: handleNewColumn
|
|
665
|
-
}), /* @__PURE__ */ React7.createElement(RefPanel, {
|
|
666
|
-
model
|
|
667
|
-
}), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
|
|
668
|
-
model
|
|
669
|
-
}));
|
|
670
|
-
});
|
|
671
|
-
var Table = {
|
|
672
|
-
Root: TableRoot,
|
|
673
|
-
Main: TableMain
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
// packages/ui/react-ui-table/src/components/Toolbar/Toolbar.tsx
|
|
677
|
-
import { createContext } from "@radix-ui/react-context";
|
|
678
|
-
import React9 from "react";
|
|
679
|
-
import { Toolbar as NaturalToolbar2, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
680
|
-
|
|
681
|
-
// packages/ui/react-ui-table/src/components/Toolbar/common.tsx
|
|
682
|
-
import React8 from "react";
|
|
683
|
-
import { Icon, Toolbar as NaturalToolbar, Tooltip } from "@dxos/react-ui";
|
|
684
|
-
var buttonStyles = "min-bs-0 p-2";
|
|
685
|
-
var tooltipProps = {
|
|
686
|
-
side: "top",
|
|
687
|
-
classNames: "z-10"
|
|
414
|
+
},
|
|
415
|
+
getData: (_el) => ({
|
|
416
|
+
type: "newColumn"
|
|
417
|
+
})
|
|
688
418
|
};
|
|
689
|
-
var
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
})
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
419
|
+
var columnSettingsButton = {
|
|
420
|
+
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
421
|
+
icon: "ph--caret-down--regular",
|
|
422
|
+
render: ({ fieldId }) => {
|
|
423
|
+
return createButton({
|
|
424
|
+
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
425
|
+
icon: columnSettingsButton.icon,
|
|
426
|
+
data: {
|
|
427
|
+
"data-field-id": fieldId
|
|
428
|
+
},
|
|
429
|
+
testId: "table-column-settings-button"
|
|
430
|
+
});
|
|
431
|
+
},
|
|
432
|
+
getData: (el) => ({
|
|
433
|
+
type: "columnSettings",
|
|
434
|
+
fieldId: el.getAttribute("data-field-id")
|
|
435
|
+
})
|
|
706
436
|
};
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
437
|
+
var referencedCellButton = {
|
|
438
|
+
attr: BUTTON_IDENTIFIERS.referencedCell,
|
|
439
|
+
icon: "ph--link-simple-horizontal--regular",
|
|
440
|
+
render: ({ targetId, schemaId }) => {
|
|
441
|
+
return createButton({
|
|
442
|
+
attr: BUTTON_IDENTIFIERS.referencedCell,
|
|
443
|
+
icon: referencedCellButton.icon,
|
|
444
|
+
data: {
|
|
445
|
+
"data-target-id": targetId,
|
|
446
|
+
"data-schema-id": schemaId
|
|
447
|
+
},
|
|
448
|
+
testId: "table-ref-cell-button"
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
getData: (el) => ({
|
|
452
|
+
type: "referencedCell",
|
|
453
|
+
targetId: el.getAttribute("data-target-id"),
|
|
454
|
+
schemaId: el.getAttribute("data-schema-id")
|
|
455
|
+
})
|
|
719
456
|
};
|
|
720
|
-
var
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
457
|
+
var rowMenuButton = {
|
|
458
|
+
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
459
|
+
icon: "ph--dots-three--regular",
|
|
460
|
+
render: ({ rowIndex }) => {
|
|
461
|
+
return createButton({
|
|
462
|
+
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
463
|
+
icon: rowMenuButton.icon,
|
|
464
|
+
data: {
|
|
465
|
+
"data-row-index": rowIndex.toString()
|
|
466
|
+
},
|
|
467
|
+
testId: "table-row-menu-button"
|
|
468
|
+
});
|
|
469
|
+
},
|
|
470
|
+
getData: (el) => ({
|
|
471
|
+
type: "rowMenu",
|
|
472
|
+
rowIndex: Number(el.getAttribute("data-row-index"))
|
|
473
|
+
})
|
|
731
474
|
};
|
|
732
|
-
var
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
475
|
+
var sortButton = {
|
|
476
|
+
attr: BUTTON_IDENTIFIERS.sort,
|
|
477
|
+
icon: "ph--sort-ascending--regular",
|
|
478
|
+
render: ({ fieldId, direction }) => {
|
|
479
|
+
return createButton({
|
|
480
|
+
attr: BUTTON_IDENTIFIERS.sort,
|
|
481
|
+
icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
|
|
482
|
+
data: {
|
|
483
|
+
"data-field-id": fieldId,
|
|
484
|
+
"data-direction": direction ?? ""
|
|
485
|
+
},
|
|
486
|
+
testId: "table-sort-button",
|
|
487
|
+
// TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
|
|
488
|
+
// This is a bit hacky.
|
|
489
|
+
type: "secondary"
|
|
490
|
+
});
|
|
491
|
+
},
|
|
492
|
+
getData: (el) => ({
|
|
493
|
+
type: "sort",
|
|
494
|
+
fieldId: el.getAttribute("data-field-id"),
|
|
495
|
+
direction: el.getAttribute("data-direction")
|
|
496
|
+
})
|
|
743
497
|
};
|
|
744
|
-
var
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
498
|
+
var tableButtons = {
|
|
499
|
+
addColumn: addColumnButton,
|
|
500
|
+
columnSettings: columnSettingsButton,
|
|
501
|
+
referencedCell: referencedCellButton,
|
|
502
|
+
rowMenu: rowMenuButton,
|
|
503
|
+
sort: sortButton
|
|
749
504
|
};
|
|
750
505
|
|
|
751
|
-
// packages/ui/react-ui-table/src/
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
import { computed as computed2, effect as effect2, signal as signal3 } from "@preact/signals-core";
|
|
756
|
-
import orderBy from "lodash.orderby";
|
|
757
|
-
import { Resource as Resource2 } from "@dxos/context";
|
|
758
|
-
import { getValue as getValue2, setValue, FormatEnum as FormatEnum3 } from "@dxos/echo-schema";
|
|
759
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
760
|
-
import { PublicKey as PublicKey2 } from "@dxos/react-client";
|
|
761
|
-
import { cellClassesForFieldType, cellClassesForRowSelection, formatForDisplay, formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
762
|
-
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
763
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
764
|
-
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
765
|
-
|
|
766
|
-
// packages/ui/react-ui-table/src/model/modal-controller.ts
|
|
767
|
-
import { signal } from "@preact/signals-core";
|
|
768
|
-
import { log as log2 } from "@dxos/log";
|
|
769
|
-
|
|
770
|
-
// packages/ui/react-ui-table/src/util/signals.ts
|
|
771
|
-
var touch = (value) => value;
|
|
772
|
-
|
|
773
|
-
// packages/ui/react-ui-table/src/util/table.ts
|
|
774
|
-
import { AST, Format, FormatEnum as FormatEnum2, S as S2, TypedObject, TypeEnum } from "@dxos/echo-schema";
|
|
775
|
-
import { log } from "@dxos/log";
|
|
776
|
-
import { PublicKey } from "@dxos/react-client";
|
|
777
|
-
import { create as create2 } from "@dxos/react-client/echo";
|
|
778
|
-
import { createFieldId, createView, ViewProjection } from "@dxos/schema";
|
|
779
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
|
|
780
|
-
var initializeTable = ({ space, table, initialRow = true }) => {
|
|
781
|
-
log.info("initializeTable", {
|
|
782
|
-
table
|
|
783
|
-
}, {
|
|
784
|
-
F: __dxlog_file3,
|
|
785
|
-
L: 32,
|
|
786
|
-
S: void 0,
|
|
787
|
-
C: (f, a) => f(...a)
|
|
788
|
-
});
|
|
789
|
-
const ContactSchema = TypedObject({
|
|
790
|
-
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
791
|
-
version: "0.1.0"
|
|
792
|
-
})({
|
|
793
|
-
name: S2.optional(S2.String).annotations({
|
|
794
|
-
[AST.TitleAnnotationId]: "Name"
|
|
795
|
-
}),
|
|
796
|
-
email: S2.optional(Format.Email),
|
|
797
|
-
salary: S2.optional(Format.Currency()).annotations({
|
|
798
|
-
[AST.TitleAnnotationId]: "Salary"
|
|
799
|
-
})
|
|
800
|
-
});
|
|
801
|
-
const contactSchema = space.db.schemaRegistry.addSchema(ContactSchema);
|
|
802
|
-
table.view = createView({
|
|
803
|
-
name: "Test",
|
|
804
|
-
typename: contactSchema.typename,
|
|
805
|
-
jsonSchema: contactSchema.jsonSchema,
|
|
806
|
-
fields: [
|
|
807
|
-
"name",
|
|
808
|
-
"email",
|
|
809
|
-
"salary"
|
|
810
|
-
]
|
|
811
|
-
});
|
|
812
|
-
const projection = new ViewProjection(contactSchema, table.view);
|
|
813
|
-
projection.setFieldProjection({
|
|
814
|
-
field: {
|
|
815
|
-
id: table.view.fields[2].id,
|
|
816
|
-
path: "salary",
|
|
817
|
-
size: 150
|
|
818
|
-
}
|
|
819
|
-
});
|
|
820
|
-
projection.setFieldProjection({
|
|
821
|
-
field: {
|
|
822
|
-
id: createFieldId(),
|
|
823
|
-
path: "manager",
|
|
824
|
-
referencePath: "name"
|
|
825
|
-
},
|
|
826
|
-
props: {
|
|
827
|
-
property: "manager",
|
|
828
|
-
type: TypeEnum.Ref,
|
|
829
|
-
format: FormatEnum2.Ref,
|
|
830
|
-
referenceSchema: contactSchema.typename,
|
|
831
|
-
title: "Manager"
|
|
832
|
-
}
|
|
833
|
-
});
|
|
834
|
-
if (initialRow) {
|
|
835
|
-
space.db.add(create2(contactSchema, {}));
|
|
836
|
-
}
|
|
837
|
-
return contactSchema;
|
|
506
|
+
// packages/ui/react-ui-table/src/util/table-controls.ts
|
|
507
|
+
var CONTROL_IDENTIFIERS = {
|
|
508
|
+
checkbox: "data-table-checkbox",
|
|
509
|
+
switch: "data-table-switch"
|
|
838
510
|
};
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
referencedCell: "data-table-ref-cell-button",
|
|
843
|
-
columnSettings: "data-table-column-settings-button",
|
|
844
|
-
rowMenu: "data-table-row-menu-button",
|
|
845
|
-
newColumn: "data-table-new-column-button"
|
|
511
|
+
var BASE_CLASSES = {
|
|
512
|
+
checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
|
|
513
|
+
switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
|
|
846
514
|
};
|
|
847
|
-
var
|
|
848
|
-
|
|
849
|
-
columnSettings: "ph--caret-down--regular",
|
|
850
|
-
rowMenu: "ph--dots-three--regular",
|
|
851
|
-
newColumn: "ph--plus--regular"
|
|
515
|
+
var renderAttributes = (data) => {
|
|
516
|
+
return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
852
517
|
};
|
|
853
|
-
var
|
|
854
|
-
|
|
855
|
-
return `<button class="${buttonClasses}" ${TABLE_ATTRS[button]}="${value}" data-testid="${testId}" ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${ICONS[button]}"/></svg></button>`;
|
|
518
|
+
var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
|
|
519
|
+
return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
|
|
856
520
|
};
|
|
857
|
-
var
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
attr:
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
521
|
+
var renderCheckbox = ({ rowIndex, header = false, checked = false, disabled = false }) => {
|
|
522
|
+
const attrs = {
|
|
523
|
+
[CONTROL_IDENTIFIERS.checkbox]: "",
|
|
524
|
+
"data-row-index": rowIndex.toString(),
|
|
525
|
+
...header && {
|
|
526
|
+
"data-header": ""
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
|
|
530
|
+
};
|
|
531
|
+
var renderSwitch = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
|
|
532
|
+
const attrs = {
|
|
533
|
+
[CONTROL_IDENTIFIERS.switch]: "",
|
|
534
|
+
"data-row-index": rowIndex.toString(),
|
|
535
|
+
"data-col-index": colIndex.toString()
|
|
536
|
+
};
|
|
537
|
+
return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
|
|
538
|
+
};
|
|
539
|
+
var tableControls = {
|
|
540
|
+
checkbox: {
|
|
541
|
+
attr: CONTROL_IDENTIFIERS.checkbox,
|
|
542
|
+
render: renderCheckbox,
|
|
543
|
+
getData: (el) => ({
|
|
544
|
+
type: "checkbox",
|
|
545
|
+
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
546
|
+
header: el.hasAttribute("data-header")
|
|
883
547
|
})
|
|
884
548
|
},
|
|
885
|
-
|
|
886
|
-
attr:
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
549
|
+
switch: {
|
|
550
|
+
attr: CONTROL_IDENTIFIERS.switch,
|
|
551
|
+
render: renderSwitch,
|
|
552
|
+
getData: (el) => ({
|
|
553
|
+
type: "switch",
|
|
554
|
+
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
555
|
+
colIndex: Number(el.getAttribute("data-col-index"))
|
|
892
556
|
})
|
|
893
557
|
}
|
|
894
558
|
};
|
|
895
559
|
|
|
896
|
-
// packages/ui/react-ui-table/src/model/
|
|
897
|
-
var
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
this.
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
this.
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
const target = event.target;
|
|
908
|
-
const rowButton = target.closest(`button[${tableButtons.rowMenu.attr}]`);
|
|
909
|
-
if (rowButton) {
|
|
910
|
-
this._triggerRef.current = rowButton;
|
|
911
|
-
this._state.value = {
|
|
912
|
-
type: "row",
|
|
913
|
-
rowIndex: Number(rowButton.getAttribute(tableButtons.rowMenu.attr))
|
|
914
|
-
};
|
|
915
|
-
return true;
|
|
916
|
-
}
|
|
917
|
-
const columnButton = target.closest(`button[${tableButtons.columnSettings.attr}]`);
|
|
918
|
-
if (columnButton) {
|
|
919
|
-
const fieldId = columnButton.getAttribute(tableButtons.columnSettings.attr);
|
|
920
|
-
this._triggerRef.current = columnButton;
|
|
921
|
-
this._state.value = {
|
|
922
|
-
type: "column",
|
|
923
|
-
fieldId
|
|
924
|
-
};
|
|
925
|
-
return true;
|
|
926
|
-
}
|
|
927
|
-
const addColumnButton = target.closest(`button[${tableButtons.addColumn.attr}]`);
|
|
928
|
-
if (addColumnButton) {
|
|
929
|
-
this._triggerRef.current = addColumnButton;
|
|
930
|
-
this._state.value = {
|
|
931
|
-
type: "columnSettings",
|
|
932
|
-
mode: {
|
|
933
|
-
type: "create"
|
|
934
|
-
}
|
|
935
|
-
};
|
|
936
|
-
return true;
|
|
560
|
+
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
561
|
+
var SelectionModel = class extends Resource {
|
|
562
|
+
constructor(_rows, _onSelectionChanged) {
|
|
563
|
+
super();
|
|
564
|
+
this._rows = _rows;
|
|
565
|
+
this._onSelectionChanged = _onSelectionChanged;
|
|
566
|
+
this._selection = signal(/* @__PURE__ */ new Set());
|
|
567
|
+
this._validSelectedIds = computed(() => {
|
|
568
|
+
const rows = this._rows.value;
|
|
569
|
+
if (!rows) {
|
|
570
|
+
return /* @__PURE__ */ new Set();
|
|
937
571
|
}
|
|
938
|
-
const
|
|
939
|
-
|
|
940
|
-
this.
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
return false;
|
|
949
|
-
};
|
|
950
|
-
this.openColumnSettings = () => {
|
|
951
|
-
if (this._state.value.type === "column") {
|
|
952
|
-
const fieldId = this._state.value.fieldId;
|
|
953
|
-
requestAnimationFrame(() => {
|
|
954
|
-
this._state.value = {
|
|
955
|
-
type: "columnSettings",
|
|
956
|
-
mode: {
|
|
957
|
-
type: "edit",
|
|
958
|
-
fieldId
|
|
959
|
-
}
|
|
960
|
-
};
|
|
961
|
-
});
|
|
962
|
-
}
|
|
963
|
-
};
|
|
964
|
-
this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
|
|
965
|
-
if (anchorCell) {
|
|
966
|
-
this._triggerRef.current = anchorCell;
|
|
967
|
-
this._state.value = {
|
|
968
|
-
type: "createRefPanel",
|
|
969
|
-
typename,
|
|
970
|
-
initialValues,
|
|
971
|
-
onCreate
|
|
972
|
-
};
|
|
973
|
-
} else {
|
|
974
|
-
log2.warn("anchor cell not found while creating new ref", void 0, {
|
|
975
|
-
F: __dxlog_file4,
|
|
976
|
-
L: 119,
|
|
977
|
-
S: this,
|
|
978
|
-
C: (f, a) => f(...a)
|
|
979
|
-
});
|
|
980
|
-
}
|
|
981
|
-
};
|
|
982
|
-
this.close = () => {
|
|
983
|
-
this._state.value = {
|
|
984
|
-
type: "closed"
|
|
985
|
-
};
|
|
986
|
-
};
|
|
987
|
-
}
|
|
988
|
-
get state() {
|
|
989
|
-
return this._state;
|
|
990
|
-
}
|
|
991
|
-
get trigger() {
|
|
992
|
-
return this._triggerRef;
|
|
993
|
-
}
|
|
994
|
-
};
|
|
995
|
-
|
|
996
|
-
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
997
|
-
import { computed, effect, signal as signal2 } from "@preact/signals-core";
|
|
998
|
-
import { Resource } from "@dxos/context";
|
|
999
|
-
var SelectionModel = class extends Resource {
|
|
1000
|
-
constructor(_rows, _onSelectionChanged) {
|
|
1001
|
-
super();
|
|
1002
|
-
this._rows = _rows;
|
|
1003
|
-
this._onSelectionChanged = _onSelectionChanged;
|
|
1004
|
-
this._selection = signal2(/* @__PURE__ */ new Set());
|
|
1005
|
-
this._validSelectedIds = computed(() => {
|
|
1006
|
-
const rows = this._rows.value;
|
|
1007
|
-
if (!rows) {
|
|
1008
|
-
return /* @__PURE__ */ new Set();
|
|
1009
|
-
}
|
|
1010
|
-
const validIds = new Set(rows.map((row) => row.id));
|
|
1011
|
-
return new Set([
|
|
1012
|
-
...this._selection.value
|
|
1013
|
-
].filter((id) => validIds.has(id)));
|
|
1014
|
-
});
|
|
1015
|
-
this._hasSelection = computed(() => this._validSelectedIds.value.size > 0);
|
|
1016
|
-
this._allSelected = computed(() => {
|
|
1017
|
-
const rows = this._rows.value;
|
|
1018
|
-
if (rows.length === 0) {
|
|
1019
|
-
return false;
|
|
572
|
+
const validIds = new Set(rows.map((row) => row.id));
|
|
573
|
+
return new Set([
|
|
574
|
+
...this._selection.value
|
|
575
|
+
].filter((id) => validIds.has(id)));
|
|
576
|
+
});
|
|
577
|
+
this._hasSelection = computed(() => this._validSelectedIds.value.size > 0);
|
|
578
|
+
this._allSelected = computed(() => {
|
|
579
|
+
const rows = this._rows.value;
|
|
580
|
+
if (rows.length === 0) {
|
|
581
|
+
return false;
|
|
1020
582
|
}
|
|
1021
583
|
return rows.every((row) => this._selection.value.has(row.id));
|
|
1022
584
|
});
|
|
@@ -1042,7 +604,16 @@ var SelectionModel = class extends Resource {
|
|
|
1042
604
|
this._selection.value = newSelection;
|
|
1043
605
|
};
|
|
1044
606
|
this.setSelection = (mode) => {
|
|
1045
|
-
|
|
607
|
+
switch (mode) {
|
|
608
|
+
case "all": {
|
|
609
|
+
this._selection.value = new Set(this._rows.value.map((row) => row.id));
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
case "none": {
|
|
613
|
+
this._selection.value = /* @__PURE__ */ new Set();
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
1046
617
|
};
|
|
1047
618
|
}
|
|
1048
619
|
async _open() {
|
|
@@ -1066,25 +637,173 @@ var SelectionModel = class extends Resource {
|
|
|
1066
637
|
}
|
|
1067
638
|
};
|
|
1068
639
|
|
|
1069
|
-
// packages/ui/react-ui-table/src/
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
};
|
|
1074
|
-
var
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
640
|
+
// packages/ui/react-ui-table/src/model/table-sorting.ts
|
|
641
|
+
import { computed as computed2, signal as signal2 } from "@preact/signals-core";
|
|
642
|
+
import orderBy from "lodash.orderby";
|
|
643
|
+
import { getValue, FormatEnum as FormatEnum2, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
644
|
+
import { formatForDisplay } from "@dxos/react-ui-form";
|
|
645
|
+
var TableSorting = class {
|
|
646
|
+
constructor(rows, _view, _projection) {
|
|
647
|
+
this._view = _view;
|
|
648
|
+
this._projection = _projection;
|
|
649
|
+
this._displayToDataIndex = /* @__PURE__ */ new Map();
|
|
650
|
+
this._localSort = signal2(void 0);
|
|
651
|
+
this._rows = rows;
|
|
652
|
+
this._isDirty = computed2(() => {
|
|
653
|
+
const local = this._localSort.value;
|
|
654
|
+
const viewSort = this._view?.query.sort?.[0];
|
|
655
|
+
if (local?.type === "cleared") {
|
|
656
|
+
return viewSort !== void 0;
|
|
657
|
+
}
|
|
658
|
+
if (local?.type === "active") {
|
|
659
|
+
if (!viewSort) {
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
663
|
+
}
|
|
664
|
+
return false;
|
|
665
|
+
});
|
|
666
|
+
this.sortedRows = this.initialiseSortedRows();
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* @reactive
|
|
670
|
+
* @returns Local sort if present, falls back to view sort.
|
|
671
|
+
*/
|
|
672
|
+
get sorting() {
|
|
673
|
+
const local = this._localSort.value;
|
|
674
|
+
if (local?.type === "cleared") {
|
|
675
|
+
return void 0;
|
|
676
|
+
}
|
|
677
|
+
if (local?.type === "active") {
|
|
678
|
+
return local.sort;
|
|
679
|
+
}
|
|
680
|
+
return this._view?.query.sort?.[0];
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* @reactive
|
|
684
|
+
* @returns Whether local sort differs from view sort.
|
|
685
|
+
*/
|
|
686
|
+
get isDirty() {
|
|
687
|
+
return this._isDirty.value;
|
|
688
|
+
}
|
|
689
|
+
getDataIndex(displayIndex) {
|
|
690
|
+
return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
|
|
691
|
+
}
|
|
692
|
+
setSort(fieldId, direction) {
|
|
693
|
+
this._localSort.value = {
|
|
694
|
+
type: "active",
|
|
695
|
+
sort: {
|
|
696
|
+
fieldId,
|
|
697
|
+
direction
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
toggleSort(fieldId) {
|
|
702
|
+
if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
switch (this.sorting.direction) {
|
|
706
|
+
case "asc": {
|
|
707
|
+
this.setSort(fieldId, "desc");
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
case "desc": {
|
|
711
|
+
this.setSort(fieldId, "asc");
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
clearSort() {
|
|
717
|
+
this._localSort.value = {
|
|
718
|
+
type: "cleared"
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
save() {
|
|
722
|
+
if (this._view && this._localSort.value !== void 0) {
|
|
723
|
+
if (this._localSort.value.type === "active") {
|
|
724
|
+
this._view.query.sort = [
|
|
725
|
+
this._localSort.value.sort
|
|
726
|
+
];
|
|
727
|
+
} else {
|
|
728
|
+
this._view.query.sort = [];
|
|
729
|
+
}
|
|
730
|
+
this._localSort.value = void 0;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
//
|
|
734
|
+
// Initialisation.
|
|
735
|
+
//
|
|
736
|
+
initialiseSortedRows() {
|
|
737
|
+
return computed2(() => {
|
|
738
|
+
this._displayToDataIndex.clear();
|
|
739
|
+
const sort = this.sorting;
|
|
740
|
+
if (!sort || !this._view) {
|
|
741
|
+
return this._rows.value;
|
|
742
|
+
}
|
|
743
|
+
const field = this._view.fields.find((f) => f.id === sort.fieldId);
|
|
744
|
+
if (!field) {
|
|
745
|
+
return this._rows.value;
|
|
746
|
+
}
|
|
747
|
+
const { props } = this._projection.getFieldProjection(field.id);
|
|
748
|
+
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
749
|
+
const sortValue = this.getSortValue(props, field, item);
|
|
750
|
+
const isEmpty = !(props.type === TypeEnum2.Boolean) && (sortValue == null || sortValue === "");
|
|
751
|
+
return {
|
|
752
|
+
item,
|
|
753
|
+
index,
|
|
754
|
+
value: sortValue,
|
|
755
|
+
isEmpty
|
|
756
|
+
};
|
|
757
|
+
});
|
|
758
|
+
const ordered = orderBy(dataWithIndices, [
|
|
759
|
+
"isEmpty",
|
|
760
|
+
"value"
|
|
761
|
+
], [
|
|
762
|
+
"asc",
|
|
763
|
+
sort.direction
|
|
764
|
+
]);
|
|
765
|
+
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
766
|
+
if (displayIndex !== dataIndex) {
|
|
767
|
+
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
return ordered.map(({ item }) => item);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
getSortValue(props, field, item) {
|
|
774
|
+
const { type, format } = props;
|
|
775
|
+
const value = getValue(item, field.path);
|
|
776
|
+
if (type === TypeEnum2.Boolean) {
|
|
777
|
+
return !!value;
|
|
778
|
+
}
|
|
779
|
+
if (type === TypeEnum2.Number) {
|
|
780
|
+
return value;
|
|
781
|
+
}
|
|
782
|
+
if (value == null) {
|
|
783
|
+
return value;
|
|
784
|
+
}
|
|
785
|
+
if (format === FormatEnum2.SingleSelect) {
|
|
786
|
+
const options = props.options;
|
|
787
|
+
if (!options) {
|
|
788
|
+
return void 0;
|
|
789
|
+
}
|
|
790
|
+
const option = options.find((option2) => option2.id === value);
|
|
791
|
+
return option ? options.indexOf(option) : void 0;
|
|
792
|
+
}
|
|
793
|
+
if (format === FormatEnum2.Ref && field.referencePath) {
|
|
794
|
+
const refValue = getValue(value.target, field.referencePath);
|
|
795
|
+
return refValue;
|
|
796
|
+
}
|
|
797
|
+
return formatForDisplay({
|
|
798
|
+
type,
|
|
799
|
+
format,
|
|
800
|
+
value
|
|
801
|
+
});
|
|
1083
802
|
}
|
|
1084
803
|
};
|
|
1085
804
|
|
|
1086
805
|
// packages/ui/react-ui-table/src/model/table-model.ts
|
|
1087
|
-
var
|
|
806
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
1088
807
|
var TableModel = class extends Resource2 {
|
|
1089
808
|
constructor({ table, projection, sorting = [], pinnedRows = {
|
|
1090
809
|
top: [],
|
|
@@ -1102,200 +821,7 @@ var TableModel = class extends Resource2 {
|
|
|
1102
821
|
col: 0
|
|
1103
822
|
}
|
|
1104
823
|
});
|
|
1105
|
-
/**
|
|
1106
|
-
* Maps display indices to data indices.
|
|
1107
|
-
* Used for translating between sorted/displayed order and original data order.
|
|
1108
|
-
* Keys are display indices, values are corresponding data indices.
|
|
1109
|
-
*/
|
|
1110
|
-
this._displayToDataIndex = /* @__PURE__ */ new Map();
|
|
1111
|
-
this._sorting = signal3(void 0);
|
|
1112
824
|
this._rows = signal3([]);
|
|
1113
|
-
this._modalController = new ModalController();
|
|
1114
|
-
//
|
|
1115
|
-
// Get Cells
|
|
1116
|
-
//
|
|
1117
|
-
this.getCells = (range, plane) => {
|
|
1118
|
-
switch (plane) {
|
|
1119
|
-
case "grid": {
|
|
1120
|
-
this._visibleRange.value = range;
|
|
1121
|
-
return this.getMainGridCells(range);
|
|
1122
|
-
}
|
|
1123
|
-
case "frozenRowsStart": {
|
|
1124
|
-
return this.getHeaderCells(range);
|
|
1125
|
-
}
|
|
1126
|
-
case "frozenColsStart": {
|
|
1127
|
-
return this.getSelectionColumnCells(range);
|
|
1128
|
-
}
|
|
1129
|
-
case "frozenColsEnd": {
|
|
1130
|
-
return this.getActionColumnCells(range);
|
|
1131
|
-
}
|
|
1132
|
-
case "fixedStartStart": {
|
|
1133
|
-
return this.getSelectAllCell();
|
|
1134
|
-
}
|
|
1135
|
-
case "fixedStartEnd": {
|
|
1136
|
-
return this.getNewColumnCell();
|
|
1137
|
-
}
|
|
1138
|
-
default: {
|
|
1139
|
-
return {};
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
};
|
|
1143
|
-
this.getMainGridCells = (range) => {
|
|
1144
|
-
const cells = {};
|
|
1145
|
-
const fields = this._table.view?.fields ?? [];
|
|
1146
|
-
const addCell = (obj, field, colIndex, displayIndex) => {
|
|
1147
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1148
|
-
const cell = {
|
|
1149
|
-
get value() {
|
|
1150
|
-
const value = getValue2(obj, field.path);
|
|
1151
|
-
if (value == null) {
|
|
1152
|
-
return "";
|
|
1153
|
-
}
|
|
1154
|
-
switch (props.format) {
|
|
1155
|
-
case FormatEnum3.Ref: {
|
|
1156
|
-
if (!field.referencePath) {
|
|
1157
|
-
return "";
|
|
1158
|
-
}
|
|
1159
|
-
return getValue2(value, field.referencePath);
|
|
1160
|
-
}
|
|
1161
|
-
default: {
|
|
1162
|
-
return formatForDisplay({
|
|
1163
|
-
type: props.type,
|
|
1164
|
-
format: props.format,
|
|
1165
|
-
value
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
};
|
|
1171
|
-
const classes = [];
|
|
1172
|
-
const formatClasses = cellClassesForFieldType({
|
|
1173
|
-
type: props.type,
|
|
1174
|
-
format: props.format
|
|
1175
|
-
});
|
|
1176
|
-
if (formatClasses) {
|
|
1177
|
-
classes.push(formatClasses);
|
|
1178
|
-
}
|
|
1179
|
-
const rowSelectionClasses = cellClassesForRowSelection(this._selection.isObjectSelected(obj));
|
|
1180
|
-
if (rowSelectionClasses) {
|
|
1181
|
-
classes.push(rowSelectionClasses);
|
|
1182
|
-
}
|
|
1183
|
-
if (classes.length > 0) {
|
|
1184
|
-
cell.className = mx2(classes.flat());
|
|
1185
|
-
}
|
|
1186
|
-
if (cell.value && props.format === FormatEnum3.Ref && props.referenceSchema) {
|
|
1187
|
-
const targetObj = getValue2(obj, field.path);
|
|
1188
|
-
cell.accessoryHtml = tableButtons.referencedCell.render({
|
|
1189
|
-
targetId: targetObj.id,
|
|
1190
|
-
schemaId: props.referenceSchema
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
const idx = toPlaneCellIndex({
|
|
1194
|
-
col: colIndex,
|
|
1195
|
-
row: displayIndex
|
|
1196
|
-
});
|
|
1197
|
-
cells[idx] = cell;
|
|
1198
|
-
};
|
|
1199
|
-
for (let row = range.start.row; row <= range.end.row && row < this._sortedRows.value.length; row++) {
|
|
1200
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1201
|
-
const field = fields[col];
|
|
1202
|
-
if (!field) {
|
|
1203
|
-
continue;
|
|
1204
|
-
}
|
|
1205
|
-
addCell(this._sortedRows.value[row], field, col, row);
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
return cells;
|
|
1209
|
-
};
|
|
1210
|
-
this.getHeaderCells = (range) => {
|
|
1211
|
-
const cells = {};
|
|
1212
|
-
const fields = this.table.view?.fields ?? [];
|
|
1213
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1214
|
-
const { field, props } = this._projection.getFieldProjection(fields[col].id);
|
|
1215
|
-
cells[toPlaneCellIndex({
|
|
1216
|
-
col,
|
|
1217
|
-
row: 0
|
|
1218
|
-
})] = {
|
|
1219
|
-
// TODO(burdon): Use same logic as form for fallback title.
|
|
1220
|
-
value: props.title ?? field.path,
|
|
1221
|
-
readonly: true,
|
|
1222
|
-
resizeHandle: "col",
|
|
1223
|
-
accessoryHtml: tableButtons.columnSettings.render({
|
|
1224
|
-
fieldId: field.id
|
|
1225
|
-
})
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
return cells;
|
|
1229
|
-
};
|
|
1230
|
-
this.getSelectionColumnCells = (range) => {
|
|
1231
|
-
const cells = {};
|
|
1232
|
-
for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
|
|
1233
|
-
const isSelected = this._selection.isRowIndexSelected(row);
|
|
1234
|
-
const classes = cellClassesForRowSelection(isSelected);
|
|
1235
|
-
cells[toPlaneCellIndex({
|
|
1236
|
-
col: 0,
|
|
1237
|
-
row
|
|
1238
|
-
})] = {
|
|
1239
|
-
value: "",
|
|
1240
|
-
readonly: true,
|
|
1241
|
-
className: classes ? mx2(classes) : void 0,
|
|
1242
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1243
|
-
rowIndex: row,
|
|
1244
|
-
checked: isSelected
|
|
1245
|
-
})
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
return cells;
|
|
1249
|
-
};
|
|
1250
|
-
this.getActionColumnCells = (range) => {
|
|
1251
|
-
const cells = {};
|
|
1252
|
-
for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
|
|
1253
|
-
const isSelected = this._selection.isRowIndexSelected(row);
|
|
1254
|
-
const classes = cellClassesForRowSelection(isSelected);
|
|
1255
|
-
cells[toPlaneCellIndex({
|
|
1256
|
-
col: 0,
|
|
1257
|
-
row
|
|
1258
|
-
})] = {
|
|
1259
|
-
value: "",
|
|
1260
|
-
readonly: true,
|
|
1261
|
-
className: classes ? mx2(classes) : void 0,
|
|
1262
|
-
accessoryHtml: tableButtons.rowMenu.render({
|
|
1263
|
-
rowIndex: row
|
|
1264
|
-
})
|
|
1265
|
-
};
|
|
1266
|
-
}
|
|
1267
|
-
return cells;
|
|
1268
|
-
};
|
|
1269
|
-
this.getSelectAllCell = () => {
|
|
1270
|
-
return {
|
|
1271
|
-
[toPlaneCellIndex({
|
|
1272
|
-
col: 0,
|
|
1273
|
-
row: 0
|
|
1274
|
-
})]: {
|
|
1275
|
-
value: "",
|
|
1276
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1277
|
-
rowIndex: 0,
|
|
1278
|
-
header: true,
|
|
1279
|
-
checked: this._selection.allRowsSeleted.value
|
|
1280
|
-
}),
|
|
1281
|
-
readonly: true
|
|
1282
|
-
}
|
|
1283
|
-
};
|
|
1284
|
-
};
|
|
1285
|
-
this.getNewColumnCell = () => {
|
|
1286
|
-
return {
|
|
1287
|
-
[toPlaneCellIndex({
|
|
1288
|
-
col: 0,
|
|
1289
|
-
row: 0
|
|
1290
|
-
})]: {
|
|
1291
|
-
value: "",
|
|
1292
|
-
accessoryHtml: tableButtons.addColumn.render({
|
|
1293
|
-
disabled: (this._table.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1294
|
-
}),
|
|
1295
|
-
readonly: true
|
|
1296
|
-
}
|
|
1297
|
-
};
|
|
1298
|
-
};
|
|
1299
825
|
//
|
|
1300
826
|
// Data
|
|
1301
827
|
//
|
|
@@ -1303,13 +829,13 @@ var TableModel = class extends Resource2 {
|
|
|
1303
829
|
this._rows.value = obj;
|
|
1304
830
|
};
|
|
1305
831
|
this.getRowCount = () => this._rows.value.length;
|
|
1306
|
-
this.getColumnCount = () => this.table.view?.fields.length ?? 0;
|
|
832
|
+
this.getColumnCount = () => this.table.view?.target?.fields.length ?? 0;
|
|
1307
833
|
this.insertRow = (rowIndex) => {
|
|
1308
|
-
const row = rowIndex !== void 0 ? this.
|
|
834
|
+
const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
|
|
1309
835
|
this._onInsertRow?.(row);
|
|
1310
836
|
};
|
|
1311
837
|
this.deleteRow = (rowIndex) => {
|
|
1312
|
-
const row = this.
|
|
838
|
+
const row = this._sorting.getDataIndex(rowIndex);
|
|
1313
839
|
const obj = this._rows.value[row];
|
|
1314
840
|
const objectsToDelete = [];
|
|
1315
841
|
if (this._selection.hasSelection.value) {
|
|
@@ -1321,12 +847,12 @@ var TableModel = class extends Resource2 {
|
|
|
1321
847
|
this._onDeleteRows?.(row, objectsToDelete);
|
|
1322
848
|
};
|
|
1323
849
|
this.getCellData = ({ col, row }) => {
|
|
1324
|
-
const fields = this.table.view?.fields ?? [];
|
|
850
|
+
const fields = this.table.view?.target?.fields ?? [];
|
|
1325
851
|
if (col < 0 || col >= fields.length) {
|
|
1326
852
|
return void 0;
|
|
1327
853
|
}
|
|
1328
854
|
const field = fields[col];
|
|
1329
|
-
const dataIndex = this.
|
|
855
|
+
const dataIndex = this._sorting.getDataIndex(row);
|
|
1330
856
|
const value = getValue2(this._rows.value[dataIndex], field.path);
|
|
1331
857
|
if (value == null) {
|
|
1332
858
|
return "";
|
|
@@ -1337,7 +863,7 @@ var TableModel = class extends Resource2 {
|
|
|
1337
863
|
if (!field.referencePath) {
|
|
1338
864
|
return "";
|
|
1339
865
|
}
|
|
1340
|
-
return getValue2(value, field.referencePath);
|
|
866
|
+
return getValue2(value.target, field.referencePath);
|
|
1341
867
|
}
|
|
1342
868
|
default: {
|
|
1343
869
|
return formatForEditing({
|
|
@@ -1349,8 +875,8 @@ var TableModel = class extends Resource2 {
|
|
|
1349
875
|
}
|
|
1350
876
|
};
|
|
1351
877
|
this.setCellData = ({ col, row }, value) => {
|
|
1352
|
-
const rowIdx = this.
|
|
1353
|
-
const fields = this.table.view?.fields ?? [];
|
|
878
|
+
const rowIdx = this._sorting.getDataIndex(row);
|
|
879
|
+
const fields = this.table.view?.target?.fields ?? [];
|
|
1354
880
|
if (col < 0 || col >= fields.length) {
|
|
1355
881
|
return;
|
|
1356
882
|
}
|
|
@@ -1358,7 +884,9 @@ var TableModel = class extends Resource2 {
|
|
|
1358
884
|
const { props } = this._projection.getFieldProjection(field.id);
|
|
1359
885
|
switch (props.format) {
|
|
1360
886
|
case FormatEnum3.Ref: {
|
|
1361
|
-
|
|
887
|
+
if (isReactiveObject(value)) {
|
|
888
|
+
setValue(this._rows.value[rowIdx], field.path, makeRef2(value));
|
|
889
|
+
}
|
|
1362
890
|
break;
|
|
1363
891
|
}
|
|
1364
892
|
default: {
|
|
@@ -1371,31 +899,13 @@ var TableModel = class extends Resource2 {
|
|
|
1371
899
|
}
|
|
1372
900
|
}
|
|
1373
901
|
};
|
|
1374
|
-
//
|
|
1375
|
-
// Interactions
|
|
1376
|
-
//
|
|
1377
|
-
this.handleGridClick = (event) => {
|
|
1378
|
-
if (!this._modalController.handleClick(event)) {
|
|
1379
|
-
const target = event.target;
|
|
1380
|
-
const selectionCheckbox = target.closest(`input[${tableControls.checkbox.attributes.checkbox}]`);
|
|
1381
|
-
if (selectionCheckbox) {
|
|
1382
|
-
const isHeader = selectionCheckbox.hasAttribute(tableControls.checkbox.attributes.header);
|
|
1383
|
-
if (isHeader) {
|
|
1384
|
-
if (this._selection.allRowsSeleted.value) {
|
|
1385
|
-
this._selection.setSelection("none");
|
|
1386
|
-
} else {
|
|
1387
|
-
this._selection.setSelection("all");
|
|
1388
|
-
}
|
|
1389
|
-
} else {
|
|
1390
|
-
const rowIndex = Number(selectionCheckbox.getAttribute(tableControls.checkbox.attributes.checkbox));
|
|
1391
|
-
this._selection.toggleSelectionForRowIndex(rowIndex);
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
};
|
|
1396
902
|
this._table = table;
|
|
1397
903
|
this._projection = projection;
|
|
1398
|
-
this._sorting
|
|
904
|
+
this._sorting = new TableSorting(this._rows, table.view?.target, projection);
|
|
905
|
+
if (sorting.length > 0) {
|
|
906
|
+
const [sort] = sorting;
|
|
907
|
+
this._sorting.setSort(sort.fieldId, sort.direction);
|
|
908
|
+
}
|
|
1399
909
|
this._pinnedRows = pinnedRows;
|
|
1400
910
|
this._onInsertRow = onInsertRow;
|
|
1401
911
|
this._onDeleteRows = onDeleteRows;
|
|
@@ -1409,13 +919,22 @@ var TableModel = class extends Resource2 {
|
|
|
1409
919
|
get projection() {
|
|
1410
920
|
return this._projection;
|
|
1411
921
|
}
|
|
922
|
+
get rows() {
|
|
923
|
+
return this._sorting.sortedRows;
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* @reactive
|
|
927
|
+
*/
|
|
928
|
+
get sorting() {
|
|
929
|
+
return this._sorting;
|
|
930
|
+
}
|
|
1412
931
|
get pinnedRows() {
|
|
1413
932
|
return this._pinnedRows;
|
|
1414
933
|
}
|
|
1415
934
|
get columnMeta() {
|
|
1416
|
-
|
|
1417
|
-
F:
|
|
1418
|
-
L:
|
|
935
|
+
invariant(this._columnMeta, void 0, {
|
|
936
|
+
F: __dxlog_file,
|
|
937
|
+
L: 117,
|
|
1419
938
|
S: this,
|
|
1420
939
|
A: [
|
|
1421
940
|
"this._columnMeta",
|
|
@@ -1424,28 +943,25 @@ var TableModel = class extends Resource2 {
|
|
|
1424
943
|
});
|
|
1425
944
|
return this._columnMeta;
|
|
1426
945
|
}
|
|
1427
|
-
get sorting() {
|
|
1428
|
-
return this._sorting.value;
|
|
1429
|
-
}
|
|
1430
|
-
get modalController() {
|
|
1431
|
-
return this._modalController;
|
|
1432
|
-
}
|
|
1433
946
|
get selection() {
|
|
1434
947
|
return this._selection;
|
|
1435
948
|
}
|
|
949
|
+
/** @reactive */
|
|
950
|
+
get isViewDirty() {
|
|
951
|
+
return this._sorting.isDirty;
|
|
952
|
+
}
|
|
1436
953
|
//
|
|
1437
954
|
// Initialisation
|
|
1438
955
|
//
|
|
1439
956
|
async _open() {
|
|
1440
957
|
this.initializeColumnMeta();
|
|
1441
|
-
this.initializeSorting();
|
|
1442
958
|
this.initializeEffects();
|
|
1443
|
-
this._selection = new SelectionModel(this.
|
|
959
|
+
this._selection = new SelectionModel(this._sorting.sortedRows, () => this._onRowOrderChanged?.());
|
|
1444
960
|
await this._selection.open(this._ctx);
|
|
1445
961
|
}
|
|
1446
962
|
initializeColumnMeta() {
|
|
1447
|
-
this._columnMeta =
|
|
1448
|
-
const fields = this._table.view?.fields ?? [];
|
|
963
|
+
this._columnMeta = computed3(() => {
|
|
964
|
+
const fields = this._table.view?.target?.fields ?? [];
|
|
1449
965
|
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
1450
966
|
index,
|
|
1451
967
|
{
|
|
@@ -1470,45 +986,9 @@ var TableModel = class extends Resource2 {
|
|
|
1470
986
|
};
|
|
1471
987
|
});
|
|
1472
988
|
}
|
|
1473
|
-
initializeSorting() {
|
|
1474
|
-
this._sortedRows = computed2(() => {
|
|
1475
|
-
this._displayToDataIndex.clear();
|
|
1476
|
-
const sort = this._sorting.value;
|
|
1477
|
-
if (!sort) {
|
|
1478
|
-
return this._rows.value;
|
|
1479
|
-
}
|
|
1480
|
-
const field = this._table.view?.fields.find((field2) => field2.id === sort.fieldId);
|
|
1481
|
-
if (!field) {
|
|
1482
|
-
return this._rows.value;
|
|
1483
|
-
}
|
|
1484
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
1485
|
-
const value = getValue2(item, field.path);
|
|
1486
|
-
return {
|
|
1487
|
-
item,
|
|
1488
|
-
index,
|
|
1489
|
-
value,
|
|
1490
|
-
isEmpty: value == null || value === ""
|
|
1491
|
-
};
|
|
1492
|
-
});
|
|
1493
|
-
const sorted = orderBy(dataWithIndices, [
|
|
1494
|
-
"isEmpty",
|
|
1495
|
-
"value"
|
|
1496
|
-
], [
|
|
1497
|
-
"asc",
|
|
1498
|
-
sort.direction
|
|
1499
|
-
]);
|
|
1500
|
-
for (let displayIndex = 0; displayIndex < sorted.length; displayIndex++) {
|
|
1501
|
-
const { index: dataIndex } = sorted[displayIndex];
|
|
1502
|
-
if (displayIndex !== dataIndex) {
|
|
1503
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
return sorted.map(({ item }) => item);
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
989
|
initializeEffects() {
|
|
1510
990
|
const rowOrderWatcher = effect2(() => {
|
|
1511
|
-
touch(this.
|
|
991
|
+
touch(this._sorting.sortedRows.value);
|
|
1512
992
|
this._onRowOrderChanged?.();
|
|
1513
993
|
});
|
|
1514
994
|
this._ctx.onDispose(rowOrderWatcher);
|
|
@@ -1517,8 +997,8 @@ var TableModel = class extends Resource2 {
|
|
|
1517
997
|
const rowEffects = [];
|
|
1518
998
|
for (let row = start.row; row <= end.row; row++) {
|
|
1519
999
|
rowEffects.push(effect2(() => {
|
|
1520
|
-
const obj = this.
|
|
1521
|
-
this?._table?.view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
|
|
1000
|
+
const obj = this._sorting.sortedRows.value[row];
|
|
1001
|
+
this?._table?.view?.target?.fields.forEach((field) => touch(getValue2(obj, field.path)));
|
|
1522
1002
|
this._onCellUpdate?.({
|
|
1523
1003
|
row,
|
|
1524
1004
|
col: start.col,
|
|
@@ -1530,6 +1010,19 @@ var TableModel = class extends Resource2 {
|
|
|
1530
1010
|
});
|
|
1531
1011
|
this._ctx.onDispose(rowEffectManager);
|
|
1532
1012
|
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Updates a cell's value using a transform function.
|
|
1015
|
+
* @param {DxGridPlanePosition} position - The position of the cell to update.
|
|
1016
|
+
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1017
|
+
*/
|
|
1018
|
+
updateCellData({ col, row }, update) {
|
|
1019
|
+
const dataRow = this._sorting.getDataIndex(row);
|
|
1020
|
+
const fields = this.table.view?.target?.fields ?? [];
|
|
1021
|
+
const field = fields[col];
|
|
1022
|
+
const value = getValue2(this._rows.value[dataRow], field.path);
|
|
1023
|
+
const updatedValue = update(value);
|
|
1024
|
+
setValue(this._rows.value[dataRow], field.path, updatedValue);
|
|
1025
|
+
}
|
|
1533
1026
|
//
|
|
1534
1027
|
// Column Operations
|
|
1535
1028
|
//
|
|
@@ -1537,11 +1030,8 @@ var TableModel = class extends Resource2 {
|
|
|
1537
1030
|
if (!this.table.view) {
|
|
1538
1031
|
return;
|
|
1539
1032
|
}
|
|
1540
|
-
const field = this.table.view.fields.find((field2) => field2.id === fieldId);
|
|
1033
|
+
const field = this.table.view.target?.fields.find((field2) => field2.id === fieldId);
|
|
1541
1034
|
if (field && this._onDeleteColumn) {
|
|
1542
|
-
if (this._sorting.value?.fieldId === fieldId) {
|
|
1543
|
-
this.clearSort();
|
|
1544
|
-
}
|
|
1545
1035
|
this._onDeleteColumn(field.id);
|
|
1546
1036
|
}
|
|
1547
1037
|
}
|
|
@@ -1549,7 +1039,7 @@ var TableModel = class extends Resource2 {
|
|
|
1549
1039
|
// Resize
|
|
1550
1040
|
//
|
|
1551
1041
|
setColumnWidth(columnIndex, width) {
|
|
1552
|
-
const fields = this.table.view?.fields ?? [];
|
|
1042
|
+
const fields = this.table.view?.target?.fields ?? [];
|
|
1553
1043
|
if (columnIndex < fields.length) {
|
|
1554
1044
|
const newWidth = Math.max(0, width);
|
|
1555
1045
|
const field = fields[columnIndex];
|
|
@@ -1559,18 +1049,6 @@ var TableModel = class extends Resource2 {
|
|
|
1559
1049
|
}
|
|
1560
1050
|
}
|
|
1561
1051
|
//
|
|
1562
|
-
// Sorting
|
|
1563
|
-
//
|
|
1564
|
-
setSort(fieldId, direction) {
|
|
1565
|
-
this._sorting.value = {
|
|
1566
|
-
fieldId,
|
|
1567
|
-
direction
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
clearSort() {
|
|
1571
|
-
this._sorting.value = void 0;
|
|
1572
|
-
}
|
|
1573
|
-
//
|
|
1574
1052
|
// Pinning
|
|
1575
1053
|
//
|
|
1576
1054
|
// TODO(burdon): Change to setPinned(on/off).
|
|
@@ -1581,9 +1059,881 @@ var TableModel = class extends Resource2 {
|
|
|
1581
1059
|
this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
|
|
1582
1060
|
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1583
1061
|
}
|
|
1062
|
+
//
|
|
1063
|
+
// View operations
|
|
1064
|
+
//
|
|
1065
|
+
saveView() {
|
|
1066
|
+
this._sorting.save();
|
|
1067
|
+
}
|
|
1584
1068
|
};
|
|
1585
1069
|
|
|
1586
|
-
// packages/ui/react-ui-table/src/
|
|
1070
|
+
// packages/ui/react-ui-table/src/model/modal-controller.ts
|
|
1071
|
+
import { signal as signal4 } from "@preact/signals-core";
|
|
1072
|
+
import { log } from "@dxos/log";
|
|
1073
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
|
|
1074
|
+
var ModalController = class {
|
|
1075
|
+
constructor() {
|
|
1076
|
+
this._state = signal4({
|
|
1077
|
+
type: "closed"
|
|
1078
|
+
});
|
|
1079
|
+
this._triggerRef = {
|
|
1080
|
+
current: null
|
|
1081
|
+
};
|
|
1082
|
+
this.setTrigger = (trigger) => {
|
|
1083
|
+
this._triggerRef.current = trigger;
|
|
1084
|
+
};
|
|
1085
|
+
this.showRowMenu = (rowIndex) => {
|
|
1086
|
+
this._state.value = {
|
|
1087
|
+
type: "row",
|
|
1088
|
+
rowIndex
|
|
1089
|
+
};
|
|
1090
|
+
};
|
|
1091
|
+
this.showColumnMenu = (fieldId) => {
|
|
1092
|
+
this._state.value = {
|
|
1093
|
+
type: "column",
|
|
1094
|
+
fieldId
|
|
1095
|
+
};
|
|
1096
|
+
};
|
|
1097
|
+
this.showColumnCreator = () => {
|
|
1098
|
+
this._state.value = {
|
|
1099
|
+
type: "columnSettings",
|
|
1100
|
+
mode: {
|
|
1101
|
+
type: "create"
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
};
|
|
1105
|
+
this.showReferencePanel = (targetId, schemaId) => {
|
|
1106
|
+
this._state.value = {
|
|
1107
|
+
type: "refPanel",
|
|
1108
|
+
targetId,
|
|
1109
|
+
typename: schemaId
|
|
1110
|
+
};
|
|
1111
|
+
};
|
|
1112
|
+
this.openColumnSettings = () => {
|
|
1113
|
+
if (this._state.value.type === "column") {
|
|
1114
|
+
const fieldId = this._state.value.fieldId;
|
|
1115
|
+
requestAnimationFrame(() => {
|
|
1116
|
+
this._state.value = {
|
|
1117
|
+
type: "columnSettings",
|
|
1118
|
+
mode: {
|
|
1119
|
+
type: "edit",
|
|
1120
|
+
fieldId
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
|
|
1127
|
+
if (anchorCell) {
|
|
1128
|
+
this._triggerRef.current = anchorCell;
|
|
1129
|
+
this._state.value = {
|
|
1130
|
+
type: "createRefPanel",
|
|
1131
|
+
typename,
|
|
1132
|
+
initialValues,
|
|
1133
|
+
onCreate
|
|
1134
|
+
};
|
|
1135
|
+
} else {
|
|
1136
|
+
log.warn("anchor cell not found while creating new ref", void 0, {
|
|
1137
|
+
F: __dxlog_file2,
|
|
1138
|
+
L: 86,
|
|
1139
|
+
S: this,
|
|
1140
|
+
C: (f, a) => f(...a)
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
this.close = () => {
|
|
1145
|
+
this._state.value = {
|
|
1146
|
+
type: "closed"
|
|
1147
|
+
};
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
get state() {
|
|
1151
|
+
return this._state;
|
|
1152
|
+
}
|
|
1153
|
+
get trigger() {
|
|
1154
|
+
return this._triggerRef;
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
// packages/ui/react-ui-table/src/model/table-presentation.ts
|
|
1159
|
+
import { signal as signal5 } from "@preact/signals-core";
|
|
1160
|
+
import { FormatEnum as FormatEnum4, getValue as getValue3 } from "@dxos/echo-schema";
|
|
1161
|
+
import { cellClassesForFieldType, cellClassesForRowSelection, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
|
|
1162
|
+
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
1163
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
1164
|
+
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1165
|
+
var TablePresentation = class {
|
|
1166
|
+
constructor(model, _visibleRange = signal5({
|
|
1167
|
+
start: {
|
|
1168
|
+
row: 0,
|
|
1169
|
+
col: 0
|
|
1170
|
+
},
|
|
1171
|
+
end: {
|
|
1172
|
+
row: 0,
|
|
1173
|
+
col: 0
|
|
1174
|
+
}
|
|
1175
|
+
})) {
|
|
1176
|
+
this.model = model;
|
|
1177
|
+
this._visibleRange = _visibleRange;
|
|
1178
|
+
}
|
|
1179
|
+
getCells(range, plane) {
|
|
1180
|
+
switch (plane) {
|
|
1181
|
+
case "grid":
|
|
1182
|
+
this._visibleRange.value = range;
|
|
1183
|
+
return this.getMainGridCells(range);
|
|
1184
|
+
case "frozenRowsStart":
|
|
1185
|
+
return this.getHeaderCells(range);
|
|
1186
|
+
case "frozenColsStart":
|
|
1187
|
+
return this.getSelectionColumnCells(range);
|
|
1188
|
+
case "frozenColsEnd":
|
|
1189
|
+
return this.getActionColumnCells(range);
|
|
1190
|
+
case "fixedStartStart":
|
|
1191
|
+
return this.getSelectAllCell();
|
|
1192
|
+
case "fixedStartEnd":
|
|
1193
|
+
return this.getNewColumnCell();
|
|
1194
|
+
default:
|
|
1195
|
+
return {};
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
getMainGridCells(range) {
|
|
1199
|
+
const cells = {};
|
|
1200
|
+
const fields = this.model.table.view?.target?.fields ?? [];
|
|
1201
|
+
const addCell = (obj, field, colIndex, displayIndex) => {
|
|
1202
|
+
const { props } = this.model.projection.getFieldProjection(field.id);
|
|
1203
|
+
const cell = {
|
|
1204
|
+
get value() {
|
|
1205
|
+
const value = getValue3(obj, field.path);
|
|
1206
|
+
if (value == null) {
|
|
1207
|
+
return "";
|
|
1208
|
+
}
|
|
1209
|
+
switch (props.format) {
|
|
1210
|
+
case FormatEnum4.Boolean:
|
|
1211
|
+
case FormatEnum4.SingleSelect: {
|
|
1212
|
+
return "";
|
|
1213
|
+
}
|
|
1214
|
+
case FormatEnum4.Ref: {
|
|
1215
|
+
if (!field.referencePath) {
|
|
1216
|
+
return "";
|
|
1217
|
+
}
|
|
1218
|
+
return getValue3(value.target, field.referencePath);
|
|
1219
|
+
}
|
|
1220
|
+
default: {
|
|
1221
|
+
return formatForDisplay2({
|
|
1222
|
+
type: props.type,
|
|
1223
|
+
format: props.format,
|
|
1224
|
+
value
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
const classes = [];
|
|
1231
|
+
const formatClasses = cellClassesForFieldType({
|
|
1232
|
+
type: props.type,
|
|
1233
|
+
format: props.format
|
|
1234
|
+
});
|
|
1235
|
+
if (formatClasses) {
|
|
1236
|
+
classes.push(formatClasses);
|
|
1237
|
+
}
|
|
1238
|
+
const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj));
|
|
1239
|
+
if (rowSelectionClasses) {
|
|
1240
|
+
classes.push(rowSelectionClasses);
|
|
1241
|
+
}
|
|
1242
|
+
if (classes.length > 0) {
|
|
1243
|
+
cell.className = mx(classes.flat());
|
|
1244
|
+
}
|
|
1245
|
+
if (props.format === FormatEnum4.Ref && props.referenceSchema) {
|
|
1246
|
+
const targetObj = getValue3(obj, field.path)?.target;
|
|
1247
|
+
if (targetObj) {
|
|
1248
|
+
cell.accessoryHtml = tableButtons.referencedCell.render({
|
|
1249
|
+
targetId: targetObj.id,
|
|
1250
|
+
schemaId: props.referenceSchema
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
if (props.format === FormatEnum4.Boolean) {
|
|
1255
|
+
const value = getValue3(obj, field.path);
|
|
1256
|
+
cell.accessoryHtml = tableControls.switch.render({
|
|
1257
|
+
colIndex,
|
|
1258
|
+
rowIndex: displayIndex,
|
|
1259
|
+
checked: value ?? false
|
|
1260
|
+
});
|
|
1261
|
+
cell.readonly = true;
|
|
1262
|
+
}
|
|
1263
|
+
if (props.format === FormatEnum4.SingleSelect) {
|
|
1264
|
+
const value = getValue3(obj, field.path);
|
|
1265
|
+
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1266
|
+
if (options) {
|
|
1267
|
+
const option = options.find((o) => o.id === value);
|
|
1268
|
+
if (option) {
|
|
1269
|
+
cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
const idx = toPlaneCellIndex({
|
|
1274
|
+
col: colIndex,
|
|
1275
|
+
row: displayIndex
|
|
1276
|
+
});
|
|
1277
|
+
cells[idx] = cell;
|
|
1278
|
+
};
|
|
1279
|
+
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1280
|
+
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1281
|
+
const field = fields[col];
|
|
1282
|
+
if (!field) {
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
addCell(this.model.rows.value[row], field, col, row);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
return cells;
|
|
1289
|
+
}
|
|
1290
|
+
getHeaderCells(range) {
|
|
1291
|
+
const cells = {};
|
|
1292
|
+
const fields = this.model.table.view?.target?.fields ?? [];
|
|
1293
|
+
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1294
|
+
const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
|
|
1295
|
+
const sorting = this.model.sorting?.sorting;
|
|
1296
|
+
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1297
|
+
cells[toPlaneCellIndex({
|
|
1298
|
+
col,
|
|
1299
|
+
row: 0
|
|
1300
|
+
})] = {
|
|
1301
|
+
// TODO(burdon): Use same logic as form for fallback title.
|
|
1302
|
+
value: props.title ?? field.path,
|
|
1303
|
+
readonly: true,
|
|
1304
|
+
resizeHandle: "col",
|
|
1305
|
+
accessoryHtml: `
|
|
1306
|
+
${direction !== void 0 ? tableButtons.sort.render({
|
|
1307
|
+
fieldId: field.id,
|
|
1308
|
+
direction
|
|
1309
|
+
}) : ""}
|
|
1310
|
+
${tableButtons.columnSettings.render({
|
|
1311
|
+
fieldId: field.id
|
|
1312
|
+
})}
|
|
1313
|
+
`,
|
|
1314
|
+
className: "!bg-gridHeader"
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
return cells;
|
|
1318
|
+
}
|
|
1319
|
+
getSelectionColumnCells(range) {
|
|
1320
|
+
const cells = {};
|
|
1321
|
+
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1322
|
+
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1323
|
+
const classes = cellClassesForRowSelection(isSelected);
|
|
1324
|
+
cells[toPlaneCellIndex({
|
|
1325
|
+
col: 0,
|
|
1326
|
+
row
|
|
1327
|
+
})] = {
|
|
1328
|
+
value: "",
|
|
1329
|
+
readonly: true,
|
|
1330
|
+
className: classes ? mx(classes) : void 0,
|
|
1331
|
+
accessoryHtml: tableControls.checkbox.render({
|
|
1332
|
+
rowIndex: row,
|
|
1333
|
+
checked: isSelected
|
|
1334
|
+
})
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
return cells;
|
|
1338
|
+
}
|
|
1339
|
+
getActionColumnCells(range) {
|
|
1340
|
+
const cells = {};
|
|
1341
|
+
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1342
|
+
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1343
|
+
const classes = cellClassesForRowSelection(isSelected);
|
|
1344
|
+
cells[toPlaneCellIndex({
|
|
1345
|
+
col: 0,
|
|
1346
|
+
row
|
|
1347
|
+
})] = {
|
|
1348
|
+
value: "",
|
|
1349
|
+
readonly: true,
|
|
1350
|
+
className: classes ? mx(classes) : void 0,
|
|
1351
|
+
accessoryHtml: tableButtons.rowMenu.render({
|
|
1352
|
+
rowIndex: row
|
|
1353
|
+
})
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
return cells;
|
|
1357
|
+
}
|
|
1358
|
+
getSelectAllCell() {
|
|
1359
|
+
return {
|
|
1360
|
+
[toPlaneCellIndex({
|
|
1361
|
+
col: 0,
|
|
1362
|
+
row: 0
|
|
1363
|
+
})]: {
|
|
1364
|
+
accessoryHtml: tableControls.checkbox.render({
|
|
1365
|
+
rowIndex: 0,
|
|
1366
|
+
header: true,
|
|
1367
|
+
checked: this.model.selection.allRowsSeleted.value
|
|
1368
|
+
}),
|
|
1369
|
+
className: "!bg-gridHeader",
|
|
1370
|
+
readonly: true,
|
|
1371
|
+
value: ""
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
getNewColumnCell() {
|
|
1376
|
+
return {
|
|
1377
|
+
[toPlaneCellIndex({
|
|
1378
|
+
col: 0,
|
|
1379
|
+
row: 0
|
|
1380
|
+
})]: {
|
|
1381
|
+
accessoryHtml: tableButtons.addColumn.render({
|
|
1382
|
+
disabled: (this.model.table.view?.target?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1383
|
+
}),
|
|
1384
|
+
className: "!bg-gridHeader",
|
|
1385
|
+
readonly: true,
|
|
1386
|
+
value: ""
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
|
|
1392
|
+
// packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
|
|
1393
|
+
import React6, { useCallback as useCallback3, useMemo as useMemo3, useRef } from "react";
|
|
1394
|
+
import { FormatEnum as FormatEnum5 } from "@dxos/echo-schema";
|
|
1395
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1396
|
+
import { cellQuery, editorKeys, parseCellIndex, useGridContext as useGridContext2, GridCellEditor } from "@dxos/react-ui-grid";
|
|
1397
|
+
|
|
1398
|
+
// packages/ui/react-ui-table/src/components/TableCellEditor/extension.ts
|
|
1399
|
+
import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
|
|
1400
|
+
import { EditorView } from "@codemirror/view";
|
|
1401
|
+
var completion = ({ debug, onQuery, onMatch }) => {
|
|
1402
|
+
return [
|
|
1403
|
+
EditorView.theme({
|
|
1404
|
+
".cm-completionDialog": {
|
|
1405
|
+
width: "var(--dx-gridCellWidth)"
|
|
1406
|
+
}
|
|
1407
|
+
}),
|
|
1408
|
+
autocompletion({
|
|
1409
|
+
icons: false,
|
|
1410
|
+
activateOnTyping: true,
|
|
1411
|
+
closeOnBlur: !debug,
|
|
1412
|
+
override: [
|
|
1413
|
+
async (context) => {
|
|
1414
|
+
const text = context.state.doc.toString();
|
|
1415
|
+
return {
|
|
1416
|
+
from: 0,
|
|
1417
|
+
options: await onQuery(text)
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
],
|
|
1421
|
+
// TODO(burdon): Consts from grid (to line-up with grid).
|
|
1422
|
+
tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
|
|
1423
|
+
optionClass: () => "flex h-[33px] items-center"
|
|
1424
|
+
}),
|
|
1425
|
+
// Check for accepted completion metadata in the transaction.
|
|
1426
|
+
EditorView.updateListener.of((update) => {
|
|
1427
|
+
update.transactions.forEach((tr) => {
|
|
1428
|
+
const completion2 = tr.annotation(pickedCompletion);
|
|
1429
|
+
if (completion2) {
|
|
1430
|
+
onMatch(completion2.data);
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
})
|
|
1434
|
+
];
|
|
1435
|
+
};
|
|
1436
|
+
|
|
1437
|
+
// packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
|
|
1438
|
+
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
1439
|
+
var newValue = Symbol.for("newValue");
|
|
1440
|
+
var createOption = (text) => ({
|
|
1441
|
+
[newValue]: true,
|
|
1442
|
+
text
|
|
1443
|
+
});
|
|
1444
|
+
var isCreateOption = (data) => typeof data === "object" && data[newValue];
|
|
1445
|
+
var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
|
|
1446
|
+
const { id: gridId, editing, setEditing } = useGridContext2("TableCellEditor", __gridScope);
|
|
1447
|
+
const suppressNextBlur = useRef(false);
|
|
1448
|
+
const fieldProjection = useMemo3(() => {
|
|
1449
|
+
if (!model || !editing) {
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
const { col } = parseCellIndex(editing.index);
|
|
1453
|
+
const field = model.projection.view.fields[col];
|
|
1454
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1455
|
+
invariant2(fieldProjection2, void 0, {
|
|
1456
|
+
F: __dxlog_file3,
|
|
1457
|
+
L: 67,
|
|
1458
|
+
S: void 0,
|
|
1459
|
+
A: [
|
|
1460
|
+
"fieldProjection",
|
|
1461
|
+
""
|
|
1462
|
+
]
|
|
1463
|
+
});
|
|
1464
|
+
return fieldProjection2;
|
|
1465
|
+
}, [
|
|
1466
|
+
model,
|
|
1467
|
+
editing
|
|
1468
|
+
]);
|
|
1469
|
+
const handleEnter = useCallback3((value) => {
|
|
1470
|
+
if (!model || !editing) {
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
const cell = parseCellIndex(editing.index);
|
|
1474
|
+
model.setCellData(cell, value);
|
|
1475
|
+
onEnter?.(cell);
|
|
1476
|
+
onFocus?.();
|
|
1477
|
+
setEditing(null);
|
|
1478
|
+
}, [
|
|
1479
|
+
model,
|
|
1480
|
+
editing
|
|
1481
|
+
]);
|
|
1482
|
+
const handleBlur = useCallback3((value) => {
|
|
1483
|
+
if (!model || !editing) {
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
if (suppressNextBlur.current) {
|
|
1487
|
+
suppressNextBlur.current = false;
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
const cell = parseCellIndex(editing.index);
|
|
1491
|
+
if (value !== void 0) {
|
|
1492
|
+
model.setCellData(cell, value);
|
|
1493
|
+
}
|
|
1494
|
+
}, [
|
|
1495
|
+
model,
|
|
1496
|
+
editing
|
|
1497
|
+
]);
|
|
1498
|
+
const handleClose = useCallback3((value, event) => {
|
|
1499
|
+
if (!model || !editing || !fieldProjection) {
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
const cell = parseCellIndex(editing.index);
|
|
1503
|
+
onEnter?.(cell);
|
|
1504
|
+
if (event && onFocus) {
|
|
1505
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
1506
|
+
}
|
|
1507
|
+
}, [
|
|
1508
|
+
model,
|
|
1509
|
+
editing,
|
|
1510
|
+
onFocus,
|
|
1511
|
+
onEnter,
|
|
1512
|
+
fieldProjection,
|
|
1513
|
+
determineNavigationAxis,
|
|
1514
|
+
determineNavigationDelta
|
|
1515
|
+
]);
|
|
1516
|
+
const extension = useMemo3(() => {
|
|
1517
|
+
if (!fieldProjection) {
|
|
1518
|
+
return [];
|
|
1519
|
+
}
|
|
1520
|
+
const extension2 = [
|
|
1521
|
+
editorKeys({
|
|
1522
|
+
onClose: handleClose,
|
|
1523
|
+
...editing?.initialContent && {
|
|
1524
|
+
onNav: handleClose
|
|
1525
|
+
}
|
|
1526
|
+
})
|
|
1527
|
+
];
|
|
1528
|
+
if (onQuery) {
|
|
1529
|
+
switch (fieldProjection.props.format) {
|
|
1530
|
+
case FormatEnum5.Ref: {
|
|
1531
|
+
extension2.push([
|
|
1532
|
+
completion({
|
|
1533
|
+
onQuery: (text) => onQuery(fieldProjection, text),
|
|
1534
|
+
onMatch: (data) => {
|
|
1535
|
+
if (model && editing && modals) {
|
|
1536
|
+
if (isCreateOption(data)) {
|
|
1537
|
+
const { field, props } = fieldProjection;
|
|
1538
|
+
if (props.referenceSchema) {
|
|
1539
|
+
suppressNextBlur.current = true;
|
|
1540
|
+
modals.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
|
|
1541
|
+
[field.referencePath]: data.text
|
|
1542
|
+
}, (data2) => {
|
|
1543
|
+
handleEnter(data2);
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
} else {
|
|
1547
|
+
handleEnter(data);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
})
|
|
1552
|
+
]);
|
|
1553
|
+
break;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
return extension2;
|
|
1558
|
+
}, [
|
|
1559
|
+
model,
|
|
1560
|
+
modals,
|
|
1561
|
+
editing,
|
|
1562
|
+
fieldProjection,
|
|
1563
|
+
handleClose
|
|
1564
|
+
]);
|
|
1565
|
+
const getCellContent = useCallback3(() => {
|
|
1566
|
+
if (model && editing) {
|
|
1567
|
+
const value = model.getCellData(parseCellIndex(editing.index));
|
|
1568
|
+
return value !== void 0 ? String(value) : "";
|
|
1569
|
+
}
|
|
1570
|
+
}, [
|
|
1571
|
+
model,
|
|
1572
|
+
editing
|
|
1573
|
+
]);
|
|
1574
|
+
return /* @__PURE__ */ React6.createElement(GridCellEditor, {
|
|
1575
|
+
extension,
|
|
1576
|
+
getCellContent,
|
|
1577
|
+
onBlur: handleBlur
|
|
1578
|
+
});
|
|
1579
|
+
};
|
|
1580
|
+
var determineNavigationAxis = ({ key }) => {
|
|
1581
|
+
switch (key) {
|
|
1582
|
+
case "ArrowUp":
|
|
1583
|
+
case "ArrowDown":
|
|
1584
|
+
case "Enter": {
|
|
1585
|
+
return "row";
|
|
1586
|
+
}
|
|
1587
|
+
case "ArrowLeft":
|
|
1588
|
+
case "ArrowRight":
|
|
1589
|
+
case "Tab":
|
|
1590
|
+
return "col";
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
var determineNavigationDelta = ({ key, shift }) => {
|
|
1594
|
+
switch (key) {
|
|
1595
|
+
case "ArrowUp":
|
|
1596
|
+
case "ArrowLeft":
|
|
1597
|
+
return -1;
|
|
1598
|
+
case "ArrowDown":
|
|
1599
|
+
case "ArrowRight":
|
|
1600
|
+
return 1;
|
|
1601
|
+
}
|
|
1602
|
+
return shift ? -1 : 1;
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1605
|
+
// packages/ui/react-ui-table/src/components/Table/Table.tsx
|
|
1606
|
+
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
|
|
1607
|
+
var inlineEndLine = "[&>.dx-grid]:relative [&>.dx-grid]:after:absolute [&>.dx-grid]:after:inset-block-0 [&>.dx-grid]:after:-inline-end-px [&>.dx-grid]:after:is-px [&>.dx-grid]:after:bg-separator";
|
|
1608
|
+
var blockEndLine = "[&>.dx-grid]:before:absolute [&>.dx-grid]:before:inset-inline-0 [&>.dx-grid]:before:-block-end-px [&>.dx-grid]:before:bs-px [&>.dx-grid]:before:bg-separator";
|
|
1609
|
+
var frozen = {
|
|
1610
|
+
frozenRowsStart: 1,
|
|
1611
|
+
frozenColsStart: 1,
|
|
1612
|
+
frozenColsEnd: 1
|
|
1613
|
+
};
|
|
1614
|
+
var TableRoot = ({ children, role }) => {
|
|
1615
|
+
return /* @__PURE__ */ React7.createElement("div", {
|
|
1616
|
+
role: "none",
|
|
1617
|
+
className: mx2("relative border-bs !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
|
|
1618
|
+
}, children);
|
|
1619
|
+
};
|
|
1620
|
+
var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention }, forwardedRef) => {
|
|
1621
|
+
const [dxGrid, setDxGrid] = useState2(null);
|
|
1622
|
+
const { hasAttention } = useAttention(model?.table ? fullyQualifiedId(model.table) : "table");
|
|
1623
|
+
const { t } = useTranslation3(translationKey);
|
|
1624
|
+
const modals = useMemo4(() => new ModalController(), []);
|
|
1625
|
+
useImperativeHandle(forwardedRef, () => {
|
|
1626
|
+
if (!presentation || !dxGrid) {
|
|
1627
|
+
return {};
|
|
1628
|
+
}
|
|
1629
|
+
dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
|
|
1630
|
+
return {
|
|
1631
|
+
update: (cell) => {
|
|
1632
|
+
if (cell) {
|
|
1633
|
+
dxGrid.updateIfWithinBounds(cell);
|
|
1634
|
+
} else {
|
|
1635
|
+
dxGrid.updateCells(true);
|
|
1636
|
+
dxGrid.requestUpdate();
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
};
|
|
1640
|
+
}, [
|
|
1641
|
+
presentation,
|
|
1642
|
+
dxGrid
|
|
1643
|
+
]);
|
|
1644
|
+
const handleGridClick = useCallback4((event) => {
|
|
1645
|
+
if (!modals) {
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
|
|
1649
|
+
const tableButtonElement = event.target.closest(buttonSelector);
|
|
1650
|
+
if (tableButtonElement) {
|
|
1651
|
+
const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
|
|
1652
|
+
if (!button) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
modals.setTrigger(tableButtonElement);
|
|
1656
|
+
const data = button.getData(tableButtonElement);
|
|
1657
|
+
switch (data.type) {
|
|
1658
|
+
case "rowMenu": {
|
|
1659
|
+
modals.showRowMenu(data.rowIndex);
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
case "columnSettings": {
|
|
1663
|
+
modals.showColumnMenu(data.fieldId);
|
|
1664
|
+
break;
|
|
1665
|
+
}
|
|
1666
|
+
case "newColumn": {
|
|
1667
|
+
modals.showColumnCreator();
|
|
1668
|
+
break;
|
|
1669
|
+
}
|
|
1670
|
+
case "referencedCell": {
|
|
1671
|
+
modals.showReferencePanel(data.targetId, data.schemaId);
|
|
1672
|
+
break;
|
|
1673
|
+
}
|
|
1674
|
+
case "sort": {
|
|
1675
|
+
model?.sorting?.toggleSort(data.fieldId);
|
|
1676
|
+
break;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1681
|
+
const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
|
|
1682
|
+
const controlElement = event.target.closest(controlSelector);
|
|
1683
|
+
if (controlElement) {
|
|
1684
|
+
const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
|
|
1685
|
+
if (!control) {
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
const data = control.getData(controlElement);
|
|
1689
|
+
switch (data.type) {
|
|
1690
|
+
case "checkbox": {
|
|
1691
|
+
if (data.header) {
|
|
1692
|
+
model?.selection.setSelection(model.selection.allRowsSeleted.value ? "none" : "all");
|
|
1693
|
+
} else {
|
|
1694
|
+
model?.selection.toggleSelectionForRowIndex(data.rowIndex);
|
|
1695
|
+
}
|
|
1696
|
+
break;
|
|
1697
|
+
}
|
|
1698
|
+
case "switch": {
|
|
1699
|
+
if (model) {
|
|
1700
|
+
model.updateCellData({
|
|
1701
|
+
row: data.rowIndex,
|
|
1702
|
+
col: data.colIndex
|
|
1703
|
+
}, (value) => !value);
|
|
1704
|
+
}
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}, [
|
|
1710
|
+
model,
|
|
1711
|
+
modals
|
|
1712
|
+
]);
|
|
1713
|
+
const handleFocus = useCallback4((increment, delta) => {
|
|
1714
|
+
if (dxGrid) {
|
|
1715
|
+
dxGrid.refocus(increment, delta);
|
|
1716
|
+
}
|
|
1717
|
+
}, [
|
|
1718
|
+
dxGrid
|
|
1719
|
+
]);
|
|
1720
|
+
const handleEnter = useCallback4((cell) => {
|
|
1721
|
+
if (model && cell.row === model.getRowCount() - 1) {
|
|
1722
|
+
model.insertRow(cell.row);
|
|
1723
|
+
if (dxGrid) {
|
|
1724
|
+
requestAnimationFrame(() => {
|
|
1725
|
+
dxGrid?.scrollToRow(cell.row + 1);
|
|
1726
|
+
dxGrid?.refocus("row", 1);
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}, [
|
|
1731
|
+
model,
|
|
1732
|
+
dxGrid
|
|
1733
|
+
]);
|
|
1734
|
+
const handleKeyDown = useCallback4((event) => {
|
|
1735
|
+
const cell = closestCell(event.target);
|
|
1736
|
+
if (!model || !cell) {
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
switch (event.key) {
|
|
1740
|
+
case "Backspace":
|
|
1741
|
+
case "Delete": {
|
|
1742
|
+
model.setCellData(cell, void 0);
|
|
1743
|
+
break;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
}, [
|
|
1747
|
+
model
|
|
1748
|
+
]);
|
|
1749
|
+
const handleAxisResize = useCallback4((event) => {
|
|
1750
|
+
if (event.axis === "col") {
|
|
1751
|
+
const columnIndex = parseInt(event.index, 10);
|
|
1752
|
+
model?.setColumnWidth(columnIndex, event.size);
|
|
1753
|
+
}
|
|
1754
|
+
}, [
|
|
1755
|
+
model
|
|
1756
|
+
]);
|
|
1757
|
+
const handleWheel = useCallback4((event) => {
|
|
1758
|
+
if (!ignoreAttention && !hasAttention) {
|
|
1759
|
+
event.stopPropagation();
|
|
1760
|
+
}
|
|
1761
|
+
}, [
|
|
1762
|
+
hasAttention,
|
|
1763
|
+
ignoreAttention
|
|
1764
|
+
]);
|
|
1765
|
+
const handleNewColumn = useCallback4(() => {
|
|
1766
|
+
const columns = model?.getColumnCount();
|
|
1767
|
+
if (dxGrid && columns) {
|
|
1768
|
+
dxGrid.scrollToColumn(columns - 1);
|
|
1769
|
+
}
|
|
1770
|
+
}, [
|
|
1771
|
+
model,
|
|
1772
|
+
dxGrid
|
|
1773
|
+
]);
|
|
1774
|
+
const handleQuery = useCallback4(async ({ field, props }, text) => {
|
|
1775
|
+
if (model && props.referenceSchema && field.referencePath) {
|
|
1776
|
+
const space = getSpace4(model.table);
|
|
1777
|
+
invariant3(space, void 0, {
|
|
1778
|
+
F: __dxlog_file4,
|
|
1779
|
+
L: 264,
|
|
1780
|
+
S: void 0,
|
|
1781
|
+
A: [
|
|
1782
|
+
"space",
|
|
1783
|
+
""
|
|
1784
|
+
]
|
|
1785
|
+
});
|
|
1786
|
+
const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
|
|
1787
|
+
if (schema) {
|
|
1788
|
+
const { objects } = await space.db.query(Filter.schema(schema)).run();
|
|
1789
|
+
const options = objects.map((obj) => {
|
|
1790
|
+
const value = getValue4(obj, field.referencePath);
|
|
1791
|
+
if (!value || typeof value !== "string") {
|
|
1792
|
+
return void 0;
|
|
1793
|
+
}
|
|
1794
|
+
return {
|
|
1795
|
+
label: value,
|
|
1796
|
+
data: obj
|
|
1797
|
+
};
|
|
1798
|
+
}).filter(isNotFalsy);
|
|
1799
|
+
return [
|
|
1800
|
+
...options,
|
|
1801
|
+
{
|
|
1802
|
+
label: t("create new object label", {
|
|
1803
|
+
text
|
|
1804
|
+
}),
|
|
1805
|
+
data: createOption(text)
|
|
1806
|
+
}
|
|
1807
|
+
];
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
return [];
|
|
1811
|
+
}, [
|
|
1812
|
+
model
|
|
1813
|
+
]);
|
|
1814
|
+
if (!model || !modals) {
|
|
1815
|
+
return /* @__PURE__ */ React7.createElement("span", {
|
|
1816
|
+
role: "none",
|
|
1817
|
+
className: "attention-surface"
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
return /* @__PURE__ */ React7.createElement(Grid.Root, {
|
|
1821
|
+
id: model.table.id ?? "table-grid"
|
|
1822
|
+
}, /* @__PURE__ */ React7.createElement(TableCellEditor, {
|
|
1823
|
+
model,
|
|
1824
|
+
modals,
|
|
1825
|
+
onEnter: handleEnter,
|
|
1826
|
+
onFocus: handleFocus,
|
|
1827
|
+
onQuery: handleQuery
|
|
1828
|
+
}), /* @__PURE__ */ React7.createElement(Grid.Content, {
|
|
1829
|
+
onWheelCapture: handleWheel,
|
|
1830
|
+
className: mx2("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
|
|
1831
|
+
frozen,
|
|
1832
|
+
columns: model.columnMeta.value,
|
|
1833
|
+
limitRows: model.getRowCount() ?? 0,
|
|
1834
|
+
limitColumns: model.table.view?.target?.fields?.length ?? 0,
|
|
1835
|
+
onAxisResize: handleAxisResize,
|
|
1836
|
+
onClick: handleGridClick,
|
|
1837
|
+
onKeyDown: handleKeyDown,
|
|
1838
|
+
overscroll: "trap",
|
|
1839
|
+
ref: setDxGrid
|
|
1840
|
+
}), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
|
|
1841
|
+
model,
|
|
1842
|
+
modals
|
|
1843
|
+
}), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
|
|
1844
|
+
model,
|
|
1845
|
+
modals
|
|
1846
|
+
}), /* @__PURE__ */ React7.createElement(ColumnSettings, {
|
|
1847
|
+
model,
|
|
1848
|
+
modals,
|
|
1849
|
+
onNewColumn: handleNewColumn
|
|
1850
|
+
}), /* @__PURE__ */ React7.createElement(RefPanel, {
|
|
1851
|
+
model,
|
|
1852
|
+
modals
|
|
1853
|
+
}), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
|
|
1854
|
+
model,
|
|
1855
|
+
modals
|
|
1856
|
+
}));
|
|
1857
|
+
});
|
|
1858
|
+
var Table = {
|
|
1859
|
+
Root: TableRoot,
|
|
1860
|
+
Main: TableMain
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
// packages/ui/react-ui-table/src/components/TableToolbar/TableToolbar.tsx
|
|
1864
|
+
import React8, { useCallback as useCallback5, useMemo as useMemo5 } from "react";
|
|
1865
|
+
import { create as create3 } from "@dxos/live-object";
|
|
1866
|
+
import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
|
|
1867
|
+
var createTableToolbarActions = (state) => {
|
|
1868
|
+
const add = createMenuAction("add-row", {
|
|
1869
|
+
type: "add-row",
|
|
1870
|
+
icon: "ph--plus--regular",
|
|
1871
|
+
label: [
|
|
1872
|
+
"add row",
|
|
1873
|
+
{
|
|
1874
|
+
ns: translationKey
|
|
1875
|
+
}
|
|
1876
|
+
],
|
|
1877
|
+
testId: "table.toolbar.add-row"
|
|
1878
|
+
});
|
|
1879
|
+
const save = createMenuAction("save-view", {
|
|
1880
|
+
type: "save-view",
|
|
1881
|
+
icon: "ph--floppy-disk--regular",
|
|
1882
|
+
label: [
|
|
1883
|
+
"save view label",
|
|
1884
|
+
{
|
|
1885
|
+
ns: translationKey
|
|
1886
|
+
}
|
|
1887
|
+
],
|
|
1888
|
+
testId: "table.toolbar.save-view",
|
|
1889
|
+
iconOnly: false,
|
|
1890
|
+
hidden: !state.viewDirty
|
|
1891
|
+
});
|
|
1892
|
+
const gap = createGapSeparator();
|
|
1893
|
+
const comment = createMenuAction("comment", {
|
|
1894
|
+
type: "comment",
|
|
1895
|
+
icon: "ph--chat-text--regular",
|
|
1896
|
+
label: [
|
|
1897
|
+
"create comment",
|
|
1898
|
+
{
|
|
1899
|
+
ns: translationKey
|
|
1900
|
+
}
|
|
1901
|
+
],
|
|
1902
|
+
testId: "table.toolbar.comment"
|
|
1903
|
+
});
|
|
1904
|
+
const nodes = [
|
|
1905
|
+
add,
|
|
1906
|
+
save,
|
|
1907
|
+
...gap.nodes,
|
|
1908
|
+
comment
|
|
1909
|
+
];
|
|
1910
|
+
return {
|
|
1911
|
+
nodes,
|
|
1912
|
+
edges: nodes.map(({ id: target }) => ({
|
|
1913
|
+
source: "root",
|
|
1914
|
+
target
|
|
1915
|
+
}))
|
|
1916
|
+
};
|
|
1917
|
+
};
|
|
1918
|
+
var TableToolbar = ({ classNames, viewDirty, attendableId, onAction }) => {
|
|
1919
|
+
const state = useMemo5(() => create3({
|
|
1920
|
+
viewDirty
|
|
1921
|
+
}), []);
|
|
1922
|
+
const actionsCreator = useCallback5(() => createTableToolbarActions(state), [
|
|
1923
|
+
state
|
|
1924
|
+
]);
|
|
1925
|
+
const menu = useMenuActions(actionsCreator);
|
|
1926
|
+
return /* @__PURE__ */ React8.createElement(MenuProvider, {
|
|
1927
|
+
...menu,
|
|
1928
|
+
attendableId,
|
|
1929
|
+
onAction
|
|
1930
|
+
}, /* @__PURE__ */ React8.createElement(ToolbarMenu, {
|
|
1931
|
+
classNames
|
|
1932
|
+
}));
|
|
1933
|
+
};
|
|
1934
|
+
|
|
1935
|
+
// packages/ui/react-ui-table/src/hooks/useTableModel.ts
|
|
1936
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
1587
1937
|
var useTableModel = ({ objects, table, projection, ...props }) => {
|
|
1588
1938
|
const [model, setModel] = useState3();
|
|
1589
1939
|
useEffect2(() => {
|
|
@@ -1619,15 +1969,22 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
|
|
|
1619
1969
|
return model;
|
|
1620
1970
|
};
|
|
1621
1971
|
export {
|
|
1972
|
+
BUTTON_IDENTIFIERS,
|
|
1973
|
+
CONTROL_IDENTIFIERS,
|
|
1974
|
+
ModalController,
|
|
1622
1975
|
Table,
|
|
1976
|
+
TableModel,
|
|
1977
|
+
TablePresentation,
|
|
1623
1978
|
TableSchema,
|
|
1979
|
+
TableToolbar,
|
|
1624
1980
|
TableType,
|
|
1625
|
-
Toolbar,
|
|
1626
1981
|
initializeTable,
|
|
1982
|
+
renderCheckbox,
|
|
1983
|
+
renderSwitch,
|
|
1627
1984
|
tableButtons,
|
|
1985
|
+
tableControls,
|
|
1628
1986
|
touch,
|
|
1629
1987
|
translations_default as translations,
|
|
1630
|
-
useTableModel
|
|
1631
|
-
useToolbarContext
|
|
1988
|
+
useTableModel
|
|
1632
1989
|
};
|
|
1633
1990
|
//# sourceMappingURL=index.mjs.map
|