@dxos/react-ui-table 0.8.4-main.f9ba587 → 0.8.4-main.fcc0d83b33
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-FBURZBPH.mjs +70 -0
- package/dist/lib/browser/chunk-FBURZBPH.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/chunk-YGC7LZJN.mjs +1695 -0
- package/dist/lib/browser/chunk-YGC7LZJN.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1158 -2872
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +115 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/browser/translations.mjs +36 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +4 -5
- package/dist/lib/node-esm/chunk-DKKMSVKP.mjs +71 -0
- package/dist/lib/node-esm/chunk-DKKMSVKP.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-GKIWDEZ7.mjs +1697 -0
- package/dist/lib/node-esm/chunk-GKIWDEZ7.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1158 -2872
- 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 +116 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/lib/node-esm/translations.mjs +37 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +4 -5
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +2 -3
- 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/DynamicTable.d.ts +7 -7
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +35 -3
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +111 -0
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +21 -18
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +110 -6
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +17 -0
- package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +14 -9
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +12 -18
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +38 -5
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +26 -56
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +6 -6
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +11 -10
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +5 -8
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +18 -8
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +116 -34
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +5 -2
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/playwright/TableManager.d.ts +2 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
- 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 +25 -0
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +21 -23
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +26 -0
- package/dist/types/src/types/Table.d.ts.map +1 -0
- 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/util/dynamic-table.d.ts +15 -14
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
- package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +2 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts +7 -0
- package/dist/types/src/util/query-ast.d.ts.map +1 -0
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/src/util/signals.d.ts.map +1 -1
- package/dist/types/src/util/sort.d.ts +12 -0
- package/dist/types/src/util/sort.d.ts.map +1 -0
- package/dist/types/src/util/table-buttons.d.ts +20 -20
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +4 -4
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/tag.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +80 -69
- package/src/components/Table/ColumnActionsMenu.tsx +18 -13
- package/src/components/Table/ColumnSettings.tsx +18 -15
- package/src/components/Table/DynamicTable.stories.tsx +40 -36
- package/src/components/Table/DynamicTable.tsx +38 -34
- package/src/components/Table/Relations.stories.tsx +281 -0
- package/src/components/Table/RowActionsMenu.tsx +28 -18
- package/src/components/Table/Table.stories.tsx +198 -220
- package/src/components/Table/Table.tsx +47 -376
- package/src/components/Table/TableContent.tsx +421 -0
- package/src/components/Table/TableToolbar.tsx +111 -0
- package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -6
- package/src/components/TableCellEditor/FormCellEditor.tsx +153 -49
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +38 -77
- package/src/components/TableCellEditor/TableCellEditor.tsx +104 -233
- package/src/components/TableCellEditor/index.ts +1 -0
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +46 -37
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useAddRow.ts +14 -14
- package/src/hooks/useProjectionModel.ts +39 -0
- package/src/hooks/useTableModel.ts +41 -35
- package/src/index.ts +0 -5
- package/src/model/modal-controller.ts +24 -41
- package/src/model/selection-model.ts +75 -41
- package/src/model/table-model.test.ts +91 -56
- package/src/model/table-model.ts +468 -187
- package/src/model/table-presentation.test.ts +77 -60
- package/src/model/table-presentation.ts +112 -66
- package/src/playwright/TableManager.ts +13 -6
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +180 -43
- package/src/testing/index.ts +5 -0
- package/src/testing/useTestTableModel.ts +133 -0
- package/src/translations.ts +20 -22
- package/src/types/Table.ts +79 -0
- package/src/types/index.ts +2 -2
- package/src/util/dynamic-table.test.ts +77 -0
- package/src/util/dynamic-table.ts +51 -36
- package/src/util/index.ts +2 -1
- package/src/util/query-ast.ts +22 -0
- package/src/util/schema.ts +4 -4
- package/src/util/sort.ts +90 -0
- package/src/util/table-buttons.ts +4 -3
- package/src/util/table-controls.ts +6 -3
- package/dist/lib/browser/chunk-Q5QQXJUO.mjs +0 -27
- package/dist/lib/browser/chunk-Q5QQXJUO.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs +0 -29
- package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs.map +0 -7
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
- package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
- package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
- package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
- package/dist/types/src/model/table-sorting.d.ts +0 -53
- package/dist/types/src/model/table-sorting.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/dist/types/src/util/table.d.ts +0 -14
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/Table/CreateRefPanel.tsx +0 -84
- package/src/components/Table/relations.stories.tsx +0 -123
- package/src/components/TableCellEditor/extension.ts +0 -61
- package/src/components/TableToolbar/TableToolbar.tsx +0 -102
- package/src/components/TableToolbar/index.ts +0 -5
- package/src/model/table-sorting.ts +0 -216
- package/src/types/table.ts +0 -27
- package/src/util/table.ts +0 -127
|
@@ -1,313 +1,57 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"column action clear sorting": "Clear Sorting",
|
|
26
|
-
"column action settings": "Column Settings",
|
|
27
|
-
"column action delete": "Delete Column",
|
|
28
|
-
"delete row label": "Delete row",
|
|
29
|
-
"bulk delete row label": "Delete selected rows",
|
|
30
|
-
"column deleted label": "Column deleted",
|
|
31
|
-
"new column button label": "Create column",
|
|
32
|
-
"create new object label": "Create new object \u201C{{text}}\u201D",
|
|
33
|
-
"save view label": "Save changes to view"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
];
|
|
3
|
+
BUTTON_IDENTIFIERS,
|
|
4
|
+
CONTROL_IDENTIFIERS,
|
|
5
|
+
CheckboxStory,
|
|
6
|
+
SwitchStory,
|
|
7
|
+
TableModel,
|
|
8
|
+
TablePresentation,
|
|
9
|
+
cellClassesForRowSelection,
|
|
10
|
+
compareValues,
|
|
11
|
+
createDirectChangeCallback,
|
|
12
|
+
createEchoChangeCallback,
|
|
13
|
+
extractOrder,
|
|
14
|
+
getSortValue,
|
|
15
|
+
tableButtons,
|
|
16
|
+
tableControls,
|
|
17
|
+
useAddRow,
|
|
18
|
+
useProjectionModel,
|
|
19
|
+
useTableModel
|
|
20
|
+
} from "./chunk-GKIWDEZ7.mjs";
|
|
21
|
+
import {
|
|
22
|
+
Table_exports
|
|
23
|
+
} from "./chunk-DKKMSVKP.mjs";
|
|
24
|
+
import "./chunk-HSLMI22Q.mjs";
|
|
38
25
|
|
|
39
26
|
// src/components/Table/Table.tsx
|
|
40
|
-
import {
|
|
41
|
-
import
|
|
42
|
-
import {
|
|
43
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
44
|
-
import { Filter } from "@dxos/react-client/echo";
|
|
45
|
-
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
46
|
-
import { useAttention } from "@dxos/react-ui-attention";
|
|
47
|
-
import { closestCell, Grid, gridSeparatorInlineEnd, gridSeparatorBlockEnd } from "@dxos/react-ui-grid";
|
|
48
|
-
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
49
|
-
import { isNotFalsy, safeParseInt } from "@dxos/util";
|
|
50
|
-
|
|
51
|
-
// src/components/Table/ColumnActionsMenu.tsx
|
|
52
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
53
|
-
import React from "react";
|
|
54
|
-
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
55
|
-
var ColumnActionsMenu = ({ model, modals }) => {
|
|
56
|
-
var _effect = _useSignals();
|
|
57
|
-
try {
|
|
58
|
-
const { t } = useTranslation(translationKey);
|
|
59
|
-
const state = modals.state.value;
|
|
60
|
-
if (state?.type !== "column") {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
const currentSort = model.sorting?.sorting;
|
|
64
|
-
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
65
|
-
return /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
|
|
66
|
-
modal: false,
|
|
67
|
-
open: true,
|
|
68
|
-
onOpenChange: modals.close
|
|
69
|
-
}, /* @__PURE__ */ React.createElement(DropdownMenu.VirtualTrigger, {
|
|
70
|
-
virtualRef: modals.trigger
|
|
71
|
-
}), /* @__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, {
|
|
72
|
-
"data-testid": "column-sort-descending",
|
|
73
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
74
|
-
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
75
|
-
"data-testid": "column-sort-ascending",
|
|
76
|
-
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
77
|
-
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
78
|
-
"data-testid": "column-clear-sort",
|
|
79
|
-
onClick: () => model.sorting?.clearSort()
|
|
80
|
-
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
81
|
-
"data-testid": "column-delete",
|
|
82
|
-
onClick: () => model.deleteColumn(state.fieldId)
|
|
83
|
-
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
|
|
84
|
-
"data-testid": "column-settings",
|
|
85
|
-
onClick: () => modals.openColumnSettings()
|
|
86
|
-
}, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
|
|
87
|
-
} finally {
|
|
88
|
-
_effect.f();
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// src/components/Table/ColumnSettings.tsx
|
|
93
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
94
|
-
import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
95
|
-
import { Popover } from "@dxos/react-ui";
|
|
96
|
-
import { FieldEditor } from "@dxos/react-ui-form";
|
|
97
|
-
var ColumnSettings = ({ model, modals, onNewColumn }) => {
|
|
98
|
-
var _effect = _useSignals2();
|
|
99
|
-
try {
|
|
100
|
-
const [newField, setNewField] = useState();
|
|
101
|
-
const state = modals.state.value;
|
|
102
|
-
const space = model?.space;
|
|
103
|
-
useEffect(() => {
|
|
104
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
105
|
-
setNewField(model.projection.createFieldProjection());
|
|
106
|
-
requestAnimationFrame(() => {
|
|
107
|
-
onNewColumn();
|
|
108
|
-
});
|
|
109
|
-
} else {
|
|
110
|
-
setNewField(void 0);
|
|
111
|
-
}
|
|
112
|
-
}, [
|
|
113
|
-
model?.projection,
|
|
114
|
-
state
|
|
115
|
-
]);
|
|
116
|
-
const existingField = useMemo(() => {
|
|
117
|
-
if (state?.type === "columnSettings") {
|
|
118
|
-
const { mode } = state;
|
|
119
|
-
if (mode.type === "edit") {
|
|
120
|
-
return model?.view?.fields.find((f) => f.id === mode.fieldId);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return void 0;
|
|
124
|
-
}, [
|
|
125
|
-
model?.view?.fields,
|
|
126
|
-
state
|
|
127
|
-
]);
|
|
128
|
-
const field = existingField ?? newField;
|
|
129
|
-
const handleSave = useCallback(() => {
|
|
130
|
-
modals.close();
|
|
131
|
-
}, [
|
|
132
|
-
modals
|
|
133
|
-
]);
|
|
134
|
-
const handleCancel = useCallback(() => {
|
|
135
|
-
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
136
|
-
model?.projection?.deleteFieldProjection(newField.id);
|
|
137
|
-
}
|
|
138
|
-
}, [
|
|
139
|
-
model?.projection,
|
|
140
|
-
state,
|
|
141
|
-
newField
|
|
142
|
-
]);
|
|
143
|
-
if (!model?.view || !model.projection || !field) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
147
|
-
modal: false,
|
|
148
|
-
open: state?.type === "columnSettings"
|
|
149
|
-
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
150
|
-
virtualRef: modals.trigger
|
|
151
|
-
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
152
|
-
classNames: "md:is-64"
|
|
153
|
-
}, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
|
|
154
|
-
view: model.view,
|
|
155
|
-
projection: model.projection,
|
|
156
|
-
field,
|
|
157
|
-
registry: space?.db.schemaRegistry,
|
|
158
|
-
onSave: handleSave,
|
|
159
|
-
onCancel: handleCancel
|
|
160
|
-
})), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
|
|
161
|
-
} finally {
|
|
162
|
-
_effect.f();
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// src/components/Table/CreateRefPanel.tsx
|
|
167
|
-
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
168
|
-
import { Schema } from "effect";
|
|
169
|
-
import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
|
|
170
|
-
import { live } from "@dxos/react-client/echo";
|
|
171
|
-
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
172
|
-
import { Form } from "@dxos/react-ui-form";
|
|
173
|
-
import { useGridContext } from "@dxos/react-ui-grid";
|
|
174
|
-
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
175
|
-
var _effect = _useSignals3();
|
|
176
|
-
try {
|
|
177
|
-
const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
|
|
178
|
-
const space = model?.space;
|
|
179
|
-
const state = modals.state.value;
|
|
180
|
-
const schema = useMemo2(() => {
|
|
181
|
-
if (!space || state?.type !== "createRefPanel") {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
185
|
-
typename: state.typename
|
|
186
|
-
}).runSync();
|
|
187
|
-
if (schema2) {
|
|
188
|
-
const omit = Schema.omit("id");
|
|
189
|
-
return omit(schema2);
|
|
190
|
-
}
|
|
191
|
-
}, [
|
|
192
|
-
space,
|
|
193
|
-
state
|
|
194
|
-
]);
|
|
195
|
-
const handleSave = useCallback2((values) => {
|
|
196
|
-
if (!model || !space || state?.type !== "createRefPanel") {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
const [schema2] = space.db.schemaRegistry.query({
|
|
200
|
-
typename: state.typename
|
|
201
|
-
}).runSync();
|
|
202
|
-
if (schema2) {
|
|
203
|
-
const obj = space.db.add(live(schema2, values));
|
|
204
|
-
state.onCreate?.(obj);
|
|
205
|
-
}
|
|
206
|
-
void modals.close();
|
|
207
|
-
}, [
|
|
208
|
-
modals,
|
|
209
|
-
space,
|
|
210
|
-
state
|
|
211
|
-
]);
|
|
212
|
-
const handleCancel = useCallback2(() => {
|
|
213
|
-
if (model) {
|
|
214
|
-
modals.close();
|
|
215
|
-
}
|
|
216
|
-
}, [
|
|
217
|
-
modals
|
|
218
|
-
]);
|
|
219
|
-
if (!model?.view || !model.projection) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
return /* @__PURE__ */ React3.createElement(Popover2.Root, {
|
|
223
|
-
modal: false,
|
|
224
|
-
open: state?.type === "createRefPanel" && !!schema,
|
|
225
|
-
onOpenChange: (nextOpen) => {
|
|
226
|
-
if (model && !nextOpen) {
|
|
227
|
-
return modals.close();
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.VirtualTrigger, {
|
|
231
|
-
virtualRef: modals.trigger
|
|
232
|
-
}), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
|
|
233
|
-
classNames: "md:is-64",
|
|
234
|
-
"data-grid": gridId
|
|
235
|
-
}, /* @__PURE__ */ React3.createElement(Popover2.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
|
|
236
|
-
schema,
|
|
237
|
-
values: state.initialValues ?? {},
|
|
238
|
-
onSave: handleSave,
|
|
239
|
-
onCancel: handleCancel
|
|
240
|
-
})), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null))));
|
|
241
|
-
} finally {
|
|
242
|
-
_effect.f();
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// src/components/Table/RowActionsMenu.tsx
|
|
247
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
248
|
-
import React4 from "react";
|
|
249
|
-
import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
250
|
-
var RowActionsMenu = ({ model, modals }) => {
|
|
251
|
-
var _effect = _useSignals4();
|
|
252
|
-
try {
|
|
253
|
-
const { t } = useTranslation2(translationKey);
|
|
254
|
-
const hasSelection = model.selection.hasSelection.value;
|
|
255
|
-
const state = modals.state.value;
|
|
256
|
-
if (state?.type !== "row") {
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
return /* @__PURE__ */ React4.createElement(DropdownMenu2.Root, {
|
|
260
|
-
modal: false,
|
|
261
|
-
open: true,
|
|
262
|
-
onOpenChange: modals.close
|
|
263
|
-
}, /* @__PURE__ */ React4.createElement(DropdownMenu2.VirtualTrigger, {
|
|
264
|
-
virtualRef: modals.trigger
|
|
265
|
-
}), /* @__PURE__ */ React4.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
266
|
-
"data-testid": "row-menu-delete",
|
|
267
|
-
onClick: () => model.deleteRow(state.rowIndex)
|
|
268
|
-
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
|
|
269
|
-
key: action.id,
|
|
270
|
-
"data-testid": `row-action-${action.id}`,
|
|
271
|
-
onClick: () => {
|
|
272
|
-
modals.close();
|
|
273
|
-
model.handleRowAction(action.id, state.rowIndex);
|
|
274
|
-
}
|
|
275
|
-
}, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu2.Arrow, null)));
|
|
276
|
-
} finally {
|
|
277
|
-
_effect.f();
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
// src/model/table-model.ts
|
|
282
|
-
import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
|
|
283
|
-
import { Resource as Resource2 } from "@dxos/context";
|
|
284
|
-
import { Ref as Ref3 } from "@dxos/echo";
|
|
285
|
-
import { FormatEnum as FormatEnum3, getValue as getValue2, setValue, getSnapshot, getSchema, toEffectSchema } from "@dxos/echo-schema";
|
|
286
|
-
import { invariant } from "@dxos/invariant";
|
|
287
|
-
import { ObjectId } from "@dxos/keys";
|
|
288
|
-
import { isLiveObject } from "@dxos/live-object";
|
|
289
|
-
import { formatForEditing, parseValue } from "@dxos/react-ui-form";
|
|
290
|
-
import { validateSchema } from "@dxos/schema";
|
|
27
|
+
import { Atom as Atom4 } from "@effect-atom/atom-react";
|
|
28
|
+
import { createContext } from "@radix-ui/react-context";
|
|
29
|
+
import React9, { forwardRef, useImperativeHandle, useRef as useRef3 } from "react";
|
|
291
30
|
|
|
292
|
-
// src/
|
|
293
|
-
import {
|
|
294
|
-
import
|
|
31
|
+
// src/components/Table/TableContent.tsx
|
|
32
|
+
import { Atom as Atom2, RegistryContext, useAtomValue as useAtomValue4 } from "@effect-atom/atom-react";
|
|
33
|
+
import * as String2 from "effect/String";
|
|
34
|
+
import React7, { useCallback as useCallback4, useContext, useEffect as useEffect3, useMemo as useMemo4, useState as useState4 } from "react";
|
|
35
|
+
import { log } from "@dxos/log";
|
|
36
|
+
import { useAttention } from "@dxos/react-ui-attention";
|
|
37
|
+
import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
|
|
38
|
+
import { DxEditRequest } from "@dxos/react-ui-grid";
|
|
39
|
+
import { composable, composableProps, mx } from "@dxos/ui-theme";
|
|
295
40
|
|
|
296
41
|
// src/util/dynamic-table.ts
|
|
297
|
-
import { Obj, Ref } from "@dxos/echo";
|
|
298
|
-
import {
|
|
299
|
-
|
|
300
|
-
var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
|
|
42
|
+
import { Filter, JsonSchema, Obj, Order, Query, Ref, Type } from "@dxos/echo";
|
|
43
|
+
import { ProjectionModel, ViewModel, createEchoChangeCallback as createEchoChangeCallback2, getSchemaFromPropertyDefinitions } from "@dxos/schema";
|
|
44
|
+
var getBaseSchema = ({ schema, typename, properties, jsonSchema }) => {
|
|
301
45
|
if (typename && properties) {
|
|
302
46
|
const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
|
|
303
47
|
return {
|
|
304
48
|
typename: schema2.typename,
|
|
305
|
-
jsonSchema: schema2
|
|
49
|
+
jsonSchema: JsonSchema.toJsonSchema(schema2)
|
|
306
50
|
};
|
|
307
51
|
} else if (schema) {
|
|
308
52
|
return {
|
|
309
|
-
typename: getTypename(schema),
|
|
310
|
-
jsonSchema: toJsonSchema(schema)
|
|
53
|
+
typename: Type.getTypename(schema),
|
|
54
|
+
jsonSchema: JsonSchema.toJsonSchema(schema)
|
|
311
55
|
};
|
|
312
56
|
} else if (typename && jsonSchema) {
|
|
313
57
|
return {
|
|
@@ -318,34 +62,41 @@ var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
|
|
|
318
62
|
throw new Error("invalid properties");
|
|
319
63
|
}
|
|
320
64
|
};
|
|
321
|
-
var makeDynamicTable = ({
|
|
322
|
-
const view =
|
|
323
|
-
|
|
324
|
-
typename,
|
|
65
|
+
var makeDynamicTable = ({ registry, jsonSchema, properties }) => {
|
|
66
|
+
const view = ViewModel.make({
|
|
67
|
+
query: Query.select(Filter.everything()),
|
|
325
68
|
jsonSchema,
|
|
326
69
|
...properties && {
|
|
327
70
|
fields: properties.map((property) => property.name)
|
|
328
71
|
}
|
|
329
72
|
});
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
73
|
+
const object = Obj.make(Table_exports.Table, {
|
|
74
|
+
view: Ref.make(view),
|
|
75
|
+
sizes: {}
|
|
76
|
+
});
|
|
77
|
+
const projection = new ProjectionModel({
|
|
78
|
+
registry,
|
|
79
|
+
view,
|
|
80
|
+
baseSchema: jsonSchema,
|
|
81
|
+
change: createEchoChangeCallback2(view, jsonSchema)
|
|
333
82
|
});
|
|
334
|
-
|
|
335
|
-
if (properties &&
|
|
336
|
-
setProperties(view, projection, properties);
|
|
83
|
+
projection.normalizeView();
|
|
84
|
+
if (properties && projection.getFields()) {
|
|
85
|
+
setProperties(view, projection, object, properties);
|
|
337
86
|
}
|
|
338
87
|
return {
|
|
339
|
-
|
|
340
|
-
|
|
88
|
+
projection,
|
|
89
|
+
object
|
|
341
90
|
};
|
|
342
91
|
};
|
|
343
|
-
var setProperties = (view, projection, properties) => {
|
|
92
|
+
var setProperties = (view, projection, table, properties) => {
|
|
344
93
|
for (const property of properties) {
|
|
345
|
-
const field =
|
|
94
|
+
const field = projection.getFields().find((field2) => field2.path === property.name);
|
|
346
95
|
if (field) {
|
|
347
96
|
if (property.size !== void 0) {
|
|
348
|
-
|
|
97
|
+
Obj.update(table, (table2) => {
|
|
98
|
+
table2.sizes[field.path] = property.size;
|
|
99
|
+
});
|
|
349
100
|
}
|
|
350
101
|
if (property.title !== void 0) {
|
|
351
102
|
const fieldProjection = projection.getFieldProjection(field.id);
|
|
@@ -358,13 +109,11 @@ var setProperties = (view, projection, properties) => {
|
|
|
358
109
|
});
|
|
359
110
|
}
|
|
360
111
|
if (property.sort) {
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
367
|
-
];
|
|
112
|
+
const currentQuery = Query.fromAst(Obj.getSnapshot(view).query.ast);
|
|
113
|
+
const newQuery = currentQuery.orderBy(Order.property(field.path, property.sort));
|
|
114
|
+
Obj.update(view, (view2) => {
|
|
115
|
+
view2.query.ast = newQuery.ast;
|
|
116
|
+
});
|
|
368
117
|
}
|
|
369
118
|
}
|
|
370
119
|
}
|
|
@@ -373,1910 +122,379 @@ var setProperties = (view, projection, properties) => {
|
|
|
373
122
|
// src/util/signals.ts
|
|
374
123
|
var touch = (value) => value;
|
|
375
124
|
|
|
376
|
-
// src/util/table.ts
|
|
377
|
-
import { Schema as Schema2 } from "effect";
|
|
378
|
-
import { Format, FormatEnum, Ref as Ref2, TypedObject, TypeEnum } from "@dxos/echo-schema";
|
|
379
|
-
import { PublicKey } from "@dxos/react-client";
|
|
380
|
-
import { live as live2 } from "@dxos/react-client/echo";
|
|
381
|
-
import { createFieldId, createView as createView2, getSchemaProperties, ViewProjection as ViewProjection2 } from "@dxos/schema";
|
|
382
|
-
var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
|
|
383
|
-
if (typename) {
|
|
384
|
-
const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
|
|
385
|
-
if (!schema) {
|
|
386
|
-
throw new Error(`Schema not found: ${typename}`);
|
|
387
|
-
}
|
|
388
|
-
const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
|
|
389
|
-
table.view = Ref2.make(createView2({
|
|
390
|
-
// TODO(ZaymonFC): Don't hardcode name?
|
|
391
|
-
name: "View",
|
|
392
|
-
typename: schema.typename,
|
|
393
|
-
jsonSchema: schema.jsonSchema,
|
|
394
|
-
fields
|
|
395
|
-
}));
|
|
396
|
-
return schema;
|
|
397
|
-
} else {
|
|
398
|
-
const [schema] = await space.db.schemaRegistry.register([
|
|
399
|
-
createContactSchema()
|
|
400
|
-
]);
|
|
401
|
-
const fields = ContactFields;
|
|
402
|
-
table.view = Ref2.make(createView2({
|
|
403
|
-
name: "View",
|
|
404
|
-
typename: schema.typename,
|
|
405
|
-
jsonSchema: schema.jsonSchema,
|
|
406
|
-
fields
|
|
407
|
-
}));
|
|
408
|
-
createProjection(schema, table.view.target);
|
|
409
|
-
if (initialRow) {
|
|
410
|
-
space.db.add(live2(schema, {}));
|
|
411
|
-
}
|
|
412
|
-
return schema;
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
var createContactSchema = () => TypedObject({
|
|
416
|
-
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
417
|
-
version: "0.1.0"
|
|
418
|
-
})({
|
|
419
|
-
name: Schema2.optional(Schema2.String).annotations({
|
|
420
|
-
title: "Name"
|
|
421
|
-
}),
|
|
422
|
-
active: Schema2.optional(Schema2.Boolean).annotations({
|
|
423
|
-
title: "Active"
|
|
424
|
-
}),
|
|
425
|
-
email: Schema2.optional(Format.Email),
|
|
426
|
-
salary: Schema2.optional(Format.Currency()).annotations({
|
|
427
|
-
title: "Salary"
|
|
428
|
-
})
|
|
429
|
-
});
|
|
430
|
-
var ContactFields = [
|
|
431
|
-
"name",
|
|
432
|
-
"email",
|
|
433
|
-
"salary",
|
|
434
|
-
"active"
|
|
435
|
-
];
|
|
436
|
-
var createProjection = (schema, view) => {
|
|
437
|
-
const projection = new ViewProjection2(schema.jsonSchema, view);
|
|
438
|
-
projection.setFieldProjection({
|
|
439
|
-
field: {
|
|
440
|
-
id: view.fields.find((f) => f.path === "salary").id,
|
|
441
|
-
path: "salary",
|
|
442
|
-
size: 150
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
projection.setFieldProjection({
|
|
446
|
-
field: {
|
|
447
|
-
id: view.fields.find((f) => f.path === "active").id,
|
|
448
|
-
path: "active",
|
|
449
|
-
size: 100
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
projection.setFieldProjection({
|
|
453
|
-
field: {
|
|
454
|
-
id: createFieldId(),
|
|
455
|
-
path: "manager",
|
|
456
|
-
referencePath: "name"
|
|
457
|
-
},
|
|
458
|
-
props: {
|
|
459
|
-
property: "manager",
|
|
460
|
-
type: TypeEnum.Ref,
|
|
461
|
-
format: FormatEnum.Ref,
|
|
462
|
-
referenceSchema: schema.typename,
|
|
463
|
-
title: "Manager"
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
return projection;
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
// src/util/table-buttons.ts
|
|
470
|
-
var BUTTON_IDENTIFIERS = {
|
|
471
|
-
columnSettings: "data-table-column-settings-button",
|
|
472
|
-
newColumn: "data-table-new-column-button",
|
|
473
|
-
referencedCell: "data-table-ref-cell-button",
|
|
474
|
-
rowMenu: "data-table-row-menu-button",
|
|
475
|
-
saveDraftRow: "data-table-save-draft-row-button",
|
|
476
|
-
sort: "data-table-sort-button"
|
|
477
|
-
};
|
|
478
|
-
var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
|
|
479
|
-
const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
480
|
-
const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
|
|
481
|
-
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>`;
|
|
482
|
-
};
|
|
483
|
-
var addColumnButton = {
|
|
484
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
485
|
-
icon: "ph--plus--regular",
|
|
486
|
-
render: ({ disabled }) => {
|
|
487
|
-
return createButton({
|
|
488
|
-
attr: BUTTON_IDENTIFIERS.newColumn,
|
|
489
|
-
icon: addColumnButton.icon,
|
|
490
|
-
disabled,
|
|
491
|
-
data: {},
|
|
492
|
-
testId: "table-new-column-button"
|
|
493
|
-
});
|
|
494
|
-
},
|
|
495
|
-
getData: (_el) => ({
|
|
496
|
-
type: "newColumn"
|
|
497
|
-
})
|
|
498
|
-
};
|
|
499
|
-
var columnSettingsButton = {
|
|
500
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
501
|
-
icon: "ph--caret-down--regular",
|
|
502
|
-
render: ({ fieldId }) => {
|
|
503
|
-
return createButton({
|
|
504
|
-
attr: BUTTON_IDENTIFIERS.columnSettings,
|
|
505
|
-
icon: columnSettingsButton.icon,
|
|
506
|
-
data: {
|
|
507
|
-
"data-field-id": fieldId
|
|
508
|
-
},
|
|
509
|
-
testId: "table-column-settings-button"
|
|
510
|
-
});
|
|
511
|
-
},
|
|
512
|
-
getData: (el) => ({
|
|
513
|
-
type: "columnSettings",
|
|
514
|
-
fieldId: el.getAttribute("data-field-id")
|
|
515
|
-
})
|
|
516
|
-
};
|
|
517
|
-
var rowMenuButton = {
|
|
518
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
519
|
-
icon: "ph--dots-three--regular",
|
|
520
|
-
render: ({ rowIndex }) => {
|
|
521
|
-
return createButton({
|
|
522
|
-
attr: BUTTON_IDENTIFIERS.rowMenu,
|
|
523
|
-
icon: rowMenuButton.icon,
|
|
524
|
-
data: {
|
|
525
|
-
"data-row-index": rowIndex.toString()
|
|
526
|
-
},
|
|
527
|
-
testId: "table-row-menu-button"
|
|
528
|
-
});
|
|
529
|
-
},
|
|
530
|
-
getData: (el) => ({
|
|
531
|
-
type: "rowMenu",
|
|
532
|
-
rowIndex: Number(el.getAttribute("data-row-index"))
|
|
533
|
-
})
|
|
534
|
-
};
|
|
535
|
-
var sortButton = {
|
|
536
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
537
|
-
icon: "ph--sort-ascending--regular",
|
|
538
|
-
render: ({ fieldId, direction }) => {
|
|
539
|
-
return createButton({
|
|
540
|
-
attr: BUTTON_IDENTIFIERS.sort,
|
|
541
|
-
icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
|
|
542
|
-
data: {
|
|
543
|
-
"data-field-id": fieldId,
|
|
544
|
-
"data-direction": direction ?? ""
|
|
545
|
-
},
|
|
546
|
-
testId: "table-sort-button",
|
|
547
|
-
// TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
|
|
548
|
-
// This is a bit hacky.
|
|
549
|
-
type: "secondary"
|
|
550
|
-
});
|
|
551
|
-
},
|
|
552
|
-
getData: (el) => ({
|
|
553
|
-
type: "sort",
|
|
554
|
-
fieldId: el.getAttribute("data-field-id"),
|
|
555
|
-
direction: el.getAttribute("data-direction")
|
|
556
|
-
})
|
|
557
|
-
};
|
|
558
|
-
var saveDraftRowButton = {
|
|
559
|
-
attr: BUTTON_IDENTIFIERS.saveDraftRow,
|
|
560
|
-
icon: "ph--floppy-disk--regular",
|
|
561
|
-
render: ({ rowIndex, disabled }) => {
|
|
562
|
-
return createButton({
|
|
563
|
-
attr: BUTTON_IDENTIFIERS.saveDraftRow,
|
|
564
|
-
icon: saveDraftRowButton.icon,
|
|
565
|
-
disabled,
|
|
566
|
-
data: {
|
|
567
|
-
"data-row-index": rowIndex.toString()
|
|
568
|
-
},
|
|
569
|
-
testId: "table-save-draft-row-button"
|
|
570
|
-
});
|
|
571
|
-
},
|
|
572
|
-
getData: (el) => ({
|
|
573
|
-
type: "saveDraftRow",
|
|
574
|
-
rowIndex: Number(el.getAttribute("data-row-index"))
|
|
575
|
-
})
|
|
576
|
-
};
|
|
577
|
-
var tableButtons = {
|
|
578
|
-
addColumn: addColumnButton,
|
|
579
|
-
columnSettings: columnSettingsButton,
|
|
580
|
-
rowMenu: rowMenuButton,
|
|
581
|
-
saveDraftRow: saveDraftRowButton,
|
|
582
|
-
sort: sortButton
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
// src/util/table-controls.ts
|
|
586
|
-
var CONTROL_IDENTIFIERS = {
|
|
587
|
-
checkbox: "data-table-checkbox",
|
|
588
|
-
switch: "data-table-switch"
|
|
589
|
-
};
|
|
590
|
-
var BASE_CLASSES = {
|
|
591
|
-
checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
|
|
592
|
-
switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
|
|
593
|
-
};
|
|
594
|
-
var renderAttributes = (data) => {
|
|
595
|
-
return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
596
|
-
};
|
|
597
|
-
var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
|
|
598
|
-
return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
|
|
599
|
-
};
|
|
600
|
-
var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
|
|
601
|
-
const attrs = {
|
|
602
|
-
[CONTROL_IDENTIFIERS.checkbox]: "",
|
|
603
|
-
"data-row-index": rowIndex.toString(),
|
|
604
|
-
...header && {
|
|
605
|
-
"data-header": ""
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
|
|
609
|
-
};
|
|
610
|
-
var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
|
|
611
|
-
const attrs = {
|
|
612
|
-
[CONTROL_IDENTIFIERS.switch]: "",
|
|
613
|
-
"data-row-index": rowIndex.toString(),
|
|
614
|
-
"data-col-index": colIndex.toString()
|
|
615
|
-
};
|
|
616
|
-
return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
|
|
617
|
-
};
|
|
618
|
-
var tableControls = {
|
|
619
|
-
checkbox: {
|
|
620
|
-
attr: CONTROL_IDENTIFIERS.checkbox,
|
|
621
|
-
render: CheckboxStory,
|
|
622
|
-
getData: (el) => ({
|
|
623
|
-
type: "checkbox",
|
|
624
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
625
|
-
header: el.hasAttribute("data-header")
|
|
626
|
-
})
|
|
627
|
-
},
|
|
628
|
-
switch: {
|
|
629
|
-
attr: CONTROL_IDENTIFIERS.switch,
|
|
630
|
-
render: SwitchStory,
|
|
631
|
-
getData: (el) => ({
|
|
632
|
-
type: "switch",
|
|
633
|
-
rowIndex: Number(el.getAttribute("data-row-index")),
|
|
634
|
-
colIndex: Number(el.getAttribute("data-col-index"))
|
|
635
|
-
})
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
|
|
639
125
|
// src/util/schema.ts
|
|
640
|
-
import
|
|
641
|
-
import
|
|
126
|
+
import * as Schema from "effect/Schema";
|
|
127
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
642
128
|
var narrowSchema = (schema, paths) => {
|
|
643
129
|
const ast = schema?.ast;
|
|
644
|
-
if (isTypeLiteral(ast)) {
|
|
130
|
+
if (SchemaAST.isTypeLiteral(ast)) {
|
|
645
131
|
const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
|
|
646
132
|
if (propertySignatures.length > 0) {
|
|
647
|
-
const narrowType = new TypeLiteral(propertySignatures, []);
|
|
648
|
-
return
|
|
133
|
+
const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
|
|
134
|
+
return Schema.make(narrowType);
|
|
649
135
|
}
|
|
650
136
|
}
|
|
651
137
|
return void 0;
|
|
652
138
|
};
|
|
653
139
|
|
|
654
|
-
// src/model/
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
}), this._hasSelection = computed(() => this._validSelectedIds.value.size > 0), this._allSelected = computed(() => {
|
|
667
|
-
const rows = this._rows.value;
|
|
668
|
-
if (rows.length === 0) {
|
|
669
|
-
return false;
|
|
670
|
-
}
|
|
671
|
-
return rows.every((row) => this._selection.value.has(row.id));
|
|
672
|
-
}), this.getSelectedRows = () => {
|
|
673
|
-
const selectedIds = this._validSelectedIds.value;
|
|
674
|
-
return this._rows.value.filter((row) => selectedIds.has(row.id));
|
|
675
|
-
}, this.isRowIndexSelected = (rowIndex) => {
|
|
676
|
-
const row = this._rows.value[rowIndex];
|
|
677
|
-
return this._selection.value.has(row.id);
|
|
678
|
-
}, this.isObjectSelected = (object) => {
|
|
679
|
-
return this._selection.value.has(object.id);
|
|
680
|
-
}, this.toggleSelectionForRowIndex = (rowIndex) => {
|
|
681
|
-
const row = this._rows.value[rowIndex];
|
|
682
|
-
const newSelection = new Set(this._selection.value);
|
|
683
|
-
if (newSelection.has(row.id)) {
|
|
684
|
-
newSelection.delete(row.id);
|
|
685
|
-
} else {
|
|
686
|
-
if (this._selectionMode === "single") {
|
|
687
|
-
newSelection.clear();
|
|
688
|
-
}
|
|
689
|
-
newSelection.add(row.id);
|
|
690
|
-
}
|
|
691
|
-
this._selection.value = newSelection;
|
|
692
|
-
}, this.setSelection = (mode) => {
|
|
693
|
-
switch (mode) {
|
|
694
|
-
case "all": {
|
|
695
|
-
this._selection.value = new Set(this._rows.value.map((row) => row.id));
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
698
|
-
case "none": {
|
|
699
|
-
this._selection.value = /* @__PURE__ */ new Set();
|
|
700
|
-
break;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
async _open() {
|
|
706
|
-
const selectionWatcher = effect(() => {
|
|
707
|
-
touch(this._selection.value);
|
|
708
|
-
this._onSelectionChanged?.();
|
|
140
|
+
// src/model/modal-controller.ts
|
|
141
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
142
|
+
var ModalController = class {
|
|
143
|
+
_registry;
|
|
144
|
+
_state;
|
|
145
|
+
_triggerRef = {
|
|
146
|
+
current: null
|
|
147
|
+
};
|
|
148
|
+
constructor(registry) {
|
|
149
|
+
this._registry = registry;
|
|
150
|
+
this._state = Atom.make({
|
|
151
|
+
type: "closed"
|
|
709
152
|
});
|
|
710
|
-
this._ctx.onDispose(selectionWatcher);
|
|
711
|
-
}
|
|
712
|
-
//
|
|
713
|
-
// Getters
|
|
714
|
-
//
|
|
715
|
-
get selection() {
|
|
716
|
-
return this._selection;
|
|
717
153
|
}
|
|
718
|
-
get
|
|
719
|
-
return this.
|
|
154
|
+
get state() {
|
|
155
|
+
return this._state;
|
|
720
156
|
}
|
|
721
|
-
get
|
|
722
|
-
return this.
|
|
157
|
+
get stateValue() {
|
|
158
|
+
return this._registry.get(this._state);
|
|
723
159
|
}
|
|
724
|
-
get
|
|
725
|
-
return this.
|
|
160
|
+
get trigger() {
|
|
161
|
+
return this._triggerRef;
|
|
726
162
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
this.
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
if (local?.type === "active") {
|
|
748
|
-
if (!viewSort) {
|
|
749
|
-
return true;
|
|
750
|
-
}
|
|
751
|
-
return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
|
|
163
|
+
setTrigger = (trigger) => {
|
|
164
|
+
this._triggerRef.current = trigger;
|
|
165
|
+
};
|
|
166
|
+
showRowMenu = (rowIndex) => {
|
|
167
|
+
this._registry.set(this._state, {
|
|
168
|
+
type: "row",
|
|
169
|
+
rowIndex
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
showColumnMenu = (fieldId) => {
|
|
173
|
+
this._registry.set(this._state, {
|
|
174
|
+
type: "column",
|
|
175
|
+
fieldId
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
showColumnCreator = () => {
|
|
179
|
+
this._registry.set(this._state, {
|
|
180
|
+
type: "columnSettings",
|
|
181
|
+
mode: {
|
|
182
|
+
type: "create"
|
|
752
183
|
}
|
|
753
|
-
return false;
|
|
754
184
|
});
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
185
|
+
};
|
|
186
|
+
showReferencePanel = (targetId, schemaId) => {
|
|
187
|
+
this._registry.set(this._state, {
|
|
188
|
+
type: "refPanel",
|
|
189
|
+
targetId,
|
|
190
|
+
typename: schemaId
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
openColumnSettings = () => {
|
|
194
|
+
const currentState = this._registry.get(this._state);
|
|
195
|
+
if (currentState.type === "column") {
|
|
196
|
+
const fieldId = currentState.fieldId;
|
|
197
|
+
requestAnimationFrame(() => {
|
|
198
|
+
this._registry.set(this._state, {
|
|
199
|
+
type: "columnSettings",
|
|
200
|
+
mode: {
|
|
201
|
+
type: "edit",
|
|
202
|
+
fieldId
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
765
206
|
}
|
|
766
|
-
|
|
767
|
-
|
|
207
|
+
};
|
|
208
|
+
close = () => {
|
|
209
|
+
this._registry.set(this._state, {
|
|
210
|
+
type: "closed"
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
216
|
+
import { EditorView } from "@codemirror/view";
|
|
217
|
+
import React3, { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
218
|
+
import { debounce } from "@dxos/async";
|
|
219
|
+
import { Format, TypeEnum } from "@dxos/echo/internal";
|
|
220
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
221
|
+
import { GridCellEditor, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
222
|
+
|
|
223
|
+
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
224
|
+
import React from "react";
|
|
225
|
+
import { useGridContext } from "@dxos/react-ui-grid";
|
|
226
|
+
var CellValidationMessage = ({ __gridScope, validationError, variant = "error" }) => {
|
|
227
|
+
const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
|
|
228
|
+
if (!editing || !validationError) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
const bgClass = variant === "error" ? "bg-error-surface" : "bg-warning-surface";
|
|
232
|
+
const textClass = variant === "error" ? "text-error-surface-text" : "text-warning-surface-text";
|
|
233
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
234
|
+
role: "none",
|
|
235
|
+
className: `absolute ${bgClass} ${textClass} rounded-h-sm text-xs p-1`,
|
|
236
|
+
style: {
|
|
237
|
+
...{
|
|
238
|
+
"--dx-grid-cell-width": `${box?.inlineSize ?? 200}px`
|
|
239
|
+
},
|
|
240
|
+
zIndex: 10,
|
|
241
|
+
insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
|
|
242
|
+
insetInlineStart: box.insetInlineStart,
|
|
243
|
+
inlineSize: box.inlineSize
|
|
768
244
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}
|
|
788
|
-
};
|
|
245
|
+
}, validationError);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
249
|
+
import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
250
|
+
import { Entity } from "@dxos/echo";
|
|
251
|
+
import { Ref as Ref2, getValue } from "@dxos/echo/internal";
|
|
252
|
+
import { invariant } from "@dxos/invariant";
|
|
253
|
+
import { Popover } from "@dxos/react-ui";
|
|
254
|
+
import { Form } from "@dxos/react-ui-form";
|
|
255
|
+
import { parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
256
|
+
import { getDeep, isTruthy, setDeep } from "@dxos/util";
|
|
257
|
+
import { translationKey } from "#translations";
|
|
258
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
259
|
+
var createOptionLabel = [
|
|
260
|
+
"create-new-object.label",
|
|
261
|
+
{
|
|
262
|
+
ns: translationKey
|
|
789
263
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
264
|
+
];
|
|
265
|
+
var FormCellEditor = ({ __gridScope, schema, model, fieldProjection, onSave, onCreate, ...formProps }) => {
|
|
266
|
+
const anchorRef = useRef(null);
|
|
267
|
+
const { id: _gridId, editing: contextEditing, setEditing } = useGridContext2("ArrayEditor", __gridScope);
|
|
268
|
+
const [editing, setLocalEditing] = useState(false);
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (contextEditing && contextEditing.cellElement) {
|
|
271
|
+
anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
|
|
272
|
+
setLocalEditing(true);
|
|
273
|
+
} else {
|
|
274
|
+
anchorRef.current = null;
|
|
275
|
+
setLocalEditing(false);
|
|
793
276
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
this.setSort(fieldId, "asc");
|
|
801
|
-
break;
|
|
802
|
-
}
|
|
277
|
+
}, [
|
|
278
|
+
contextEditing
|
|
279
|
+
]);
|
|
280
|
+
const narrowedSchema = useMemo(() => {
|
|
281
|
+
if (!schema) {
|
|
282
|
+
return void 0;
|
|
803
283
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
];
|
|
284
|
+
return narrowSchema(schema, [
|
|
285
|
+
fieldProjection.field.path
|
|
286
|
+
]);
|
|
287
|
+
}, [
|
|
288
|
+
JSON.stringify(schema),
|
|
289
|
+
fieldProjection.field.path
|
|
290
|
+
]);
|
|
291
|
+
const originalRow = useMemo(() => {
|
|
292
|
+
if (model && contextEditing) {
|
|
293
|
+
const cell = parseCellIndex(contextEditing.index);
|
|
294
|
+
if (model.isDraftCell(cell)) {
|
|
295
|
+
const draftRow = model.getDraftRows()[cell.row];
|
|
296
|
+
invariant(draftRow, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 52, S: void 0, A: ["draftRow", ""] });
|
|
297
|
+
return draftRow.data;
|
|
816
298
|
} else {
|
|
817
|
-
|
|
299
|
+
const row = model.getRowAt(cell.row);
|
|
300
|
+
invariant(row, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 56, S: void 0, A: ["row", ""] });
|
|
301
|
+
return row;
|
|
818
302
|
}
|
|
819
|
-
this._localSort.value = void 0;
|
|
820
303
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
const dataWithIndices = this._rows.value.map((item, index) => {
|
|
838
|
-
const sortValue = this.getSortValue(props, field, item);
|
|
839
|
-
const isEmpty = !(props.type === TypeEnum2.Boolean) && (sortValue == null || sortValue === "");
|
|
840
|
-
return {
|
|
841
|
-
item,
|
|
842
|
-
index,
|
|
843
|
-
value: sortValue,
|
|
844
|
-
isEmpty
|
|
845
|
-
};
|
|
846
|
-
});
|
|
847
|
-
const ordered = orderBy(dataWithIndices, [
|
|
848
|
-
"isEmpty",
|
|
849
|
-
"value"
|
|
850
|
-
], [
|
|
851
|
-
"asc",
|
|
852
|
-
sort.direction
|
|
853
|
-
]);
|
|
854
|
-
ordered.forEach(({ index: dataIndex }, displayIndex) => {
|
|
855
|
-
if (displayIndex !== dataIndex) {
|
|
856
|
-
this._displayToDataIndex.set(displayIndex, dataIndex);
|
|
857
|
-
}
|
|
858
|
-
});
|
|
859
|
-
return ordered.map(({ item }) => item);
|
|
860
|
-
});
|
|
861
|
-
}
|
|
862
|
-
getSortValue(props, field, item) {
|
|
863
|
-
const { type, format } = props;
|
|
864
|
-
const value = getValue(item, field.path);
|
|
865
|
-
if (type === TypeEnum2.Boolean) {
|
|
866
|
-
return !!value;
|
|
304
|
+
return void 0;
|
|
305
|
+
}, [
|
|
306
|
+
model,
|
|
307
|
+
contextEditing
|
|
308
|
+
]);
|
|
309
|
+
const initialFormValues = useMemo(() => originalRow ? JSON.parse(JSON.stringify(originalRow)) : {}, [
|
|
310
|
+
originalRow
|
|
311
|
+
]);
|
|
312
|
+
const [formValues, setFormValues] = useState(initialFormValues);
|
|
313
|
+
const handleValuesChanged = useCallback((values) => {
|
|
314
|
+
setFormValues(values);
|
|
315
|
+
}, []);
|
|
316
|
+
const handleOpenChange = useCallback((nextOpen) => {
|
|
317
|
+
if (nextOpen === false) {
|
|
318
|
+
setEditing(null);
|
|
319
|
+
onSave?.();
|
|
867
320
|
}
|
|
868
|
-
|
|
869
|
-
|
|
321
|
+
setLocalEditing(nextOpen);
|
|
322
|
+
}, []);
|
|
323
|
+
const handleSave = useCallback((values) => {
|
|
324
|
+
if (!originalRow) {
|
|
325
|
+
return;
|
|
870
326
|
}
|
|
871
|
-
|
|
872
|
-
|
|
327
|
+
const path = fieldProjection.field.path;
|
|
328
|
+
const value = getDeep(values, [
|
|
329
|
+
path
|
|
330
|
+
]);
|
|
331
|
+
if (model) {
|
|
332
|
+
model.changeRow(originalRow, (mutableRow) => {
|
|
333
|
+
setDeep(mutableRow, [
|
|
334
|
+
path
|
|
335
|
+
], value);
|
|
336
|
+
});
|
|
337
|
+
} else {
|
|
338
|
+
setDeep(originalRow, [
|
|
339
|
+
path
|
|
340
|
+
], value);
|
|
873
341
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
342
|
+
contextEditing?.cellElement?.focus();
|
|
343
|
+
setEditing(null);
|
|
344
|
+
setLocalEditing(false);
|
|
345
|
+
onSave?.();
|
|
346
|
+
}, [
|
|
347
|
+
fieldProjection.field.path,
|
|
348
|
+
onSave,
|
|
349
|
+
contextEditing,
|
|
350
|
+
originalRow,
|
|
351
|
+
model
|
|
352
|
+
]);
|
|
353
|
+
const handleCreate = useCallback((schema2, values) => {
|
|
354
|
+
const objectWithId = onCreate?.(schema2, values);
|
|
355
|
+
if (objectWithId && originalRow) {
|
|
356
|
+
const ref = Ref2.make(objectWithId);
|
|
357
|
+
const path = fieldProjection.field.path;
|
|
358
|
+
if (model) {
|
|
359
|
+
model.changeRow(originalRow, (mutableRow) => {
|
|
360
|
+
setDeep(mutableRow, [
|
|
361
|
+
path
|
|
362
|
+
], ref);
|
|
363
|
+
});
|
|
364
|
+
} else {
|
|
365
|
+
setDeep(originalRow, [
|
|
366
|
+
path
|
|
367
|
+
], ref);
|
|
878
368
|
}
|
|
879
|
-
const option = options.find((option2) => option2.id === value);
|
|
880
|
-
return option ? options.indexOf(option) : void 0;
|
|
881
369
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
370
|
+
contextEditing?.cellElement?.focus();
|
|
371
|
+
setEditing(null);
|
|
372
|
+
setLocalEditing(false);
|
|
373
|
+
onSave?.();
|
|
374
|
+
}, [
|
|
375
|
+
fieldProjection.field.path,
|
|
376
|
+
onSave,
|
|
377
|
+
contextEditing,
|
|
378
|
+
originalRow,
|
|
379
|
+
onCreate,
|
|
380
|
+
model
|
|
381
|
+
]);
|
|
382
|
+
const getOptions = useCallback((results) => results.map((obj) => {
|
|
383
|
+
return {
|
|
384
|
+
id: Entity.getDXN(obj).toString(),
|
|
385
|
+
label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
|
|
386
|
+
};
|
|
387
|
+
}).filter(isTruthy), [
|
|
388
|
+
fieldProjection
|
|
389
|
+
]);
|
|
390
|
+
if (!editing) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
394
|
+
open: editing,
|
|
395
|
+
onOpenChange: handleOpenChange
|
|
396
|
+
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
397
|
+
virtualRef: anchorRef
|
|
398
|
+
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
399
|
+
tabIndex: -1,
|
|
400
|
+
classNames: "dx-card-popover-width dx-density-fine"
|
|
401
|
+
}, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form.Root, {
|
|
402
|
+
...formProps,
|
|
403
|
+
autoFocus: true,
|
|
404
|
+
schema: narrowedSchema,
|
|
405
|
+
values: formValues,
|
|
406
|
+
onValuesChanged: handleValuesChanged,
|
|
407
|
+
projection: model?.projection,
|
|
408
|
+
createInitialValuePath: fieldProjection.field.referencePath,
|
|
409
|
+
createOptionIcon: "ph--plus--regular",
|
|
410
|
+
createOptionLabel,
|
|
411
|
+
db: model?.db,
|
|
412
|
+
getOptions,
|
|
413
|
+
onCreate: handleCreate,
|
|
414
|
+
onSave: handleSave
|
|
415
|
+
}, /* @__PURE__ */ React2.createElement(Form.Viewport, null, /* @__PURE__ */ React2.createElement(Form.Content, null, /* @__PURE__ */ React2.createElement(Form.FieldSet, null), /* @__PURE__ */ React2.createElement(Form.Actions, null))))))));
|
|
892
416
|
};
|
|
893
417
|
|
|
894
|
-
// src/
|
|
895
|
-
var
|
|
896
|
-
var
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
const ids = [];
|
|
901
|
-
let match;
|
|
902
|
-
while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
|
|
903
|
-
if (match[2]) {
|
|
904
|
-
ids.push(match[2]);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
return ids.length > 0 ? ids : void 0;
|
|
908
|
-
};
|
|
909
|
-
|
|
910
|
-
// src/model/table-model.ts
|
|
911
|
-
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
|
|
912
|
-
var defaultFeatures = {
|
|
913
|
-
selection: {
|
|
914
|
-
enabled: true,
|
|
915
|
-
mode: "multiple"
|
|
916
|
-
},
|
|
917
|
-
dataEditable: false,
|
|
918
|
-
schemaEditable: false
|
|
919
|
-
};
|
|
920
|
-
var TableModel = class extends Resource2 {
|
|
921
|
-
constructor({ id, space, view, projection, features = {}, sorting = [], pinnedRows = {
|
|
922
|
-
top: [],
|
|
923
|
-
bottom: []
|
|
924
|
-
}, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
|
|
925
|
-
super();
|
|
926
|
-
this._visibleRange = signal3({
|
|
927
|
-
start: {
|
|
928
|
-
row: 0,
|
|
929
|
-
col: 0
|
|
930
|
-
},
|
|
931
|
-
end: {
|
|
932
|
-
row: 0,
|
|
933
|
-
col: 0
|
|
934
|
-
}
|
|
935
|
-
});
|
|
936
|
-
this._rows = signal3([]);
|
|
937
|
-
this._draftRows = signal3([]);
|
|
938
|
-
//
|
|
939
|
-
// Data
|
|
940
|
-
//
|
|
941
|
-
this.setRows = (obj) => {
|
|
942
|
-
this._rows.value = obj;
|
|
943
|
-
};
|
|
944
|
-
this.getRowCount = () => this._rows.value.length;
|
|
945
|
-
/**
|
|
946
|
-
* @reactive
|
|
947
|
-
*/
|
|
948
|
-
this.getDraftRowCount = () => this._draftRows.value.length;
|
|
949
|
-
this.getColumnCount = () => this._view?.fields.length ?? 0;
|
|
950
|
-
this.insertRow = () => {
|
|
951
|
-
const result = this._onInsertRow?.();
|
|
952
|
-
if (result === false && this._draftRows.value.length === 0) {
|
|
953
|
-
this.createDraftRow();
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
this.commitDraftRow = (draftRowIndex) => {
|
|
957
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
|
|
958
|
-
return false;
|
|
959
|
-
}
|
|
960
|
-
const draftRow = this._draftRows.value[draftRowIndex];
|
|
961
|
-
if (!draftRow.valid) {
|
|
962
|
-
return false;
|
|
963
|
-
}
|
|
964
|
-
const success = this._onInsertRow?.(draftRow.data);
|
|
965
|
-
if (success) {
|
|
966
|
-
const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
|
|
967
|
-
this._draftRows.value = newDraftRows;
|
|
968
|
-
}
|
|
969
|
-
return success ?? false;
|
|
970
|
-
};
|
|
971
|
-
this.deleteRow = (rowIndex) => {
|
|
972
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
973
|
-
const obj = this._rows.value[row];
|
|
974
|
-
const objectsToDelete = [];
|
|
975
|
-
if (this.features.selection.enabled && this._selection.hasSelection.value) {
|
|
976
|
-
const selectedRows = this._selection.getSelectedRows();
|
|
977
|
-
objectsToDelete.push(...selectedRows);
|
|
978
|
-
} else {
|
|
979
|
-
objectsToDelete.push(obj);
|
|
980
|
-
}
|
|
981
|
-
this._onDeleteRows?.(row, objectsToDelete);
|
|
982
|
-
};
|
|
983
|
-
this.handleRowAction = (actionId, rowIndex) => {
|
|
984
|
-
if (!this._onRowAction) {
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
const row = this._sorting.getDataIndex(rowIndex);
|
|
988
|
-
const data = this._rows.value[row];
|
|
989
|
-
if (data) {
|
|
990
|
-
this._onRowAction(actionId, data);
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
this.getCellData = (cell) => {
|
|
994
|
-
const { col, row, plane } = cell;
|
|
995
|
-
const fields = this._view?.fields ?? [];
|
|
996
|
-
if (col < 0 || col >= fields.length) {
|
|
997
|
-
return void 0;
|
|
998
|
-
}
|
|
999
|
-
const field = fields[col];
|
|
1000
|
-
let value;
|
|
1001
|
-
if (plane === "frozenRowsEnd") {
|
|
1002
|
-
if (row >= 0 && row < this._draftRows.value.length) {
|
|
1003
|
-
value = getValue2(this._draftRows.value[row].data, field.path);
|
|
1004
|
-
} else {
|
|
1005
|
-
return void 0;
|
|
1006
|
-
}
|
|
1007
|
-
} else {
|
|
1008
|
-
const dataIndex = this._sorting.getDataIndex(row);
|
|
1009
|
-
value = getValue2(this._rows.value[dataIndex], field.path);
|
|
1010
|
-
}
|
|
1011
|
-
if (value == null) {
|
|
1012
|
-
return "";
|
|
1013
|
-
}
|
|
1014
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1015
|
-
switch (props.format) {
|
|
1016
|
-
case FormatEnum3.Ref: {
|
|
1017
|
-
if (!field.referencePath) {
|
|
1018
|
-
return "";
|
|
1019
|
-
}
|
|
1020
|
-
return getValue2(value.target, field.referencePath);
|
|
1021
|
-
}
|
|
1022
|
-
default: {
|
|
1023
|
-
return formatForEditing({
|
|
1024
|
-
type: props.type,
|
|
1025
|
-
format: props.format,
|
|
1026
|
-
value
|
|
1027
|
-
});
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
|
-
this.validateCellData = async ({ col, row, plane }, value) => {
|
|
1032
|
-
const fields = this._view?.fields ?? [];
|
|
1033
|
-
if (col < 0 || col >= fields.length) {
|
|
1034
|
-
return {
|
|
1035
|
-
valid: false,
|
|
1036
|
-
error: "Invalid column index"
|
|
1037
|
-
};
|
|
1038
|
-
}
|
|
1039
|
-
const field = fields[col];
|
|
1040
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1041
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
1042
|
-
const isDraftRow = plane === "frozenRowsEnd";
|
|
1043
|
-
if (isDraftRow) {
|
|
1044
|
-
const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
|
|
1045
|
-
if (isInvalidDraftRowIndex) {
|
|
1046
|
-
return {
|
|
1047
|
-
valid: false,
|
|
1048
|
-
error: "Invalid draft row index"
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
const draftRow = this._draftRows.value[row];
|
|
1052
|
-
const snapshot = {
|
|
1053
|
-
...draftRow.data
|
|
1054
|
-
};
|
|
1055
|
-
setValue(snapshot, field.path, transformedValue);
|
|
1056
|
-
const validationErrors = this.validateDraftRowData(snapshot);
|
|
1057
|
-
if (validationErrors.length > 0) {
|
|
1058
|
-
const error = validationErrors.find((err) => err.path === field.path);
|
|
1059
|
-
if (error) {
|
|
1060
|
-
return {
|
|
1061
|
-
valid: false,
|
|
1062
|
-
error: error.message
|
|
1063
|
-
};
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
return {
|
|
1067
|
-
valid: true
|
|
1068
|
-
};
|
|
1069
|
-
} else {
|
|
1070
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
1071
|
-
const currentRow = this._rows.value[rowIdx];
|
|
1072
|
-
invariant(currentRow, "Invalid row index", {
|
|
1073
|
-
F: __dxlog_file,
|
|
1074
|
-
L: 507,
|
|
1075
|
-
S: this,
|
|
1076
|
-
A: [
|
|
1077
|
-
"currentRow",
|
|
1078
|
-
"'Invalid row index'"
|
|
1079
|
-
]
|
|
1080
|
-
});
|
|
1081
|
-
const snapshot = getSnapshot(currentRow);
|
|
1082
|
-
setValue(snapshot, field.path, transformedValue);
|
|
1083
|
-
const schema = getSchema(currentRow);
|
|
1084
|
-
invariant(schema, void 0, {
|
|
1085
|
-
F: __dxlog_file,
|
|
1086
|
-
L: 513,
|
|
1087
|
-
S: this,
|
|
1088
|
-
A: [
|
|
1089
|
-
"schema",
|
|
1090
|
-
""
|
|
1091
|
-
]
|
|
1092
|
-
});
|
|
1093
|
-
const validationResult = validateSchema(schema, snapshot);
|
|
1094
|
-
if (validationResult && validationResult.length > 0) {
|
|
1095
|
-
const error = validationResult[0];
|
|
1096
|
-
invariant(error.path === field.path, void 0, {
|
|
1097
|
-
F: __dxlog_file,
|
|
1098
|
-
L: 518,
|
|
1099
|
-
S: this,
|
|
1100
|
-
A: [
|
|
1101
|
-
"error.path === field.path",
|
|
1102
|
-
""
|
|
1103
|
-
]
|
|
1104
|
-
});
|
|
1105
|
-
return {
|
|
1106
|
-
valid: false,
|
|
1107
|
-
error: error.message
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
return {
|
|
1111
|
-
valid: true
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
};
|
|
1115
|
-
this.setCellData = (cell, value) => {
|
|
1116
|
-
const { col, row, plane } = cell;
|
|
1117
|
-
const fields = this._view?.fields ?? [];
|
|
1118
|
-
if (col < 0 || col >= fields.length) {
|
|
1119
|
-
return;
|
|
1120
|
-
}
|
|
1121
|
-
const field = fields[col];
|
|
1122
|
-
const { props } = this._projection.getFieldProjection(field.id);
|
|
1123
|
-
const transformedValue = editorTextToCellValue(props, value);
|
|
1124
|
-
if (props.format === FormatEnum3.Ref && !isLiveObject(value)) {
|
|
1125
|
-
return;
|
|
1126
|
-
}
|
|
1127
|
-
if (plane === "frozenRowsEnd") {
|
|
1128
|
-
if (row >= 0 && row < this._draftRows.value.length) {
|
|
1129
|
-
setValue(this._draftRows.value[row].data, field.path, transformedValue);
|
|
1130
|
-
this.validateDraftRow(row);
|
|
1131
|
-
}
|
|
1132
|
-
} else {
|
|
1133
|
-
const rowIdx = this._sorting.getDataIndex(row);
|
|
1134
|
-
setValue(this._rows.value[rowIdx], field.path, transformedValue);
|
|
1135
|
-
}
|
|
1136
|
-
};
|
|
1137
|
-
this._id = id;
|
|
1138
|
-
this._space = space;
|
|
1139
|
-
this._view = view;
|
|
1140
|
-
this._projection = projection;
|
|
1141
|
-
this._features = {
|
|
1142
|
-
...defaultFeatures,
|
|
1143
|
-
...features
|
|
1144
|
-
};
|
|
1145
|
-
invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
|
|
1146
|
-
F: __dxlog_file,
|
|
1147
|
-
L: 145,
|
|
1148
|
-
S: this,
|
|
1149
|
-
A: [
|
|
1150
|
-
"!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
|
|
1151
|
-
"'Single selection is not compatible with editable tables.'"
|
|
1152
|
-
]
|
|
1153
|
-
});
|
|
1154
|
-
this._sorting = new TableSorting(this._rows, this._view, projection);
|
|
1155
|
-
if (sorting.length > 0) {
|
|
1156
|
-
const [sort] = sorting;
|
|
1157
|
-
this._sorting.setSort(sort.fieldId, sort.direction);
|
|
1158
|
-
}
|
|
1159
|
-
this._pinnedRows = pinnedRows;
|
|
1160
|
-
this._rowActions = rowActions;
|
|
1161
|
-
this._onInsertRow = onInsertRow;
|
|
1162
|
-
this._onDeleteRows = onDeleteRows;
|
|
1163
|
-
this._onDeleteColumn = onDeleteColumn;
|
|
1164
|
-
this._onCellUpdate = onCellUpdate;
|
|
1165
|
-
this._onRowOrderChange = onRowOrderChange;
|
|
1166
|
-
this._onRowAction = onRowAction;
|
|
1167
|
-
}
|
|
1168
|
-
get id() {
|
|
1169
|
-
return this._id;
|
|
1170
|
-
}
|
|
1171
|
-
get space() {
|
|
1172
|
-
return this._space;
|
|
1173
|
-
}
|
|
1174
|
-
get view() {
|
|
1175
|
-
return this._view;
|
|
1176
|
-
}
|
|
1177
|
-
get projection() {
|
|
1178
|
-
return this._projection;
|
|
1179
|
-
}
|
|
1180
|
-
get rows() {
|
|
1181
|
-
return this._sorting.sortedRows;
|
|
1182
|
-
}
|
|
1183
|
-
get features() {
|
|
1184
|
-
return this._features;
|
|
1185
|
-
}
|
|
1186
|
-
/**
|
|
1187
|
-
* @reactive
|
|
1188
|
-
*/
|
|
1189
|
-
get sorting() {
|
|
1190
|
-
return this._sorting;
|
|
1191
|
-
}
|
|
1192
|
-
/**
|
|
1193
|
-
* Gets the row data at the specified display index.
|
|
1194
|
-
*/
|
|
1195
|
-
getRowAt(displayIndex) {
|
|
1196
|
-
if (displayIndex < 0 || displayIndex >= this._sorting.sortedRows.value.length) {
|
|
1197
|
-
return void 0;
|
|
1198
|
-
}
|
|
1199
|
-
return this._sorting.sortedRows.value[displayIndex];
|
|
1200
|
-
}
|
|
1201
|
-
get pinnedRows() {
|
|
1202
|
-
return this._pinnedRows;
|
|
1203
|
-
}
|
|
1204
|
-
get columnMeta() {
|
|
1205
|
-
invariant(this._columnMeta, void 0, {
|
|
1206
|
-
F: __dxlog_file,
|
|
1207
|
-
L: 214,
|
|
1208
|
-
S: this,
|
|
1209
|
-
A: [
|
|
1210
|
-
"this._columnMeta",
|
|
1211
|
-
""
|
|
1212
|
-
]
|
|
1213
|
-
});
|
|
1214
|
-
return this._columnMeta;
|
|
1215
|
-
}
|
|
1216
|
-
get selection() {
|
|
1217
|
-
return this._selection;
|
|
1218
|
-
}
|
|
1219
|
-
/** @reactive */
|
|
1220
|
-
get isViewDirty() {
|
|
1221
|
-
return this._sorting.isDirty;
|
|
1222
|
-
}
|
|
1223
|
-
get rowActions() {
|
|
1224
|
-
return this._rowActions;
|
|
1225
|
-
}
|
|
1226
|
-
//
|
|
1227
|
-
// Initialisation
|
|
1228
|
-
//
|
|
1229
|
-
async _open() {
|
|
1230
|
-
this.initializeColumnMeta();
|
|
1231
|
-
this.initializeEffects();
|
|
1232
|
-
this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", () => this._onRowOrderChange?.());
|
|
1233
|
-
await this._selection.open(this._ctx);
|
|
1234
|
-
}
|
|
1235
|
-
initializeColumnMeta() {
|
|
1236
|
-
this._columnMeta = computed3(() => {
|
|
1237
|
-
const fields = this._view?.fields ?? [];
|
|
1238
|
-
const meta = Object.fromEntries(fields.map((field, index) => [
|
|
1239
|
-
index,
|
|
1240
|
-
{
|
|
1241
|
-
size: field?.size ?? 256,
|
|
1242
|
-
resizeable: true
|
|
1243
|
-
}
|
|
1244
|
-
]));
|
|
1245
|
-
return {
|
|
1246
|
-
grid: meta,
|
|
1247
|
-
frozenColsStart: {
|
|
1248
|
-
0: {
|
|
1249
|
-
size: 30,
|
|
1250
|
-
resizeable: false
|
|
1251
|
-
}
|
|
1252
|
-
},
|
|
1253
|
-
frozenColsEnd: {
|
|
1254
|
-
0: {
|
|
1255
|
-
size: 40,
|
|
1256
|
-
resizeable: false
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
};
|
|
1260
|
-
});
|
|
1261
|
-
}
|
|
1262
|
-
initializeEffects() {
|
|
1263
|
-
const rowOrderWatcher = effect2(() => {
|
|
1264
|
-
touch(this._sorting.sortedRows.value);
|
|
1265
|
-
this._onRowOrderChange?.();
|
|
1266
|
-
});
|
|
1267
|
-
this._ctx.onDispose(rowOrderWatcher);
|
|
1268
|
-
const rowEffectManager = effect2(() => {
|
|
1269
|
-
const { start, end } = touch(this._visibleRange.value);
|
|
1270
|
-
const rowEffects = [];
|
|
1271
|
-
for (let row = start.row; row <= end.row; row++) {
|
|
1272
|
-
rowEffects.push(effect2(() => {
|
|
1273
|
-
const obj = this._sorting.sortedRows.value[row];
|
|
1274
|
-
this._view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
|
|
1275
|
-
this._onCellUpdate?.({
|
|
1276
|
-
row,
|
|
1277
|
-
col: start.col,
|
|
1278
|
-
plane: "grid"
|
|
1279
|
-
});
|
|
1280
|
-
}));
|
|
1281
|
-
}
|
|
1282
|
-
return () => rowEffects.forEach((cleanup) => cleanup());
|
|
1283
|
-
});
|
|
1284
|
-
this._ctx.onDispose(rowEffectManager);
|
|
1285
|
-
const draftRowsWatcher = effect2(() => {
|
|
1286
|
-
touch(this._draftRows.value);
|
|
1287
|
-
this._onRowOrderChange?.();
|
|
1288
|
-
});
|
|
1289
|
-
this._ctx.onDispose(draftRowsWatcher);
|
|
1290
|
-
}
|
|
1291
|
-
// TODO(ZaymonFC): Return .value instead of exposing the signal.
|
|
1292
|
-
get draftRows() {
|
|
1293
|
-
return this._draftRows;
|
|
1294
|
-
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Checks if a specific field path has validation errors for a given draft row.
|
|
1297
|
-
* @param draftRowIndex - The index of the draft row to check
|
|
1298
|
-
* @param fieldPath - The path of the field to check for validation errors
|
|
1299
|
-
* @returns true if the field has validation errors, false otherwise
|
|
1300
|
-
*/
|
|
1301
|
-
hasDraftRowValidationError(draftRowIndex, fieldPath) {
|
|
1302
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
|
|
1303
|
-
return false;
|
|
1304
|
-
}
|
|
1305
|
-
const draftRow = this._draftRows.value[draftRowIndex];
|
|
1306
|
-
const validationErrors = draftRow.validationErrors || [];
|
|
1307
|
-
return validationErrors.some((error) => error.path === fieldPath);
|
|
1308
|
-
}
|
|
1309
|
-
createDraftRow() {
|
|
1310
|
-
if (!this._view) {
|
|
1311
|
-
return;
|
|
1312
|
-
}
|
|
1313
|
-
const draftData = {
|
|
1314
|
-
id: ObjectId.random()
|
|
1315
|
-
};
|
|
1316
|
-
const validationErrors = this.validateDraftRowData(draftData);
|
|
1317
|
-
const draftRow = {
|
|
1318
|
-
data: draftData,
|
|
1319
|
-
valid: validationErrors.length === 0,
|
|
1320
|
-
validationErrors
|
|
1321
|
-
};
|
|
1322
|
-
this._draftRows.value = [
|
|
1323
|
-
...this._draftRows.value,
|
|
1324
|
-
draftRow
|
|
1325
|
-
];
|
|
1326
|
-
}
|
|
1327
|
-
validateDraftRow(draftRowIndex) {
|
|
1328
|
-
if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
const draftRow = this._draftRows.value[draftRowIndex];
|
|
1332
|
-
const validationErrors = this.validateDraftRowData(draftRow.data);
|
|
1333
|
-
const updatedDraftRow = {
|
|
1334
|
-
...draftRow,
|
|
1335
|
-
valid: validationErrors.length === 0,
|
|
1336
|
-
validationErrors
|
|
1337
|
-
};
|
|
1338
|
-
const newDraftRows = [
|
|
1339
|
-
...this._draftRows.value
|
|
1340
|
-
];
|
|
1341
|
-
newDraftRows[draftRowIndex] = updatedDraftRow;
|
|
1342
|
-
this._draftRows.value = newDraftRows;
|
|
1343
|
-
}
|
|
1344
|
-
validateDraftRowData(data) {
|
|
1345
|
-
const schema = toEffectSchema(this._projection.schema);
|
|
1346
|
-
return validateSchema(schema, data) || [];
|
|
1347
|
-
}
|
|
1348
|
-
/**
|
|
1349
|
-
* Updates a cell's value using a transform function.
|
|
1350
|
-
* @param {DxGridPlanePosition} position - The position of the cell to update.
|
|
1351
|
-
* @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
|
|
1352
|
-
*/
|
|
1353
|
-
updateCellData({ col, row }, update) {
|
|
1354
|
-
const dataRow = this._sorting.getDataIndex(row);
|
|
1355
|
-
const fields = this._view?.fields ?? [];
|
|
1356
|
-
const field = fields[col];
|
|
1357
|
-
const value = getValue2(this._rows.value[dataRow], field.path);
|
|
1358
|
-
const updatedValue = update(value);
|
|
1359
|
-
setValue(this._rows.value[dataRow], field.path, updatedValue);
|
|
1360
|
-
}
|
|
1361
|
-
/**
|
|
1362
|
-
* Gets the domain-appropriate cell type for a given cell position.
|
|
1363
|
-
* This abstracts away the low-level grid plane concepts and provides domain-specific types.
|
|
1364
|
-
* @param cell - The cell position to classify
|
|
1365
|
-
* @returns The domain-appropriate cell type
|
|
1366
|
-
*/
|
|
1367
|
-
getCellType(cell) {
|
|
1368
|
-
switch (cell.plane) {
|
|
1369
|
-
case "frozenRowsEnd":
|
|
1370
|
-
return "draft";
|
|
1371
|
-
case "frozenRowsStart":
|
|
1372
|
-
return "header";
|
|
1373
|
-
case "grid":
|
|
1374
|
-
default:
|
|
1375
|
-
return "standard";
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
/**
|
|
1379
|
-
* Convenience method to check if a cell is a draft cell.
|
|
1380
|
-
* @param cell - The cell position to check
|
|
1381
|
-
* @returns true if the cell is a draft cell, false otherwise
|
|
1382
|
-
*/
|
|
1383
|
-
isDraftCell(cell) {
|
|
1384
|
-
return this.getCellType(cell) === "draft";
|
|
1385
|
-
}
|
|
1386
|
-
//
|
|
1387
|
-
// Column Operations
|
|
1388
|
-
//
|
|
1389
|
-
deleteColumn(fieldId) {
|
|
1390
|
-
if (!this._view) {
|
|
418
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
419
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
420
|
+
var TableValueEditor = ({ __gridScope, schema, model, modals, onFocus, onSave, onCreate }) => {
|
|
421
|
+
const { editing } = useGridContext3("TableValueEditor", __gridScope);
|
|
422
|
+
const fieldProjection = useMemo2(() => {
|
|
423
|
+
if (!model || !editing) {
|
|
1391
424
|
return;
|
|
1392
425
|
}
|
|
1393
|
-
const
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
//
|
|
1412
|
-
// Pinning
|
|
1413
|
-
//
|
|
1414
|
-
// TODO(burdon): Change to setPinned(on/off).
|
|
1415
|
-
pinRow(rowIndex, side) {
|
|
1416
|
-
this._pinnedRows[side].push(rowIndex);
|
|
1417
|
-
}
|
|
1418
|
-
unpinRow(rowIndex) {
|
|
1419
|
-
this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
|
|
1420
|
-
this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
|
|
1421
|
-
}
|
|
1422
|
-
//
|
|
1423
|
-
// View operations
|
|
1424
|
-
//
|
|
1425
|
-
saveView() {
|
|
1426
|
-
this._sorting.save();
|
|
1427
|
-
}
|
|
1428
|
-
};
|
|
1429
|
-
var editorTextToCellValue = (props, value) => {
|
|
1430
|
-
switch (props.format) {
|
|
1431
|
-
case FormatEnum3.Ref: {
|
|
1432
|
-
if (isLiveObject(value)) {
|
|
1433
|
-
return Ref3.make(value);
|
|
1434
|
-
} else {
|
|
1435
|
-
return value;
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
case FormatEnum3.SingleSelect: {
|
|
1439
|
-
const ids = extractTagIds(value);
|
|
1440
|
-
if (ids && ids.length > 0) {
|
|
1441
|
-
return ids[0];
|
|
1442
|
-
} else {
|
|
1443
|
-
return value;
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
case FormatEnum3.MultiSelect: {
|
|
1447
|
-
const ids = extractTagIds(value);
|
|
1448
|
-
return ids || value;
|
|
1449
|
-
}
|
|
1450
|
-
default: {
|
|
1451
|
-
return parseValue({
|
|
1452
|
-
type: props.type,
|
|
1453
|
-
format: props.format,
|
|
1454
|
-
value
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
};
|
|
1459
|
-
|
|
1460
|
-
// src/model/modal-controller.ts
|
|
1461
|
-
import { signal as signal4 } from "@preact/signals-core";
|
|
1462
|
-
import { log } from "@dxos/log";
|
|
1463
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
|
|
1464
|
-
var ModalController = class {
|
|
1465
|
-
constructor() {
|
|
1466
|
-
this._state = signal4({
|
|
1467
|
-
type: "closed"
|
|
1468
|
-
});
|
|
1469
|
-
this._triggerRef = {
|
|
1470
|
-
current: null
|
|
1471
|
-
};
|
|
1472
|
-
this.setTrigger = (trigger) => {
|
|
1473
|
-
this._triggerRef.current = trigger;
|
|
1474
|
-
};
|
|
1475
|
-
this.showRowMenu = (rowIndex) => {
|
|
1476
|
-
this._state.value = {
|
|
1477
|
-
type: "row",
|
|
1478
|
-
rowIndex
|
|
1479
|
-
};
|
|
1480
|
-
};
|
|
1481
|
-
this.showColumnMenu = (fieldId) => {
|
|
1482
|
-
this._state.value = {
|
|
1483
|
-
type: "column",
|
|
1484
|
-
fieldId
|
|
1485
|
-
};
|
|
1486
|
-
};
|
|
1487
|
-
this.showColumnCreator = () => {
|
|
1488
|
-
this._state.value = {
|
|
1489
|
-
type: "columnSettings",
|
|
1490
|
-
mode: {
|
|
1491
|
-
type: "create"
|
|
1492
|
-
}
|
|
1493
|
-
};
|
|
1494
|
-
};
|
|
1495
|
-
this.showReferencePanel = (targetId, schemaId) => {
|
|
1496
|
-
this._state.value = {
|
|
1497
|
-
type: "refPanel",
|
|
1498
|
-
targetId,
|
|
1499
|
-
typename: schemaId
|
|
1500
|
-
};
|
|
1501
|
-
};
|
|
1502
|
-
this.openColumnSettings = () => {
|
|
1503
|
-
if (this._state.value.type === "column") {
|
|
1504
|
-
const fieldId = this._state.value.fieldId;
|
|
1505
|
-
requestAnimationFrame(() => {
|
|
1506
|
-
this._state.value = {
|
|
1507
|
-
type: "columnSettings",
|
|
1508
|
-
mode: {
|
|
1509
|
-
type: "edit",
|
|
1510
|
-
fieldId
|
|
1511
|
-
}
|
|
1512
|
-
};
|
|
1513
|
-
});
|
|
1514
|
-
}
|
|
1515
|
-
};
|
|
1516
|
-
this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
|
|
1517
|
-
if (anchorCell) {
|
|
1518
|
-
this._triggerRef.current = anchorCell;
|
|
1519
|
-
this._state.value = {
|
|
1520
|
-
type: "createRefPanel",
|
|
1521
|
-
typename,
|
|
1522
|
-
initialValues,
|
|
1523
|
-
onCreate
|
|
1524
|
-
};
|
|
1525
|
-
} else {
|
|
1526
|
-
log.warn("anchor cell not found while creating new ref", void 0, {
|
|
1527
|
-
F: __dxlog_file2,
|
|
1528
|
-
L: 86,
|
|
1529
|
-
S: this,
|
|
1530
|
-
C: (f, a) => f(...a)
|
|
1531
|
-
});
|
|
1532
|
-
}
|
|
1533
|
-
};
|
|
1534
|
-
this.close = () => {
|
|
1535
|
-
this._state.value = {
|
|
1536
|
-
type: "closed"
|
|
1537
|
-
};
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
get state() {
|
|
1541
|
-
return this._state;
|
|
1542
|
-
}
|
|
1543
|
-
get trigger() {
|
|
1544
|
-
return this._triggerRef;
|
|
1545
|
-
}
|
|
1546
|
-
};
|
|
1547
|
-
|
|
1548
|
-
// src/model/table-presentation.ts
|
|
1549
|
-
import { signal as signal5 } from "@preact/signals-core";
|
|
1550
|
-
import { isNotNullable } from "effect/Predicate";
|
|
1551
|
-
import { Obj as Obj2 } from "@dxos/echo";
|
|
1552
|
-
import { FormatEnum as FormatEnum4, getValue as getValue3, TypeEnum as TypeEnum3 } from "@dxos/echo-schema";
|
|
1553
|
-
import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
|
|
1554
|
-
import { toPlaneCellIndex } from "@dxos/react-ui-grid";
|
|
1555
|
-
import { mx } from "@dxos/react-ui-theme";
|
|
1556
|
-
import { VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
1557
|
-
var TablePresentation = class {
|
|
1558
|
-
constructor(model, _visibleRange = signal5({
|
|
1559
|
-
start: {
|
|
1560
|
-
row: 0,
|
|
1561
|
-
col: 0
|
|
1562
|
-
},
|
|
1563
|
-
end: {
|
|
1564
|
-
row: 0,
|
|
1565
|
-
col: 0
|
|
1566
|
-
}
|
|
1567
|
-
})) {
|
|
1568
|
-
this.model = model;
|
|
1569
|
-
this._visibleRange = _visibleRange;
|
|
1570
|
-
this.fieldProjectionCache = /* @__PURE__ */ new Map();
|
|
1571
|
-
}
|
|
1572
|
-
getCells(range, plane) {
|
|
1573
|
-
this.fieldProjectionCache.clear();
|
|
1574
|
-
let cells;
|
|
1575
|
-
switch (plane) {
|
|
1576
|
-
case "grid":
|
|
1577
|
-
this._visibleRange.value = range;
|
|
1578
|
-
cells = this.getMainGridCells(range);
|
|
1579
|
-
break;
|
|
1580
|
-
case "frozenRowsStart":
|
|
1581
|
-
cells = this.getHeaderCells(range);
|
|
1582
|
-
break;
|
|
1583
|
-
case "frozenColsStart":
|
|
1584
|
-
cells = this.getSelectionColumnCells(range);
|
|
1585
|
-
break;
|
|
1586
|
-
case "frozenColsEnd":
|
|
1587
|
-
cells = this.getActionColumnCells(range);
|
|
1588
|
-
break;
|
|
1589
|
-
case "fixedStartStart":
|
|
1590
|
-
cells = this.getSelectAllCell();
|
|
1591
|
-
break;
|
|
1592
|
-
case "fixedStartEnd":
|
|
1593
|
-
cells = this.getNewColumnCell();
|
|
1594
|
-
break;
|
|
1595
|
-
case "frozenRowsEnd":
|
|
1596
|
-
cells = this.getDraftRowCells(range);
|
|
1597
|
-
break;
|
|
1598
|
-
case "fixedEndEnd":
|
|
1599
|
-
cells = this.getDraftActionCells(range);
|
|
1600
|
-
break;
|
|
1601
|
-
default:
|
|
1602
|
-
cells = {};
|
|
1603
|
-
}
|
|
1604
|
-
if (plane === "grid" && this.model.features.dataEditable === false) {
|
|
1605
|
-
Object.values(cells).forEach((cell) => {
|
|
1606
|
-
cell.readonly = "text-select";
|
|
1607
|
-
});
|
|
1608
|
-
}
|
|
1609
|
-
return cells;
|
|
1610
|
-
}
|
|
1611
|
-
/**
|
|
1612
|
-
* Gets a field projection, using cache if available within the current render pass.
|
|
1613
|
-
*/
|
|
1614
|
-
getFieldProjection(fieldId) {
|
|
1615
|
-
let projection = this.fieldProjectionCache.get(fieldId);
|
|
1616
|
-
if (!projection) {
|
|
1617
|
-
projection = this.model.projection.getFieldProjection(fieldId);
|
|
1618
|
-
this.fieldProjectionCache.set(fieldId, projection);
|
|
1619
|
-
}
|
|
1620
|
-
return projection;
|
|
1621
|
-
}
|
|
1622
|
-
createDataCell(cells, obj, field, colIndex, displayIndex) {
|
|
1623
|
-
const { props } = this.getFieldProjection(field.id);
|
|
1624
|
-
const cell = {
|
|
1625
|
-
get value() {
|
|
1626
|
-
const value = getValue3(obj, field.path);
|
|
1627
|
-
if (value == null) {
|
|
1628
|
-
return "";
|
|
1629
|
-
}
|
|
1630
|
-
if (props.type === "array") {
|
|
1631
|
-
return "";
|
|
1632
|
-
}
|
|
1633
|
-
switch (props.format) {
|
|
1634
|
-
case FormatEnum4.Boolean:
|
|
1635
|
-
case FormatEnum4.SingleSelect:
|
|
1636
|
-
case FormatEnum4.MultiSelect: {
|
|
1637
|
-
return "";
|
|
1638
|
-
}
|
|
1639
|
-
case FormatEnum4.Ref: {
|
|
1640
|
-
if (!field.referencePath) {
|
|
1641
|
-
return "";
|
|
1642
|
-
}
|
|
1643
|
-
return getValue3(value.target, field.referencePath);
|
|
1644
|
-
}
|
|
1645
|
-
default: {
|
|
1646
|
-
return formatForDisplay2({
|
|
1647
|
-
type: props.type,
|
|
1648
|
-
format: props.format,
|
|
1649
|
-
value
|
|
1650
|
-
});
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
};
|
|
1655
|
-
const classes = [];
|
|
1656
|
-
const formatClasses = cellClassesForFieldType({
|
|
1657
|
-
type: props.type,
|
|
1658
|
-
format: props.format
|
|
1659
|
-
});
|
|
1660
|
-
if (formatClasses) {
|
|
1661
|
-
classes.push(formatClasses);
|
|
1662
|
-
}
|
|
1663
|
-
const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj), this.model.selection.selectionMode);
|
|
1664
|
-
if (rowSelectionClasses) {
|
|
1665
|
-
classes.push(rowSelectionClasses);
|
|
1666
|
-
}
|
|
1667
|
-
if (classes.length > 0) {
|
|
1668
|
-
cell.className = mx(classes.flat());
|
|
1669
|
-
}
|
|
1670
|
-
if (props.type === TypeEnum3.Array) {
|
|
1671
|
-
const targetArray = getValue3(obj, field.path);
|
|
1672
|
-
if (targetArray && Array.isArray(targetArray)) {
|
|
1673
|
-
const getLabel = (value) => {
|
|
1674
|
-
if (!value) {
|
|
1675
|
-
return void 0;
|
|
1676
|
-
}
|
|
1677
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1678
|
-
return String(value);
|
|
1679
|
-
}
|
|
1680
|
-
if (Array.isArray(value)) {
|
|
1681
|
-
return "Array";
|
|
1682
|
-
}
|
|
1683
|
-
if (typeof value === "object" && value.name) {
|
|
1684
|
-
return value.name;
|
|
1685
|
-
}
|
|
1686
|
-
if (typeof value === "object" && value.value) {
|
|
1687
|
-
return `${value.value}`;
|
|
1688
|
-
}
|
|
1689
|
-
return "Object";
|
|
1690
|
-
};
|
|
1691
|
-
const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
|
|
1692
|
-
return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
|
|
1693
|
-
}).join("");
|
|
1694
|
-
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
if (props.format === FormatEnum4.Ref && props.referenceSchema) {
|
|
1698
|
-
const targetObj = getValue3(obj, field.path)?.target;
|
|
1699
|
-
if (targetObj) {
|
|
1700
|
-
const dxn = Obj2.getDXN(targetObj)?.toString();
|
|
1701
|
-
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>`;
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
if (props.format === FormatEnum4.Boolean) {
|
|
1705
|
-
const value = getValue3(obj, field.path);
|
|
1706
|
-
cell.accessoryHtml = tableControls.switch.render({
|
|
1707
|
-
colIndex,
|
|
1708
|
-
rowIndex: displayIndex,
|
|
1709
|
-
checked: value ?? false
|
|
1710
|
-
});
|
|
1711
|
-
cell.readonly = "no-text-select";
|
|
1712
|
-
}
|
|
1713
|
-
if (props.format === FormatEnum4.SingleSelect) {
|
|
1714
|
-
const value = getValue3(obj, field.path);
|
|
1715
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1716
|
-
if (options) {
|
|
1717
|
-
const option = options.find((o) => o.id === value);
|
|
1718
|
-
if (option) {
|
|
1719
|
-
cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
if (props.format === FormatEnum4.MultiSelect) {
|
|
1724
|
-
const values = getValue3(obj, field.path);
|
|
1725
|
-
const options = this.model.projection.getFieldProjection(field.id).props.options;
|
|
1726
|
-
if (options && values && values.length > 0) {
|
|
1727
|
-
const tags = values.map((value) => {
|
|
1728
|
-
const option = options.find((o) => o.id === value);
|
|
1729
|
-
if (option) {
|
|
1730
|
-
return `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
|
|
1731
|
-
}
|
|
1732
|
-
return null;
|
|
1733
|
-
}).filter(Boolean).join("");
|
|
1734
|
-
if (tags) {
|
|
1735
|
-
cell.accessoryHtml = tags;
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
const idx = toPlaneCellIndex({
|
|
1740
|
-
col: colIndex,
|
|
1741
|
-
row: displayIndex
|
|
426
|
+
const { col } = parseCellIndex2(editing.index);
|
|
427
|
+
const field = model.projection.getFields()[col];
|
|
428
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
429
|
+
invariant2(fieldProjection2, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 21, S: void 0, A: ["fieldProjection", ""] });
|
|
430
|
+
return fieldProjection2;
|
|
431
|
+
}, [
|
|
432
|
+
model,
|
|
433
|
+
editing
|
|
434
|
+
]);
|
|
435
|
+
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === Format.TypeFormat.SingleSelect || fieldProjection?.props.format === Format.TypeFormat.Ref) {
|
|
436
|
+
return /* @__PURE__ */ React3.createElement(FormCellEditor, {
|
|
437
|
+
__gridScope,
|
|
438
|
+
schema,
|
|
439
|
+
model,
|
|
440
|
+
fieldProjection,
|
|
441
|
+
modals,
|
|
442
|
+
onSave,
|
|
443
|
+
onCreate
|
|
1742
444
|
});
|
|
1743
|
-
cells[idx] = cell;
|
|
1744
|
-
}
|
|
1745
|
-
getMainGridCells(range) {
|
|
1746
|
-
const cells = {};
|
|
1747
|
-
const fields = this.model.view?.fields ?? [];
|
|
1748
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1749
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1750
|
-
const field = fields[col];
|
|
1751
|
-
if (!field) {
|
|
1752
|
-
continue;
|
|
1753
|
-
}
|
|
1754
|
-
this.createDataCell(cells, this.model.rows.value[row], field, col, row);
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
return cells;
|
|
1758
|
-
}
|
|
1759
|
-
getDraftRowCells(range) {
|
|
1760
|
-
const cells = {};
|
|
1761
|
-
const fields = this.model.view?.fields ?? [];
|
|
1762
|
-
const draftRows = this.model.draftRows.value;
|
|
1763
|
-
for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
|
|
1764
|
-
const draftRow = draftRows[row];
|
|
1765
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1766
|
-
const field = fields[col];
|
|
1767
|
-
if (!field) {
|
|
1768
|
-
continue;
|
|
1769
|
-
}
|
|
1770
|
-
this.createDataCell(cells, draftRow.data, field, col, row);
|
|
1771
|
-
if (this.model.hasDraftRowValidationError(row, field.path)) {
|
|
1772
|
-
const cellIndex = toPlaneCellIndex({
|
|
1773
|
-
col,
|
|
1774
|
-
row
|
|
1775
|
-
});
|
|
1776
|
-
const cellValue = cells[cellIndex];
|
|
1777
|
-
if (cellValue) {
|
|
1778
|
-
const existingClasses = cellValue.className || "";
|
|
1779
|
-
const draftClasses = "dx-grid__cell--flagged";
|
|
1780
|
-
cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
return cells;
|
|
1786
|
-
}
|
|
1787
|
-
getHeaderCells(range) {
|
|
1788
|
-
const cells = {};
|
|
1789
|
-
const fields = this.model.view?.fields ?? [];
|
|
1790
|
-
for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
|
|
1791
|
-
const { field, props } = this.getFieldProjection(fields[col].id);
|
|
1792
|
-
const sorting = this.model.sorting?.sorting;
|
|
1793
|
-
const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
|
|
1794
|
-
cells[toPlaneCellIndex({
|
|
1795
|
-
col,
|
|
1796
|
-
row: 0
|
|
1797
|
-
})] = {
|
|
1798
|
-
// TODO(burdon): Use same logic as form for fallback title.
|
|
1799
|
-
value: props.title ?? field.path,
|
|
1800
|
-
readonly: true,
|
|
1801
|
-
resizeHandle: "col",
|
|
1802
|
-
accessoryHtml: `
|
|
1803
|
-
${direction !== void 0 ? tableButtons.sort.render({
|
|
1804
|
-
fieldId: field.id,
|
|
1805
|
-
direction
|
|
1806
|
-
}) : ""}
|
|
1807
|
-
${tableButtons.columnSettings.render({
|
|
1808
|
-
fieldId: field.id
|
|
1809
|
-
})}
|
|
1810
|
-
`,
|
|
1811
|
-
className: "!bg-toolbarSurface"
|
|
1812
|
-
};
|
|
1813
|
-
}
|
|
1814
|
-
return cells;
|
|
1815
|
-
}
|
|
1816
|
-
getSelectionColumnCells(range) {
|
|
1817
|
-
const cells = {};
|
|
1818
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1819
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1820
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1821
|
-
cells[toPlaneCellIndex({
|
|
1822
|
-
col: 0,
|
|
1823
|
-
row
|
|
1824
|
-
})] = {
|
|
1825
|
-
value: "",
|
|
1826
|
-
readonly: "no-text-select",
|
|
1827
|
-
className: classes ? mx(classes) : void 0,
|
|
1828
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1829
|
-
rowIndex: row,
|
|
1830
|
-
checked: isSelected
|
|
1831
|
-
})
|
|
1832
|
-
};
|
|
1833
|
-
}
|
|
1834
|
-
return cells;
|
|
1835
|
-
}
|
|
1836
|
-
getActionColumnCells(range) {
|
|
1837
|
-
const cells = {};
|
|
1838
|
-
for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
|
|
1839
|
-
const isSelected = this.model.selection.isRowIndexSelected(row);
|
|
1840
|
-
const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
|
|
1841
|
-
cells[toPlaneCellIndex({
|
|
1842
|
-
col: 0,
|
|
1843
|
-
row
|
|
1844
|
-
})] = {
|
|
1845
|
-
value: "",
|
|
1846
|
-
readonly: true,
|
|
1847
|
-
className: classes ? mx(classes) : void 0,
|
|
1848
|
-
accessoryHtml: tableButtons.rowMenu.render({
|
|
1849
|
-
rowIndex: row
|
|
1850
|
-
})
|
|
1851
|
-
};
|
|
1852
|
-
}
|
|
1853
|
-
return cells;
|
|
1854
|
-
}
|
|
1855
|
-
getSelectAllCell() {
|
|
1856
|
-
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === "single") {
|
|
1857
|
-
return {
|
|
1858
|
-
[toPlaneCellIndex({
|
|
1859
|
-
col: 0,
|
|
1860
|
-
row: 0
|
|
1861
|
-
})]: {
|
|
1862
|
-
className: "!bg-toolbarSurface",
|
|
1863
|
-
readonly: true,
|
|
1864
|
-
value: ""
|
|
1865
|
-
}
|
|
1866
|
-
};
|
|
1867
|
-
}
|
|
1868
|
-
return {
|
|
1869
|
-
[toPlaneCellIndex({
|
|
1870
|
-
col: 0,
|
|
1871
|
-
row: 0
|
|
1872
|
-
})]: {
|
|
1873
|
-
accessoryHtml: tableControls.checkbox.render({
|
|
1874
|
-
rowIndex: 0,
|
|
1875
|
-
header: true,
|
|
1876
|
-
checked: this.model.selection.allRowsSeleted.value
|
|
1877
|
-
}),
|
|
1878
|
-
className: "!bg-toolbarSurface",
|
|
1879
|
-
readonly: true,
|
|
1880
|
-
value: ""
|
|
1881
|
-
}
|
|
1882
|
-
};
|
|
1883
|
-
}
|
|
1884
|
-
getNewColumnCell() {
|
|
1885
|
-
return {
|
|
1886
|
-
[toPlaneCellIndex({
|
|
1887
|
-
col: 0,
|
|
1888
|
-
row: 0
|
|
1889
|
-
})]: {
|
|
1890
|
-
accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
|
|
1891
|
-
disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT
|
|
1892
|
-
}) : void 0,
|
|
1893
|
-
className: "!bg-toolbarSurface",
|
|
1894
|
-
readonly: true,
|
|
1895
|
-
value: ""
|
|
1896
|
-
}
|
|
1897
|
-
};
|
|
1898
|
-
}
|
|
1899
|
-
getDraftActionCells(range) {
|
|
1900
|
-
const cells = {};
|
|
1901
|
-
const draftRows = this.model.draftRows.value;
|
|
1902
|
-
for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
|
|
1903
|
-
const draftRow = draftRows[row];
|
|
1904
|
-
const disabled = !draftRow.valid;
|
|
1905
|
-
cells[toPlaneCellIndex({
|
|
1906
|
-
col: 0,
|
|
1907
|
-
row
|
|
1908
|
-
})] = {
|
|
1909
|
-
value: "",
|
|
1910
|
-
readonly: true,
|
|
1911
|
-
accessoryHtml: tableButtons.saveDraftRow.render({
|
|
1912
|
-
rowIndex: row,
|
|
1913
|
-
disabled
|
|
1914
|
-
})
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
return cells;
|
|
1918
445
|
}
|
|
446
|
+
return /* @__PURE__ */ React3.createElement(TableCellEditor, {
|
|
447
|
+
model,
|
|
448
|
+
modals,
|
|
449
|
+
onFocus,
|
|
450
|
+
onSave,
|
|
451
|
+
__gridScope
|
|
452
|
+
});
|
|
1919
453
|
};
|
|
1920
|
-
var
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
return
|
|
454
|
+
var TableCellEditor = ({ __gridScope, model, modals, onFocus, onSave }) => {
|
|
455
|
+
const { editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
|
|
456
|
+
const suppressNextBlur = useRef2(false);
|
|
457
|
+
const [validationError, setValidationError] = useState2(null);
|
|
458
|
+
const [validationVariant, setValidationVariant] = useState2("error");
|
|
459
|
+
const fieldProjection = useMemo2(() => {
|
|
460
|
+
if (!model || !editing) {
|
|
461
|
+
return;
|
|
1928
462
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
};
|
|
1942
|
-
|
|
1943
|
-
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
1944
|
-
import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
|
|
1945
|
-
import React7, { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef2, useState as useState2 } from "react";
|
|
1946
|
-
import { FormatEnum as FormatEnum5, TypeEnum as TypeEnum4 } from "@dxos/echo-schema";
|
|
1947
|
-
import { invariant as invariant3 } from "@dxos/invariant";
|
|
1948
|
-
import { useThemeContext } from "@dxos/react-ui";
|
|
1949
|
-
import { createMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
1950
|
-
import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext4, GridCellEditor } from "@dxos/react-ui-grid";
|
|
1951
|
-
import { tagPicker, createLinks } from "@dxos/react-ui-tag-picker";
|
|
1952
|
-
|
|
1953
|
-
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
1954
|
-
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
1955
|
-
import React5 from "react";
|
|
1956
|
-
import { useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
1957
|
-
var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
|
|
1958
|
-
var _effect = _useSignals5();
|
|
1959
|
-
try {
|
|
1960
|
-
const { editing, editBox: box } = useGridContext2("GridSheetCellEditor", __gridScope);
|
|
1961
|
-
if (!editing || !validationError) {
|
|
1962
|
-
return null;
|
|
463
|
+
const { col } = parseCellIndex2(editing.index);
|
|
464
|
+
const field = model.projection.getFields()[col];
|
|
465
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
466
|
+
invariant2(fieldProjection2, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 59, S: void 0, A: ["fieldProjection", ""] });
|
|
467
|
+
return fieldProjection2;
|
|
468
|
+
}, [
|
|
469
|
+
model,
|
|
470
|
+
editing
|
|
471
|
+
]);
|
|
472
|
+
const handleEnter = useCallback2(async (value) => {
|
|
473
|
+
if (!model || !editing) {
|
|
474
|
+
return;
|
|
1963
475
|
}
|
|
1964
|
-
const
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
...{
|
|
1971
|
-
"--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
|
|
1972
|
-
},
|
|
1973
|
-
zIndex: 10,
|
|
1974
|
-
insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
|
|
1975
|
-
insetInlineStart: box.insetInlineStart,
|
|
1976
|
-
inlineSize: box.inlineSize
|
|
1977
|
-
}
|
|
1978
|
-
}, validationError);
|
|
1979
|
-
} finally {
|
|
1980
|
-
_effect.f();
|
|
1981
|
-
}
|
|
1982
|
-
};
|
|
1983
|
-
|
|
1984
|
-
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
1985
|
-
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
1986
|
-
import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
|
|
1987
|
-
import { getSnapshot as getSnapshot2 } from "@dxos/echo-schema";
|
|
1988
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
1989
|
-
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
1990
|
-
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
1991
|
-
import { parseCellIndex, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
1992
|
-
import { getDeep, setDeep } from "@dxos/util";
|
|
1993
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
1994
|
-
var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
1995
|
-
var _effect = _useSignals6();
|
|
1996
|
-
try {
|
|
1997
|
-
const { editing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
|
|
1998
|
-
const cellRef = useRef(null);
|
|
1999
|
-
useEffect2(() => {
|
|
2000
|
-
if (editing && editing.cellElement) {
|
|
2001
|
-
cellRef.current = editing.cellElement;
|
|
2002
|
-
}
|
|
2003
|
-
}, [
|
|
2004
|
-
editing?.cellElement
|
|
2005
|
-
]);
|
|
2006
|
-
const narrowedSchema = useMemo3(() => {
|
|
2007
|
-
if (!schema) {
|
|
2008
|
-
return void 0;
|
|
2009
|
-
}
|
|
2010
|
-
return narrowSchema(schema, [
|
|
2011
|
-
fieldProjection.field.path
|
|
2012
|
-
]);
|
|
2013
|
-
}, [
|
|
2014
|
-
JSON.stringify(schema),
|
|
2015
|
-
fieldProjection.field.path
|
|
2016
|
-
]);
|
|
2017
|
-
const originalRow = useMemo3(() => {
|
|
2018
|
-
if (model && editing) {
|
|
2019
|
-
const cell = parseCellIndex(editing.index);
|
|
2020
|
-
const row = model.getRowAt(cell.row);
|
|
2021
|
-
invariant2(row, void 0, {
|
|
2022
|
-
F: __dxlog_file3,
|
|
2023
|
-
L: 47,
|
|
2024
|
-
S: void 0,
|
|
2025
|
-
A: [
|
|
2026
|
-
"row",
|
|
2027
|
-
""
|
|
2028
|
-
]
|
|
2029
|
-
});
|
|
2030
|
-
return row;
|
|
2031
|
-
}
|
|
2032
|
-
return void 0;
|
|
2033
|
-
}, [
|
|
2034
|
-
model,
|
|
2035
|
-
editing
|
|
2036
|
-
]);
|
|
2037
|
-
const formValues = useMemo3(() => {
|
|
2038
|
-
if (originalRow) {
|
|
2039
|
-
return getSnapshot2(originalRow);
|
|
2040
|
-
}
|
|
2041
|
-
}, [
|
|
2042
|
-
originalRow
|
|
2043
|
-
]);
|
|
2044
|
-
const handleSave = useCallback3((values) => {
|
|
2045
|
-
const path = fieldProjection.field.path;
|
|
2046
|
-
const value = getDeep(values, [
|
|
2047
|
-
path
|
|
2048
|
-
]);
|
|
2049
|
-
setDeep(originalRow, [
|
|
2050
|
-
path
|
|
2051
|
-
], value);
|
|
476
|
+
const cell = parseCellIndex2(editing.index);
|
|
477
|
+
const validationResult = await model.validateCellData(cell, value);
|
|
478
|
+
if (validationResult.valid) {
|
|
479
|
+
setValidationError(null);
|
|
480
|
+
model.setCellData(cell, value);
|
|
481
|
+
onFocus?.();
|
|
2052
482
|
setEditing(null);
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
const handleOpenChange = useCallback3((nextOpen) => {
|
|
2058
|
-
if (nextOpen === false) {
|
|
2059
|
-
setEditing(null);
|
|
2060
|
-
}
|
|
2061
|
-
}, [
|
|
2062
|
-
setEditing
|
|
2063
|
-
]);
|
|
2064
|
-
if (!editing) {
|
|
2065
|
-
return null;
|
|
2066
|
-
}
|
|
2067
|
-
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
2068
|
-
open: editing !== null,
|
|
2069
|
-
onOpenChange: handleOpenChange
|
|
2070
|
-
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
2071
|
-
virtualRef: cellRef
|
|
2072
|
-
}), /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
2073
|
-
tabIndex: -1,
|
|
2074
|
-
classNames: "popover-card-width"
|
|
2075
|
-
}, /* @__PURE__ */ React6.createElement(Popover3.Arrow, null), /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, /* @__PURE__ */ React6.createElement(Form2, {
|
|
2076
|
-
values: formValues,
|
|
2077
|
-
schema: narrowedSchema,
|
|
2078
|
-
onSave: handleSave
|
|
2079
|
-
}))));
|
|
2080
|
-
} finally {
|
|
2081
|
-
_effect.f();
|
|
2082
|
-
}
|
|
2083
|
-
};
|
|
2084
|
-
|
|
2085
|
-
// src/components/TableCellEditor/extension.ts
|
|
2086
|
-
import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
|
|
2087
|
-
import { EditorView } from "@codemirror/view";
|
|
2088
|
-
var completion = ({ debug, onQuery, onMatch }) => {
|
|
2089
|
-
return [
|
|
2090
|
-
EditorView.theme({
|
|
2091
|
-
".cm-completionDialog": {
|
|
2092
|
-
width: "var(--dx-gridCellWidth)"
|
|
2093
|
-
}
|
|
2094
|
-
}),
|
|
2095
|
-
autocompletion({
|
|
2096
|
-
icons: false,
|
|
2097
|
-
activateOnTyping: true,
|
|
2098
|
-
closeOnBlur: !debug,
|
|
2099
|
-
override: [
|
|
2100
|
-
async (context) => {
|
|
2101
|
-
const text = context.state.doc.toString();
|
|
2102
|
-
return {
|
|
2103
|
-
from: 0,
|
|
2104
|
-
options: await onQuery(text)
|
|
2105
|
-
};
|
|
2106
|
-
}
|
|
2107
|
-
],
|
|
2108
|
-
// TODO(burdon): Consts from grid (to line-up with grid).
|
|
2109
|
-
tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
|
|
2110
|
-
optionClass: () => "flex h-[33px] items-center"
|
|
2111
|
-
}),
|
|
2112
|
-
// Check for accepted completion metadata in the transaction.
|
|
2113
|
-
EditorView.updateListener.of((update) => {
|
|
2114
|
-
update.transactions.forEach((tr) => {
|
|
2115
|
-
const completion2 = tr.annotation(pickedCompletion);
|
|
2116
|
-
if (completion2) {
|
|
2117
|
-
onMatch(completion2.data);
|
|
2118
|
-
}
|
|
2119
|
-
});
|
|
2120
|
-
})
|
|
2121
|
-
];
|
|
2122
|
-
};
|
|
2123
|
-
|
|
2124
|
-
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
2125
|
-
var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
2126
|
-
var newValue = Symbol.for("newValue");
|
|
2127
|
-
var createOption = (text) => ({
|
|
2128
|
-
[newValue]: true,
|
|
2129
|
-
text
|
|
2130
|
-
});
|
|
2131
|
-
var isCreateOption = (data) => typeof data === "object" && data[newValue];
|
|
2132
|
-
var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gridScope }) => {
|
|
2133
|
-
var _effect = _useSignals7();
|
|
2134
|
-
try {
|
|
2135
|
-
const { editing } = useGridContext4("TableValueEditor", __gridScope);
|
|
2136
|
-
const fieldProjection = useMemo4(() => {
|
|
2137
|
-
if (!model || !editing) {
|
|
2138
|
-
return;
|
|
2139
|
-
}
|
|
2140
|
-
const { col } = parseCellIndex2(editing.index);
|
|
2141
|
-
const field = model.projection.view.fields[col];
|
|
2142
|
-
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
2143
|
-
invariant3(fieldProjection2, void 0, {
|
|
2144
|
-
F: __dxlog_file4,
|
|
2145
|
-
L: 74,
|
|
2146
|
-
S: void 0,
|
|
2147
|
-
A: [
|
|
2148
|
-
"fieldProjection",
|
|
2149
|
-
""
|
|
2150
|
-
]
|
|
2151
|
-
});
|
|
2152
|
-
return fieldProjection2;
|
|
2153
|
-
}, [
|
|
2154
|
-
model,
|
|
2155
|
-
editing
|
|
2156
|
-
]);
|
|
2157
|
-
if (fieldProjection?.props.type === TypeEnum4.Array) {
|
|
2158
|
-
return /* @__PURE__ */ React7.createElement(FormCellEditor, {
|
|
2159
|
-
fieldProjection,
|
|
2160
|
-
model,
|
|
2161
|
-
schema,
|
|
2162
|
-
__gridScope
|
|
2163
|
-
});
|
|
483
|
+
onSave?.();
|
|
484
|
+
} else {
|
|
485
|
+
setValidationError(validationResult.error);
|
|
486
|
+
setValidationVariant("error");
|
|
2164
487
|
}
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
}
|
|
2176
|
-
};
|
|
2177
|
-
var editorSlots = {
|
|
2178
|
-
scroller: {
|
|
2179
|
-
className: "!plb-[--dx-grid-cell-editor-padding-block]"
|
|
2180
|
-
}
|
|
2181
|
-
};
|
|
2182
|
-
var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
|
|
2183
|
-
var _effect = _useSignals7();
|
|
2184
|
-
try {
|
|
2185
|
-
const { id: gridId, editing, setEditing } = useGridContext4("TableCellEditor", __gridScope);
|
|
2186
|
-
const suppressNextBlur = useRef2(false);
|
|
2187
|
-
const { themeMode } = useThemeContext();
|
|
2188
|
-
const [_validationError, setValidationError] = useState2(null);
|
|
2189
|
-
const [_validationVariant, setValidationVariant] = useState2("error");
|
|
2190
|
-
const fieldProjection = useMemo4(() => {
|
|
2191
|
-
if (!model || !editing) {
|
|
2192
|
-
return;
|
|
2193
|
-
}
|
|
2194
|
-
const { col } = parseCellIndex2(editing.index);
|
|
2195
|
-
const field = model.projection.view.fields[col];
|
|
2196
|
-
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
2197
|
-
invariant3(fieldProjection2, void 0, {
|
|
2198
|
-
F: __dxlog_file4,
|
|
2199
|
-
L: 119,
|
|
2200
|
-
S: void 0,
|
|
2201
|
-
A: [
|
|
2202
|
-
"fieldProjection",
|
|
2203
|
-
""
|
|
2204
|
-
]
|
|
2205
|
-
});
|
|
2206
|
-
return fieldProjection2;
|
|
2207
|
-
}, [
|
|
2208
|
-
model,
|
|
2209
|
-
editing
|
|
2210
|
-
]);
|
|
2211
|
-
useEffect3(() => {
|
|
2212
|
-
if (!model || !editing || !fieldProjection) {
|
|
2213
|
-
setValidationError(null);
|
|
2214
|
-
return;
|
|
2215
|
-
}
|
|
2216
|
-
const cell = parseCellIndex2(editing.index);
|
|
2217
|
-
const { row, col } = cell;
|
|
2218
|
-
if (model.isDraftCell(cell)) {
|
|
2219
|
-
const field = model.projection.view.fields[col];
|
|
2220
|
-
const hasValidationError = model.hasDraftRowValidationError(row, field.path);
|
|
2221
|
-
if (hasValidationError) {
|
|
2222
|
-
const draftRows = model.draftRows.value;
|
|
2223
|
-
if (row >= 0 && row < draftRows.length) {
|
|
2224
|
-
const draftRow = draftRows[row];
|
|
2225
|
-
const validationError = draftRow.validationErrors?.find((error) => error.path === field.path);
|
|
2226
|
-
if (validationError) {
|
|
2227
|
-
setValidationError(validationError.message);
|
|
2228
|
-
setValidationVariant("warning");
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
} else {
|
|
2232
|
-
setValidationError(null);
|
|
2233
|
-
}
|
|
2234
|
-
} else {
|
|
2235
|
-
setValidationError(null);
|
|
2236
|
-
}
|
|
2237
|
-
}, [
|
|
2238
|
-
model,
|
|
2239
|
-
editing,
|
|
2240
|
-
fieldProjection
|
|
2241
|
-
]);
|
|
2242
|
-
const handleEnter = useCallback4(async (value) => {
|
|
2243
|
-
if (!model || !editing) {
|
|
2244
|
-
return;
|
|
2245
|
-
}
|
|
2246
|
-
const cell = parseCellIndex2(editing.index);
|
|
2247
|
-
const validationResult = await model.validateCellData(cell, value);
|
|
2248
|
-
if (validationResult.valid) {
|
|
2249
|
-
setValidationError(null);
|
|
2250
|
-
model.setCellData(cell, value);
|
|
2251
|
-
onEnter?.(cell);
|
|
2252
|
-
onFocus?.();
|
|
2253
|
-
setEditing(null);
|
|
2254
|
-
} else {
|
|
2255
|
-
setValidationError(validationResult.error);
|
|
2256
|
-
setValidationVariant("error");
|
|
2257
|
-
}
|
|
2258
|
-
}, [
|
|
2259
|
-
model,
|
|
2260
|
-
editing,
|
|
2261
|
-
onEnter,
|
|
2262
|
-
onFocus,
|
|
2263
|
-
setEditing
|
|
2264
|
-
]);
|
|
2265
|
-
const handleBlur = useCallback4(async (value) => {
|
|
2266
|
-
if (!model || !editing) {
|
|
2267
|
-
return;
|
|
2268
|
-
}
|
|
2269
|
-
if (suppressNextBlur.current) {
|
|
2270
|
-
suppressNextBlur.current = false;
|
|
2271
|
-
}
|
|
2272
|
-
}, [
|
|
2273
|
-
model,
|
|
2274
|
-
editing
|
|
2275
|
-
]);
|
|
2276
|
-
const handleClose = useCallback4(async (value, event) => {
|
|
2277
|
-
if (!model || !editing || !fieldProjection) {
|
|
2278
|
-
return;
|
|
2279
|
-
}
|
|
488
|
+
}, [
|
|
489
|
+
model,
|
|
490
|
+
editing,
|
|
491
|
+
onFocus,
|
|
492
|
+
setEditing
|
|
493
|
+
]);
|
|
494
|
+
const handleBlur = useCallback2(async (value) => {
|
|
495
|
+
if (suppressNextBlur.current) {
|
|
496
|
+
suppressNextBlur.current = false;
|
|
497
|
+
} else if (model && editing) {
|
|
2280
498
|
const cell = parseCellIndex2(editing.index);
|
|
2281
499
|
if (value !== void 0) {
|
|
2282
500
|
const result = await model.validateCellData(cell, value);
|
|
@@ -2284,169 +502,109 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2284
502
|
setValidationError(null);
|
|
2285
503
|
model.setCellData(cell, value);
|
|
2286
504
|
setEditing(null);
|
|
2287
|
-
|
|
2288
|
-
if (event && onFocus) {
|
|
2289
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2290
|
-
}
|
|
2291
|
-
} else {
|
|
2292
|
-
setValidationError(result.error);
|
|
2293
|
-
setValidationVariant("error");
|
|
505
|
+
onSave?.();
|
|
2294
506
|
}
|
|
2295
|
-
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}, [
|
|
510
|
+
model,
|
|
511
|
+
editing
|
|
512
|
+
]);
|
|
513
|
+
const handleClose = useCallback2(async (value, event) => {
|
|
514
|
+
if (!model || !editing || !fieldProjection) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const cell = parseCellIndex2(editing.index);
|
|
518
|
+
if (value !== void 0) {
|
|
519
|
+
const result = await model.validateCellData(cell, value);
|
|
520
|
+
if (result.valid) {
|
|
521
|
+
suppressNextBlur.current = true;
|
|
2296
522
|
setValidationError(null);
|
|
523
|
+
model.setCellData(cell, value);
|
|
2297
524
|
setEditing(null);
|
|
525
|
+
onSave?.();
|
|
2298
526
|
if (event && onFocus) {
|
|
2299
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
527
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
|
|
2300
528
|
}
|
|
529
|
+
} else {
|
|
530
|
+
setValidationError(result.error);
|
|
531
|
+
setValidationVariant("error");
|
|
2301
532
|
}
|
|
2302
|
-
}
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
]);
|
|
2310
|
-
const extension = useMemo4(() => {
|
|
2311
|
-
if (!fieldProjection) {
|
|
2312
|
-
return [];
|
|
2313
|
-
}
|
|
2314
|
-
const extension2 = [
|
|
2315
|
-
editorKeys({
|
|
2316
|
-
onClose: handleClose,
|
|
2317
|
-
...editing?.initialContent && {
|
|
2318
|
-
onNav: handleClose
|
|
2319
|
-
}
|
|
2320
|
-
})
|
|
2321
|
-
];
|
|
2322
|
-
const format = fieldProjection.props.format;
|
|
2323
|
-
if (format === FormatEnum5.SingleSelect || format === FormatEnum5.MultiSelect) {
|
|
2324
|
-
extension2.push(createMarkdownExtensions({
|
|
2325
|
-
themeMode
|
|
2326
|
-
}));
|
|
2327
|
-
const options = fieldProjection.props.options || [];
|
|
2328
|
-
const mode = format === FormatEnum5.SingleSelect ? "single-select" : "multi-select";
|
|
2329
|
-
extension2.push(tagPicker({
|
|
2330
|
-
mode,
|
|
2331
|
-
keymap: false,
|
|
2332
|
-
onSearch: (text, selectedIds) => {
|
|
2333
|
-
return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
|
|
2334
|
-
id: option.id,
|
|
2335
|
-
label: option.title,
|
|
2336
|
-
hue: option.color
|
|
2337
|
-
}));
|
|
2338
|
-
},
|
|
2339
|
-
onUpdate: (ids) => {
|
|
2340
|
-
if (model && editing) {
|
|
2341
|
-
if (ids.length === 0) {
|
|
2342
|
-
return;
|
|
2343
|
-
}
|
|
2344
|
-
if (mode === "single-select") {
|
|
2345
|
-
void handleEnter(ids[0]);
|
|
2346
|
-
} else {
|
|
2347
|
-
void handleEnter(ids);
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
}));
|
|
533
|
+
} else {
|
|
534
|
+
suppressNextBlur.current = true;
|
|
535
|
+
setValidationError(null);
|
|
536
|
+
setEditing(null);
|
|
537
|
+
onSave?.();
|
|
538
|
+
if (event && onFocus) {
|
|
539
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2352
540
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
} else {
|
|
2372
|
-
void handleEnter(data);
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
})
|
|
2377
|
-
]);
|
|
2378
|
-
break;
|
|
2379
|
-
}
|
|
541
|
+
}
|
|
542
|
+
}, [
|
|
543
|
+
model,
|
|
544
|
+
editing,
|
|
545
|
+
onFocus,
|
|
546
|
+
fieldProjection,
|
|
547
|
+
setEditing,
|
|
548
|
+
onSave
|
|
549
|
+
]);
|
|
550
|
+
const extensions = useMemo2(() => {
|
|
551
|
+
if (!fieldProjection) {
|
|
552
|
+
return [];
|
|
553
|
+
}
|
|
554
|
+
const extensions2 = [
|
|
555
|
+
editorKeys({
|
|
556
|
+
onClose: handleClose,
|
|
557
|
+
...editing?.initialContent && {
|
|
558
|
+
onNav: handleClose
|
|
2380
559
|
}
|
|
2381
|
-
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
editing,
|
|
2387
|
-
fieldProjection,
|
|
2388
|
-
handleClose,
|
|
2389
|
-
themeMode
|
|
2390
|
-
]);
|
|
2391
|
-
const getCellContent = useCallback4(() => {
|
|
2392
|
-
if (model && editing) {
|
|
560
|
+
})
|
|
561
|
+
];
|
|
562
|
+
if (model && editing) {
|
|
563
|
+
extensions2.push(EditorView.updateListener.of(debounce((update) => {
|
|
564
|
+
const content = update.state.doc.toString();
|
|
2393
565
|
const cell = parseCellIndex2(editing.index);
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
const options = fieldProjection2.props.options || [];
|
|
2401
|
-
if (fieldProjection2.props.format === FormatEnum5.MultiSelect) {
|
|
2402
|
-
const tagItems = value2.split(",").map((id) => {
|
|
2403
|
-
const option = options.find((o) => o.id === id);
|
|
2404
|
-
if (option) {
|
|
2405
|
-
return {
|
|
2406
|
-
id,
|
|
2407
|
-
label: option.title,
|
|
2408
|
-
hue: option.color
|
|
2409
|
-
};
|
|
2410
|
-
}
|
|
2411
|
-
return void 0;
|
|
2412
|
-
}).filter((item) => item !== void 0);
|
|
2413
|
-
return createLinks(tagItems);
|
|
2414
|
-
} else {
|
|
2415
|
-
const option = options.find((o) => o.id === value2);
|
|
2416
|
-
if (option) {
|
|
2417
|
-
const tagItem = {
|
|
2418
|
-
id: value2,
|
|
2419
|
-
label: option.title,
|
|
2420
|
-
hue: option.color
|
|
2421
|
-
};
|
|
2422
|
-
return createLinks([
|
|
2423
|
-
tagItem
|
|
2424
|
-
]);
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
566
|
+
void model.validateCellData(cell, content).then((result) => {
|
|
567
|
+
if (result.valid) {
|
|
568
|
+
setValidationError(null);
|
|
569
|
+
} else {
|
|
570
|
+
setValidationError(result.error);
|
|
571
|
+
setValidationVariant("error");
|
|
2427
572
|
}
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
573
|
+
});
|
|
574
|
+
}, 10)));
|
|
575
|
+
}
|
|
576
|
+
return extensions2;
|
|
577
|
+
}, [
|
|
578
|
+
model,
|
|
579
|
+
modals,
|
|
580
|
+
editing,
|
|
581
|
+
fieldProjection,
|
|
582
|
+
handleClose
|
|
583
|
+
]);
|
|
584
|
+
const getCellContent = useCallback2(() => {
|
|
585
|
+
if (model && editing) {
|
|
586
|
+
const cell = parseCellIndex2(editing.index);
|
|
587
|
+
const value = model.getCellData(cell);
|
|
588
|
+
return value !== void 0 ? String(value) : "";
|
|
589
|
+
}
|
|
590
|
+
}, [
|
|
591
|
+
model,
|
|
592
|
+
editing
|
|
593
|
+
]);
|
|
594
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
|
|
595
|
+
validationError,
|
|
596
|
+
variant: validationVariant,
|
|
597
|
+
__gridScope
|
|
598
|
+
}), /* @__PURE__ */ React3.createElement(GridCellEditor, {
|
|
599
|
+
extensions,
|
|
600
|
+
slots: {
|
|
601
|
+
content: {
|
|
602
|
+
className: "!py-(--dx-grid-cell-editor-padding-block)"
|
|
2432
603
|
}
|
|
2433
|
-
},
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(CellValidationMessage, {
|
|
2438
|
-
validationError: _validationError,
|
|
2439
|
-
variant: _validationVariant,
|
|
2440
|
-
__gridScope
|
|
2441
|
-
}), /* @__PURE__ */ React7.createElement(GridCellEditor, {
|
|
2442
|
-
extension,
|
|
2443
|
-
getCellContent,
|
|
2444
|
-
onBlur: handleBlur,
|
|
2445
|
-
slots: editorSlots
|
|
2446
|
-
}));
|
|
2447
|
-
} finally {
|
|
2448
|
-
_effect.f();
|
|
2449
|
-
}
|
|
604
|
+
},
|
|
605
|
+
getCellContent,
|
|
606
|
+
onBlur: handleBlur
|
|
607
|
+
}));
|
|
2450
608
|
};
|
|
2451
609
|
var determineNavigationAxis = ({ key }) => {
|
|
2452
610
|
switch (key) {
|
|
@@ -2461,554 +619,573 @@ var determineNavigationAxis = ({ key }) => {
|
|
|
2461
619
|
return "col";
|
|
2462
620
|
}
|
|
2463
621
|
};
|
|
2464
|
-
var determineNavigationDelta = ({ key, shift }) => {
|
|
2465
|
-
switch (key) {
|
|
2466
|
-
case "ArrowUp":
|
|
2467
|
-
case "ArrowLeft":
|
|
2468
|
-
return -1;
|
|
2469
|
-
case "ArrowDown":
|
|
2470
|
-
case "ArrowRight":
|
|
2471
|
-
return 1;
|
|
622
|
+
var determineNavigationDelta = ({ key, shift }) => {
|
|
623
|
+
switch (key) {
|
|
624
|
+
case "ArrowUp":
|
|
625
|
+
case "ArrowLeft":
|
|
626
|
+
return -1;
|
|
627
|
+
case "ArrowDown":
|
|
628
|
+
case "ArrowRight":
|
|
629
|
+
return 1;
|
|
630
|
+
}
|
|
631
|
+
return shift ? -1 : 1;
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/components/Table/ColumnActionsMenu.tsx
|
|
635
|
+
import { useAtomValue } from "@effect-atom/atom-react";
|
|
636
|
+
import React4 from "react";
|
|
637
|
+
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
638
|
+
import { translationKey as translationKey2 } from "#translations";
|
|
639
|
+
var ColumnActionsMenu = ({ model, modals }) => {
|
|
640
|
+
const { t } = useTranslation(translationKey2);
|
|
641
|
+
const state = useAtomValue(modals.state);
|
|
642
|
+
if (state?.type !== "column") {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
const currentSort = model.getSorting();
|
|
646
|
+
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
647
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
648
|
+
modal: false,
|
|
649
|
+
open: true,
|
|
650
|
+
onOpenChange: modals.close
|
|
651
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
|
|
652
|
+
virtualRef: modals.trigger
|
|
653
|
+
}), /* @__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, {
|
|
654
|
+
"data-testid": "column-sort-descending",
|
|
655
|
+
onClick: () => model.setSort(state.fieldId, "desc")
|
|
656
|
+
}, t("column-action-sort-descending.menu")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
657
|
+
"data-testid": "column-sort-ascending",
|
|
658
|
+
onClick: () => model.setSort(state.fieldId, "asc")
|
|
659
|
+
}, t("column-action-sort-ascending.menu")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
660
|
+
"data-testid": "column-clear-sort",
|
|
661
|
+
onClick: () => model.clearSort()
|
|
662
|
+
}, t("column-action-clear-sorting.menu")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
663
|
+
"data-testid": "column-delete",
|
|
664
|
+
onClick: () => model.deleteColumn(state.fieldId)
|
|
665
|
+
}, t("column-action-delete.menu")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
666
|
+
"data-testid": "column-settings",
|
|
667
|
+
onClick: () => modals.openColumnSettings()
|
|
668
|
+
}, t("column-action-settings.menu"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// src/components/Table/ColumnSettings.tsx
|
|
672
|
+
import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
|
|
673
|
+
import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
674
|
+
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
675
|
+
import { FieldEditor } from "@dxos/react-ui-form";
|
|
676
|
+
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
677
|
+
const [newField, setNewField] = useState3();
|
|
678
|
+
const state = useAtomValue2(modals.state);
|
|
679
|
+
useEffect2(() => {
|
|
680
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
681
|
+
setNewField(model.projection.createFieldProjection());
|
|
682
|
+
requestAnimationFrame(() => {
|
|
683
|
+
onNewColumn();
|
|
684
|
+
});
|
|
685
|
+
} else {
|
|
686
|
+
setNewField(void 0);
|
|
687
|
+
}
|
|
688
|
+
}, [
|
|
689
|
+
model?.projection,
|
|
690
|
+
state
|
|
691
|
+
]);
|
|
692
|
+
const existingField = useMemo3(() => {
|
|
693
|
+
if (state?.type === "columnSettings") {
|
|
694
|
+
const { mode } = state;
|
|
695
|
+
if (mode.type === "edit") {
|
|
696
|
+
return model?.projection?.getFields().find((f) => f.id === mode.fieldId);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return void 0;
|
|
700
|
+
}, [
|
|
701
|
+
model?.projection,
|
|
702
|
+
state
|
|
703
|
+
]);
|
|
704
|
+
const field = existingField ?? newField;
|
|
705
|
+
const handleSave = useCallback3(() => {
|
|
706
|
+
modals.close();
|
|
707
|
+
}, [
|
|
708
|
+
modals
|
|
709
|
+
]);
|
|
710
|
+
const handleCancel = useCallback3(() => {
|
|
711
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
712
|
+
model?.projection.deleteFieldProjection(newField.id);
|
|
713
|
+
}
|
|
714
|
+
}, [
|
|
715
|
+
model?.projection,
|
|
716
|
+
state,
|
|
717
|
+
newField
|
|
718
|
+
]);
|
|
719
|
+
if (!model?.projection || !field) {
|
|
720
|
+
return null;
|
|
721
|
+
}
|
|
722
|
+
return /* @__PURE__ */ React5.createElement(Popover2.Root, {
|
|
723
|
+
modal: false,
|
|
724
|
+
open: state?.type === "columnSettings"
|
|
725
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
|
|
726
|
+
virtualRef: modals.trigger
|
|
727
|
+
}), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
|
|
728
|
+
classNames: "md:w-64"
|
|
729
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
|
|
730
|
+
projection: model.projection,
|
|
731
|
+
field,
|
|
732
|
+
registry,
|
|
733
|
+
onSave: handleSave,
|
|
734
|
+
onCancel: handleCancel
|
|
735
|
+
})), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
// src/components/Table/RowActionsMenu.tsx
|
|
739
|
+
import { useAtomValue as useAtomValue3 } from "@effect-atom/atom-react";
|
|
740
|
+
import React6 from "react";
|
|
741
|
+
import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
742
|
+
import { translationKey as translationKey3 } from "#translations";
|
|
743
|
+
var RowActionsMenu = ({ model, modals }) => {
|
|
744
|
+
const { t } = useTranslation2(translationKey3);
|
|
745
|
+
const hasSelection = model.selection.hasSelection;
|
|
746
|
+
const state = useAtomValue3(modals.state);
|
|
747
|
+
if (state?.type !== "row") {
|
|
748
|
+
return null;
|
|
749
|
+
}
|
|
750
|
+
return /* @__PURE__ */ React6.createElement(DropdownMenu2.Root, {
|
|
751
|
+
modal: false,
|
|
752
|
+
open: true,
|
|
753
|
+
onOpenChange: modals.close
|
|
754
|
+
}, /* @__PURE__ */ React6.createElement(DropdownMenu2.VirtualTrigger, {
|
|
755
|
+
virtualRef: modals.trigger
|
|
756
|
+
}), /* @__PURE__ */ React6.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React6.createElement(DropdownMenu2.Viewport, null, model.rowActions?.length > 0 && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(DropdownMenu2.Group, null, model.rowActions?.map((action) => /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
|
|
757
|
+
key: action.id,
|
|
758
|
+
"data-testid": `row-action-${action.id}`,
|
|
759
|
+
onClick: () => {
|
|
760
|
+
modals.close();
|
|
761
|
+
model.handleRowAction(action.id, state.rowIndex);
|
|
762
|
+
}
|
|
763
|
+
}, toLocalizedString(action.label, t)))), /* @__PURE__ */ React6.createElement(DropdownMenu2.Separator, null)), model.features.dataEditable !== false && /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
|
|
764
|
+
"data-testid": "row-menu-delete",
|
|
765
|
+
onClick: () => model.deleteRow(state.rowIndex)
|
|
766
|
+
}, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React6.createElement(DropdownMenu2.Arrow, null)));
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
// src/components/Table/TableContent.tsx
|
|
770
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/Table/TableContent.tsx";
|
|
771
|
+
var columnDefault = {
|
|
772
|
+
grid: {
|
|
773
|
+
minSize: 80,
|
|
774
|
+
maxSize: 640
|
|
2472
775
|
}
|
|
2473
|
-
return shift ? -1 : 1;
|
|
2474
776
|
};
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
var _effect = _useSignals8();
|
|
2480
|
-
try {
|
|
2481
|
-
return /* @__PURE__ */ React8.createElement("div", {
|
|
2482
|
-
role: "none",
|
|
2483
|
-
className: mx2("relative !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
|
|
2484
|
-
}, children);
|
|
2485
|
-
} finally {
|
|
2486
|
-
_effect.f();
|
|
777
|
+
var rowDefault = {
|
|
778
|
+
frozenRowsStart: {
|
|
779
|
+
readonly: true,
|
|
780
|
+
focusUnfurl: false
|
|
2487
781
|
}
|
|
2488
782
|
};
|
|
2489
|
-
var
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
783
|
+
var emptyColumnMeta = Atom2.make({
|
|
784
|
+
grid: {}
|
|
785
|
+
});
|
|
786
|
+
var emptyRowsAtom = Atom2.make([]);
|
|
787
|
+
var emptyCellUpdateAtom = Atom2.make(0);
|
|
788
|
+
var TABLE_CONTENT_NAME = "Table.Content";
|
|
789
|
+
var TableContent = composable(({ schema, model, presentation, ignoreAttention, onCreate, onRowClick, testId, ...props }, forwardedRef) => {
|
|
790
|
+
const registry = useContext(RegistryContext);
|
|
791
|
+
const [dxGrid, setDxGrid] = useState4(null);
|
|
792
|
+
const { hasAttention } = useAttention(model?.id ?? "table");
|
|
793
|
+
const modals = useMemo4(() => new ModalController(registry), [
|
|
794
|
+
registry
|
|
795
|
+
]);
|
|
796
|
+
const columnMeta = useAtomValue4(model?.columnMeta ?? emptyColumnMeta);
|
|
797
|
+
const rows = useAtomValue4(model?.rows ?? emptyRowsAtom);
|
|
798
|
+
const cellUpdateCounter = useAtomValue4(model?.cellUpdate ?? emptyCellUpdateAtom);
|
|
799
|
+
const columnCount = Object.keys(columnMeta.grid).length || model?.projection.getFields().length || 0;
|
|
800
|
+
const draftRowCount = model?.getDraftRowCount() ?? 0;
|
|
801
|
+
const frozen = useMemo4(() => {
|
|
802
|
+
const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
|
|
803
|
+
return {
|
|
804
|
+
frozenRowsStart: 1,
|
|
805
|
+
frozenRowsEnd: Math.max(1, draftRowCount),
|
|
806
|
+
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
807
|
+
frozenColsEnd: noActionColumn ? 0 : 1
|
|
808
|
+
};
|
|
809
|
+
}, [
|
|
810
|
+
model,
|
|
811
|
+
draftRowCount
|
|
812
|
+
]);
|
|
813
|
+
const getCells = useCallback4((range, plane) => presentation?.getCells(range, plane) ?? {}, [
|
|
814
|
+
presentation
|
|
815
|
+
]);
|
|
816
|
+
useEffect3(() => {
|
|
817
|
+
if (!dxGrid || !presentation) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
dxGrid.getCells = getCells;
|
|
821
|
+
}, [
|
|
822
|
+
dxGrid,
|
|
823
|
+
presentation,
|
|
824
|
+
getCells
|
|
825
|
+
]);
|
|
826
|
+
useEffect3(() => {
|
|
827
|
+
if (!dxGrid) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
dxGrid.updateCells(true);
|
|
831
|
+
dxGrid.requestUpdate();
|
|
832
|
+
}, [
|
|
833
|
+
dxGrid,
|
|
834
|
+
rows,
|
|
835
|
+
cellUpdateCounter
|
|
836
|
+
]);
|
|
837
|
+
const handleInsertRowResult = useCallback4((insertResult) => {
|
|
838
|
+
if (insertResult === "draft") {
|
|
839
|
+
requestAnimationFrame(() => {
|
|
840
|
+
dxGrid?.setFocus({
|
|
841
|
+
plane: "frozenRowsEnd",
|
|
842
|
+
col: 0,
|
|
843
|
+
row: 0
|
|
844
|
+
});
|
|
845
|
+
dxGrid?.refocus();
|
|
846
|
+
});
|
|
847
|
+
} else {
|
|
848
|
+
requestAnimationFrame(() => {
|
|
849
|
+
dxGrid?.setFocus({
|
|
850
|
+
plane: "grid",
|
|
851
|
+
col: 0,
|
|
852
|
+
row: model ? model.getRowCount() - 1 : 0
|
|
853
|
+
});
|
|
854
|
+
dxGrid?.refocus();
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
}, [
|
|
858
|
+
model,
|
|
859
|
+
dxGrid
|
|
860
|
+
]);
|
|
861
|
+
const handleSave = useCallback4(() => {
|
|
862
|
+
dxGrid?.updateCells(true);
|
|
863
|
+
dxGrid?.requestUpdate();
|
|
864
|
+
}, [
|
|
865
|
+
dxGrid
|
|
866
|
+
]);
|
|
867
|
+
const handleSaveDraftRow = useCallback4((rowIndex = 0) => {
|
|
868
|
+
if (model && dxGrid) {
|
|
869
|
+
const didCommitSuccessfully = model.commitDraftRow(rowIndex);
|
|
870
|
+
if (didCommitSuccessfully) {
|
|
871
|
+
requestAnimationFrame(() => {
|
|
872
|
+
dxGrid.scrollToEndRow();
|
|
873
|
+
});
|
|
2525
874
|
}
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
presentation,
|
|
2538
|
-
dxGrid
|
|
2539
|
-
]);
|
|
2540
|
-
const handleGridClick = useCallback5((event) => {
|
|
2541
|
-
const rowIndex = safeParseInt(event.target.ariaRowIndex ?? "");
|
|
2542
|
-
if (rowIndex != null) {
|
|
2543
|
-
if (onRowClick) {
|
|
875
|
+
}
|
|
876
|
+
}, [
|
|
877
|
+
model,
|
|
878
|
+
dxGrid
|
|
879
|
+
]);
|
|
880
|
+
const handleGridClick = useCallback4((event) => {
|
|
881
|
+
const cell = closestCell(event.target);
|
|
882
|
+
if (cell) {
|
|
883
|
+
const { row: rowIndex, plane } = cell;
|
|
884
|
+
if (onRowClick) {
|
|
885
|
+
if (plane === "grid") {
|
|
2544
886
|
const row = model?.getRowAt(rowIndex);
|
|
2545
887
|
row && onRowClick(row);
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
model.selection.toggleSelectionForRowIndex(rowIndex);
|
|
888
|
+
} else {
|
|
889
|
+
onRowClick(cell);
|
|
2549
890
|
}
|
|
2550
891
|
}
|
|
2551
|
-
if (
|
|
892
|
+
if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
|
|
893
|
+
model.selection.toggleSelectionForRowIndex(rowIndex);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (!modals) {
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
|
|
900
|
+
const tableButtonElement = event.target.closest(buttonSelector);
|
|
901
|
+
if (tableButtonElement) {
|
|
902
|
+
const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
|
|
903
|
+
if (!button) {
|
|
2552
904
|
return;
|
|
2553
905
|
}
|
|
2554
|
-
|
|
2555
|
-
const
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
906
|
+
modals.setTrigger(tableButtonElement);
|
|
907
|
+
const data = button.getData(tableButtonElement);
|
|
908
|
+
switch (data.type) {
|
|
909
|
+
case "rowMenu": {
|
|
910
|
+
modals.showRowMenu(data.rowIndex);
|
|
911
|
+
break;
|
|
2560
912
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
case "rowMenu": {
|
|
2565
|
-
modals.showRowMenu(data.rowIndex);
|
|
2566
|
-
break;
|
|
2567
|
-
}
|
|
2568
|
-
case "columnSettings": {
|
|
2569
|
-
modals.showColumnMenu(data.fieldId);
|
|
2570
|
-
break;
|
|
2571
|
-
}
|
|
2572
|
-
case "newColumn": {
|
|
2573
|
-
modals.showColumnCreator();
|
|
2574
|
-
break;
|
|
2575
|
-
}
|
|
2576
|
-
case "sort": {
|
|
2577
|
-
model?.sorting?.toggleSort(data.fieldId);
|
|
2578
|
-
break;
|
|
2579
|
-
}
|
|
2580
|
-
case "saveDraftRow": {
|
|
2581
|
-
if (model) {
|
|
2582
|
-
const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
|
|
2583
|
-
if (dxGrid && didCommitSuccessfully) {
|
|
2584
|
-
requestAnimationFrame(() => {
|
|
2585
|
-
dxGrid.scrollToEndRow();
|
|
2586
|
-
});
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
break;
|
|
2590
|
-
}
|
|
913
|
+
case "columnSettings": {
|
|
914
|
+
modals.showColumnMenu(data.fieldId);
|
|
915
|
+
break;
|
|
2591
916
|
}
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
const controlElement = event.target.closest(controlSelector);
|
|
2596
|
-
if (controlElement) {
|
|
2597
|
-
const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
|
|
2598
|
-
if (!control) {
|
|
2599
|
-
return;
|
|
917
|
+
case "newColumn": {
|
|
918
|
+
modals.showColumnCreator();
|
|
919
|
+
break;
|
|
2600
920
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
if (data.header) {
|
|
2605
|
-
model?.selection.setSelection(model.selection.allRowsSeleted.value ? "none" : "all");
|
|
2606
|
-
} else {
|
|
2607
|
-
model?.selection.toggleSelectionForRowIndex(data.rowIndex);
|
|
2608
|
-
}
|
|
2609
|
-
break;
|
|
2610
|
-
}
|
|
2611
|
-
case "switch": {
|
|
2612
|
-
if (model) {
|
|
2613
|
-
model.updateCellData({
|
|
2614
|
-
row: data.rowIndex,
|
|
2615
|
-
col: data.colIndex
|
|
2616
|
-
}, (value) => !value);
|
|
2617
|
-
}
|
|
2618
|
-
break;
|
|
2619
|
-
}
|
|
921
|
+
case "sort": {
|
|
922
|
+
model?.toggleSort(data.fieldId);
|
|
923
|
+
break;
|
|
2620
924
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
modals,
|
|
2625
|
-
dxGrid
|
|
2626
|
-
]);
|
|
2627
|
-
const handleFocus = useCallback5((increment, delta) => {
|
|
2628
|
-
if (dxGrid) {
|
|
2629
|
-
dxGrid.refocus(increment, delta);
|
|
2630
|
-
}
|
|
2631
|
-
}, [
|
|
2632
|
-
dxGrid
|
|
2633
|
-
]);
|
|
2634
|
-
const handleEnter = useCallback5((cell) => {
|
|
2635
|
-
if (!model?.features.dataEditable) {
|
|
2636
|
-
return;
|
|
2637
|
-
}
|
|
2638
|
-
if (model && cell.row === model.getRowCount() - 1) {
|
|
2639
|
-
model.insertRow();
|
|
2640
|
-
if (dxGrid) {
|
|
2641
|
-
requestAnimationFrame(() => {
|
|
2642
|
-
dxGrid?.scrollToRow(cell.row + 1);
|
|
2643
|
-
dxGrid?.refocus("row", 1);
|
|
2644
|
-
});
|
|
925
|
+
case "saveDraftRow": {
|
|
926
|
+
handleSaveDraftRow();
|
|
927
|
+
break;
|
|
2645
928
|
}
|
|
2646
929
|
}
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
}
|
|
2655
|
-
const cell = closestCell(event.target);
|
|
2656
|
-
if (!model || !cell) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
|
|
933
|
+
const controlElement = event.target.closest(controlSelector);
|
|
934
|
+
if (controlElement) {
|
|
935
|
+
const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
|
|
936
|
+
if (!control) {
|
|
2657
937
|
return;
|
|
2658
938
|
}
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
case "
|
|
2662
|
-
|
|
939
|
+
const data = control.getData(controlElement);
|
|
940
|
+
switch (data.type) {
|
|
941
|
+
case "checkbox": {
|
|
942
|
+
if (data.header) {
|
|
943
|
+
model?.selection.setSelection(model.selection.allRowsSelected ? "none" : "all");
|
|
944
|
+
} else {
|
|
945
|
+
model?.selection.toggleSelectionForRowIndex(data.rowIndex);
|
|
946
|
+
}
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
949
|
+
case "switch": {
|
|
950
|
+
if (model) {
|
|
951
|
+
model.updateCellData({
|
|
952
|
+
row: data.rowIndex,
|
|
953
|
+
col: data.colIndex
|
|
954
|
+
}, (value) => !value);
|
|
955
|
+
}
|
|
2663
956
|
break;
|
|
2664
957
|
}
|
|
2665
958
|
}
|
|
2666
|
-
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
}, [
|
|
2682
|
-
hasAttention,
|
|
2683
|
-
ignoreAttention
|
|
2684
|
-
]);
|
|
2685
|
-
const handleNewColumn = useCallback5(() => {
|
|
2686
|
-
const columns = model?.getColumnCount();
|
|
2687
|
-
if (dxGrid && columns) {
|
|
2688
|
-
dxGrid.scrollToColumn(columns - 1);
|
|
959
|
+
}
|
|
960
|
+
}, [
|
|
961
|
+
model,
|
|
962
|
+
modals,
|
|
963
|
+
dxGrid
|
|
964
|
+
]);
|
|
965
|
+
const handleFocus = useCallback4((increment, delta, cell) => {
|
|
966
|
+
if (dxGrid && model) {
|
|
967
|
+
if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1 && increment !== "col") {
|
|
968
|
+
handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
|
|
969
|
+
} else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
|
|
970
|
+
handleSaveDraftRow(cell.row);
|
|
971
|
+
handleInsertRowResult(model.insertRow());
|
|
972
|
+
} else {
|
|
973
|
+
dxGrid.refocus(increment, delta);
|
|
2689
974
|
}
|
|
2690
|
-
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
975
|
+
}
|
|
976
|
+
}, [
|
|
977
|
+
dxGrid,
|
|
978
|
+
model
|
|
979
|
+
]);
|
|
980
|
+
const handleKeyDown = useCallback4((event) => {
|
|
981
|
+
if (!model?.features.dataEditable) {
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
const cell = closestCell(event.target);
|
|
985
|
+
if (!model || !cell) {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (event.metaKey || event.ctrlKey) {
|
|
989
|
+
switch (event.key) {
|
|
990
|
+
case "c": {
|
|
991
|
+
try {
|
|
992
|
+
const cellData = model.getCellData(cell);
|
|
993
|
+
const textContent = cellData?.toString() ?? "";
|
|
994
|
+
void navigator.clipboard.writeText(textContent);
|
|
995
|
+
event.preventDefault();
|
|
996
|
+
} catch (error) {
|
|
997
|
+
log.catch(error, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 262, S: void 0 });
|
|
998
|
+
}
|
|
999
|
+
break;
|
|
2712
1000
|
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
1001
|
+
case "v": {
|
|
1002
|
+
event.preventDefault();
|
|
1003
|
+
void navigator.clipboard.readText().then((clipboardText) => {
|
|
1004
|
+
try {
|
|
1005
|
+
model.setCellData(cell, String2.trim(clipboardText).replace(/[\n\r]+/, " "));
|
|
1006
|
+
handleSave();
|
|
1007
|
+
} catch {
|
|
1008
|
+
const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
|
|
1009
|
+
if (cellElement) {
|
|
1010
|
+
const rect = cellElement.getBoundingClientRect();
|
|
1011
|
+
const editRequest = new DxEditRequest({
|
|
1012
|
+
cellIndex: `${cell.plane},${cell.col},${cell.row}`,
|
|
1013
|
+
cellBox: {
|
|
1014
|
+
insetInlineStart: rect.left,
|
|
1015
|
+
insetBlockStart: rect.top,
|
|
1016
|
+
inlineSize: rect.width,
|
|
1017
|
+
blockSize: rect.height
|
|
1018
|
+
},
|
|
1019
|
+
cellElement,
|
|
1020
|
+
initialContent: clipboardText
|
|
1021
|
+
});
|
|
1022
|
+
cellElement.dispatchEvent(editRequest);
|
|
1023
|
+
}
|
|
2732
1024
|
}
|
|
2733
|
-
|
|
1025
|
+
});
|
|
1026
|
+
break;
|
|
2734
1027
|
}
|
|
2735
1028
|
}
|
|
2736
|
-
return [];
|
|
2737
|
-
}, [
|
|
2738
|
-
model,
|
|
2739
|
-
client,
|
|
2740
|
-
t
|
|
2741
|
-
]);
|
|
2742
|
-
if (!model || !modals) {
|
|
2743
|
-
return /* @__PURE__ */ React8.createElement("span", {
|
|
2744
|
-
role: "none",
|
|
2745
|
-
className: "attention-surface"
|
|
2746
|
-
});
|
|
2747
1029
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
className: mx2("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
2759
|
-
frozen,
|
|
2760
|
-
columns: model.columnMeta.value,
|
|
2761
|
-
limitRows: model.getRowCount() ?? 0,
|
|
2762
|
-
limitColumns: model.view?.fields?.length ?? 0,
|
|
2763
|
-
overscroll: "trap",
|
|
2764
|
-
onAxisResize: handleAxisResize,
|
|
2765
|
-
onClick: handleGridClick,
|
|
2766
|
-
onKeyDown: handleKeyDown,
|
|
2767
|
-
onWheelCapture: handleWheel,
|
|
2768
|
-
ref: setDxGrid
|
|
2769
|
-
}), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
|
|
2770
|
-
model,
|
|
2771
|
-
modals
|
|
2772
|
-
}), /* @__PURE__ */ React8.createElement(ColumnActionsMenu, {
|
|
2773
|
-
model,
|
|
2774
|
-
modals
|
|
2775
|
-
}), /* @__PURE__ */ React8.createElement(ColumnSettings, {
|
|
2776
|
-
model,
|
|
2777
|
-
modals,
|
|
2778
|
-
onNewColumn: handleNewColumn
|
|
2779
|
-
}), /* @__PURE__ */ React8.createElement(CreateRefPanel, {
|
|
2780
|
-
model,
|
|
2781
|
-
modals
|
|
2782
|
-
}));
|
|
2783
|
-
} finally {
|
|
2784
|
-
_effect.f();
|
|
2785
|
-
}
|
|
2786
|
-
});
|
|
2787
|
-
var Table = {
|
|
2788
|
-
Root: TableRoot,
|
|
2789
|
-
Main: TableMain
|
|
2790
|
-
};
|
|
2791
|
-
|
|
2792
|
-
// src/components/Table/DynamicTable.tsx
|
|
2793
|
-
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2794
|
-
import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback7 } from "react";
|
|
2795
|
-
import { useDefaultValue } from "@dxos/react-ui";
|
|
2796
|
-
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
2797
|
-
|
|
2798
|
-
// src/hooks/useTableModel.ts
|
|
2799
|
-
import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
|
|
2800
|
-
import { effect as effect3 } from "@preact/signals-core";
|
|
2801
|
-
import orderBy2 from "lodash.orderby";
|
|
2802
|
-
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
2803
|
-
import { fullyQualifiedId, getSpace } from "@dxos/react-client/echo";
|
|
2804
|
-
import { useSelectionActions } from "@dxos/react-ui-attention";
|
|
2805
|
-
import { isNonNullable } from "@dxos/util";
|
|
2806
|
-
var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
|
|
2807
|
-
var _effect = _useSignals9();
|
|
2808
|
-
try {
|
|
2809
|
-
const [model, setModel] = useState4();
|
|
2810
|
-
useEffect5(() => {
|
|
2811
|
-
if (!table || !projection) {
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
|
-
let model2;
|
|
2815
|
-
const t = setTimeout(async () => {
|
|
2816
|
-
model2 = new TableModel({
|
|
2817
|
-
id: fullyQualifiedId(table),
|
|
2818
|
-
space: getSpace(table),
|
|
2819
|
-
view: table.view?.target,
|
|
2820
|
-
projection,
|
|
2821
|
-
features,
|
|
2822
|
-
rowActions,
|
|
2823
|
-
onRowAction,
|
|
2824
|
-
...props
|
|
2825
|
-
});
|
|
2826
|
-
await model2.open();
|
|
2827
|
-
setModel(model2);
|
|
2828
|
-
});
|
|
2829
|
-
return () => {
|
|
2830
|
-
clearTimeout(t);
|
|
2831
|
-
void model2?.close();
|
|
2832
|
-
};
|
|
2833
|
-
}, [
|
|
2834
|
-
table,
|
|
2835
|
-
projection,
|
|
2836
|
-
table?.view?.target,
|
|
2837
|
-
features,
|
|
2838
|
-
rowActions
|
|
2839
|
-
]);
|
|
2840
|
-
useEffect5(() => {
|
|
2841
|
-
if (rows) {
|
|
2842
|
-
const sortedRows = orderBy2(rows, [
|
|
2843
|
-
(row) => String(row.id)
|
|
2844
|
-
], [
|
|
2845
|
-
"asc"
|
|
2846
|
-
]);
|
|
2847
|
-
model?.setRows(sortedRows);
|
|
2848
|
-
}
|
|
2849
|
-
}, [
|
|
2850
|
-
model,
|
|
2851
|
-
rows
|
|
2852
|
-
]);
|
|
2853
|
-
const { multiSelect, clear } = useSelectionActions([
|
|
2854
|
-
table?.id,
|
|
2855
|
-
table?.view?.target?.query.typename
|
|
2856
|
-
].filter(isNonNullable));
|
|
2857
|
-
useEffect5(() => {
|
|
2858
|
-
if (!model) {
|
|
2859
|
-
return;
|
|
2860
|
-
}
|
|
2861
|
-
const unsubscribe = effect3(() => {
|
|
2862
|
-
const selectedItems = [
|
|
2863
|
-
...model.selection.selection.value
|
|
2864
|
-
];
|
|
2865
|
-
multiSelect(selectedItems);
|
|
2866
|
-
onSelectionChanged?.(selectedItems);
|
|
2867
|
-
});
|
|
2868
|
-
return () => {
|
|
2869
|
-
clear();
|
|
2870
|
-
unsubscribe();
|
|
2871
|
-
};
|
|
2872
|
-
}, [
|
|
2873
|
-
model,
|
|
2874
|
-
onSelectionChanged
|
|
2875
|
-
]);
|
|
2876
|
-
return model;
|
|
2877
|
-
} finally {
|
|
2878
|
-
_effect.f();
|
|
2879
|
-
}
|
|
2880
|
-
};
|
|
2881
|
-
|
|
2882
|
-
// src/hooks/useAddRow.ts
|
|
2883
|
-
import { useCallback as useCallback6 } from "react";
|
|
2884
|
-
import { Obj as Obj3 } from "@dxos/echo";
|
|
2885
|
-
var useAddRow = ({ space, schema }) => {
|
|
2886
|
-
return useCallback6((data) => {
|
|
2887
|
-
if (space && schema) {
|
|
2888
|
-
try {
|
|
2889
|
-
space.db.add(Obj3.make(schema, data ?? {}));
|
|
2890
|
-
return true;
|
|
2891
|
-
} catch (error) {
|
|
2892
|
-
return false;
|
|
1030
|
+
switch (event.key) {
|
|
1031
|
+
case "Backspace":
|
|
1032
|
+
case "Delete": {
|
|
1033
|
+
try {
|
|
1034
|
+
model.setCellData(cell, void 0);
|
|
1035
|
+
event.preventDefault();
|
|
1036
|
+
handleSave();
|
|
1037
|
+
} catch {
|
|
1038
|
+
}
|
|
1039
|
+
break;
|
|
2893
1040
|
}
|
|
2894
1041
|
}
|
|
2895
|
-
return false;
|
|
2896
1042
|
}, [
|
|
2897
|
-
|
|
2898
|
-
|
|
1043
|
+
model,
|
|
1044
|
+
dxGrid,
|
|
1045
|
+
handleSave
|
|
2899
1046
|
]);
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
}
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
1047
|
+
const handleAxisResize = useCallback4((event) => {
|
|
1048
|
+
if (event.axis === "col") {
|
|
1049
|
+
const columnIndex = parseInt(event.index, 10);
|
|
1050
|
+
model?.setColumnWidth(columnIndex, event.size);
|
|
1051
|
+
}
|
|
1052
|
+
}, [
|
|
1053
|
+
model
|
|
1054
|
+
]);
|
|
1055
|
+
const handleWheel = useCallback4((event) => {
|
|
1056
|
+
if (!ignoreAttention && !hasAttention) {
|
|
1057
|
+
event.stopPropagation();
|
|
1058
|
+
}
|
|
1059
|
+
}, [
|
|
1060
|
+
hasAttention,
|
|
1061
|
+
ignoreAttention
|
|
1062
|
+
]);
|
|
1063
|
+
const handleNewColumn = useCallback4(() => {
|
|
1064
|
+
const columns = model?.getColumnCount();
|
|
1065
|
+
if (dxGrid && columns) {
|
|
1066
|
+
dxGrid.scrollToColumn(columns - 1);
|
|
1067
|
+
}
|
|
1068
|
+
}, [
|
|
1069
|
+
model,
|
|
1070
|
+
dxGrid
|
|
1071
|
+
]);
|
|
1072
|
+
const { controllerRef } = useTableContext(TABLE_CONTENT_NAME);
|
|
1073
|
+
controllerRef.current = useMemo4(() => {
|
|
1074
|
+
if (!dxGrid || !presentation) {
|
|
1075
|
+
return {};
|
|
1076
|
+
}
|
|
1077
|
+
return {
|
|
1078
|
+
update: (cell) => {
|
|
1079
|
+
if (cell) {
|
|
1080
|
+
dxGrid.updateIfWithinBounds(cell, true);
|
|
1081
|
+
} else {
|
|
1082
|
+
dxGrid.updateCells(true);
|
|
1083
|
+
dxGrid.requestUpdate();
|
|
1084
|
+
}
|
|
2933
1085
|
},
|
|
2934
|
-
|
|
2935
|
-
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
onRowOrderChange: handleRowOrderChange,
|
|
2944
|
-
onRowAction
|
|
2945
|
-
});
|
|
2946
|
-
const presentation = useMemo6(() => {
|
|
2947
|
-
if (model) {
|
|
2948
|
-
return new TablePresentation(model);
|
|
2949
|
-
}
|
|
2950
|
-
}, [
|
|
2951
|
-
model
|
|
2952
|
-
]);
|
|
2953
|
-
return /* @__PURE__ */ React9.createElement("div", {
|
|
2954
|
-
role: "none",
|
|
2955
|
-
className: mx3("is-full bs-full grow grid", classNames)
|
|
2956
|
-
}, /* @__PURE__ */ React9.createElement("div", {
|
|
1086
|
+
handleInsertRowResult
|
|
1087
|
+
};
|
|
1088
|
+
}, [
|
|
1089
|
+
dxGrid,
|
|
1090
|
+
model,
|
|
1091
|
+
presentation
|
|
1092
|
+
]);
|
|
1093
|
+
if (!model || !modals) {
|
|
1094
|
+
return /* @__PURE__ */ React7.createElement("span", {
|
|
2957
1095
|
role: "none",
|
|
2958
|
-
className: "
|
|
2959
|
-
}
|
|
2960
|
-
ref: tableRef,
|
|
2961
|
-
model,
|
|
2962
|
-
presentation,
|
|
2963
|
-
ignoreAttention: true,
|
|
2964
|
-
onRowClick
|
|
2965
|
-
}))));
|
|
2966
|
-
} finally {
|
|
2967
|
-
_effect.f();
|
|
1096
|
+
className: "dx-attention-surface"
|
|
1097
|
+
});
|
|
2968
1098
|
}
|
|
2969
|
-
|
|
1099
|
+
return /* @__PURE__ */ React7.createElement("div", {
|
|
1100
|
+
...composableProps(props, {
|
|
1101
|
+
classNames: "dx-container relative"
|
|
1102
|
+
}),
|
|
1103
|
+
ref: forwardedRef
|
|
1104
|
+
}, /* @__PURE__ */ React7.createElement(Grid.Root, {
|
|
1105
|
+
id: model.id ?? "table-grid"
|
|
1106
|
+
}, /* @__PURE__ */ React7.createElement(TableValueEditor, {
|
|
1107
|
+
model,
|
|
1108
|
+
modals,
|
|
1109
|
+
schema,
|
|
1110
|
+
onFocus: handleFocus,
|
|
1111
|
+
onSave: handleSave,
|
|
1112
|
+
onCreate
|
|
1113
|
+
}), /* @__PURE__ */ React7.createElement(Grid.Content, {
|
|
1114
|
+
className: mx("[--dx-grid-base:var(--base-surface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
1115
|
+
frozen,
|
|
1116
|
+
columns: columnMeta,
|
|
1117
|
+
columnDefault,
|
|
1118
|
+
rowDefault,
|
|
1119
|
+
limitRows: rows.length,
|
|
1120
|
+
limitColumns: columnCount,
|
|
1121
|
+
overscroll: "trap",
|
|
1122
|
+
onAxisResize: handleAxisResize,
|
|
1123
|
+
onClick: handleGridClick,
|
|
1124
|
+
onKeyDownCapture: handleKeyDown,
|
|
1125
|
+
onWheelCapture: handleWheel,
|
|
1126
|
+
...testId && {
|
|
1127
|
+
"data-testid": testId
|
|
1128
|
+
},
|
|
1129
|
+
ref: setDxGrid
|
|
1130
|
+
}), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
|
|
1131
|
+
model,
|
|
1132
|
+
modals
|
|
1133
|
+
}), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
|
|
1134
|
+
model,
|
|
1135
|
+
modals
|
|
1136
|
+
}), /* @__PURE__ */ React7.createElement(ColumnSettings, {
|
|
1137
|
+
model,
|
|
1138
|
+
modals,
|
|
1139
|
+
onNewColumn: handleNewColumn
|
|
1140
|
+
})));
|
|
1141
|
+
});
|
|
1142
|
+
TableContent.displayName = TABLE_CONTENT_NAME;
|
|
2970
1143
|
|
|
2971
|
-
// src/components/
|
|
2972
|
-
import {
|
|
2973
|
-
import {
|
|
2974
|
-
import
|
|
2975
|
-
import {
|
|
2976
|
-
import {
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
1144
|
+
// src/components/Table/TableToolbar.tsx
|
|
1145
|
+
import { Atom as Atom3, RegistryContext as RegistryContext2 } from "@effect-atom/atom-react";
|
|
1146
|
+
import React8, { useContext as useContext2, useEffect as useEffect4, useMemo as useMemo5 } from "react";
|
|
1147
|
+
import { Menu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
|
|
1148
|
+
import { composable as composable2, composableProps as composableProps2 } from "@dxos/ui-theme";
|
|
1149
|
+
import { translationKey as translationKey4 } from "#translations";
|
|
1150
|
+
var createTableToolbarActions = ({ stateAtom, onAdd, onSave, customActions }) => Atom3.make((get) => {
|
|
1151
|
+
const nodes = [];
|
|
1152
|
+
if (onAdd) {
|
|
1153
|
+
const add = createMenuAction("add-row", onAdd, {
|
|
1154
|
+
type: "add-row",
|
|
1155
|
+
icon: "ph--plus--regular",
|
|
1156
|
+
label: [
|
|
1157
|
+
"add-row.label",
|
|
1158
|
+
{
|
|
1159
|
+
ns: translationKey4
|
|
1160
|
+
}
|
|
1161
|
+
],
|
|
1162
|
+
testId: "table.toolbar.add-row"
|
|
1163
|
+
});
|
|
1164
|
+
nodes.push(add);
|
|
1165
|
+
}
|
|
1166
|
+
if (onSave) {
|
|
1167
|
+
const state = get(stateAtom);
|
|
1168
|
+
const save = createMenuAction("save-view", onSave, {
|
|
1169
|
+
type: "save-view",
|
|
1170
|
+
icon: "ph--floppy-disk--regular",
|
|
1171
|
+
label: [
|
|
1172
|
+
"save-view.label",
|
|
1173
|
+
{
|
|
1174
|
+
ns: translationKey4
|
|
1175
|
+
}
|
|
1176
|
+
],
|
|
1177
|
+
testId: "table.toolbar.save-view",
|
|
1178
|
+
iconOnly: false,
|
|
1179
|
+
hidden: !state.viewDirty
|
|
1180
|
+
});
|
|
1181
|
+
nodes.push(save);
|
|
1182
|
+
}
|
|
3003
1183
|
const gap = createGapSeparator();
|
|
3004
|
-
|
|
3005
|
-
add,
|
|
3006
|
-
save,
|
|
3007
|
-
...gap.nodes
|
|
3008
|
-
];
|
|
1184
|
+
nodes.push(...gap.nodes);
|
|
3009
1185
|
const edges = nodes.map(({ id: target }) => ({
|
|
3010
1186
|
source: "root",
|
|
3011
|
-
target
|
|
1187
|
+
target,
|
|
1188
|
+
relation: "child"
|
|
3012
1189
|
}));
|
|
3013
1190
|
if (customActions) {
|
|
3014
1191
|
const custom = get(customActions);
|
|
@@ -3020,33 +1197,140 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
|
|
|
3020
1197
|
edges
|
|
3021
1198
|
};
|
|
3022
1199
|
});
|
|
3023
|
-
var TableToolbar = ({
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
1200
|
+
var TableToolbar = composable2(({ attendableId, viewDirty, onAdd, onSave, customActions, ...props }, forwardedRef) => {
|
|
1201
|
+
const registry = useContext2(RegistryContext2);
|
|
1202
|
+
const stateAtom = useMemo5(() => Atom3.make({
|
|
1203
|
+
viewDirty
|
|
1204
|
+
}), []);
|
|
1205
|
+
useEffect4(() => {
|
|
1206
|
+
registry.set(stateAtom, {
|
|
3027
1207
|
viewDirty
|
|
3028
|
-
})
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
1208
|
+
});
|
|
1209
|
+
}, [
|
|
1210
|
+
registry,
|
|
1211
|
+
stateAtom,
|
|
1212
|
+
viewDirty
|
|
1213
|
+
]);
|
|
1214
|
+
const actionsCreator = useMemo5(() => createTableToolbarActions({
|
|
1215
|
+
stateAtom,
|
|
1216
|
+
onAdd,
|
|
1217
|
+
onSave,
|
|
1218
|
+
customActions
|
|
1219
|
+
}), [
|
|
1220
|
+
stateAtom,
|
|
1221
|
+
onAdd,
|
|
1222
|
+
onSave,
|
|
1223
|
+
customActions
|
|
1224
|
+
]);
|
|
1225
|
+
const menuActions = useMenuActions(actionsCreator);
|
|
1226
|
+
return /* @__PURE__ */ React8.createElement(Menu.Root, {
|
|
1227
|
+
...menuActions,
|
|
1228
|
+
attendableId
|
|
1229
|
+
}, /* @__PURE__ */ React8.createElement(Menu.Toolbar, {
|
|
1230
|
+
...composableProps2(props),
|
|
1231
|
+
ref: forwardedRef
|
|
1232
|
+
}));
|
|
1233
|
+
});
|
|
1234
|
+
TableToolbar.displayName = "TableToolbar";
|
|
1235
|
+
|
|
1236
|
+
// src/components/Table/Table.tsx
|
|
1237
|
+
var emptyColumnMeta2 = Atom4.make({
|
|
1238
|
+
grid: {}
|
|
1239
|
+
});
|
|
1240
|
+
var [TableContextProvider, useTableContext] = createContext("Table");
|
|
1241
|
+
var TABLE_ROOT_NAME = "Table.Root";
|
|
1242
|
+
var TableRoot = /* @__PURE__ */ forwardRef(({ children }, forwardedRef) => {
|
|
1243
|
+
const controllerRef = useRef3({});
|
|
1244
|
+
useImperativeHandle(forwardedRef, () => ({
|
|
1245
|
+
update: (cell) => controllerRef.current?.update?.(cell),
|
|
1246
|
+
handleInsertRowResult: (result) => controllerRef.current?.handleInsertRowResult?.(result)
|
|
1247
|
+
}), []);
|
|
1248
|
+
return /* @__PURE__ */ React9.createElement(TableContextProvider, {
|
|
1249
|
+
controllerRef
|
|
1250
|
+
}, children);
|
|
1251
|
+
});
|
|
1252
|
+
TableRoot.displayName = TABLE_ROOT_NAME;
|
|
1253
|
+
var Table = {
|
|
1254
|
+
Root: TableRoot,
|
|
1255
|
+
Toolbar: TableToolbar,
|
|
1256
|
+
Content: TableContent
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
// src/components/Table/DynamicTable.tsx
|
|
1260
|
+
import { RegistryContext as RegistryContext3 } from "@effect-atom/atom-react";
|
|
1261
|
+
import React10, { useCallback as useCallback5, useContext as useContext3, useEffect as useEffect5, useMemo as useMemo6, useRef as useRef4, useState as useState5 } from "react";
|
|
1262
|
+
import { useDefaultValue } from "@dxos/react-ui";
|
|
1263
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1264
|
+
var DynamicTable = ({ classNames, schema, name = "com.example.dynamicTable", rows, properties, jsonSchema: jsonSchemaProp, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
1265
|
+
const registry = useContext3(RegistryContext3);
|
|
1266
|
+
const [dynamicTable, setDynamicTable] = useState5();
|
|
1267
|
+
const { jsonSchema } = useMemo6(() => getBaseSchema({
|
|
1268
|
+
typename: name,
|
|
1269
|
+
properties,
|
|
1270
|
+
jsonSchema: jsonSchemaProp,
|
|
1271
|
+
schema
|
|
1272
|
+
}), [
|
|
1273
|
+
name,
|
|
1274
|
+
properties,
|
|
1275
|
+
jsonSchemaProp,
|
|
1276
|
+
schema
|
|
1277
|
+
]);
|
|
1278
|
+
useEffect5(() => {
|
|
1279
|
+
setDynamicTable(makeDynamicTable({
|
|
1280
|
+
registry,
|
|
1281
|
+
jsonSchema,
|
|
1282
|
+
properties
|
|
3046
1283
|
}));
|
|
3047
|
-
}
|
|
3048
|
-
|
|
3049
|
-
|
|
1284
|
+
}, [
|
|
1285
|
+
registry,
|
|
1286
|
+
jsonSchema,
|
|
1287
|
+
properties
|
|
1288
|
+
]);
|
|
1289
|
+
const tableRef = useRef4(null);
|
|
1290
|
+
const handleCellUpdate = useCallback5((cell) => {
|
|
1291
|
+
tableRef.current?.update?.(cell);
|
|
1292
|
+
}, []);
|
|
1293
|
+
const handleRowOrderChange = useCallback5(() => {
|
|
1294
|
+
tableRef.current?.update?.();
|
|
1295
|
+
}, []);
|
|
1296
|
+
const features = useDefaultValue(props.features, () => ({
|
|
1297
|
+
selection: {
|
|
1298
|
+
enabled: false
|
|
1299
|
+
},
|
|
1300
|
+
dataEditable: false
|
|
1301
|
+
}));
|
|
1302
|
+
const model = useTableModel({
|
|
1303
|
+
rows,
|
|
1304
|
+
object: dynamicTable?.object,
|
|
1305
|
+
projection: dynamicTable?.projection,
|
|
1306
|
+
features,
|
|
1307
|
+
rowActions,
|
|
1308
|
+
onCellUpdate: handleCellUpdate,
|
|
1309
|
+
onRowOrderChange: handleRowOrderChange,
|
|
1310
|
+
onRowAction
|
|
1311
|
+
});
|
|
1312
|
+
const presentation = useMemo6(() => {
|
|
1313
|
+
if (model) {
|
|
1314
|
+
return new TablePresentation(registry, model);
|
|
1315
|
+
}
|
|
1316
|
+
}, [
|
|
1317
|
+
registry,
|
|
1318
|
+
model
|
|
1319
|
+
]);
|
|
1320
|
+
return /* @__PURE__ */ React10.createElement("div", {
|
|
1321
|
+
role: "none",
|
|
1322
|
+
className: mx2("dx-expander grid", classNames)
|
|
1323
|
+
}, /* @__PURE__ */ React10.createElement("div", {
|
|
1324
|
+
role: "none",
|
|
1325
|
+
className: "grid min-h-0 overflow-hidden"
|
|
1326
|
+
}, /* @__PURE__ */ React10.createElement(Table.Root, {
|
|
1327
|
+
ref: tableRef
|
|
1328
|
+
}, /* @__PURE__ */ React10.createElement(Table.Content, {
|
|
1329
|
+
model,
|
|
1330
|
+
presentation,
|
|
1331
|
+
ignoreAttention: true,
|
|
1332
|
+
onRowClick
|
|
1333
|
+
}))));
|
|
3050
1334
|
};
|
|
3051
1335
|
export {
|
|
3052
1336
|
BUTTON_IDENTIFIERS,
|
|
@@ -3058,19 +1342,21 @@ export {
|
|
|
3058
1342
|
Table,
|
|
3059
1343
|
TableModel,
|
|
3060
1344
|
TablePresentation,
|
|
3061
|
-
TableSchema,
|
|
3062
|
-
TableToolbar,
|
|
3063
|
-
TableType,
|
|
3064
1345
|
cellClassesForRowSelection,
|
|
1346
|
+
compareValues,
|
|
1347
|
+
createDirectChangeCallback,
|
|
1348
|
+
createEchoChangeCallback,
|
|
1349
|
+
extractOrder,
|
|
3065
1350
|
getBaseSchema,
|
|
3066
|
-
|
|
1351
|
+
getSortValue,
|
|
3067
1352
|
makeDynamicTable,
|
|
3068
1353
|
narrowSchema,
|
|
3069
1354
|
tableButtons,
|
|
3070
1355
|
tableControls,
|
|
3071
1356
|
touch,
|
|
3072
|
-
translations,
|
|
3073
1357
|
useAddRow,
|
|
1358
|
+
useProjectionModel,
|
|
1359
|
+
useTableContext,
|
|
3074
1360
|
useTableModel
|
|
3075
1361
|
};
|
|
3076
1362
|
//# sourceMappingURL=index.mjs.map
|