@dxos/react-ui-table 0.8.4-main.5acf9ea → 0.8.4-main.5ea62a8
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-63UUF4IG.mjs +66 -0
- package/dist/lib/browser/chunk-63UUF4IG.mjs.map +7 -0
- package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-RQYXNWWN.mjs} +531 -460
- package/dist/lib/browser/chunk-RQYXNWWN.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +685 -623
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +6 -4
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/types/index.mjs +3 -3
- package/dist/lib/node-esm/chunk-K734DJB7.mjs +67 -0
- package/dist/lib/node-esm/chunk-K734DJB7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-QNDUGIS7.mjs} +531 -460
- package/dist/lib/node-esm/chunk-QNDUGIS7.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +685 -623
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +6 -4
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/types/index.mjs +3 -3
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -1
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +1 -1
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +50 -2
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +44 -0
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +3 -2
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +42 -3
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +7 -3
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -15
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -3
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +2 -1
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- 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 +7 -5
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +2 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +2 -2
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +4 -9
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -2
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +24 -4
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +48 -47
- package/src/components/Table/ColumnActionsMenu.tsx +1 -1
- package/src/components/Table/ColumnSettings.tsx +1 -1
- package/src/components/Table/CreateRefPanel.tsx +25 -8
- package/src/components/Table/DynamicTable.stories.tsx +7 -4
- package/src/components/Table/DynamicTable.tsx +4 -3
- package/src/components/Table/{relations.stories.tsx → Relations.stories.tsx} +40 -23
- package/src/components/Table/RowActionsMenu.tsx +3 -3
- package/src/components/Table/Table.stories.tsx +34 -23
- package/src/components/Table/Table.tsx +131 -110
- package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
- package/src/components/TableCellEditor/FormCellEditor.tsx +143 -42
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +11 -23
- package/src/components/TableCellEditor/TableCellEditor.tsx +64 -119
- package/src/components/TableToolbar/TableToolbar.tsx +2 -2
- package/src/components/testing.ts +1 -1
- package/src/hooks/useAddRow.ts +6 -4
- package/src/hooks/useTableModel.ts +1 -1
- package/src/model/modal-controller.ts +1 -1
- package/src/model/selection-model.ts +3 -2
- package/src/model/table-model.test.ts +3 -4
- package/src/model/table-model.ts +28 -23
- package/src/model/table-presentation.test.ts +4 -4
- package/src/model/table-presentation.ts +72 -30
- package/src/model/table-sorting.ts +3 -3
- package/src/playwright/smoke.spec.ts +129 -37
- package/src/testing/useTestTableModel.ts +4 -3
- package/src/translations.ts +2 -2
- package/src/types/index.ts +1 -1
- package/src/types/schema.ts +62 -5
- package/src/util/dynamic-table.ts +5 -5
- package/src/util/index.ts +0 -1
- package/src/util/schema.ts +1 -1
- package/src/util/table-buttons.ts +4 -3
- package/src/util/table-controls.ts +4 -1
- package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
- package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
- package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
- package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/util/table.d.ts +0 -11
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/TableCellEditor/extension.ts +0 -61
- package/src/util/table.ts +0 -49
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
TableModel,
|
|
8
8
|
TablePresentation,
|
|
9
9
|
cellClassesForRowSelection,
|
|
10
|
-
createTable,
|
|
11
10
|
getBaseSchema,
|
|
12
11
|
makeDynamicTable,
|
|
13
12
|
narrowSchema,
|
|
@@ -16,8 +15,8 @@ import {
|
|
|
16
15
|
touch,
|
|
17
16
|
useAddRow,
|
|
18
17
|
useTableModel
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-RQYXNWWN.mjs";
|
|
19
|
+
import "./chunk-63UUF4IG.mjs";
|
|
21
20
|
|
|
22
21
|
// src/translations.ts
|
|
23
22
|
var translationKey = "react-ui-table";
|
|
@@ -29,8 +28,8 @@ var translations = [
|
|
|
29
28
|
"create object label": "Create table",
|
|
30
29
|
"table name placeholder": "Table name",
|
|
31
30
|
"settings title": "Table settings",
|
|
32
|
-
"table schema label": "
|
|
33
|
-
"new schema": "New
|
|
31
|
+
"table schema label": "Record type",
|
|
32
|
+
"new schema": "New record type",
|
|
34
33
|
"continue label": "Continue",
|
|
35
34
|
"create stack section label": "Create table",
|
|
36
35
|
"add row label": "Add row",
|
|
@@ -53,270 +52,38 @@ var translations = [
|
|
|
53
52
|
|
|
54
53
|
// src/components/Table/Table.tsx
|
|
55
54
|
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
56
|
-
import React8, { forwardRef, useCallback as useCallback5,
|
|
57
|
-
import { Filter } from "@dxos/echo";
|
|
58
|
-
import { getValue } from "@dxos/echo-schema";
|
|
59
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
60
|
-
import { getSpace as getSpace2 } from "@dxos/react-client/echo";
|
|
61
|
-
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
55
|
+
import React8, { forwardRef, useCallback as useCallback5, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo5, useState as useState4 } from "react";
|
|
62
56
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
63
|
-
import { closestCell,
|
|
57
|
+
import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
|
|
58
|
+
import { DxEditRequest } from "@dxos/react-ui-grid";
|
|
64
59
|
import { mx } from "@dxos/react-ui-theme";
|
|
65
|
-
import { isNotFalsy, safeParseInt } from "@dxos/util";
|
|
66
|
-
|
|
67
|
-
// src/components/Table/ColumnActionsMenu.tsx
|
|
68
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
69
|
-
import React from "react";
|
|
70
|
-
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
71
|
-
var ColumnActionsMenu = ({ model, modals }) => {
|
|
72
|
-
var _effect = _useSignals();
|
|
73
|
-
try {
|
|
74
|
-
const { t } = useTranslation(translationKey);
|
|
75
|
-
const state = modals.state.value;
|
|
76
|
-
if (state?.type !== "column") {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
const currentSort = model.sorting?.sorting;
|
|
80
|
-
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
81
|
-
return /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
|
|
82
|
-
modal: false,
|
|
83
|
-
open: true,
|
|
84
|
-
onOpenChange: modals.close
|
|
85
|
-
}, /* @__PURE__ */ React.createElement(DropdownMenu.VirtualTrigger, {
|
|
86
|
-
virtualRef: modals.trigger
|
|
87
|
-
}), /* @__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, {
|
|
88
|
-
"data-testid": "column-sort-descending",
|
|
89
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
90
|
-
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
91
|
-
"data-testid": "column-sort-ascending",
|
|
92
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
93
|
-
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
94
|
-
"data-testid": "column-clear-sort",
|
|
95
|
-
onClick: () => model.sorting?.clearSort()
|
|
96
|
-
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
97
|
-
"data-testid": "column-delete",
|
|
98
|
-
onClick: () => model.deleteColumn(state.fieldId)
|
|
99
|
-
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
100
|
-
"data-testid": "column-settings",
|
|
101
|
-
onClick: () => modals.openColumnSettings()
|
|
102
|
-
}, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
|
|
103
|
-
} finally {
|
|
104
|
-
_effect.f();
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// src/components/Table/ColumnSettings.tsx
|
|
109
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
110
|
-
import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
111
|
-
import { Popover } from "@dxos/react-ui";
|
|
112
|
-
import { FieldEditor } from "@dxos/react-ui-form";
|
|
113
|
-
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
114
|
-
var _effect = _useSignals2();
|
|
115
|
-
try {
|
|
116
|
-
const [newField, setNewField] = useState();
|
|
117
|
-
const state = modals.state.value;
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
120
|
-
setNewField(model.projection.createFieldProjection());
|
|
121
|
-
requestAnimationFrame(() => {
|
|
122
|
-
onNewColumn();
|
|
123
|
-
});
|
|
124
|
-
} else {
|
|
125
|
-
setNewField(void 0);
|
|
126
|
-
}
|
|
127
|
-
}, [
|
|
128
|
-
model?.projection,
|
|
129
|
-
state
|
|
130
|
-
]);
|
|
131
|
-
const existingField = useMemo(() => {
|
|
132
|
-
if (state?.type === "columnSettings") {
|
|
133
|
-
const { mode } = state;
|
|
134
|
-
if (mode.type === "edit") {
|
|
135
|
-
return model?.projection?.fields.find((f) => f.id === mode.fieldId);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return void 0;
|
|
139
|
-
}, [
|
|
140
|
-
model?.projection?.fields,
|
|
141
|
-
state
|
|
142
|
-
]);
|
|
143
|
-
const field = existingField ?? newField;
|
|
144
|
-
const handleSave = useCallback(() => {
|
|
145
|
-
modals.close();
|
|
146
|
-
}, [
|
|
147
|
-
modals
|
|
148
|
-
]);
|
|
149
|
-
const handleCancel = useCallback(() => {
|
|
150
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
151
|
-
model?.projection.deleteFieldProjection(newField.id);
|
|
152
|
-
}
|
|
153
|
-
}, [
|
|
154
|
-
model?.projection,
|
|
155
|
-
state,
|
|
156
|
-
newField
|
|
157
|
-
]);
|
|
158
|
-
if (!model?.projection || !field) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
162
|
-
modal: false,
|
|
163
|
-
open: state?.type === "columnSettings"
|
|
164
|
-
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
165
|
-
virtualRef: modals.trigger
|
|
166
|
-
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
167
|
-
classNames: "md:is-64"
|
|
168
|
-
}, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
|
|
169
|
-
projection: model.projection,
|
|
170
|
-
field,
|
|
171
|
-
registry,
|
|
172
|
-
onSave: handleSave,
|
|
173
|
-
onCancel: handleCancel
|
|
174
|
-
})), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
|
|
175
|
-
} finally {
|
|
176
|
-
_effect.f();
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// src/components/Table/CreateRefPanel.tsx
|
|
181
|
-
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
182
|
-
import { Schema } from "effect";
|
|
183
|
-
import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
184
|
-
import { live } from "@dxos/live-object";
|
|
185
|
-
import { getSpace } from "@dxos/react-client/echo";
|
|
186
|
-
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
187
|
-
import { Form } from "@dxos/react-ui-form";
|
|
188
|
-
import { useGridContext } from "@dxos/react-ui-grid";
|
|
189
|
-
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
190
|
-
var _effect = _useSignals3();
|
|
191
|
-
try {
|
|
192
|
-
const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
|
|
193
|
-
const space = model && getSpace(model?.view);
|
|
194
|
-
const state = modals.state.value;
|
|
195
|
-
const schema = useMemo2(() => {
|
|
196
|
-
if (!space || state?.type !== "createRefPanel") {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
200
|
-
typename: state.typename
|
|
201
|
-
}).runSync();
|
|
202
|
-
if (schema2) {
|
|
203
|
-
const omit = Schema.omit("id");
|
|
204
|
-
return omit(schema2);
|
|
205
|
-
}
|
|
206
|
-
}, [
|
|
207
|
-
space,
|
|
208
|
-
state
|
|
209
|
-
]);
|
|
210
|
-
const handleSave = useCallback2((values) => {
|
|
211
|
-
if (!model || !space || state?.type !== "createRefPanel") {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
215
|
-
typename: state.typename
|
|
216
|
-
}).runSync();
|
|
217
|
-
if (schema2) {
|
|
218
|
-
const obj = space.db.add(live(schema2, values));
|
|
219
|
-
state.onCreate?.(obj);
|
|
220
|
-
}
|
|
221
|
-
void modals.close();
|
|
222
|
-
}, [
|
|
223
|
-
modals,
|
|
224
|
-
space,
|
|
225
|
-
state
|
|
226
|
-
]);
|
|
227
|
-
const handleCancel = useCallback2(() => {
|
|
228
|
-
if (model) {
|
|
229
|
-
modals.close();
|
|
230
|
-
}
|
|
231
|
-
}, [
|
|
232
|
-
modals
|
|
233
|
-
]);
|
|
234
|
-
if (!model?.projection) {
|
|
235
|
-
return null;
|
|
236
|
-
}
|
|
237
|
-
return /* @__PURE__ */ React3.createElement(Popover2.Root, {
|
|
238
|
-
modal: false,
|
|
239
|
-
open: state?.type === "createRefPanel" && !!schema,
|
|
240
|
-
onOpenChange: (nextOpen) => {
|
|
241
|
-
if (model && !nextOpen) {
|
|
242
|
-
return modals.close();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.VirtualTrigger, {
|
|
246
|
-
virtualRef: modals.trigger
|
|
247
|
-
}), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
|
|
248
|
-
classNames: "md:is-64",
|
|
249
|
-
"data-grid": gridId
|
|
250
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
|
|
251
|
-
schema,
|
|
252
|
-
values: state.initialValues ?? {},
|
|
253
|
-
onSave: handleSave,
|
|
254
|
-
onCancel: handleCancel
|
|
255
|
-
})), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null))));
|
|
256
|
-
} finally {
|
|
257
|
-
_effect.f();
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
// src/components/Table/RowActionsMenu.tsx
|
|
262
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
263
|
-
import React4 from "react";
|
|
264
|
-
import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
265
|
-
var RowActionsMenu = ({ model, modals }) => {
|
|
266
|
-
var _effect = _useSignals4();
|
|
267
|
-
try {
|
|
268
|
-
const { t } = useTranslation2(translationKey);
|
|
269
|
-
const hasSelection = model.selection.hasSelection.value;
|
|
270
|
-
const state = modals.state.value;
|
|
271
|
-
if (state?.type !== "row") {
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenu2.Root, {
|
|
275
|
-
modal: false,
|
|
276
|
-
open: true,
|
|
277
|
-
onOpenChange: modals.close
|
|
278
|
-
}, /* @__PURE__ */ React4.createElement(DropdownMenu2.VirtualTrigger, {
|
|
279
|
-
virtualRef: modals.trigger
|
|
280
|
-
}), /* @__PURE__ */ React4.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
281
|
-
"data-testid": "row-menu-delete",
|
|
282
|
-
onClick: () => model.deleteRow(state.rowIndex)
|
|
283
|
-
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
284
|
-
key: action.id,
|
|
285
|
-
"data-testid": `row-action-${action.id}`,
|
|
286
|
-
onClick: () => {
|
|
287
|
-
modals.close();
|
|
288
|
-
model.handleRowAction(action.id, state.rowIndex);
|
|
289
|
-
}
|
|
290
|
-
}, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu2.Arrow, null)));
|
|
291
|
-
} finally {
|
|
292
|
-
_effect.f();
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
60
|
|
|
296
61
|
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
297
|
-
import { useSignals as
|
|
298
|
-
import
|
|
62
|
+
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
63
|
+
import { EditorView } from "@codemirror/view";
|
|
64
|
+
import React3, { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
65
|
+
import { debounce } from "@dxos/async";
|
|
299
66
|
import { FormatEnum, TypeEnum } from "@dxos/echo-schema";
|
|
300
67
|
import { invariant as invariant2 } from "@dxos/invariant";
|
|
301
68
|
import { useThemeContext } from "@dxos/react-ui";
|
|
302
69
|
import { createMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
303
|
-
import {
|
|
304
|
-
import {
|
|
70
|
+
import { GridCellEditor, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
71
|
+
import { createLinks, tagPicker } from "@dxos/react-ui-tag-picker";
|
|
305
72
|
|
|
306
73
|
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
307
|
-
import { useSignals as
|
|
308
|
-
import
|
|
309
|
-
import { useGridContext
|
|
74
|
+
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
75
|
+
import React from "react";
|
|
76
|
+
import { useGridContext } from "@dxos/react-ui-grid";
|
|
310
77
|
var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
|
|
311
|
-
var _effect =
|
|
78
|
+
var _effect = _useSignals();
|
|
312
79
|
try {
|
|
313
|
-
const { editing, editBox: box } =
|
|
80
|
+
const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
|
|
314
81
|
if (!editing || !validationError) {
|
|
315
82
|
return null;
|
|
316
83
|
}
|
|
317
84
|
const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
|
|
318
85
|
const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
|
|
319
|
-
return /* @__PURE__ */
|
|
86
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
320
87
|
role: "none",
|
|
321
88
|
className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
|
|
322
89
|
style: {
|
|
@@ -335,22 +102,157 @@ var CellValidationMessage = ({ validationError, variant = "error", __gridScope }
|
|
|
335
102
|
};
|
|
336
103
|
|
|
337
104
|
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
338
|
-
import { useSignals as
|
|
339
|
-
import
|
|
340
|
-
import {
|
|
105
|
+
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
106
|
+
import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
107
|
+
import { Filter, Obj } from "@dxos/echo";
|
|
108
|
+
import { Ref, getValue } from "@dxos/echo-schema";
|
|
341
109
|
import { invariant } from "@dxos/invariant";
|
|
342
|
-
import {
|
|
343
|
-
import {
|
|
344
|
-
import {
|
|
345
|
-
import {
|
|
110
|
+
import { getSnapshot } from "@dxos/live-object";
|
|
111
|
+
import { getSpace } from "@dxos/react-client/echo";
|
|
112
|
+
import { Popover } from "@dxos/react-ui";
|
|
113
|
+
import { Form } from "@dxos/react-ui-form";
|
|
114
|
+
import { cellQuery, parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
115
|
+
import { getDeep, isNotFalsy, setDeep } from "@dxos/util";
|
|
346
116
|
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
347
|
-
var
|
|
348
|
-
|
|
117
|
+
var createOptionLabel = [
|
|
118
|
+
"create new object label",
|
|
119
|
+
{
|
|
120
|
+
ns: translationKey
|
|
121
|
+
}
|
|
122
|
+
];
|
|
123
|
+
var FormCellEditor = ({ fieldProjection, model, schema, onSave, client, modals, __gridScope, ...formProps }) => {
|
|
124
|
+
var _effect = _useSignals2();
|
|
349
125
|
try {
|
|
350
|
-
const { editing: contextEditing, setEditing } =
|
|
351
|
-
const [editing, setLocalEditing] =
|
|
126
|
+
const { editing: contextEditing, setEditing, id: gridId } = useGridContext2("ArrayEditor", __gridScope);
|
|
127
|
+
const [editing, setLocalEditing] = useState(false);
|
|
352
128
|
const anchorRef = useRef(null);
|
|
353
|
-
|
|
129
|
+
const getSchema = useCallback((typeAnnotation) => {
|
|
130
|
+
const space = getSpace(model.view);
|
|
131
|
+
invariant(space, void 0, {
|
|
132
|
+
F: __dxlog_file,
|
|
133
|
+
L: 53,
|
|
134
|
+
S: void 0,
|
|
135
|
+
A: [
|
|
136
|
+
"space",
|
|
137
|
+
""
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
let schema2;
|
|
141
|
+
if (client) {
|
|
142
|
+
schema2 = client.graph.schemaRegistry.getSchema(typeAnnotation.typename);
|
|
143
|
+
}
|
|
144
|
+
if (!schema2) {
|
|
145
|
+
schema2 = space.db.schemaRegistry.getSchema(typeAnnotation.typename);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
space,
|
|
149
|
+
schema: schema2
|
|
150
|
+
};
|
|
151
|
+
}, [
|
|
152
|
+
client,
|
|
153
|
+
model
|
|
154
|
+
]);
|
|
155
|
+
const handleQueryRefOptions = useCallback(async (typeAnnotation) => {
|
|
156
|
+
const { schema: schema2, space } = getSchema(typeAnnotation);
|
|
157
|
+
if (model && schema2 && space) {
|
|
158
|
+
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
159
|
+
return objects.map((obj) => {
|
|
160
|
+
return {
|
|
161
|
+
dxn: Obj.getDXN(obj),
|
|
162
|
+
label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
|
|
163
|
+
};
|
|
164
|
+
}).filter(isNotFalsy);
|
|
165
|
+
}
|
|
166
|
+
return [];
|
|
167
|
+
}, [
|
|
168
|
+
client,
|
|
169
|
+
model
|
|
170
|
+
]);
|
|
171
|
+
const originalRow = useMemo(() => {
|
|
172
|
+
if (model && contextEditing) {
|
|
173
|
+
const cell = parseCellIndex(contextEditing.index);
|
|
174
|
+
if (model.isDraftCell(cell)) {
|
|
175
|
+
const draftRow = model.draftRows.value[cell.row];
|
|
176
|
+
invariant(draftRow, void 0, {
|
|
177
|
+
F: __dxlog_file,
|
|
178
|
+
L: 94,
|
|
179
|
+
S: void 0,
|
|
180
|
+
A: [
|
|
181
|
+
"draftRow",
|
|
182
|
+
""
|
|
183
|
+
]
|
|
184
|
+
});
|
|
185
|
+
return draftRow.data;
|
|
186
|
+
} else {
|
|
187
|
+
const row = model.getRowAt(cell.row);
|
|
188
|
+
invariant(row, void 0, {
|
|
189
|
+
F: __dxlog_file,
|
|
190
|
+
L: 98,
|
|
191
|
+
S: void 0,
|
|
192
|
+
A: [
|
|
193
|
+
"row",
|
|
194
|
+
""
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
return row;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return void 0;
|
|
201
|
+
}, [
|
|
202
|
+
model,
|
|
203
|
+
contextEditing
|
|
204
|
+
]);
|
|
205
|
+
const handleSave = useCallback((values) => {
|
|
206
|
+
const path = fieldProjection.field.path;
|
|
207
|
+
const value = getDeep(values, [
|
|
208
|
+
path
|
|
209
|
+
]);
|
|
210
|
+
setDeep(originalRow, [
|
|
211
|
+
path
|
|
212
|
+
], value);
|
|
213
|
+
contextEditing?.cellElement?.focus();
|
|
214
|
+
setEditing(null);
|
|
215
|
+
setLocalEditing(false);
|
|
216
|
+
onSave?.();
|
|
217
|
+
}, [
|
|
218
|
+
fieldProjection.field.path,
|
|
219
|
+
onSave,
|
|
220
|
+
contextEditing,
|
|
221
|
+
originalRow
|
|
222
|
+
]);
|
|
223
|
+
const handleCreate = useCallback((object) => {
|
|
224
|
+
const ref = Ref.make(object);
|
|
225
|
+
const path = fieldProjection.field.path;
|
|
226
|
+
setDeep(originalRow, [
|
|
227
|
+
path
|
|
228
|
+
], ref);
|
|
229
|
+
contextEditing?.cellElement?.focus();
|
|
230
|
+
setEditing(null);
|
|
231
|
+
setLocalEditing(false);
|
|
232
|
+
onSave?.();
|
|
233
|
+
}, [
|
|
234
|
+
fieldProjection.field.path,
|
|
235
|
+
onSave,
|
|
236
|
+
contextEditing,
|
|
237
|
+
originalRow
|
|
238
|
+
]);
|
|
239
|
+
const handleCreateFromQuery = useCallback(async (typeAnnotation, query) => {
|
|
240
|
+
if (model && modals && contextEditing?.index) {
|
|
241
|
+
setLocalEditing(false);
|
|
242
|
+
modals.openCreateRef(typeAnnotation.typename, document.querySelector(cellQuery(contextEditing.index, gridId)), {
|
|
243
|
+
[fieldProjection.field.referencePath]: query
|
|
244
|
+
}, handleCreate);
|
|
245
|
+
}
|
|
246
|
+
}, [
|
|
247
|
+
model,
|
|
248
|
+
modals,
|
|
249
|
+
client,
|
|
250
|
+
contextEditing?.index,
|
|
251
|
+
gridId,
|
|
252
|
+
fieldProjection,
|
|
253
|
+
handleSave
|
|
254
|
+
]);
|
|
255
|
+
useEffect(() => {
|
|
354
256
|
if (contextEditing && contextEditing.cellElement) {
|
|
355
257
|
anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
|
|
356
258
|
setLocalEditing(true);
|
|
@@ -361,7 +263,7 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
|
|
|
361
263
|
}, [
|
|
362
264
|
contextEditing
|
|
363
265
|
]);
|
|
364
|
-
const narrowedSchema =
|
|
266
|
+
const narrowedSchema = useMemo(() => {
|
|
365
267
|
if (!schema) {
|
|
366
268
|
return void 0;
|
|
367
269
|
}
|
|
@@ -372,49 +274,10 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
|
|
|
372
274
|
JSON.stringify(schema),
|
|
373
275
|
fieldProjection.field.path
|
|
374
276
|
]);
|
|
375
|
-
const
|
|
376
|
-
if (model && contextEditing) {
|
|
377
|
-
const cell = parseCellIndex(contextEditing.index);
|
|
378
|
-
const row = model.getRowAt(cell.row);
|
|
379
|
-
invariant(row, void 0, {
|
|
380
|
-
F: __dxlog_file,
|
|
381
|
-
L: 55,
|
|
382
|
-
S: void 0,
|
|
383
|
-
A: [
|
|
384
|
-
"row",
|
|
385
|
-
""
|
|
386
|
-
]
|
|
387
|
-
});
|
|
388
|
-
return row;
|
|
389
|
-
}
|
|
390
|
-
return void 0;
|
|
391
|
-
}, [
|
|
392
|
-
model,
|
|
393
|
-
contextEditing
|
|
394
|
-
]);
|
|
395
|
-
const formValues = useMemo3(() => {
|
|
396
|
-
if (originalRow) {
|
|
397
|
-
return getSnapshot(originalRow);
|
|
398
|
-
}
|
|
399
|
-
}, [
|
|
400
|
-
originalRow
|
|
401
|
-
]);
|
|
402
|
-
const handleSave = useCallback3((values) => {
|
|
403
|
-
const path = fieldProjection.field.path;
|
|
404
|
-
const value = getDeep(values, [
|
|
405
|
-
path
|
|
406
|
-
]);
|
|
407
|
-
setDeep(originalRow, [
|
|
408
|
-
path
|
|
409
|
-
], value);
|
|
410
|
-
setEditing(null);
|
|
411
|
-
setLocalEditing(false);
|
|
412
|
-
onSave?.();
|
|
413
|
-
}, [
|
|
414
|
-
fieldProjection.field.path,
|
|
277
|
+
const formValues = useMemo(() => originalRow ? getSnapshot(originalRow) : {}, [
|
|
415
278
|
originalRow
|
|
416
279
|
]);
|
|
417
|
-
const handleOpenChange =
|
|
280
|
+
const handleOpenChange = useCallback((nextOpen) => {
|
|
418
281
|
if (nextOpen === false) {
|
|
419
282
|
setEditing(null);
|
|
420
283
|
onSave?.();
|
|
@@ -424,76 +287,38 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
|
|
|
424
287
|
if (!editing) {
|
|
425
288
|
return null;
|
|
426
289
|
}
|
|
427
|
-
return /* @__PURE__ */
|
|
290
|
+
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
428
291
|
open: editing,
|
|
429
292
|
onOpenChange: handleOpenChange
|
|
430
|
-
}, /* @__PURE__ */
|
|
293
|
+
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
431
294
|
virtualRef: anchorRef
|
|
432
|
-
}), /* @__PURE__ */
|
|
295
|
+
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
433
296
|
tabIndex: -1,
|
|
434
297
|
classNames: "popover-card-width density-fine"
|
|
435
|
-
}, /* @__PURE__ */
|
|
298
|
+
}, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form, {
|
|
299
|
+
autoFocus: true,
|
|
436
300
|
values: formValues,
|
|
437
301
|
schema: narrowedSchema,
|
|
438
|
-
onSave: handleSave
|
|
439
|
-
|
|
302
|
+
onSave: handleSave,
|
|
303
|
+
...formProps,
|
|
304
|
+
onQueryRefOptions: handleQueryRefOptions,
|
|
305
|
+
onCreateFromQuery: handleCreateFromQuery,
|
|
306
|
+
createOptionIcon: "ph--plus--regular",
|
|
307
|
+
createOptionLabel
|
|
308
|
+
})))));
|
|
440
309
|
} finally {
|
|
441
310
|
_effect.f();
|
|
442
311
|
}
|
|
443
312
|
};
|
|
444
313
|
|
|
445
|
-
// src/components/TableCellEditor/extension.ts
|
|
446
|
-
import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
|
|
447
|
-
import { EditorView } from "@codemirror/view";
|
|
448
|
-
var completion = ({ debug, onQuery, onMatch }) => {
|
|
449
|
-
return [
|
|
450
|
-
EditorView.theme({
|
|
451
|
-
".cm-completionDialog": {
|
|
452
|
-
width: "var(--dx-gridCellWidth)"
|
|
453
|
-
}
|
|
454
|
-
}),
|
|
455
|
-
autocompletion({
|
|
456
|
-
icons: false,
|
|
457
|
-
activateOnTyping: true,
|
|
458
|
-
closeOnBlur: !debug,
|
|
459
|
-
override: [
|
|
460
|
-
async (context) => {
|
|
461
|
-
const text = context.state.doc.toString();
|
|
462
|
-
return {
|
|
463
|
-
from: 0,
|
|
464
|
-
options: await onQuery(text)
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
],
|
|
468
|
-
// TODO(burdon): Consts from grid (to line-up with grid).
|
|
469
|
-
tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
|
|
470
|
-
optionClass: () => "flex h-[33px] items-center"
|
|
471
|
-
}),
|
|
472
|
-
// Check for accepted completion metadata in the transaction.
|
|
473
|
-
EditorView.updateListener.of((update) => {
|
|
474
|
-
update.transactions.forEach((tr) => {
|
|
475
|
-
const completion2 = tr.annotation(pickedCompletion);
|
|
476
|
-
if (completion2) {
|
|
477
|
-
onMatch(completion2.data);
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
})
|
|
481
|
-
];
|
|
482
|
-
};
|
|
483
|
-
|
|
484
314
|
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
485
315
|
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
486
|
-
var
|
|
487
|
-
var
|
|
488
|
-
|
|
489
|
-
text
|
|
490
|
-
});
|
|
491
|
-
var isCreateOption = (data) => typeof data === "object" && data[newValue];
|
|
492
|
-
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQuery, __gridScope }) => {
|
|
493
|
-
var _effect = _useSignals7();
|
|
316
|
+
var adaptValidationMessage = (message) => message ? message.endsWith("is missing") ? "Can\u2019t be blank" : message : null;
|
|
317
|
+
var TableValueEditor = ({ model, modals, schema, onFocus, onSave, client, __gridScope }) => {
|
|
318
|
+
var _effect = _useSignals3();
|
|
494
319
|
try {
|
|
495
|
-
const { editing } =
|
|
496
|
-
const fieldProjection =
|
|
320
|
+
const { editing } = useGridContext3("TableValueEditor", __gridScope);
|
|
321
|
+
const fieldProjection = useMemo2(() => {
|
|
497
322
|
if (!model || !editing) {
|
|
498
323
|
return;
|
|
499
324
|
}
|
|
@@ -502,7 +327,7 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQue
|
|
|
502
327
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
503
328
|
invariant2(fieldProjection2, void 0, {
|
|
504
329
|
F: __dxlog_file2,
|
|
505
|
-
L:
|
|
330
|
+
L: 72,
|
|
506
331
|
S: void 0,
|
|
507
332
|
A: [
|
|
508
333
|
"fieldProjection",
|
|
@@ -514,21 +339,21 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQue
|
|
|
514
339
|
model,
|
|
515
340
|
editing
|
|
516
341
|
]);
|
|
517
|
-
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect) {
|
|
518
|
-
return /* @__PURE__ */
|
|
342
|
+
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect || fieldProjection?.props.format === FormatEnum.Ref) {
|
|
343
|
+
return /* @__PURE__ */ React3.createElement(FormCellEditor, {
|
|
519
344
|
fieldProjection,
|
|
520
345
|
model,
|
|
521
346
|
schema,
|
|
522
347
|
__gridScope,
|
|
523
|
-
onSave
|
|
348
|
+
onSave,
|
|
349
|
+
client,
|
|
350
|
+
modals
|
|
524
351
|
});
|
|
525
352
|
}
|
|
526
|
-
return /* @__PURE__ */
|
|
353
|
+
return /* @__PURE__ */ React3.createElement(TableCellEditor, {
|
|
527
354
|
model,
|
|
528
355
|
modals,
|
|
529
|
-
onEnter,
|
|
530
356
|
onFocus,
|
|
531
|
-
onQuery,
|
|
532
357
|
onSave,
|
|
533
358
|
__gridScope
|
|
534
359
|
});
|
|
@@ -541,15 +366,15 @@ var editorSlots = {
|
|
|
541
366
|
className: "!plb-[--dx-grid-cell-editor-padding-block]"
|
|
542
367
|
}
|
|
543
368
|
};
|
|
544
|
-
var TableCellEditor = ({ model, modals,
|
|
545
|
-
var _effect =
|
|
369
|
+
var TableCellEditor = ({ model, modals, onFocus, onSave, __gridScope }) => {
|
|
370
|
+
var _effect = _useSignals3();
|
|
546
371
|
try {
|
|
547
|
-
const { id: gridId, editing, setEditing } =
|
|
372
|
+
const { id: gridId, editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
|
|
548
373
|
const suppressNextBlur = useRef2(false);
|
|
549
374
|
const { themeMode } = useThemeContext();
|
|
550
|
-
const [
|
|
551
|
-
const [
|
|
552
|
-
const fieldProjection =
|
|
375
|
+
const [validationError, setValidationError] = useState2(null);
|
|
376
|
+
const [validationVariant, setValidationVariant] = useState2("error");
|
|
377
|
+
const fieldProjection = useMemo2(() => {
|
|
553
378
|
if (!model || !editing) {
|
|
554
379
|
return;
|
|
555
380
|
}
|
|
@@ -558,7 +383,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
558
383
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
559
384
|
invariant2(fieldProjection2, void 0, {
|
|
560
385
|
F: __dxlog_file2,
|
|
561
|
-
L:
|
|
386
|
+
L: 122,
|
|
562
387
|
S: void 0,
|
|
563
388
|
A: [
|
|
564
389
|
"fieldProjection",
|
|
@@ -570,38 +395,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
570
395
|
model,
|
|
571
396
|
editing
|
|
572
397
|
]);
|
|
573
|
-
|
|
574
|
-
if (!model || !editing || !fieldProjection) {
|
|
575
|
-
setValidationError(null);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
const cell = parseCellIndex2(editing.index);
|
|
579
|
-
const { row, col } = cell;
|
|
580
|
-
if (model.isDraftCell(cell)) {
|
|
581
|
-
const field = model.projection.fields[col];
|
|
582
|
-
const hasValidationError = model.hasDraftRowValidationError(row, field.path);
|
|
583
|
-
if (hasValidationError) {
|
|
584
|
-
const draftRows = model.draftRows.value;
|
|
585
|
-
if (row >= 0 && row < draftRows.length) {
|
|
586
|
-
const draftRow = draftRows[row];
|
|
587
|
-
const validationError = draftRow.validationErrors?.find((error) => error.path === field.path);
|
|
588
|
-
if (validationError) {
|
|
589
|
-
setValidationError(validationError.message);
|
|
590
|
-
setValidationVariant("warning");
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
} else {
|
|
594
|
-
setValidationError(null);
|
|
595
|
-
}
|
|
596
|
-
} else {
|
|
597
|
-
setValidationError(null);
|
|
598
|
-
}
|
|
599
|
-
}, [
|
|
600
|
-
model,
|
|
601
|
-
editing,
|
|
602
|
-
fieldProjection
|
|
603
|
-
]);
|
|
604
|
-
const handleEnter = useCallback4(async (value) => {
|
|
398
|
+
const handleEnter = useCallback2(async (value) => {
|
|
605
399
|
if (!model || !editing) {
|
|
606
400
|
return;
|
|
607
401
|
}
|
|
@@ -610,33 +404,39 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
610
404
|
if (validationResult.valid) {
|
|
611
405
|
setValidationError(null);
|
|
612
406
|
model.setCellData(cell, value);
|
|
613
|
-
onEnter?.(cell);
|
|
614
407
|
onFocus?.();
|
|
615
408
|
setEditing(null);
|
|
616
409
|
onSave?.();
|
|
617
410
|
} else {
|
|
618
|
-
setValidationError(validationResult.error);
|
|
411
|
+
setValidationError(adaptValidationMessage(validationResult.error));
|
|
619
412
|
setValidationVariant("error");
|
|
620
413
|
}
|
|
621
414
|
}, [
|
|
622
415
|
model,
|
|
623
416
|
editing,
|
|
624
|
-
onEnter,
|
|
625
417
|
onFocus,
|
|
626
418
|
setEditing
|
|
627
419
|
]);
|
|
628
|
-
const handleBlur =
|
|
629
|
-
if (!model || !editing) {
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
420
|
+
const handleBlur = useCallback2(async (value) => {
|
|
632
421
|
if (suppressNextBlur.current) {
|
|
633
422
|
suppressNextBlur.current = false;
|
|
423
|
+
} else if (model && editing) {
|
|
424
|
+
const cell = parseCellIndex2(editing.index);
|
|
425
|
+
if (value !== void 0) {
|
|
426
|
+
const result = await model.validateCellData(cell, value);
|
|
427
|
+
if (result.valid) {
|
|
428
|
+
setValidationError(null);
|
|
429
|
+
model.setCellData(cell, value);
|
|
430
|
+
setEditing(null);
|
|
431
|
+
onSave?.();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
634
434
|
}
|
|
635
435
|
}, [
|
|
636
436
|
model,
|
|
637
437
|
editing
|
|
638
438
|
]);
|
|
639
|
-
const handleClose =
|
|
439
|
+
const handleClose = useCallback2(async (value, event) => {
|
|
640
440
|
if (!model || !editing || !fieldProjection) {
|
|
641
441
|
return;
|
|
642
442
|
}
|
|
@@ -644,19 +444,20 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
644
444
|
if (value !== void 0) {
|
|
645
445
|
const result = await model.validateCellData(cell, value);
|
|
646
446
|
if (result.valid) {
|
|
447
|
+
suppressNextBlur.current = true;
|
|
647
448
|
setValidationError(null);
|
|
648
449
|
model.setCellData(cell, value);
|
|
649
450
|
setEditing(null);
|
|
650
451
|
onSave?.();
|
|
651
|
-
onEnter?.(cell);
|
|
652
452
|
if (event && onFocus) {
|
|
653
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
453
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
|
|
654
454
|
}
|
|
655
455
|
} else {
|
|
656
456
|
setValidationError(result.error);
|
|
657
457
|
setValidationVariant("error");
|
|
658
458
|
}
|
|
659
459
|
} else {
|
|
460
|
+
suppressNextBlur.current = true;
|
|
660
461
|
setValidationError(null);
|
|
661
462
|
setEditing(null);
|
|
662
463
|
onSave?.();
|
|
@@ -668,12 +469,11 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
668
469
|
model,
|
|
669
470
|
editing,
|
|
670
471
|
onFocus,
|
|
671
|
-
onEnter,
|
|
672
472
|
fieldProjection,
|
|
673
473
|
setEditing,
|
|
674
474
|
onSave
|
|
675
475
|
]);
|
|
676
|
-
const extension =
|
|
476
|
+
const extension = useMemo2(() => {
|
|
677
477
|
if (!fieldProjection) {
|
|
678
478
|
return [];
|
|
679
479
|
}
|
|
@@ -716,131 +516,369 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
|
|
|
716
516
|
}
|
|
717
517
|
}));
|
|
718
518
|
}
|
|
719
|
-
if (
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
519
|
+
if (model && editing) {
|
|
520
|
+
extension2.push(EditorView.updateListener.of(debounce((update) => {
|
|
521
|
+
const content = update.state.doc.toString();
|
|
522
|
+
const cell = parseCellIndex2(editing.index);
|
|
523
|
+
void model.validateCellData(cell, content).then((result) => {
|
|
524
|
+
if (result.valid) {
|
|
525
|
+
setValidationError(null);
|
|
526
|
+
} else {
|
|
527
|
+
setValidationError(result.error);
|
|
528
|
+
setValidationVariant("error");
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}, 10)));
|
|
532
|
+
}
|
|
533
|
+
return extension2;
|
|
534
|
+
}, [
|
|
535
|
+
model,
|
|
536
|
+
modals,
|
|
537
|
+
editing,
|
|
538
|
+
fieldProjection,
|
|
539
|
+
handleClose,
|
|
540
|
+
themeMode
|
|
541
|
+
]);
|
|
542
|
+
const getCellContent = useCallback2(() => {
|
|
543
|
+
if (model && editing) {
|
|
544
|
+
const cell = parseCellIndex2(editing.index);
|
|
545
|
+
const { col } = cell;
|
|
546
|
+
const field = model.projection.fields[col];
|
|
547
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
548
|
+
if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
|
|
549
|
+
const value2 = model.getCellData(cell);
|
|
550
|
+
if (value2 !== void 0) {
|
|
551
|
+
const options = fieldProjection2.props.options || [];
|
|
552
|
+
if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
|
|
553
|
+
const tagItems = value2.split(",").map((id) => {
|
|
554
|
+
const option = options.find((o) => o.id === id);
|
|
555
|
+
if (option) {
|
|
556
|
+
return {
|
|
557
|
+
id,
|
|
558
|
+
label: option.title,
|
|
559
|
+
hue: option.color
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
return void 0;
|
|
563
|
+
}).filter((item) => item !== void 0);
|
|
564
|
+
return createLinks(tagItems);
|
|
565
|
+
} else {
|
|
566
|
+
const option = options.find((o) => o.id === value2);
|
|
567
|
+
if (option) {
|
|
568
|
+
const tagItem = {
|
|
569
|
+
id: value2,
|
|
570
|
+
label: option.title,
|
|
571
|
+
hue: option.color
|
|
572
|
+
};
|
|
573
|
+
return createLinks([
|
|
574
|
+
tagItem
|
|
575
|
+
]);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return "";
|
|
580
|
+
}
|
|
581
|
+
const value = model.getCellData(cell);
|
|
582
|
+
return value !== void 0 ? String(value) : "";
|
|
583
|
+
}
|
|
584
|
+
}, [
|
|
585
|
+
model,
|
|
586
|
+
editing
|
|
587
|
+
]);
|
|
588
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
|
|
589
|
+
validationError,
|
|
590
|
+
variant: validationVariant,
|
|
591
|
+
__gridScope
|
|
592
|
+
}), /* @__PURE__ */ React3.createElement(GridCellEditor, {
|
|
593
|
+
extension,
|
|
594
|
+
getCellContent,
|
|
595
|
+
onBlur: handleBlur,
|
|
596
|
+
slots: editorSlots
|
|
597
|
+
}));
|
|
598
|
+
} finally {
|
|
599
|
+
_effect.f();
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
var determineNavigationAxis = ({ key }) => {
|
|
603
|
+
switch (key) {
|
|
604
|
+
case "ArrowUp":
|
|
605
|
+
case "ArrowDown":
|
|
606
|
+
case "Enter": {
|
|
607
|
+
return "row";
|
|
608
|
+
}
|
|
609
|
+
case "ArrowLeft":
|
|
610
|
+
case "ArrowRight":
|
|
611
|
+
case "Tab":
|
|
612
|
+
return "col";
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
var determineNavigationDelta = ({ key, shift }) => {
|
|
616
|
+
switch (key) {
|
|
617
|
+
case "ArrowUp":
|
|
618
|
+
case "ArrowLeft":
|
|
619
|
+
return -1;
|
|
620
|
+
case "ArrowDown":
|
|
621
|
+
case "ArrowRight":
|
|
622
|
+
return 1;
|
|
623
|
+
}
|
|
624
|
+
return shift ? -1 : 1;
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
// src/components/Table/ColumnActionsMenu.tsx
|
|
628
|
+
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
629
|
+
import React4 from "react";
|
|
630
|
+
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
631
|
+
var ColumnActionsMenu = ({ model, modals }) => {
|
|
632
|
+
var _effect = _useSignals4();
|
|
633
|
+
try {
|
|
634
|
+
const { t } = useTranslation(translationKey);
|
|
635
|
+
const state = modals.state.value;
|
|
636
|
+
if (state?.type !== "column") {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
const currentSort = model.sorting?.sorting;
|
|
640
|
+
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
641
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
642
|
+
modal: false,
|
|
643
|
+
open: true,
|
|
644
|
+
onOpenChange: modals.close
|
|
645
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
|
|
646
|
+
virtualRef: modals.trigger
|
|
647
|
+
}), /* @__PURE__ */ React4.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
648
|
+
"data-testid": "column-sort-descending",
|
|
649
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
650
|
+
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
651
|
+
"data-testid": "column-sort-ascending",
|
|
652
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
653
|
+
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
654
|
+
"data-testid": "column-clear-sort",
|
|
655
|
+
onClick: () => model.sorting?.clearSort()
|
|
656
|
+
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
657
|
+
"data-testid": "column-delete",
|
|
658
|
+
onClick: () => model.deleteColumn(state.fieldId)
|
|
659
|
+
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
660
|
+
"data-testid": "column-settings",
|
|
661
|
+
onClick: () => modals.openColumnSettings()
|
|
662
|
+
}, t("column action settings"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
|
|
663
|
+
} finally {
|
|
664
|
+
_effect.f();
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
// src/components/Table/ColumnSettings.tsx
|
|
669
|
+
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
670
|
+
import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
671
|
+
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
672
|
+
import { FieldEditor } from "@dxos/react-ui-form";
|
|
673
|
+
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
674
|
+
var _effect = _useSignals5();
|
|
675
|
+
try {
|
|
676
|
+
const [newField, setNewField] = useState3();
|
|
677
|
+
const state = modals.state.value;
|
|
678
|
+
useEffect2(() => {
|
|
679
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
680
|
+
setNewField(model.projection.createFieldProjection());
|
|
681
|
+
requestAnimationFrame(() => {
|
|
682
|
+
onNewColumn();
|
|
683
|
+
});
|
|
684
|
+
} else {
|
|
685
|
+
setNewField(void 0);
|
|
686
|
+
}
|
|
687
|
+
}, [
|
|
688
|
+
model?.projection,
|
|
689
|
+
state
|
|
690
|
+
]);
|
|
691
|
+
const existingField = useMemo3(() => {
|
|
692
|
+
if (state?.type === "columnSettings") {
|
|
693
|
+
const { mode } = state;
|
|
694
|
+
if (mode.type === "edit") {
|
|
695
|
+
return model?.projection?.fields.find((f) => f.id === mode.fieldId);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
return void 0;
|
|
699
|
+
}, [
|
|
700
|
+
model?.projection?.fields,
|
|
701
|
+
state
|
|
702
|
+
]);
|
|
703
|
+
const field = existingField ?? newField;
|
|
704
|
+
const handleSave = useCallback3(() => {
|
|
705
|
+
modals.close();
|
|
706
|
+
}, [
|
|
707
|
+
modals
|
|
708
|
+
]);
|
|
709
|
+
const handleCancel = useCallback3(() => {
|
|
710
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
711
|
+
model?.projection.deleteFieldProjection(newField.id);
|
|
712
|
+
}
|
|
713
|
+
}, [
|
|
714
|
+
model?.projection,
|
|
715
|
+
state,
|
|
716
|
+
newField
|
|
717
|
+
]);
|
|
718
|
+
if (!model?.projection || !field) {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
return /* @__PURE__ */ React5.createElement(Popover2.Root, {
|
|
722
|
+
modal: false,
|
|
723
|
+
open: state?.type === "columnSettings"
|
|
724
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
|
|
725
|
+
virtualRef: modals.trigger
|
|
726
|
+
}), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
|
|
727
|
+
classNames: "md:is-64"
|
|
728
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
|
|
729
|
+
projection: model.projection,
|
|
730
|
+
field,
|
|
731
|
+
registry,
|
|
732
|
+
onSave: handleSave,
|
|
733
|
+
onCancel: handleCancel
|
|
734
|
+
})), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
|
|
735
|
+
} finally {
|
|
736
|
+
_effect.f();
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// src/components/Table/CreateRefPanel.tsx
|
|
741
|
+
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
742
|
+
import { Schema } from "effect";
|
|
743
|
+
import React6, { useCallback as useCallback4, useMemo as useMemo4 } from "react";
|
|
744
|
+
import { Type } from "@dxos/echo";
|
|
745
|
+
import { live } from "@dxos/live-object";
|
|
746
|
+
import { useClient } from "@dxos/react-client";
|
|
747
|
+
import { getSpace as getSpace2 } from "@dxos/react-client/echo";
|
|
748
|
+
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
749
|
+
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
750
|
+
import { useGridContext as useGridContext4 } from "@dxos/react-ui-grid";
|
|
751
|
+
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
752
|
+
var _effect = _useSignals6();
|
|
753
|
+
try {
|
|
754
|
+
const { id: gridId } = useGridContext4("TableCellEditor", __gridScope);
|
|
755
|
+
const client = useClient();
|
|
756
|
+
const space = model && getSpace2(model?.view);
|
|
757
|
+
const state = modals.state.value;
|
|
758
|
+
const getSchema = useCallback4(() => {
|
|
759
|
+
if (!space || state?.type !== "createRefPanel") {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
const staticSchema = client.graph.schemaRegistry.schemas.find((schema3) => Type.getTypename(schema3) === state.typename);
|
|
763
|
+
if (staticSchema) {
|
|
764
|
+
return staticSchema;
|
|
747
765
|
}
|
|
748
|
-
|
|
766
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
767
|
+
typename: state.typename
|
|
768
|
+
}).runSync();
|
|
769
|
+
return schema2;
|
|
770
|
+
}, [
|
|
771
|
+
space,
|
|
772
|
+
state
|
|
773
|
+
]);
|
|
774
|
+
const schema = useMemo4(() => {
|
|
775
|
+
const schema2 = getSchema();
|
|
776
|
+
if (!schema2) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
const omit = Schema.omit("id");
|
|
780
|
+
return omit(schema2);
|
|
781
|
+
}, [
|
|
782
|
+
getSchema
|
|
783
|
+
]);
|
|
784
|
+
const handleSave = useCallback4((values) => {
|
|
785
|
+
if (!model || !space || state?.type !== "createRefPanel") {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
const schema2 = getSchema();
|
|
789
|
+
if (schema2) {
|
|
790
|
+
const obj = space.db.add(live(schema2, values));
|
|
791
|
+
state.onCreate?.(obj);
|
|
792
|
+
}
|
|
793
|
+
void modals.close();
|
|
749
794
|
}, [
|
|
750
795
|
model,
|
|
751
796
|
modals,
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
handleClose,
|
|
755
|
-
themeMode
|
|
797
|
+
space,
|
|
798
|
+
state
|
|
756
799
|
]);
|
|
757
|
-
const
|
|
758
|
-
if (model
|
|
759
|
-
|
|
760
|
-
const { col } = cell;
|
|
761
|
-
const field = model.projection.fields[col];
|
|
762
|
-
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
763
|
-
if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
|
|
764
|
-
const value2 = model.getCellData(cell);
|
|
765
|
-
if (value2 !== void 0) {
|
|
766
|
-
const options = fieldProjection2.props.options || [];
|
|
767
|
-
if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
|
|
768
|
-
const tagItems = value2.split(",").map((id) => {
|
|
769
|
-
const option = options.find((o) => o.id === id);
|
|
770
|
-
if (option) {
|
|
771
|
-
return {
|
|
772
|
-
id,
|
|
773
|
-
label: option.title,
|
|
774
|
-
hue: option.color
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
return void 0;
|
|
778
|
-
}).filter((item) => item !== void 0);
|
|
779
|
-
return createLinks(tagItems);
|
|
780
|
-
} else {
|
|
781
|
-
const option = options.find((o) => o.id === value2);
|
|
782
|
-
if (option) {
|
|
783
|
-
const tagItem = {
|
|
784
|
-
id: value2,
|
|
785
|
-
label: option.title,
|
|
786
|
-
hue: option.color
|
|
787
|
-
};
|
|
788
|
-
return createLinks([
|
|
789
|
-
tagItem
|
|
790
|
-
]);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
return "";
|
|
795
|
-
}
|
|
796
|
-
const value = model.getCellData(cell);
|
|
797
|
-
return value !== void 0 ? String(value) : "";
|
|
800
|
+
const handleCancel = useCallback4(() => {
|
|
801
|
+
if (model) {
|
|
802
|
+
modals.close();
|
|
798
803
|
}
|
|
799
804
|
}, [
|
|
800
|
-
|
|
801
|
-
editing
|
|
805
|
+
modals
|
|
802
806
|
]);
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
807
|
+
if (!model?.projection) {
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
811
|
+
modal: false,
|
|
812
|
+
open: state?.type === "createRefPanel" && !!schema,
|
|
813
|
+
onOpenChange: (nextOpen) => {
|
|
814
|
+
if (model && !nextOpen) {
|
|
815
|
+
return modals.close();
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
819
|
+
virtualRef: modals.trigger
|
|
820
|
+
}), /* @__PURE__ */ React6.createElement(Popover3.Portal, null, /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
821
|
+
classNames: "md:is-64",
|
|
822
|
+
"data-grid": gridId
|
|
823
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React6.createElement(Form2, {
|
|
824
|
+
schema,
|
|
825
|
+
values: state.initialValues ?? {},
|
|
826
|
+
onSave: handleSave,
|
|
827
|
+
onCancel: handleCancel
|
|
828
|
+
})), /* @__PURE__ */ React6.createElement(Popover3.Arrow, null))));
|
|
813
829
|
} finally {
|
|
814
830
|
_effect.f();
|
|
815
831
|
}
|
|
816
832
|
};
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
833
|
+
|
|
834
|
+
// src/components/Table/RowActionsMenu.tsx
|
|
835
|
+
import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
|
|
836
|
+
import React7 from "react";
|
|
837
|
+
import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
838
|
+
var RowActionsMenu = ({ model, modals }) => {
|
|
839
|
+
var _effect = _useSignals7();
|
|
840
|
+
try {
|
|
841
|
+
const { t } = useTranslation2(translationKey);
|
|
842
|
+
const hasSelection = model.selection.hasSelection.value;
|
|
843
|
+
const state = modals.state.value;
|
|
844
|
+
if (state?.type !== "row") {
|
|
845
|
+
return null;
|
|
823
846
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
847
|
+
return /* @__PURE__ */ React7.createElement(DropdownMenu2.Root, {
|
|
848
|
+
modal: false,
|
|
849
|
+
open: true,
|
|
850
|
+
onOpenChange: modals.close
|
|
851
|
+
}, /* @__PURE__ */ React7.createElement(DropdownMenu2.VirtualTrigger, {
|
|
852
|
+
virtualRef: modals.trigger
|
|
853
|
+
}), /* @__PURE__ */ React7.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React7.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
854
|
+
"data-testid": "row-menu-delete",
|
|
855
|
+
onClick: () => model.deleteRow(state.rowIndex)
|
|
856
|
+
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
857
|
+
key: action.id,
|
|
858
|
+
"data-testid": `row-action-${action.id}`,
|
|
859
|
+
onClick: () => {
|
|
860
|
+
modals.close();
|
|
861
|
+
model.handleRowAction(action.id, state.rowIndex);
|
|
862
|
+
}
|
|
863
|
+
}, toLocalizedString(action.label, t)))), /* @__PURE__ */ React7.createElement(DropdownMenu2.Arrow, null)));
|
|
864
|
+
} finally {
|
|
865
|
+
_effect.f();
|
|
838
866
|
}
|
|
839
|
-
return shift ? -1 : 1;
|
|
840
867
|
};
|
|
841
868
|
|
|
842
869
|
// src/components/Table/Table.tsx
|
|
843
|
-
var
|
|
870
|
+
var columnDefault = {
|
|
871
|
+
grid: {
|
|
872
|
+
minSize: 80,
|
|
873
|
+
maxSize: 640
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var rowDefault = {
|
|
877
|
+
frozenRowsStart: {
|
|
878
|
+
readonly: true,
|
|
879
|
+
focusUnfurl: false
|
|
880
|
+
}
|
|
881
|
+
};
|
|
844
882
|
var TableRoot = ({ children, role = "article" }) => {
|
|
845
883
|
var _effect = _useSignals8();
|
|
846
884
|
try {
|
|
@@ -864,14 +902,19 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
864
902
|
try {
|
|
865
903
|
const [dxGrid, setDxGrid] = useState4(null);
|
|
866
904
|
const { hasAttention } = useAttention(model?.id ?? "table");
|
|
867
|
-
const { t } = useTranslation3(translationKey);
|
|
868
905
|
const modals = useMemo5(() => new ModalController(), []);
|
|
869
906
|
const draftRowCount = model?.getDraftRowCount() ?? 0;
|
|
907
|
+
const handleSave = useCallback5(() => {
|
|
908
|
+
dxGrid?.updateCells(true);
|
|
909
|
+
dxGrid?.requestUpdate();
|
|
910
|
+
}, [
|
|
911
|
+
dxGrid
|
|
912
|
+
]);
|
|
870
913
|
const frozen = useMemo5(() => {
|
|
871
914
|
const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
|
|
872
915
|
return {
|
|
873
916
|
frozenRowsStart: 1,
|
|
874
|
-
frozenRowsEnd: draftRowCount,
|
|
917
|
+
frozenRowsEnd: Math.max(1, draftRowCount),
|
|
875
918
|
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
876
919
|
frozenColsEnd: noActionColumn ? 0 : 1
|
|
877
920
|
};
|
|
@@ -882,7 +925,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
882
925
|
const getCells = useCallback5((range, plane) => presentation?.getCells(range, plane) ?? {}, [
|
|
883
926
|
presentation
|
|
884
927
|
]);
|
|
885
|
-
|
|
928
|
+
useEffect3(() => {
|
|
886
929
|
if (!presentation || !dxGrid) {
|
|
887
930
|
return;
|
|
888
931
|
}
|
|
@@ -892,6 +935,30 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
892
935
|
dxGrid,
|
|
893
936
|
getCells
|
|
894
937
|
]);
|
|
938
|
+
const handleInsertRowResult = useCallback5((insertResult) => {
|
|
939
|
+
if (insertResult === "draft") {
|
|
940
|
+
requestAnimationFrame(() => {
|
|
941
|
+
dxGrid?.setFocus({
|
|
942
|
+
plane: "frozenRowsEnd",
|
|
943
|
+
col: 0,
|
|
944
|
+
row: 0
|
|
945
|
+
});
|
|
946
|
+
dxGrid?.refocus();
|
|
947
|
+
});
|
|
948
|
+
} else {
|
|
949
|
+
requestAnimationFrame(() => {
|
|
950
|
+
dxGrid?.setFocus({
|
|
951
|
+
plane: "grid",
|
|
952
|
+
col: 0,
|
|
953
|
+
row: model ? model.getRowCount() - 1 : 0
|
|
954
|
+
});
|
|
955
|
+
dxGrid?.refocus();
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}, [
|
|
959
|
+
model,
|
|
960
|
+
dxGrid
|
|
961
|
+
]);
|
|
895
962
|
useImperativeHandle(forwardedRef, () => {
|
|
896
963
|
if (!presentation || !dxGrid) {
|
|
897
964
|
return {};
|
|
@@ -904,18 +971,38 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
904
971
|
dxGrid.updateCells(true);
|
|
905
972
|
dxGrid.requestUpdate();
|
|
906
973
|
}
|
|
907
|
-
}
|
|
974
|
+
},
|
|
975
|
+
handleInsertRowResult
|
|
908
976
|
};
|
|
909
977
|
}, [
|
|
910
978
|
presentation,
|
|
979
|
+
dxGrid,
|
|
980
|
+
model
|
|
981
|
+
]);
|
|
982
|
+
const handleSaveDraftRow = useCallback5((rowIndex = 0) => {
|
|
983
|
+
if (model && dxGrid) {
|
|
984
|
+
const didCommitSuccessfully = model.commitDraftRow(rowIndex);
|
|
985
|
+
if (didCommitSuccessfully) {
|
|
986
|
+
requestAnimationFrame(() => {
|
|
987
|
+
dxGrid.scrollToEndRow();
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}, [
|
|
992
|
+
model,
|
|
911
993
|
dxGrid
|
|
912
994
|
]);
|
|
913
995
|
const handleGridClick = useCallback5((event) => {
|
|
914
|
-
const
|
|
915
|
-
if (
|
|
996
|
+
const cell = closestCell(event.target);
|
|
997
|
+
if (cell) {
|
|
998
|
+
const { row: rowIndex, plane } = cell;
|
|
916
999
|
if (onRowClick) {
|
|
917
|
-
|
|
918
|
-
|
|
1000
|
+
if (plane === "grid") {
|
|
1001
|
+
const row = model?.getRowAt(rowIndex);
|
|
1002
|
+
row && onRowClick(row);
|
|
1003
|
+
} else {
|
|
1004
|
+
onRowClick(cell);
|
|
1005
|
+
}
|
|
919
1006
|
}
|
|
920
1007
|
if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
|
|
921
1008
|
model.selection.toggleSelectionForRowIndex(rowIndex);
|
|
@@ -951,14 +1038,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
951
1038
|
break;
|
|
952
1039
|
}
|
|
953
1040
|
case "saveDraftRow": {
|
|
954
|
-
|
|
955
|
-
const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
|
|
956
|
-
if (dxGrid && didCommitSuccessfully) {
|
|
957
|
-
requestAnimationFrame(() => {
|
|
958
|
-
dxGrid.scrollToEndRow();
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
}
|
|
1041
|
+
handleSaveDraftRow();
|
|
962
1042
|
break;
|
|
963
1043
|
}
|
|
964
1044
|
}
|
|
@@ -997,29 +1077,20 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
997
1077
|
modals,
|
|
998
1078
|
dxGrid
|
|
999
1079
|
]);
|
|
1000
|
-
const handleFocus = useCallback5((increment, delta) => {
|
|
1001
|
-
if (dxGrid) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
return;
|
|
1010
|
-
}
|
|
1011
|
-
if (model && cell.row === model.getRowCount() - 1) {
|
|
1012
|
-
model.insertRow();
|
|
1013
|
-
if (dxGrid) {
|
|
1014
|
-
requestAnimationFrame(() => {
|
|
1015
|
-
dxGrid?.scrollToRow(cell.row + 1);
|
|
1016
|
-
dxGrid?.refocus("row", 1);
|
|
1017
|
-
});
|
|
1080
|
+
const handleFocus = useCallback5((increment, delta, cell) => {
|
|
1081
|
+
if (dxGrid && model) {
|
|
1082
|
+
if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1) {
|
|
1083
|
+
handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
|
|
1084
|
+
} else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
|
|
1085
|
+
handleSaveDraftRow(cell.row);
|
|
1086
|
+
handleInsertRowResult(model.insertRow());
|
|
1087
|
+
} else {
|
|
1088
|
+
dxGrid.refocus(increment, delta);
|
|
1018
1089
|
}
|
|
1019
1090
|
}
|
|
1020
1091
|
}, [
|
|
1021
|
-
|
|
1022
|
-
|
|
1092
|
+
dxGrid,
|
|
1093
|
+
model
|
|
1023
1094
|
]);
|
|
1024
1095
|
const handleKeyDown = useCallback5((event) => {
|
|
1025
1096
|
if (!model?.features.dataEditable) {
|
|
@@ -1029,6 +1100,48 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
1029
1100
|
if (!model || !cell) {
|
|
1030
1101
|
return;
|
|
1031
1102
|
}
|
|
1103
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1104
|
+
switch (event.key) {
|
|
1105
|
+
case "c": {
|
|
1106
|
+
try {
|
|
1107
|
+
const cellData = model.getCellData(cell);
|
|
1108
|
+
const textContent = cellData?.toString() ?? "";
|
|
1109
|
+
void navigator.clipboard.writeText(textContent);
|
|
1110
|
+
event.preventDefault();
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
console.warn("Failed to copy cell content:", error);
|
|
1113
|
+
}
|
|
1114
|
+
break;
|
|
1115
|
+
}
|
|
1116
|
+
case "v": {
|
|
1117
|
+
event.preventDefault();
|
|
1118
|
+
void navigator.clipboard.readText().then((clipboardText) => {
|
|
1119
|
+
try {
|
|
1120
|
+
model.setCellData(cell, clipboardText);
|
|
1121
|
+
handleSave();
|
|
1122
|
+
} catch {
|
|
1123
|
+
const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
|
|
1124
|
+
if (cellElement) {
|
|
1125
|
+
const rect = cellElement.getBoundingClientRect();
|
|
1126
|
+
const editRequest = new DxEditRequest({
|
|
1127
|
+
cellIndex: `${cell.plane},${cell.col},${cell.row}`,
|
|
1128
|
+
cellBox: {
|
|
1129
|
+
insetInlineStart: rect.left,
|
|
1130
|
+
insetBlockStart: rect.top,
|
|
1131
|
+
inlineSize: rect.width,
|
|
1132
|
+
blockSize: rect.height
|
|
1133
|
+
},
|
|
1134
|
+
cellElement,
|
|
1135
|
+
initialContent: clipboardText
|
|
1136
|
+
});
|
|
1137
|
+
cellElement.dispatchEvent(editRequest);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1032
1145
|
switch (event.key) {
|
|
1033
1146
|
case "Backspace":
|
|
1034
1147
|
case "Delete": {
|
|
@@ -1041,7 +1154,9 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
1041
1154
|
}
|
|
1042
1155
|
}
|
|
1043
1156
|
}, [
|
|
1044
|
-
model
|
|
1157
|
+
model,
|
|
1158
|
+
dxGrid,
|
|
1159
|
+
handleSave
|
|
1045
1160
|
]);
|
|
1046
1161
|
const handleAxisResize = useCallback5((event) => {
|
|
1047
1162
|
if (event.axis === "col") {
|
|
@@ -1068,59 +1183,6 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
1068
1183
|
model,
|
|
1069
1184
|
dxGrid
|
|
1070
1185
|
]);
|
|
1071
|
-
const handleQuery = useCallback5(async ({ field, props }, text) => {
|
|
1072
|
-
if (model && props.referenceSchema && field.referencePath) {
|
|
1073
|
-
const space = getSpace2(model.view);
|
|
1074
|
-
invariant3(space, void 0, {
|
|
1075
|
-
F: __dxlog_file3,
|
|
1076
|
-
L: 330,
|
|
1077
|
-
S: void 0,
|
|
1078
|
-
A: [
|
|
1079
|
-
"space",
|
|
1080
|
-
""
|
|
1081
|
-
]
|
|
1082
|
-
});
|
|
1083
|
-
let schema2;
|
|
1084
|
-
if (client) {
|
|
1085
|
-
schema2 = client.graph.schemaRegistry.getSchema(props.referenceSchema);
|
|
1086
|
-
}
|
|
1087
|
-
if (!schema2) {
|
|
1088
|
-
schema2 = space.db.schemaRegistry.getSchema(props.referenceSchema);
|
|
1089
|
-
}
|
|
1090
|
-
if (schema2) {
|
|
1091
|
-
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
1092
|
-
const options = objects.map((obj) => {
|
|
1093
|
-
const value = getValue(obj, field.referencePath);
|
|
1094
|
-
if (!value || typeof value !== "string") {
|
|
1095
|
-
return void 0;
|
|
1096
|
-
}
|
|
1097
|
-
return {
|
|
1098
|
-
label: value,
|
|
1099
|
-
data: obj
|
|
1100
|
-
};
|
|
1101
|
-
}).filter(isNotFalsy);
|
|
1102
|
-
return [
|
|
1103
|
-
...options,
|
|
1104
|
-
{
|
|
1105
|
-
label: t("create new object label", {
|
|
1106
|
-
text
|
|
1107
|
-
}),
|
|
1108
|
-
data: createOption(text)
|
|
1109
|
-
}
|
|
1110
|
-
];
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
return [];
|
|
1114
|
-
}, [
|
|
1115
|
-
model,
|
|
1116
|
-
client,
|
|
1117
|
-
t
|
|
1118
|
-
]);
|
|
1119
|
-
const handleSave = useCallback5(() => {
|
|
1120
|
-
dxGrid?.updateCells(true);
|
|
1121
|
-
}, [
|
|
1122
|
-
dxGrid
|
|
1123
|
-
]);
|
|
1124
1186
|
if (!model || !modals) {
|
|
1125
1187
|
return /* @__PURE__ */ React8.createElement("span", {
|
|
1126
1188
|
role: "none",
|
|
@@ -1133,14 +1195,15 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
1133
1195
|
model,
|
|
1134
1196
|
modals,
|
|
1135
1197
|
schema,
|
|
1136
|
-
onEnter: handleEnter,
|
|
1137
1198
|
onFocus: handleFocus,
|
|
1138
|
-
|
|
1139
|
-
|
|
1199
|
+
onSave: handleSave,
|
|
1200
|
+
client
|
|
1140
1201
|
}), /* @__PURE__ */ React8.createElement(Grid.Content, {
|
|
1141
1202
|
className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
1142
1203
|
frozen,
|
|
1143
1204
|
columns: model.columnMeta.value,
|
|
1205
|
+
columnDefault,
|
|
1206
|
+
rowDefault,
|
|
1144
1207
|
limitRows: model.getRowCount() ?? 0,
|
|
1145
1208
|
limitColumns: model.projection.fields.length,
|
|
1146
1209
|
overscroll: "trap",
|
|
@@ -1174,7 +1237,7 @@ var Table = {
|
|
|
1174
1237
|
|
|
1175
1238
|
// src/components/Table/DynamicTable.tsx
|
|
1176
1239
|
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
1177
|
-
import React9, {
|
|
1240
|
+
import React9, { useCallback as useCallback6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
1178
1241
|
import { useDefaultValue } from "@dxos/react-ui";
|
|
1179
1242
|
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1180
1243
|
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
@@ -1254,7 +1317,7 @@ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking
|
|
|
1254
1317
|
import { Rx } from "@effect-rx/rx-react";
|
|
1255
1318
|
import React10, { useMemo as useMemo7 } from "react";
|
|
1256
1319
|
import { live as live2 } from "@dxos/live-object";
|
|
1257
|
-
import {
|
|
1320
|
+
import { MenuProvider, ToolbarMenu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
|
|
1258
1321
|
import { rxFromSignal } from "@dxos/react-ui-menu";
|
|
1259
1322
|
var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
|
|
1260
1323
|
const add = createMenuAction("add-row", onAdd, {
|
|
@@ -1341,7 +1404,6 @@ export {
|
|
|
1341
1404
|
TablePresentation,
|
|
1342
1405
|
TableToolbar,
|
|
1343
1406
|
cellClassesForRowSelection,
|
|
1344
|
-
createTable,
|
|
1345
1407
|
getBaseSchema,
|
|
1346
1408
|
makeDynamicTable,
|
|
1347
1409
|
narrowSchema,
|