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