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