@dxos/react-ui-table 0.7.2-staging.6d26b2a → 0.7.3-main.2dd075e

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 (75) hide show
  1. package/dist/lib/browser/{chunk-EWGUNGJC.mjs → chunk-IYCSJDMB.mjs} +5 -3
  2. package/dist/lib/browser/chunk-IYCSJDMB.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +461 -237
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types/index.mjs +3 -1
  7. package/dist/lib/node/{chunk-A2N7XWW6.cjs → chunk-MHBMVCFZ.cjs} +8 -5
  8. package/dist/lib/node/chunk-MHBMVCFZ.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +471 -253
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/types/index.cjs +4 -2
  13. package/dist/lib/node/types/index.cjs.map +2 -2
  14. package/dist/lib/node-esm/{chunk-SABDOZ6I.mjs → chunk-BMWGPXPL.mjs} +5 -3
  15. package/dist/lib/node-esm/chunk-BMWGPXPL.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +461 -237
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/types/index.mjs +3 -1
  20. package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/ColumnSettings.d.ts +2 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  24. package/dist/types/src/components/Table/CreateRefPanel.d.ts +8 -0
  25. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -0
  26. package/dist/types/src/components/Table/RefPanel.d.ts +8 -0
  27. package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -0
  28. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Table.d.ts +2 -2
  30. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  31. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +16 -7
  32. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  33. package/dist/types/src/components/TableCellEditor/extension.d.ts +2 -1
  34. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -1
  35. package/dist/types/src/components/testing.d.ts +1 -1
  36. package/dist/types/src/components/testing.d.ts.map +1 -1
  37. package/dist/types/src/model/modal-controller.d.ts +11 -0
  38. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  39. package/dist/types/src/model/table-model.d.ts +4 -5
  40. package/dist/types/src/model/table-model.d.ts.map +1 -1
  41. package/dist/types/src/translations.d.ts +1 -0
  42. package/dist/types/src/translations.d.ts.map +1 -1
  43. package/dist/types/src/types/table.d.ts +57 -2
  44. package/dist/types/src/types/table.d.ts.map +1 -1
  45. package/dist/types/src/util/index.d.ts +0 -1
  46. package/dist/types/src/util/index.d.ts.map +1 -1
  47. package/dist/types/src/util/table-buttons.d.ts +8 -0
  48. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  49. package/package.json +29 -28
  50. package/src/_deprecated/components/Table/Table.stories.tsx +1 -1
  51. package/src/components/Table/ColumnActionsMenu.tsx +0 -1
  52. package/src/components/Table/ColumnSettings.tsx +7 -4
  53. package/src/components/Table/CreateRefPanel.tsx +83 -0
  54. package/src/components/Table/RefPanel.tsx +52 -0
  55. package/src/components/Table/RowActionsMenu.tsx +1 -2
  56. package/src/components/Table/Table.stories.tsx +2 -2
  57. package/src/components/Table/Table.tsx +60 -33
  58. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +2 -2
  59. package/src/components/TableCellEditor/TableCellEditor.tsx +72 -23
  60. package/src/components/TableCellEditor/extension.ts +3 -4
  61. package/src/components/testing.ts +2 -1
  62. package/src/model/modal-controller.ts +43 -0
  63. package/src/model/table-model.test.ts +5 -3
  64. package/src/model/table-model.ts +34 -22
  65. package/src/playwright/smoke.spec.ts +0 -4
  66. package/src/translations.ts +1 -0
  67. package/src/types/table.ts +5 -5
  68. package/src/util/index.ts +0 -1
  69. package/src/util/table-buttons.ts +18 -1
  70. package/dist/lib/browser/chunk-EWGUNGJC.mjs.map +0 -7
  71. package/dist/lib/node/chunk-A2N7XWW6.cjs.map +0 -7
  72. package/dist/lib/node-esm/chunk-SABDOZ6I.mjs.map +0 -7
  73. package/dist/types/src/util/grid.d.ts +0 -14
  74. package/dist/types/src/util/grid.d.ts.map +0 -1
  75. package/src/util/grid.ts +0 -23
@@ -1,7 +1,8 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
+ TableSchema,
3
4
  TableType
4
- } from "./chunk-SABDOZ6I.mjs";
5
+ } from "./chunk-BMWGPXPL.mjs";
5
6
 
6
7
  // packages/ui/react-ui-table/src/translations.ts
7
8
  var translationKey = "table";
@@ -27,17 +28,19 @@ var translations_default = [
27
28
  "delete row label": "Delete row",
28
29
  "bulk delete row label": "Delete selected rows",
29
30
  "column deleted label": "Column deleted",
30
- "new column button label": "Create column"
31
+ "new column button label": "Create column",
32
+ "create new object label": "Create new object \u201C{{text}}\u201D"
31
33
  }
32
34
  }
33
35
  }
34
36
  ];
35
37
 
36
38
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
37
- import React5, { forwardRef, useCallback as useCallback3, useImperativeHandle, useState as useState2 } from "react";
39
+ import React7, { forwardRef, useCallback as useCallback4, useImperativeHandle, useState as useState2 } from "react";
38
40
  import { getValue } from "@dxos/echo-schema";
39
41
  import { invariant as invariant2 } from "@dxos/invariant";
40
- import { Filter, getSpace as getSpace2, fullyQualifiedId } from "@dxos/react-client/echo";
42
+ import { Filter, getSpace as getSpace4, fullyQualifiedId } from "@dxos/react-client/echo";
43
+ import { useTranslation as useTranslation3 } from "@dxos/react-ui";
41
44
  import { useAttention } from "@dxos/react-ui-attention";
42
45
  import { Grid, closestCell } from "@dxos/react-ui-grid";
43
46
  import { mx } from "@dxos/react-ui-theme";
@@ -83,13 +86,16 @@ import React2, { useCallback, useEffect, useMemo, useState } from "react";
83
86
  import { getSpace } from "@dxos/react-client/echo";
84
87
  import { DropdownMenu as DropdownMenu2 } from "@dxos/react-ui";
85
88
  import { FieldEditor } from "@dxos/react-ui-form";
