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