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