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