@dxos/react-ui-table 0.8.4-main.2e9d522 → 0.8.4-main.5ea62a8

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.
Files changed (119) hide show
  1. package/dist/lib/browser/chunk-63UUF4IG.mjs +66 -0
  2. package/dist/lib/browser/chunk-63UUF4IG.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-RQYXNWWN.mjs} +531 -460
  4. package/dist/lib/browser/chunk-RQYXNWWN.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +691 -625
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +6 -4
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types/index.mjs +3 -3
  11. package/dist/lib/node-esm/chunk-K734DJB7.mjs +67 -0
  12. package/dist/lib/node-esm/chunk-K734DJB7.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-QNDUGIS7.mjs} +531 -460
  14. package/dist/lib/node-esm/chunk-QNDUGIS7.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +691 -625
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +6 -4
  19. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/types/index.mjs +3 -3
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -1
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -1
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/CreateRefPanel.d.ts +1 -1
  26. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  28. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +50 -2
  29. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  30. package/dist/types/src/components/Table/Relations.stories.d.ts +44 -0
  31. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  32. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  33. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  34. package/dist/types/src/components/Table/Table.d.ts +3 -2
  35. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  36. package/dist/types/src/components/Table/Table.stories.d.ts +42 -3
  37. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  39. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +7 -3
  40. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  41. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -15
  42. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  43. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -3
  44. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useAddRow.d.ts +2 -1
  47. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  48. package/dist/types/src/hooks/useTableModel.d.ts +1 -1
  49. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  50. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  51. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  52. package/dist/types/src/model/table-model.d.ts +7 -5
  53. package/dist/types/src/model/table-model.d.ts.map +1 -1
  54. package/dist/types/src/model/table-presentation.d.ts +2 -1
  55. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  56. package/dist/types/src/model/table-sorting.d.ts +2 -2
  57. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  58. package/dist/types/src/testing/useTestTableModel.d.ts +4 -9
  59. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  60. package/dist/types/src/translations.d.ts +2 -2
  61. package/dist/types/src/types/index.d.ts +1 -1
  62. package/dist/types/src/types/index.d.ts.map +1 -1
  63. package/dist/types/src/types/schema.d.ts +24 -4
  64. package/dist/types/src/types/schema.d.ts.map +1 -1
  65. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  66. package/dist/types/src/util/index.d.ts +0 -1
  67. package/dist/types/src/util/index.d.ts.map +1 -1
  68. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  69. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  70. package/dist/types/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +44 -39
  72. package/src/components/Table/ColumnActionsMenu.tsx +1 -1
  73. package/src/components/Table/ColumnSettings.tsx +1 -1
  74. package/src/components/Table/CreateRefPanel.tsx +25 -8
  75. package/src/components/Table/DynamicTable.stories.tsx +7 -4
  76. package/src/components/Table/DynamicTable.tsx +4 -3
  77. package/src/components/Table/{relations.stories.tsx → Relations.stories.tsx} +40 -23
  78. package/src/components/Table/RowActionsMenu.tsx +3 -3
  79. package/src/components/Table/Table.stories.tsx +34 -23
  80. package/src/components/Table/Table.tsx +138 -112
  81. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  82. package/src/components/TableCellEditor/FormCellEditor.tsx +143 -42
  83. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +11 -23
  84. package/src/components/TableCellEditor/TableCellEditor.tsx +64 -119
  85. package/src/components/TableToolbar/TableToolbar.tsx +2 -2
  86. package/src/components/testing.ts +1 -1
  87. package/src/hooks/useAddRow.ts +6 -4
  88. package/src/hooks/useTableModel.ts +1 -1
  89. package/src/model/modal-controller.ts +1 -1
  90. package/src/model/selection-model.ts +3 -2
  91. package/src/model/table-model.test.ts +3 -4
  92. package/src/model/table-model.ts +28 -23
  93. package/src/model/table-presentation.test.ts +4 -4
  94. package/src/model/table-presentation.ts +72 -30
  95. package/src/model/table-sorting.ts +3 -3
  96. package/src/playwright/smoke.spec.ts +129 -37
  97. package/src/testing/useTestTableModel.ts +4 -3
  98. package/src/translations.ts +2 -2
  99. package/src/types/index.ts +1 -1
  100. package/src/types/schema.ts +62 -5
  101. package/src/util/dynamic-table.ts +5 -5
  102. package/src/util/index.ts +0 -1
  103. package/src/util/schema.ts +1 -1
  104. package/src/util/table-buttons.ts +4 -3
  105. package/src/util/table-controls.ts +4 -1
  106. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
  107. package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
  108. package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
  109. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
  110. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
  111. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
  112. package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
  113. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
  114. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  115. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  116. package/dist/types/src/util/table.d.ts +0 -11
  117. package/dist/types/src/util/table.d.ts.map +0 -1
  118. package/src/components/TableCellEditor/extension.ts +0 -61
  119. package/src/util/table.ts +0 -49
@@ -7,7 +7,6 @@ import {
7
7
  TableModel,
8
8
  TablePresentation,
9
9
  cellClassesForRowSelection,
10
- createTable,
11
10
  getBaseSchema,
12
11
  makeDynamicTable,
13
12
  narrowSchema,
@@ -16,8 +15,8 @@ import {
16
15
  touch,
17
16
  useAddRow,
18
17
  useTableModel
19
- } from "./chunk-5XLSHLOG.mjs";
20
- import "./chunk-L2LSB6KV.mjs";
18
+ } from "./chunk-RQYXNWWN.mjs";
19
+ import "./chunk-63UUF4IG.mjs";
21
20
 
22
21
  // src/translations.ts
23
22
  var translationKey = "react-ui-table";
