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