86
- var ColumnSettings = ({ model }) => {
89
+ var ColumnSettings = ({ model, onNewColumn }) => {
87
90
  const [newField, setNewField] = useState();
88
91
  const state = model?.modalController.state.value;
89
92
  const space = getSpace(model?.table);
90
93
  useEffect(() => {
91
94
  if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
92
95
  setNewField(model.projection.createFieldProjection());
96
+ requestAnimationFrame(() => {
97
+ onNewColumn();
98
+ });
93
99
  } else {
94
100
  setNewField(void 0);
95
101
  }
@@ -110,7 +116,7 @@ var ColumnSettings = ({ model }) => {
110
116
  state
111
117
  ]);
112
118
  const field = existingField ?? newField;
113
- const handleClose = useCallback(() => {
119
+ const handleSave = useCallback(() => {
114
120
  model?.modalController.close();
115
121
  }, [
116
122
  model?.modalController
@@ -139,43 +145,152 @@ var ColumnSettings = ({ model }) => {
139
145
  projection: model.projection,
140
146
  field,
141
147
  registry: space?.db.schemaRegistry,
142
- onClose: handleClose,
148
+ onSave: handleSave,
143
149
  onCancel: handleCancel
144
150
  })), /* @__PURE__ */ React2.createElement(DropdownMenu2.Arrow, null))));
145
151
  };
146
152
 
153
+ // packages/ui/react-ui-table/src/components/Table/CreateRefPanel.tsx
154
+ import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
155
+ import { S } from "@dxos/echo-schema";
156
+ import { create, getSpace as getSpace2 } from "@dxos/react-client/echo";
157
+ import { Popover } from "@dxos/react-ui";
158
+ import { Form } from "@dxos/react-ui-form";
159
+ import { useGridContext } from "@dxos/react-ui-grid";
160
+ var CreateRefPanel = ({ model, __gridScope }) => {
161
+ const { id: gridId } = useGridContext("TableCellEditor", __gridScope);
162
+ const space = getSpace2(model?.table);
163
+ const state = model?.modalController.state.value;
164
+ const schema = useMemo2(() => {
165
+ if (!space || state?.type !== "createRefPanel") {
166
+ return;
167
+ }
168
+ const schema2 = space.db.schemaRegistry.getSchema(state.typename)?.schema;
169
+ if (schema2) {
170
+ const omit = S.omit("id");
171
+ return omit(schema2);
172
+ }
173
+ }, [
174
+ space,
175
+ state
176
+ ]);
177
+ const handleSave = useCallback2((values) => {
178
+ if (!model || !space || state?.type !== "createRefPanel") {
179
+ return;
180
+ }
181
+ const schema2 = space.db.schemaRegistry.getSchema(state.typename)?.schema;
182
+ if (schema2) {
183
+ const obj = space.db.add(create(schema2, values));
184
+ state.onCreate?.(obj);
185
+ }
186
+ void model.modalController.close();
187
+ }, [
188
+ model?.modalController,
189
+ space,
190
+ state
191
+ ]);
192
+ const handleCancel = useCallback2(() => {
193
+ if (model) {
194
+ model.modalController.close();
195
+ }
196
+ }, [
197
+ model?.modalController
198
+ ]);
199
+ if (!model?.table?.view || !model.projection) {
200
+ return null;
201
+ }
202
+ return /* @__PURE__ */ React3.createElement(Popover.Root, {
203
+ modal: false,
204
+ open: state?.type === "createRefPanel" && !!schema,
205
+ onOpenChange: (nextOpen) => {
206
+ if (model && !nextOpen) {
207
+ return model.modalController.close();
208
+ }
209
+ }
210
+ }, /* @__PURE__ */ React3.createElement(Popover.VirtualTrigger, {
211
+ virtualRef: model.modalController.trigger
212
+ }), /* @__PURE__ */ React3.createElement(Popover.Portal, null, /* @__PURE__ */ React3.createElement(Popover.Content, {
213
+ classNames: "md:is-64",
214
+ "data-grid": gridId
215
+ }, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
216
+ schema,
217
+ values: state.initialValues ?? {},
218
+ onSave: handleSave,
219
+ onCancel: handleCancel
220
+ }), /* @__PURE__ */ React3.createElement(Popover.Arrow, null))));
221
+ };
222
+
223
+ // packages/ui/react-ui-table/src/components/Table/RefPanel.tsx
224
+ import React4 from "react";
225
+ import { getSpace as getSpace3 } from "@dxos/react-client/echo";
226
+ import { Popover as Popover2 } from "@dxos/react-ui";
227
+ import { Form as Form2 } from "@dxos/react-ui-form";
228
+ var getRefTargetObj = (space, id) => {
229
+ if (space && id) {
230
+ return space?.db.getObjectById(id);
231
+ } else {
232
+ return void 0;
233
+ }
234
+ };
235
+ var RefPanel = ({ model }) => {
236
+ const state = model?.modalController.state.value;
237
+ const space = getSpace3(model?.table);
238
+ const targetObj = getRefTargetObj(space, state?.type === "refPanel" ? state.targetId : void 0);
239
+ const schema = space && state?.type === "refPanel" ? space.db.schemaRegistry.getSchema(state.typename) : void 0;
240
+ if (!model?.table?.view || !model.projection) {
241
+ return null;
242
+ }
243
+ return /* @__PURE__ */ React4.createElement(Popover2.Root, {
244
+ modal: false,
245
+ open: state?.type === "refPanel" && !!targetObj && !!schema,
246
+ onOpenChange: (nextOpen) => {
247
+ if (model && !nextOpen) {
248
+ return model.modalController.close();
249
+ }
250
+ }
251
+ }, /* @__PURE__ */ React4.createElement(Popover2.VirtualTrigger, {
252
+ virtualRef: model.modalController.trigger
253
+ }), /* @__PURE__ */ React4.createElement(Popover2.Portal, null, /* @__PURE__ */ React4.createElement(Popover2.Content, {
254
+ classNames: "md:is-64"
255
+ }, targetObj && schema && /* @__PURE__ */ React4.createElement(Form2, {
256
+ readonly: true,
257
+ values: targetObj,
258
+ schema
259
+ }), /* @__PURE__ */ React4.createElement(Popover2.Arrow, null))));
260
+ };
261
+
147
262
  // packages/ui/react-ui-table/src/components/Table/RowActionsMenu.tsx
148
- import React3 from "react";
263
+ import React5 from "react";
149
264
  import { DropdownMenu as DropdownMenu3, useTranslation as useTranslation2 } from "@dxos/react-ui";
