@dxos/react-ui-table 0.8.3 → 0.8.4-main.1f223c7
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 +814 -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 +814 -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 +167 -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,158 @@ 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 React8, { forwardRef, useCallback as useCallback5,
|
|
41
|
-
import { getValue as getValue4 } from "@dxos/echo-schema";
|
|
42
|
-
import { invariant as invariant4 } from "@dxos/invariant";
|
|
43
|
-
import { Filter } from "@dxos/react-client/echo";
|
|
44
|
-
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
55
|
+
import React8, { forwardRef, useCallback as useCallback5, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo5, useState as useState4 } from "react";
|
|
45
56
|
import { useAttention } from "@dxos/react-ui-attention";
|
|
46
|
-
import { closestCell,
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
57
|
+
import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
|
|
58
|
+
import { DxEditRequest } from "@dxos/react-ui-grid";
|
|
59
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
60
|
+
|
|
61
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
62
|
+
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
63
|
+
import { EditorView } from "@codemirror/view";
|
|
64
|
+
import React3, { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
65
|
+
import { debounce } from "@dxos/async";
|
|
66
|
+
import { FormatEnum, TypeEnum } from "@dxos/echo-schema";
|
|
67
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
68
|
+
import { createMarkdownExtensions } from "@dxos/react-ui-editor";
|
|
69
|
+
import { GridCellEditor, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
|
|
70
|
+
import { createLinks, tagPicker } from "@dxos/react-ui-tag-picker";
|
|
49
71
|
|
|
50
|
-
//
|
|
72
|
+
// src/components/TableCellEditor/CellValidationMessage.tsx
|
|
51
73
|
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
52
74
|
import React from "react";
|
|
53
|
-
import {
|
|
54
|
-
var
|
|
75
|
+
import { useGridContext } from "@dxos/react-ui-grid";
|
|
76
|
+
var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
|
|
55
77
|
var _effect = _useSignals();
|
|
56
78
|
try {
|
|
57
|
-
const {
|
|
58
|
-
|
|
59
|
-
if (state?.type !== "column") {
|
|
79
|
+
const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
|
|
80
|
+
if (!editing || !validationError) {
|
|
60
81
|
return null;
|
|
61
82
|
}
|
|
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))));
|
|
83
|
+
const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
|
|
84
|
+
const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
|
|
85
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
86
|
+
role: "none",
|
|
87
|
+
className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
|
|
88
|
+
style: {
|
|
89
|
+
...{
|
|
90
|
+
"--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
|
|
91
|
+
},
|
|
92
|
+
zIndex: 10,
|
|
93
|
+
insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
|
|
94
|
+
insetInlineStart: box.insetInlineStart,
|
|
95
|
+
inlineSize: box.inlineSize
|
|
96
|
+
}
|
|
97
|
+
}, validationError);
|
|
86
98
|
} finally {
|
|
87
99
|
_effect.f();
|
|
88
100
|
}
|
|
89
101
|
};
|
|
90
102
|
|
|
91
|
-
//
|
|
103
|
+
// src/components/TableCellEditor/FormCellEditor.tsx
|
|
92
104
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
93
|
-
import React2, { useCallback, useEffect, useMemo, useState } from "react";
|
|
105
|
+
import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
106
|
+
import { Filter, Obj } from "@dxos/echo";
|
|
107
|
+
import { Ref, getValue } from "@dxos/echo-schema";
|
|
108
|
+
import { invariant } from "@dxos/invariant";
|
|
109
|
+
import { getSnapshot } from "@dxos/live-object";
|
|
110
|
+
import { getSpace } from "@dxos/react-client/echo";
|
|
94
111
|
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
112
|
import { Form } from "@dxos/react-ui-form";
|
|
172
|
-
import { useGridContext } from "@dxos/react-ui-grid";
|
|
173
|
-
|
|
174
|
-
|
|
113
|
+
import { cellQuery, parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
|
|
114
|
+
import { getDeep, isNotFalsy, setDeep } from "@dxos/util";
|
|
115
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
|
|
116
|
+
var createOptionLabel = [
|
|
117
|
+
"create new object label",
|
|
118
|
+
{
|
|
119
|
+
ns: translationKey
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
var FormCellEditor = ({ fieldProjection, model, schema, onSave, client, modals, __gridScope, ...formProps }) => {
|
|
123
|
+
var _effect = _useSignals2();
|
|
175
124
|
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;
|
|
125
|
+
const { editing: contextEditing, setEditing, id: gridId } = useGridContext2("ArrayEditor", __gridScope);
|
|
126
|
+
const [editing, setLocalEditing] = useState(false);
|
|
127
|
+
const anchorRef = useRef(null);
|
|
128
|
+
const getSchema = useCallback((typeAnnotation) => {
|
|
129
|
+
const space = getSpace(model.view);
|
|
130
|
+
invariant(space, void 0, {
|
|
131
|
+
F: __dxlog_file,
|
|
132
|
+
L: 53,
|
|
133
|
+
S: void 0,
|
|
134
|
+
A: [
|
|
135
|
+
"space",
|
|
136
|
+
""
|
|
137
|
+
]
|
|
138
|
+
});
|
|
139
|
+
let schema2;
|
|
140
|
+
if (client) {
|
|
141
|
+
schema2 = client.graph.schemaRegistry.getSchema(typeAnnotation.typename);
|
|
197
142
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}).runSync();
|
|
201
|
-
if (schema2) {
|
|
202
|
-
const obj = space.db.add(live(schema2, values));
|
|
203
|
-
state.onCreate?.(obj);
|
|
143
|
+
if (!schema2) {
|
|
144
|
+
schema2 = space.db.schemaRegistry.getSchema(typeAnnotation.typename);
|
|
204
145
|
}
|
|
205
|
-
|
|
146
|
+
return {
|
|
147
|
+
space,
|
|
148
|
+
schema: schema2
|
|
149
|
+
};
|
|
206
150
|
}, [
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
state
|
|
151
|
+
client,
|
|
152
|
+
model
|
|
210
153
|
]);
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
154
|
+
const handleQueryRefOptions = useCallback(async (typeAnnotation) => {
|
|
155
|
+
const { schema: schema2, space } = getSchema(typeAnnotation);
|
|
156
|
+
if (model && schema2 && space) {
|
|
157
|
+
const { objects } = await space.db.query(Filter.type(schema2)).run();
|
|
158
|
+
return objects.map((obj) => {
|
|
159
|
+
return {
|
|
160
|
+
dxn: Obj.getDXN(obj),
|
|
161
|
+
label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
|
|
162
|
+
};
|
|
163
|
+
}).filter(isNotFalsy);
|
|
214
164
|
}
|
|
165
|
+
return [];
|
|
215
166
|
}, [
|
|
216
|
-
|
|
167
|
+
client,
|
|
168
|
+
model
|
|
217
169
|
]);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
170
|
+
const originalRow = useMemo(() => {
|
|
171
|
+
if (model && contextEditing) {
|
|
172
|
+
const cell = parseCellIndex(contextEditing.index);
|
|
173
|
+
if (model.isDraftCell(cell)) {
|
|
174
|
+
const draftRow = model.draftRows.value[cell.row];
|
|
175
|
+
invariant(draftRow, void 0, {
|
|
176
|
+
F: __dxlog_file,
|
|
177
|
+
L: 94,
|
|
178
|
+
S: void 0,
|
|
179
|
+
A: [
|
|
180
|
+
"draftRow",
|
|
181
|
+
""
|
|
182
|
+
]
|
|
183
|
+
});
|
|
184
|
+
return draftRow.data;
|
|
185
|
+
} else {
|
|
186
|
+
const row = model.getRowAt(cell.row);
|
|
187
|
+
invariant(row, void 0, {
|
|
188
|
+
F: __dxlog_file,
|
|
189
|
+
L: 98,
|
|
190
|
+
S: void 0,
|
|
191
|
+
A: [
|
|
192
|
+
"row",
|
|
193
|
+
""
|
|
194
|
+
]
|
|
195
|
+
});
|
|
196
|
+
return row;
|
|
227
197
|
}
|
|
228
198
|
}
|
|
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
199
|
return void 0;
|
|
1783
200
|
}, [
|
|
1784
201
|
model,
|
|
1785
|
-
|
|
1786
|
-
]);
|
|
1787
|
-
const formValues = useMemo3(() => {
|
|
1788
|
-
if (originalRow) {
|
|
1789
|
-
return getSnapshot2(originalRow);
|
|
1790
|
-
}
|
|
1791
|
-
}, [
|
|
1792
|
-
originalRow
|
|
202
|
+
contextEditing
|
|
1793
203
|
]);
|
|
1794
|
-
const handleSave =
|
|
204
|
+
const handleSave = useCallback((values) => {
|
|
1795
205
|
const path = fieldProjection.field.path;
|
|
1796
206
|
const value = getDeep(values, [
|
|
1797
207
|
path
|
|
@@ -1799,100 +209,124 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
|
|
|
1799
209
|
setDeep(originalRow, [
|
|
1800
210
|
path
|
|
1801
211
|
], value);
|
|
212
|
+
contextEditing?.cellElement?.focus();
|
|
1802
213
|
setEditing(null);
|
|
214
|
+
setLocalEditing(false);
|
|
215
|
+
onSave?.();
|
|
1803
216
|
}, [
|
|
1804
217
|
fieldProjection.field.path,
|
|
218
|
+
onSave,
|
|
219
|
+
contextEditing,
|
|
1805
220
|
originalRow
|
|
1806
221
|
]);
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
|
|
222
|
+
const handleCreate = useCallback((object) => {
|
|
223
|
+
const ref = Ref.make(object);
|
|
224
|
+
const path = fieldProjection.field.path;
|
|
225
|
+
setDeep(originalRow, [
|
|
226
|
+
path
|
|
227
|
+
], ref);
|
|
228
|
+
contextEditing?.cellElement?.focus();
|
|
229
|
+
setEditing(null);
|
|
230
|
+
setLocalEditing(false);
|
|
231
|
+
onSave?.();
|
|
232
|
+
}, [
|
|
233
|
+
fieldProjection.field.path,
|
|
234
|
+
onSave,
|
|
235
|
+
contextEditing,
|
|
236
|
+
originalRow
|
|
237
|
+
]);
|
|
238
|
+
const handleCreateFromQuery = useCallback(async (typeAnnotation, query) => {
|
|
239
|
+
if (model && modals && contextEditing?.index) {
|
|
240
|
+
setLocalEditing(false);
|
|
241
|
+
modals.openCreateRef(typeAnnotation.typename, document.querySelector(cellQuery(contextEditing.index, gridId)), {
|
|
242
|
+
[fieldProjection.field.referencePath]: query
|
|
243
|
+
}, handleCreate);
|
|
1810
244
|
}
|
|
1811
245
|
}, [
|
|
1812
|
-
|
|
246
|
+
model,
|
|
247
|
+
modals,
|
|
248
|
+
client,
|
|
249
|
+
contextEditing?.index,
|
|
250
|
+
gridId,
|
|
251
|
+
fieldProjection,
|
|
252
|
+
handleSave
|
|
253
|
+
]);
|
|
254
|
+
useEffect(() => {
|
|
255
|
+
if (contextEditing && contextEditing.cellElement) {
|
|
256
|
+
anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
|
|
257
|
+
setLocalEditing(true);
|
|
258
|
+
} else {
|
|
259
|
+
anchorRef.current = null;
|
|
260
|
+
setLocalEditing(false);
|
|
261
|
+
}
|
|
262
|
+
}, [
|
|
263
|
+
contextEditing
|
|
264
|
+
]);
|
|
265
|
+
const narrowedSchema = useMemo(() => {
|
|
266
|
+
if (!schema) {
|
|
267
|
+
return void 0;
|
|
268
|
+
}
|
|
269
|
+
return narrowSchema(schema, [
|
|
270
|
+
fieldProjection.field.path
|
|
271
|
+
]);
|
|
272
|
+
}, [
|
|
273
|
+
JSON.stringify(schema),
|
|
274
|
+
fieldProjection.field.path
|
|
275
|
+
]);
|
|
276
|
+
const formValues = useMemo(() => originalRow ? getSnapshot(originalRow) : {}, [
|
|
277
|
+
originalRow
|
|
1813
278
|
]);
|
|
279
|
+
const handleOpenChange = useCallback((nextOpen) => {
|
|
280
|
+
if (nextOpen === false) {
|
|
281
|
+
setEditing(null);
|
|
282
|
+
onSave?.();
|
|
283
|
+
}
|
|
284
|
+
setLocalEditing(nextOpen);
|
|
285
|
+
}, []);
|
|
1814
286
|
if (!editing) {
|
|
1815
287
|
return null;
|
|
1816
288
|
}
|
|
1817
|
-
return /* @__PURE__ */
|
|
1818
|
-
open: editing
|
|
289
|
+
return /* @__PURE__ */ React2.createElement(Popover.Root, {
|
|
290
|
+
open: editing,
|
|
1819
291
|
onOpenChange: handleOpenChange
|
|
1820
|
-
}, /* @__PURE__ */
|
|
1821
|
-
virtualRef:
|
|
1822
|
-
}), /* @__PURE__ */
|
|
292
|
+
}, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
|
|
293
|
+
virtualRef: anchorRef
|
|
294
|
+
}), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
|
|
1823
295
|
tabIndex: -1,
|
|
1824
|
-
classNames: "popover-card-width"
|
|
1825
|
-
}, /* @__PURE__ */
|
|
296
|
+
classNames: "popover-card-width density-fine"
|
|
297
|
+
}, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form, {
|
|
298
|
+
autoFocus: true,
|
|
1826
299
|
values: formValues,
|
|
1827
300
|
schema: narrowedSchema,
|
|
1828
|
-
onSave: handleSave
|
|
1829
|
-
|
|
301
|
+
onSave: handleSave,
|
|
302
|
+
...formProps,
|
|
303
|
+
onQueryRefOptions: handleQueryRefOptions,
|
|
304
|
+
onCreateFromQuery: handleCreateFromQuery,
|
|
305
|
+
createOptionIcon: "ph--plus--regular",
|
|
306
|
+
createOptionLabel
|
|
307
|
+
})))));
|
|
1830
308
|
} finally {
|
|
1831
309
|
_effect.f();
|
|
1832
310
|
}
|
|
1833
311
|
};
|
|
1834
312
|
|
|
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();
|
|
313
|
+
// src/components/TableCellEditor/TableCellEditor.tsx
|
|
314
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
|
|
315
|
+
var adaptValidationMessage = (message) => message ? message.endsWith("is missing") ? "Can\u2019t be blank" : message : null;
|
|
316
|
+
var TableValueEditor = ({ model, modals, schema, onFocus, onSave, client, __gridScope }) => {
|
|
317
|
+
var _effect = _useSignals3();
|
|
1884
318
|
try {
|
|
1885
|
-
const { editing } =
|
|
1886
|
-
const fieldProjection =
|
|
319
|
+
const { editing } = useGridContext3("TableValueEditor", __gridScope);
|
|
320
|
+
const fieldProjection = useMemo2(() => {
|
|
1887
321
|
if (!model || !editing) {
|
|
1888
322
|
return;
|
|
1889
323
|
}
|
|
1890
324
|
const { col } = parseCellIndex2(editing.index);
|
|
1891
|
-
const field = model.projection.
|
|
325
|
+
const field = model.projection.fields[col];
|
|
1892
326
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1893
|
-
|
|
1894
|
-
F:
|
|
1895
|
-
L:
|
|
327
|
+
invariant2(fieldProjection2, void 0, {
|
|
328
|
+
F: __dxlog_file2,
|
|
329
|
+
L: 71,
|
|
1896
330
|
S: void 0,
|
|
1897
331
|
A: [
|
|
1898
332
|
"fieldProjection",
|
|
@@ -1904,43 +338,50 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
|
|
|
1904
338
|
model,
|
|
1905
339
|
editing
|
|
1906
340
|
]);
|
|
1907
|
-
if (fieldProjection?.props.type ===
|
|
1908
|
-
return /* @__PURE__ */
|
|
341
|
+
if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect || fieldProjection?.props.format === FormatEnum.Ref) {
|
|
342
|
+
return /* @__PURE__ */ React3.createElement(FormCellEditor, {
|
|
1909
343
|
fieldProjection,
|
|
1910
344
|
model,
|
|
1911
345
|
schema,
|
|
1912
|
-
__gridScope
|
|
346
|
+
__gridScope,
|
|
347
|
+
onSave,
|
|
348
|
+
client,
|
|
349
|
+
modals
|
|
1913
350
|
});
|
|
1914
351
|
}
|
|
1915
|
-
return /* @__PURE__ */
|
|
352
|
+
return /* @__PURE__ */ React3.createElement(TableCellEditor, {
|
|
1916
353
|
model,
|
|
1917
354
|
modals,
|
|
1918
|
-
onEnter,
|
|
1919
355
|
onFocus,
|
|
1920
|
-
|
|
356
|
+
onSave,
|
|
1921
357
|
__gridScope
|
|
1922
358
|
});
|
|
1923
359
|
} finally {
|
|
1924
360
|
_effect.f();
|
|
1925
361
|
}
|
|
1926
362
|
};
|
|
1927
|
-
var
|
|
1928
|
-
|
|
363
|
+
var editorSlots = {
|
|
364
|
+
scroll: {
|
|
365
|
+
className: "!plb-[--dx-grid-cell-editor-padding-block]"
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
var TableCellEditor = ({ model, modals, onFocus, onSave, __gridScope }) => {
|
|
369
|
+
var _effect = _useSignals3();
|
|
1929
370
|
try {
|
|
1930
|
-
const {
|
|
371
|
+
const { editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
|
|
1931
372
|
const suppressNextBlur = useRef2(false);
|
|
1932
|
-
const
|
|
1933
|
-
const [
|
|
1934
|
-
const fieldProjection =
|
|
373
|
+
const [validationError, setValidationError] = useState2(null);
|
|
374
|
+
const [validationVariant, setValidationVariant] = useState2("error");
|
|
375
|
+
const fieldProjection = useMemo2(() => {
|
|
1935
376
|
if (!model || !editing) {
|
|
1936
377
|
return;
|
|
1937
378
|
}
|
|
1938
379
|
const { col } = parseCellIndex2(editing.index);
|
|
1939
|
-
const field = model.projection.
|
|
380
|
+
const field = model.projection.fields[col];
|
|
1940
381
|
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
1941
|
-
|
|
1942
|
-
F:
|
|
1943
|
-
L:
|
|
382
|
+
invariant2(fieldProjection2, void 0, {
|
|
383
|
+
F: __dxlog_file2,
|
|
384
|
+
L: 120,
|
|
1944
385
|
S: void 0,
|
|
1945
386
|
A: [
|
|
1946
387
|
"fieldProjection",
|
|
@@ -1952,40 +393,48 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1952
393
|
model,
|
|
1953
394
|
editing
|
|
1954
395
|
]);
|
|
1955
|
-
const handleEnter =
|
|
396
|
+
const handleEnter = useCallback2(async (value) => {
|
|
1956
397
|
if (!model || !editing) {
|
|
1957
398
|
return;
|
|
1958
399
|
}
|
|
1959
400
|
const cell = parseCellIndex2(editing.index);
|
|
1960
|
-
const
|
|
1961
|
-
if (
|
|
401
|
+
const validationResult = await model.validateCellData(cell, value);
|
|
402
|
+
if (validationResult.valid) {
|
|
1962
403
|
setValidationError(null);
|
|
1963
404
|
model.setCellData(cell, value);
|
|
1964
|
-
onEnter?.(cell);
|
|
1965
405
|
onFocus?.();
|
|
1966
406
|
setEditing(null);
|
|
407
|
+
onSave?.();
|
|
1967
408
|
} else {
|
|
1968
|
-
setValidationError(
|
|
409
|
+
setValidationError(adaptValidationMessage(validationResult.error));
|
|
410
|
+
setValidationVariant("error");
|
|
1969
411
|
}
|
|
1970
412
|
}, [
|
|
1971
413
|
model,
|
|
1972
414
|
editing,
|
|
1973
|
-
onEnter,
|
|
1974
415
|
onFocus,
|
|
1975
416
|
setEditing
|
|
1976
417
|
]);
|
|
1977
|
-
const handleBlur =
|
|
1978
|
-
if (!model || !editing) {
|
|
1979
|
-
return;
|
|
1980
|
-
}
|
|
418
|
+
const handleBlur = useCallback2(async (value) => {
|
|
1981
419
|
if (suppressNextBlur.current) {
|
|
1982
420
|
suppressNextBlur.current = false;
|
|
421
|
+
} else if (model && editing) {
|
|
422
|
+
const cell = parseCellIndex2(editing.index);
|
|
423
|
+
if (value !== void 0) {
|
|
424
|
+
const result = await model.validateCellData(cell, value);
|
|
425
|
+
if (result.valid) {
|
|
426
|
+
setValidationError(null);
|
|
427
|
+
model.setCellData(cell, value);
|
|
428
|
+
setEditing(null);
|
|
429
|
+
onSave?.();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
1983
432
|
}
|
|
1984
433
|
}, [
|
|
1985
434
|
model,
|
|
1986
435
|
editing
|
|
1987
436
|
]);
|
|
1988
|
-
const handleClose =
|
|
437
|
+
const handleClose = useCallback2(async (value, event) => {
|
|
1989
438
|
if (!model || !editing || !fieldProjection) {
|
|
1990
439
|
return;
|
|
1991
440
|
}
|
|
@@ -1993,19 +442,23 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
1993
442
|
if (value !== void 0) {
|
|
1994
443
|
const result = await model.validateCellData(cell, value);
|
|
1995
444
|
if (result.valid) {
|
|
445
|
+
suppressNextBlur.current = true;
|
|
1996
446
|
setValidationError(null);
|
|
1997
447
|
model.setCellData(cell, value);
|
|
1998
448
|
setEditing(null);
|
|
1999
|
-
|
|
449
|
+
onSave?.();
|
|
2000
450
|
if (event && onFocus) {
|
|
2001
|
-
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
451
|
+
onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
|
|
2002
452
|
}
|
|
2003
453
|
} else {
|
|
2004
454
|
setValidationError(result.error);
|
|
455
|
+
setValidationVariant("error");
|
|
2005
456
|
}
|
|
2006
457
|
} else {
|
|
458
|
+
suppressNextBlur.current = true;
|
|
2007
459
|
setValidationError(null);
|
|
2008
460
|
setEditing(null);
|
|
461
|
+
onSave?.();
|
|
2009
462
|
if (event && onFocus) {
|
|
2010
463
|
onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
|
|
2011
464
|
}
|
|
@@ -2014,15 +467,15 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2014
467
|
model,
|
|
2015
468
|
editing,
|
|
2016
469
|
onFocus,
|
|
2017
|
-
onEnter,
|
|
2018
470
|
fieldProjection,
|
|
2019
|
-
setEditing
|
|
471
|
+
setEditing,
|
|
472
|
+
onSave
|
|
2020
473
|
]);
|
|
2021
|
-
const
|
|
474
|
+
const extensions = useMemo2(() => {
|
|
2022
475
|
if (!fieldProjection) {
|
|
2023
476
|
return [];
|
|
2024
477
|
}
|
|
2025
|
-
const
|
|
478
|
+
const extensions2 = [
|
|
2026
479
|
editorKeys({
|
|
2027
480
|
onClose: handleClose,
|
|
2028
481
|
...editing?.initialContent && {
|
|
@@ -2031,15 +484,13 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2031
484
|
})
|
|
2032
485
|
];
|
|
2033
486
|
const format = fieldProjection.props.format;
|
|
2034
|
-
if (format ===
|
|
2035
|
-
extension2.push(createMarkdownExtensions({
|
|
2036
|
-
themeMode
|
|
2037
|
-
}));
|
|
487
|
+
if (format === FormatEnum.SingleSelect || format === FormatEnum.MultiSelect) {
|
|
2038
488
|
const options = fieldProjection.props.options || [];
|
|
2039
|
-
const mode = format ===
|
|
2040
|
-
|
|
489
|
+
const mode = format === FormatEnum.SingleSelect ? "single-select" : "multi-select";
|
|
490
|
+
extensions2.push(createMarkdownExtensions());
|
|
491
|
+
extensions2.push(tagPicker({
|
|
2041
492
|
mode,
|
|
2042
|
-
|
|
493
|
+
keymap: false,
|
|
2043
494
|
onSearch: (text, selectedIds) => {
|
|
2044
495
|
return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
|
|
2045
496
|
id: option.id,
|
|
@@ -2061,135 +512,381 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
|
|
|
2061
512
|
}
|
|
2062
513
|
}));
|
|
2063
514
|
}
|
|
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
|
-
|
|
515
|
+
if (model && editing) {
|
|
516
|
+
extensions2.push(EditorView.updateListener.of(debounce((update) => {
|
|
517
|
+
const content = update.state.doc.toString();
|
|
518
|
+
const cell = parseCellIndex2(editing.index);
|
|
519
|
+
void model.validateCellData(cell, content).then((result) => {
|
|
520
|
+
if (result.valid) {
|
|
521
|
+
setValidationError(null);
|
|
522
|
+
} else {
|
|
523
|
+
setValidationError(result.error);
|
|
524
|
+
setValidationVariant("error");
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
}, 10)));
|
|
528
|
+
}
|
|
529
|
+
return extensions2;
|
|
530
|
+
}, [
|
|
531
|
+
model,
|
|
532
|
+
modals,
|
|
533
|
+
editing,
|
|
534
|
+
fieldProjection,
|
|
535
|
+
handleClose
|
|
536
|
+
]);
|
|
537
|
+
const getCellContent = useCallback2(() => {
|
|
538
|
+
if (model && editing) {
|
|
539
|
+
const cell = parseCellIndex2(editing.index);
|
|
540
|
+
const { col } = cell;
|
|
541
|
+
const field = model.projection.fields[col];
|
|
542
|
+
const fieldProjection2 = model.projection.getFieldProjection(field.id);
|
|
543
|
+
if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
|
|
544
|
+
const value2 = model.getCellData(cell);
|
|
545
|
+
if (value2 !== void 0) {
|
|
546
|
+
const options = fieldProjection2.props.options || [];
|
|
547
|
+
if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
|
|
548
|
+
const tagItems = value2.split(",").map((id) => {
|
|
549
|
+
const option = options.find((o) => o.id === id);
|
|
550
|
+
if (option) {
|
|
551
|
+
return {
|
|
552
|
+
id,
|
|
553
|
+
label: option.title,
|
|
554
|
+
hue: option.color
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
return void 0;
|
|
558
|
+
}).filter((item) => item !== void 0);
|
|
559
|
+
return createLinks(tagItems);
|
|
560
|
+
} else {
|
|
561
|
+
const option = options.find((o) => o.id === value2);
|
|
562
|
+
if (option) {
|
|
563
|
+
const tagItem = {
|
|
564
|
+
id: value2,
|
|
565
|
+
label: option.title,
|
|
566
|
+
hue: option.color
|
|
567
|
+
};
|
|
568
|
+
return createLinks([
|
|
569
|
+
tagItem
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return "";
|
|
575
|
+
}
|
|
576
|
+
const value = model.getCellData(cell);
|
|
577
|
+
return value !== void 0 ? String(value) : "";
|
|
578
|
+
}
|
|
579
|
+
}, [
|
|
580
|
+
model,
|
|
581
|
+
editing
|
|
582
|
+
]);
|
|
583
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
|
|
584
|
+
validationError,
|
|
585
|
+
variant: validationVariant,
|
|
586
|
+
__gridScope
|
|
587
|
+
}), /* @__PURE__ */ React3.createElement(GridCellEditor, {
|
|
588
|
+
extensions,
|
|
589
|
+
getCellContent,
|
|
590
|
+
onBlur: handleBlur,
|
|
591
|
+
slots: editorSlots
|
|
592
|
+
}));
|
|
593
|
+
} finally {
|
|
594
|
+
_effect.f();
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
var determineNavigationAxis = ({ key }) => {
|
|
598
|
+
switch (key) {
|
|
599
|
+
case "ArrowUp":
|
|
600
|
+
case "ArrowDown":
|
|
601
|
+
case "Enter": {
|
|
602
|
+
return "row";
|
|
603
|
+
}
|
|
604
|
+
case "ArrowLeft":
|
|
605
|
+
case "ArrowRight":
|
|
606
|
+
case "Tab":
|
|
607
|
+
return "col";
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
var determineNavigationDelta = ({ key, shift }) => {
|
|
611
|
+
switch (key) {
|
|
612
|
+
case "ArrowUp":
|
|
613
|
+
case "ArrowLeft":
|
|
614
|
+
return -1;
|
|
615
|
+
case "ArrowDown":
|
|
616
|
+
case "ArrowRight":
|
|
617
|
+
return 1;
|
|
618
|
+
}
|
|
619
|
+
return shift ? -1 : 1;
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// src/components/Table/ColumnActionsMenu.tsx
|
|
623
|
+
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
624
|
+
import React4 from "react";
|
|
625
|
+
import { DropdownMenu, useTranslation } from "@dxos/react-ui";
|
|
626
|
+
var ColumnActionsMenu = ({ model, modals }) => {
|
|
627
|
+
var _effect = _useSignals4();
|
|
628
|
+
try {
|
|
629
|
+
const { t } = useTranslation(translationKey);
|
|
630
|
+
const state = modals.state.value;
|
|
631
|
+
if (state?.type !== "column") {
|
|
632
|
+
return null;
|
|
633
|
+
}
|
|
634
|
+
const currentSort = model.sorting?.sorting;
|
|
635
|
+
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
636
|
+
return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
|
|
637
|
+
modal: false,
|
|
638
|
+
open: true,
|
|
639
|
+
onOpenChange: modals.close
|
|
640
|
+
}, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
|
|
641
|
+
virtualRef: modals.trigger
|
|
642
|
+
}), /* @__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, {
|
|
643
|
+
"data-testid": "column-sort-descending",
|
|
644
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "desc")
|
|
645
|
+
}, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
646
|
+
"data-testid": "column-sort-ascending",
|
|
647
|
+
onClick: () => model.sorting?.setSort(state.fieldId, "asc")
|
|
648
|
+
}, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
649
|
+
"data-testid": "column-clear-sort",
|
|
650
|
+
onClick: () => model.sorting?.clearSort()
|
|
651
|
+
}, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
652
|
+
"data-testid": "column-delete",
|
|
653
|
+
onClick: () => model.deleteColumn(state.fieldId)
|
|
654
|
+
}, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
|
|
655
|
+
"data-testid": "column-settings",
|
|
656
|
+
onClick: () => modals.openColumnSettings()
|
|
657
|
+
}, t("column action settings"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
|
|
658
|
+
} finally {
|
|
659
|
+
_effect.f();
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
// src/components/Table/ColumnSettings.tsx
|
|
664
|
+
import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
|
|
665
|
+
import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
666
|
+
import { Popover as Popover2 } from "@dxos/react-ui";
|
|
667
|
+
import { FieldEditor } from "@dxos/react-ui-form";
|
|
668
|
+
var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
|
|
669
|
+
var _effect = _useSignals5();
|
|
670
|
+
try {
|
|
671
|
+
const [newField, setNewField] = useState3();
|
|
672
|
+
const state = modals.state.value;
|
|
673
|
+
useEffect2(() => {
|
|
674
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
|
|
675
|
+
setNewField(model.projection.createFieldProjection());
|
|
676
|
+
requestAnimationFrame(() => {
|
|
677
|
+
onNewColumn();
|
|
678
|
+
});
|
|
679
|
+
} else {
|
|
680
|
+
setNewField(void 0);
|
|
681
|
+
}
|
|
682
|
+
}, [
|
|
683
|
+
model?.projection,
|
|
684
|
+
state
|
|
685
|
+
]);
|
|
686
|
+
const existingField = useMemo3(() => {
|
|
687
|
+
if (state?.type === "columnSettings") {
|
|
688
|
+
const { mode } = state;
|
|
689
|
+
if (mode.type === "edit") {
|
|
690
|
+
return model?.projection?.fields.find((f) => f.id === mode.fieldId);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return void 0;
|
|
694
|
+
}, [
|
|
695
|
+
model?.projection?.fields,
|
|
696
|
+
state
|
|
697
|
+
]);
|
|
698
|
+
const field = existingField ?? newField;
|
|
699
|
+
const handleSave = useCallback3(() => {
|
|
700
|
+
modals.close();
|
|
701
|
+
}, [
|
|
702
|
+
modals
|
|
703
|
+
]);
|
|
704
|
+
const handleCancel = useCallback3(() => {
|
|
705
|
+
if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
|
|
706
|
+
model?.projection.deleteFieldProjection(newField.id);
|
|
707
|
+
}
|
|
708
|
+
}, [
|
|
709
|
+
model?.projection,
|
|
710
|
+
state,
|
|
711
|
+
newField
|
|
712
|
+
]);
|
|
713
|
+
if (!model?.projection || !field) {
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
return /* @__PURE__ */ React5.createElement(Popover2.Root, {
|
|
717
|
+
modal: false,
|
|
718
|
+
open: state?.type === "columnSettings"
|
|
719
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
|
|
720
|
+
virtualRef: modals.trigger
|
|
721
|
+
}), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
|
|
722
|
+
classNames: "md:is-64"
|
|
723
|
+
}, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
|
|
724
|
+
projection: model.projection,
|
|
725
|
+
field,
|
|
726
|
+
registry,
|
|
727
|
+
onSave: handleSave,
|
|
728
|
+
onCancel: handleCancel
|
|
729
|
+
})), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
|
|
730
|
+
} finally {
|
|
731
|
+
_effect.f();
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// src/components/Table/CreateRefPanel.tsx
|
|
736
|
+
import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
|
|
737
|
+
import { Schema } from "effect";
|
|
738
|
+
import React6, { useCallback as useCallback4, useMemo as useMemo4 } from "react";
|
|
739
|
+
import { Type } from "@dxos/echo";
|
|
740
|
+
import { live } from "@dxos/live-object";
|
|
741
|
+
import { useClient } from "@dxos/react-client";
|
|
742
|
+
import { getSpace as getSpace2 } from "@dxos/react-client/echo";
|
|
743
|
+
import { Popover as Popover3 } from "@dxos/react-ui";
|
|
744
|
+
import { Form as Form2 } from "@dxos/react-ui-form";
|
|
745
|
+
import { useGridContext as useGridContext4 } from "@dxos/react-ui-grid";
|
|
746
|
+
var CreateRefPanel = ({ model, modals, __gridScope }) => {
|
|
747
|
+
var _effect = _useSignals6();
|
|
748
|
+
try {
|
|
749
|
+
const { id: gridId } = useGridContext4("TableCellEditor", __gridScope);
|
|
750
|
+
const client = useClient();
|
|
751
|
+
const space = model && getSpace2(model?.view);
|
|
752
|
+
const state = modals.state.value;
|
|
753
|
+
const getSchema = useCallback4(() => {
|
|
754
|
+
if (!space || state?.type !== "createRefPanel") {
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
const staticSchema = client.graph.schemaRegistry.schemas.find((schema3) => Type.getTypename(schema3) === state.typename);
|
|
758
|
+
if (staticSchema) {
|
|
759
|
+
return staticSchema;
|
|
760
|
+
}
|
|
761
|
+
const [schema2] = space.db.schemaRegistry.query({
|
|
762
|
+
typename: state.typename
|
|
763
|
+
}).runSync();
|
|
764
|
+
return schema2;
|
|
765
|
+
}, [
|
|
766
|
+
space,
|
|
767
|
+
state
|
|
768
|
+
]);
|
|
769
|
+
const schema = useMemo4(() => {
|
|
770
|
+
const schema2 = getSchema();
|
|
771
|
+
if (!schema2) {
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
const omit = Schema.omit("id");
|
|
775
|
+
return omit(schema2);
|
|
776
|
+
}, [
|
|
777
|
+
getSchema
|
|
778
|
+
]);
|
|
779
|
+
const handleSave = useCallback4((values) => {
|
|
780
|
+
if (!model || !space || state?.type !== "createRefPanel") {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
const schema2 = getSchema();
|
|
784
|
+
if (schema2) {
|
|
785
|
+
const obj = space.db.add(live(schema2, values));
|
|
786
|
+
state.onCreate?.(obj);
|
|
2092
787
|
}
|
|
2093
|
-
|
|
788
|
+
void modals.close();
|
|
2094
789
|
}, [
|
|
2095
790
|
model,
|
|
2096
791
|
modals,
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
handleClose,
|
|
2100
|
-
themeMode
|
|
792
|
+
space,
|
|
793
|
+
state
|
|
2101
794
|
]);
|
|
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) : "";
|
|
795
|
+
const handleCancel = useCallback4(() => {
|
|
796
|
+
if (model) {
|
|
797
|
+
modals.close();
|
|
2143
798
|
}
|
|
2144
799
|
}, [
|
|
2145
|
-
|
|
2146
|
-
editing
|
|
800
|
+
modals
|
|
2147
801
|
]);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
802
|
+
if (!model?.projection) {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
return /* @__PURE__ */ React6.createElement(Popover3.Root, {
|
|
806
|
+
modal: false,
|
|
807
|
+
open: state?.type === "createRefPanel" && !!schema,
|
|
808
|
+
onOpenChange: (nextOpen) => {
|
|
809
|
+
if (model && !nextOpen) {
|
|
810
|
+
return modals.close();
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
|
|
814
|
+
virtualRef: modals.trigger
|
|
815
|
+
}), /* @__PURE__ */ React6.createElement(Popover3.Portal, null, /* @__PURE__ */ React6.createElement(Popover3.Content, {
|
|
816
|
+
classNames: "md:is-64",
|
|
817
|
+
"data-grid": gridId
|
|
818
|
+
}, /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React6.createElement(Form2, {
|
|
819
|
+
schema,
|
|
820
|
+
values: state.initialValues ?? {},
|
|
821
|
+
onSave: handleSave,
|
|
822
|
+
onCancel: handleCancel
|
|
823
|
+
})), /* @__PURE__ */ React6.createElement(Popover3.Arrow, null))));
|
|
2156
824
|
} finally {
|
|
2157
825
|
_effect.f();
|
|
2158
826
|
}
|
|
2159
827
|
};
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
828
|
+
|
|
829
|
+
// src/components/Table/RowActionsMenu.tsx
|
|
830
|
+
import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
|
|
831
|
+
import React7 from "react";
|
|
832
|
+
import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
833
|
+
var RowActionsMenu = ({ model, modals }) => {
|
|
834
|
+
var _effect = _useSignals7();
|
|
835
|
+
try {
|
|
836
|
+
const { t } = useTranslation2(translationKey);
|
|
837
|
+
const hasSelection = model.selection.hasSelection.value;
|
|
838
|
+
const state = modals.state.value;
|
|
839
|
+
if (state?.type !== "row") {
|
|
840
|
+
return null;
|
|
2166
841
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
842
|
+
return /* @__PURE__ */ React7.createElement(DropdownMenu2.Root, {
|
|
843
|
+
modal: false,
|
|
844
|
+
open: true,
|
|
845
|
+
onOpenChange: modals.close
|
|
846
|
+
}, /* @__PURE__ */ React7.createElement(DropdownMenu2.VirtualTrigger, {
|
|
847
|
+
virtualRef: modals.trigger
|
|
848
|
+
}), /* @__PURE__ */ React7.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React7.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
849
|
+
"data-testid": "row-menu-delete",
|
|
850
|
+
onClick: () => model.deleteRow(state.rowIndex)
|
|
851
|
+
}, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
|
|
852
|
+
key: action.id,
|
|
853
|
+
"data-testid": `row-action-${action.id}`,
|
|
854
|
+
onClick: () => {
|
|
855
|
+
modals.close();
|
|
856
|
+
model.handleRowAction(action.id, state.rowIndex);
|
|
857
|
+
}
|
|
858
|
+
}, toLocalizedString(action.label, t)))), /* @__PURE__ */ React7.createElement(DropdownMenu2.Arrow, null)));
|
|
859
|
+
} finally {
|
|
860
|
+
_effect.f();
|
|
2171
861
|
}
|
|
2172
862
|
};
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
case "ArrowRight":
|
|
2180
|
-
return 1;
|
|
863
|
+
|
|
864
|
+
// src/components/Table/Table.tsx
|
|
865
|
+
var columnDefault = {
|
|
866
|
+
grid: {
|
|
867
|
+
minSize: 80,
|
|
868
|
+
maxSize: 640
|
|
2181
869
|
}
|
|
2182
|
-
return shift ? -1 : 1;
|
|
2183
870
|
};
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
871
|
+
var rowDefault = {
|
|
872
|
+
frozenRowsStart: {
|
|
873
|
+
readonly: true,
|
|
874
|
+
focusUnfurl: false
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
var TableRoot = ({ children, role = "article" }) => {
|
|
2188
878
|
var _effect = _useSignals8();
|
|
2189
879
|
try {
|
|
2190
880
|
return /* @__PURE__ */ React8.createElement("div", {
|
|
2191
881
|
role: "none",
|
|
2192
|
-
className:
|
|
882
|
+
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]", [
|
|
883
|
+
"card--popover",
|
|
884
|
+
"section",
|
|
885
|
+
"card--extrinsic"
|
|
886
|
+
].includes(role) && "overflow-hidden", [
|
|
887
|
+
"article",
|
|
888
|
+
"slide"
|
|
889
|
+
].includes(role) && "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:bs-0")
|
|
2193
890
|
}, children);
|
|
2194
891
|
} finally {
|
|
2195
892
|
_effect.f();
|
|
@@ -2198,19 +895,27 @@ var TableRoot = ({ children, role }) => {
|
|
|
2198
895
|
var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
|
|
2199
896
|
var _effect = _useSignals8();
|
|
2200
897
|
try {
|
|
2201
|
-
const [dxGrid, setDxGrid] =
|
|
898
|
+
const [dxGrid, setDxGrid] = useState4(null);
|
|
2202
899
|
const { hasAttention } = useAttention(model?.id ?? "table");
|
|
2203
|
-
const { t } = useTranslation3(translationKey);
|
|
2204
900
|
const modals = useMemo5(() => new ModalController(), []);
|
|
901
|
+
const draftRowCount = model?.getDraftRowCount() ?? 0;
|
|
902
|
+
const handleSave = useCallback5(() => {
|
|
903
|
+
dxGrid?.updateCells(true);
|
|
904
|
+
dxGrid?.requestUpdate();
|
|
905
|
+
}, [
|
|
906
|
+
dxGrid
|
|
907
|
+
]);
|
|
2205
908
|
const frozen = useMemo5(() => {
|
|
2206
909
|
const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
|
|
2207
910
|
return {
|
|
2208
911
|
frozenRowsStart: 1,
|
|
912
|
+
frozenRowsEnd: Math.max(1, draftRowCount),
|
|
2209
913
|
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
2210
914
|
frozenColsEnd: noActionColumn ? 0 : 1
|
|
2211
915
|
};
|
|
2212
916
|
}, [
|
|
2213
|
-
model
|
|
917
|
+
model,
|
|
918
|
+
draftRowCount
|
|
2214
919
|
]);
|
|
2215
920
|
const getCells = useCallback5((range, plane) => presentation?.getCells(range, plane) ?? {}, [
|
|
2216
921
|
presentation
|
|
@@ -2225,6 +930,30 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2225
930
|
dxGrid,
|
|
2226
931
|
getCells
|
|
2227
932
|
]);
|
|
933
|
+
const handleInsertRowResult = useCallback5((insertResult) => {
|
|
934
|
+
if (insertResult === "draft") {
|
|
935
|
+
requestAnimationFrame(() => {
|
|
936
|
+
dxGrid?.setFocus({
|
|
937
|
+
plane: "frozenRowsEnd",
|
|
938
|
+
col: 0,
|
|
939
|
+
row: 0
|
|
940
|
+
});
|
|
941
|
+
dxGrid?.refocus();
|
|
942
|
+
});
|
|
943
|
+
} else {
|
|
944
|
+
requestAnimationFrame(() => {
|
|
945
|
+
dxGrid?.setFocus({
|
|
946
|
+
plane: "grid",
|
|
947
|
+
col: 0,
|
|
948
|
+
row: model ? model.getRowCount() - 1 : 0
|
|
949
|
+
});
|
|
950
|
+
dxGrid?.refocus();
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
}, [
|
|
954
|
+
model,
|
|
955
|
+
dxGrid
|
|
956
|
+
]);
|
|
2228
957
|
useImperativeHandle(forwardedRef, () => {
|
|
2229
958
|
if (!presentation || !dxGrid) {
|
|
2230
959
|
return {};
|
|
@@ -2232,23 +961,43 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2232
961
|
return {
|
|
2233
962
|
update: (cell) => {
|
|
2234
963
|
if (cell) {
|
|
2235
|
-
dxGrid.updateIfWithinBounds(cell);
|
|
964
|
+
dxGrid.updateIfWithinBounds(cell, true);
|
|
2236
965
|
} else {
|
|
2237
966
|
dxGrid.updateCells(true);
|
|
2238
967
|
dxGrid.requestUpdate();
|
|
2239
968
|
}
|
|
2240
|
-
}
|
|
969
|
+
},
|
|
970
|
+
handleInsertRowResult
|
|
2241
971
|
};
|
|
2242
972
|
}, [
|
|
2243
973
|
presentation,
|
|
974
|
+
dxGrid,
|
|
975
|
+
model
|
|
976
|
+
]);
|
|
977
|
+
const handleSaveDraftRow = useCallback5((rowIndex = 0) => {
|
|
978
|
+
if (model && dxGrid) {
|
|
979
|
+
const didCommitSuccessfully = model.commitDraftRow(rowIndex);
|
|
980
|
+
if (didCommitSuccessfully) {
|
|
981
|
+
requestAnimationFrame(() => {
|
|
982
|
+
dxGrid.scrollToEndRow();
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}, [
|
|
987
|
+
model,
|
|
2244
988
|
dxGrid
|
|
2245
989
|
]);
|
|
2246
990
|
const handleGridClick = useCallback5((event) => {
|
|
2247
|
-
const
|
|
2248
|
-
if (
|
|
991
|
+
const cell = closestCell(event.target);
|
|
992
|
+
if (cell) {
|
|
993
|
+
const { row: rowIndex, plane } = cell;
|
|
2249
994
|
if (onRowClick) {
|
|
2250
|
-
|
|
2251
|
-
|
|
995
|
+
if (plane === "grid") {
|
|
996
|
+
const row = model?.getRowAt(rowIndex);
|
|
997
|
+
row && onRowClick(row);
|
|
998
|
+
} else {
|
|
999
|
+
onRowClick(cell);
|
|
1000
|
+
}
|
|
2252
1001
|
}
|
|
2253
1002
|
if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
|
|
2254
1003
|
model.selection.toggleSelectionForRowIndex(rowIndex);
|
|
@@ -2283,6 +1032,10 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2283
1032
|
model?.sorting?.toggleSort(data.fieldId);
|
|
2284
1033
|
break;
|
|
2285
1034
|
}
|
|
1035
|
+
case "saveDraftRow": {
|
|
1036
|
+
handleSaveDraftRow();
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
2286
1039
|
}
|
|
2287
1040
|
return;
|
|
2288
1041
|
}
|
|
@@ -2316,31 +1069,23 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2316
1069
|
}
|
|
2317
1070
|
}, [
|
|
2318
1071
|
model,
|
|
2319
|
-
modals
|
|
2320
|
-
]);
|
|
2321
|
-
const handleFocus = useCallback5((increment, delta) => {
|
|
2322
|
-
if (dxGrid) {
|
|
2323
|
-
dxGrid.refocus(increment, delta);
|
|
2324
|
-
}
|
|
2325
|
-
}, [
|
|
1072
|
+
modals,
|
|
2326
1073
|
dxGrid
|
|
2327
1074
|
]);
|
|
2328
|
-
const
|
|
2329
|
-
if (
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
dxGrid?.refocus("row", 1);
|
|
2338
|
-
});
|
|
1075
|
+
const handleFocus = useCallback5((increment, delta, cell) => {
|
|
1076
|
+
if (dxGrid && model) {
|
|
1077
|
+
if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1) {
|
|
1078
|
+
handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
|
|
1079
|
+
} else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
|
|
1080
|
+
handleSaveDraftRow(cell.row);
|
|
1081
|
+
handleInsertRowResult(model.insertRow());
|
|
1082
|
+
} else {
|
|
1083
|
+
dxGrid.refocus(increment, delta);
|
|
2339
1084
|
}
|
|
2340
1085
|
}
|
|
2341
1086
|
}, [
|
|
2342
|
-
|
|
2343
|
-
|
|
1087
|
+
dxGrid,
|
|
1088
|
+
model
|
|
2344
1089
|
]);
|
|
2345
1090
|
const handleKeyDown = useCallback5((event) => {
|
|
2346
1091
|
if (!model?.features.dataEditable) {
|
|
@@ -2350,15 +1095,63 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2350
1095
|
if (!model || !cell) {
|
|
2351
1096
|
return;
|
|
2352
1097
|
}
|
|
1098
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1099
|
+
switch (event.key) {
|
|
1100
|
+
case "c": {
|
|
1101
|
+
try {
|
|
1102
|
+
const cellData = model.getCellData(cell);
|
|
1103
|
+
const textContent = cellData?.toString() ?? "";
|
|
1104
|
+
void navigator.clipboard.writeText(textContent);
|
|
1105
|
+
event.preventDefault();
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
console.warn("Failed to copy cell content:", error);
|
|
1108
|
+
}
|
|
1109
|
+
break;
|
|
1110
|
+
}
|
|
1111
|
+
case "v": {
|
|
1112
|
+
event.preventDefault();
|
|
1113
|
+
void navigator.clipboard.readText().then((clipboardText) => {
|
|
1114
|
+
try {
|
|
1115
|
+
model.setCellData(cell, clipboardText);
|
|
1116
|
+
handleSave();
|
|
1117
|
+
} catch {
|
|
1118
|
+
const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
|
|
1119
|
+
if (cellElement) {
|
|
1120
|
+
const rect = cellElement.getBoundingClientRect();
|
|
1121
|
+
const editRequest = new DxEditRequest({
|
|
1122
|
+
cellIndex: `${cell.plane},${cell.col},${cell.row}`,
|
|
1123
|
+
cellBox: {
|
|
1124
|
+
insetInlineStart: rect.left,
|
|
1125
|
+
insetBlockStart: rect.top,
|
|
1126
|
+
inlineSize: rect.width,
|
|
1127
|
+
blockSize: rect.height
|
|
1128
|
+
},
|
|
1129
|
+
cellElement,
|
|
1130
|
+
initialContent: clipboardText
|
|
1131
|
+
});
|
|
1132
|
+
cellElement.dispatchEvent(editRequest);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
break;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
2353
1140
|
switch (event.key) {
|
|
2354
1141
|
case "Backspace":
|
|
2355
1142
|
case "Delete": {
|
|
2356
|
-
|
|
1143
|
+
try {
|
|
1144
|
+
model.setCellData(cell, void 0);
|
|
1145
|
+
event.preventDefault();
|
|
1146
|
+
} catch {
|
|
1147
|
+
}
|
|
2357
1148
|
break;
|
|
2358
1149
|
}
|
|
2359
1150
|
}
|
|
2360
1151
|
}, [
|
|
2361
|
-
model
|
|
1152
|
+
model,
|
|
1153
|
+
dxGrid,
|
|
1154
|
+
handleSave
|
|
2362
1155
|
]);
|
|
2363
1156
|
const handleAxisResize = useCallback5((event) => {
|
|
2364
1157
|
if (event.axis === "col") {
|
|
@@ -2385,54 +1178,6 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2385
1178
|
model,
|
|
2386
1179
|
dxGrid
|
|
2387
1180
|
]);
|
|
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
1181
|
if (!model || !modals) {
|
|
2437
1182
|
return /* @__PURE__ */ React8.createElement("span", {
|
|
2438
1183
|
role: "none",
|
|
@@ -2445,20 +1190,21 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
|
|
|
2445
1190
|
model,
|
|
2446
1191
|
modals,
|
|
2447
1192
|
schema,
|
|
2448
|
-
onEnter: handleEnter,
|
|
2449
1193
|
onFocus: handleFocus,
|
|
2450
|
-
|
|
1194
|
+
onSave: handleSave,
|
|
1195
|
+
client
|
|
2451
1196
|
}), /* @__PURE__ */ React8.createElement(Grid.Content, {
|
|
2452
|
-
className:
|
|
1197
|
+
className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
|
|
2453
1198
|
frozen,
|
|
2454
|
-
// getCells={getCells}
|
|
2455
1199
|
columns: model.columnMeta.value,
|
|
1200
|
+
columnDefault,
|
|
1201
|
+
rowDefault,
|
|
2456
1202
|
limitRows: model.getRowCount() ?? 0,
|
|
2457
|
-
limitColumns: model.
|
|
1203
|
+
limitColumns: model.projection.fields.length,
|
|
2458
1204
|
overscroll: "trap",
|
|
2459
1205
|
onAxisResize: handleAxisResize,
|
|
2460
1206
|
onClick: handleGridClick,
|
|
2461
|
-
|
|
1207
|
+
onKeyDownCapture: handleKeyDown,
|
|
2462
1208
|
onWheelCapture: handleWheel,
|
|
2463
1209
|
ref: setDxGrid
|
|
2464
1210
|
}), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
|
|
@@ -2484,116 +1230,33 @@ var Table = {
|
|
|
2484
1230
|
Main: TableMain
|
|
2485
1231
|
};
|
|
2486
1232
|
|
|
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
|
|
1233
|
+
// src/components/Table/DynamicTable.tsx
|
|
2494
1234
|
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 }) => {
|
|
1235
|
+
import React9, { useCallback as useCallback6, useMemo as useMemo6, useRef as useRef3 } from "react";
|
|
1236
|
+
import { useDefaultValue } from "@dxos/react-ui";
|
|
1237
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
1238
|
+
var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
|
|
2502
1239
|
var _effect = _useSignals9();
|
|
2503
1240
|
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
|
-
}, [
|
|
1241
|
+
const { typename, jsonSchema } = useMemo6(() => getBaseSchema({
|
|
1242
|
+
typename: name,
|
|
1243
|
+
properties,
|
|
1244
|
+
jsonSchema: _jsonSchema,
|
|
1245
|
+
schema
|
|
1246
|
+
}), [
|
|
2593
1247
|
name,
|
|
2594
1248
|
properties,
|
|
2595
|
-
|
|
2596
|
-
|
|
1249
|
+
_jsonSchema,
|
|
1250
|
+
schema
|
|
1251
|
+
]);
|
|
1252
|
+
const { projection, view } = useMemo6(() => makeDynamicTable({
|
|
1253
|
+
typename,
|
|
1254
|
+
jsonSchema,
|
|
1255
|
+
properties
|
|
1256
|
+
}), [
|
|
1257
|
+
typename,
|
|
1258
|
+
jsonSchema,
|
|
1259
|
+
properties
|
|
2597
1260
|
]);
|
|
2598
1261
|
const tableRef = useRef3(null);
|
|
2599
1262
|
const handleCellUpdate = useCallback6((cell) => {
|
|
@@ -2609,8 +1272,9 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2609
1272
|
dataEditable: false
|
|
2610
1273
|
}));
|
|
2611
1274
|
const model = useTableModel({
|
|
2612
|
-
table,
|
|
2613
1275
|
rows,
|
|
1276
|
+
view,
|
|
1277
|
+
schema: jsonSchema,
|
|
2614
1278
|
projection,
|
|
2615
1279
|
features,
|
|
2616
1280
|
rowActions,
|
|
@@ -2627,7 +1291,7 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2627
1291
|
]);
|
|
2628
1292
|
return /* @__PURE__ */ React9.createElement("div", {
|
|
2629
1293
|
role: "none",
|
|
2630
|
-
className:
|
|
1294
|
+
className: mx2("is-full bs-full grow grid", classNames)
|
|
2631
1295
|
}, /* @__PURE__ */ React9.createElement("div", {
|
|
2632
1296
|
role: "none",
|
|
2633
1297
|
className: "grid min-bs-0 overflow-hidden"
|
|
@@ -2643,12 +1307,12 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
|
|
|
2643
1307
|
}
|
|
2644
1308
|
};
|
|
2645
1309
|
|
|
2646
|
-
//
|
|
2647
|
-
import { useSignals as
|
|
1310
|
+
// src/components/TableToolbar/TableToolbar.tsx
|
|
1311
|
+
import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
|
|
2648
1312
|
import { Rx } from "@effect-rx/rx-react";
|
|
2649
1313
|
import React10, { useMemo as useMemo7 } from "react";
|
|
2650
|
-
import { live as
|
|
2651
|
-
import {
|
|
1314
|
+
import { live as live2 } from "@dxos/live-object";
|
|
1315
|
+
import { MenuProvider, ToolbarMenu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
|
|
2652
1316
|
import { rxFromSignal } from "@dxos/react-ui-menu";
|
|
2653
1317
|
var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
|
|
2654
1318
|
const add = createMenuAction("add-row", onAdd, {
|
|
@@ -2696,9 +1360,9 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
|
|
|
2696
1360
|
};
|
|
2697
1361
|
});
|
|
2698
1362
|
var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
|
|
2699
|
-
var _effect =
|
|
1363
|
+
var _effect = _useSignals10();
|
|
2700
1364
|
try {
|
|
2701
|
-
const state = useMemo7(() =>
|
|
1365
|
+
const state = useMemo7(() => live2({
|
|
2702
1366
|
viewDirty
|
|
2703
1367
|
}), []);
|
|
2704
1368
|
const actionsCreator = useMemo7(() => createTableToolbarActions({
|
|
@@ -2733,18 +1397,16 @@ export {
|
|
|
2733
1397
|
Table,
|
|
2734
1398
|
TableModel,
|
|
2735
1399
|
TablePresentation,
|
|
2736
|
-
TableSchema,
|
|
2737
1400
|
TableToolbar,
|
|
2738
|
-
TableType,
|
|
2739
1401
|
cellClassesForRowSelection,
|
|
2740
1402
|
getBaseSchema,
|
|
2741
|
-
initializeTable,
|
|
2742
1403
|
makeDynamicTable,
|
|
2743
1404
|
narrowSchema,
|
|
2744
1405
|
tableButtons,
|
|
2745
1406
|
tableControls,
|
|
2746
1407
|
touch,
|
|
2747
|
-
|
|
1408
|
+
translations,
|
|
1409
|
+
useAddRow,
|
|
2748
1410
|
useTableModel
|
|
2749
1411
|
};
|
|
2750
1412
|
//# sourceMappingURL=index.mjs.map
|