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