150
265
  var RowActionsMenu = ({ model }) => {
151
266
  const { t } = useTranslation2(translationKey);
152
- const state = model.modalController.state.value;
153
267
  const hasSelection = model.selection.hasSelection.value;
268
+ const state = model.modalController.state.value;
154
269
  if (state?.type !== "row") {
155
270
  return null;
156
271
  }
157
- return /* @__PURE__ */ React3.createElement(DropdownMenu3.Root, {
272
+ return /* @__PURE__ */ React5.createElement(DropdownMenu3.Root, {
158
273
  modal: false,
159
274
  open: true,
160
275
  onOpenChange: model.modalController.close
161
- }, /* @__PURE__ */ React3.createElement(DropdownMenu3.VirtualTrigger, {
276
+ }, /* @__PURE__ */ React5.createElement(DropdownMenu3.VirtualTrigger, {
162
277
  virtualRef: model.modalController.trigger
163
- }), /* @__PURE__ */ React3.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React3.createElement(DropdownMenu3.Viewport, null, /* @__PURE__ */ React3.createElement(DropdownMenu3.Item, {
278
+ }), /* @__PURE__ */ React5.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Viewport, null, /* @__PURE__ */ React5.createElement(DropdownMenu3.Item, {
164
279
  "data-testid": "row-menu-delete",
165
280
  onClick: () => model.deleteRow(state.rowIndex)
166
- }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React3.createElement(DropdownMenu3.Arrow, null)));
281
+ }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React5.createElement(DropdownMenu3.Arrow, null)));
167
282
  };
168
283
 
169
284
  // packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
170
- import React4, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
171
- import { FormatEnum as FormatEnum2 } from "@dxos/echo-schema";
285
+ import React6, { useCallback as useCallback3, useMemo as useMemo3, useRef } from "react";
286
+ import { FormatEnum } from "@dxos/echo-schema";
172
287
  import { invariant } from "@dxos/invariant";
173
- import { editorKeys, GridCellEditor, useGridContext } from "@dxos/react-ui-grid";
288
+ import { cellQuery, editorKeys, parseCellIndex, useGridContext as useGridContext2, GridCellEditor } from "@dxos/react-ui-grid";
174
289
 
175
290
  // packages/ui/react-ui-table/src/components/TableCellEditor/extension.ts
176
291
  import { autocompletion, pickedCompletion } from "@codemirror/autocomplete";
177
292
  import { EditorView } from "@codemirror/view";
178
- var completion = ({ onQuery, onMatch }) => {
293
+ var completion = ({ debug, onQuery, onMatch }) => {
179
294
  return [
180
295
  EditorView.theme({
181
296
  ".cm-completionDialog": {
@@ -185,6 +300,7 @@ var completion = ({ onQuery, onMatch }) => {
185
300
  autocompletion({
186
301
  icons: false,
187
302
  activateOnTyping: true,
303
+ closeOnBlur: !debug,
188
304
  override: [
189
305
  async (context) => {
190
306
  const text = context.state.doc.toString();
@@ -210,147 +326,27 @@ var completion = ({ onQuery, onMatch }) => {
210
326
  ];
211
327
  };
212
328
 
213
- // packages/ui/react-ui-table/src/util/grid.ts
214
- var fromGridCell = ({ col, row }) => {
215
- return `${col},${row}`;
216
- };
217
- var toGridCell = (cell) => {
218
- const [col, row] = cell.split(",").map(Number);
219
- return {
220
- row,
221
- col
222
- };
223
- };
224
-
225
- // packages/ui/react-ui-table/src/util/signals.ts
226
- var touch = (value) => value;
227
-
228
- // packages/ui/react-ui-table/src/util/table.ts
229
- import { AST, Format, FormatEnum, S, TypedObject, TypeEnum } from "@dxos/echo-schema";
230
- import { log } from "@dxos/log";
231
- import { PublicKey } from "@dxos/react-client";
232
- import { create } from "@dxos/react-client/echo";
233
- import { createFieldId, createView, ViewProjection } from "@dxos/schema";
234
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
235
- var initializeTable = ({ space, table, initialRow = true }) => {
236
- log.info("initializeTable", {
237
- table
238
- }, {
239
- F: __dxlog_file,
240
- L: 32,
241
- S: void 0,
242
- C: (f, a) => f(...a)
243
- });
244
- const ContactSchema = TypedObject({
245
- typename: `example.com/type/${PublicKey.random().truncate()}`,
246
- version: "0.1.0"
247
- })({
248
- name: S.optional(S.String).annotations({
249
- [AST.TitleAnnotationId]: "Name"
250
- }),
251
- email: S.optional(Format.Email),
252
- salary: S.optional(Format.Currency()).annotations({
253
- [AST.TitleAnnotationId]: "Salary"
254
- })
255
- });
256
- const contactSchema = space.db.schemaRegistry.addSchema(ContactSchema);
257
- table.view = createView({
258
- name: "Test",
259
- typename: contactSchema.typename,
260
- jsonSchema: contactSchema.jsonSchema,
261
- fields: [
262
- "name",
263
- "email",
264
- "salary"
265
- ]
266
- });
267
- const projection = new ViewProjection(contactSchema, table.view);
268
- projection.setFieldProjection({
269
- field: {
270
- id: table.view.fields[2].id,
271
- path: "salary",
272
- size: 150
273
- }
274
- });
275
- projection.setFieldProjection({
276
- field: {
277
- id: createFieldId(),
278
- path: "manager",
279
- referencePath: "name"
280
- },
281
- props: {
282
- property: "manager",
283
- type: TypeEnum.Ref,
284
- format: FormatEnum.Ref,
285
- referenceSchema: contactSchema.typename,
286
- title: "Manager"
287
- }
288
- });
289
- if (initialRow) {
290
- space.db.add(create(contactSchema, {}));
291
- }
292
- return contactSchema;
293
- };
294
-
295
- // packages/ui/react-ui-table/src/util/table-buttons.ts
296
- var TABLE_ATTRS = {
297
- columnSettings: "data-table-column-settings-button",
298
- rowMenu: "data-table-row-menu-button",
299
- newColumn: "data-table-new-column-button"
300
- };
301
- var ICONS = {
302
- columnSettings: "ph--caret-down--regular",
303
- rowMenu: "ph--dots-three--regular",
304
- newColumn: "ph--plus--regular"
305
- };
306
- var createButtonHtml = ({ button, value = "", disabled = false, testId }) => {
307
- const buttonClasses = "ch-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 inline-end-2";
308
- return `<button class="${buttonClasses}" ${TABLE_ATTRS[button]}="${value}" data-testid="${testId}" ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${ICONS[button]}"/></svg></button>`;
309
- };
310
- var tableButtons = {
311
- columnSettings: {
312
- attr: TABLE_ATTRS.columnSettings,
313
- icon: ICONS.columnSettings,
314
- render: ({ fieldId }) => createButtonHtml({
315
- button: "columnSettings",
316
- value: fieldId,
317
- testId: "table-column-settings-button"
318
- })
319
- },
320
- rowMenu: {
321
- attr: TABLE_ATTRS.rowMenu,
322
- icon: ICONS.rowMenu,
323
- render: ({ rowIndex }) => createButtonHtml({
324
- button: "rowMenu",
325
- value: rowIndex.toString(),
326
- testId: "table-row-menu-button"
327
- })
328
- },
329
- addColumn: {
330
- attr: TABLE_ATTRS.newColumn,
331
- icon: ICONS.newColumn,
332
- render: ({ disabled } = {}) => createButtonHtml({
333
- button: "newColumn",
334
- disabled,
335
- testId: "table-new-column-button"
336
- })
337
- }
338
- };
339
-
340
329
  // packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
341
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
330
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
331
+ var newValue = Symbol.for("newValue");
332
+ var createOption = (text) => ({
333
+ [newValue]: true,
334
+ text
335
+ });
336
+ var isCreateOption = (data) => typeof data === "object" && data[newValue];
342
337
  var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
343
- const { editing } = useGridContext("TableCellEditor", __gridScope);
344
- const fieldProjection = useMemo2(() => {
338
+ const { id: gridId, editing, setEditing } = useGridContext2("TableCellEditor", __gridScope);
339
+ const suppressNextBlur = useRef(false);
340
+ const fieldProjection = useMemo3(() => {
345
341
  if (!model || !editing) {
346
342
  return;
347
343
  }
348
- const { col } = toGridCell(editing.index);
344
+ const { col } = parseCellIndex(editing.index);
349
345
  const field = model.projection.view.fields[col];
350
346
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
351
347
  invariant(fieldProjection2, void 0, {
352
- F: __dxlog_file2,
353
- L: 49,
348
+ F: __dxlog_file,
349
+ L: 65,
354
350
  S: void 0,
355
351
  A: [
356
352
  "fieldProjection",
@@ -362,29 +358,28 @@ var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
362
358
  model,
363
359
  editing
364
360
  ]);
365
- const handleClose = useCallback2((value, event) => {
366
- if (!model || !editing || !fieldProjection) {
361
+ const handleEnter = useCallback3((value) => {
362
+ if (!model || !editing) {
367
363
  return;
368
364
  }
369
- const cell = toGridCell(editing.index);
365
+ const cell = parseCellIndex(editing.index);
366
+ model.setCellData(cell, value);
370
367
  onEnter?.(cell);
371
- if (event && onFocus) {
372
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
373
- }
368
+ onFocus?.();
369
+ setEditing(null);
374
370
  }, [
375
371
  model,
376
- editing,
377
- onFocus,
378
- onEnter,
379
- fieldProjection,
380
- determineNavigationAxis,
381
- determineNavigationDelta
372
+ editing
382
373
  ]);
383
- const handleBlur = useCallback2((value) => {
374
+ const handleBlur = useCallback3((value) => {
384
375
  if (!model || !editing) {
385
376
  return;
386
377
  }
387
- const cell = toGridCell(editing.index);
378
+ if (suppressNextBlur.current) {
379
+ suppressNextBlur.current = false;
380
+ return;
381
+ }
382
+ const cell = parseCellIndex(editing.index);
388
383
  if (value !== void 0) {
389
384
  model.setCellData(cell, value);
390
385
  }
@@ -392,7 +387,25 @@ var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
392
387
  model,
393
388
  editing
394
389
  ]);
395
- const extension = useMemo2(() => {
390
+ const handleClose = useCallback3((value, event) => {
391
+ if (!model || !editing || !fieldProjection) {
392
+ return;
393
+ }
394
+ const cell = parseCellIndex(editing.index);
395
+ onEnter?.(cell);
396
+ if (event && onFocus) {
397
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
398
+ }
399
+ }, [
400
+ model,
401
+ editing,
402
+ onFocus,
403
+ onEnter,
404
+ fieldProjection,
405
+ determineNavigationAxis,
406
+ determineNavigationDelta
407
+ ]);
408
+ const extension = useMemo3(() => {
396
409
  if (!fieldProjection) {
397
410
  return [];
398
411
  }
@@ -406,16 +419,25 @@ var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
406
419
  ];
407
420
  if (onQuery) {
408
421
  switch (fieldProjection.props.format) {
409
- case FormatEnum2.Ref: {
422
+ case FormatEnum.Ref: {
410
423
  extension2.push([
411
424
  completion({
412
425
  onQuery: (text) => onQuery(fieldProjection, text),
413
426
  onMatch: (data) => {
414
427
  if (model && editing) {
415
- const cell = toGridCell(editing.index);
416
- model.setCellData(cell, data);
417
- onEnter?.(cell);
418
- onFocus?.();
428
+ if (isCreateOption(data)) {
429
+ const { field, props } = fieldProjection;
430
+ if (props.referenceSchema) {
431
+ suppressNextBlur.current = true;
432
+ model.modalController.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
433
+ [field.referencePath]: data.text
434
+ }, (data2) => {
435
+ handleEnter(data2);
436
+ });
437
+ }
438
+ } else {
439
+ handleEnter(data);
440
+ }
419
441
  }
420
442
  }
421
443
  })
@@ -431,16 +453,16 @@ var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
431
453
  fieldProjection,
432
454
  handleClose
433
455
  ]);
434
- const getCellContent = useCallback2(() => {
456
+ const getCellContent = useCallback3(() => {
435
457
  if (model && editing) {
436
- const value = model.getCellData(toGridCell(editing.index));
458
+ const value = model.getCellData(parseCellIndex(editing.index));
437
459
  return value !== void 0 ? String(value) : "";
438
460
  }
439
461
  }, [
440
462
  model,
441
463
  editing
442
464
  ]);
443
- return /* @__PURE__ */ React4.createElement(GridCellEditor, {
465
+ return /* @__PURE__ */ React6.createElement(GridCellEditor, {
444
466
  extension,
445
467
  getCellContent,
446
468
  onBlur: handleBlur
@@ -472,7 +494,7 @@ var determineNavigationDelta = ({ key, shift }) => {
472
494
  };
473
495
 
474
496
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
475
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
497
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
476
498
  var inlineEndLine = "[&>.dx-grid]:relative [&>.dx-grid]:after:absolute [&>.dx-grid]:after:inset-block-0 [&>.dx-grid]:after:-inline-end-px [&>.dx-grid]:after:is-px [&>.dx-grid]:after:bg-separator";
477
499
  var blockEndLine = "[&>.dx-grid]:before:absolute [&>.dx-grid]:before:inset-inline-0 [&>.dx-grid]:before:-block-end-px [&>.dx-grid]:before:bs-px [&>.dx-grid]:before:bg-separator";
478
500
  var frozen = {
@@ -481,7 +503,7 @@ var frozen = {
481
503
  frozenColsEnd: 1
482
504
  };
483
505
  var TableRoot = ({ children, role }) => {
484
- return /* @__PURE__ */ React5.createElement("div", {
506
+ return /* @__PURE__ */ React7.createElement("div", {
485
507
  role: "none",
486
508
  className: mx("relative border-bs !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
487
509
  }, children);
@@ -489,6 +511,7 @@ var TableRoot = ({ children, role }) => {
489
511
  var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwardedRef) => {
490
512
  const [dxGrid, setDxGrid] = useState2(null);
491
513
  const { hasAttention } = useAttention(model?.table ? fullyQualifiedId(model.table) : "table");
514
+ const { t } = useTranslation3(translationKey);
492
515
  useImperativeHandle(forwardedRef, () => {
493
516
  if (!model || !dxGrid) {
494
517
  return {};
@@ -507,17 +530,28 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
507
530
  model,
508
531
  dxGrid
509
532
  ]);
510
- const handleFocus = (increment, delta) => {
511
- dxGrid?.refocus(increment, delta);
512
- };
513
- const handleEnter = useCallback3((cell) => {
533
+ const handleFocus = useCallback4((increment, delta) => {
534
+ if (dxGrid) {
535
+ dxGrid.refocus(increment, delta);
536
+ }
537
+ }, [
538
+ dxGrid
539
+ ]);
540
+ const handleEnter = useCallback4((cell) => {
514
541
  if (model && cell.row === model.getRowCount() - 1) {
515
542
  model.insertRow(cell.row);
543
+ if (dxGrid) {
544
+ requestAnimationFrame(() => {
545
+ dxGrid?.scrollToRow(cell.row + 1);
546
+ dxGrid?.refocus("row", 1);
547
+ });
548
+ }
516
549
  }
517
550
  }, [
518
- model
551
+ model,
552
+ dxGrid
519
553
  ]);
520
- const handleKeyDown = useCallback3((event) => {
554
+ const handleKeyDown = useCallback4((event) => {
521
555
  const cell = closestCell(event.target);
522
556
  if (!model || !cell) {
523
557
  return;
@@ -532,7 +566,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
532
566
  }, [
533
567
  model
534
568
  ]);
535
- const handleAxisResize = useCallback3((event) => {
569
+ const handleAxisResize = useCallback4((event) => {
536
570
  if (event.axis === "col") {
537
571
  const columnIndex = parseInt(event.index, 10);
538
572
  model?.setColumnWidth(columnIndex, event.size);
@@ -540,7 +574,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
540
574
  }, [
541
575
  model
542
576
  ]);
543
- const handleWheel = useCallback3((event) => {
577
+ const handleWheel = useCallback4((event) => {
544
578
  if (!ignoreAttention && !hasAttention) {
545
579
  event.stopPropagation();
546
580
  }
@@ -548,12 +582,21 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
548
582
  hasAttention,
549
583
  ignoreAttention
550
584
  ]);
551
- const handleQuery = useCallback3(async ({ field, props }, _text) => {
585
+ const handleNewColumn = useCallback4(() => {
586
+ const columns = model?.getColumnCount();
587
+ if (dxGrid && columns) {
588
+ dxGrid.scrollToColumn(columns - 1);
589
+ }
590
+ }, [
591
+ model,
592
+ dxGrid
593
+ ]);
594
+ const handleQuery = useCallback4(async ({ field, props }, text) => {
552
595
  if (model && props.referenceSchema && field.referencePath) {
553
- const space = getSpace2(model.table);
596
+ const space = getSpace4(model.table);
554
597
  invariant2(space, void 0, {
555
- F: __dxlog_file3,
556
- L: 158,
598
+ F: __dxlog_file2,
599
+ L: 180,
557
600
  S: void 0,
558
601
  A: [
559
602
  "space",
@@ -563,7 +606,7 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
563
606
  const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
564
607
  if (schema) {
565
608
  const { objects } = await space.db.query(Filter.schema(schema)).run();
566
- return objects.map((obj) => {
609
+ const options = objects.map((obj) => {
567
610
  const value = getValue(obj, field.referencePath);
568
611
  if (!value || typeof value !== "string") {
569
612
  return void 0;
@@ -573,6 +616,15 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
573
616
  data: obj
574
617
  };
575
618
  }).filter(isNotFalsy);
619
+ return [
620
+ ...options,
621
+ {
622
+ label: t("create new object label", {
623
+ text
624
+ }),
625
+ data: createOption(text)
626
+ }
627
+ ];
576
628
  }
577
629
  }
578
630
  return [];
@@ -580,19 +632,19 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
580
632
  model
581
633
  ]);
582
634
  if (!model) {
583
- return /* @__PURE__ */ React5.createElement("span", {
635
+ return /* @__PURE__ */ React7.createElement("span", {
584
636
  role: "none",
585
637
  className: "attention-surface"
586
638
  });
587
639
  }
588
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Grid.Root, {
640
+ return /* @__PURE__ */ React7.createElement(Grid.Root, {
589
641
  id: model.table.id ?? "table-grid"
590
- }, /* @__PURE__ */ React5.createElement(TableCellEditor, {
642
+ }, /* @__PURE__ */ React7.createElement(TableCellEditor, {
591
643
  model,
592
644
  onEnter: handleEnter,
593
645
  onFocus: handleFocus,
594
646
  onQuery: handleQuery
595
- }), /* @__PURE__ */ React5.createElement(Grid.Content, {
647
+ }), /* @__PURE__ */ React7.createElement(Grid.Content, {
596
648
  onWheelCapture: handleWheel,
597
649
  className: mx("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
598
650
  frozen,
@@ -604,11 +656,16 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, ignoreAttention }, forwarde
604
656
  onKeyDown: handleKeyDown,
605
657
  overscroll: "trap",
606
658
  ref: setDxGrid
607
- })), /* @__PURE__ */ React5.createElement(RowActionsMenu, {
659
+ }), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
660
+ model
661
+ }), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
608
662
  model
609
- }), /* @__PURE__ */ React5.createElement(ColumnActionsMenu, {
663
+ }), /* @__PURE__ */ React7.createElement(ColumnSettings, {
664
+ model,
665
+ onNewColumn: handleNewColumn
666
+ }), /* @__PURE__ */ React7.createElement(RefPanel, {
610
667
  model
611
- }), /* @__PURE__ */ React5.createElement(ColumnSettings, {
668
+ }), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
612
669
  model
613
670
  }));
614
671
  });
@@ -619,42 +676,42 @@ var Table = {
619
676
 
620
677
  // packages/ui/react-ui-table/src/components/Toolbar/Toolbar.tsx
621
678
  import { createContext } from "@radix-ui/react-context";
622
- import React7 from "react";
623
- import { Toolbar as NaturalToolbar2, useTranslation as useTranslation3 } from "@dxos/react-ui";
679
+ import React9 from "react";
680
+ import { Toolbar as NaturalToolbar2, useTranslation as useTranslation4 } from "@dxos/react-ui";
624
681
 
625
682
  // packages/ui/react-ui-table/src/components/Toolbar/common.tsx
626
- import React6 from "react";
683
+ import React8 from "react";
627
684
  import { Icon, Toolbar as NaturalToolbar, Tooltip } from "@dxos/react-ui";
628
685
  var buttonStyles = "min-bs-0 p-2";
629
686
  var tooltipProps = {
630
687
  side: "top",
631
688
  classNames: "z-10"
632
689
  };
633
- var ToolbarSeparator = () => /* @__PURE__ */ React6.createElement("div", {
690
+ var ToolbarSeparator = () => /* @__PURE__ */ React8.createElement("div", {
634
691
  role: "separator",
635
692
  className: "grow"
636
693
  });
637
694
  var ToolbarButton = ({ icon, children, ...props }) => {
638
- return /* @__PURE__ */ React6.createElement(Tooltip.Root, null, /* @__PURE__ */ React6.createElement(Tooltip.Trigger, {
695
+ return /* @__PURE__ */ React8.createElement(Tooltip.Root, null, /* @__PURE__ */ React8.createElement(Tooltip.Trigger, {
639
696
  asChild: true
640
- }, /* @__PURE__ */ React6.createElement(NaturalToolbar.Button, {
697
+ }, /* @__PURE__ */ React8.createElement(NaturalToolbar.Button, {
641
698
  variant: "ghost",
642
699
  ...props,
643
700
  classNames: buttonStyles
644
- }, /* @__PURE__ */ React6.createElement(Icon, {
701
+ }, /* @__PURE__ */ React8.createElement(Icon, {
645
702
  icon,
646
703
  size: 5
647
- }), /* @__PURE__ */ React6.createElement("span", {
704
+ }), /* @__PURE__ */ React8.createElement("span", {
648
705
  className: "sr-only"
649
- }, children))), /* @__PURE__ */ React6.createElement(Tooltip.Portal, null, /* @__PURE__ */ React6.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React6.createElement(Tooltip.Arrow, null))));
706
+ }, children))), /* @__PURE__ */ React8.createElement(Tooltip.Portal, null, /* @__PURE__ */ React8.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React8.createElement(Tooltip.Arrow, null))));
650
707
  };
651
708
 
652
709
  // packages/ui/react-ui-table/src/components/Toolbar/Toolbar.tsx
653
710
  var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
654
711
  var ToolbarRoot = ({ classNames, children, onAction }) => {
655
- return /* @__PURE__ */ React7.createElement(ToolbarContextProvider, {
712
+ return /* @__PURE__ */ React9.createElement(ToolbarContextProvider, {
656
713
  onAction
657
- }, /* @__PURE__ */ React7.createElement(NaturalToolbar2.Root, {
714
+ }, /* @__PURE__ */ React9.createElement(NaturalToolbar2.Root, {
658
715
  classNames: [
659
716
  "is-full shrink-0 overflow-x-auto overflow-y-hidden p-1 attention-surface",
660
717
  classNames
@@ -663,8 +720,8 @@ var ToolbarRoot = ({ classNames, children, onAction }) => {
663
720
  };
664
721
  var Editing = () => {
665
722
  const { onAction } = useToolbarContext("Editing");
666
- const { t } = useTranslation3(translationKey);
667
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(ToolbarButton, {
723
+ const { t } = useTranslation4(translationKey);
724
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(ToolbarButton, {
668
725
  value: "add-row",
669
726
  icon: "ph--plus--regular",
670
727
  "data-testid": "table.toolbar.add-row",
@@ -675,8 +732,8 @@ var Editing = () => {
675
732
  };
676
733
  var Actions = () => {
677
734
  const { onAction } = useToolbarContext("Actions");
678
- const { t } = useTranslation3(translationKey);
679
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(ToolbarButton, {
735
+ const { t } = useTranslation4(translationKey);
736
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(ToolbarButton, {
680
737
  value: "comment",
681
738
  icon: "ph--chat-text--regular",
682
739
  "data-testid": "table.toolbar.comment",
@@ -703,11 +760,142 @@ import { getValue as getValue2, setValue, FormatEnum as FormatEnum3 } from "@dxo
703
760
  import { invariant as invariant3 } from "@dxos/invariant";
704
761
  import { PublicKey as PublicKey2 } from "@dxos/react-client";
705
762
  import { cellClassesForFieldType, cellClassesForRowSelection, formatForDisplay, formatForEditing, parseValue } from "@dxos/react-ui-form";
763
+ import { toPlaneCellIndex } from "@dxos/react-ui-grid";
706
764
  import { mx as mx2 } from "@dxos/react-ui-theme";
707
765
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
708
766
 
709
767
  // packages/ui/react-ui-table/src/model/modal-controller.ts
710
768
  import { signal } from "@preact/signals-core";
769
+ import { log as log2 } from "@dxos/log";
770
+
771
+ // packages/ui/react-ui-table/src/util/signals.ts
772
+ var touch = (value) => value;
773
+
774
+ // packages/ui/react-ui-table/src/util/table.ts
775
+ import { AST, Format, FormatEnum as FormatEnum2, S as S2, TypedObject, TypeEnum } from "@dxos/echo-schema";
776
+ import { log } from "@dxos/log";
777
+ import { PublicKey } from "@dxos/react-client";
778
+ import { create as create2 } from "@dxos/react-client/echo";
779
+ import { createFieldId, createView, ViewProjection } from "@dxos/schema";
780
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
781
+ var initializeTable = ({ space, table, initialRow = true }) => {
782
+ log.info("initializeTable", {
783
+ table
784
+ }, {
785
+ F: __dxlog_file3,
786
+ L: 32,
787
+ S: void 0,
788
+ C: (f, a) => f(...a)
789
+ });
790
+ const ContactSchema = TypedObject({
791
+ typename: `example.com/type/${PublicKey.random().truncate()}`,
792
+ version: "0.1.0"
793
+ })({
794
+ name: S2.optional(S2.String).annotations({
795
+ [AST.TitleAnnotationId]: "Name"
796
+ }),
797
+ email: S2.optional(Format.Email),
798
+ salary: S2.optional(Format.Currency()).annotations({
799
+ [AST.TitleAnnotationId]: "Salary"
800
+ })
801
+ });
802
+ const contactSchema = space.db.schemaRegistry.addSchema(ContactSchema);
803
+ table.view = createView({
804
+ name: "Test",
805
+ typename: contactSchema.typename,
806
+ jsonSchema: contactSchema.jsonSchema,
807
+ fields: [
808
+ "name",
809
+ "email",
810
+ "salary"
811
+ ]
812
+ });
813
+ const projection = new ViewProjection(contactSchema, table.view);
814
+ projection.setFieldProjection({
815
+ field: {
816
+ id: table.view.fields[2].id,
817
+ path: "salary",
818
+ size: 150
819
+ }
820
+ });
821
+ projection.setFieldProjection({
822
+ field: {
823
+ id: createFieldId(),
824
+ path: "manager",
825
+ referencePath: "name"
826
+ },
827
+ props: {
828
+ property: "manager",
829
+ type: TypeEnum.Ref,
830
+ format: FormatEnum2.Ref,
831
+ referenceSchema: contactSchema.typename,
832
+ title: "Manager"
833
+ }
834
+ });
835
+ if (initialRow) {
836
+ space.db.add(create2(contactSchema, {}));
837
+ }
838
+ return contactSchema;
839
+ };
840
+
841
+ // packages/ui/react-ui-table/src/util/table-buttons.ts
842
+ var TABLE_ATTRS = {
843
+ referencedCell: "data-table-ref-cell-button",
844
+ columnSettings: "data-table-column-settings-button",
845
+ rowMenu: "data-table-row-menu-button",
846
+ newColumn: "data-table-new-column-button"
847
+ };
848
+ var ICONS = {
849
+ referencedCell: "ph--link-simple-horizontal--regular",
850
+ columnSettings: "ph--caret-down--regular",
851
+ rowMenu: "ph--dots-three--regular",
852
+ newColumn: "ph--plus--regular"
853
+ };
854
+ var createButtonHtml = ({ button, value = "", disabled = false, testId }) => {
855
+ const buttonClasses = "ch-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 inline-end-2";
856
+ return `<button class="${buttonClasses}" ${TABLE_ATTRS[button]}="${value}" data-testid="${testId}" ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${ICONS[button]}"/></svg></button>`;
857
+ };
858
+ var tableButtons = {
859
+ referencedCell: {
860
+ attr: TABLE_ATTRS.referencedCell,
861
+ icon: ICONS.referencedCell,
862
+ render: ({ targetId, schemaId }) => createButtonHtml({
863
+ button: "referencedCell",
864
+ value: `${schemaId}#${targetId}`,
865
+ testId: "table-ref-cell-button"
866
+ })
867
+ },
868
+ columnSettings: {
869
+ attr: TABLE_ATTRS.columnSettings,
870
+ icon: ICONS.columnSettings,
871
+ render: ({ fieldId }) => createButtonHtml({
872
+ button: "columnSettings",
873
+ value: fieldId,
874
+ testId: "table-column-settings-button"
875
+ })
876
+ },
877
+ rowMenu: {
878
+ attr: TABLE_ATTRS.rowMenu,
879
+ icon: ICONS.rowMenu,
880
+ render: ({ rowIndex }) => createButtonHtml({
881
+ button: "rowMenu",
882
+ value: rowIndex.toString(),
883
+ testId: "table-row-menu-button"
884
+ })
885
+ },
886
+ addColumn: {
887
+ attr: TABLE_ATTRS.newColumn,
888
+ icon: ICONS.newColumn,
889
+ render: ({ disabled } = {}) => createButtonHtml({
890
+ button: "newColumn",
891
+ disabled,
892
+ testId: "table-new-column-button"
893
+ })
894
+ }
895
+ };
896
+
897
+ // packages/ui/react-ui-table/src/model/modal-controller.ts
898
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
711
899
  var ModalController = class {
712
900
  constructor() {
713
901
  this._state = signal({
@@ -748,6 +936,16 @@ var ModalController = class {
748
936
  };
749
937
  return true;
750
938
  }
939
+ const refButton = target.closest(`button[${tableButtons.referencedCell.attr}]`);
940
+ if (refButton) {
941
+ this._triggerRef.current = refButton;
942
+ const [schemaId, targetId] = refButton.getAttribute(tableButtons.referencedCell.attr).split("#");
943
+ this._state.value = {
944
+ type: "refPanel",
945
+ targetId,
946
+ typename: schemaId
947
+ };
948
+ }
751
949
  return false;
752
950
  };
753
951
  this.openColumnSettings = () => {
@@ -764,6 +962,24 @@ var ModalController = class {
764
962
  });
765
963
  }
766
964
  };
965
+ this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
966
+ if (anchorCell) {
967
+ this._triggerRef.current = anchorCell;
968
+ this._state.value = {
969
+ type: "createRefPanel",
970
+ typename,
971
+ initialValues,
972
+ onCreate
973
+ };
974
+ } else {
975
+ log2.warn("anchor cell not found while creating new ref", void 0, {
976
+ F: __dxlog_file4,
977
+ L: 119,
978
+ S: this,
979
+ C: (f, a) => f(...a)
980
+ });
981
+ }
982
+ };
767
983
  this.close = () => {
768
984
  this._state.value = {
769
985
  type: "closed"
@@ -869,7 +1085,7 @@ var tableControls = {
869
1085
  };
870
1086
 
871
1087
  // packages/ui/react-ui-table/src/model/table-model.ts
872
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
1088
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
873
1089
  var TableModel = class extends Resource2 {
874
1090
  constructor({ table, projection, sorting = [], pinnedRows = {
875
1091
  top: [],
@@ -926,14 +1142,14 @@ var TableModel = class extends Resource2 {
926
1142
  }
927
1143
  };
928
1144
  this.getMainGridCells = (range) => {
929
- const values = {};
1145
+ const cells = {};
930
1146
  const fields = this._table.view?.fields ?? [];
931
1147
  const addCell = (obj, field, colIndex, displayIndex) => {
932
1148
  const { props } = this._projection.getFieldProjection(field.id);
933
- const value = {
1149
+ const cell = {
934
1150
  get value() {
935
- const value2 = getValue2(obj, field.path);
936
- if (value2 == null) {
1151
+ const value = getValue2(obj, field.path);
1152
+ if (value == null) {
937
1153
  return "";
938
1154
  }
939
1155
  switch (props.format) {
@@ -941,13 +1157,13 @@ var TableModel = class extends Resource2 {
941
1157
  if (!field.referencePath) {
942
1158
  return "";
943
1159
  }
944
- return getValue2(value2, field.referencePath);
1160
+ return getValue2(value, field.referencePath);
945
1161
  }
946
1162
  default: {
947
1163
  return formatForDisplay({
948
1164
  type: props.type,
949
1165
  format: props.format,
950
- value: value2
1166
+ value
951
1167
  });
952
1168
  }
953
1169
  }
@@ -966,13 +1182,20 @@ var TableModel = class extends Resource2 {
966
1182
  classes.push(rowSelectionClasses);
967
1183
  }
968
1184
  if (classes.length > 0) {
969
- value.className = mx2(classes.flat());
1185
+ cell.className = mx2(classes.flat());
1186
+ }
1187
+ if (cell.value && props.format === FormatEnum3.Ref && props.referenceSchema) {
1188
+ const targetObj = getValue2(obj, field.path);
1189
+ cell.accessoryHtml = tableButtons.referencedCell.render({
1190
+ targetId: targetObj.id,
1191
+ schemaId: props.referenceSchema
1192
+ });
970
1193
  }
971
- const idx = fromGridCell({
1194
+ const idx = toPlaneCellIndex({
972
1195
  col: colIndex,
973
1196
  row: displayIndex
974
1197
  });
975
- values[idx] = value;
1198
+ cells[idx] = cell;
976
1199
  };
977
1200
  for (let row = range.start.row; row <= range.end.row && row < this._sortedRows.value.length; row++) {
978
1201
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
@@ -983,17 +1206,18 @@ var TableModel = class extends Resource2 {
983
1206
  addCell(this._sortedRows.value[row], field, col, row);
984
1207
  }
985
1208
  }
986
- return values;
1209
+ return cells;
987
1210
  };
988
1211
  this.getHeaderCells = (range) => {
989
- const values = {};
1212
+ const cells = {};
990
1213
  const fields = this.table.view?.fields ?? [];
991
1214
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
992
1215
  const { field, props } = this._projection.getFieldProjection(fields[col].id);
993
- values[fromGridCell({
1216
+ cells[toPlaneCellIndex({
994
1217
  col,
995
1218
  row: 0
996
1219
  })] = {
1220
+ // TODO(burdon): Use same logic as form for fallback title.
997
1221
  value: props.title ?? field.path,
998
1222
  readonly: true,
999
1223
  resizeHandle: "col",
@@ -1002,14 +1226,14 @@ var TableModel = class extends Resource2 {
1002
1226
  })
1003
1227
  };
1004
1228
  }
1005
- return values;
1229
+ return cells;
1006
1230
  };
1007
1231
  this.getSelectionColumnCells = (range) => {
1008
- const values = {};
1232
+ const cells = {};
1009
1233
  for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
1010
1234
  const isSelected = this._selection.isRowIndexSelected(row);
1011
1235
  const classes = cellClassesForRowSelection(isSelected);
1012
- values[fromGridCell({
1236
+ cells[toPlaneCellIndex({
1013
1237
  col: 0,
1014
1238
  row
1015
1239
  })] = {
@@ -1022,14 +1246,14 @@ var TableModel = class extends Resource2 {
1022
1246
  })
1023
1247
  };
1024
1248
  }
1025
- return values;
1249
+ return cells;
1026
1250
  };
1027
1251
  this.getActionColumnCells = (range) => {
1028
- const values = {};
1252
+ const cells = {};
1029
1253
  for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
1030
1254
  const isSelected = this._selection.isRowIndexSelected(row);
1031
1255
  const classes = cellClassesForRowSelection(isSelected);
1032
- values[fromGridCell({
1256
+ cells[toPlaneCellIndex({
1033
1257
  col: 0,
1034
1258
  row
1035
1259
  })] = {
@@ -1041,11 +1265,11 @@ var TableModel = class extends Resource2 {
1041
1265
  })
1042
1266
  };
1043
1267
  }
1044
- return values;
1268
+ return cells;
1045
1269
  };
1046
1270
  this.getSelectAllCell = () => {
1047
1271
  return {
1048
- [fromGridCell({
1272
+ [toPlaneCellIndex({
1049
1273
  col: 0,
1050
1274
  row: 0
1051
1275
  })]: {
@@ -1061,7 +1285,7 @@ var TableModel = class extends Resource2 {
1061
1285
  };
1062
1286
  this.getNewColumnCell = () => {
1063
1287
  return {
1064
- [fromGridCell({
1288
+ [toPlaneCellIndex({
1065
1289
  col: 0,
1066
1290
  row: 0
1067
1291
  })]: {
@@ -1191,8 +1415,8 @@ var TableModel = class extends Resource2 {
1191
1415
  }
1192
1416
  get columnMeta() {
1193
1417
  invariant3(this._columnMeta, void 0, {
1194
- F: __dxlog_file4,
1195
- L: 124,
1418
+ F: __dxlog_file5,
1419
+ L: 126,
1196
1420
  S: this,
1197
1421
  A: [
1198
1422
  "this._columnMeta",
@@ -1298,7 +1522,8 @@ var TableModel = class extends Resource2 {
1298
1522
  this?._table?.view?.fields.forEach((field) => touch(getValue2(obj, field.path)));
1299
1523
  this._onCellUpdate?.({
1300
1524
  row,
1301
- col: start.col
1525
+ col: start.col,
1526
+ plane: "grid"
1302
1527
  });
1303
1528
  }));
1304
1529
  }
@@ -1396,12 +1621,11 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1396
1621
  };
1397
1622
  export {
1398
1623
  Table,
1624
+ TableSchema,
1399
1625
  TableType,
1400
1626
  Toolbar,
1401
- fromGridCell,
1402
1627
  initializeTable,
1403
1628
  tableButtons,
1404
- toGridCell,
1405
1629
  touch,
1406
1630
  translations_default as translations,
1407
1631
  useTableModel,