@dxos/react-ui-table 0.8.3-staging.0fa589b → 0.8.4-main.28f8d3d
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-L2LSB6KV.mjs +18 -0
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs +1814 -0
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +728 -2104
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +123 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +3 -5
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +20 -0
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs +1815 -0
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +728 -2104
- 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 +124 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +3 -5
- 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 +4 -2
- 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 +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/{relations.stories.d.ts → Relations.stories.d.ts} +2 -2
- 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 +1 -0
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +2 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +2 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -7
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -40
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +13 -0
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +8 -7
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.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 +2 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +58 -21
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +10 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +4 -4
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts +3 -0
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/useTestTableModel.d.ts +41 -0
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +5 -6
- package/dist/types/src/translations.d.ts.map +1 -1
- 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 +8 -0
- package/dist/types/src/types/schema.d.ts.map +1 -0
- package/dist/types/src/util/dynamic-table.d.ts +3 -4
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts +15 -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/src/util/table.d.ts +9 -11
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +52 -40
- package/src/components/Table/ColumnActionsMenu.tsx +1 -1
- package/src/components/Table/ColumnSettings.tsx +15 -11
- package/src/components/Table/CreateRefPanel.tsx +6 -4
- package/src/components/Table/DynamicTable.stories.tsx +4 -3
- package/src/components/Table/DynamicTable.tsx +17 -10
- package/src/components/Table/{relations.stories.tsx → Relations.stories.tsx} +37 -37
- package/src/components/Table/RowActionsMenu.tsx +3 -3
- package/src/components/Table/Table.stories.tsx +109 -148
- package/src/components/Table/Table.tsx +95 -66
- package/src/components/TableCellEditor/CellValidationMessage.tsx +7 -2
- package/src/components/TableCellEditor/FormCellEditor.tsx +30 -21
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +27 -30
- package/src/components/TableCellEditor/TableCellEditor.tsx +88 -34
- package/src/components/TableCellEditor/extension.ts +2 -2
- package/src/components/TableToolbar/TableToolbar.tsx +2 -2
- package/src/components/testing.ts +7 -24
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAddRow.ts +36 -0
- package/src/hooks/useTableModel.ts +21 -17
- package/src/index.ts +1 -2
- package/src/model/modal-controller.ts +1 -1
- package/src/model/selection-model.ts +6 -3
- package/src/model/table-model.test.ts +8 -8
- package/src/model/table-model.ts +278 -86
- package/src/model/table-presentation.test.ts +8 -8
- package/src/model/table-presentation.ts +240 -135
- package/src/model/table-sorting.ts +11 -11
- package/src/playwright/playwright.config.ts +17 -0
- package/src/playwright/smoke.spec.ts +113 -20
- package/src/testing/index.ts +5 -0
- package/src/testing/useTestTableModel.ts +123 -0
- package/src/translations.ts +7 -5
- package/src/types/index.ts +2 -2
- package/src/types/schema.ts +16 -0
- package/src/util/dynamic-table.ts +20 -18
- package/src/util/schema.ts +1 -1
- package/src/util/table-buttons.ts +26 -2
- package/src/util/table-controls.ts +4 -1
- package/src/util/table.ts +37 -111
- package/dist/lib/browser/chunk-TL7CKQQV.mjs +0 -27
- package/dist/lib/browser/chunk-TL7CKQQV.mjs.map +0 -7
- package/dist/lib/node/chunk-O2VPBNS5.cjs +0 -50
- package/dist/lib/node/chunk-O2VPBNS5.cjs.map +0 -7
- package/dist/lib/node/index.cjs +0 -2739
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/types/index.cjs +0 -31
- package/dist/lib/node/types/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-GBT6GD4G.mjs +0 -29
- package/dist/lib/node-esm/chunk-GBT6GD4G.mjs.map +0 -7
- package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
- package/dist/types/src/types/table.d.ts +0 -56
- package/dist/types/src/types/table.d.ts.map +0 -1
- package/src/playwright/playwright.config.cts +0 -18
- package/src/types/table.ts +0 -27
|
@@ -1,1721 +1,95 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"create comment": "Create thread",
|
|
22
|
-
"column action sort descending": "Sort Descending",
|
|
23
|
-
"column action sort ascending": "Sort Ascending",
|
|
24
|
-
"column action clear sorting": "Clear Sorting",
|
|
25
|
-
"column action settings": "Column Settings",
|
|
26
|
-
"column action delete": "Delete Column",
|
|
27
|
-
"delete row label": "Delete row",
|
|
28
|
-
"bulk delete row label": "Delete selected rows",
|
|
29
|
-
"column deleted label": "Column deleted",
|
|
30
|
-
"new column button label": "Create column",
|
|
31
|
-
"create new object label": "Create new object \u201C{{text}}\u201D",
|
|
32
|
-
"save view label": "Save changes to view"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
// packages/ui/react-ui-table/src/components/Table/Table.tsx
|
|
39
|
-
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
40
|
-
import React8, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as useState3, useMemo as useMemo5, useEffect as useEffect3 } from "react";
|
|
41
|
-
import { getValue as getValue4 } from "@dxos/echo-schema";
|
|
42
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
43
|
-
import { Filter } from "@dxos/react-client/echo";
|
|
44
|
-
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
45
|
-
import { useAttention } from "@dxos/react-ui-attention";
|
|
46
|
-
import { closestCell, Grid, gridSeparatorInlineEnd, gridSeparatorBlockEnd } from "@dxos/react-ui-grid";
|
|
47
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
48
|
-
import { isNotFalsy, safeParseInt } from "@dxos/util";
|
|
49
|
-
|
|
50
|
-
// packages/ui/react-ui-table/src/components/Table/ColumnActionsMenu.tsx
|
|
51
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
52
|
-
import React from "react";
|
|
53
|
-
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
54
|
-
var ColumnActionsMenu = ({ model, modals }) => {
|
|
55
|
-
var _effect = _useSignals();
|
|
56
|
-
try {
|
|
57
|
-
const { t } = useTranslation(translationKey);
|
|
58
|
-
const state = modals.state.value;
|
|
59
|
-
if (state?.type !== "column") {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
const currentSort = model.sorting?.sorting;
|
|
63
|
-
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
64
|
-
return /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
|
|
65
|
-
modal: false,
|
|
66
|
-
open: true,
|
|
67
|
-
onOpenChange: modals.close
|
|
68
|
-
}, /* @__PURE__ */ React.createElement(DropdownMenu.VirtualTrigger, {
|
|
69
|
-
virtualRef: modals.trigger
|
|
70
|
-
}), /* @__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, {
|
|
71
|
-
"data-testid": "column-sort-descending",
|
|
72
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
73
|
-
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
74
|
-
"data-testid": "column-sort-ascending",
|
|
75
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
76
|
-
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
77
|
-
"data-testid": "column-clear-sort",
|
|
78
|
-
onClick: () => model.sorting?.clearSort()
|
|
79
|
-
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
80
|
-
"data-testid": "column-delete",
|
|
81
|
-
onClick: () => model.deleteColumn(state.fieldId)
|
|
82
|
-
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
83
|
-
"data-testid": "column-settings",
|
|
84
|
-
onClick: () => modals.openColumnSettings()
|
|
85
|
-
}, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
|
|
86
|
-
} finally {
|
|
87
|
-
_effect.f();
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// packages/ui/react-ui-table/src/components/Table/ColumnSettings.tsx
|
|
92
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
93
|
-
import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
94
|
-
import { Popover } from "@dxos/react-ui";
|
|
95
|
-
import { FieldEditor } from "@dxos/react-ui-form";
|
|
96
|
-
var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
97
|
-
var _effect = _useSignals2();
|
|
98
|
-
try {
|
|
99
|
-
const [newField, setNewField] = useState();
|
|
100
|
-
const state = modals.state.value;
|
|
101
|
-
const space = model?.space;
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
104
|
-
setNewField(model.projection.createFieldProjection());
|
|
105
|
-
requestAnimationFrame(() => {
|
|
106
|
-
onNewColumn();
|
|
107
|
-
});
|
|
108
|
-
} else {
|
|
109
|
-
setNewField(void 0);
|
|
110
|
-
}
|
|
111
|
-
}, [
|
|
112
|
-
model?.projection,
|
|
113
|
-
state
|
|
114
|
-
]);
|
|
115
|
-
const existingField = useMemo(() => {
|
|
116
|
-
if (state?.type === "columnSettings") {
|
|
117
|
-
const { mode } = state;
|
|
118
|
-
if (mode.type === "edit") {
|
|
119
|
-
return model?.view?.fields.find((f) => f.id === mode.fieldId);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return void 0;
|
|
123
|
-
}, [
|
|
124
|
-
model?.view?.fields,
|
|
125
|
-
state
|
|
126
|
-
]);
|
|
127
|
-
const field = existingField ?? newField;
|
|
128
|
-
const handleSave = useCallback(() => {
|
|
129
|
-
modals.close();
|
|
130
|
-
}, [
|
|
131
|
-
modals
|
|
132
|
-
]);
|
|
133
|
-
const handleCancel = useCallback(() => {
|
|
134
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
135
|
-
model?.projection?.deleteFieldProjection(newField.id);
|
|
136
|
-
}
|
|
137
|
-
}, [
|
|
138
|
-
model?.projection,
|
|
139
|
-
state,
|
|
140
|
-
newField
|
|
141
|
-
]);
|
|
142
|
-
if (!model?.view || !model.projection || !field) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
146
|
-
modal: false,
|
|
147
|
-
open: state?.type === "columnSettings"
|
|
148
|
-
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
149
|
-
virtualRef: modals.trigger
|
|
150
|
-
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
151
|
-
classNames: "md:is-64"
|
|
152
|
-
}, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
|
|
153
|
-
view: model.view,
|
|
154
|
-
projection: model.projection,
|
|
155
|
-
field,
|
|
156
|
-
registry: space?.db.schemaRegistry,
|
|
157
|
-
onSave: handleSave,
|
|
158
|
-
onCancel: handleCancel
|
|
159
|
-
})), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
|
|
160
|
-
} finally {
|
|
161
|
-
_effect.f();
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
// packages/ui/react-ui-table/src/components/Table/CreateRefPanel.tsx
|
|
166
|
-
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
167
|
-
import { Schema } from "effect";
|
|
168
|
-
import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
169
|
-
import { live } from "@dxos/react-client/echo";
|
|
170
|
-
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
171
|
-
import { Form } from "@dxos/react-ui-form";
|
|
172
|
-
import { useGridContext } from "@dxos/react-ui-grid";
|
|
173
|
-
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
174
|
-
var _effect = _useSignals3();
|
|
175
|
-
try {
|
|
176
|
-
const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
|
|
177
|
-
const space = model?.space;
|
|
178
|
-
const state = modals.state.value;
|
|
179
|
-
const schema = useMemo2(() => {
|
|
180
|
-
if (!space || state?.type !== "createRefPanel") {
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
184
|
-
typename: state.typename
|
|
185
|
-
}).runSync();
|
|
186
|
-
if (schema2) {
|
|
187
|
-
const omit = Schema.omit("id");
|
|
188
|
-
return omit(schema2);
|
|
189
|
-
}
|
|
190
|
-
}, [
|
|
191
|
-
space,
|
|
192
|
-
state
|
|
193
|
-
]);
|
|
194
|
-
const handleSave = useCallback2((values) => {
|
|
195
|
-
if (!model || !space || state?.type !== "createRefPanel") {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
199
|
-
typename: state.typename
|
|
200
|
-
}).runSync();
|
|
201
|
-
if (schema2) {
|
|
202
|
-
const obj = space.db.add(live(schema2, values));
|
|
203
|
-
state.onCreate?.(obj);
|
|
204
|
-
}
|
|
205
|
-
void modals.close();
|
|
206
|
-
}, [
|
|
207
|
-
modals,
|
|
208
|
-
space,
|
|
209
|
-
state
|
|
210
|
-
]);
|
|
211
|
-
const handleCancel = useCallback2(() => {
|
|
212
|
-
if (model) {
|
|
213
|
-
modals.close();
|
|
214
|
-
}
|
|
215
|
-
}, [
|
|
216
|
-
modals
|
|
217
|
-
]);
|
|
218
|
-
if (!model?.view || !model.projection) {
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
return /* @__PURE__ */ React3.createElement(Popover2.Root, {
|
|
222
|
-
modal: false,
|
|
223
|
-
open: state?.type === "createRefPanel" && !!schema,
|
|
224
|
-
onOpenChange: (nextOpen) => {
|
|
225
|
-
if (model && !nextOpen) {
|
|
226
|
-
return modals.close();
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.VirtualTrigger, {
|
|
230
|
-
virtualRef: modals.trigger
|
|
231
|
-
}), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
|
|
232
|
-
classNames: "md:is-64",
|
|
233
|
-
"data-grid": gridId
|
|
234
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
|
|
235
|
-
schema,
|
|
236
|
-
values: state.initialValues ?? {},
|
|
237
|
-
onSave: handleSave,
|
|
238
|
-
onCancel: handleCancel
|
|
239
|
-
})), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null))));
|
|
240
|
-
} finally {
|
|
241
|
-
_effect.f();
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
// packages/ui/react-ui-table/src/components/Table/RowActionsMenu.tsx
|
|
246
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
247
|
-
import React4 from "react";
|
|
248
|
-
import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
249
|
-
var RowActionsMenu = ({ model, modals }) => {
|
|
250
|
-
var _effect = _useSignals4();
|
|
251
|
-
try {
|
|
252
|
-
const { t } = useTranslation2(translationKey);
|
|
253
|
-
const hasSelection = model.selection.hasSelection.value;
|
|
254
|
-
const state = modals.state.value;
|
|
255
|
-
if (state?.type !== "row") {
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenu2.Root, {
|
|
259
|
-
modal: false,
|
|
260
|
-
open: true,
|
|
261
|
-
onOpenChange: modals.close
|
|
262
|
-
}, /* @__PURE__ */ React4.createElement(DropdownMenu2.VirtualTrigger, {
|
|
263
|
-
virtualRef: modals.trigger
|
|
264
|
-
}), /* @__PURE__ */ React4.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
265
|
-
"data-testid": "row-menu-delete",
|
|
266
|
-
onClick: () => model.deleteRow(state.rowIndex)
|
|
267
|
-
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
268
|
-
key: action.id,
|
|
269
|
-
"data-testid": `row-action-${action.id}`,
|
|
270
|
-
onClick: () => {
|
|
271
|
-
modals.close();
|
|
272
|
-
model.handleRowAction(action.id, state.rowIndex);
|
|
273
|
-
}
|
|
274
|
-
}, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu2.Arrow, null)));
|
|
275
|
-
} finally {
|
|
276
|
-
_effect.f();
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// packages/ui/react-ui-table/src/model/table-model.ts
|
|
281
|
-
import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
|
|
282
|
-
import { Resource as Resource2 } from "@dxos/context";
|
|
283
|
-
import { FormatEnum as FormatEnum3, getValue as getValue2, setValue, getSnapshot, getSchema } from "@dxos/echo-schema";
|
|
284
|
-
import { invariant } from "@dxos/invariant";
|
|
285
|
-
import { isLiveObject, makeRef } from "@dxos/live-object";
|
|
286
|
-
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
287
|
-
import { validateSchema } from "@dxos/schema";
|
|
288
|
-
|
|
289
|
-
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
290
|
-
import { computed, effect, signal } from "@preact/signals-core";
|
|
291
|
-
import { Resource } from "@dxos/context";
|
|
292
|
-
|
|
293
|
-
// packages/ui/react-ui-table/src/util/dynamic-table.ts
|
|
294
|
-
import { Obj, Ref } from "@dxos/echo";
|
|
295
|
-
import { getTypename, toJsonSchema } from "@dxos/echo-schema";
|
|
296
|
-
import { createView, getSchemaFromPropertyDefinitions, ViewProjection } from "@dxos/schema";
|
|
297
|
-
var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
|
|
298
|
-
if (typename && properties) {
|
|
299
|
-
const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
|
|
300
|
-
return {
|
|
301
|
-
typename: schema2.typename,
|
|
302
|
-
jsonSchema: schema2.jsonSchema
|
|
303
|
-
};
|
|
304
|
-
} else if (schema) {
|
|
305
|
-
return {
|
|
306
|
-
typename: getTypename(schema),
|
|
307
|
-
jsonSchema: toJsonSchema(schema)
|
|
308
|
-
};
|
|
309
|
-
} else if (typename && jsonSchema) {
|
|
310
|
-
return {
|
|
311
|
-
typename,
|
|
312
|
-
jsonSchema
|
|
313
|
-
};
|
|
314
|
-
} else {
|
|
315
|
-
throw new Error("invalid properties");
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
|
|
319
|
-
const view = createView({
|
|
320
|
-
name: "dynamic-table",
|
|
321
|
-
typename,
|
|
322
|
-
jsonSchema,
|
|
323
|
-
...properties && {
|
|
324
|
-
fields: properties.map((property) => property.name)
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
const table = Obj.make(TableType, {
|
|
328
|
-
name: "dynamic-table",
|
|
329
|
-
view: Ref.make(view)
|
|
330
|
-
});
|
|
331
|
-
const projection = new ViewProjection(jsonSchema, view);
|
|
332
|
-
if (properties && view.fields) {
|
|
333
|
-
setProperties(view, projection, properties);
|
|
334
|
-
}
|
|
335
|
-
return {
|
|
336
|
-
table,
|
|
337
|
-
projection
|
|
338
|
-
};
|
|
339
|
-
};
|
|
340
|
-
var setProperties = (view, projection, properties) => {
|
|
341
|
-
for (const property of properties) {
|
|
342
|
-
const field = view.fields.find((field2) => field2.path === property.name);
|
|
343
|
-
if (field) {
|
|
344
|
-
if (property.size !== void 0) {
|
|
345
|
-
field.size = property.size;
|
|
346
|
-
}
|
|
347
|
-
if (property.title !== void 0) {
|
|
348
|
-
const fieldProjection = projection.getFieldProjection(field.id);
|
|
349
|
-
projection.setFieldProjection({
|
|
350
|
-
...fieldProjection,
|
|
351
|
-
props: {
|
|
352
|
-
...fieldProjection.props,
|
|
353
|
-
title: property.title
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
if (property.sort) {
|
|
358
|
-
const fieldId = field.id;
|
|
359
|
-
view.query.sort = [
|
|
360
|
-
{
|
|
361
|
-
fieldId,
|
|
362
|
-
direction: property.sort
|
|
363
|
-
}
|
|
364
|
-
];
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
// packages/ui/react-ui-table/src/util/signals.ts
|
|
371
|
-
var touch = (value) => value;
|
|
372
|
-
|
|
373
|
-
// packages/ui/react-ui-table/src/util/table.ts
|
|
374
|
-
import { Schema as Schema2 } from "effect";
|
|
375
|
-
import { Format, FormatEnum, Ref as Ref2, TypedObject, TypeEnum } from "@dxos/echo-schema";
|
|
376
|
-
import { PublicKey } from "@dxos/react-client";
|
|
377
|
-
import { live as live2 } from "@dxos/react-client/echo";
|
|
378
|
-
import { createFieldId, createView as createView2, getSchemaProperties, ViewProjection as ViewProjection2 } from "@dxos/schema";
|
|
379
|
-
var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
|
|
380
|
-
if (typename) {
|
|
381
|
-
const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
|
|
382
|
-
if (!schema) {
|
|
383
|
-
throw new Error(`Schema not found: ${typename}`);
|
|
384
|
-
}
|
|
385
|
-
const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
|
|
386
|
-
table.view = Ref2.make(createView2({
|
|
387
|
-
// TODO(ZaymonFC): Don't hardcode name?
|
|
388
|
-
name: "View",
|
|
389
|
-
typename: schema.typename,
|
|
390
|
-
jsonSchema: schema.jsonSchema,
|
|
391
|
-
fields
|
|
392
|
-
}));
|
|
393
|
-
return schema;
|
|
394
|
-
} else {
|
|
395
|
-
const [schema] = await space.db.schemaRegistry.register([
|
|
396
|
-
createContactSchema()
|
|
397
|
-
]);
|
|
398
|
-
const fields = ContactFields;
|
|
399
|
-
table.view = Ref2.make(createView2({
|
|
400
|
-
name: "View",
|
|
401
|
-
typename: schema.typename,
|
|
402
|
-
jsonSchema: schema.jsonSchema,
|
|
403
|
-
fields
|
|
404
|
-
}));
|
|
405
|
-
createProjection(schema, table.view.target);
|
|
406
|
-
if (initialRow) {
|
|
407
|
-
space.db.add(live2(schema, {}));
|
|
408
|
-
}
|
|
409
|
-
return schema;
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
var createContactSchema = () => TypedObject({
|
|
413
|
-
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
414
|
-
version: "0.1.0"
|
|
415
|
-
})({
|
|
416
|
-
name: Schema2.optional(Schema2.String).annotations({
|
|
417
|
-
title: "Name"
|
|
418
|
-
}),
|
|
419
|
-
active: Schema2.optional(Schema2.Boolean).annotations({
|
|
420
|
-
title: "Active"
|
|
421
|
-
}),
|
|
422
|
-
email: Schema2.optional(Format.Email),
|
|
423
|
-
salary: Schema2.optional(Format.Currency()).annotations({
|
|
424
|
-
title: "Salary"
|
|
425
|
-
})
|
|
426
|
-
});
|
|
427
|
-
var ContactFields = [
|
|
428
|
-
"name",
|
|
429
|
-
"email",
|
|
430
|
-
"salary",
|
|
431
|
-
"active"
|
|
432
|
-
];
|
|
433
|
-
var createProjection = (schema, view) => {
|
|
434
|
-
const projection = new ViewProjection2(schema.jsonSchema, view);
|
|
435
|
-
projection.setFieldProjection({
|
|
436
|
-
field: {
|
|
437
|
-
id: view.fields.find((f) => f.path === "salary").id,
|
|
438
|
-
path: "salary",
|
|
439
|
-
size: 150
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
projection.setFieldProjection({
|
|
443
|
-
field: {
|
|
444
|
-
id: view.fields.find((f) => f.path === "active").id,
|
|
445
|
-
path: "active",
|
|
446
|
-
size: 100
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
projection.setFieldProjection({
|
|
450
|
-
field: {
|
|
451
|
-
id: createFieldId(),
|
|
452
|
-
path: "manager",
|
|
453
|
-
referencePath: "name"
|
|
454
|
-
},
|
|
455
|
-
props: {
|
|
456
|
-
property: "manager",
|
|
457
|
-
type: TypeEnum.Ref,
|
|
458
|
-
format: FormatEnum.Ref,
|
|
459
|
-
referenceSchema: schema.typename,
|
|
460
|
-
title: "Manager"
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
return projection;
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
// packages/ui/react-ui-table/src/util/table-buttons.ts
|
|
467
|
-
var BUTTON_IDENTIFIERS = {
|
|
468
|
-
columnSettings: "data-table-column-settings-button",
|
|
469
|
-
newColumn: "data-table-new-column-button",
|
|
470
|
-
referencedCell: "data-table-ref-cell-button",
|
|
471
|
-
rowMenu: "data-table-row-menu-button",
|
|
472
|
-
sort: "data-table-sort-button"
|
|
473
|
-
};
|
|
474
|
-
var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
|
|
475
|
-
const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
476
|
-
const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
|
|
477
|
-
return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? "disabled" : ""}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
478
|
-
};
|
|
479
|
-
var addColumnButton = {
|
|
480
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
481
|
-
icon: "ph--plus--regular",
|
|
482
|
-
render: ({ disabled }) => {
|
|
483
|
-
return createButton({
|
|
484
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
485
|
-
icon: addColumnButton.icon,
|
|
486
|
-
disabled,
|
|
487
|
-
data: {},
|
|
488
|
-
testId: "table-new-column-button"
|
|
489
|
-
});
|
|
490
|
-
},
|
|
491
|
-
getData: (_el) => ({
|
|
492
|
-
type: "newColumn"
|
|
493
|
-
})
|
|
494
|
-
};
|
|
495
|
-
var columnSettingsButton = {
|
|
496
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
497
|
-
icon: "ph--caret-down--regular",
|
|
498
|
-
render: ({ fieldId }) => {
|
|
499
|
-
return createButton({
|
|
500
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
501
|
-
icon: columnSettingsButton.icon,
|
|
502
|
-
data: {
|
|
503
|
-
"data-field-id": fieldId
|
|
504
|
-
},
|
|
505
|
-
testId: "table-column-settings-button"
|
|
506
|
-
});
|
|
507
|
-
},
|
|
508
|
-
getData: (el) => ({
|
|
509
|
-
type: "columnSettings",
|
|
510
|
-
fieldId: el.getAttribute("data-field-id")
|
|
511
|
-
})
|
|
512
|
-
};
|
|
513
|
-
var rowMenuButton = {
|
|
514
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
515
|
-
icon: "ph--dots-three--regular",
|
|
516
|
-
render: ({ rowIndex }) => {
|
|
517
|
-
return createButton({
|
|
518
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
519
|
-
icon: rowMenuButton.icon,
|
|
520
|
-
data: {
|
|
521
|
-
"data-row-index": rowIndex.toString()
|
|
522
|
-
},
|
|
523
|
-
testId: "table-row-menu-button"
|
|
524
|
-
});
|
|
525
|
-
},
|
|
526
|
-
getData: (el) => ({
|
|
527
|
-
type: "rowMenu",
|
|
528
|
-
rowIndex: Number(el.getAttribute("data-row-index"))
|
|
529
|
-
})
|
|
530
|
-
};
|
|
531
|
-
var sortButton = {
|
|
532
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
533
|
-
icon: "ph--sort-ascending--regular",
|
|
534
|
-
render: ({ fieldId, direction }) => {
|
|
535
|
-
return createButton({
|
|
536
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
537
|
-
icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
|
|
538
|
-
data: {
|
|
539
|
-
"data-field-id": fieldId,
|
|
540
|
-
"data-direction": direction ?? ""
|
|
541
|
-
},
|
|
542
|
-
testId: "table-sort-button",
|
|
543
|
-
// TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
|
|
544
|
-
// This is a bit hacky.
|
|
545
|
-
type: "secondary"
|
|
546
|
-
});
|
|
547
|
-
},
|
|
548
|
-
getData: (el) => ({
|
|
549
|
-
type: "sort",
|
|
550
|
-
fieldId: el.getAttribute("data-field-id"),
|
|
551
|
-
direction: el.getAttribute("data-direction")
|
|
552
|
-
})
|
|
553
|
-
};
|
|
554
|
-
var tableButtons = {
|
|
555
|
-
addColumn: addColumnButton,
|
|
556
|
-
columnSettings: columnSettingsButton,
|
|
557
|
-
rowMenu: rowMenuButton,
|
|
558
|
-
sort: sortButton
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
// packages/ui/react-ui-table/src/util/table-controls.ts
|
|
562
|
-
var CONTROL_IDENTIFIERS = {
|
|
563
|
-
checkbox: "data-table-checkbox",
|
|
564
|
-
switch: "data-table-switch"
|
|
565
|
-
};
|
|
566
|
-
var BASE_CLASSES = {
|
|
567
|
-
checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
|
|
568
|
-
switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
|
|
569
|
-
};
|
|
570
|
-
var renderAttributes = (data) => {
|
|
571
|
-
return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
572
|
-
};
|
|
573
|
-
var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
|
|
574
|
-
return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
|
|
575
|
-
};
|
|
576
|
-
var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
|
|
577
|
-
const attrs = {
|
|
578
|
-
[CONTROL_IDENTIFIERS.checkbox]: "",
|
|
579
|
-
"data-row-index": rowIndex.toString(),
|
|
580
|
-
...header && {
|
|
581
|
-
"data-header": ""
|
|
582
|
-
}
|
|
583
|
-
};
|
|
584
|
-
return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
|
|
585
|
-
};
|
|
586
|
-
var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
|
|
587
|
-
const attrs = {
|
|
588
|
-
[CONTROL_IDENTIFIERS.switch]: "",
|
|
589
|
-
"data-row-index": rowIndex.toString(),
|
|
590
|
-
"data-col-index": colIndex.toString()
|
|
591
|
-
};
|
|
592
|
-
return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
|
|
593
|
-
};
|
|
594
|
-
var tableControls = {
|
|
595
|
-
checkbox: {
|
|
596
|
-
attr: CONTROL_IDENTIFIERS.checkbox,
|
|
597
|
-
render: CheckboxStory,
|
|
598
|
-
getData: (el) => ({
|
|
599
|
-
type: "checkbox",
|
|
600
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
601
|
-
header: el.hasAttribute("data-header")
|
|
602
|
-
})
|
|
603
|
-
},
|
|
604
|
-
switch: {
|
|
605
|
-
attr: CONTROL_IDENTIFIERS.switch,
|
|
606
|
-
render: SwitchStory,
|
|
607
|
-
getData: (el) => ({
|
|
608
|
-
type: "switch",
|
|
609
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
610
|
-
colIndex: Number(el.getAttribute("data-col-index"))
|
|
611
|
-
})
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
// packages/ui/react-ui-table/src/util/schema.ts
|
|
616
|
-
import { Schema as Schema3 } from "effect";
|
|
617
|
-
import { isTypeLiteral, TypeLiteral } from "effect/SchemaAST";
|
|
618
|
-
var narrowSchema = (schema, paths) => {
|
|
619
|
-
const ast = schema?.ast;
|
|
620
|
-
if (isTypeLiteral(ast)) {
|
|
621
|
-
const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
|
|
622
|
-
if (propertySignatures.length > 0) {
|
|
623
|
-
const narrowType = new TypeLiteral(propertySignatures, []);
|
|
624
|
-
return Schema3.make(narrowType);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
return void 0;
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
// packages/ui/react-ui-table/src/model/selection-model.ts
|
|
631
|
-
var SelectionModel = class extends Resource {
|
|
632
|
-
constructor(_rows, _selectionMode, _onSelectionChanged) {
|
|
633
|
-
super(), this._rows = _rows, this._selectionMode = _selectionMode, this._onSelectionChanged = _onSelectionChanged, this._selection = signal(/* @__PURE__ */ new Set()), this._validSelectedIds = computed(() => {
|
|
634
|
-
const rows = this._rows.value;
|
|
635
|
-
if (!rows) {
|
|
636
|
-
return /* @__PURE__ */ new Set();
|
|
637
|
-
}
|
|
638
|
-
const validIds = new Set(rows.map((row) => row.id));
|
|
639
|
-
return new Set([
|
|
640
|
-
...this._selection.value
|
|
641
|
-
].filter((id) => validIds.has(id)));
|
|
642
|
-
}), this._hasSelection = computed(() => this._validSelectedIds.value.size > 0), this._allSelected = computed(() => {
|
|
643
|
-
const rows = this._rows.value;
|
|
644
|
-
if (rows.length === 0) {
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
return rows.every((row) => this._selection.value.has(row.id));
|
|
648
|
-
}), this.getSelectedRows = () => {
|
|
649
|
-
const selectedIds = this._validSelectedIds.value;
|
|
650
|
-
return this._rows.value.filter((row) => selectedIds.has(row.id));
|
|
651
|
-
}, this.isRowIndexSelected = (rowIndex) => {
|
|
652
|
-
const row = this._rows.value[rowIndex];
|
|
653
|
-
return this._selection.value.has(row.id);
|
|
654
|
-
}, this.isObjectSelected = (object) => {
|
|
655
|
-
return this._selection.value.has(object.id);
|
|
656
|
-
}, this.toggleSelectionForRowIndex = (rowIndex) => {
|
|
657
|
-
const row = this._rows.value[rowIndex];
|
|
658
|
-
const newSelection = new Set(this._selection.value);
|
|
659
|
-
if (newSelection.has(row.id)) {
|
|
660
|
-
newSelection.delete(row.id);
|
|
661
|
-
} else {
|
|
662
|
-
if (this._selectionMode === "single") {
|
|
663
|
-
newSelection.clear();
|
|
664
|
-
}
|
|
665
|
-
newSelection.add(row.id);
|
|
666
|
-
}
|
|
667
|
-
this._selection.value = newSelection;
|
|
668
|
-
}, this.setSelection = (mode) => {
|
|
669
|
-
switch (mode) {
|
|
670
|
-
case "all": {
|
|
671
|
-
this._selection.value = new Set(this._rows.value.map((row) => row.id));
|
|
672
|
-
break;
|
|
673
|
-
}
|
|
674
|
-
case "none": {
|
|
675
|
-
this._selection.value = /* @__PURE__ */ new Set();
|
|
676
|
-
break;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
async _open() {
|
|
682
|
-
const selectionWatcher = effect(() => {
|
|
683
|
-
touch(this._selection.value);
|
|
684
|
-
this._onSelectionChanged?.();
|
|
685
|
-
});
|
|
686
|
-
this._ctx.onDispose(selectionWatcher);
|
|
687
|
-
}
|
|
688
|
-
//
|
|
689
|
-
// Getters
|
|
690
|
-
//
|
|
691
|
-
get selection() {
|
|
692
|
-
return this._selection;
|
|
693
|
-
}
|
|
694
|
-
get hasSelection() {
|
|
695
|
-
return this._hasSelection;
|
|
696
|
-
}
|
|
697
|
-
get allRowsSeleted() {
|
|
698
|
-
return this._allSelected;
|
|
699
|
-
}
|
|
700
|
-
get selectionMode() {
|
|
701
|
-
return this._selectionMode;
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
// packages/ui/react-ui-table/src/model/table-sorting.ts
|
|
706
|
-
import { computed as computed2, signal as signal2 } from "@preact/signals-core";
|
|
707
|
-
import orderBy from "lodash.orderby";
|
|
708
|
-
import { getValue, FormatEnum as FormatEnum2, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
|
|
709
|
-
import { formatForDisplay } from "@dxos/react-ui-form";
|
|
710
|
-
var TableSorting = class {
|
|
711
|
-
constructor(rows, _view, _projection) {
|
|
712
|
-
this._view = _view;
|
|
713
|
-
this._projection = _projection;
|
|
714
|
-
this._displayToDataIndex = /* @__PURE__ */ new Map();
|
|
715
|
-
this._localSort = signal2(void 0);
|
|
716
|
-
this._rows = rows;
|
|
717
|
-
this._isDirty = computed2(() => {
|
|
718
|
-
const local = this._localSort.value;
|
|
719
|
-
const viewSort = this._view?.query.sort?.[0];
|
|
720
|
-
if (local?.type === "cleared") {
|
|
721
|
-
return viewSort !== void 0;
|
|
722
|
-
}
|
|
723
|
-
if (local?.type === "active") {
|
|
724
|
-
if (!viewSort) {
|
|
725
|
-
return true;
|
|
726
|
-
}
|
|
727
|
-
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
728
|
-
}
|
|
729
|
-
return false;
|
|
730
|
-
});
|
|
731
|
-
this.sortedRows = this.initialiseSortedRows();
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* @reactive
|
|
735
|
-
* @returns Local sort if present, falls back to view sort.
|
|
736
|
-
*/
|
|
737
|
-
get sorting() {
|
|
738
|
-
const local = this._localSort.value;
|
|
739
|
-
if (local?.type === "cleared") {
|
|
740
|
-
return void 0;
|
|
741
|
-
}
|
|
742
|
-
if (local?.type === "active") {
|
|
743
|
-
return local.sort;
|
|
744
|
-
}
|
|
745
|
-
return this._view?.query.sort?.[0];
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* @reactive
|
|
749
|
-
* @returns Whether local sort differs from view sort.
|
|
750
|
-
*/
|
|
751
|
-
get isDirty() {
|
|
752
|
-
return this._isDirty.value;
|
|
753
|
-
}
|
|
754
|
-
getDataIndex(displayIndex) {
|
|
755
|
-
return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
|
|
756
|
-
}
|
|
757
|
-
setSort(fieldId, direction) {
|
|
758
|
-
this._localSort.value = {
|
|
759
|
-
type: "active",
|
|
760
|
-
sort: {
|
|
761
|
-
fieldId,
|
|
762
|
-
direction
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
}
|
|
766
|
-
toggleSort(fieldId) {
|
|
767
|
-
if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
switch (this.sorting.direction) {
|
|
771
|
-
case "asc": {
|
|
772
|
-
this.setSort(fieldId, "desc");
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
case "desc": {
|
|
776
|
-
this.setSort(fieldId, "asc");
|
|
777
|
-
break;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
clearSort() {
|
|
782
|
-
this._localSort.value = {
|
|
783
|
-
type: "cleared"
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
save() {
|
|
787
|
-
if (this._view && this._localSort.value !== void 0) {
|
|
788
|
-
if (this._localSort.value.type === "active") {
|
|
789
|
-
this._view.query.sort = [
|
|
790
|
-
this._localSort.value.sort
|
|
791
|
-
];
|
|
792
|
-
} else {
|
|
793
|
-
this._view.query.sort = [];
|
|
794
|
-
}
|
|
795
|
-
this._localSort.value = void 0;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
//
|
|
799
|
-
// Initialisation.
|
|
800
|
-
//
|
|
801
|
-
initialiseSortedRows() {
|
|
802
|
-
return computed2(() => {
|
|
803
|
-
this._displayToDataIndex.clear();
|
|
804
|
-
const sort = this.sorting;
|
|
805
|
-
if (!sort || !this._view) {
|
|
806
|
-
return this._rows.value;
|
|
807
|
-
}
|
|
808
|
-
const field = this._view.fields.find((f) => f.id === sort.fieldId);
|
|
809
|
-
if (!field) {
|
|
810
|
-
return this._rows.value;
|
|
811
|
-
}
|
|
812
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
813
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
814
|
-
const sortValue = this.getSortValue(props, field, item);
|
|
815
|
-
const isEmpty = !(props.type === TypeEnum2.Boolean) && (sortValue == null || sortValue === "");
|
|
816
|
-
return {
|
|
817
|
-
item,
|
|
818
|
-
index,
|
|
819
|
-
value: sortValue,
|
|
820
|
-
isEmpty
|
|
821
|
-
};
|
|
822
|
-
});
|
|
823
|
-
const ordered = orderBy(dataWithIndices, [
|
|
824
|
-
"isEmpty",
|
|
825
|
-
"value"
|
|
826
|
-
], [
|
|
827
|
-
"asc",
|
|
828
|
-
sort.direction
|
|
829
|
-
]);
|
|
830
|
-
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
831
|
-
if (displayIndex !== dataIndex) {
|
|
832
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
833
|
-
}
|
|
834
|
-
});
|
|
835
|
-
return ordered.map(({ item }) => item);
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
getSortValue(props, field, item) {
|
|
839
|
-
const { type, format } = props;
|
|
840
|
-
const value = getValue(item, field.path);
|
|
841
|
-
if (type === TypeEnum2.Boolean) {
|
|
842
|
-
return !!value;
|
|
843
|
-
}
|
|
844
|
-
if (type === TypeEnum2.Number) {
|
|
845
|
-
return value;
|
|
846
|
-
}
|
|
847
|
-
if (value == null) {
|
|
848
|
-
return value;
|
|
849
|
-
}
|
|
850
|
-
if (format === FormatEnum2.SingleSelect) {
|
|
851
|
-
const options = props.options;
|
|
852
|
-
if (!options) {
|
|
853
|
-
return void 0;
|
|
854
|
-
}
|
|
855
|
-
const option = options.find((option2) => option2.id === value);
|
|
856
|
-
return option ? options.indexOf(option) : void 0;
|
|
857
|
-
}
|
|
858
|
-
if (format === FormatEnum2.Ref && field.referencePath) {
|
|
859
|
-
const refValue = getValue(value.target, field.referencePath);
|
|
860
|
-
return refValue;
|
|
861
|
-
}
|
|
862
|
-
return formatForDisplay({
|
|
863
|
-
type,
|
|
864
|
-
format,
|
|
865
|
-
value
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
|
|
870
|
-
// packages/ui/react-ui-table/src/util/tag.ts
|
|
871
|
-
var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
872
|
-
var extractTagIds = (value) => {
|
|
873
|
-
if (typeof value !== "string") {
|
|
874
|
-
return void 0;
|
|
875
|
-
}
|
|
876
|
-
const ids = [];
|
|
877
|
-
let match;
|
|
878
|
-
while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
|
|
879
|
-
if (match[2]) {
|
|
880
|
-
ids.push(match[2]);
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
return ids.length > 0 ? ids : void 0;
|
|
884
|
-
};
|
|
885
|
-
|
|
886
|
-
// packages/ui/react-ui-table/src/model/table-model.ts
|
|
887
|
-
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
888
|
-
var defaultFeatures = {
|
|
889
|
-
selection: {
|
|
890
|
-
enabled: true,
|
|
891
|
-
mode: "multiple"
|
|
892
|
-
},
|
|
893
|
-
dataEditable: false,
|
|
894
|
-
schemaEditable: false
|
|
895
|
-
};
|
|
896
|
-
var TableModel = class extends Resource2 {
|
|
897
|
-
constructor({ id, space, view, projection, features = {}, sorting = [], pinnedRows = {
|
|
898
|
-
top: [],
|
|
899
|
-
bottom: []
|
|
900
|
-
}, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
|
|
901
|
-
super();
|
|
902
|
-
this._visibleRange = signal3({
|
|
903
|
-
start: {
|
|
904
|
-
row: 0,
|
|
905
|
-
col: 0
|
|
906
|
-
},
|
|
907
|
-
end: {
|
|
908
|
-
row: 0,
|
|
909
|
-
col: 0
|
|
910
|
-
}
|
|
911
|
-
});
|
|
912
|
-
this._rows = signal3([]);
|
|
913
|
-
//
|
|
914
|
-
// Data
|
|
915
|
-
//
|
|
916
|
-
this.setRows = (obj) => {
|
|
917
|
-
this._rows.value = obj;
|
|
918
|
-
};
|
|
919
|
-
this.getRowCount = () => this._rows.value.length;
|
|
920
|
-
this.getColumnCount = () => this._view?.fields.length ?? 0;
|
|
921
|
-
this.insertRow = (rowIndex) => {
|
|
922
|
-
const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
|
|
923
|
-
this._onInsertRow?.(row);
|
|
924
|
-
};
|
|
925
|
-
this.deleteRow = (rowIndex) => {
|
|
926
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
927
|
-
const obj = this._rows.value[row];
|
|
928
|
-
const objectsToDelete = [];
|
|
929
|
-
if (this.features.selection.enabled && this._selection.hasSelection.value) {
|
|
930
|
-
const selectedRows = this._selection.getSelectedRows();
|
|
931
|
-
objectsToDelete.push(...selectedRows);
|
|
932
|
-
} else {
|
|
933
|
-
objectsToDelete.push(obj);
|
|
934
|
-
}
|
|
935
|
-
this._onDeleteRows?.(row, objectsToDelete);
|
|
936
|
-
};
|
|
937
|
-
this.handleRowAction = (actionId, rowIndex) => {
|
|
938
|
-
if (!this._onRowAction) {
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
942
|
-
const data = this._rows.value[row];
|
|
943
|
-
if (data) {
|
|
944
|
-
this._onRowAction(actionId, data);
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
this.getCellData = ({ col, row }) => {
|
|
948
|
-
const fields = this._view?.fields ?? [];
|
|
949
|
-
if (col < 0 || col >= fields.length) {
|
|
950
|
-
return void 0;
|
|
951
|
-
}
|
|
952
|
-
const field = fields[col];
|
|
953
|
-
const dataIndex = this._sorting.getDataIndex(row);
|
|
954
|
-
const value = getValue2(this._rows.value[dataIndex], field.path);
|
|
955
|
-
if (value == null) {
|
|
956
|
-
return "";
|
|
957
|
-
}
|
|
958
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
959
|
-
switch (props.format) {
|
|
960
|
-
case FormatEnum3.Ref: {
|
|
961
|
-
if (!field.referencePath) {
|
|
962
|
-
return "";
|
|
963
|
-
}
|
|
964
|
-
return getValue2(value.target, field.referencePath);
|
|
965
|
-
}
|
|
966
|
-
default: {
|
|
967
|
-
return formatForEditing({
|
|
968
|
-
type: props.type,
|
|
969
|
-
format: props.format,
|
|
970
|
-
value
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
};
|
|
975
|
-
this.validateCellData = async ({ col, row }, value) => {
|
|
976
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
977
|
-
const fields = this._view?.fields ?? [];
|
|
978
|
-
if (col < 0 || col >= fields.length) {
|
|
979
|
-
return {
|
|
980
|
-
valid: false,
|
|
981
|
-
error: "Invalid column index"
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
const field = fields[col];
|
|
985
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
986
|
-
const currentRow = this._rows.value[rowIdx];
|
|
987
|
-
invariant(currentRow, "Invalid row index", {
|
|
988
|
-
F: __dxlog_file,
|
|
989
|
-
L: 355,
|
|
990
|
-
S: this,
|
|
991
|
-
A: [
|
|
992
|
-
"currentRow",
|
|
993
|
-
"'Invalid row index'"
|
|
994
|
-
]
|
|
995
|
-
});
|
|
996
|
-
const snapshot = getSnapshot(currentRow);
|
|
997
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
998
|
-
setValue(snapshot, field.path, transformedValue);
|
|
999
|
-
const schema = getSchema(currentRow);
|
|
1000
|
-
invariant(schema, void 0, {
|
|
1001
|
-
F: __dxlog_file,
|
|
1002
|
-
L: 365,
|
|
1003
|
-
S: this,
|
|
1004
|
-
A: [
|
|
1005
|
-
"schema",
|
|
1006
|
-
""
|
|
1007
|
-
]
|
|
1008
|
-
});
|
|
1009
|
-
const validationResult = validateSchema(schema, snapshot);
|
|
1010
|
-
if (validationResult && validationResult.length > 0) {
|
|
1011
|
-
const error = validationResult[0];
|
|
1012
|
-
invariant(error.path === field.path, void 0, {
|
|
1013
|
-
F: __dxlog_file,
|
|
1014
|
-
L: 370,
|
|
1015
|
-
S: this,
|
|
1016
|
-
A: [
|
|
1017
|
-
"error.path === field.path",
|
|
1018
|
-
""
|
|
1019
|
-
]
|
|
1020
|
-
});
|
|
1021
|
-
return {
|
|
1022
|
-
valid: false,
|
|
1023
|
-
error: error.message
|
|
1024
|
-
};
|
|
1025
|
-
}
|
|
1026
|
-
return {
|
|
1027
|
-
valid: true
|
|
1028
|
-
};
|
|
1029
|
-
};
|
|
1030
|
-
this.setCellData = ({ col, row }, value) => {
|
|
1031
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
1032
|
-
const fields = this._view?.fields ?? [];
|
|
1033
|
-
if (col < 0 || col >= fields.length) {
|
|
1034
|
-
return;
|
|
1035
|
-
}
|
|
1036
|
-
const field = fields[col];
|
|
1037
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1038
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
1039
|
-
if (props.format === FormatEnum3.Ref && !isLiveObject(value)) {
|
|
1040
|
-
return;
|
|
1041
|
-
}
|
|
1042
|
-
setValue(this._rows.value[rowIdx], field.path, transformedValue);
|
|
1043
|
-
};
|
|
1044
|
-
this._id = id;
|
|
1045
|
-
this._space = space;
|
|
1046
|
-
this._view = view;
|
|
1047
|
-
this._projection = projection;
|
|
1048
|
-
this._features = {
|
|
1049
|
-
...defaultFeatures,
|
|
1050
|
-
...features
|
|
1051
|
-
};
|
|
1052
|
-
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
|
|
1053
|
-
F: __dxlog_file,
|
|
1054
|
-
L: 126,
|
|
1055
|
-
S: this,
|
|
1056
|
-
A: [
|
|
1057
|
-
"!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
|
|
1058
|
-
"'Single selection is not compatible with editable tables.'"
|
|
1059
|
-
]
|
|
1060
|
-
});
|
|
1061
|
-
this._sorting = new TableSorting(this._rows, this._view, projection);
|
|
1062
|
-
if (sorting.length > 0) {
|
|
1063
|
-
const [sort] = sorting;
|
|
1064
|
-
this._sorting.setSort(sort.fieldId, sort.direction);
|
|
1065
|
-
}
|
|
1066
|
-
this._pinnedRows = pinnedRows;
|
|
1067
|
-
this._rowActions = rowActions;
|
|
1068
|
-
this._onInsertRow = onInsertRow;
|
|
1069
|
-
this._onDeleteRows = onDeleteRows;
|
|
1070
|
-
this._onDeleteColumn = onDeleteColumn;
|
|
1071
|
-
this._onCellUpdate = onCellUpdate;
|
|
1072
|
-
this._onRowOrderChange = onRowOrderChange;
|
|
1073
|
-
this._onRowAction = onRowAction;
|
|
1074
|
-
}
|
|
1075
|
-
get id() {
|
|
1076
|
-
return this._id;
|
|
1077
|
-
}
|
|
1078
|
-
get space() {
|
|
1079
|
-
return this._space;
|
|
1080
|
-
}
|
|
1081
|
-
get view() {
|
|
1082
|
-
return this._view;
|
|
1083
|
-
}
|
|
1084
|
-
get projection() {
|
|
1085
|
-
return this._projection;
|
|
1086
|
-
}
|
|
1087
|
-
get rows() {
|
|
1088
|
-
return this._sorting.sortedRows;
|
|
1089
|
-
}
|
|
1090
|
-
get features() {
|
|
1091
|
-
return this._features;
|
|
1092
|
-
}
|
|
1093
|
-
/**
|
|
1094
|
-
* @reactive
|
|
1095
|
-
*/
|
|
1096
|
-
get sorting() {
|
|
1097
|
-
return this._sorting;
|
|
1098
|
-
}
|
|
1099
|
-
/**
|
|
1100
|
-
* Gets the row data at the specified display index.
|
|
1101
|
-
*/
|
|
1102
|
-
getRowAt(displayIndex) {
|
|
1103
|
-
if (displayIndex < 0 || displayIndex >= this._sorting.sortedRows.value.length) {
|
|
1104
|
-
return void 0;
|
|
1105
|
-
}
|
|
1106
|
-
return this._sorting.sortedRows.value[displayIndex];
|
|
1107
|
-
}
|
|
1108
|
-
get pinnedRows() {
|
|
1109
|
-
return this._pinnedRows;
|
|
1110
|
-
}
|
|
1111
|
-
get columnMeta() {
|
|
1112
|
-
invariant(this._columnMeta, void 0, {
|
|
1113
|
-
F: __dxlog_file,
|
|
1114
|
-
L: 195,
|
|
1115
|
-
S: this,
|
|
1116
|
-
A: [
|
|
1117
|
-
"this._columnMeta",
|
|
1118
|
-
""
|
|
1119
|
-
]
|
|
1120
|
-
});
|
|
1121
|
-
return this._columnMeta;
|
|
1122
|
-
}
|
|
1123
|
-
get selection() {
|
|
1124
|
-
return this._selection;
|
|
1125
|
-
}
|
|
1126
|
-
/** @reactive */
|
|
1127
|
-
get isViewDirty() {
|
|
1128
|
-
return this._sorting.isDirty;
|
|
1129
|
-
}
|
|
1130
|
-
get rowActions() {
|
|
1131
|
-
return this._rowActions;
|
|
1132
|
-
}
|
|
1133
|
-
//
|
|
1134
|
-
// Initialisation
|
|
1135
|
-
//
|
|
1136
|
-
async _open() {
|
|
1137
|
-
this.initializeColumnMeta();
|
|
1138
|
-
this.initializeEffects();
|
|
1139
|
-
this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", () => this._onRowOrderChange?.());
|
|
1140
|
-
await this._selection.open(this._ctx);
|
|
1141
|
-
}
|
|
1142
|
-
initializeColumnMeta() {
|
|
1143
|
-
this._columnMeta = computed3(() => {
|
|
1144
|
-
const fields = this._view?.fields ?? [];
|
|
1145
|
-
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
1146
|
-
index,
|
|
1147
|
-
{
|
|
1148
|
-
size: field?.size ?? 256,
|
|
1149
|
-
resizeable: true
|
|
1150
|
-
}
|
|
1151
|
-
]));
|
|
1152
|
-
return {
|
|
1153
|
-
grid: meta,
|
|
1154
|
-
frozenColsStart: {
|
|
1155
|
-
0: {
|
|
1156
|
-
size: 30,
|
|
1157
|
-
resizeable: false
|
|
1158
|
-
}
|
|
1159
|
-
},
|
|
1160
|
-
frozenColsEnd: {
|
|
1161
|
-
0: {
|
|
1162
|
-
size: 40,
|
|
1163
|
-
resizeable: false
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
};
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
initializeEffects() {
|
|
1170
|
-
const rowOrderWatcher = effect2(() => {
|
|
1171
|
-
touch(this._sorting.sortedRows.value);
|
|
1172
|
-
this._onRowOrderChange?.();
|
|
1173
|
-
});
|
|
1174
|
-
this._ctx.onDispose(rowOrderWatcher);
|
|
1175
|
-
const rowEffectManager = effect2(() => {
|
|
1176
|
-
const { start, end } = touch(this._visibleRange.value);
|
|
1177
|
-
const rowEffects = [];
|
|
1178
|
-
for (let row = start.row; row <= end.row; row++) {
|
|
1179
|
-
rowEffects.push(effect2(() => {
|
|
1180
|
-
const obj = this._sorting.sortedRows.value[row];
|
|
1181
|
-
this._view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
|
|
1182
|
-
this._onCellUpdate?.({
|
|
1183
|
-
row,
|
|
1184
|
-
col: start.col,
|
|
1185
|
-
plane: "grid"
|
|
1186
|
-
});
|
|
1187
|
-
}));
|
|
1188
|
-
}
|
|
1189
|
-
return () => rowEffects.forEach((cleanup) => cleanup());
|
|
1190
|
-
});
|
|
1191
|
-
this._ctx.onDispose(rowEffectManager);
|
|
1192
|
-
}
|
|
1193
|
-
/**
|
|
1194
|
-
* Updates a cell's value using a transform function.
|
|
1195
|
-
* @param {DxGridPlanePosition} position - The position of the cell to update.
|
|
1196
|
-
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1197
|
-
*/
|
|
1198
|
-
updateCellData({ col, row }, update) {
|
|
1199
|
-
const dataRow = this._sorting.getDataIndex(row);
|
|
1200
|
-
const fields = this._view?.fields ?? [];
|
|
1201
|
-
const field = fields[col];
|
|
1202
|
-
const value = getValue2(this._rows.value[dataRow], field.path);
|
|
1203
|
-
const updatedValue = update(value);
|
|
1204
|
-
setValue(this._rows.value[dataRow], field.path, updatedValue);
|
|
1205
|
-
}
|
|
1206
|
-
//
|
|
1207
|
-
// Column Operations
|
|
1208
|
-
//
|
|
1209
|
-
deleteColumn(fieldId) {
|
|
1210
|
-
if (!this._view) {
|
|
1211
|
-
return;
|
|
1212
|
-
}
|
|
1213
|
-
const field = this._view?.fields.find((field2) => field2.id === fieldId);
|
|
1214
|
-
if (field && this._onDeleteColumn) {
|
|
1215
|
-
this._onDeleteColumn(field.id);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
//
|
|
1219
|
-
// Resize
|
|
1220
|
-
//
|
|
1221
|
-
setColumnWidth(columnIndex, width) {
|
|
1222
|
-
const fields = this._view?.fields ?? [];
|
|
1223
|
-
if (columnIndex < fields.length) {
|
|
1224
|
-
const newWidth = Math.max(0, width);
|
|
1225
|
-
const field = fields[columnIndex];
|
|
1226
|
-
if (field) {
|
|
1227
|
-
field.size = newWidth;
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
//
|
|
1232
|
-
// Pinning
|
|
1233
|
-
//
|
|
1234
|
-
// TODO(burdon): Change to setPinned(on/off).
|
|
1235
|
-
pinRow(rowIndex, side) {
|
|
1236
|
-
this._pinnedRows[side].push(rowIndex);
|
|
1237
|
-
}
|
|
1238
|
-
unpinRow(rowIndex) {
|
|
1239
|
-
this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
|
|
1240
|
-
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1241
|
-
}
|
|
1242
|
-
//
|
|
1243
|
-
// View operations
|
|
1244
|
-
//
|
|
1245
|
-
saveView() {
|
|
1246
|
-
this._sorting.save();
|
|
1247
|
-
}
|
|
1248
|
-
};
|
|
1249
|
-
var editorTextToCellValue = (props, value) => {
|
|
1250
|
-
switch (props.format) {
|
|
1251
|
-
case FormatEnum3.Ref: {
|
|
1252
|
-
if (isLiveObject(value)) {
|
|
1253
|
-
return makeRef(value);
|
|
1254
|
-
} else {
|
|
1255
|
-
return value;
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
case FormatEnum3.SingleSelect: {
|
|
1259
|
-
const ids = extractTagIds(value);
|
|
1260
|
-
if (ids && ids.length > 0) {
|
|
1261
|
-
return ids[0];
|
|
1262
|
-
} else {
|
|
1263
|
-
return value;
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
case FormatEnum3.MultiSelect: {
|
|
1267
|
-
const ids = extractTagIds(value);
|
|
1268
|
-
return ids || value;
|
|
1269
|
-
}
|
|
1270
|
-
default: {
|
|
1271
|
-
return parseValue({
|
|
1272
|
-
type: props.type,
|
|
1273
|
-
format: props.format,
|
|
1274
|
-
value
|
|
1275
|
-
});
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
|
|
1280
|
-
// packages/ui/react-ui-table/src/model/modal-controller.ts
|
|
1281
|
-
import { signal as signal4 } from "@preact/signals-core";
|
|
1282
|
-
import { log } from "@dxos/log";
|
|
1283
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
|
|
1284
|
-
var ModalController = class {
|
|
1285
|
-
constructor() {
|
|
1286
|
-
this._state = signal4({
|
|
1287
|
-
type: "closed"
|
|
1288
|
-
});
|
|
1289
|
-
this._triggerRef = {
|
|
1290
|
-
current: null
|
|
1291
|
-
};
|
|
1292
|
-
this.setTrigger = (trigger) => {
|
|
1293
|
-
this._triggerRef.current = trigger;
|
|
1294
|
-
};
|
|
1295
|
-
this.showRowMenu = (rowIndex) => {
|
|
1296
|
-
this._state.value = {
|
|
1297
|
-
type: "row",
|
|
1298
|
-
rowIndex
|
|
1299
|
-
};
|
|
1300
|
-
};
|
|
1301
|
-
this.showColumnMenu = (fieldId) => {
|
|
1302
|
-
this._state.value = {
|
|
1303
|
-
type: "column",
|
|
1304
|
-
fieldId
|
|
1305
|
-
};
|
|
1306
|
-
};
|
|
1307
|
-
this.showColumnCreator = () => {
|
|
1308
|
-
this._state.value = {
|
|
1309
|
-
type: "columnSettings",
|
|
1310
|
-
mode: {
|
|
1311
|
-
type: "create"
|
|
1312
|
-
}
|
|
1313
|
-
};
|
|
1314
|
-
};
|
|
1315
|
-
this.showReferencePanel = (targetId, schemaId) => {
|
|
1316
|
-
this._state.value = {
|
|
1317
|
-
type: "refPanel",
|
|
1318
|
-
targetId,
|
|
1319
|
-
typename: schemaId
|
|
1320
|
-
};
|
|
1321
|
-
};
|
|
1322
|
-
this.openColumnSettings = () => {
|
|
1323
|
-
if (this._state.value.type === "column") {
|
|
1324
|
-
const fieldId = this._state.value.fieldId;
|
|
1325
|
-
requestAnimationFrame(() => {
|
|
1326
|
-
this._state.value = {
|
|
1327
|
-
type: "columnSettings",
|
|
1328
|
-
mode: {
|
|
1329
|
-
type: "edit",
|
|
1330
|
-
fieldId
|
|
1331
|
-
}
|
|
1332
|
-
};
|
|
1333
|
-
});
|
|
1334
|
-
}
|
|
1335
|
-
};
|
|
1336
|
-
this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
|
|
1337
|
-
if (anchorCell) {
|
|
1338
|
-
this._triggerRef.current = anchorCell;
|
|
1339
|
-
this._state.value = {
|
|
1340
|
-
type: "createRefPanel",
|
|
1341
|
-
typename,
|
|
1342
|
-
initialValues,
|
|
1343
|
-
onCreate
|
|
1344
|
-
};
|
|
1345
|
-
} else {
|
|
1346
|
-
log.warn("anchor cell not found while creating new ref", void 0, {
|
|
1347
|
-
F: __dxlog_file2,
|
|
1348
|
-
L: 86,
|
|
1349
|
-
S: this,
|
|
1350
|
-
C: (f, a) => f(...a)
|
|
1351
|
-
});
|
|
1352
|
-
}
|
|
1353
|
-
};
|
|
1354
|
-
this.close = () => {
|
|
1355
|
-
this._state.value = {
|
|
1356
|
-
type: "closed"
|
|
1357
|
-
};
|
|
1358
|
-
};
|
|
1359
|
-
}
|
|
1360
|
-
get state() {
|
|
1361
|
-
return this._state;
|
|
1362
|
-
}
|
|
1363
|
-
get trigger() {
|
|
1364
|
-
return this._triggerRef;
|
|
1365
|
-
}
|
|
1366
|
-
};
|
|
2
|
+
BUTTON_IDENTIFIERS,
|
|
3
|
+
CONTROL_IDENTIFIERS,
|
|
4
|
+
CheckboxStory,
|
|
5
|
+
ModalController,
|
|
6
|
+
SwitchStory,
|
|
7
|
+
TableModel,
|
|
8
|
+
TablePresentation,
|
|
9
|
+
cellClassesForRowSelection,
|
|
10
|
+
createTable,
|
|
11
|
+
getBaseSchema,
|
|
12
|
+
makeDynamicTable,
|
|
13
|
+
narrowSchema,
|
|
14
|
+
tableButtons,
|
|
15
|
+
tableControls,
|
|
16
|
+
touch,
|
|
17
|
+
useAddRow,
|
|
18
|
+
useTableModel
|
|
19
|
+
} from "./chunk-ZAOSIG3L.mjs";
|
|
20
|
+
import "./chunk-L2LSB6KV.mjs";
|
|
1367
21
|
|
|
1368
|
-
//
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
cells = this.getMainGridCells(range);
|
|
1396
|
-
break;
|
|
1397
|
-
case "frozenRowsStart":
|
|
1398
|
-
cells = this.getHeaderCells(range);
|
|
1399
|
-
break;
|
|
1400
|
-
case "frozenColsStart":
|
|
1401
|
-
cells = this.getSelectionColumnCells(range);
|
|
1402
|
-
break;
|
|
1403
|
-
case "frozenColsEnd":
|
|
1404
|
-
cells = this.getActionColumnCells(range);
|
|
1405
|
-
break;
|
|
1406
|
-
case "fixedStartStart":
|
|
1407
|
-
cells = this.getSelectAllCell();
|
|
1408
|
-
break;
|
|
1409
|
-
case "fixedStartEnd":
|
|
1410
|
-
cells = this.getNewColumnCell();
|
|
1411
|
-
break;
|
|
1412
|
-
default:
|
|
1413
|
-
cells = {};
|
|
1414
|
-
}
|
|
1415
|
-
if (plane === "grid" && this.model.features.dataEditable === false) {
|
|
1416
|
-
Object.values(cells).forEach((cell) => {
|
|
1417
|
-
cell.readonly = "text-select";
|
|
1418
|
-
});
|
|
1419
|
-
}
|
|
1420
|
-
return cells;
|
|
1421
|
-
}
|
|
1422
|
-
getMainGridCells(range) {
|
|
1423
|
-
const cells = {};
|
|
1424
|
-
const fields = this.model.view?.fields ?? [];
|
|
1425
|
-
const addCell = (obj, field, colIndex, displayIndex) => {
|
|
1426
|
-
const { props } = this.model.projection.getFieldProjection(field.id);
|
|
1427
|
-
const cell = {
|
|
1428
|
-
get value() {
|
|
1429
|
-
const value = getValue3(obj, field.path);
|
|
1430
|
-
if (value == null) {
|
|
1431
|
-
return "";
|
|
1432
|
-
}
|
|
1433
|
-
if (props.type === "array") {
|
|
1434
|
-
return "";
|
|
1435
|
-
}
|
|
1436
|
-
switch (props.format) {
|
|
1437
|
-
case FormatEnum4.Boolean:
|
|
1438
|
-
case FormatEnum4.SingleSelect:
|
|
1439
|
-
case FormatEnum4.MultiSelect: {
|
|
1440
|
-
return "";
|
|
1441
|
-
}
|
|
1442
|
-
case FormatEnum4.Ref: {
|
|
1443
|
-
if (!field.referencePath) {
|
|
1444
|
-
return "";
|
|
1445
|
-
}
|
|
1446
|
-
return getValue3(value.target, field.referencePath);
|
|
1447
|
-
}
|
|
1448
|
-
default: {
|
|
1449
|
-
return formatForDisplay2({
|
|
1450
|
-
type: props.type,
|
|
1451
|
-
format: props.format,
|
|
1452
|
-
value
|
|
1453
|
-
});
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
};
|
|
1458
|
-
const classes = [];
|
|
1459
|
-
const formatClasses = cellClassesForFieldType({
|
|
1460
|
-
type: props.type,
|
|
1461
|
-
format: props.format
|
|
1462
|
-
});
|
|
1463
|
-
if (formatClasses) {
|
|
1464
|
-
classes.push(formatClasses);
|
|
1465
|
-
}
|
|
1466
|
-
const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj), this.model.selection.selectionMode);
|
|
1467
|
-
if (rowSelectionClasses) {
|
|
1468
|
-
classes.push(rowSelectionClasses);
|
|
1469
|
-
}
|
|
1470
|
-
if (classes.length > 0) {
|
|
1471
|
-
cell.className = mx(classes.flat());
|
|
1472
|
-
}
|
|
1473
|
-
if (props.type === TypeEnum3.Array) {
|
|
1474
|
-
const targetArray = getValue3(obj, field.path);
|
|
1475
|
-
if (targetArray && Array.isArray(targetArray)) {
|
|
1476
|
-
const getLabel = (value) => {
|
|
1477
|
-
if (!value) {
|
|
1478
|
-
return void 0;
|
|
1479
|
-
}
|
|
1480
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1481
|
-
return String(value);
|
|
1482
|
-
}
|
|
1483
|
-
if (Array.isArray(value)) {
|
|
1484
|
-
return "Array";
|
|
1485
|
-
}
|
|
1486
|
-
if (typeof value === "object" && value.name) {
|
|
1487
|
-
return value.name;
|
|
1488
|
-
}
|
|
1489
|
-
if (typeof value === "object" && value.value) {
|
|
1490
|
-
return `${value.value}`;
|
|
1491
|
-
}
|
|
1492
|
-
return "Object";
|
|
1493
|
-
};
|
|
1494
|
-
const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
|
|
1495
|
-
return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
|
|
1496
|
-
}).join("");
|
|
1497
|
-
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
if (props.format === FormatEnum4.Ref && props.referenceSchema) {
|
|
1501
|
-
const targetObj = getValue3(obj, field.path)?.target;
|
|
1502
|
-
if (targetObj) {
|
|
1503
|
-
const dxn = getObjectDXN(targetObj)?.toString();
|
|
1504
|
-
cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button is-6 pli-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
if (props.format === FormatEnum4.Boolean) {
|
|
1508
|
-
const value = getValue3(obj, field.path);
|
|
1509
|
-
cell.accessoryHtml = tableControls.switch.render({
|
|
1510
|
-
colIndex,
|
|
1511
|
-
rowIndex: displayIndex,
|
|
1512
|
-
checked: value ?? false
|
|
1513
|
-
});
|
|
1514
|
-
cell.readonly = "no-text-select";
|
|
1515
|
-
}
|
|
1516
|
-
if (props.format === FormatEnum4.SingleSelect) {
|
|
1517
|
-
const value = getValue3(obj, field.path);
|
|
1518
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1519
|
-
if (options) {
|
|
1520
|
-
const option = options.find((o) => o.id === value);
|
|
1521
|
-
if (option) {
|
|
1522
|
-
cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
if (props.format === FormatEnum4.MultiSelect) {
|
|
1527
|
-
const values = getValue3(obj, field.path);
|
|
1528
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1529
|
-
if (options && values && values.length > 0) {
|
|
1530
|
-
const tags = values.map((value) => {
|
|
1531
|
-
const option = options.find((o) => o.id === value);
|
|
1532
|
-
if (option) {
|
|
1533
|
-
return `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1534
|
-
}
|
|
1535
|
-
return null;
|
|
1536
|
-
}).filter(Boolean).join(" ");
|
|
1537
|
-
if (tags) {
|
|
1538
|
-
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1">${tags}</div>`;
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
const idx = toPlaneCellIndex({
|
|
1543
|
-
col: colIndex,
|
|
1544
|
-
row: displayIndex
|
|
1545
|
-
});
|
|
1546
|
-
cells[idx] = cell;
|
|
1547
|
-
};
|
|
1548
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1549
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1550
|
-
const field = fields[col];
|
|
1551
|
-
if (!field) {
|
|
1552
|
-
continue;
|
|
1553
|
-
}
|
|
1554
|
-
addCell(this.model.rows.value[row], field, col, row);
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
return cells;
|
|
1558
|
-
}
|
|
1559
|
-
getHeaderCells(range) {
|
|
1560
|
-
const cells = {};
|
|
1561
|
-
const fields = this.model.view?.fields ?? [];
|
|
1562
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1563
|
-
const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
|
|
1564
|
-
const sorting = this.model.sorting?.sorting;
|
|
1565
|
-
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1566
|
-
cells[toPlaneCellIndex({
|
|
1567
|
-
col,
|
|
1568
|
-
row: 0
|
|
1569
|
-
})] = {
|
|
1570
|
-
// TODO(burdon): Use same logic as form for fallback title.
|
|
1571
|
-
value: props.title ?? field.path,
|
|
1572
|
-
readonly: true,
|
|
1573
|
-
resizeHandle: "col",
|
|
1574
|
-
accessoryHtml: `
|
|
1575
|
-
${direction !== void 0 ? tableButtons.sort.render({
|
|
1576
|
-
fieldId: field.id,
|
|
1577
|
-
direction
|
|
1578
|
-
}) : ""}
|
|
1579
|
-
${tableButtons.columnSettings.render({
|
|
1580
|
-
fieldId: field.id
|
|
1581
|
-
})}
|
|
1582
|
-
`,
|
|
1583
|
-
className: "!bg-toolbarSurface"
|
|
1584
|
-
};
|
|
1585
|
-
}
|
|
1586
|
-
return cells;
|
|
1587
|
-
}
|
|
1588
|
-
getSelectionColumnCells(range) {
|
|
1589
|
-
const cells = {};
|
|
1590
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1591
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1592
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1593
|
-
cells[toPlaneCellIndex({
|
|
1594
|
-
col: 0,
|
|
1595
|
-
row
|
|
1596
|
-
})] = {
|
|
1597
|
-
value: "",
|
|
1598
|
-
readonly: "no-text-select",
|
|
1599
|
-
className: classes ? mx(classes) : void 0,
|
|
1600
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1601
|
-
rowIndex: row,
|
|
1602
|
-
checked: isSelected
|
|
1603
|
-
})
|
|
1604
|
-
};
|
|
1605
|
-
}
|
|
1606
|
-
return cells;
|
|
1607
|
-
}
|
|
1608
|
-
getActionColumnCells(range) {
|
|
1609
|
-
const cells = {};
|
|
1610
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1611
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1612
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1613
|
-
cells[toPlaneCellIndex({
|
|
1614
|
-
col: 0,
|
|
1615
|
-
row
|
|
1616
|
-
})] = {
|
|
1617
|
-
value: "",
|
|
1618
|
-
readonly: true,
|
|
1619
|
-
className: classes ? mx(classes) : void 0,
|
|
1620
|
-
accessoryHtml: tableButtons.rowMenu.render({
|
|
1621
|
-
rowIndex: row
|
|
1622
|
-
})
|
|
1623
|
-
};
|
|
1624
|
-
}
|
|
1625
|
-
return cells;
|
|
1626
|
-
}
|
|
1627
|
-
getSelectAllCell() {
|
|
1628
|
-
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === "single") {
|
|
1629
|
-
return {
|
|
1630
|
-
[toPlaneCellIndex({
|
|
1631
|
-
col: 0,
|
|
1632
|
-
row: 0
|
|
1633
|
-
})]: {
|
|
1634
|
-
className: "!bg-toolbarSurface",
|
|
1635
|
-
readonly: true,
|
|
1636
|
-
value: ""
|
|
1637
|
-
}
|
|
1638
|
-
};
|
|
1639
|
-
}
|
|
1640
|
-
return {
|
|
1641
|
-
[toPlaneCellIndex({
|
|
1642
|
-
col: 0,
|
|
1643
|
-
row: 0
|
|
1644
|
-
})]: {
|
|
1645
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1646
|
-
rowIndex: 0,
|
|
1647
|
-
header: true,
|
|
1648
|
-
checked: this.model.selection.allRowsSeleted.value
|
|
1649
|
-
}),
|
|
1650
|
-
className: "!bg-toolbarSurface",
|
|
1651
|
-
readonly: true,
|
|
1652
|
-
value: ""
|
|
1653
|
-
}
|
|
1654
|
-
};
|
|
1655
|
-
}
|
|
1656
|
-
getNewColumnCell() {
|
|
1657
|
-
return {
|
|
1658
|
-
[toPlaneCellIndex({
|
|
1659
|
-
col: 0,
|
|
1660
|
-
row: 0
|
|
1661
|
-
})]: {
|
|
1662
|
-
accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
|
|
1663
|
-
disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1664
|
-
}) : void 0,
|
|
1665
|
-
className: "!bg-toolbarSurface",
|
|
1666
|
-
readonly: true,
|
|
1667
|
-
value: ""
|
|
22
|
+
// src/translations.ts
|
|
23
|
+
var translationKey = "react-ui-table";
|
|
24
|
+
var translations = [
|
|
25
|
+
{
|
|
26
|
+
"en-US": {
|
|
27
|
+
[translationKey]: {
|
|
28
|
+
"object placeholder": "New table",
|
|
29
|
+
"create object label": "Create table",
|
|
30
|
+
"table name placeholder": "Table name",
|
|
31
|
+
"settings title": "Table settings",
|
|
32
|
+
"table schema label": "Record type",
|
|
33
|
+
"new schema": "New record type",
|
|
34
|
+
"continue label": "Continue",
|
|
35
|
+
"create stack section label": "Create table",
|
|
36
|
+
"add row label": "Add row",
|
|
37
|
+
"create comment": "Create thread",
|
|
38
|
+
"column action sort descending": "Sort Descending",
|
|
39
|
+
"column action sort ascending": "Sort Ascending",
|
|
40
|
+
"column action clear sorting": "Clear Sorting",
|
|
41
|
+
"column action settings": "Column Settings",
|
|
42
|
+
"column action delete": "Delete Column",
|
|
43
|
+
"delete row label": "Delete row",
|
|
44
|
+
"bulk delete row label": "Delete selected rows",
|
|
45
|
+
"column deleted label": "Column deleted",
|
|
46
|
+
"new column button label": "Create column",
|
|
47
|
+
"create new object label": "Create new object \u201C{{text}}\u201D",
|
|
48
|
+
"save view label": "Save changes to view"
|
|
1668
49
|
}
|
|
1669
|
-
};
|
|
1670
|
-
}
|
|
1671
|
-
};
|
|
1672
|
-
var cellClassesForRowSelection = (selected, selectionMode) => {
|
|
1673
|
-
if (!selected) {
|
|
1674
|
-
if (selectionMode === "single") {
|
|
1675
|
-
return [
|
|
1676
|
-
"!cursor-pointer"
|
|
1677
|
-
];
|
|
1678
|
-
} else {
|
|
1679
|
-
return void 0;
|
|
1680
50
|
}
|
|
1681
51
|
}
|
|
1682
|
-
|
|
1683
|
-
case "single":
|
|
1684
|
-
return [
|
|
1685
|
-
"!bg-currentRelated hover:bg-hoverSurface",
|
|
1686
|
-
"!cursor-pointer"
|
|
1687
|
-
];
|
|
1688
|
-
case "multiple":
|
|
1689
|
-
return [
|
|
1690
|
-
"!bg-gridCellSelected"
|
|
1691
|
-
];
|
|
1692
|
-
}
|
|
1693
|
-
};
|
|
52
|
+
];
|
|
1694
53
|
|
|
1695
|
-
//
|
|
1696
|
-
import { useSignals as
|
|
1697
|
-
import
|
|
1698
|
-
import {
|
|
54
|
+
// src/components/Table/Table.tsx
|
|
55
|
+
import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
|
|
56
|
+
import React8, { forwardRef, useCallback as useCallback5, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo5, useState as useState4 } from "react";
|
|
57
|
+
import { Filter } from "@dxos/echo";
|
|
58
|
+
import { getValue } from "@dxos/echo-schema";
|
|
1699
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";
|
|
62
|
+
import { useAttention } from "@dxos/react-ui-attention";
|
|
63
|
+
import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
|
|
64
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
65
|
+
import { isNotFalsy, safeParseInt } from "@dxos/util";
|
|
66
|
+
|
|
67
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
68
|
+
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
69
|
+
import React3, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
70
|
+
import { FormatEnum, TypeEnum } from "@dxos/echo-schema";
|
|
71
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1700
72
|
import { useThemeContext } from "@dxos/react-ui";
|
|
1701
73
|
import { createMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
1702
|
-
import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as
|
|
1703
|
-
import {
|
|
74
|
+
import { GridCellEditor, cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
75
|
+
import { createLinks, tagPicker } from "@dxos/react-ui-tag-picker";
|
|
1704
76
|
|
|
1705
|
-
//
|
|
1706
|
-
import { useSignals as
|
|
1707
|
-
import
|
|
1708
|
-
import { useGridContext
|
|
1709
|
-
var CellValidationMessage = ({ validationError, __gridScope }) => {
|
|
1710
|
-
var _effect =
|
|
77
|
+
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
78
|
+
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
79
|
+
import React from "react";
|
|
80
|
+
import { useGridContext } from "@dxos/react-ui-grid";
|
|
81
|
+
var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
|
|
82
|
+
var _effect = _useSignals();
|
|
1711
83
|
try {
|
|
1712
|
-
const { editing, editBox: box } =
|
|
84
|
+
const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
|
|
1713
85
|
if (!editing || !validationError) {
|
|
1714
86
|
return null;
|
|
1715
87
|
}
|
|
1716
|
-
|
|
88
|
+
const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
|
|
89
|
+
const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
|
|
90
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
1717
91
|
role: "none",
|
|
1718
|
-
className:
|
|
92
|
+
className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
|
|
1719
93
|
style: {
|
|
1720
94
|
...{
|
|
1721
95
|
"--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
|
|
@@ -1731,108 +105,7 @@ var CellValidationMessage = ({ validationError, __gridScope }) => {
|
|
|
1731
105
|
}
|
|
1732
106
|
};
|
|
1733
107
|
|
|
1734
|
-
//
|
|
1735
|
-
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
1736
|
-
import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
|
|
1737
|
-
import { getSnapshot as getSnapshot2 } from "@dxos/echo-schema";
|
|
1738
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1739
|
-
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
1740
|
-
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
1741
|
-
import { parseCellIndex, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
1742
|
-
import { getDeep, setDeep } from "@dxos/util";
|
|
1743
|
-
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
1744
|
-
var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
1745
|
-
var _effect = _useSignals6();
|
|
1746
|
-
try {
|
|
1747
|
-
const { editing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
|
|
1748
|
-
const cellRef = useRef(null);
|
|
1749
|
-
useEffect2(() => {
|
|
1750
|
-
if (editing && editing.cellElement) {
|
|
1751
|
-
cellRef.current = editing.cellElement;
|
|
1752
|
-
}
|
|
1753
|
-
}, [
|
|
1754
|
-
editing?.cellElement
|
|
1755
|
-
]);
|
|
1756
|
-
const narrowedSchema = useMemo3(() => {
|
|
1757
|
-
if (!schema) {
|
|
1758
|
-
return void 0;
|
|
1759
|
-
}
|
|
1760
|
-
return narrowSchema(schema, [
|
|
1761
|
-
fieldProjection.field.path
|
|
1762
|
-
]);
|
|
1763
|
-
}, [
|
|
1764
|
-
JSON.stringify(schema),
|
|
1765
|
-
fieldProjection.field.path
|
|
1766
|
-
]);
|
|
1767
|
-
const originalRow = useMemo3(() => {
|
|
1768
|
-
if (model && editing) {
|
|
1769
|
-
const cell = parseCellIndex(editing.index);
|
|
1770
|
-
const row = model.getRowAt(cell.row);
|
|
1771
|
-
invariant2(row, void 0, {
|
|
1772
|
-
F: __dxlog_file3,
|
|
1773
|
-
L: 47,
|
|
1774
|
-
S: void 0,
|
|
1775
|
-
A: [
|
|
1776
|
-
"row",
|
|
1777
|
-
""
|
|
1778
|
-
]
|
|
1779
|
-
});
|
|
1780
|
-
return row;
|
|
1781
|
-
}
|
|
1782
|
-
return void 0;
|
|
1783
|
-
}, [
|
|
1784
|
-
model,
|
|
1785
|
-
editing
|
|
1786
|
-
]);
|
|
1787
|
-
const formValues = useMemo3(() => {
|
|
1788
|
-
if (originalRow) {
|
|
1789
|
-
return getSnapshot2(originalRow);
|
|
1790
|
-
}
|
|
1791
|
-
}, [
|
|
1792
|
-
originalRow
|
|
1793
|
-
]);
|
|
1794
|
-
const handleSave = useCallback3((values) => {
|
|
1795
|
-
const path = fieldProjection.field.path;
|
|
1796
|
-
const value = getDeep(values, [
|
|
1797
|
-
path
|
|
1798
|
-
]);
|
|
1799
|
-
setDeep(originalRow, [
|
|
1800
|
-
path
|
|
1801
|
-
], value);
|
|
1802
|
-
setEditing(null);
|
|
1803
|
-
}, [
|
|
1804
|
-
fieldProjection.field.path,
|
|
1805
|
-
originalRow
|
|
1806
|
-
]);
|
|
1807
|
-
const handleOpenChange = useCallback3((nextOpen) => {
|
|
1808
|
-
if (nextOpen === false) {
|
|
1809
|
-
setEditing(null);
|
|
1810
|
-
}
|
|
1811
|
-
}, [
|
|
1812
|
-
setEditing
|
|
1813
|
-
]);
|
|
1814
|
-
if (!editing) {
|
|
1815
|
-
return null;
|
|
1816
|
-
}
|
|
1817
|
-
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
1818
|
-
open: editing !== null,
|
|
1819
|
-
onOpenChange: handleOpenChange
|
|
1820
|
-
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
1821
|
-
virtualRef: cellRef
|
|
1822
|
-
}), /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
1823
|
-
tabIndex: -1,
|
|
1824
|
-
classNames: "popover-card-width"
|
|
1825
|
-
}, /* @__PURE__ */ React6.createElement(Popover3.Arrow, null), /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, /* @__PURE__ */ React6.createElement(Form2, {
|
|
1826
|
-
values: formValues,
|
|
1827
|
-
schema: narrowedSchema,
|
|
1828
|
-
onSave: handleSave
|
|
1829
|
-
}))));
|
|
1830
|
-
} finally {
|
|
1831
|
-
_effect.f();
|
|
1832
|
-
}
|
|
1833
|
-
};
|
|
1834
|
-
|
|
1835
|
-
// packages/ui/react-ui-table/src/components/TableCellEditor/extension.ts
|
|
108
|
+
// src/components/TableCellEditor/extension.ts
|
|
1836
109
|
import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
|
|
1837
110
|
import { EditorView } from "@codemirror/view";
|
|
1838
111
|
var completion = ({ debug, onQuery, onMatch }) => {
|
|
@@ -1871,28 +144,136 @@ var completion = ({ debug, onQuery, onMatch }) => {
|
|
|
1871
144
|
];
|
|
1872
145
|
};
|
|
1873
146
|
|
|
1874
|
-
//
|
|
1875
|
-
|
|
147
|
+
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
148
|
+
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
149
|
+
import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
150
|
+
import { getSnapshot } from "@dxos/echo-schema";
|
|
151
|
+
import { invariant } from "@dxos/invariant";
|
|
152
|
+
import { Popover } from "@dxos/react-ui";
|
|
153
|
+
import { Form } from "@dxos/react-ui-form";
|
|
154
|
+
import { parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
155
|
+
import { getDeep, setDeep } from "@dxos/util";
|
|
156
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
157
|
+
var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) => {
|
|
158
|
+
var _effect = _useSignals2();
|
|
159
|
+
try {
|
|
160
|
+
const { editing: contextEditing, setEditing } = useGridContext2("ArrayEditor", __gridScope);
|
|
161
|
+
const [editing, setLocalEditing] = useState(false);
|
|
162
|
+
const anchorRef = useRef(null);
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (contextEditing && contextEditing.cellElement) {
|
|
165
|
+
anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
|
|
166
|
+
setLocalEditing(true);
|
|
167
|
+
} else {
|
|
168
|
+
anchorRef.current = null;
|
|
169
|
+
setLocalEditing(false);
|
|
170
|
+
}
|
|
171
|
+
}, [
|
|
172
|
+
contextEditing
|
|
173
|
+
]);
|
|
174
|
+
const narrowedSchema = useMemo(() => {
|
|
175
|
+
if (!schema) {
|
|
176
|
+
return void 0;
|
|
177
|
+
}
|
|
178
|
+
return narrowSchema(schema, [
|
|
179
|
+
fieldProjection.field.path
|
|
180
|
+
]);
|
|
181
|
+
}, [
|
|
182
|
+
JSON.stringify(schema),
|
|
183
|
+
fieldProjection.field.path
|
|
184
|
+
]);
|
|
185
|
+
const originalRow = useMemo(() => {
|
|
186
|
+
if (model && contextEditing) {
|
|
187
|
+
const cell = parseCellIndex(contextEditing.index);
|
|
188
|
+
const row = model.getRowAt(cell.row);
|
|
189
|
+
invariant(row, void 0, {
|
|
190
|
+
F: __dxlog_file,
|
|
191
|
+
L: 55,
|
|
192
|
+
S: void 0,
|
|
193
|
+
A: [
|
|
194
|
+
"row",
|
|
195
|
+
""
|
|
196
|
+
]
|
|
197
|
+
});
|
|
198
|
+
return row;
|
|
199
|
+
}
|
|
200
|
+
return void 0;
|
|
201
|
+
}, [
|
|
202
|
+
model,
|
|
203
|
+
contextEditing
|
|
204
|
+
]);
|
|
205
|
+
const formValues = useMemo(() => {
|
|
206
|
+
if (originalRow) {
|
|
207
|
+
return getSnapshot(originalRow);
|
|
208
|
+
}
|
|
209
|
+
}, [
|
|
210
|
+
originalRow
|
|
211
|
+
]);
|
|
212
|
+
const handleSave = useCallback((values) => {
|
|
213
|
+
const path = fieldProjection.field.path;
|
|
214
|
+
const value = getDeep(values, [
|
|
215
|
+
path
|
|
216
|
+
]);
|
|
217
|
+
setDeep(originalRow, [
|
|
218
|
+
path
|
|
219
|
+
], value);
|
|
220
|
+
setEditing(null);
|
|
221
|
+
setLocalEditing(false);
|
|
222
|
+
onSave?.();
|
|
223
|
+
}, [
|
|
224
|
+
fieldProjection.field.path,
|
|
225
|
+
originalRow
|
|
226
|
+
]);
|
|
227
|
+
const handleOpenChange = useCallback((nextOpen) => {
|
|
228
|
+
if (nextOpen === false) {
|
|
229
|
+
setEditing(null);
|
|
230
|
+
onSave?.();
|
|
231
|
+
}
|
|
232
|
+
setLocalEditing(nextOpen);
|
|
233
|
+
}, []);
|
|
234
|
+
if (!editing) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
238
|
+
open: editing,
|
|
239
|
+
onOpenChange: handleOpenChange
|
|
240
|
+
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
241
|
+
virtualRef: anchorRef
|
|
242
|
+
}), /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
243
|
+
tabIndex: -1,
|
|
244
|
+
classNames: "popover-card-width density-fine"
|
|
245
|
+
}, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form, {
|
|
246
|
+
values: formValues,
|
|
247
|
+
schema: narrowedSchema,
|
|
248
|
+
onSave: handleSave
|
|
249
|
+
}))));
|
|
250
|
+
} finally {
|
|
251
|
+
_effect.f();
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
256
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
1876
257
|
var newValue = Symbol.for("newValue");
|
|
1877
258
|
var createOption = (text) => ({
|
|
1878
259
|
[newValue]: true,
|
|
1879
260
|
text
|
|
1880
261
|
});
|
|
1881
262
|
var isCreateOption = (data) => typeof data === "object" && data[newValue];
|
|
1882
|
-
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gridScope }) => {
|
|
1883
|
-
var _effect =
|
|
263
|
+
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQuery, __gridScope }) => {
|
|
264
|
+
var _effect = _useSignals3();
|
|
1884
265
|
try {
|
|
1885
|
-
const { editing } =
|
|
1886
|
-
const fieldProjection =
|
|
266
|
+
const { editing } = useGridContext3("TableValueEditor", __gridScope);
|
|
267
|
+
const fieldProjection = useMemo2(() => {
|
|
1887
268
|
if (!model || !editing) {
|
|
1888
269
|
return;
|
|
1889
270
|
}
|
|
1890
271
|
const { col } = parseCellIndex2(editing.index);
|
|
1891
|
-
const field = model.projection.
|
|
272
|
+
const field = model.projection.fields[col];
|
|
1892
273
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1893
|
-
|
|
1894
|
-
F:
|
|
1895
|
-
L:
|
|
274
|
+
invariant2(fieldProjection2, void 0, {
|
|
275
|
+
F: __dxlog_file2,
|
|
276
|
+
L: 76,
|
|
1896
277
|
S: void 0,
|
|
1897
278
|
A: [
|
|
1898
279
|
"fieldProjection",
|
|
@@ -1904,43 +285,51 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
|
|
|
1904
285
|
model,
|
|
1905
286
|
editing
|
|
1906
287
|
]);
|
|
1907
|
-
if (fieldProjection?.props.type ===
|
|
1908
|
-
return /* @__PURE__ */
|
|
288
|
+
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect) {
|
|
289
|
+
return /* @__PURE__ */ React3.createElement(FormCellEditor, {
|
|
1909
290
|
fieldProjection,
|
|
1910
291
|
model,
|
|
1911
292
|
schema,
|
|
1912
|
-
__gridScope
|
|
293
|
+
__gridScope,
|
|
294
|
+
onSave
|
|
1913
295
|
});
|
|
1914
296
|
}
|
|
1915
|
-
return /* @__PURE__ */
|
|
297
|
+
return /* @__PURE__ */ React3.createElement(TableCellEditor, {
|
|
1916
298
|
model,
|
|
1917
299
|
modals,
|
|
1918
300
|
onEnter,
|
|
1919
301
|
onFocus,
|
|
1920
302
|
onQuery,
|
|
303
|
+
onSave,
|
|
1921
304
|
__gridScope
|
|
1922
305
|
});
|
|
1923
306
|
} finally {
|
|
1924
307
|
_effect.f();
|
|
1925
308
|
}
|
|
1926
309
|
};
|
|
1927
|
-
var
|
|
1928
|
-
|
|
310
|
+
var editorSlots = {
|
|
311
|
+
scroller: {
|
|
312
|
+
className: "!plb-[--dx-grid-cell-editor-padding-block]"
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gridScope }) => {
|
|
316
|
+
var _effect = _useSignals3();
|
|
1929
317
|
try {
|
|
1930
|
-
const { id: gridId, editing, setEditing } =
|
|
318
|
+
const { id: gridId, editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
|
|
1931
319
|
const suppressNextBlur = useRef2(false);
|
|
1932
320
|
const { themeMode } = useThemeContext();
|
|
1933
|
-
const [
|
|
1934
|
-
const
|
|
321
|
+
const [validationError, setValidationError] = useState2(null);
|
|
322
|
+
const [validationVariant, setValidationVariant] = useState2("error");
|
|
323
|
+
const fieldProjection = useMemo2(() => {
|
|
1935
324
|
if (!model || !editing) {
|
|
1936
325
|
return;
|
|
1937
326
|
}
|
|
1938
327
|
const { col } = parseCellIndex2(editing.index);
|
|
1939
|
-
const field = model.projection.
|
|
328
|
+
const field = model.projection.fields[col];
|
|
1940
329
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1941
|
-
|
|
1942
|
-
F:
|
|
1943
|
-
L:
|
|
330
|
+
invariant2(fieldProjection2, void 0, {
|
|
331
|
+
F: __dxlog_file2,
|
|
332
|
+
L: 135,
|
|
1944
333
|
S: void 0,
|
|
1945
334
|
A: [
|
|
1946
335
|
"fieldProjection",
|
|
@@ -1952,20 +341,53 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1952
341
|
model,
|
|
1953
342
|
editing
|
|
1954
343
|
]);
|
|
1955
|
-
|
|
344
|
+
useEffect2(() => {
|
|
345
|
+
if (!model || !editing || !fieldProjection) {
|
|
346
|
+
setValidationError(null);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const cell = parseCellIndex2(editing.index);
|
|
350
|
+
const { row, col } = cell;
|
|
351
|
+
if (model.isDraftCell(cell)) {
|
|
352
|
+
const field = model.projection.fields[col];
|
|
353
|
+
const hasValidationError = model.hasDraftRowValidationError(row, field.path);
|
|
354
|
+
if (hasValidationError) {
|
|
355
|
+
const draftRows = model.draftRows.value;
|
|
356
|
+
if (row >= 0 && row < draftRows.length) {
|
|
357
|
+
const draftRow = draftRows[row];
|
|
358
|
+
const validationError2 = draftRow.validationErrors?.find((error) => error.path === field.path);
|
|
359
|
+
if (validationError2) {
|
|
360
|
+
setValidationError(validationError2.message);
|
|
361
|
+
setValidationVariant("warning");
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
setValidationError(null);
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
setValidationError(null);
|
|
369
|
+
}
|
|
370
|
+
}, [
|
|
371
|
+
model,
|
|
372
|
+
editing,
|
|
373
|
+
fieldProjection
|
|
374
|
+
]);
|
|
375
|
+
const handleEnter = useCallback2(async (value) => {
|
|
1956
376
|
if (!model || !editing) {
|
|
1957
377
|
return;
|
|
1958
378
|
}
|
|
1959
379
|
const cell = parseCellIndex2(editing.index);
|
|
1960
|
-
const
|
|
1961
|
-
if (
|
|
380
|
+
const validationResult = await model.validateCellData(cell, value);
|
|
381
|
+
if (validationResult.valid) {
|
|
1962
382
|
setValidationError(null);
|
|
1963
383
|
model.setCellData(cell, value);
|
|
1964
384
|
onEnter?.(cell);
|
|
1965
385
|
onFocus?.();
|
|
1966
386
|
setEditing(null);
|
|
387
|
+
onSave?.();
|
|
1967
388
|
} else {
|
|
1968
|
-
setValidationError(
|
|
389
|
+
setValidationError(validationResult.error);
|
|
390
|
+
setValidationVariant("error");
|
|
1969
391
|
}
|
|
1970
392
|
}, [
|
|
1971
393
|
model,
|
|
@@ -1974,7 +396,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1974
396
|
onFocus,
|
|
1975
397
|
setEditing
|
|
1976
398
|
]);
|
|
1977
|
-
const handleBlur =
|
|
399
|
+
const handleBlur = useCallback2(async (value) => {
|
|
1978
400
|
if (!model || !editing) {
|
|
1979
401
|
return;
|
|
1980
402
|
}
|
|
@@ -1985,7 +407,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1985
407
|
model,
|
|
1986
408
|
editing
|
|
1987
409
|
]);
|
|
1988
|
-
const handleClose =
|
|
410
|
+
const handleClose = useCallback2(async (value, event) => {
|
|
1989
411
|
if (!model || !editing || !fieldProjection) {
|
|
1990
412
|
return;
|
|
1991
413
|
}
|
|
@@ -1996,16 +418,19 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1996
418
|
setValidationError(null);
|
|
1997
419
|
model.setCellData(cell, value);
|
|
1998
420
|
setEditing(null);
|
|
421
|
+
onSave?.();
|
|
1999
422
|
onEnter?.(cell);
|
|
2000
423
|
if (event && onFocus) {
|
|
2001
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
424
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
|
|
2002
425
|
}
|
|
2003
426
|
} else {
|
|
2004
427
|
setValidationError(result.error);
|
|
428
|
+
setValidationVariant("error");
|
|
2005
429
|
}
|
|
2006
430
|
} else {
|
|
2007
431
|
setValidationError(null);
|
|
2008
432
|
setEditing(null);
|
|
433
|
+
onSave?.();
|
|
2009
434
|
if (event && onFocus) {
|
|
2010
435
|
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2011
436
|
}
|
|
@@ -2016,9 +441,10 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2016
441
|
onFocus,
|
|
2017
442
|
onEnter,
|
|
2018
443
|
fieldProjection,
|
|
2019
|
-
setEditing
|
|
444
|
+
setEditing,
|
|
445
|
+
onSave
|
|
2020
446
|
]);
|
|
2021
|
-
const extension =
|
|
447
|
+
const extension = useMemo2(() => {
|
|
2022
448
|
if (!fieldProjection) {
|
|
2023
449
|
return [];
|
|
2024
450
|
}
|
|
@@ -2031,15 +457,15 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2031
457
|
})
|
|
2032
458
|
];
|
|
2033
459
|
const format = fieldProjection.props.format;
|
|
2034
|
-
if (format ===
|
|
460
|
+
if (format === FormatEnum.SingleSelect || format === FormatEnum.MultiSelect) {
|
|
2035
461
|
extension2.push(createMarkdownExtensions({
|
|
2036
462
|
themeMode
|
|
2037
463
|
}));
|
|
2038
464
|
const options = fieldProjection.props.options || [];
|
|
2039
|
-
const mode = format ===
|
|
2040
|
-
extension2.push(
|
|
465
|
+
const mode = format === FormatEnum.SingleSelect ? "single-select" : "multi-select";
|
|
466
|
+
extension2.push(tagPicker({
|
|
2041
467
|
mode,
|
|
2042
|
-
|
|
468
|
+
keymap: false,
|
|
2043
469
|
onSearch: (text, selectedIds) => {
|
|
2044
470
|
return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
|
|
2045
471
|
id: option.id,
|
|
@@ -2061,135 +487,373 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2061
487
|
}
|
|
2062
488
|
}));
|
|
2063
489
|
}
|
|
2064
|
-
if (onQuery) {
|
|
2065
|
-
switch (fieldProjection.props.format) {
|
|
2066
|
-
case
|
|
2067
|
-
extension2.push([
|
|
2068
|
-
completion({
|
|
2069
|
-
onQuery: (text) => onQuery(fieldProjection, text),
|
|
2070
|
-
onMatch: (data) => {
|
|
2071
|
-
if (model && editing && modals) {
|
|
2072
|
-
if (isCreateOption(data)) {
|
|
2073
|
-
const { field, props } = fieldProjection;
|
|
2074
|
-
if (props.referenceSchema) {
|
|
2075
|
-
suppressNextBlur.current = true;
|
|
2076
|
-
modals.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
|
|
2077
|
-
[field.referencePath]: data.text
|
|
2078
|
-
}, (data2) => {
|
|
2079
|
-
void handleEnter(data2);
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
} else {
|
|
2083
|
-
void handleEnter(data);
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
})
|
|
2088
|
-
]);
|
|
2089
|
-
break;
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
490
|
+
if (onQuery) {
|
|
491
|
+
switch (fieldProjection.props.format) {
|
|
492
|
+
case FormatEnum.Ref: {
|
|
493
|
+
extension2.push([
|
|
494
|
+
completion({
|
|
495
|
+
onQuery: (text) => onQuery(fieldProjection, text),
|
|
496
|
+
onMatch: (data) => {
|
|
497
|
+
if (model && editing && modals) {
|
|
498
|
+
if (isCreateOption(data)) {
|
|
499
|
+
const { field, props } = fieldProjection;
|
|
500
|
+
if (props.referenceSchema) {
|
|
501
|
+
suppressNextBlur.current = true;
|
|
502
|
+
modals.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
|
|
503
|
+
[field.referencePath]: data.text
|
|
504
|
+
}, (data2) => {
|
|
505
|
+
void handleEnter(data2);
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
} else {
|
|
509
|
+
void handleEnter(data);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
})
|
|
514
|
+
]);
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return extension2;
|
|
520
|
+
}, [
|
|
521
|
+
model,
|
|
522
|
+
modals,
|
|
523
|
+
editing,
|
|
524
|
+
fieldProjection,
|
|
525
|
+
handleClose,
|
|
526
|
+
themeMode
|
|
527
|
+
]);
|
|
528
|
+
const getCellContent = useCallback2(() => {
|
|
529
|
+
if (model && editing) {
|
|
530
|
+
const cell = parseCellIndex2(editing.index);
|
|
531
|
+
const { col } = cell;
|
|
532
|
+
const field = model.projection.fields[col];
|
|
533
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
534
|
+
if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
|
|
535
|
+
const value2 = model.getCellData(cell);
|
|
536
|
+
if (value2 !== void 0) {
|
|
537
|
+
const options = fieldProjection2.props.options || [];
|
|
538
|
+
if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
|
|
539
|
+
const tagItems = value2.split(",").map((id) => {
|
|
540
|
+
const option = options.find((o) => o.id === id);
|
|
541
|
+
if (option) {
|
|
542
|
+
return {
|
|
543
|
+
id,
|
|
544
|
+
label: option.title,
|
|
545
|
+
hue: option.color
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
return void 0;
|
|
549
|
+
}).filter((item) => item !== void 0);
|
|
550
|
+
return createLinks(tagItems);
|
|
551
|
+
} else {
|
|
552
|
+
const option = options.find((o) => o.id === value2);
|
|
553
|
+
if (option) {
|
|
554
|
+
const tagItem = {
|
|
555
|
+
id: value2,
|
|
556
|
+
label: option.title,
|
|
557
|
+
hue: option.color
|
|
558
|
+
};
|
|
559
|
+
return createLinks([
|
|
560
|
+
tagItem
|
|
561
|
+
]);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return "";
|
|
566
|
+
}
|
|
567
|
+
const value = model.getCellData(cell);
|
|
568
|
+
return value !== void 0 ? String(value) : "";
|
|
569
|
+
}
|
|
570
|
+
}, [
|
|
571
|
+
model,
|
|
572
|
+
editing
|
|
573
|
+
]);
|
|
574
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
|
|
575
|
+
validationError,
|
|
576
|
+
variant: validationVariant,
|
|
577
|
+
__gridScope
|
|
578
|
+
}), /* @__PURE__ */ React3.createElement(GridCellEditor, {
|
|
579
|
+
extension,
|
|
580
|
+
getCellContent,
|
|
581
|
+
onBlur: handleBlur,
|
|
582
|
+
slots: editorSlots
|
|
583
|
+
}));
|
|
584
|
+
} finally {
|
|
585
|
+
_effect.f();
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
var determineNavigationAxis = ({ key }) => {
|
|
589
|
+
switch (key) {
|
|
590
|
+
case "ArrowUp":
|
|
591
|
+
case "ArrowDown":
|
|
592
|
+
case "Enter": {
|
|
593
|
+
return "row";
|
|
594
|
+
}
|
|
595
|
+
case "ArrowLeft":
|
|
596
|
+
case "ArrowRight":
|
|
597
|
+
case "Tab":
|
|
598
|
+
return "col";
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
var determineNavigationDelta = ({ key, shift }) => {
|
|
602
|
+
switch (key) {
|
|
603
|
+
case "ArrowUp":
|
|
604
|
+
case "ArrowLeft":
|
|
605
|
+
return -1;
|
|
606
|
+
case "ArrowDown":
|
|
607
|
+
case "ArrowRight":
|
|
608
|
+
return 1;
|
|
609
|
+
}
|
|
610
|
+
return shift ? -1 : 1;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// src/components/Table/ColumnActionsMenu.tsx
|
|
614
|
+
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
615
|
+
import React4 from "react";
|
|
616
|
+
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
617
|
+
var ColumnActionsMenu = ({ model, modals }) => {
|
|
618
|
+
var _effect = _useSignals4();
|
|
619
|
+
try {
|
|
620
|
+
const { t } = useTranslation(translationKey);
|
|
621
|
+
const state = modals.state.value;
|
|
622
|
+
if (state?.type !== "column") {
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
const currentSort = model.sorting?.sorting;
|
|
626
|
+
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
627
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
628
|
+
modal: false,
|
|
629
|
+
open: true,
|
|
630
|
+
onOpenChange: modals.close
|
|
631
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
|
|
632
|
+
virtualRef: modals.trigger
|
|
633
|
+
}), /* @__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, {
|
|
634
|
+
"data-testid": "column-sort-descending",
|
|
635
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
636
|
+
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
637
|
+
"data-testid": "column-sort-ascending",
|
|
638
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
639
|
+
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
640
|
+
"data-testid": "column-clear-sort",
|
|
641
|
+
onClick: () => model.sorting?.clearSort()
|
|
642
|
+
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
643
|
+
"data-testid": "column-delete",
|
|
644
|
+
onClick: () => model.deleteColumn(state.fieldId)
|
|
645
|
+
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
646
|
+
"data-testid": "column-settings",
|
|
647
|
+
onClick: () => modals.openColumnSettings()
|
|
648
|
+
}, t("column action settings"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
|
|
649
|
+
} finally {
|
|
650
|
+
_effect.f();
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
// src/components/Table/ColumnSettings.tsx
|
|
655
|
+
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
656
|
+
import React5, { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
657
|
+
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
658
|
+
import { FieldEditor } from "@dxos/react-ui-form";
|
|
659
|
+
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
660
|
+
var _effect = _useSignals5();
|
|
661
|
+
try {
|
|
662
|
+
const [newField, setNewField] = useState3();
|
|
663
|
+
const state = modals.state.value;
|
|
664
|
+
useEffect3(() => {
|
|
665
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
666
|
+
setNewField(model.projection.createFieldProjection());
|
|
667
|
+
requestAnimationFrame(() => {
|
|
668
|
+
onNewColumn();
|
|
669
|
+
});
|
|
670
|
+
} else {
|
|
671
|
+
setNewField(void 0);
|
|
672
|
+
}
|
|
673
|
+
}, [
|
|
674
|
+
model?.projection,
|
|
675
|
+
state
|
|
676
|
+
]);
|
|
677
|
+
const existingField = useMemo3(() => {
|
|
678
|
+
if (state?.type === "columnSettings") {
|
|
679
|
+
const { mode } = state;
|
|
680
|
+
if (mode.type === "edit") {
|
|
681
|
+
return model?.projection?.fields.find((f) => f.id === mode.fieldId);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return void 0;
|
|
685
|
+
}, [
|
|
686
|
+
model?.projection?.fields,
|
|
687
|
+
state
|
|
688
|
+
]);
|
|
689
|
+
const field = existingField ?? newField;
|
|
690
|
+
const handleSave = useCallback3(() => {
|
|
691
|
+
modals.close();
|
|
692
|
+
}, [
|
|
693
|
+
modals
|
|
694
|
+
]);
|
|
695
|
+
const handleCancel = useCallback3(() => {
|
|
696
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
697
|
+
model?.projection.deleteFieldProjection(newField.id);
|
|
698
|
+
}
|
|
699
|
+
}, [
|
|
700
|
+
model?.projection,
|
|
701
|
+
state,
|
|
702
|
+
newField
|
|
703
|
+
]);
|
|
704
|
+
if (!model?.projection || !field) {
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
707
|
+
return /* @__PURE__ */ React5.createElement(Popover2.Root, {
|
|
708
|
+
modal: false,
|
|
709
|
+
open: state?.type === "columnSettings"
|
|
710
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
|
|
711
|
+
virtualRef: modals.trigger
|
|
712
|
+
}), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
|
|
713
|
+
classNames: "md:is-64"
|
|
714
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
|
|
715
|
+
projection: model.projection,
|
|
716
|
+
field,
|
|
717
|
+
registry,
|
|
718
|
+
onSave: handleSave,
|
|
719
|
+
onCancel: handleCancel
|
|
720
|
+
})), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
|
|
721
|
+
} finally {
|
|
722
|
+
_effect.f();
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
// src/components/Table/CreateRefPanel.tsx
|
|
727
|
+
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
728
|
+
import { Schema } from "effect";
|
|
729
|
+
import React6, { useCallback as useCallback4, useMemo as useMemo4 } from "react";
|
|
730
|
+
import { live } from "@dxos/live-object";
|
|
731
|
+
import { getSpace } from "@dxos/react-client/echo";
|
|
732
|
+
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
733
|
+
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
734
|
+
import { useGridContext as useGridContext4 } from "@dxos/react-ui-grid";
|
|
735
|
+
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
736
|
+
var _effect = _useSignals6();
|
|
737
|
+
try {
|
|
738
|
+
const { id: gridId } = useGridContext4("TableCellEditor", __gridScope);
|
|
739
|
+
const space = model && getSpace(model?.view);
|
|
740
|
+
const state = modals.state.value;
|
|
741
|
+
const schema = useMemo4(() => {
|
|
742
|
+
if (!space || state?.type !== "createRefPanel") {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
746
|
+
typename: state.typename
|
|
747
|
+
}).runSync();
|
|
748
|
+
if (schema2) {
|
|
749
|
+
const omit = Schema.omit("id");
|
|
750
|
+
return omit(schema2);
|
|
2092
751
|
}
|
|
2093
|
-
return extension2;
|
|
2094
752
|
}, [
|
|
2095
|
-
|
|
753
|
+
space,
|
|
754
|
+
state
|
|
755
|
+
]);
|
|
756
|
+
const handleSave = useCallback4((values) => {
|
|
757
|
+
if (!model || !space || state?.type !== "createRefPanel") {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
761
|
+
typename: state.typename
|
|
762
|
+
}).runSync();
|
|
763
|
+
if (schema2) {
|
|
764
|
+
const obj = space.db.add(live(schema2, values));
|
|
765
|
+
state.onCreate?.(obj);
|
|
766
|
+
}
|
|
767
|
+
void modals.close();
|
|
768
|
+
}, [
|
|
2096
769
|
modals,
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
handleClose,
|
|
2100
|
-
themeMode
|
|
770
|
+
space,
|
|
771
|
+
state
|
|
2101
772
|
]);
|
|
2102
|
-
const
|
|
2103
|
-
if (model
|
|
2104
|
-
|
|
2105
|
-
const { col } = cell;
|
|
2106
|
-
const field = model.projection.view.fields[col];
|
|
2107
|
-
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
2108
|
-
if (fieldProjection2?.props.format === FormatEnum5.SingleSelect || fieldProjection2?.props.format === FormatEnum5.MultiSelect) {
|
|
2109
|
-
const value2 = model.getCellData(cell);
|
|
2110
|
-
if (value2 !== void 0) {
|
|
2111
|
-
const options = fieldProjection2.props.options || [];
|
|
2112
|
-
if (fieldProjection2.props.format === FormatEnum5.MultiSelect && Array.isArray(value2)) {
|
|
2113
|
-
const tagItems = value2.map((id) => {
|
|
2114
|
-
const option = options.find((o) => o.id === id);
|
|
2115
|
-
if (option) {
|
|
2116
|
-
return {
|
|
2117
|
-
id,
|
|
2118
|
-
label: option.title,
|
|
2119
|
-
hue: option.color
|
|
2120
|
-
};
|
|
2121
|
-
}
|
|
2122
|
-
return void 0;
|
|
2123
|
-
}).filter((item) => item !== void 0);
|
|
2124
|
-
return createLinks(tagItems);
|
|
2125
|
-
} else {
|
|
2126
|
-
const option = options.find((o) => o.id === value2);
|
|
2127
|
-
if (option) {
|
|
2128
|
-
const tagItem = {
|
|
2129
|
-
id: value2,
|
|
2130
|
-
label: option.title,
|
|
2131
|
-
hue: option.color
|
|
2132
|
-
};
|
|
2133
|
-
return createLinks([
|
|
2134
|
-
tagItem
|
|
2135
|
-
]);
|
|
2136
|
-
}
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
return "";
|
|
2140
|
-
}
|
|
2141
|
-
const value = model.getCellData(cell);
|
|
2142
|
-
return value !== void 0 ? String(value) : "";
|
|
773
|
+
const handleCancel = useCallback4(() => {
|
|
774
|
+
if (model) {
|
|
775
|
+
modals.close();
|
|
2143
776
|
}
|
|
2144
777
|
}, [
|
|
2145
|
-
|
|
2146
|
-
editing
|
|
778
|
+
modals
|
|
2147
779
|
]);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
780
|
+
if (!model?.projection) {
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
784
|
+
modal: false,
|
|
785
|
+
open: state?.type === "createRefPanel" && !!schema,
|
|
786
|
+
onOpenChange: (nextOpen) => {
|
|
787
|
+
if (model && !nextOpen) {
|
|
788
|
+
return modals.close();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
792
|
+
virtualRef: modals.trigger
|
|
793
|
+
}), /* @__PURE__ */ React6.createElement(Popover3.Portal, null, /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
794
|
+
classNames: "md:is-64",
|
|
795
|
+
"data-grid": gridId
|
|
796
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React6.createElement(Form2, {
|
|
797
|
+
schema,
|
|
798
|
+
values: state.initialValues ?? {},
|
|
799
|
+
onSave: handleSave,
|
|
800
|
+
onCancel: handleCancel
|
|
801
|
+
})), /* @__PURE__ */ React6.createElement(Popover3.Arrow, null))));
|
|
2156
802
|
} finally {
|
|
2157
803
|
_effect.f();
|
|
2158
804
|
}
|
|
2159
805
|
};
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
806
|
+
|
|
807
|
+
// src/components/Table/RowActionsMenu.tsx
|
|
808
|
+
import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
|
|
809
|
+
import React7 from "react";
|
|
810
|
+
import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
811
|
+
var RowActionsMenu = ({ model, modals }) => {
|
|
812
|
+
var _effect = _useSignals7();
|
|
813
|
+
try {
|
|
814
|
+
const { t } = useTranslation2(translationKey);
|
|
815
|
+
const hasSelection = model.selection.hasSelection.value;
|
|
816
|
+
const state = modals.state.value;
|
|
817
|
+
if (state?.type !== "row") {
|
|
818
|
+
return null;
|
|
2166
819
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
820
|
+
return /* @__PURE__ */ React7.createElement(DropdownMenu2.Root, {
|
|
821
|
+
modal: false,
|
|
822
|
+
open: true,
|
|
823
|
+
onOpenChange: modals.close
|
|
824
|
+
}, /* @__PURE__ */ React7.createElement(DropdownMenu2.VirtualTrigger, {
|
|
825
|
+
virtualRef: modals.trigger
|
|
826
|
+
}), /* @__PURE__ */ React7.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React7.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
827
|
+
"data-testid": "row-menu-delete",
|
|
828
|
+
onClick: () => model.deleteRow(state.rowIndex)
|
|
829
|
+
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
830
|
+
key: action.id,
|
|
831
|
+
"data-testid": `row-action-${action.id}`,
|
|
832
|
+
onClick: () => {
|
|
833
|
+
modals.close();
|
|
834
|
+
model.handleRowAction(action.id, state.rowIndex);
|
|
835
|
+
}
|
|
836
|
+
}, toLocalizedString(action.label, t)))), /* @__PURE__ */ React7.createElement(DropdownMenu2.Arrow, null)));
|
|
837
|
+
} finally {
|
|
838
|
+
_effect.f();
|
|
2181
839
|
}
|
|
2182
|
-
return shift ? -1 : 1;
|
|
2183
840
|
};
|
|
2184
841
|
|
|
2185
|
-
//
|
|
2186
|
-
var
|
|
2187
|
-
var TableRoot = ({ children, role }) => {
|
|
842
|
+
// src/components/Table/Table.tsx
|
|
843
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
|
|
844
|
+
var TableRoot = ({ children, role = "article" }) => {
|
|
2188
845
|
var _effect = _useSignals8();
|
|
2189
846
|
try {
|
|
2190
847
|
return /* @__PURE__ */ React8.createElement("div", {
|
|
2191
848
|
role: "none",
|
|
2192
|
-
className:
|
|
849
|
+
className: mx("relative !border-separator [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]", role === "card--popover" && "popover-card-height", role === "section" && "attention-surface", role === "card--intrinsic" && "[&_.dx-grid]:bs-[--dx-grid-content-block-size]", [
|
|
850
|
+
"card--popover",
|
|
851
|
+
"section",
|
|
852
|
+
"card--extrinsic"
|
|
853
|
+
].includes(role) && "overflow-hidden", [
|
|
854
|
+
"article",
|
|
855
|
+
"slide"
|
|
856
|
+
].includes(role) && "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:bs-0")
|
|
2193
857
|
}, children);
|
|
2194
858
|
} finally {
|
|
2195
859
|
_effect.f();
|
|
@@ -2198,24 +862,27 @@ var TableRoot = ({ children, role }) => {
|
|
|
2198
862
|
var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
|
|
2199
863
|
var _effect = _useSignals8();
|
|
2200
864
|
try {
|
|
2201
|
-
const [dxGrid, setDxGrid] =
|
|
865
|
+
const [dxGrid, setDxGrid] = useState4(null);
|
|
2202
866
|
const { hasAttention } = useAttention(model?.id ?? "table");
|
|
2203
867
|
const { t } = useTranslation3(translationKey);
|
|
2204
868
|
const modals = useMemo5(() => new ModalController(), []);
|
|
869
|
+
const draftRowCount = model?.getDraftRowCount() ?? 0;
|
|
2205
870
|
const frozen = useMemo5(() => {
|
|
2206
871
|
const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
|
|
2207
872
|
return {
|
|
2208
873
|
frozenRowsStart: 1,
|
|
874
|
+
frozenRowsEnd: draftRowCount,
|
|
2209
875
|
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
2210
876
|
frozenColsEnd: noActionColumn ? 0 : 1
|
|
2211
877
|
};
|
|
2212
878
|
}, [
|
|
2213
|
-
model
|
|
879
|
+
model,
|
|
880
|
+
draftRowCount
|
|
2214
881
|
]);
|
|
2215
882
|
const getCells = useCallback5((range, plane) => presentation?.getCells(range, plane) ?? {}, [
|
|
2216
883
|
presentation
|
|
2217
884
|
]);
|
|
2218
|
-
|
|
885
|
+
useEffect4(() => {
|
|
2219
886
|
if (!presentation || !dxGrid) {
|
|
2220
887
|
return;
|
|
2221
888
|
}
|
|
@@ -2232,19 +899,42 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2232
899
|
return {
|
|
2233
900
|
update: (cell) => {
|
|
2234
901
|
if (cell) {
|
|
2235
|
-
dxGrid.updateIfWithinBounds(cell);
|
|
902
|
+
dxGrid.updateIfWithinBounds(cell, true);
|
|
2236
903
|
} else {
|
|
2237
904
|
dxGrid.updateCells(true);
|
|
2238
905
|
dxGrid.requestUpdate();
|
|
2239
906
|
}
|
|
907
|
+
},
|
|
908
|
+
focusDraft: () => {
|
|
909
|
+
requestAnimationFrame(() => {
|
|
910
|
+
dxGrid.setFocus({
|
|
911
|
+
plane: "frozenRowsEnd",
|
|
912
|
+
col: 0,
|
|
913
|
+
row: 0
|
|
914
|
+
});
|
|
915
|
+
dxGrid.refocus();
|
|
916
|
+
});
|
|
2240
917
|
}
|
|
2241
918
|
};
|
|
2242
919
|
}, [
|
|
2243
920
|
presentation,
|
|
2244
921
|
dxGrid
|
|
2245
922
|
]);
|
|
923
|
+
const handleSaveDraftRow = useCallback5((rowIndex = 0) => {
|
|
924
|
+
if (model && dxGrid) {
|
|
925
|
+
const didCommitSuccessfully = model.commitDraftRow(rowIndex);
|
|
926
|
+
if (didCommitSuccessfully) {
|
|
927
|
+
requestAnimationFrame(() => {
|
|
928
|
+
dxGrid.scrollToEndRow();
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}, [
|
|
933
|
+
model,
|
|
934
|
+
dxGrid
|
|
935
|
+
]);
|
|
2246
936
|
const handleGridClick = useCallback5((event) => {
|
|
2247
|
-
const rowIndex = safeParseInt(event.target.ariaRowIndex ?? "");
|
|
937
|
+
const rowIndex = safeParseInt(event.target.closest("[aria-rowindex]")?.ariaRowIndex ?? "");
|
|
2248
938
|
if (rowIndex != null) {
|
|
2249
939
|
if (onRowClick) {
|
|
2250
940
|
const row = model?.getRowAt(rowIndex);
|
|
@@ -2283,6 +973,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2283
973
|
model?.sorting?.toggleSort(data.fieldId);
|
|
2284
974
|
break;
|
|
2285
975
|
}
|
|
976
|
+
case "saveDraftRow": {
|
|
977
|
+
handleSaveDraftRow();
|
|
978
|
+
break;
|
|
979
|
+
}
|
|
2286
980
|
}
|
|
2287
981
|
return;
|
|
2288
982
|
}
|
|
@@ -2316,31 +1010,35 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2316
1010
|
}
|
|
2317
1011
|
}, [
|
|
2318
1012
|
model,
|
|
2319
|
-
modals
|
|
2320
|
-
]);
|
|
2321
|
-
const handleFocus = useCallback5((increment, delta) => {
|
|
2322
|
-
if (dxGrid) {
|
|
2323
|
-
dxGrid.refocus(increment, delta);
|
|
2324
|
-
}
|
|
2325
|
-
}, [
|
|
1013
|
+
modals,
|
|
2326
1014
|
dxGrid
|
|
2327
1015
|
]);
|
|
2328
|
-
const
|
|
2329
|
-
if (
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
1016
|
+
const handleFocus = useCallback5((increment, delta, cell) => {
|
|
1017
|
+
if (dxGrid && model) {
|
|
1018
|
+
if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1) {
|
|
1019
|
+
if (draftRowCount < 1) {
|
|
1020
|
+
model.insertRow();
|
|
1021
|
+
}
|
|
1022
|
+
dxGrid.setFocus({
|
|
1023
|
+
plane: "frozenRowsEnd",
|
|
1024
|
+
col: 0,
|
|
1025
|
+
row: 0
|
|
1026
|
+
});
|
|
1027
|
+
} else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
|
|
1028
|
+
handleSaveDraftRow(cell.row);
|
|
1029
|
+
model.insertRow();
|
|
1030
|
+
dxGrid.setFocus({
|
|
1031
|
+
plane: "frozenRowsEnd",
|
|
1032
|
+
col: 0,
|
|
1033
|
+
row: 0
|
|
2338
1034
|
});
|
|
1035
|
+
} else {
|
|
1036
|
+
dxGrid.refocus(increment, delta);
|
|
2339
1037
|
}
|
|
2340
1038
|
}
|
|
2341
1039
|
}, [
|
|
2342
|
-
|
|
2343
|
-
|
|
1040
|
+
dxGrid,
|
|
1041
|
+
model
|
|
2344
1042
|
]);
|
|
2345
1043
|
const handleKeyDown = useCallback5((event) => {
|
|
2346
1044
|
if (!model?.features.dataEditable) {
|
|
@@ -2353,7 +1051,11 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2353
1051
|
switch (event.key) {
|
|
2354
1052
|
case "Backspace":
|
|
2355
1053
|
case "Delete": {
|
|
2356
|
-
|
|
1054
|
+
try {
|
|
1055
|
+
model.setCellData(cell, void 0);
|
|
1056
|
+
event.preventDefault();
|
|
1057
|
+
} catch {
|
|
1058
|
+
}
|
|
2357
1059
|
break;
|
|
2358
1060
|
}
|
|
2359
1061
|
}
|
|
@@ -2387,10 +1089,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2387
1089
|
]);
|
|
2388
1090
|
const handleQuery = useCallback5(async ({ field, props }, text) => {
|
|
2389
1091
|
if (model && props.referenceSchema && field.referencePath) {
|
|
2390
|
-
const space = model.
|
|
2391
|
-
|
|
2392
|
-
F:
|
|
2393
|
-
L:
|
|
1092
|
+
const space = getSpace2(model.view);
|
|
1093
|
+
invariant3(space, void 0, {
|
|
1094
|
+
F: __dxlog_file3,
|
|
1095
|
+
L: 336,
|
|
2394
1096
|
S: void 0,
|
|
2395
1097
|
A: [
|
|
2396
1098
|
"space",
|
|
@@ -2407,7 +1109,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2407
1109
|
if (schema2) {
|
|
2408
1110
|
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
2409
1111
|
const options = objects.map((obj) => {
|
|
2410
|
-
const value =
|
|
1112
|
+
const value = getValue(obj, field.referencePath);
|
|
2411
1113
|
if (!value || typeof value !== "string") {
|
|
2412
1114
|
return void 0;
|
|
2413
1115
|
}
|
|
@@ -2433,6 +1135,12 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2433
1135
|
client,
|
|
2434
1136
|
t
|
|
2435
1137
|
]);
|
|
1138
|
+
const handleSave = useCallback5(() => {
|
|
1139
|
+
dxGrid?.updateCells(true);
|
|
1140
|
+
dxGrid?.requestUpdate();
|
|
1141
|
+
}, [
|
|
1142
|
+
dxGrid
|
|
1143
|
+
]);
|
|
2436
1144
|
if (!model || !modals) {
|
|
2437
1145
|
return /* @__PURE__ */ React8.createElement("span", {
|
|
2438
1146
|
role: "none",
|
|
@@ -2445,20 +1153,19 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2445
1153
|
model,
|
|
2446
1154
|
modals,
|
|
2447
1155
|
schema,
|
|
2448
|
-
onEnter: handleEnter,
|
|
2449
1156
|
onFocus: handleFocus,
|
|
2450
|
-
onQuery: handleQuery
|
|
1157
|
+
onQuery: handleQuery,
|
|
1158
|
+
onSave: handleSave
|
|
2451
1159
|
}), /* @__PURE__ */ React8.createElement(Grid.Content, {
|
|
2452
|
-
className:
|
|
1160
|
+
className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
2453
1161
|
frozen,
|
|
2454
|
-
// getCells={getCells}
|
|
2455
1162
|
columns: model.columnMeta.value,
|
|
2456
1163
|
limitRows: model.getRowCount() ?? 0,
|
|
2457
|
-
limitColumns: model.
|
|
1164
|
+
limitColumns: model.projection.fields.length,
|
|
2458
1165
|
overscroll: "trap",
|
|
2459
1166
|
onAxisResize: handleAxisResize,
|
|
2460
1167
|
onClick: handleGridClick,
|
|
2461
|
-
|
|
1168
|
+
onKeyDownCapture: handleKeyDown,
|
|
2462
1169
|
onWheelCapture: handleWheel,
|
|
2463
1170
|
ref: setDxGrid
|
|
2464
1171
|
}), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
|
|
@@ -2484,116 +1191,33 @@ var Table = {
|
|
|
2484
1191
|
Main: TableMain
|
|
2485
1192
|
};
|
|
2486
1193
|
|
|
2487
|
-
//
|
|
2488
|
-
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2489
|
-
import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
|
|
2490
|
-
import { useDefaultValue } from "@dxos/react-ui";
|
|
2491
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
2492
|
-
|
|
2493
|
-
// packages/ui/react-ui-table/src/hooks/useTableModel.ts
|
|
1194
|
+
// src/components/Table/DynamicTable.tsx
|
|
2494
1195
|
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
2495
|
-
import {
|
|
2496
|
-
import
|
|
2497
|
-
import {
|
|
2498
|
-
|
|
2499
|
-
import { useSelectionActions } from "@dxos/react-ui-attention";
|
|
2500
|
-
import { isNonNullable } from "@dxos/util";
|
|
2501
|
-
var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
1196
|
+
import React9, { useCallback as useCallback6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
1197
|
+
import { useDefaultValue } from "@dxos/react-ui";
|
|
1198
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1199
|
+
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2502
1200
|
var _effect = _useSignals9();
|
|
2503
1201
|
try {
|
|
2504
|
-
const
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
const t = setTimeout(async () => {
|
|
2511
|
-
model2 = new TableModel({
|
|
2512
|
-
id: fullyQualifiedId(table),
|
|
2513
|
-
space: getSpace(table),
|
|
2514
|
-
view: table.view?.target,
|
|
2515
|
-
projection,
|
|
2516
|
-
features,
|
|
2517
|
-
rowActions,
|
|
2518
|
-
onRowAction,
|
|
2519
|
-
...props
|
|
2520
|
-
});
|
|
2521
|
-
await model2.open();
|
|
2522
|
-
setModel(model2);
|
|
2523
|
-
});
|
|
2524
|
-
return () => {
|
|
2525
|
-
clearTimeout(t);
|
|
2526
|
-
void model2?.close();
|
|
2527
|
-
};
|
|
2528
|
-
}, [
|
|
2529
|
-
table,
|
|
2530
|
-
projection,
|
|
2531
|
-
table?.view?.target,
|
|
2532
|
-
features,
|
|
2533
|
-
rowActions
|
|
2534
|
-
]);
|
|
2535
|
-
useEffect4(() => {
|
|
2536
|
-
if (rows) {
|
|
2537
|
-
const sortedRows = orderBy2(rows, [
|
|
2538
|
-
(row) => String(row.id)
|
|
2539
|
-
], [
|
|
2540
|
-
"asc"
|
|
2541
|
-
]);
|
|
2542
|
-
model?.setRows(sortedRows);
|
|
2543
|
-
}
|
|
2544
|
-
}, [
|
|
2545
|
-
model,
|
|
2546
|
-
rows
|
|
2547
|
-
]);
|
|
2548
|
-
const { multiSelect, clear } = useSelectionActions([
|
|
2549
|
-
table?.id,
|
|
2550
|
-
table?.view?.target?.query.typename
|
|
2551
|
-
].filter(isNonNullable));
|
|
2552
|
-
useEffect4(() => {
|
|
2553
|
-
if (!model) {
|
|
2554
|
-
return;
|
|
2555
|
-
}
|
|
2556
|
-
const unsubscribe = effect3(() => {
|
|
2557
|
-
const selectedItems = [
|
|
2558
|
-
...model.selection.selection.value
|
|
2559
|
-
];
|
|
2560
|
-
multiSelect(selectedItems);
|
|
2561
|
-
onSelectionChanged?.(selectedItems);
|
|
2562
|
-
});
|
|
2563
|
-
return () => {
|
|
2564
|
-
clear();
|
|
2565
|
-
unsubscribe();
|
|
2566
|
-
};
|
|
2567
|
-
}, [
|
|
2568
|
-
model,
|
|
2569
|
-
onSelectionChanged
|
|
2570
|
-
]);
|
|
2571
|
-
return model;
|
|
2572
|
-
} finally {
|
|
2573
|
-
_effect.f();
|
|
2574
|
-
}
|
|
2575
|
-
};
|
|
2576
|
-
|
|
2577
|
-
// packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
|
|
2578
|
-
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2579
|
-
var _effect = _useSignals10();
|
|
2580
|
-
try {
|
|
2581
|
-
const { table, projection } = useMemo6(() => {
|
|
2582
|
-
const props2 = getBaseSchema({
|
|
2583
|
-
typename: name,
|
|
2584
|
-
properties,
|
|
2585
|
-
jsonSchema,
|
|
2586
|
-
schema
|
|
2587
|
-
});
|
|
2588
|
-
return makeDynamicTable({
|
|
2589
|
-
...props2,
|
|
2590
|
-
properties
|
|
2591
|
-
});
|
|
2592
|
-
}, [
|
|
1202
|
+
const { typename, jsonSchema } = useMemo6(() => getBaseSchema({
|
|
1203
|
+
typename: name,
|
|
1204
|
+
properties,
|
|
1205
|
+
jsonSchema: _jsonSchema,
|
|
1206
|
+
schema
|
|
1207
|
+
}), [
|
|
2593
1208
|
name,
|
|
2594
1209
|
properties,
|
|
2595
|
-
|
|
2596
|
-
|
|
1210
|
+
_jsonSchema,
|
|
1211
|
+
schema
|
|
1212
|
+
]);
|
|
1213
|
+
const { projection, view } = useMemo6(() => makeDynamicTable({
|
|
1214
|
+
typename,
|
|
1215
|
+
jsonSchema,
|
|
1216
|
+
properties
|
|
1217
|
+
}), [
|
|
1218
|
+
typename,
|
|
1219
|
+
jsonSchema,
|
|
1220
|
+
properties
|
|
2597
1221
|
]);
|
|
2598
1222
|
const tableRef = useRef3(null);
|
|
2599
1223
|
const handleCellUpdate = useCallback6((cell) => {
|
|
@@ -2609,8 +1233,9 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2609
1233
|
dataEditable: false
|
|
2610
1234
|
}));
|
|
2611
1235
|
const model = useTableModel({
|
|
2612
|
-
table,
|
|
2613
1236
|
rows,
|
|
1237
|
+
view,
|
|
1238
|
+
schema: jsonSchema,
|
|
2614
1239
|
projection,
|
|
2615
1240
|
features,
|
|
2616
1241
|
rowActions,
|
|
@@ -2627,7 +1252,7 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2627
1252
|
]);
|
|
2628
1253
|
return /* @__PURE__ */ React9.createElement("div", {
|
|
2629
1254
|
role: "none",
|
|
2630
|
-
className:
|
|
1255
|
+
className: mx2("is-full bs-full grow grid", classNames)
|
|
2631
1256
|
}, /* @__PURE__ */ React9.createElement("div", {
|
|
2632
1257
|
role: "none",
|
|
2633
1258
|
className: "grid min-bs-0 overflow-hidden"
|
|
@@ -2643,12 +1268,12 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2643
1268
|
}
|
|
2644
1269
|
};
|
|
2645
1270
|
|
|
2646
|
-
//
|
|
2647
|
-
import { useSignals as
|
|
1271
|
+
// src/components/TableToolbar/TableToolbar.tsx
|
|
1272
|
+
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2648
1273
|
import { Rx } from "@effect-rx/rx-react";
|
|
2649
1274
|
import React10, { useMemo as useMemo7 } from "react";
|
|
2650
|
-
import { live as
|
|
2651
|
-
import {
|
|
1275
|
+
import { live as live2 } from "@dxos/live-object";
|
|
1276
|
+
import { MenuProvider, ToolbarMenu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
|
|
2652
1277
|
import { rxFromSignal } from "@dxos/react-ui-menu";
|
|
2653
1278
|
var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
|
|
2654
1279
|
const add = createMenuAction("add-row", onAdd, {
|
|
@@ -2696,9 +1321,9 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
|
|
|
2696
1321
|
};
|
|
2697
1322
|
});
|
|
2698
1323
|
var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
|
|
2699
|
-
var _effect =
|
|
1324
|
+
var _effect = _useSignals10();
|
|
2700
1325
|
try {
|
|
2701
|
-
const state = useMemo7(() =>
|
|
1326
|
+
const state = useMemo7(() => live2({
|
|
2702
1327
|
viewDirty
|
|
2703
1328
|
}), []);
|
|
2704
1329
|
const actionsCreator = useMemo7(() => createTableToolbarActions({
|
|
@@ -2733,18 +1358,17 @@ export {
|
|
|
2733
1358
|
Table,
|
|
2734
1359
|
TableModel,
|
|
2735
1360
|
TablePresentation,
|
|
2736
|
-
TableSchema,
|
|
2737
1361
|
TableToolbar,
|
|
2738
|
-
TableType,
|
|
2739
1362
|
cellClassesForRowSelection,
|
|
1363
|
+
createTable,
|
|
2740
1364
|
getBaseSchema,
|
|
2741
|
-
initializeTable,
|
|
2742
1365
|
makeDynamicTable,
|
|
2743
1366
|
narrowSchema,
|
|
2744
1367
|
tableButtons,
|
|
2745
1368
|
tableControls,
|
|
2746
1369
|
touch,
|
|
2747
|
-
|
|
1370
|
+
translations,
|
|
1371
|
+
useAddRow,
|
|
2748
1372
|
useTableModel
|
|
2749
1373
|
};
|
|
2750
1374
|
//# sourceMappingURL=index.mjs.map
|