@@ -29,8 +28,8 @@ var translations = [
29
28
  "create object label": "Create table",
30
29
  "table name placeholder": "Table name",
31
30
  "settings title": "Table settings",
32
- "table schema label": "Schema",
33
- "new schema": "New schema",
31
+ "table schema label": "Record type",
32
+ "new schema": "New record type",
34
33
  "continue label": "Continue",
35
34
  "create stack section label": "Create table",
36
35
  "add row label": "Add row",
@@ -53,270 +52,38 @@ var translations = [
53
52
 
54
53
  // src/components/Table/Table.tsx
55
54
  import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
56
- import React8, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as useState4, useMemo as useMemo5, useEffect as useEffect4 } from "react";
57
- import { Filter } from "@dxos/echo";
58
- import { getValue } from "@dxos/echo-schema";
59
- import { invariant as invariant3 } from "@dxos/invariant";
60
- import { getSpace as getSpace2 } from "@dxos/react-client/echo";
61
- import { useTranslation as useTranslation3 } from "@dxos/react-ui";
55
+ import React8, { forwardRef, useCallback as useCallback5, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo5, useState as useState4 } from "react";
62
56
  import { useAttention } from "@dxos/react-ui-attention";
63
- import { closestCell, Grid, gridSeparatorInlineEnd, gridSeparatorBlockEnd } from "@dxos/react-ui-grid";
57
+ import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
58
+ import { DxEditRequest } from "@dxos/react-ui-grid";
64
59
  import { mx } from "@dxos/react-ui-theme";
65
- import { isNotFalsy, safeParseInt } from "@dxos/util";
66
-
67
- // src/components/Table/ColumnActionsMenu.tsx
68
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
69
- import React from "react";
70
- import { DropdownMenu, useTranslation } from "@dxos/react-ui";
71
- var ColumnActionsMenu = ({ model, modals }) => {
72
- var _effect = _useSignals();
73
- try {
74
- const { t } = useTranslation(translationKey);
75
- const state = modals.state.value;
76
- if (state?.type !== "column") {
77
- return null;
78
- }
79
- const currentSort = model.sorting?.sorting;
80
- const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
81
- return /* @__PURE__ */ React.createElement(DropdownMenu.Root, {
82
- modal: false,
83
- open: true,
84
- onOpenChange: modals.close
85
- }, /* @__PURE__ */ React.createElement(DropdownMenu.VirtualTrigger, {
86
- virtualRef: modals.trigger
87
- }), /* @__PURE__ */ React.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React.createElement(DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
88
- "data-testid": "column-sort-descending",
89
- onClick: () => model.sorting?.setSort(state.fieldId, "desc")
90
- }, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
91
- "data-testid": "column-sort-ascending",
92
- onClick: () => model.sorting?.setSort(state.fieldId, "asc")
93
- }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
94
- "data-testid": "column-clear-sort",
95
- onClick: () => model.sorting?.clearSort()
96
- }, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
97
- "data-testid": "column-delete",
98
- onClick: () => model.deleteColumn(state.fieldId)
99
- }, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
100
- "data-testid": "column-settings",
101
- onClick: () => modals.openColumnSettings()
102
- }, t("column action settings"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))));
103
- } finally {
104
- _effect.f();
105
- }
106
- };
107
-
108
- // src/components/Table/ColumnSettings.tsx
109
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
110
- import React2, { useCallback, useEffect, useMemo, useState } from "react";
111
- import { Popover } from "@dxos/react-ui";
112
- import { FieldEditor } from "@dxos/react-ui-form";
113
- var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
114
- var _effect = _useSignals2();
115
- try {
116
- const [newField, setNewField] = useState();
117
- const state = modals.state.value;
118
- useEffect(() => {
119
- if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
120
- setNewField(model.projection.createFieldProjection());
121
- requestAnimationFrame(() => {
122
- onNewColumn();
123
- });
124
- } else {
125
- setNewField(void 0);
126
- }
127
- }, [
128
- model?.projection,
129
- state
130
- ]);
131
- const existingField = useMemo(() => {
132
- if (state?.type === "columnSettings") {
133
- const { mode } = state;
134
- if (mode.type === "edit") {
135
- return model?.projection?.fields.find((f) => f.id === mode.fieldId);
136
- }
137
- }
138
- return void 0;
139
- }, [
140
- model?.projection?.fields,
141
- state
142
- ]);
143
- const field = existingField ?? newField;
144
- const handleSave = useCallback(() => {
145
- modals.close();
146
- }, [
147
- modals
148
- ]);
149
- const handleCancel = useCallback(() => {
150
- if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
151
- model?.projection.deleteFieldProjection(newField.id);
152
- }
153
- }, [
154
- model?.projection,
155
- state,
156
- newField
157
- ]);
158
- if (!model?.projection || !field) {
159
- return null;
160
- }
161
- return /* @__PURE__ */ React2.createElement(Popover.Root, {
162
- modal: false,
163
- open: state?.type === "columnSettings"
164
- }, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
165
- virtualRef: modals.trigger
166
- }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
167
- classNames: "md:is-64"
168
- }, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
169
- projection: model.projection,
170
- field,
171
- registry,
172
- onSave: handleSave,
173
- onCancel: handleCancel
174
- })), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
175
- } finally {
176
- _effect.f();
177
- }
178
- };
179
-
180
- // src/components/Table/CreateRefPanel.tsx
181
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
182
- import { Schema } from "effect";
183
- import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
184
- import { live } from "@dxos/live-object";
185
- import { getSpace } from "@dxos/react-client/echo";
186
- import { Popover as Popover2 } from "@dxos/react-ui";
187
- import { Form } from "@dxos/react-ui-form";
188
- import { useGridContext } from "@dxos/react-ui-grid";
189
- var CreateRefPanel = ({ model, modals, __gridScope }) => {
190
- var _effect = _useSignals3();
191
- try {
192
- const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
193
- const space = model && getSpace(model?.view);
194
- const state = modals.state.value;
195
- const schema = useMemo2(() => {
196
- if (!space || state?.type !== "createRefPanel") {
197
- return;
198
- }
199
- const [schema2] = space.db.schemaRegistry.query({
200
- typename: state.typename
201
- }).runSync();
202
- if (schema2) {
203
- const omit = Schema.omit("id");
204
- return omit(schema2);
205
- }
206
- }, [
207
- space,
208
- state
209
- ]);
210
- const handleSave = useCallback2((values) => {
211
- if (!model || !space || state?.type !== "createRefPanel") {
212
- return;
213
- }
214
- const [schema2] = space.db.schemaRegistry.query({
215
- typename: state.typename
216
- }).runSync();
217
- if (schema2) {
218
- const obj = space.db.add(live(schema2, values));
219
- state.onCreate?.(obj);
220
- }
221
- void modals.close();
222
- }, [
223
- modals,
224
- space,
225
- state
226
- ]);
227
- const handleCancel = useCallback2(() => {
228
- if (model) {
229
- modals.close();
230
- }
231
- }, [
232
- modals
233
- ]);
234
- if (!model?.projection) {
235
- return null;
236
- }
237
- return /* @__PURE__ */ React3.createElement(Popover2.Root, {
238
- modal: false,
239
- open: state?.type === "createRefPanel" && !!schema,
240
- onOpenChange: (nextOpen) => {
241
- if (model && !nextOpen) {
242
- return modals.close();
243
- }
244
- }
245
- }, /* @__PURE__ */ React3.createElement(Popover2.VirtualTrigger, {
246
- virtualRef: modals.trigger
247
- }), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
248
- classNames: "md:is-64",
249
- "data-grid": gridId
250
- }, /* @__PURE__ */ React3.createElement(Popover2.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
251
- schema,
252
- values: state.initialValues ?? {},
253
- onSave: handleSave,
254
- onCancel: handleCancel
255
- })), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null))));
256
- } finally {
257
- _effect.f();
258
- }
259
- };
260
-
261
- // src/components/Table/RowActionsMenu.tsx
262
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
263
- import React4 from "react";
264
- import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
265
- var RowActionsMenu = ({ model, modals }) => {
266
- var _effect = _useSignals4();
267
- try {
268
- const { t } = useTranslation2(translationKey);
269
- const hasSelection = model.selection.hasSelection.value;
270
- const state = modals.state.value;
271
- if (state?.type !== "row") {
272
- return null;
273
- }
274
- return /* @__PURE__ */ React4.createElement(DropdownMenu2.Root, {
275
- modal: false,
276
- open: true,
277
- onOpenChange: modals.close
278
- }, /* @__PURE__ */ React4.createElement(DropdownMenu2.VirtualTrigger, {
279
- virtualRef: modals.trigger
280
- }), /* @__PURE__ */ React4.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
281
- "data-testid": "row-menu-delete",
282
- onClick: () => model.deleteRow(state.rowIndex)
283
- }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
284
- key: action.id,
285
- "data-testid": `row-action-${action.id}`,
286
- onClick: () => {
287
- modals.close();
288
- model.handleRowAction(action.id, state.rowIndex);
289
- }
290
- }, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu2.Arrow, null)));
291
- } finally {
292
- _effect.f();
293
- }
294
- };
295
60
 
296
61
  // src/components/TableCellEditor/TableCellEditor.tsx
