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