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