297
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
298
- import React7, { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef2, useState as useState3 } from "react";
62
+ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
63
+ import { EditorView } from "@codemirror/view";
64
+ import React3, { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
65
+ import { debounce } from "@dxos/async";
299
66
  import { FormatEnum, TypeEnum } from "@dxos/echo-schema";
300
67
  import { invariant as invariant2 } from "@dxos/invariant";
301
68
  import { useThemeContext } from "@dxos/react-ui";
302
69
  import { createMarkdownExtensions } from "@dxos/react-ui-editor";
303
- import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext4, GridCellEditor } from "@dxos/react-ui-grid";
304
- import { tagPicker, createLinks } from "@dxos/react-ui-tag-picker";
70
+ import { GridCellEditor, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
71
+ import { createLinks, tagPicker } from "@dxos/react-ui-tag-picker";
305
72
 
306
73
  // src/components/TableCellEditor/CellValidationMessage.tsx
307
- import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
308
- import React5 from "react";
309
- import { useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
74
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
75
+ import React from "react";
76
+ import { useGridContext } from "@dxos/react-ui-grid";
310
77
  var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
311
- var _effect = _useSignals5();
78
+ var _effect = _useSignals();
312
79
  try {
313
- const { editing, editBox: box } = useGridContext2("GridSheetCellEditor", __gridScope);
80
+ const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
314
81
  if (!editing || !validationError) {
315
82
  return null;
316
83
  }
317
84
  const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
318
85
  const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
319
- return /* @__PURE__ */ React5.createElement("div", {
86
+ return /* @__PURE__ */ React.createElement("div", {
320
87
  role: "none",
321
88
  className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
322
89
  style: {
@@ -335,22 +102,157 @@ var CellValidationMessage = ({ validationError, variant = "error", __gridScope }
335
102
  };
336
103
 
337
104
  // src/components/TableCellEditor/FormCellEditor.tsx
338
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
339
- import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef, useState as useState2 } from "react";
340
- import { getSnapshot } from "@dxos/echo-schema";
105
+ import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
106
+ import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
107
+ import { Filter, Obj } from "@dxos/echo";
108
+ import { Ref, getValue } from "@dxos/echo-schema";
341
109
  import { invariant } from "@dxos/invariant";
342
- import { Popover as Popover3 } from "@dxos/react-ui";
343
- import { Form as Form2 } from "@dxos/react-ui-form";
344
- import { parseCellIndex, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
345
- import { getDeep, setDeep } from "@dxos/util";
110
+ import { getSnapshot } from "@dxos/live-object";
111
+ import { getSpace } from "@dxos/react-client/echo";
112
+ import { Popover } from "@dxos/react-ui";
113
+ import { Form } from "@dxos/react-ui-form";
114
+ import { cellQuery, parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
115
+ import { getDeep, isNotFalsy, setDeep } from "@dxos/util";
346
116
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
347
- var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) => {
348
- var _effect = _useSignals6();
117
+ var createOptionLabel = [
118
+ "create new object label",
119
+ {
120
+ ns: translationKey
121
+ }
122
+ ];
123
+ var FormCellEditor = ({ fieldProjection, model, schema, onSave, client, modals, __gridScope, ...formProps }) => {
124
+ var _effect = _useSignals2();
349
125
  try {
350
- const { editing: contextEditing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
351
- const [editing, setLocalEditing] = useState2(false);
126
+ const { editing: contextEditing, setEditing, id: gridId } = useGridContext2("ArrayEditor", __gridScope);
127
+ const [editing, setLocalEditing] = useState(false);
352
128
  const anchorRef = useRef(null);
353
- useEffect2(() => {
129
+ const getSchema = useCallback((typeAnnotation) => {
130
+ const space = getSpace(model.view);
131
+ invariant(space, void 0, {
132
+ F: __dxlog_file,
133
+ L: 53,
134
+ S: void 0,
135
+ A: [
136
+ "space",
137
+ ""
138
+ ]
139
+ });
140
+ let schema2;
141
+ if (client) {
142
+ schema2 = client.graph.schemaRegistry.getSchema(typeAnnotation.typename);
143
+ }
144
+ if (!schema2) {
145
+ schema2 = space.db.schemaRegistry.getSchema(typeAnnotation.typename);
146
+ }
147
+ return {
148
+ space,
149
+ schema: schema2
150
+ };
151
+ }, [
152
+ client,
153
+ model
154
+ ]);
155
+ const handleQueryRefOptions = useCallback(async (typeAnnotation) => {
156
+ const { schema: schema2, space } = getSchema(typeAnnotation);
157
+ if (model && schema2 && space) {
158
+ const { objects } = await space.db.query(Filter.type(schema2)).run();
159
+ return objects.map((obj) => {
160
+ return {
161
+ dxn: Obj.getDXN(obj),
162
+ label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
163
+ };
164
+ }).filter(isNotFalsy);
165
+ }
166
+ return [];
167
+ }, [
168
+ client,
169
+ model
170
+ ]);
171
+ const originalRow = useMemo(() => {
172
+ if (model && contextEditing) {
173
+ const cell = parseCellIndex(contextEditing.index);
174
+ if (model.isDraftCell(cell)) {
175
+ const draftRow = model.draftRows.value[cell.row];
176
+ invariant(draftRow, void 0, {
177
+ F: __dxlog_file,
178
+ L: 94,
179
+ S: void 0,
180
+ A: [
181
+ "draftRow",
182
+ ""
183
+ ]
184
+ });
185
+ return draftRow.data;
186
+ } else {
187
+ const row = model.getRowAt(cell.row);
188
+ invariant(row, void 0, {
189
+ F: __dxlog_file,
190
+ L: 98,
191
+ S: void 0,
192
+ A: [
193
+ "row",
194
+ ""
195
+ ]
196
+ });
197
+ return row;
198
+ }
199
+ }
200
+ return void 0;
201
+ }, [
202
+ model,
203
+ contextEditing
204
+ ]);
205
+ const handleSave = useCallback((values) => {
206
+ const path = fieldProjection.field.path;
207
+ const value = getDeep(values, [
208
+ path
209
+ ]);
210
+ setDeep(originalRow, [
211
+ path
212
+ ], value);
213
+ contextEditing?.cellElement?.focus();
214
+ setEditing(null);
215
+ setLocalEditing(false);
216
+ onSave?.();
217
+ }, [
218
+ fieldProjection.field.path,
219
+ onSave,
220
+ contextEditing,
221
+ originalRow
222
+ ]);
223
+ const handleCreate = useCallback((object) => {
224
+ const ref = Ref.make(object);
225
+ const path = fieldProjection.field.path;
226
+ setDeep(originalRow, [
227
+ path
228
+ ], ref);
229
+ contextEditing?.cellElement?.focus();
230
+ setEditing(null);
231
+ setLocalEditing(false);
232
+ onSave?.();
233
+ }, [
234
+ fieldProjection.field.path,
235
+ onSave,
236
+ contextEditing,
237
+ originalRow
238
+ ]);
239
+ const handleCreateFromQuery = useCallback(async (typeAnnotation, query) => {
240
+ if (model && modals && contextEditing?.index) {
241
+ setLocalEditing(false);
242
+ modals.openCreateRef(typeAnnotation.typename, document.querySelector(cellQuery(contextEditing.index, gridId)), {
243
+ [fieldProjection.field.referencePath]: query
244
+ }, handleCreate);
245
+ }
246
+ }, [
247
+ model,
248
+ modals,
249
+ client,
250
+ contextEditing?.index,
251
+ gridId,
252
+ fieldProjection,
253
+ handleSave
254
+ ]);
255
+ useEffect(() => {
354
256
  if (contextEditing && contextEditing.cellElement) {
355
257
  anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
356
258
  setLocalEditing(true);
@@ -361,7 +263,7 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
361
263
  }, [
362
264
  contextEditing
363
265
  ]);
364
- const narrowedSchema = useMemo3(() => {
266
+ const narrowedSchema = useMemo(() => {
365
267
  if (!schema) {
366
268
  return void 0;
367
269
  }
@@ -372,49 +274,10 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
372
274
  JSON.stringify(schema),
373
275
  fieldProjection.field.path
374
276
  ]);
375
- const originalRow = useMemo3(() => {
376
- if (model && contextEditing) {
377
- const cell = parseCellIndex(contextEditing.index);
378
- const row = model.getRowAt(cell.row);
379
- invariant(row, void 0, {
380
- F: __dxlog_file,
381
- L: 55,
382
- S: void 0,
383
- A: [
384
- "row",
385
- ""
386
- ]
387
- });
388
- return row;
389
- }
390
- return void 0;
391
- }, [
392
- model,
393
- contextEditing
394
- ]);
395
- const formValues = useMemo3(() => {
396
- if (originalRow) {
397
- return getSnapshot(originalRow);
398
- }
399
- }, [
400
- originalRow
401
- ]);
402
- const handleSave = useCallback3((values) => {
403
- const path = fieldProjection.field.path;
404
- const value = getDeep(values, [
405
- path
406
- ]);
407
- setDeep(originalRow, [
408
- path
409
- ], value);
410
- setEditing(null);
411
- setLocalEditing(false);
412
- onSave?.();
413
- }, [
414
- fieldProjection.field.path,
277
+ const formValues = useMemo(() => originalRow ? getSnapshot(originalRow) : {}, [
415
278
  originalRow
416
279
  ]);
417
- const handleOpenChange = useCallback3((nextOpen) => {
280
+ const handleOpenChange = useCallback((nextOpen) => {
418
281
  if (nextOpen === false) {
419
282
  setEditing(null);
420
283
  onSave?.();
@@ -424,76 +287,38 @@ var FormCellEditor = ({ fieldProjection, model, schema, onSave, __gridScope }) =
424
287
  if (!editing) {
425
288
  return null;
426
289
  }
427
- return /* @__PURE__ */ React6.createElement(Popover3.Root, {
290
+ return /* @__PURE__ */ React2.createElement(Popover.Root, {
428
291
  open: editing,
429
292
  onOpenChange: handleOpenChange
430
- }, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
293
+ }, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
431
294
  virtualRef: anchorRef
432
- }), /* @__PURE__ */ React6.createElement(Popover3.Content, {
295
+ }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
433
296
  tabIndex: -1,
434
297
  classNames: "popover-card-width density-fine"
435
- }, /* @__PURE__ */ React6.createElement(Popover3.Arrow, null), /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, /* @__PURE__ */ React6.createElement(Form2, {
298
+ }, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form, {
299
+ autoFocus: true,
436
300
  values: formValues,
437
301
  schema: narrowedSchema,
438
- onSave: handleSave
439
- }))));
302
+ onSave: handleSave,
303
+ ...formProps,
304
+ onQueryRefOptions: handleQueryRefOptions,
305
+ onCreateFromQuery: handleCreateFromQuery,
306
+ createOptionIcon: "ph--plus--regular",
307
+ createOptionLabel
308
+ })))));
440
309
  } finally {
441
310
  _effect.f();
442
311
  }
443
312
  };
444
313
 
445
- // src/components/TableCellEditor/extension.ts
446
- import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
447
- import { EditorView } from "@codemirror/view";
448
- var completion = ({ debug, onQuery, onMatch }) => {
449
- return [
450
- EditorView.theme({
451
- ".cm-completionDialog": {
452
- width: "var(--dx-gridCellWidth)"
453
- }
454
- }),
455
- autocompletion({
456
- icons: false,
457
- activateOnTyping: true,
458
- closeOnBlur: !debug,
459
- override: [
460
- async (context) => {
461
- const text = context.state.doc.toString();
462
- return {
463
- from: 0,
464
- options: await onQuery(text)
465
- };
466
- }
467
- ],
468
- // TODO(burdon): Consts from grid (to line-up with grid).
469
- tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
470
- optionClass: () => "flex h-[33px] items-center"
471
- }),
472
- // Check for accepted completion metadata in the transaction.
473
- EditorView.updateListener.of((update) => {
474
- update.transactions.forEach((tr) => {
475
- const completion2 = tr.annotation(pickedCompletion);
476
- if (completion2) {
477
- onMatch(completion2.data);
478
- }
479
- });
480
- })
481
- ];
482
- };
483
-
484
314
  // src/components/TableCellEditor/TableCellEditor.tsx
485
315
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
486
- var newValue = Symbol.for("newValue");
487
- var createOption = (text) => ({
488
- [newValue]: true,
489
- text
490
- });
491
- var isCreateOption = (data) => typeof data === "object" && data[newValue];
492
- var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQuery, __gridScope }) => {
493
- var _effect = _useSignals7();
316
+ var adaptValidationMessage = (message) => message ? message.endsWith("is missing") ? "Can\u2019t be blank" : message : null;
317
+ var TableValueEditor = ({ model, modals, schema, onFocus, onSave, client, __gridScope }) => {
318
+ var _effect = _useSignals3();
494
319
  try {
495
- const { editing } = useGridContext4("TableValueEditor", __gridScope);
496
- const fieldProjection = useMemo4(() => {
320
+ const { editing } = useGridContext3("TableValueEditor", __gridScope);
321
+ const fieldProjection = useMemo2(() => {
497
322
  if (!model || !editing) {
498
323
  return;
499
324
  }
@@ -502,7 +327,7 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQue
502
327
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
503
328
  invariant2(fieldProjection2, void 0, {
504
329
  F: __dxlog_file2,
505
- L: 76,
330
+ L: 72,
506
331
  S: void 0,
507
332
  A: [
508
333
  "fieldProjection",
@@ -514,21 +339,21 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onSave, onQue
514
339
  model,
515
340
  editing
516
341
  ]);
517
- if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect) {
518
- return /* @__PURE__ */ React7.createElement(FormCellEditor, {
342
+ if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum.SingleSelect || fieldProjection?.props.format === FormatEnum.Ref) {
343
+ return /* @__PURE__ */ React3.createElement(FormCellEditor, {
519
344
  fieldProjection,
520
345
  model,
521
346
  schema,
522
347
  __gridScope,
523
- onSave
348
+ onSave,
349
+ client,
350
+ modals
524
351
  });
525
352
  }
526
- return /* @__PURE__ */ React7.createElement(TableCellEditor, {
353
+ return /* @__PURE__ */ React3.createElement(TableCellEditor, {
527
354
  model,
528
355
  modals,
529
- onEnter,
530
356
  onFocus,
531
- onQuery,
532
357
  onSave,
533
358
  __gridScope
534
359
  });
@@ -541,15 +366,15 @@ var editorSlots = {
541
366
  className: "!plb-[--dx-grid-cell-editor-padding-block]"
542
367
  }
543
368
  };
544
- var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gridScope }) => {
545
- var _effect = _useSignals7();
369
+ var TableCellEditor = ({ model, modals, onFocus, onSave, __gridScope }) => {
370
+ var _effect = _useSignals3();
546
371
  try {
547
- const { id: gridId, editing, setEditing } = useGridContext4("TableCellEditor", __gridScope);
372
+ const { id: gridId, editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
548
373
  const suppressNextBlur = useRef2(false);
549
374
  const { themeMode } = useThemeContext();
550
- const [_validationError, setValidationError] = useState3(null);
551
- const [_validationVariant, setValidationVariant] = useState3("error");
552
- const fieldProjection = useMemo4(() => {
375
+ const [validationError, setValidationError] = useState2(null);
376
+ const [validationVariant, setValidationVariant] = useState2("error");
377
+ const fieldProjection = useMemo2(() => {
553
378
  if (!model || !editing) {
554
379
  return;
555
380
  }
@@ -558,7 +383,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
558
383
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
559
384
  invariant2(fieldProjection2, void 0, {
560
385
  F: __dxlog_file2,
561
- L: 135,
386
+ L: 122,
562
387
  S: void 0,
563
388
  A: [
564
389
  "fieldProjection",
@@ -570,38 +395,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
570
395
  model,
571
396
  editing
572
397
  ]);
573
- useEffect3(() => {
574
- if (!model || !editing || !fieldProjection) {
575
- setValidationError(null);
576
- return;
577
- }
578
- const cell = parseCellIndex2(editing.index);
579
- const { row, col } = cell;
580
- if (model.isDraftCell(cell)) {
581
- const field = model.projection.fields[col];
582
- const hasValidationError = model.hasDraftRowValidationError(row, field.path);
583
- if (hasValidationError) {
584
- const draftRows = model.draftRows.value;
585
- if (row >= 0 && row < draftRows.length) {
586
- const draftRow = draftRows[row];
587
- const validationError = draftRow.validationErrors?.find((error) => error.path === field.path);
588
- if (validationError) {
589
- setValidationError(validationError.message);
590
- setValidationVariant("warning");
591
- }
592
- }
593
- } else {
594
- setValidationError(null);
595
- }
596
- } else {
597
- setValidationError(null);
598
- }
599
- }, [
600
- model,
601
- editing,
602
- fieldProjection
603
- ]);
604
- const handleEnter = useCallback4(async (value) => {
398
+ const handleEnter = useCallback2(async (value) => {
605
399
  if (!model || !editing) {
606
400
  return;
607
401
  }
@@ -610,33 +404,39 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
610
404
  if (validationResult.valid) {
611
405
  setValidationError(null);
612
406
  model.setCellData(cell, value);
613
- onEnter?.(cell);
614
407
  onFocus?.();
615
408
  setEditing(null);
616
409
  onSave?.();
617
410
  } else {
618
- setValidationError(validationResult.error);
411
+ setValidationError(adaptValidationMessage(validationResult.error));
619
412
  setValidationVariant("error");
620
413
  }
621
414
  }, [
622
415
  model,
623
416
  editing,
624
- onEnter,
625
417
  onFocus,
626
418
  setEditing
627
419
  ]);
628
- const handleBlur = useCallback4(async (value) => {
629
- if (!model || !editing) {
630
- return;
631
- }
420
+ const handleBlur = useCallback2(async (value) => {
632
421
  if (suppressNextBlur.current) {
633
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
+ }
634
434
  }
635
435
  }, [
636
436
  model,
637
437
  editing
638
438
  ]);
639
- const handleClose = useCallback4(async (value, event) => {
439
+ const handleClose = useCallback2(async (value, event) => {
640
440
  if (!model || !editing || !fieldProjection) {
641
441
  return;
642
442
  }
@@ -644,19 +444,20 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
644
444
  if (value !== void 0) {
645
445
  const result = await model.validateCellData(cell, value);
646
446
  if (result.valid) {
447
+ suppressNextBlur.current = true;
647
448
  setValidationError(null);
648
449
  model.setCellData(cell, value);
649
450
  setEditing(null);
650
451
  onSave?.();
651
- onEnter?.(cell);
652
452
  if (event && onFocus) {
653
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
453
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
654
454
  }
655
455
  } else {
656
456
  setValidationError(result.error);
657
457
  setValidationVariant("error");
658
458
  }
659
459
  } else {
460
+ suppressNextBlur.current = true;
660
461
  setValidationError(null);
661
462
  setEditing(null);
662
463
  onSave?.();
@@ -668,12 +469,11 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
668
469
  model,
669
470
  editing,
670
471
  onFocus,
671
- onEnter,
672
472
  fieldProjection,
673
473
  setEditing,
674
474
  onSave
675
475
  ]);
676
- const extension = useMemo4(() => {
476
+ const extension = useMemo2(() => {
677
477
  if (!fieldProjection) {
678
478
  return [];
679
479
  }
@@ -716,131 +516,369 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, onSave, __gri
716
516
  }
717
517
  }));
718
518
  }
719
- if (onQuery) {
720
- switch (fieldProjection.props.format) {
721
- case FormatEnum.Ref: {
722
- extension2.push([
723
- completion({
724
- onQuery: (text) => onQuery(fieldProjection, text),
725
- onMatch: (data) => {
726
- if (model && editing && modals) {
727
- if (isCreateOption(data)) {
728
- const { field, props } = fieldProjection;
729
- if (props.referenceSchema) {
730
- suppressNextBlur.current = true;
731
- modals.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
732
- [field.referencePath]: data.text
733
- }, (data2) => {
734
- void handleEnter(data2);
735
- });
736
- }
737
- } else {
738
- void handleEnter(data);
739
- }
740
- }
741
- }
742
- })
743
- ]);
744
- break;
745
- }
746
- }
519
+ if (model && editing) {
520
+ extension2.push(EditorView.updateListener.of(debounce((update) => {
521
+ const content = update.state.doc.toString();
522
+ const cell = parseCellIndex2(editing.index);
523
+ void model.validateCellData(cell, content).then((result) => {
524
+ if (result.valid) {
525
+ setValidationError(null);
526
+ } else {
527
+ setValidationError(result.error);
528
+ setValidationVariant("error");
529
+ }
530
+ });
531
+ }, 10)));
532
+ }
533
+ return extension2;
534
+ }, [
535
+ model,
536
+ modals,
537
+ editing,
538
+ fieldProjection,
539
+ handleClose,
540
+ themeMode
541
+ ]);
542
+ const getCellContent = useCallback2(() => {
543
+ if (model && editing) {
544
+ const cell = parseCellIndex2(editing.index);
545
+ const { col } = cell;
546
+ const field = model.projection.fields[col];
547
+ const fieldProjection2 = model.projection.getFieldProjection(field.id);
548
+ if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
549
+ const value2 = model.getCellData(cell);
550
+ if (value2 !== void 0) {
551
+ const options = fieldProjection2.props.options || [];
552
+ if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
553
+ const tagItems = value2.split(",").map((id) => {
554
+ const option = options.find((o) => o.id === id);
555
+ if (option) {
556
+ return {
557
+ id,
558
+ label: option.title,
559
+ hue: option.color
560
+ };
561
+ }
562
+ return void 0;
563
+ }).filter((item) => item !== void 0);
564
+ return createLinks(tagItems);
565
+ } else {
566
+ const option = options.find((o) => o.id === value2);
567
+ if (option) {
568
+ const tagItem = {
569
+ id: value2,
570
+ label: option.title,
571
+ hue: option.color
572
+ };
573
+ return createLinks([
574
+ tagItem
575
+ ]);
576
+ }
577
+ }
578
+ }
579
+ return "";
580
+ }
581
+ const value = model.getCellData(cell);
582
+ return value !== void 0 ? String(value) : "";
583
+ }
584
+ }, [
585
+ model,
586
+ editing
587
+ ]);
588
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
589
+ validationError,
590
+ variant: validationVariant,
591
+ __gridScope
592
+ }), /* @__PURE__ */ React3.createElement(GridCellEditor, {
593
+ extension,
594
+ getCellContent,
595
+ onBlur: handleBlur,
596
+ slots: editorSlots
597
+ }));
598
+ } finally {
599
+ _effect.f();
600
+ }
601
+ };
602
+ var determineNavigationAxis = ({ key }) => {
603
+ switch (key) {
604
+ case "ArrowUp":
605
+ case "ArrowDown":
606
+ case "Enter": {
607
+ return "row";
608
+ }
609
+ case "ArrowLeft":
610
+ case "ArrowRight":
611
+ case "Tab":
612
+ return "col";
613
+ }
614
+ };
615
+ var determineNavigationDelta = ({ key, shift }) => {
616
+ switch (key) {
617
+ case "ArrowUp":
618
+ case "ArrowLeft":
619
+ return -1;
620
+ case "ArrowDown":
621
+ case "ArrowRight":
622
+ return 1;
623
+ }
624
+ return shift ? -1 : 1;
625
+ };
626
+
627
+ // src/components/Table/ColumnActionsMenu.tsx
628
+ import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
629
+ import React4 from "react";
630
+ import { DropdownMenu, useTranslation } from "@dxos/react-ui";
631
+ var ColumnActionsMenu = ({ model, modals }) => {
632
+ var _effect = _useSignals4();
633
+ try {
634
+ const { t } = useTranslation(translationKey);
635
+ const state = modals.state.value;
636
+ if (state?.type !== "column") {
637
+ return null;
638
+ }
639
+ const currentSort = model.sorting?.sorting;
640
+ const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
641
+ return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
642
+ modal: false,
643
+ open: true,
644
+ onOpenChange: modals.close
645
+ }, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
646
+ virtualRef: modals.trigger
647
+ }), /* @__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, {
648
+ "data-testid": "column-sort-descending",
649
+ onClick: () => model.sorting?.setSort(state.fieldId, "desc")
650
+ }, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
651
+ "data-testid": "column-sort-ascending",
652
+ onClick: () => model.sorting?.setSort(state.fieldId, "asc")
653
+ }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
654
+ "data-testid": "column-clear-sort",
655
+ onClick: () => model.sorting?.clearSort()
656
+ }, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
657
+ "data-testid": "column-delete",
658
+ onClick: () => model.deleteColumn(state.fieldId)
659
+ }, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
660
+ "data-testid": "column-settings",
661
+ onClick: () => modals.openColumnSettings()
662
+ }, t("column action settings"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
663
+ } finally {
664
+ _effect.f();
665
+ }
666
+ };
667
+
668
+ // src/components/Table/ColumnSettings.tsx
669
+ import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
670
+ import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useState as useState3 } from "react";
671
+ import { Popover as Popover2 } from "@dxos/react-ui";
672
+ import { FieldEditor } from "@dxos/react-ui-form";
673
+ var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
674
+ var _effect = _useSignals5();
675
+ try {
676
+ const [newField, setNewField] = useState3();
677
+ const state = modals.state.value;
678
+ useEffect2(() => {
679
+ if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
680
+ setNewField(model.projection.createFieldProjection());
681
+ requestAnimationFrame(() => {
682
+ onNewColumn();
683
+ });
684
+ } else {
685
+ setNewField(void 0);
686
+ }
687
+ }, [
688
+ model?.projection,
689
+ state
690
+ ]);
691
+ const existingField = useMemo3(() => {
692
+ if (state?.type === "columnSettings") {
693
+ const { mode } = state;
694
+ if (mode.type === "edit") {
695
+ return model?.projection?.fields.find((f) => f.id === mode.fieldId);
696
+ }
697
+ }
698
+ return void 0;
699
+ }, [
700
+ model?.projection?.fields,
701
+ state
702
+ ]);
703
+ const field = existingField ?? newField;
704
+ const handleSave = useCallback3(() => {
705
+ modals.close();
706
+ }, [
707
+ modals
708
+ ]);
709
+ const handleCancel = useCallback3(() => {
710
+ if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
711
+ model?.projection.deleteFieldProjection(newField.id);
712
+ }
713
+ }, [
714
+ model?.projection,
715
+ state,
716
+ newField
717
+ ]);
718
+ if (!model?.projection || !field) {
719
+ return null;
720
+ }
721
+ return /* @__PURE__ */ React5.createElement(Popover2.Root, {
722
+ modal: false,
723
+ open: state?.type === "columnSettings"
724
+ }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
725
+ virtualRef: modals.trigger
726
+ }), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
727
+ classNames: "md:is-64"
728
+ }, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
729
+ projection: model.projection,
730
+ field,
731
+ registry,
732
+ onSave: handleSave,
733
+ onCancel: handleCancel
734
+ })), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
735
+ } finally {
736
+ _effect.f();
737
+ }
738
+ };
739
+
740
+ // src/components/Table/CreateRefPanel.tsx
741
+ import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
742
+ import { Schema } from "effect";
743
+ import React6, { useCallback as useCallback4, useMemo as useMemo4 } from "react";
744
+ import { Type } from "@dxos/echo";
745
+ import { live } from "@dxos/live-object";
746
+ import { useClient } from "@dxos/react-client";
747
+ import { getSpace as getSpace2 } from "@dxos/react-client/echo";
748
+ import { Popover as Popover3 } from "@dxos/react-ui";
749
+ import { Form as Form2 } from "@dxos/react-ui-form";
750
+ import { useGridContext as useGridContext4 } from "@dxos/react-ui-grid";
751
+ var CreateRefPanel = ({ model, modals, __gridScope }) => {
752
+ var _effect = _useSignals6();
753
+ try {
754
+ const { id: gridId } = useGridContext4("TableCellEditor", __gridScope);
755
+ const client = useClient();
756
+ const space = model && getSpace2(model?.view);
757
+ const state = modals.state.value;
758
+ const getSchema = useCallback4(() => {
759
+ if (!space || state?.type !== "createRefPanel") {
760
+ return;
761
+ }
762
+ const staticSchema = client.graph.schemaRegistry.schemas.find((schema3) => Type.getTypename(schema3) === state.typename);
763
+ if (staticSchema) {
764
+ return staticSchema;
747
765
  }
748
- return extension2;
766
+ const [schema2] = space.db.schemaRegistry.query({
767
+ typename: state.typename
768
+ }).runSync();
769
+ return schema2;
770
+ }, [
771
+ space,
772
+ state
773
+ ]);
774
+ const schema = useMemo4(() => {
775
+ const schema2 = getSchema();
776
+ if (!schema2) {
777
+ return;
778
+ }
779
+ const omit = Schema.omit("id");
780
+ return omit(schema2);
781
+ }, [
782
+ getSchema
783
+ ]);
784
+ const handleSave = useCallback4((values) => {
785
+ if (!model || !space || state?.type !== "createRefPanel") {
786
+ return;
787
+ }
788
+ const schema2 = getSchema();
789
+ if (schema2) {
790
+ const obj = space.db.add(live(schema2, values));
791
+ state.onCreate?.(obj);
792
+ }
793
+ void modals.close();
749
794
  }, [
750
795
  model,
751
796
  modals,
752
- editing,
753
- fieldProjection,
754
- handleClose,
755
- themeMode
797
+ space,
798
+ state
756
799
  ]);
757
- const getCellContent = useCallback4(() => {
758
- if (model && editing) {
759
- const cell = parseCellIndex2(editing.index);
760
- const { col } = cell;
761
- const field = model.projection.fields[col];
762
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
763
- if (fieldProjection2?.props.format === FormatEnum.SingleSelect || fieldProjection2?.props.format === FormatEnum.MultiSelect) {
764
- const value2 = model.getCellData(cell);
765
- if (value2 !== void 0) {
766
- const options = fieldProjection2.props.options || [];
767
- if (fieldProjection2.props.format === FormatEnum.MultiSelect) {
768
- const tagItems = value2.split(",").map((id) => {
769
- const option = options.find((o) => o.id === id);
770
- if (option) {
771
- return {
772
- id,
773
- label: option.title,
774
- hue: option.color
775
- };
776
- }
777
- return void 0;
778
- }).filter((item) => item !== void 0);
779
- return createLinks(tagItems);
780
- } else {
781
- const option = options.find((o) => o.id === value2);
782
- if (option) {
783
- const tagItem = {
784
- id: value2,
785
- label: option.title,
786
- hue: option.color
787
- };
788
- return createLinks([
789
- tagItem
790
- ]);
791
- }
792
- }
793
- }
794
- return "";
795
- }
796
- const value = model.getCellData(cell);
797
- return value !== void 0 ? String(value) : "";
800
+ const handleCancel = useCallback4(() => {
801
+ if (model) {
802
+ modals.close();
798
803
  }
799
804
  }, [
800
- model,
801
- editing
805
+ modals
802
806
  ]);
803
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(CellValidationMessage, {
804
- validationError: _validationError,
805
- variant: _validationVariant,
806
- __gridScope
807
- }), /* @__PURE__ */ React7.createElement(GridCellEditor, {
808
- extension,
809
- getCellContent,
810
- onBlur: handleBlur,
811
- slots: editorSlots
812
- }));
807
+ if (!model?.projection) {
808
+ return null;
809
+ }
810
+ return /* @__PURE__ */ React6.createElement(Popover3.Root, {
811
+ modal: false,
812
+ open: state?.type === "createRefPanel" && !!schema,
813
+ onOpenChange: (nextOpen) => {
814
+ if (model && !nextOpen) {
815
+ return modals.close();
816
+ }
817
+ }
818
+ }, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
819
+ virtualRef: modals.trigger
820
+ }), /* @__PURE__ */ React6.createElement(Popover3.Portal, null, /* @__PURE__ */ React6.createElement(Popover3.Content, {
821
+ classNames: "md:is-64",
822
+ "data-grid": gridId
823
+ }, /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React6.createElement(Form2, {
824
+ schema,
825
+ values: state.initialValues ?? {},
826
+ onSave: handleSave,
827
+ onCancel: handleCancel
828
+ })), /* @__PURE__ */ React6.createElement(Popover3.Arrow, null))));
813
829
  } finally {
814
830
  _effect.f();
815
831
  }
816
832
  };
817
- var determineNavigationAxis = ({ key }) => {
818
- switch (key) {
819
- case "ArrowUp":
820
- case "ArrowDown":
821
- case "Enter": {
822
- return "row";
833
+
834
+ // src/components/Table/RowActionsMenu.tsx
835
+ import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
836
+ import React7 from "react";
837
+ import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
838
+ var RowActionsMenu = ({ model, modals }) => {
839
+ var _effect = _useSignals7();
840
+ try {
841
+ const { t } = useTranslation2(translationKey);
842
+ const hasSelection = model.selection.hasSelection.value;
843
+ const state = modals.state.value;
844
+ if (state?.type !== "row") {
845
+ return null;
823
846
  }
824
- case "ArrowLeft":
825
- case "ArrowRight":
826
- case "Tab":
827
- return "col";
828
- }
829
- };
830
- var determineNavigationDelta = ({ key, shift }) => {
831
- switch (key) {
832
- case "ArrowUp":
833
- case "ArrowLeft":
834
- return -1;
835
- case "ArrowDown":
836
- case "ArrowRight":
837
- return 1;
847
+ return /* @__PURE__ */ React7.createElement(DropdownMenu2.Root, {
848
+ modal: false,
849
+ open: true,
850
+ onOpenChange: modals.close
851
+ }, /* @__PURE__ */ React7.createElement(DropdownMenu2.VirtualTrigger, {
852
+ virtualRef: modals.trigger
853
+ }), /* @__PURE__ */ React7.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React7.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
854
+ "data-testid": "row-menu-delete",
855
+ onClick: () => model.deleteRow(state.rowIndex)
856
+ }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React7.createElement(DropdownMenu2.Item, {
857
+ key: action.id,
858
+ "data-testid": `row-action-${action.id}`,
859
+ onClick: () => {
860
+ modals.close();
861
+ model.handleRowAction(action.id, state.rowIndex);
862
+ }
863
+ }, toLocalizedString(action.label, t)))), /* @__PURE__ */ React7.createElement(DropdownMenu2.Arrow, null)));
864
+ } finally {
865
+ _effect.f();
838
866
  }
839
- return shift ? -1 : 1;
840
867
  };
841
868
 
842
869
  // src/components/Table/Table.tsx
843
- var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
870
+ var columnDefault = {
871
+ grid: {
872
+ minSize: 80,
873
+ maxSize: 640
874
+ }
875
+ };
876
+ var rowDefault = {
877
+ frozenRowsStart: {
878
+ readonly: true,
879
+ focusUnfurl: false
880
+ }
881
+ };
844
882
  var TableRoot = ({ children, role = "article" }) => {
845
883
  var _effect = _useSignals8();
846
884
  try {
@@ -864,14 +902,19 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
864
902
  try {
865
903
  const [dxGrid, setDxGrid] = useState4(null);
866
904
  const { hasAttention } = useAttention(model?.id ?? "table");
867
- const { t } = useTranslation3(translationKey);
868
905
  const modals = useMemo5(() => new ModalController(), []);
869
906
  const draftRowCount = model?.getDraftRowCount() ?? 0;
907
+ const handleSave = useCallback5(() => {
908
+ dxGrid?.updateCells(true);
909
+ dxGrid?.requestUpdate();
910
+ }, [
911
+ dxGrid
912
+ ]);
870
913
  const frozen = useMemo5(() => {
871
914
  const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
872
915
  return {
873
916
  frozenRowsStart: 1,
874
- frozenRowsEnd: draftRowCount,
917
+ frozenRowsEnd: Math.max(1, draftRowCount),
875
918
  frozenColsStart: model?.features.selection.enabled ? 1 : 0,
876
919
  frozenColsEnd: noActionColumn ? 0 : 1
877
920
  };
@@ -882,7 +925,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
882
925
  const getCells = useCallback5((range, plane) => presentation?.getCells(range, plane) ?? {}, [
883
926
  presentation
884
927
  ]);
885
- useEffect4(() => {
928
+ useEffect3(() => {
886
929
  if (!presentation || !dxGrid) {
887
930
  return;
888
931
  }
@@ -892,6 +935,30 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
892
935
  dxGrid,
893
936
  getCells
894
937
  ]);
938
+ const handleInsertRowResult = useCallback5((insertResult) => {
939
+ if (insertResult === "draft") {
940
+ requestAnimationFrame(() => {
941
+ dxGrid?.setFocus({
942
+ plane: "frozenRowsEnd",
943
+ col: 0,
944
+ row: 0
945
+ });
946
+ dxGrid?.refocus();
947
+ });
948
+ } else {
949
+ requestAnimationFrame(() => {
950
+ dxGrid?.setFocus({
951
+ plane: "grid",
952
+ col: 0,
953
+ row: model ? model.getRowCount() - 1 : 0
954
+ });
955
+ dxGrid?.refocus();
956
+ });
957
+ }
958
+ }, [
959
+ model,
960
+ dxGrid
961
+ ]);
895
962
  useImperativeHandle(forwardedRef, () => {
896
963
  if (!presentation || !dxGrid) {
897
964
  return {};
@@ -904,18 +971,38 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
904
971
  dxGrid.updateCells(true);
905
972
  dxGrid.requestUpdate();
906
973
  }
907
- }
974
+ },
975
+ handleInsertRowResult
908
976
  };
909
977
  }, [
910
978
  presentation,
979
+ dxGrid,
980
+ model
981
+ ]);
982
+ const handleSaveDraftRow = useCallback5((rowIndex = 0) => {
983
+ if (model && dxGrid) {
984
+ const didCommitSuccessfully = model.commitDraftRow(rowIndex);
985
+ if (didCommitSuccessfully) {
986
+ requestAnimationFrame(() => {
987
+ dxGrid.scrollToEndRow();
988
+ });
989
+ }
990
+ }
991
+ }, [
992
+ model,
911
993
  dxGrid
912
994
  ]);
913
995
  const handleGridClick = useCallback5((event) => {
914
- const rowIndex = safeParseInt(event.target.closest("[aria-rowindex]")?.ariaRowIndex ?? "");
915
- if (rowIndex != null) {
996
+ const cell = closestCell(event.target);
997
+ if (cell) {
998
+ const { row: rowIndex, plane } = cell;
916
999
  if (onRowClick) {
917
- const row = model?.getRowAt(rowIndex);
918
- row && onRowClick(row);
1000
+ if (plane === "grid") {
1001
+ const row = model?.getRowAt(rowIndex);
1002
+ row && onRowClick(row);
1003
+ } else {
1004
+ onRowClick(cell);
1005
+ }
919
1006
  }
920
1007
  if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
921
1008
  model.selection.toggleSelectionForRowIndex(rowIndex);
@@ -951,14 +1038,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
951
1038
  break;
952
1039
  }
953
1040
  case "saveDraftRow": {
954
- if (model) {
955
- const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
956
- if (dxGrid && didCommitSuccessfully) {
957
- requestAnimationFrame(() => {
958
- dxGrid.scrollToEndRow();
959
- });
960
- }
961
- }
1041
+ handleSaveDraftRow();
962
1042
  break;
963
1043
  }
964
1044
  }
@@ -997,29 +1077,20 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
997
1077
  modals,
998
1078
  dxGrid
999
1079
  ]);
1000
- const handleFocus = useCallback5((increment, delta) => {
1001
- if (dxGrid) {
1002
- dxGrid.refocus(increment, delta);
1003
- }
1004
- }, [
1005
- dxGrid
1006
- ]);
1007
- const handleEnter = useCallback5((cell) => {
1008
- if (!model?.features.dataEditable) {
1009
- return;
1010
- }
1011
- if (model && cell.row === model.getRowCount() - 1) {
1012
- model.insertRow();
1013
- if (dxGrid) {
1014
- requestAnimationFrame(() => {
1015
- dxGrid?.scrollToRow(cell.row + 1);
1016
- dxGrid?.refocus("row", 1);
1017
- });
1080
+ const handleFocus = useCallback5((increment, delta, cell) => {
1081
+ if (dxGrid && model) {
1082
+ if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1) {
1083
+ handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
1084
+ } else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
1085
+ handleSaveDraftRow(cell.row);
1086
+ handleInsertRowResult(model.insertRow());
1087
+ } else {
1088
+ dxGrid.refocus(increment, delta);
1018
1089
  }
1019
1090
  }
1020
1091
  }, [
1021
- model,
1022
- dxGrid
1092
+ dxGrid,
1093
+ model
1023
1094
  ]);
1024
1095
  const handleKeyDown = useCallback5((event) => {
1025
1096
  if (!model?.features.dataEditable) {
@@ -1029,15 +1100,63 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1029
1100
  if (!model || !cell) {
1030
1101
  return;
1031
1102
  }
1103
+ if (event.metaKey || event.ctrlKey) {
1104
+ switch (event.key) {
1105
+ case "c": {
1106
+ try {
1107
+ const cellData = model.getCellData(cell);
1108
+ const textContent = cellData?.toString() ?? "";
1109
+ void navigator.clipboard.writeText(textContent);
1110
+ event.preventDefault();
1111
+ } catch (error) {
1112
+ console.warn("Failed to copy cell content:", error);
1113
+ }
1114
+ break;
1115
+ }
1116
+ case "v": {
1117
+ event.preventDefault();
1118
+ void navigator.clipboard.readText().then((clipboardText) => {
1119
+ try {
1120
+ model.setCellData(cell, clipboardText);
1121
+ handleSave();
1122
+ } catch {
1123
+ const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
1124
+ if (cellElement) {
1125
+ const rect = cellElement.getBoundingClientRect();
1126
+ const editRequest = new DxEditRequest({
1127
+ cellIndex: `${cell.plane},${cell.col},${cell.row}`,
1128
+ cellBox: {
1129
+ insetInlineStart: rect.left,
1130
+ insetBlockStart: rect.top,
1131
+ inlineSize: rect.width,
1132
+ blockSize: rect.height
1133
+ },
1134
+ cellElement,
1135
+ initialContent: clipboardText
1136
+ });
1137
+ cellElement.dispatchEvent(editRequest);
1138
+ }
1139
+ }
1140
+ });
1141
+ break;
1142
+ }
1143
+ }
1144
+ }
1032
1145
  switch (event.key) {
1033
1146
  case "Backspace":
1034
1147
  case "Delete": {
1035
- model.setCellData(cell, void 0);
1148
+ try {
1149
+ model.setCellData(cell, void 0);
1150
+ event.preventDefault();
1151
+ } catch {
1152
+ }
1036
1153
  break;
1037
1154
  }
1038
1155
  }
1039
1156
  }, [
1040
- model
1157
+ model,
1158
+ dxGrid,
1159
+ handleSave
1041
1160
  ]);
1042
1161
  const handleAxisResize = useCallback5((event) => {
1043
1162
  if (event.axis === "col") {
@@ -1064,59 +1183,6 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1064
1183
  model,
1065
1184
  dxGrid
1066
1185
  ]);
1067
- const handleQuery = useCallback5(async ({ field, props }, text) => {
1068
- if (model && props.referenceSchema && field.referencePath) {
1069
- const space = getSpace2(model.view);
1070
- invariant3(space, void 0, {
1071
- F: __dxlog_file3,
1072
- L: 325,
1073
- S: void 0,
1074
- A: [
1075
- "space",
1076
- ""
1077
- ]
1078
- });
1079
- let schema2;
1080
- if (client) {
1081
- schema2 = client.graph.schemaRegistry.getSchema(props.referenceSchema);
1082
- }
1083
- if (!schema2) {
1084
- schema2 = space.db.schemaRegistry.getSchema(props.referenceSchema);
1085
- }
1086
- if (schema2) {
1087
- const { objects } = await space.db.query(Filter.type(schema2)).run();
1088
- const options = objects.map((obj) => {
1089
- const value = getValue(obj, field.referencePath);
1090
- if (!value || typeof value !== "string") {
1091
- return void 0;
1092
- }
1093
- return {
1094
- label: value,
1095
- data: obj
1096
- };
1097
- }).filter(isNotFalsy);
1098
- return [
1099
- ...options,
1100
- {
1101
- label: t("create new object label", {
1102
- text
1103
- }),
1104
- data: createOption(text)
1105
- }
1106
- ];
1107
- }
1108
- }
1109
- return [];
1110
- }, [
1111
- model,
1112
- client,
1113
- t
1114
- ]);
1115
- const handleSave = useCallback5(() => {
1116
- dxGrid?.updateCells(true);
1117
- }, [
1118
- dxGrid
1119
- ]);
1120
1186
  if (!model || !modals) {
1121
1187
  return /* @__PURE__ */ React8.createElement("span", {
1122
1188
  role: "none",
@@ -1129,20 +1195,21 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
1129
1195
  model,
1130
1196
  modals,
1131
1197
  schema,
1132
- onEnter: handleEnter,
1133
1198
  onFocus: handleFocus,
1134
- onQuery: handleQuery,
1135
- onSave: handleSave
1199
+ onSave: handleSave,
1200
+ client
1136
1201
  }), /* @__PURE__ */ React8.createElement(Grid.Content, {
1137
1202
  className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
1138
1203
  frozen,
1139
1204
  columns: model.columnMeta.value,
1205
+ columnDefault,
1206
+ rowDefault,
1140
1207
  limitRows: model.getRowCount() ?? 0,
1141
1208
  limitColumns: model.projection.fields.length,
1142
1209
  overscroll: "trap",
1143
1210
  onAxisResize: handleAxisResize,
1144
1211
  onClick: handleGridClick,
1145
- onKeyDown: handleKeyDown,
1212
+ onKeyDownCapture: handleKeyDown,
1146
1213
  onWheelCapture: handleWheel,
1147
1214
  ref: setDxGrid
1148
1215
  }), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
@@ -1170,7 +1237,7 @@ var Table = {
1170
1237
 
1171
1238
  // src/components/Table/DynamicTable.tsx
1172
1239
  import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
1173
- import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
1240
+ import React9, { useCallback as useCallback6, useMemo as useMemo6, useRef as useRef3 } from "react";
1174
1241
  import { useDefaultValue } from "@dxos/react-ui";
1175
1242
  import { mx as mx2 } from "@dxos/react-ui-theme";
1176
1243
  var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
@@ -1250,7 +1317,7 @@ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking
1250
1317
  import { Rx } from "@effect-rx/rx-react";
1251
1318
  import React10, { useMemo as useMemo7 } from "react";
1252
1319
  import { live as live2 } from "@dxos/live-object";
1253
- import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
1320
+ import { MenuProvider, ToolbarMenu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
1254
1321
  import { rxFromSignal } from "@dxos/react-ui-menu";
1255
1322
  var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
1256
1323
  const add = createMenuAction("add-row", onAdd, {
@@ -1337,7 +1404,6 @@ export {
1337
1404
  TablePresentation,
1338
1405
  TableToolbar,
1339
1406
  cellClassesForRowSelection,
1340
- createTable,
1341
1407
  getBaseSchema,
1342
1408
  makeDynamicTable,
1343
1409
  narrowSchema,