@dxos/react-ui-table 0.7.4 → 0.7.5-main.9cb18ac

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 (90) hide show
  1. package/dist/lib/browser/{chunk-IYCSJDMB.mjs → chunk-AT7O4RAD.mjs} +4 -4
  2. package/dist/lib/browser/{chunk-IYCSJDMB.mjs.map → chunk-AT7O4RAD.mjs.map} +2 -2
  3. package/dist/lib/browser/index.mjs +1407 -1218
  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 +1 -1
  7. package/dist/lib/node/{chunk-MHBMVCFZ.cjs → chunk-YSBXNBDJ.cjs} +6 -6
  8. package/dist/lib/node/{chunk-MHBMVCFZ.cjs.map → chunk-YSBXNBDJ.cjs.map} +2 -2
  9. package/dist/lib/node/index.cjs +1139 -936
  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 +3 -3
  13. package/dist/lib/node/types/index.cjs.map +1 -1
  14. package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs → chunk-6OH2NHUX.mjs} +4 -4
  15. package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs.map → chunk-6OH2NHUX.mjs.map} +2 -2
  16. package/dist/lib/node-esm/index.mjs +1407 -1218
  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 +1 -1
  20. package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts +1 -1
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +4 -3
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -2
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/CreateRefPanel.d.ts +3 -2
  26. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/RefPanel.d.ts +4 -3
  28. package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/RowActionsMenu.d.ts +3 -2
  30. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/Table.d.ts +2 -1
  32. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -2
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/testing.d.ts +55 -71
  38. package/dist/types/src/components/testing.d.ts.map +1 -1
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/model/index.d.ts +1 -0
  42. package/dist/types/src/model/index.d.ts.map +1 -1
  43. package/dist/types/src/model/modal-controller.d.ts +6 -2
  44. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  45. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  46. package/dist/types/src/model/table-model.d.ts +8 -12
  47. package/dist/types/src/model/table-model.d.ts.map +1 -1
  48. package/dist/types/src/model/table-presentation.d.ts +22 -0
  49. package/dist/types/src/model/table-presentation.d.ts.map +1 -0
  50. package/dist/types/src/model/table-presentation.test.d.ts +2 -0
  51. package/dist/types/src/model/table-presentation.test.d.ts.map +1 -0
  52. package/dist/types/src/playwright/TableManager.d.ts +2 -1
  53. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  54. package/dist/types/src/types/table.d.ts +118 -154
  55. package/dist/types/src/types/table.d.ts.map +1 -1
  56. package/dist/types/src/util/index.d.ts +1 -0
  57. package/dist/types/src/util/index.d.ts.map +1 -1
  58. package/dist/types/src/util/table-buttons.d.ts +50 -20
  59. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  60. package/dist/types/src/util/table-controls.d.ts +32 -9
  61. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  62. package/dist/types/src/util/table.d.ts +2 -2
  63. package/dist/types/src/util/table.d.ts.map +1 -1
  64. package/dist/types/tsconfig.tsbuildinfo +1 -0
  65. package/package.json +29 -29
  66. package/src/components/Table/ColumnActionsMenu.tsx +8 -8
  67. package/src/components/Table/ColumnSettings.tsx +11 -11
  68. package/src/components/Table/CreateRefPanel.tsx +13 -14
  69. package/src/components/Table/RefPanel.tsx +9 -9
  70. package/src/components/Table/RowActionsMenu.tsx +6 -7
  71. package/src/components/Table/Table.stories.tsx +40 -23
  72. package/src/components/Table/Table.tsx +235 -148
  73. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +13 -12
  74. package/src/components/TableCellEditor/TableCellEditor.tsx +6 -4
  75. package/src/components/testing.ts +10 -8
  76. package/src/index.ts +2 -0
  77. package/src/model/index.ts +1 -0
  78. package/src/model/modal-controller.ts +15 -48
  79. package/src/model/selection-model.ts +12 -1
  80. package/src/model/table-model.test.ts +4 -71
  81. package/src/model/table-model.ts +59 -232
  82. package/src/model/table-presentation.test.ts +102 -0
  83. package/src/model/table-presentation.ts +217 -0
  84. package/src/playwright/TableManager.ts +5 -1
  85. package/src/playwright/smoke.spec.ts +79 -1
  86. package/src/types/table.ts +3 -3
  87. package/src/util/index.ts +1 -0
  88. package/src/util/table-buttons.ts +97 -48
  89. package/src/util/table-controls.ts +71 -7
  90. package/src/util/table.ts +21 -13
@@ -28,19 +28,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
+ BUTTON_IDENTIFIERS: () => BUTTON_IDENTIFIERS,
32
+ CONTROL_IDENTIFIERS: () => CONTROL_IDENTIFIERS,
33
+ ModalController: () => ModalController,
31
34
  Table: () => Table,
32
- TableSchema: () => import_chunk_MHBMVCFZ.TableSchema,
33
- TableType: () => import_chunk_MHBMVCFZ.TableType,
35
+ TableModel: () => TableModel,
36
+ TablePresentation: () => TablePresentation,
37
+ TableSchema: () => import_chunk_YSBXNBDJ.TableSchema,
38
+ TableType: () => import_chunk_YSBXNBDJ.TableType,
34
39
  Toolbar: () => Toolbar,
35
40
  initializeTable: () => initializeTable,
41
+ renderCheckbox: () => renderCheckbox,
42
+ renderSwitch: () => renderSwitch,
36
43
  tableButtons: () => tableButtons,
44
+ tableControls: () => tableControls,
37
45
  touch: () => touch,
38
46
  translations: () => translations_default,
39
47
  useTableModel: () => useTableModel,
40
48
  useToolbarContext: () => useToolbarContext
41
49
  });
42
50
  module.exports = __toCommonJS(node_exports);
43
- var import_chunk_MHBMVCFZ = require("./chunk-MHBMVCFZ.cjs");
51
+ var import_chunk_YSBXNBDJ = require("./chunk-YSBXNBDJ.cjs");
44
52
  var import_react = __toESM(require("react"));
45
53
  var import_echo_schema = require("@dxos/echo-schema");
46
54
  var import_invariant = require("@dxos/invariant");
@@ -68,10 +76,33 @@ var import_react_ui5 = require("@dxos/react-ui");
68
76
  var import_react_ui_form3 = require("@dxos/react-ui-form");
69
77
  var import_react6 = __toESM(require("react"));
70
78
  var import_react_ui6 = require("@dxos/react-ui");
71
- var import_react7 = __toESM(require("react"));
79
+ var import_signals_core = require("@preact/signals-core");
80
+ var import_lodash = __toESM(require("lodash.orderby"));
81
+ var import_context = require("@dxos/context");
72
82
  var import_echo_schema3 = require("@dxos/echo-schema");
73
83
  var import_invariant2 = require("@dxos/invariant");
84
+ var import_live_object = require("@dxos/live-object");
85
+ var import_react_client = require("@dxos/react-client");
86
+ var import_react_ui_form4 = require("@dxos/react-ui-form");
87
+ var import_signals_core2 = require("@preact/signals-core");
88
+ var import_context2 = require("@dxos/context");
89
+ var import_echo_schema4 = require("@dxos/echo-schema");
90
+ var import_log = require("@dxos/log");
91
+ var import_react_client2 = require("@dxos/react-client");
92
+ var import_echo5 = require("@dxos/react-client/echo");
93
+ var import_schema = require("@dxos/schema");
94
+ var import_signals_core3 = require("@preact/signals-core");
95
+ var import_log2 = require("@dxos/log");
96
+ var import_signals_core4 = require("@preact/signals-core");
97
+ var import_echo_schema5 = require("@dxos/echo-schema");
98
+ var import_react_ui_form5 = require("@dxos/react-ui-form");
74
99
  var import_react_ui_grid3 = require("@dxos/react-ui-grid");
100
+ var import_react_ui_theme2 = require("@dxos/react-ui-theme");
101
+ var import_schema2 = require("@dxos/schema");
102
+ var import_react7 = __toESM(require("react"));
103
+ var import_echo_schema6 = require("@dxos/echo-schema");
104
+ var import_invariant3 = require("@dxos/invariant");
105
+ var import_react_ui_grid4 = require("@dxos/react-ui-grid");
75
106
  var import_autocomplete = require("@codemirror/autocomplete");
76
107
  var import_view = require("@codemirror/view");
77
108
  var import_react_context = require("@radix-ui/react-context");
@@ -80,25 +111,6 @@ var import_react_ui7 = require("@dxos/react-ui");
80
111
  var import_react9 = __toESM(require("react"));
81
112
  var import_react_ui8 = require("@dxos/react-ui");
82
113
  var import_react10 = require("react");
83
- var import_signals_core = require("@preact/signals-core");
84
- var import_lodash = __toESM(require("lodash.orderby"));
85
- var import_context = require("@dxos/context");
86
- var import_echo_schema4 = require("@dxos/echo-schema");
87
- var import_invariant3 = require("@dxos/invariant");
88
- var import_react_client = require("@dxos/react-client");
89
- var import_react_ui_form4 = require("@dxos/react-ui-form");
90
- var import_react_ui_grid4 = require("@dxos/react-ui-grid");
91
- var import_react_ui_theme2 = require("@dxos/react-ui-theme");
92
- var import_schema = require("@dxos/schema");
93
- var import_signals_core2 = require("@preact/signals-core");
94
- var import_log = require("@dxos/log");
95
- var import_echo_schema5 = require("@dxos/echo-schema");
96
- var import_log2 = require("@dxos/log");
97
- var import_react_client2 = require("@dxos/react-client");
98
- var import_echo5 = require("@dxos/react-client/echo");
99
- var import_schema2 = require("@dxos/schema");
100
- var import_signals_core3 = require("@preact/signals-core");
101
- var import_context2 = require("@dxos/context");
102
114
  var translationKey = "table";
103
115
  var translations_default = [
104
116
  {
@@ -128,20 +140,20 @@ var translations_default = [
128
140
  }
129
141
  }
130
142
  ];
131
- var ColumnActionsMenu = ({ model }) => {
143
+ var ColumnActionsMenu = ({ model, modals }) => {
132
144
  const { t } = (0, import_react_ui2.useTranslation)(translationKey);
133
- const state = model?.modalController.state.value;
134
- if (!model || state?.type !== "column") {
145
+ const state = modals.state.value;
146
+ if (state?.type !== "column") {
135
147
  return null;
136
148
  }
137
149
  const currentSort = model.sorting;
138
150
  const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
139
151
  return /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Root, {
140
152
  modal: false,
141
- open: state?.type === "column",
142
- onOpenChange: model.modalController.close
153
+ open: true,
154
+ onOpenChange: modals.close
143
155
  }, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.VirtualTrigger, {
144
- virtualRef: model.modalController.trigger
156
+ virtualRef: modals.trigger
145
157
  }), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Portal, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Content, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
146
158
  "data-testid": "column-sort-descending",
147
159
  onClick: () => model.setSort(state.fieldId, "desc")
@@ -156,12 +168,12 @@ var ColumnActionsMenu = ({ model }) => {
156
168
  onClick: () => model.deleteColumn(state.fieldId)
157
169
  }, t("column action delete")), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
158
170
  "data-testid": "column-settings",
159
- onClick: () => model.modalController.openColumnSettings()
171
+ onClick: () => modals.openColumnSettings()
160
172
  }, t("column action settings"))), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Arrow, null))));
161
173
  };
162
- var ColumnSettings = ({ model, onNewColumn }) => {
174
+ var ColumnSettings = ({ model, modals, onNewColumn }) => {
163
175
  const [newField, setNewField] = (0, import_react3.useState)();
164
- const state = model?.modalController.state.value;
176
+ const state = modals.state.value;
165
177
  const space = (0, import_echo2.getSpace)(model?.table);
166
178
  (0, import_react3.useEffect)(() => {
167
179
  if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
@@ -180,19 +192,19 @@ var ColumnSettings = ({ model, onNewColumn }) => {
180
192
  if (state?.type === "columnSettings") {
181
193
  const { mode } = state;
182
194
  if (mode.type === "edit") {
183
- return model?.table?.view?.fields.find((f) => f.id === mode.fieldId);
195
+ return model?.table?.view?.target?.fields.find((f) => f.id === mode.fieldId);
184
196
  }
185
197
  }
186
198
  return void 0;
187
199
  }, [
188
- model?.table?.view?.fields,
200
+ model?.table?.view?.target?.fields,
189
201
  state
190
202
  ]);
191
203
  const field = existingField ?? newField;
192
204
  const handleSave = (0, import_react3.useCallback)(() => {
193
- model?.modalController.close();
205
+ modals.close();
194
206
  }, [
195
- model?.modalController
207
+ modals
196
208
  ]);
197
209
  const handleCancel = (0, import_react3.useCallback)(() => {
198
210
  if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
@@ -203,18 +215,18 @@ var ColumnSettings = ({ model, onNewColumn }) => {
203
215
  state,
204
216
  newField
205
217
  ]);
206
- if (!model?.table?.view || !model.projection || !field) {
218
+ if (!model?.table?.view?.target || !model.projection || !field) {
207
219
  return null;
208
220
  }
209
221
  return /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.Root, {
210
222
  modal: false,
211
223
  open: state?.type === "columnSettings"
212
224
  }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.VirtualTrigger, {
213
- virtualRef: model.modalController.trigger
225
+ virtualRef: modals.trigger
214
226
  }), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.Portal, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.Content, {
215
227
  classNames: "md:is-64"
216
228
  }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.Viewport, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui_form.FieldEditor, {
217
- view: model.table.view,
229
+ view: model.table.view.target,
218
230
  projection: model.projection,
219
231
  field,
220
232
  registry: space?.db.schemaRegistry,
@@ -222,15 +234,17 @@ var ColumnSettings = ({ model, onNewColumn }) => {
222
234
  onCancel: handleCancel
223
235
  })), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.DropdownMenu.Arrow, null))));
224
236
  };
225
- var CreateRefPanel = ({ model, __gridScope }) => {
237
+ var CreateRefPanel = ({ model, modals, __gridScope }) => {
226
238
  const { id: gridId } = (0, import_react_ui_grid2.useGridContext)("TableCellEditor", __gridScope);
227
239
  const space = (0, import_echo3.getSpace)(model?.table);
228
- const state = model?.modalController.state.value;
240
+ const state = modals.state.value;
229
241
  const schema = (0, import_react4.useMemo)(() => {
230
242
  if (!space || state?.type !== "createRefPanel") {
231
243
  return;
232
244
  }
233
- const schema2 = space.db.schemaRegistry.getSchema(state.typename)?.schema;
245
+ const [schema2] = space.db.schemaRegistry.query({
246
+ typename: state.typename
247
+ }).runSync();
234
248
  if (schema2) {
235
249
  const omit = import_echo_schema2.S.omit("id");
236
250
  return omit(schema2);
@@ -243,23 +257,25 @@ var CreateRefPanel = ({ model, __gridScope }) => {
243
257
  if (!model || !space || state?.type !== "createRefPanel") {
244
258
  return;
245
259
  }
246
- const schema2 = space.db.schemaRegistry.getSchema(state.typename)?.schema;
260
+ const [schema2] = space.db.schemaRegistry.query({
261
+ typename: state.typename
262
+ }).runSync();
247
263
  if (schema2) {
248
264
  const obj = space.db.add((0, import_echo3.create)(schema2, values));
249
265
  state.onCreate?.(obj);
250
266
  }
251
- void model.modalController.close();
267
+ void modals.close();
252
268
  }, [
253
- model?.modalController,
269
+ modals,
254
270
  space,
255
271
  state
256
272
  ]);
257
273
  const handleCancel = (0, import_react4.useCallback)(() => {
258
274
  if (model) {
259
- model.modalController.close();
275
+ modals.close();
260
276
  }
261
277
  }, [
262
- model?.modalController
278
+ modals
263
279
  ]);
264
280
  if (!model?.table?.view || !model.projection) {
265
281
  return null;
@@ -269,11 +285,11 @@ var CreateRefPanel = ({ model, __gridScope }) => {
269
285
  open: state?.type === "createRefPanel" && !!schema,
270
286
  onOpenChange: (nextOpen) => {
271
287
  if (model && !nextOpen) {
272
- return model.modalController.close();
288
+ return modals.close();
273
289
  }
274
290
  }
275
291
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.VirtualTrigger, {
276
- virtualRef: model.modalController.trigger
292
+ virtualRef: modals.trigger
277
293
  }), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Portal, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Content, {
278
294
  classNames: "md:is-64",
279
295
  "data-grid": gridId
@@ -291,24 +307,24 @@ var getRefTargetObj = (space, id) => {
291
307
  return void 0;
292
308
  }
293
309
  };
294
- var RefPanel = ({ model }) => {
295
- const state = model?.modalController.state.value;
296
- const space = (0, import_echo4.getSpace)(model?.table);
310
+ var RefPanel = ({ model, modals }) => {
311
+ const state = modals.state.value;
312
+ const space = (0, import_echo4.getSpace)(model.table);
297
313
  const targetObj = getRefTargetObj(space, state?.type === "refPanel" ? state.targetId : void 0);
298
314
  const schema = space && state?.type === "refPanel" ? space.db.schemaRegistry.getSchema(state.typename) : void 0;
299
- if (!model?.table?.view || !model.projection) {
315
+ if (!model.table?.view || !model.projection) {
300
316
  return null;
301
317
  }
302
318
  return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Popover.Root, {
303
319
  modal: false,
304
320
  open: state?.type === "refPanel" && !!targetObj && !!schema,
305
321
  onOpenChange: (nextOpen) => {
306
- if (model && !nextOpen) {
307
- return model.modalController.close();
322
+ if (!nextOpen) {
323
+ return modals.close();
308
324
  }
309
325
  }
310
326
  }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Popover.VirtualTrigger, {
311
- virtualRef: model.modalController.trigger
327
+ virtualRef: modals.trigger
312
328
  }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Popover.Portal, null, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Popover.Content, {
313
329
  classNames: "md:is-64"
314
330
  }, targetObj && schema && /* @__PURE__ */ import_react5.default.createElement(import_react_ui_form3.Form, {
@@ -317,687 +333,236 @@ var RefPanel = ({ model }) => {
317
333
  schema
318
334
  }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Popover.Arrow, null))));
319
335
  };
320
- var RowActionsMenu = ({ model }) => {
336
+ var RowActionsMenu = ({ model, modals }) => {
321
337
  const { t } = (0, import_react_ui6.useTranslation)(translationKey);
322
338
  const hasSelection = model.selection.hasSelection.value;
323
- const state = model.modalController.state.value;
339
+ const state = modals.state.value;
324
340
  if (state?.type !== "row") {
325
341
  return null;
326
342
  }
327
343
  return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Root, {
328
344
  modal: false,
329
345
  open: true,
330
- onOpenChange: model.modalController.close
346
+ onOpenChange: modals.close
331
347
  }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.VirtualTrigger, {
332
- virtualRef: model.modalController.trigger
348
+ virtualRef: modals.trigger
333
349
  }), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Content, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Viewport, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Item, {
334
350
  "data-testid": "row-menu-delete",
335
351
  onClick: () => model.deleteRow(state.rowIndex)
336
352
  }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.DropdownMenu.Arrow, null)));
337
353
  };
338
- var completion = ({ debug, onQuery, onMatch }) => {
339
- return [
340
- import_view.EditorView.theme({
341
- ".cm-completionDialog": {
342
- width: "var(--dx-gridCellWidth)"
343
- }
344
- }),
345
- (0, import_autocomplete.autocompletion)({
346
- icons: false,
347
- activateOnTyping: true,
348
- closeOnBlur: !debug,
349
- override: [
350
- async (context) => {
351
- const text = context.state.doc.toString();
352
- return {
353
- from: 0,
354
- options: await onQuery(text)
355
- };
356
- }
357
- ],
358
- // TODO(burdon): Consts from grid (to line-up with grid).
359
- tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
360
- optionClass: () => "flex h-[33px] items-center"
354
+ var touch = (value) => value;
355
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
356
+ var initializeTable = async ({ space, table, initialRow = true }) => {
357
+ (0, import_log.log)("initializeTable", {
358
+ table
359
+ }, {
360
+ F: __dxlog_file,
361
+ L: 36,
362
+ S: void 0,
363
+ C: (f, a) => f(...a)
364
+ });
365
+ const ContactSchema = (0, import_echo_schema4.TypedObject)({
366
+ typename: `example.com/type/${import_react_client2.PublicKey.random().truncate()}`,
367
+ version: "0.1.0"
368
+ })({
369
+ name: import_echo_schema4.S.optional(import_echo_schema4.S.String).annotations({
370
+ [import_echo_schema4.AST.TitleAnnotationId]: "Name"
361
371
  }),
362
- // Check for accepted completion metadata in the transaction.
363
- import_view.EditorView.updateListener.of((update) => {
364
- update.transactions.forEach((tr) => {
365
- const completion2 = tr.annotation(import_autocomplete.pickedCompletion);
366
- if (completion2) {
367
- onMatch(completion2.data);
368
- }
369
- });
372
+ active: import_echo_schema4.S.optional(import_echo_schema4.S.Boolean),
373
+ email: import_echo_schema4.S.optional(import_echo_schema4.Format.Email),
374
+ salary: import_echo_schema4.S.optional(import_echo_schema4.Format.Currency()).annotations({
375
+ [import_echo_schema4.AST.TitleAnnotationId]: "Salary"
370
376
  })
371
- ];
372
- };
373
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
374
- var newValue = Symbol.for("newValue");
375
- var createOption = (text) => ({
376
- [newValue]: true,
377
- text
378
- });
379
- var isCreateOption = (data) => typeof data === "object" && data[newValue];
380
- var TableCellEditor = ({ model, onEnter, onFocus, onQuery, __gridScope }) => {
381
- const { id: gridId, editing, setEditing } = (0, import_react_ui_grid3.useGridContext)("TableCellEditor", __gridScope);
382
- const suppressNextBlur = (0, import_react7.useRef)(false);
383
- const fieldProjection = (0, import_react7.useMemo)(() => {
384
- if (!model || !editing) {
385
- return;
386
- }
387
- const { col } = (0, import_react_ui_grid3.parseCellIndex)(editing.index);
388
- const field = model.projection.view.fields[col];
389
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
390
- (0, import_invariant2.invariant)(fieldProjection2, void 0, {
391
- F: __dxlog_file,
392
- L: 65,
393
- S: void 0,
394
- A: [
395
- "fieldProjection",
396
- ""
397
- ]
398
- });
399
- return fieldProjection2;
400
- }, [
401
- model,
402
- editing
403
- ]);
404
- const handleEnter = (0, import_react7.useCallback)((value) => {
405
- if (!model || !editing) {
406
- return;
407
- }
408
- const cell = (0, import_react_ui_grid3.parseCellIndex)(editing.index);
409
- model.setCellData(cell, value);
410
- onEnter?.(cell);
411
- onFocus?.();
412
- setEditing(null);
413
- }, [
414
- model,
415
- editing
416
- ]);
417
- const handleBlur = (0, import_react7.useCallback)((value) => {
418
- if (!model || !editing) {
419
- return;
420
- }
421
- if (suppressNextBlur.current) {
422
- suppressNextBlur.current = false;
423
- return;
424
- }
425
- const cell = (0, import_react_ui_grid3.parseCellIndex)(editing.index);
426
- if (value !== void 0) {
427
- model.setCellData(cell, value);
428
- }
429
- }, [
430
- model,
431
- editing
432
- ]);
433
- const handleClose = (0, import_react7.useCallback)((value, event) => {
434
- if (!model || !editing || !fieldProjection) {
435
- return;
436
- }
437
- const cell = (0, import_react_ui_grid3.parseCellIndex)(editing.index);
438
- onEnter?.(cell);
439
- if (event && onFocus) {
440
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
441
- }
442
- }, [
443
- model,
444
- editing,
445
- onFocus,
446
- onEnter,
447
- fieldProjection,
448
- determineNavigationAxis,
449
- determineNavigationDelta
450
- ]);
451
- const extension = (0, import_react7.useMemo)(() => {
452
- if (!fieldProjection) {
453
- return [];
454
- }
455
- const extension2 = [
456
- (0, import_react_ui_grid3.editorKeys)({
457
- onClose: handleClose,
458
- ...editing?.initialContent && {
459
- onNav: handleClose
460
- }
461
- })
462
- ];
463
- if (onQuery) {
464
- switch (fieldProjection.props.format) {
465
- case import_echo_schema3.FormatEnum.Ref: {
466
- extension2.push([
467
- completion({
468
- onQuery: (text) => onQuery(fieldProjection, text),
469
- onMatch: (data) => {
470
- if (model && editing) {
471
- if (isCreateOption(data)) {
472
- const { field, props } = fieldProjection;
473
- if (props.referenceSchema) {
474
- suppressNextBlur.current = true;
475
- model.modalController.openCreateRef(props.referenceSchema, document.querySelector((0, import_react_ui_grid3.cellQuery)(editing.index, gridId)), {
476
- [field.referencePath]: data.text
477
- }, (data2) => {
478
- handleEnter(data2);
479
- });
480
- }
481
- } else {
482
- handleEnter(data);
483
- }
484
- }
485
- }
486
- })
487
- ]);
488
- break;
489
- }
490
- }
491
- }
492
- return extension2;
493
- }, [
494
- model,
495
- editing,
496
- fieldProjection,
497
- handleClose
377
+ });
378
+ const [contactSchema] = await space.db.schemaRegistry.register([
379
+ ContactSchema
498
380
  ]);
499
- const getCellContent = (0, import_react7.useCallback)(() => {
500
- if (model && editing) {
501
- const value = model.getCellData((0, import_react_ui_grid3.parseCellIndex)(editing.index));
502
- return value !== void 0 ? String(value) : "";
381
+ table.view = (0, import_echo5.makeRef)((0, import_schema.createView)({
382
+ name: "Test",
383
+ typename: contactSchema.typename,
384
+ jsonSchema: contactSchema.jsonSchema,
385
+ fields: [
386
+ "name",
387
+ "active",
388
+ "email",
389
+ "salary"
390
+ ]
391
+ }));
392
+ const projection = new import_schema.ViewProjection(contactSchema, table.view.target);
393
+ projection.setFieldProjection({
394
+ field: {
395
+ id: table.view.target.fields.find((f) => f.path === "salary").id,
396
+ path: "salary",
397
+ size: 150
503
398
  }
504
- }, [
505
- model,
506
- editing
507
- ]);
508
- return /* @__PURE__ */ import_react7.default.createElement(import_react_ui_grid3.GridCellEditor, {
509
- extension,
510
- getCellContent,
511
- onBlur: handleBlur
512
399
  });
513
- };
514
- var determineNavigationAxis = ({ key }) => {
515
- switch (key) {
516
- case "ArrowUp":
517
- case "ArrowDown":
518
- case "Enter": {
519
- return "row";
400
+ projection.setFieldProjection({
401
+ field: {
402
+ id: (0, import_schema.createFieldId)(),
403
+ path: "manager",
404
+ referencePath: "name"
405
+ },
406
+ props: {
407
+ property: "manager",
408
+ type: import_echo_schema4.TypeEnum.Ref,
409
+ format: import_echo_schema4.FormatEnum.Ref,
410
+ referenceSchema: contactSchema.typename,
411
+ title: "Manager"
520
412
  }
521
- case "ArrowLeft":
522
- case "ArrowRight":
523
- case "Tab":
524
- return "col";
525
- }
526
- };
527
- var determineNavigationDelta = ({ key, shift }) => {
528
- switch (key) {
529
- case "ArrowUp":
530
- case "ArrowLeft":
531
- return -1;
532
- case "ArrowDown":
533
- case "ArrowRight":
534
- return 1;
413
+ });
414
+ if (initialRow) {
415
+ space.db.add((0, import_echo5.create)(contactSchema, {}));
535
416
  }
536
- return shift ? -1 : 1;
417
+ return contactSchema;
537
418
  };
538
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
539
- 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";
540
- 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";
541
- var frozen = {
542
- frozenRowsStart: 1,
543
- frozenColsStart: 1,
544
- frozenColsEnd: 1
419
+ var BUTTON_IDENTIFIERS = {
420
+ columnSettings: "data-table-column-settings-button",
421
+ newColumn: "data-table-new-column-button",
422
+ referencedCell: "data-table-ref-cell-button",
423
+ rowMenu: "data-table-row-menu-button"
545
424
  };
546
- var TableRoot = ({ children, role }) => {
547
- return /* @__PURE__ */ import_react.default.createElement("div", {
548
- role: "none",
549
- className: (0, import_react_ui_theme.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]")
550
- }, children);
425
+ var createButton = ({ attr, data, disabled = false, icon, testId }) => {
426
+ const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
427
+ return `<button ${attr} data-testid="${testId}" class="ch-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 inline-end-2" ${dataAttrs} ${disabled ? "disabled" : ""}><svg><use href="/icons.svg#${icon}"/></svg></button>`;
551
428
  };
552
- var TableMain = /* @__PURE__ */ (0, import_react.forwardRef)(({ model, ignoreAttention }, forwardedRef) => {
553
- const [dxGrid, setDxGrid] = (0, import_react.useState)(null);
554
- const { hasAttention } = (0, import_react_ui_attention.useAttention)(model?.table ? (0, import_echo.fullyQualifiedId)(model.table) : "table");
555
- const { t } = (0, import_react_ui.useTranslation)(translationKey);
556
- (0, import_react.useImperativeHandle)(forwardedRef, () => {
557
- if (!model || !dxGrid) {
558
- return {};
559
- }
560
- dxGrid.getCells = model.getCells.bind(model);
561
- return {
562
- update: (cell) => {
563
- if (cell) {
564
- dxGrid.updateIfWithinBounds(cell);
565
- } else {
566
- dxGrid.updateCells(true);
567
- }
568
- }
569
- };
570
- }, [
571
- model,
572
- dxGrid
573
- ]);
574
- const handleFocus = (0, import_react.useCallback)((increment, delta) => {
575
- if (dxGrid) {
576
- dxGrid.refocus(increment, delta);
577
- }
578
- }, [
579
- dxGrid
580
- ]);
581
- const handleEnter = (0, import_react.useCallback)((cell) => {
582
- if (model && cell.row === model.getRowCount() - 1) {
583
- model.insertRow(cell.row);
584
- if (dxGrid) {
585
- requestAnimationFrame(() => {
586
- dxGrid?.scrollToRow(cell.row + 1);
587
- dxGrid?.refocus("row", 1);
588
- });
589
- }
590
- }
591
- }, [
592
- model,
593
- dxGrid
594
- ]);
595
- const handleKeyDown = (0, import_react.useCallback)((event) => {
596
- const cell = (0, import_react_ui_grid.closestCell)(event.target);
597
- if (!model || !cell) {
598
- return;
599
- }
600
- switch (event.key) {
601
- case "Backspace":
602
- case "Delete": {
603
- model.setCellData(cell, void 0);
604
- break;
605
- }
606
- }
607
- }, [
608
- model
609
- ]);
610
- const handleAxisResize = (0, import_react.useCallback)((event) => {
611
- if (event.axis === "col") {
612
- const columnIndex = parseInt(event.index, 10);
613
- model?.setColumnWidth(columnIndex, event.size);
614
- }
615
- }, [
616
- model
617
- ]);
618
- const handleWheel = (0, import_react.useCallback)((event) => {
619
- if (!ignoreAttention && !hasAttention) {
620
- event.stopPropagation();
621
- }
622
- }, [
623
- hasAttention,
624
- ignoreAttention
625
- ]);
626
- const handleNewColumn = (0, import_react.useCallback)(() => {
627
- const columns = model?.getColumnCount();
628
- if (dxGrid && columns) {
629
- dxGrid.scrollToColumn(columns - 1);
630
- }
631
- }, [
632
- model,
633
- dxGrid
634
- ]);
635
- const handleQuery = (0, import_react.useCallback)(async ({ field, props }, text) => {
636
- if (model && props.referenceSchema && field.referencePath) {
637
- const space = (0, import_echo.getSpace)(model.table);
638
- (0, import_invariant.invariant)(space, void 0, {
639
- F: __dxlog_file2,
640
- L: 180,
641
- S: void 0,
642
- A: [
643
- "space",
644
- ""
645
- ]
646
- });
647
- const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
648
- if (schema) {
649
- const { objects } = await space.db.query(import_echo.Filter.schema(schema)).run();
650
- const options = objects.map((obj) => {
651
- const value = (0, import_echo_schema.getValue)(obj, field.referencePath);
652
- if (!value || typeof value !== "string") {
653
- return void 0;
654
- }
655
- return {
656
- label: value,
657
- data: obj
658
- };
659
- }).filter(import_util.isNotFalsy);
660
- return [
661
- ...options,
662
- {
663
- label: t("create new object label", {
664
- text
665
- }),
666
- data: createOption(text)
667
- }
668
- ];
669
- }
670
- }
671
- return [];
672
- }, [
673
- model
674
- ]);
675
- if (!model) {
676
- return /* @__PURE__ */ import_react.default.createElement("span", {
677
- role: "none",
678
- className: "attention-surface"
429
+ var addColumnButton = {
430
+ attr: BUTTON_IDENTIFIERS.newColumn,
431
+ icon: "ph--plus--regular",
432
+ render: ({ disabled }) => {
433
+ return createButton({
434
+ attr: BUTTON_IDENTIFIERS.newColumn,
435
+ icon: addColumnButton.icon,
436
+ disabled,
437
+ data: {},
438
+ testId: "table-new-column-button"
679
439
  });
680
- }
681
- return /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Root, {
682
- id: model.table.id ?? "table-grid"
683
- }, /* @__PURE__ */ import_react.default.createElement(TableCellEditor, {
684
- model,
685
- onEnter: handleEnter,
686
- onFocus: handleFocus,
687
- onQuery: handleQuery
688
- }), /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Content, {
689
- onWheelCapture: handleWheel,
690
- className: (0, import_react_ui_theme.mx)("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
691
- frozen,
692
- columns: model.columnMeta.value,
693
- limitRows: model.getRowCount() ?? 0,
694
- limitColumns: model.table.view?.fields?.length ?? 0,
695
- onAxisResize: handleAxisResize,
696
- onClick: model?.handleGridClick,
697
- onKeyDown: handleKeyDown,
698
- overscroll: "trap",
699
- ref: setDxGrid
700
- }), /* @__PURE__ */ import_react.default.createElement(RowActionsMenu, {
701
- model
702
- }), /* @__PURE__ */ import_react.default.createElement(ColumnActionsMenu, {
703
- model
704
- }), /* @__PURE__ */ import_react.default.createElement(ColumnSettings, {
705
- model,
706
- onNewColumn: handleNewColumn
707
- }), /* @__PURE__ */ import_react.default.createElement(RefPanel, {
708
- model
709
- }), /* @__PURE__ */ import_react.default.createElement(CreateRefPanel, {
710
- model
711
- }));
712
- });
713
- var Table = {
714
- Root: TableRoot,
715
- Main: TableMain
440
+ },
441
+ getData: (_el) => ({
442
+ type: "newColumn"
443
+ })
716
444
  };
717
- var buttonStyles = "min-bs-0 p-2";
718
- var tooltipProps = {
719
- side: "top",
720
- classNames: "z-10"
445
+ var columnSettingsButton = {
446
+ attr: BUTTON_IDENTIFIERS.columnSettings,
447
+ icon: "ph--caret-down--regular",
448
+ render: ({ fieldId }) => {
449
+ return createButton({
450
+ attr: BUTTON_IDENTIFIERS.columnSettings,
451
+ icon: columnSettingsButton.icon,
452
+ data: {
453
+ "data-field-id": fieldId
454
+ },
455
+ testId: "table-column-settings-button"
456
+ });
457
+ },
458
+ getData: (el) => ({
459
+ type: "columnSettings",
460
+ fieldId: el.getAttribute("data-field-id")
461
+ })
721
462
  };
722
- var ToolbarSeparator = () => /* @__PURE__ */ import_react9.default.createElement("div", {
723
- role: "separator",
724
- className: "grow"
725
- });
726
- var ToolbarButton = ({ icon, children, ...props }) => {
727
- return /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Root, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Trigger, {
728
- asChild: true
729
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Toolbar.Button, {
730
- variant: "ghost",
731
- ...props,
732
- classNames: buttonStyles
733
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Icon, {
734
- icon,
735
- size: 5
736
- }), /* @__PURE__ */ import_react9.default.createElement("span", {
737
- className: "sr-only"
738
- }, children))), /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Portal, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Content, tooltipProps, children, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Arrow, null))));
463
+ var referencedCellButton = {
464
+ attr: BUTTON_IDENTIFIERS.referencedCell,
465
+ icon: "ph--link-simple-horizontal--regular",
466
+ render: ({ targetId, schemaId }) => {
467
+ return createButton({
468
+ attr: BUTTON_IDENTIFIERS.referencedCell,
469
+ icon: referencedCellButton.icon,
470
+ data: {
471
+ "data-target-id": targetId,
472
+ "data-schema-id": schemaId
473
+ },
474
+ testId: "table-ref-cell-button"
475
+ });
476
+ },
477
+ getData: (el) => ({
478
+ type: "referencedCell",
479
+ targetId: el.getAttribute("data-target-id"),
480
+ schemaId: el.getAttribute("data-schema-id")
481
+ })
739
482
  };
740
- var [ToolbarContextProvider, useToolbarContext] = (0, import_react_context.createContext)("Toolbar");
741
- var ToolbarRoot = ({ classNames, children, onAction }) => {
742
- return /* @__PURE__ */ import_react8.default.createElement(ToolbarContextProvider, {
743
- onAction
744
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Toolbar.Root, {
745
- classNames: [
746
- "is-full shrink-0 overflow-x-auto overflow-y-hidden p-1 attention-surface",
747
- classNames
748
- ]
749
- }, children));
483
+ var rowMenuButton = {
484
+ attr: BUTTON_IDENTIFIERS.rowMenu,
485
+ icon: "ph--dots-three--regular",
486
+ render: ({ rowIndex }) => {
487
+ return createButton({
488
+ attr: BUTTON_IDENTIFIERS.rowMenu,
489
+ icon: rowMenuButton.icon,
490
+ data: {
491
+ "data-row-index": rowIndex.toString()
492
+ },
493
+ testId: "table-row-menu-button"
494
+ });
495
+ },
496
+ getData: (el) => ({
497
+ type: "rowMenu",
498
+ rowIndex: Number(el.getAttribute("data-row-index"))
499
+ })
750
500
  };
751
- var Editing = () => {
752
- const { onAction } = useToolbarContext("Editing");
753
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
754
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
755
- value: "add-row",
756
- icon: "ph--plus--regular",
757
- "data-testid": "table.toolbar.add-row",
758
- onClick: () => onAction?.({
759
- type: "add-row"
760
- })
761
- }, t("add row")));
501
+ var tableButtons = {
502
+ addColumn: addColumnButton,
503
+ columnSettings: columnSettingsButton,
504
+ referencedCell: referencedCellButton,
505
+ rowMenu: rowMenuButton
762
506
  };
763
- var Actions = () => {
764
- const { onAction } = useToolbarContext("Actions");
765
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
766
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
767
- value: "comment",
768
- icon: "ph--chat-text--regular",
769
- "data-testid": "table.toolbar.comment",
770
- onClick: () => onAction?.({
771
- type: "comment"
772
- })
773
- }, t("create comment")));
507
+ var CONTROL_IDENTIFIERS = {
508
+ checkbox: "data-table-checkbox",
509
+ switch: "data-table-switch"
774
510
  };
775
- var Toolbar = {
776
- Root: ToolbarRoot,
777
- Editing,
778
- Actions,
779
- Separator: ToolbarSeparator
511
+ var BASE_CLASSES = {
512
+ checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] ch-checkbox",
513
+ switch: "absolute inset-block-[.25rem] inline-end-[.25rem] ch-checkbox--switch"
780
514
  };
781
- var touch = (value) => value;
782
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/util/table.ts";
783
- var initializeTable = ({ space, table, initialRow = true }) => {
784
- import_log2.log.info("initializeTable", {
785
- table
786
- }, {
787
- F: __dxlog_file3,
788
- L: 32,
789
- S: void 0,
790
- C: (f, a) => f(...a)
791
- });
792
- const ContactSchema = (0, import_echo_schema5.TypedObject)({
793
- typename: `example.com/type/${import_react_client2.PublicKey.random().truncate()}`,
794
- version: "0.1.0"
795
- })({
796
- name: import_echo_schema5.S.optional(import_echo_schema5.S.String).annotations({
797
- [import_echo_schema5.AST.TitleAnnotationId]: "Name"
798
- }),
799
- email: import_echo_schema5.S.optional(import_echo_schema5.Format.Email),
800
- salary: import_echo_schema5.S.optional(import_echo_schema5.Format.Currency()).annotations({
801
- [import_echo_schema5.AST.TitleAnnotationId]: "Salary"
802
- })
803
- });
804
- const contactSchema = space.db.schemaRegistry.addSchema(ContactSchema);
805
- table.view = (0, import_schema2.createView)({
806
- name: "Test",
807
- typename: contactSchema.typename,
808
- jsonSchema: contactSchema.jsonSchema,
809
- fields: [
810
- "name",
811
- "email",
812
- "salary"
813
- ]
814
- });
815
- const projection = new import_schema2.ViewProjection(contactSchema, table.view);
816
- projection.setFieldProjection({
817
- field: {
818
- id: table.view.fields[2].id,
819
- path: "salary",
820
- size: 150
821
- }
822
- });
823
- projection.setFieldProjection({
824
- field: {
825
- id: (0, import_schema2.createFieldId)(),
826
- path: "manager",
827
- referencePath: "name"
828
- },
829
- props: {
830
- property: "manager",
831
- type: import_echo_schema5.TypeEnum.Ref,
832
- format: import_echo_schema5.FormatEnum.Ref,
833
- referenceSchema: contactSchema.typename,
834
- title: "Manager"
835
- }
836
- });
837
- if (initialRow) {
838
- space.db.add((0, import_echo5.create)(contactSchema, {}));
839
- }
840
- return contactSchema;
515
+ var renderAttributes = (data) => {
516
+ return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
841
517
  };
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"
518
+ var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
519
+ return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
847
520
  };
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"
521
+ var renderCheckbox = ({ rowIndex, header = false, checked = false, disabled = false }) => {
522
+ const attrs = {
523
+ [CONTROL_IDENTIFIERS.checkbox]: "",
524
+ "data-row-index": rowIndex.toString(),
525
+ ...header && {
526
+ "data-header": ""
527
+ }
528
+ };
529
+ return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
853
530
  };
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>`;
531
+ var renderSwitch = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
532
+ const attrs = {
533
+ [CONTROL_IDENTIFIERS.switch]: "",
534
+ "data-row-index": rowIndex.toString(),
535
+ "data-col-index": colIndex.toString()
536
+ };
537
+ return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
857
538
  };
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"
539
+ var tableControls = {
540
+ checkbox: {
541
+ attr: CONTROL_IDENTIFIERS.checkbox,
542
+ render: renderCheckbox,
543
+ getData: (el) => ({
544
+ type: "checkbox",
545
+ rowIndex: Number(el.getAttribute("data-row-index")),
546
+ header: el.hasAttribute("data-header")
884
547
  })
885
548
  },
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"
549
+ switch: {
550
+ attr: CONTROL_IDENTIFIERS.switch,
551
+ render: renderSwitch,
552
+ getData: (el) => ({
553
+ type: "switch",
554
+ rowIndex: Number(el.getAttribute("data-row-index")),
555
+ colIndex: Number(el.getAttribute("data-col-index"))
893
556
  })
894
557
  }
895
558
  };
896
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
897
- var ModalController = class {
898
- constructor() {
899
- this._state = (0, import_signals_core2.signal)({
900
- type: "closed"
901
- });
902
- this._triggerRef = {
903
- current: null
904
- };
905
- this.handleClick = (event) => {
906
- const target = event.target;
907
- const rowButton = target.closest(`button[${tableButtons.rowMenu.attr}]`);
908
- if (rowButton) {
909
- this._triggerRef.current = rowButton;
910
- this._state.value = {
911
- type: "row",
912
- rowIndex: Number(rowButton.getAttribute(tableButtons.rowMenu.attr))
913
- };
914
- return true;
915
- }
916
- const columnButton = target.closest(`button[${tableButtons.columnSettings.attr}]`);
917
- if (columnButton) {
918
- const fieldId = columnButton.getAttribute(tableButtons.columnSettings.attr);
919
- this._triggerRef.current = columnButton;
920
- this._state.value = {
921
- type: "column",
922
- fieldId
923
- };
924
- return true;
925
- }
926
- const addColumnButton = target.closest(`button[${tableButtons.addColumn.attr}]`);
927
- if (addColumnButton) {
928
- this._triggerRef.current = addColumnButton;
929
- this._state.value = {
930
- type: "columnSettings",
931
- mode: {
932
- type: "create"
933
- }
934
- };
935
- return true;
936
- }
937
- const refButton = target.closest(`button[${tableButtons.referencedCell.attr}]`);
938
- if (refButton) {
939
- this._triggerRef.current = refButton;
940
- const [schemaId, targetId] = refButton.getAttribute(tableButtons.referencedCell.attr).split("#");
941
- this._state.value = {
942
- type: "refPanel",
943
- targetId,
944
- typename: schemaId
945
- };
946
- }
947
- return false;
948
- };
949
- this.openColumnSettings = () => {
950
- if (this._state.value.type === "column") {
951
- const fieldId = this._state.value.fieldId;
952
- requestAnimationFrame(() => {
953
- this._state.value = {
954
- type: "columnSettings",
955
- mode: {
956
- type: "edit",
957
- fieldId
958
- }
959
- };
960
- });
961
- }
962
- };
963
- this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
964
- if (anchorCell) {
965
- this._triggerRef.current = anchorCell;
966
- this._state.value = {
967
- type: "createRefPanel",
968
- typename,
969
- initialValues,
970
- onCreate
971
- };
972
- } else {
973
- import_log.log.warn("anchor cell not found while creating new ref", void 0, {
974
- F: __dxlog_file4,
975
- L: 119,
976
- S: this,
977
- C: (f, a) => f(...a)
978
- });
979
- }
980
- };
981
- this.close = () => {
982
- this._state.value = {
983
- type: "closed"
984
- };
985
- };
986
- }
987
- get state() {
988
- return this._state;
989
- }
990
- get trigger() {
991
- return this._triggerRef;
992
- }
993
- };
994
559
  var SelectionModel = class extends import_context2.Resource {
995
560
  constructor(_rows, _onSelectionChanged) {
996
561
  super();
997
562
  this._rows = _rows;
998
563
  this._onSelectionChanged = _onSelectionChanged;
999
- this._selection = (0, import_signals_core3.signal)(/* @__PURE__ */ new Set());
1000
- this._validSelectedIds = (0, import_signals_core3.computed)(() => {
564
+ this._selection = (0, import_signals_core2.signal)(/* @__PURE__ */ new Set());
565
+ this._validSelectedIds = (0, import_signals_core2.computed)(() => {
1001
566
  const rows = this._rows.value;
1002
567
  if (!rows) {
1003
568
  return /* @__PURE__ */ new Set();
@@ -1007,8 +572,8 @@ var SelectionModel = class extends import_context2.Resource {
1007
572
  ...this._selection.value
1008
573
  ].filter((id) => validIds.has(id)));
1009
574
  });
1010
- this._hasSelection = (0, import_signals_core3.computed)(() => this._validSelectedIds.value.size > 0);
1011
- this._allSelected = (0, import_signals_core3.computed)(() => {
575
+ this._hasSelection = (0, import_signals_core2.computed)(() => this._validSelectedIds.value.size > 0);
576
+ this._allSelected = (0, import_signals_core2.computed)(() => {
1012
577
  const rows = this._rows.value;
1013
578
  if (rows.length === 0) {
1014
579
  return false;
@@ -1037,11 +602,20 @@ var SelectionModel = class extends import_context2.Resource {
1037
602
  this._selection.value = newSelection;
1038
603
  };
1039
604
  this.setSelection = (mode) => {
1040
- this._selection.value = mode === "all" ? new Set(this._rows.value.map((row) => row.id)) : /* @__PURE__ */ new Set();
605
+ switch (mode) {
606
+ case "all": {
607
+ this._selection.value = new Set(this._rows.value.map((row) => row.id));
608
+ break;
609
+ }
610
+ case "none": {
611
+ this._selection.value = /* @__PURE__ */ new Set();
612
+ break;
613
+ }
614
+ }
1041
615
  };
1042
616
  }
1043
617
  async _open() {
1044
- const selectionWatcher = (0, import_signals_core3.effect)(() => {
618
+ const selectionWatcher = (0, import_signals_core2.effect)(() => {
1045
619
  touch(this._selection.value);
1046
620
  this._onSelectionChanged?.();
1047
621
  });
@@ -1060,22 +634,7 @@ var SelectionModel = class extends import_context2.Resource {
1060
634
  return this._allSelected;
1061
635
  }
1062
636
  };
1063
- var checkboxAttributes = {
1064
- checkbox: "data-table-checkbox",
1065
- header: "data-table-header"
1066
- };
1067
- var renderCheckbox = ({ rowIndex, header = false, checked = false, disabled = false }) => {
1068
- const baseClasses = "absolute inset-block-[6px] inline-end-[6px] ch-checkbox";
1069
- const { attributes } = tableControls.checkbox;
1070
- return `<input type="checkbox" class="${baseClasses}" ${attributes.checkbox}="${rowIndex}" ${header ? attributes.header : ""} ${checked ? "checked" : ""} ${disabled ? "disabled" : ""} data-testid="table-selection"/>`;
1071
- };
1072
- var tableControls = {
1073
- checkbox: {
1074
- attributes: checkboxAttributes,
1075
- render: renderCheckbox
1076
- }
1077
- };
1078
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
637
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
1079
638
  var TableModel = class extends import_context.Resource {
1080
639
  constructor({ table, projection, sorting = [], pinnedRows = {
1081
640
  top: [],
@@ -1096,194 +655,11 @@ var TableModel = class extends import_context.Resource {
1096
655
  this._displayToDataIndex = /* @__PURE__ */ new Map();
1097
656
  this._sorting = (0, import_signals_core.signal)(void 0);
1098
657
  this._rows = (0, import_signals_core.signal)([]);
1099
- this._modalController = new ModalController();
1100
- this.getCells = (range, plane) => {
1101
- switch (plane) {
1102
- case "grid": {
1103
- this._visibleRange.value = range;
1104
- return this.getMainGridCells(range);
1105
- }
1106
- case "frozenRowsStart": {
1107
- return this.getHeaderCells(range);
1108
- }
1109
- case "frozenColsStart": {
1110
- return this.getSelectionColumnCells(range);
1111
- }
1112
- case "frozenColsEnd": {
1113
- return this.getActionColumnCells(range);
1114
- }
1115
- case "fixedStartStart": {
1116
- return this.getSelectAllCell();
1117
- }
1118
- case "fixedStartEnd": {
1119
- return this.getNewColumnCell();
1120
- }
1121
- default: {
1122
- return {};
1123
- }
1124
- }
1125
- };
1126
- this.getMainGridCells = (range) => {
1127
- const cells = {};
1128
- const fields = this._table.view?.fields ?? [];
1129
- const addCell = (obj, field, colIndex, displayIndex) => {
1130
- const { props } = this._projection.getFieldProjection(field.id);
1131
- const cell = {
1132
- get value() {
1133
- const value = (0, import_echo_schema4.getValue)(obj, field.path);
1134
- if (value == null) {
1135
- return "";
1136
- }
1137
- switch (props.format) {
1138
- case import_echo_schema4.FormatEnum.Ref: {
1139
- if (!field.referencePath) {
1140
- return "";
1141
- }
1142
- return (0, import_echo_schema4.getValue)(value, field.referencePath);
1143
- }
1144
- default: {
1145
- return (0, import_react_ui_form4.formatForDisplay)({
1146
- type: props.type,
1147
- format: props.format,
1148
- value
1149
- });
1150
- }
1151
- }
1152
- }
1153
- };
1154
- const classes = [];
1155
- const formatClasses = (0, import_react_ui_form4.cellClassesForFieldType)({
1156
- type: props.type,
1157
- format: props.format
1158
- });
1159
- if (formatClasses) {
1160
- classes.push(formatClasses);
1161
- }
1162
- const rowSelectionClasses = (0, import_react_ui_form4.cellClassesForRowSelection)(this._selection.isObjectSelected(obj));
1163
- if (rowSelectionClasses) {
1164
- classes.push(rowSelectionClasses);
1165
- }
1166
- if (classes.length > 0) {
1167
- cell.className = (0, import_react_ui_theme2.mx)(classes.flat());
1168
- }
1169
- if (cell.value && props.format === import_echo_schema4.FormatEnum.Ref && props.referenceSchema) {
1170
- const targetObj = (0, import_echo_schema4.getValue)(obj, field.path);
1171
- cell.accessoryHtml = tableButtons.referencedCell.render({
1172
- targetId: targetObj.id,
1173
- schemaId: props.referenceSchema
1174
- });
1175
- }
1176
- const idx = (0, import_react_ui_grid4.toPlaneCellIndex)({
1177
- col: colIndex,
1178
- row: displayIndex
1179
- });
1180
- cells[idx] = cell;
1181
- };
1182
- for (let row = range.start.row; row <= range.end.row && row < this._sortedRows.value.length; row++) {
1183
- for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1184
- const field = fields[col];
1185
- if (!field) {
1186
- continue;
1187
- }
1188
- addCell(this._sortedRows.value[row], field, col, row);
1189
- }
1190
- }
1191
- return cells;
1192
- };
1193
- this.getHeaderCells = (range) => {
1194
- const cells = {};
1195
- const fields = this.table.view?.fields ?? [];
1196
- for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1197
- const { field, props } = this._projection.getFieldProjection(fields[col].id);
1198
- cells[(0, import_react_ui_grid4.toPlaneCellIndex)({
1199
- col,
1200
- row: 0
1201
- })] = {
1202
- // TODO(burdon): Use same logic as form for fallback title.
1203
- value: props.title ?? field.path,
1204
- readonly: true,
1205
- resizeHandle: "col",
1206
- accessoryHtml: tableButtons.columnSettings.render({
1207
- fieldId: field.id
1208
- })
1209
- };
1210
- }
1211
- return cells;
1212
- };
1213
- this.getSelectionColumnCells = (range) => {
1214
- const cells = {};
1215
- for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
1216
- const isSelected = this._selection.isRowIndexSelected(row);
1217
- const classes = (0, import_react_ui_form4.cellClassesForRowSelection)(isSelected);
1218
- cells[(0, import_react_ui_grid4.toPlaneCellIndex)({
1219
- col: 0,
1220
- row
1221
- })] = {
1222
- value: "",
1223
- readonly: true,
1224
- className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1225
- accessoryHtml: tableControls.checkbox.render({
1226
- rowIndex: row,
1227
- checked: isSelected
1228
- })
1229
- };
1230
- }
1231
- return cells;
1232
- };
1233
- this.getActionColumnCells = (range) => {
1234
- const cells = {};
1235
- for (let row = range.start.row; row <= range.end.row && row < this._rows.value.length; row++) {
1236
- const isSelected = this._selection.isRowIndexSelected(row);
1237
- const classes = (0, import_react_ui_form4.cellClassesForRowSelection)(isSelected);
1238
- cells[(0, import_react_ui_grid4.toPlaneCellIndex)({
1239
- col: 0,
1240
- row
1241
- })] = {
1242
- value: "",
1243
- readonly: true,
1244
- className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1245
- accessoryHtml: tableButtons.rowMenu.render({
1246
- rowIndex: row
1247
- })
1248
- };
1249
- }
1250
- return cells;
1251
- };
1252
- this.getSelectAllCell = () => {
1253
- return {
1254
- [(0, import_react_ui_grid4.toPlaneCellIndex)({
1255
- col: 0,
1256
- row: 0
1257
- })]: {
1258
- value: "",
1259
- accessoryHtml: tableControls.checkbox.render({
1260
- rowIndex: 0,
1261
- header: true,
1262
- checked: this._selection.allRowsSeleted.value
1263
- }),
1264
- readonly: true
1265
- }
1266
- };
1267
- };
1268
- this.getNewColumnCell = () => {
1269
- return {
1270
- [(0, import_react_ui_grid4.toPlaneCellIndex)({
1271
- col: 0,
1272
- row: 0
1273
- })]: {
1274
- value: "",
1275
- accessoryHtml: tableButtons.addColumn.render({
1276
- disabled: (this._table.view?.fields?.length ?? 0) >= import_schema.VIEW_FIELD_LIMIT
1277
- }),
1278
- readonly: true
1279
- }
1280
- };
1281
- };
1282
658
  this.setRows = (obj) => {
1283
659
  this._rows.value = obj;
1284
660
  };
1285
661
  this.getRowCount = () => this._rows.value.length;
1286
- this.getColumnCount = () => this.table.view?.fields.length ?? 0;
662
+ this.getColumnCount = () => this.table.view?.target?.fields.length ?? 0;
1287
663
  this.insertRow = (rowIndex) => {
1288
664
  const row = rowIndex !== void 0 ? this._displayToDataIndex.get(rowIndex) ?? rowIndex : this._rows.value.length;
1289
665
  this._onInsertRow?.(row);
@@ -1301,23 +677,23 @@ var TableModel = class extends import_context.Resource {
1301
677
  this._onDeleteRows?.(row, objectsToDelete);
1302
678
  };
1303
679
  this.getCellData = ({ col, row }) => {
1304
- const fields = this.table.view?.fields ?? [];
680
+ const fields = this.table.view?.target?.fields ?? [];
1305
681
  if (col < 0 || col >= fields.length) {
1306
682
  return void 0;
1307
683
  }
1308
684
  const field = fields[col];
1309
685
  const dataIndex = this._displayToDataIndex.get(row) ?? row;
1310
- const value = (0, import_echo_schema4.getValue)(this._rows.value[dataIndex], field.path);
686
+ const value = (0, import_echo_schema3.getValue)(this._rows.value[dataIndex], field.path);
1311
687
  if (value == null) {
1312
688
  return "";
1313
689
  }
1314
690
  const { props } = this._projection.getFieldProjection(field.id);
1315
691
  switch (props.format) {
1316
- case import_echo_schema4.FormatEnum.Ref: {
692
+ case import_echo_schema3.FormatEnum.Ref: {
1317
693
  if (!field.referencePath) {
1318
694
  return "";
1319
695
  }
1320
- return (0, import_echo_schema4.getValue)(value, field.referencePath);
696
+ return (0, import_echo_schema3.getValue)(value.target, field.referencePath);
1321
697
  }
1322
698
  default: {
1323
699
  return (0, import_react_ui_form4.formatForEditing)({
@@ -1330,19 +706,21 @@ var TableModel = class extends import_context.Resource {
1330
706
  };
1331
707
  this.setCellData = ({ col, row }, value) => {
1332
708
  const rowIdx = this._displayToDataIndex.get(row) ?? row;
1333
- const fields = this.table.view?.fields ?? [];
709
+ const fields = this.table.view?.target?.fields ?? [];
1334
710
  if (col < 0 || col >= fields.length) {
1335
711
  return;
1336
712
  }
1337
713
  const field = fields[col];
1338
714
  const { props } = this._projection.getFieldProjection(field.id);
1339
715
  switch (props.format) {
1340
- case import_echo_schema4.FormatEnum.Ref: {
1341
- (0, import_echo_schema4.setValue)(this._rows.value[rowIdx], field.path, value);
716
+ case import_echo_schema3.FormatEnum.Ref: {
717
+ if ((0, import_live_object.isReactiveObject)(value)) {
718
+ (0, import_echo_schema3.setValue)(this._rows.value[rowIdx], field.path, (0, import_live_object.makeRef)(value));
719
+ }
1342
720
  break;
1343
721
  }
1344
722
  default: {
1345
- (0, import_echo_schema4.setValue)(this._rows.value[rowIdx], field.path, (0, import_react_ui_form4.parseValue)({
723
+ (0, import_echo_schema3.setValue)(this._rows.value[rowIdx], field.path, (0, import_react_ui_form4.parseValue)({
1346
724
  type: props.type,
1347
725
  format: props.format,
1348
726
  value
@@ -1351,25 +729,6 @@ var TableModel = class extends import_context.Resource {
1351
729
  }
1352
730
  }
1353
731
  };
1354
- this.handleGridClick = (event) => {
1355
- if (!this._modalController.handleClick(event)) {
1356
- const target = event.target;
1357
- const selectionCheckbox = target.closest(`input[${tableControls.checkbox.attributes.checkbox}]`);
1358
- if (selectionCheckbox) {
1359
- const isHeader = selectionCheckbox.hasAttribute(tableControls.checkbox.attributes.header);
1360
- if (isHeader) {
1361
- if (this._selection.allRowsSeleted.value) {
1362
- this._selection.setSelection("none");
1363
- } else {
1364
- this._selection.setSelection("all");
1365
- }
1366
- } else {
1367
- const rowIndex = Number(selectionCheckbox.getAttribute(tableControls.checkbox.attributes.checkbox));
1368
- this._selection.toggleSelectionForRowIndex(rowIndex);
1369
- }
1370
- }
1371
- }
1372
- };
1373
732
  this._table = table;
1374
733
  this._projection = projection;
1375
734
  this._sorting.value = sorting.at(0);
@@ -1386,13 +745,16 @@ var TableModel = class extends import_context.Resource {
1386
745
  get projection() {
1387
746
  return this._projection;
1388
747
  }
748
+ get rows() {
749
+ return this._sortedRows;
750
+ }
1389
751
  get pinnedRows() {
1390
752
  return this._pinnedRows;
1391
753
  }
1392
754
  get columnMeta() {
1393
- (0, import_invariant3.invariant)(this._columnMeta, void 0, {
1394
- F: __dxlog_file5,
1395
- L: 126,
755
+ (0, import_invariant2.invariant)(this._columnMeta, void 0, {
756
+ F: __dxlog_file2,
757
+ L: 117,
1396
758
  S: this,
1397
759
  A: [
1398
760
  "this._columnMeta",
@@ -1404,9 +766,6 @@ var TableModel = class extends import_context.Resource {
1404
766
  get sorting() {
1405
767
  return this._sorting.value;
1406
768
  }
1407
- get modalController() {
1408
- return this._modalController;
1409
- }
1410
769
  get selection() {
1411
770
  return this._selection;
1412
771
  }
@@ -1422,7 +781,7 @@ var TableModel = class extends import_context.Resource {
1422
781
  }
1423
782
  initializeColumnMeta() {
1424
783
  this._columnMeta = (0, import_signals_core.computed)(() => {
1425
- const fields = this._table.view?.fields ?? [];
784
+ const fields = this._table.view?.target?.fields ?? [];
1426
785
  const meta = Object.fromEntries(fields.map((field, index) => [
1427
786
  index,
1428
787
  {
@@ -1454,17 +813,32 @@ var TableModel = class extends import_context.Resource {
1454
813
  if (!sort) {
1455
814
  return this._rows.value;
1456
815
  }
1457
- const field = this._table.view?.fields.find((field2) => field2.id === sort.fieldId);
816
+ const field = this._table.view?.target?.fields.find((field2) => field2.id === sort.fieldId);
1458
817
  if (!field) {
1459
818
  return this._rows.value;
1460
819
  }
820
+ const { props } = this._projection.getFieldProjection(field.id);
1461
821
  const dataWithIndices = this._rows.value.map((item, index) => {
1462
- const value = (0, import_echo_schema4.getValue)(item, field.path);
822
+ const rawValue = (0, import_echo_schema3.getValue)(item, field.path);
823
+ let sortValue = rawValue;
824
+ if (props.type.startsWith("boolean")) {
825
+ sortValue = !!rawValue;
826
+ } else if (rawValue != null) {
827
+ if (props.format === import_echo_schema3.FormatEnum.Ref && field.referencePath) {
828
+ sortValue = (0, import_echo_schema3.getValue)(rawValue, field.referencePath);
829
+ } else {
830
+ sortValue = (0, import_react_ui_form4.formatForDisplay)({
831
+ type: props.type,
832
+ format: props.format,
833
+ value: rawValue
834
+ });
835
+ }
836
+ }
1463
837
  return {
1464
838
  item,
1465
839
  index,
1466
- value,
1467
- isEmpty: value == null || value === ""
840
+ value: sortValue,
841
+ isEmpty: !props.type.startsWith("boolean") && (sortValue == null || sortValue === "")
1468
842
  };
1469
843
  });
1470
844
  const sorted = (0, import_lodash.default)(dataWithIndices, [
@@ -1495,7 +869,7 @@ var TableModel = class extends import_context.Resource {
1495
869
  for (let row = start.row; row <= end.row; row++) {
1496
870
  rowEffects.push((0, import_signals_core.effect)(() => {
1497
871
  const obj = this._sortedRows.value[row];
1498
- this?._table?.view?.fields.forEach((field) => touch((0, import_echo_schema4.getValue)(obj, field.path)));
872
+ this?._table?.view?.target?.fields.forEach((field) => touch((0, import_echo_schema3.getValue)(obj, field.path)));
1499
873
  this._onCellUpdate?.({
1500
874
  row,
1501
875
  col: start.col,
@@ -1507,6 +881,19 @@ var TableModel = class extends import_context.Resource {
1507
881
  });
1508
882
  this._ctx.onDispose(rowEffectManager);
1509
883
  }
884
+ /**
885
+ * Updates a cell's value using a transform function.
886
+ * @param {DxGridPlanePosition} position - The position of the cell to update.
887
+ * @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
888
+ */
889
+ updateCellData({ col, row }, update) {
890
+ const dataRow = this._displayToDataIndex.get(row) ?? row;
891
+ const fields = this.table.view?.target?.fields ?? [];
892
+ const field = fields[col];
893
+ const value = (0, import_echo_schema3.getValue)(this._rows.value[dataRow], field.path);
894
+ const updatedValue = update(value);
895
+ (0, import_echo_schema3.setValue)(this._rows.value[dataRow], field.path, updatedValue);
896
+ }
1510
897
  //
1511
898
  // Column Operations
1512
899
  //
@@ -1514,7 +901,7 @@ var TableModel = class extends import_context.Resource {
1514
901
  if (!this.table.view) {
1515
902
  return;
1516
903
  }
1517
- const field = this.table.view.fields.find((field2) => field2.id === fieldId);
904
+ const field = this.table.view.target?.fields.find((field2) => field2.id === fieldId);
1518
905
  if (field && this._onDeleteColumn) {
1519
906
  if (this._sorting.value?.fieldId === fieldId) {
1520
907
  this.clearSort();
@@ -1526,7 +913,7 @@ var TableModel = class extends import_context.Resource {
1526
913
  // Resize
1527
914
  //
1528
915
  setColumnWidth(columnIndex, width) {
1529
- const fields = this.table.view?.fields ?? [];
916
+ const fields = this.table.view?.target?.fields ?? [];
1530
917
  if (columnIndex < fields.length) {
1531
918
  const newWidth = Math.max(0, width);
1532
919
  const field = fields[columnIndex];
@@ -1559,6 +946,814 @@ var TableModel = class extends import_context.Resource {
1559
946
  this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
1560
947
  }
1561
948
  };
949
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
950
+ var ModalController = class {
951
+ constructor() {
952
+ this._state = (0, import_signals_core3.signal)({
953
+ type: "closed"
954
+ });
955
+ this._triggerRef = {
956
+ current: null
957
+ };
958
+ this.setTrigger = (trigger) => {
959
+ this._triggerRef.current = trigger;
960
+ };
961
+ this.showRowMenu = (rowIndex) => {
962
+ this._state.value = {
963
+ type: "row",
964
+ rowIndex
965
+ };
966
+ };
967
+ this.showColumnMenu = (fieldId) => {
968
+ this._state.value = {
969
+ type: "column",
970
+ fieldId
971
+ };
972
+ };
973
+ this.showColumnCreator = () => {
974
+ this._state.value = {
975
+ type: "columnSettings",
976
+ mode: {
977
+ type: "create"
978
+ }
979
+ };
980
+ };
981
+ this.showReferencePanel = (targetId, schemaId) => {
982
+ this._state.value = {
983
+ type: "refPanel",
984
+ targetId,
985
+ typename: schemaId
986
+ };
987
+ };
988
+ this.openColumnSettings = () => {
989
+ if (this._state.value.type === "column") {
990
+ const fieldId = this._state.value.fieldId;
991
+ requestAnimationFrame(() => {
992
+ this._state.value = {
993
+ type: "columnSettings",
994
+ mode: {
995
+ type: "edit",
996
+ fieldId
997
+ }
998
+ };
999
+ });
1000
+ }
1001
+ };
1002
+ this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
1003
+ if (anchorCell) {
1004
+ this._triggerRef.current = anchorCell;
1005
+ this._state.value = {
1006
+ type: "createRefPanel",
1007
+ typename,
1008
+ initialValues,
1009
+ onCreate
1010
+ };
1011
+ } else {
1012
+ import_log2.log.warn("anchor cell not found while creating new ref", void 0, {
1013
+ F: __dxlog_file3,
1014
+ L: 86,
1015
+ S: this,
1016
+ C: (f, a) => f(...a)
1017
+ });
1018
+ }
1019
+ };
1020
+ this.close = () => {
1021
+ this._state.value = {
1022
+ type: "closed"
1023
+ };
1024
+ };
1025
+ }
1026
+ get state() {
1027
+ return this._state;
1028
+ }
1029
+ get trigger() {
1030
+ return this._triggerRef;
1031
+ }
1032
+ };
1033
+ var TablePresentation = class {
1034
+ constructor(model, _visibleRange = (0, import_signals_core4.signal)({
1035
+ start: {
1036
+ row: 0,
1037
+ col: 0
1038
+ },
1039
+ end: {
1040
+ row: 0,
1041
+ col: 0
1042
+ }
1043
+ })) {
1044
+ this.model = model;
1045
+ this._visibleRange = _visibleRange;
1046
+ }
1047
+ getCells(range, plane) {
1048
+ switch (plane) {
1049
+ case "grid":
1050
+ this._visibleRange.value = range;
1051
+ return this.getMainGridCells(range);
1052
+ case "frozenRowsStart":
1053
+ return this.getHeaderCells(range);
1054
+ case "frozenColsStart":
1055
+ return this.getSelectionColumnCells(range);
1056
+ case "frozenColsEnd":
1057
+ return this.getActionColumnCells(range);
1058
+ case "fixedStartStart":
1059
+ return this.getSelectAllCell();
1060
+ case "fixedStartEnd":
1061
+ return this.getNewColumnCell();
1062
+ default:
1063
+ return {};
1064
+ }
1065
+ }
1066
+ getMainGridCells(range) {
1067
+ const cells = {};
1068
+ const fields = this.model.table.view?.target?.fields ?? [];
1069
+ const addCell = (obj, field, colIndex, displayIndex) => {
1070
+ const { props } = this.model.projection.getFieldProjection(field.id);
1071
+ const cell = {
1072
+ get value() {
1073
+ const value = (0, import_echo_schema5.getValue)(obj, field.path);
1074
+ if (value == null) {
1075
+ return "";
1076
+ }
1077
+ switch (props.format) {
1078
+ case import_echo_schema5.FormatEnum.Boolean: {
1079
+ return "";
1080
+ }
1081
+ case import_echo_schema5.FormatEnum.Ref: {
1082
+ if (!field.referencePath) {
1083
+ return "";
1084
+ }
1085
+ return (0, import_echo_schema5.getValue)(value.target, field.referencePath);
1086
+ }
1087
+ default: {
1088
+ return (0, import_react_ui_form5.formatForDisplay)({
1089
+ type: props.type,
1090
+ format: props.format,
1091
+ value
1092
+ });
1093
+ }
1094
+ }
1095
+ }
1096
+ };
1097
+ const classes = [];
1098
+ const formatClasses = (0, import_react_ui_form5.cellClassesForFieldType)({
1099
+ type: props.type,
1100
+ format: props.format
1101
+ });
1102
+ if (formatClasses) {
1103
+ classes.push(formatClasses);
1104
+ }
1105
+ const rowSelectionClasses = (0, import_react_ui_form5.cellClassesForRowSelection)(this.model.selection.isObjectSelected(obj));
1106
+ if (rowSelectionClasses) {
1107
+ classes.push(rowSelectionClasses);
1108
+ }
1109
+ if (classes.length > 0) {
1110
+ cell.className = (0, import_react_ui_theme2.mx)(classes.flat());
1111
+ }
1112
+ if (props.format === import_echo_schema5.FormatEnum.Ref && props.referenceSchema) {
1113
+ const targetObj = (0, import_echo_schema5.getValue)(obj, field.path)?.target;
1114
+ if (targetObj) {
1115
+ cell.accessoryHtml = tableButtons.referencedCell.render({
1116
+ targetId: targetObj.id,
1117
+ schemaId: props.referenceSchema
1118
+ });
1119
+ }
1120
+ }
1121
+ if (props.format === import_echo_schema5.FormatEnum.Boolean) {
1122
+ const value = (0, import_echo_schema5.getValue)(obj, field.path);
1123
+ cell.accessoryHtml = tableControls.switch.render({
1124
+ colIndex,
1125
+ rowIndex: displayIndex,
1126
+ checked: value ?? false
1127
+ });
1128
+ cell.readonly = true;
1129
+ }
1130
+ const idx = (0, import_react_ui_grid3.toPlaneCellIndex)({
1131
+ col: colIndex,
1132
+ row: displayIndex
1133
+ });
1134
+ cells[idx] = cell;
1135
+ };
1136
+ for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1137
+ for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1138
+ const field = fields[col];
1139
+ if (!field) {
1140
+ continue;
1141
+ }
1142
+ addCell(this.model.rows.value[row], field, col, row);
1143
+ }
1144
+ }
1145
+ return cells;
1146
+ }
1147
+ getHeaderCells(range) {
1148
+ const cells = {};
1149
+ const fields = this.model.table.view?.target?.fields ?? [];
1150
+ for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1151
+ const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
1152
+ cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1153
+ col,
1154
+ row: 0
1155
+ })] = {
1156
+ // TODO(burdon): Use same logic as form for fallback title.
1157
+ value: props.title ?? field.path,
1158
+ readonly: true,
1159
+ resizeHandle: "col",
1160
+ accessoryHtml: tableButtons.columnSettings.render({
1161
+ fieldId: field.id
1162
+ }),
1163
+ className: "!bg-gridHeader"
1164
+ };
1165
+ }
1166
+ return cells;
1167
+ }
1168
+ getSelectionColumnCells(range) {
1169
+ const cells = {};
1170
+ for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1171
+ const isSelected = this.model.selection.isRowIndexSelected(row);
1172
+ const classes = (0, import_react_ui_form5.cellClassesForRowSelection)(isSelected);
1173
+ cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1174
+ col: 0,
1175
+ row
1176
+ })] = {
1177
+ value: "",
1178
+ readonly: true,
1179
+ className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1180
+ accessoryHtml: tableControls.checkbox.render({
1181
+ rowIndex: row,
1182
+ checked: isSelected
1183
+ })
1184
+ };
1185
+ }
1186
+ return cells;
1187
+ }
1188
+ getActionColumnCells(range) {
1189
+ const cells = {};
1190
+ for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1191
+ const isSelected = this.model.selection.isRowIndexSelected(row);
1192
+ const classes = (0, import_react_ui_form5.cellClassesForRowSelection)(isSelected);
1193
+ cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1194
+ col: 0,
1195
+ row
1196
+ })] = {
1197
+ value: "",
1198
+ readonly: true,
1199
+ className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1200
+ accessoryHtml: tableButtons.rowMenu.render({
1201
+ rowIndex: row
1202
+ })
1203
+ };
1204
+ }
1205
+ return cells;
1206
+ }
1207
+ getSelectAllCell() {
1208
+ return {
1209
+ [(0, import_react_ui_grid3.toPlaneCellIndex)({
1210
+ col: 0,
1211
+ row: 0
1212
+ })]: {
1213
+ accessoryHtml: tableControls.checkbox.render({
1214
+ rowIndex: 0,
1215
+ header: true,
1216
+ checked: this.model.selection.allRowsSeleted.value
1217
+ }),
1218
+ className: "!bg-gridHeader",
1219
+ readonly: true,
1220
+ value: ""
1221
+ }
1222
+ };
1223
+ }
1224
+ getNewColumnCell() {
1225
+ return {
1226
+ [(0, import_react_ui_grid3.toPlaneCellIndex)({
1227
+ col: 0,
1228
+ row: 0
1229
+ })]: {
1230
+ accessoryHtml: tableButtons.addColumn.render({
1231
+ disabled: (this.model.table.view?.target?.fields?.length ?? 0) >= import_schema2.VIEW_FIELD_LIMIT
1232
+ }),
1233
+ className: "!bg-gridHeader",
1234
+ readonly: true,
1235
+ value: ""
1236
+ }
1237
+ };
1238
+ }
1239
+ };
1240
+ var completion = ({ debug, onQuery, onMatch }) => {
1241
+ return [
1242
+ import_view.EditorView.theme({
1243
+ ".cm-completionDialog": {
1244
+ width: "var(--dx-gridCellWidth)"
1245
+ }
1246
+ }),
1247
+ (0, import_autocomplete.autocompletion)({
1248
+ icons: false,
1249
+ activateOnTyping: true,
1250
+ closeOnBlur: !debug,
1251
+ override: [
1252
+ async (context) => {
1253
+ const text = context.state.doc.toString();
1254
+ return {
1255
+ from: 0,
1256
+ options: await onQuery(text)
1257
+ };
1258
+ }
1259
+ ],
1260
+ // TODO(burdon): Consts from grid (to line-up with grid).
1261
+ tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
1262
+ optionClass: () => "flex h-[33px] items-center"
1263
+ }),
1264
+ // Check for accepted completion metadata in the transaction.
1265
+ import_view.EditorView.updateListener.of((update) => {
1266
+ update.transactions.forEach((tr) => {
1267
+ const completion2 = tr.annotation(import_autocomplete.pickedCompletion);
1268
+ if (completion2) {
1269
+ onMatch(completion2.data);
1270
+ }
1271
+ });
1272
+ })
1273
+ ];
1274
+ };
1275
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
1276
+ var newValue = Symbol.for("newValue");
1277
+ var createOption = (text) => ({
1278
+ [newValue]: true,
1279
+ text
1280
+ });
1281
+ var isCreateOption = (data) => typeof data === "object" && data[newValue];
1282
+ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
1283
+ const { id: gridId, editing, setEditing } = (0, import_react_ui_grid4.useGridContext)("TableCellEditor", __gridScope);
1284
+ const suppressNextBlur = (0, import_react7.useRef)(false);
1285
+ const fieldProjection = (0, import_react7.useMemo)(() => {
1286
+ if (!model || !editing) {
1287
+ return;
1288
+ }
1289
+ const { col } = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1290
+ const field = model.projection.view.fields[col];
1291
+ const fieldProjection2 = model.projection.getFieldProjection(field.id);
1292
+ (0, import_invariant3.invariant)(fieldProjection2, void 0, {
1293
+ F: __dxlog_file4,
1294
+ L: 67,
1295
+ S: void 0,
1296
+ A: [
1297
+ "fieldProjection",
1298
+ ""
1299
+ ]
1300
+ });
1301
+ return fieldProjection2;
1302
+ }, [
1303
+ model,
1304
+ editing
1305
+ ]);
1306
+ const handleEnter = (0, import_react7.useCallback)((value) => {
1307
+ if (!model || !editing) {
1308
+ return;
1309
+ }
1310
+ const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1311
+ model.setCellData(cell, value);
1312
+ onEnter?.(cell);
1313
+ onFocus?.();
1314
+ setEditing(null);
1315
+ }, [
1316
+ model,
1317
+ editing
1318
+ ]);
1319
+ const handleBlur = (0, import_react7.useCallback)((value) => {
1320
+ if (!model || !editing) {
1321
+ return;
1322
+ }
1323
+ if (suppressNextBlur.current) {
1324
+ suppressNextBlur.current = false;
1325
+ return;
1326
+ }
1327
+ const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1328
+ if (value !== void 0) {
1329
+ model.setCellData(cell, value);
1330
+ }
1331
+ }, [
1332
+ model,
1333
+ editing
1334
+ ]);
1335
+ const handleClose = (0, import_react7.useCallback)((value, event) => {
1336
+ if (!model || !editing || !fieldProjection) {
1337
+ return;
1338
+ }
1339
+ const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1340
+ onEnter?.(cell);
1341
+ if (event && onFocus) {
1342
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
1343
+ }
1344
+ }, [
1345
+ model,
1346
+ editing,
1347
+ onFocus,
1348
+ onEnter,
1349
+ fieldProjection,
1350
+ determineNavigationAxis,
1351
+ determineNavigationDelta
1352
+ ]);
1353
+ const extension = (0, import_react7.useMemo)(() => {
1354
+ if (!fieldProjection) {
1355
+ return [];
1356
+ }
1357
+ const extension2 = [
1358
+ (0, import_react_ui_grid4.editorKeys)({
1359
+ onClose: handleClose,
1360
+ ...editing?.initialContent && {
1361
+ onNav: handleClose
1362
+ }
1363
+ })
1364
+ ];
1365
+ if (onQuery) {
1366
+ switch (fieldProjection.props.format) {
1367
+ case import_echo_schema6.FormatEnum.Ref: {
1368
+ extension2.push([
1369
+ completion({
1370
+ onQuery: (text) => onQuery(fieldProjection, text),
1371
+ onMatch: (data) => {
1372
+ if (model && editing && modals) {
1373
+ if (isCreateOption(data)) {
1374
+ const { field, props } = fieldProjection;
1375
+ if (props.referenceSchema) {
1376
+ suppressNextBlur.current = true;
1377
+ modals.openCreateRef(props.referenceSchema, document.querySelector((0, import_react_ui_grid4.cellQuery)(editing.index, gridId)), {
1378
+ [field.referencePath]: data.text
1379
+ }, (data2) => {
1380
+ handleEnter(data2);
1381
+ });
1382
+ }
1383
+ } else {
1384
+ handleEnter(data);
1385
+ }
1386
+ }
1387
+ }
1388
+ })
1389
+ ]);
1390
+ break;
1391
+ }
1392
+ }
1393
+ }
1394
+ return extension2;
1395
+ }, [
1396
+ model,
1397
+ modals,
1398
+ editing,
1399
+ fieldProjection,
1400
+ handleClose
1401
+ ]);
1402
+ const getCellContent = (0, import_react7.useCallback)(() => {
1403
+ if (model && editing) {
1404
+ const value = model.getCellData((0, import_react_ui_grid4.parseCellIndex)(editing.index));
1405
+ return value !== void 0 ? String(value) : "";
1406
+ }
1407
+ }, [
1408
+ model,
1409
+ editing
1410
+ ]);
1411
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui_grid4.GridCellEditor, {
1412
+ extension,
1413
+ getCellContent,
1414
+ onBlur: handleBlur
1415
+ });
1416
+ };
1417
+ var determineNavigationAxis = ({ key }) => {
1418
+ switch (key) {
1419
+ case "ArrowUp":
1420
+ case "ArrowDown":
1421
+ case "Enter": {
1422
+ return "row";
1423
+ }
1424
+ case "ArrowLeft":
1425
+ case "ArrowRight":
1426
+ case "Tab":
1427
+ return "col";
1428
+ }
1429
+ };
1430
+ var determineNavigationDelta = ({ key, shift }) => {
1431
+ switch (key) {
1432
+ case "ArrowUp":
1433
+ case "ArrowLeft":
1434
+ return -1;
1435
+ case "ArrowDown":
1436
+ case "ArrowRight":
1437
+ return 1;
1438
+ }
1439
+ return shift ? -1 : 1;
1440
+ };
1441
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
1442
+ 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";
1443
+ 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";
1444
+ var frozen = {
1445
+ frozenRowsStart: 1,
1446
+ frozenColsStart: 1,
1447
+ frozenColsEnd: 1
1448
+ };
1449
+ var TableRoot = ({ children, role }) => {
1450
+ return /* @__PURE__ */ import_react.default.createElement("div", {
1451
+ role: "none",
1452
+ className: (0, import_react_ui_theme.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]")
1453
+ }, children);
1454
+ };
1455
+ var TableMain = /* @__PURE__ */ (0, import_react.forwardRef)(({ model, presentation, ignoreAttention }, forwardedRef) => {
1456
+ const [dxGrid, setDxGrid] = (0, import_react.useState)(null);
1457
+ const { hasAttention } = (0, import_react_ui_attention.useAttention)(model?.table ? (0, import_echo.fullyQualifiedId)(model.table) : "table");
1458
+ const { t } = (0, import_react_ui.useTranslation)(translationKey);
1459
+ const modals = (0, import_react.useMemo)(() => new ModalController(), []);
1460
+ (0, import_react.useImperativeHandle)(forwardedRef, () => {
1461
+ if (!presentation || !dxGrid) {
1462
+ return {};
1463
+ }
1464
+ dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
1465
+ return {
1466
+ update: (cell) => {
1467
+ if (cell) {
1468
+ dxGrid.updateIfWithinBounds(cell);
1469
+ } else {
1470
+ dxGrid.updateCells(true);
1471
+ dxGrid.requestUpdate();
1472
+ }
1473
+ }
1474
+ };
1475
+ }, [
1476
+ presentation,
1477
+ dxGrid
1478
+ ]);
1479
+ const handleGridClick = (0, import_react.useCallback)((event) => {
1480
+ if (!modals) {
1481
+ return;
1482
+ }
1483
+ const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
1484
+ const tableButtonElement = event.target.closest(buttonSelector);
1485
+ if (tableButtonElement) {
1486
+ const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
1487
+ if (!button) {
1488
+ return;
1489
+ }
1490
+ modals.setTrigger(tableButtonElement);
1491
+ const data = button.getData(tableButtonElement);
1492
+ switch (data.type) {
1493
+ case "rowMenu": {
1494
+ modals.showRowMenu(data.rowIndex);
1495
+ break;
1496
+ }
1497
+ case "columnSettings": {
1498
+ modals.showColumnMenu(data.fieldId);
1499
+ break;
1500
+ }
1501
+ case "newColumn": {
1502
+ modals.showColumnCreator();
1503
+ break;
1504
+ }
1505
+ case "referencedCell": {
1506
+ modals.showReferencePanel(data.targetId, data.schemaId);
1507
+ break;
1508
+ }
1509
+ }
1510
+ return;
1511
+ }
1512
+ const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
1513
+ const controlElement = event.target.closest(controlSelector);
1514
+ if (controlElement) {
1515
+ const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
1516
+ if (!control) {
1517
+ return;
1518
+ }
1519
+ const data = control.getData(controlElement);
1520
+ switch (data.type) {
1521
+ case "checkbox": {
1522
+ if (data.header) {
1523
+ model?.selection.setSelection(model.selection.allRowsSeleted.value ? "none" : "all");
1524
+ } else {
1525
+ model?.selection.toggleSelectionForRowIndex(data.rowIndex);
1526
+ }
1527
+ break;
1528
+ }
1529
+ case "switch": {
1530
+ if (model) {
1531
+ model.updateCellData({
1532
+ row: data.rowIndex,
1533
+ col: data.colIndex
1534
+ }, (value) => !value);
1535
+ }
1536
+ break;
1537
+ }
1538
+ }
1539
+ }
1540
+ }, [
1541
+ model,
1542
+ modals
1543
+ ]);
1544
+ const handleFocus = (0, import_react.useCallback)((increment, delta) => {
1545
+ if (dxGrid) {
1546
+ dxGrid.refocus(increment, delta);
1547
+ }
1548
+ }, [
1549
+ dxGrid
1550
+ ]);
1551
+ const handleEnter = (0, import_react.useCallback)((cell) => {
1552
+ if (model && cell.row === model.getRowCount() - 1) {
1553
+ model.insertRow(cell.row);
1554
+ if (dxGrid) {
1555
+ requestAnimationFrame(() => {
1556
+ dxGrid?.scrollToRow(cell.row + 1);
1557
+ dxGrid?.refocus("row", 1);
1558
+ });
1559
+ }
1560
+ }
1561
+ }, [
1562
+ model,
1563
+ dxGrid
1564
+ ]);
1565
+ const handleKeyDown = (0, import_react.useCallback)((event) => {
1566
+ const cell = (0, import_react_ui_grid.closestCell)(event.target);
1567
+ if (!model || !cell) {
1568
+ return;
1569
+ }
1570
+ switch (event.key) {
1571
+ case "Backspace":
1572
+ case "Delete": {
1573
+ model.setCellData(cell, void 0);
1574
+ break;
1575
+ }
1576
+ }
1577
+ }, [
1578
+ model
1579
+ ]);
1580
+ const handleAxisResize = (0, import_react.useCallback)((event) => {
1581
+ if (event.axis === "col") {
1582
+ const columnIndex = parseInt(event.index, 10);
1583
+ model?.setColumnWidth(columnIndex, event.size);
1584
+ }
1585
+ }, [
1586
+ model
1587
+ ]);
1588
+ const handleWheel = (0, import_react.useCallback)((event) => {
1589
+ if (!ignoreAttention && !hasAttention) {
1590
+ event.stopPropagation();
1591
+ }
1592
+ }, [
1593
+ hasAttention,
1594
+ ignoreAttention
1595
+ ]);
1596
+ const handleNewColumn = (0, import_react.useCallback)(() => {
1597
+ const columns = model?.getColumnCount();
1598
+ if (dxGrid && columns) {
1599
+ dxGrid.scrollToColumn(columns - 1);
1600
+ }
1601
+ }, [
1602
+ model,
1603
+ dxGrid
1604
+ ]);
1605
+ const handleQuery = (0, import_react.useCallback)(async ({ field, props }, text) => {
1606
+ if (model && props.referenceSchema && field.referencePath) {
1607
+ const space = (0, import_echo.getSpace)(model.table);
1608
+ (0, import_invariant.invariant)(space, void 0, {
1609
+ F: __dxlog_file5,
1610
+ L: 260,
1611
+ S: void 0,
1612
+ A: [
1613
+ "space",
1614
+ ""
1615
+ ]
1616
+ });
1617
+ const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
1618
+ if (schema) {
1619
+ const { objects } = await space.db.query(import_echo.Filter.schema(schema)).run();
1620
+ const options = objects.map((obj) => {
1621
+ const value = (0, import_echo_schema.getValue)(obj, field.referencePath);
1622
+ if (!value || typeof value !== "string") {
1623
+ return void 0;
1624
+ }
1625
+ return {
1626
+ label: value,
1627
+ data: obj
1628
+ };
1629
+ }).filter(import_util.isNotFalsy);
1630
+ return [
1631
+ ...options,
1632
+ {
1633
+ label: t("create new object label", {
1634
+ text
1635
+ }),
1636
+ data: createOption(text)
1637
+ }
1638
+ ];
1639
+ }
1640
+ }
1641
+ return [];
1642
+ }, [
1643
+ model
1644
+ ]);
1645
+ if (!model || !modals) {
1646
+ return /* @__PURE__ */ import_react.default.createElement("span", {
1647
+ role: "none",
1648
+ className: "attention-surface"
1649
+ });
1650
+ }
1651
+ return /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Root, {
1652
+ id: model.table.id ?? "table-grid"
1653
+ }, /* @__PURE__ */ import_react.default.createElement(TableCellEditor, {
1654
+ model,
1655
+ modals,
1656
+ onEnter: handleEnter,
1657
+ onFocus: handleFocus,
1658
+ onQuery: handleQuery
1659
+ }), /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Content, {
1660
+ onWheelCapture: handleWheel,
1661
+ className: (0, import_react_ui_theme.mx)("[--dx-grid-base:var(--surface-bg)]", inlineEndLine, blockEndLine),
1662
+ frozen,
1663
+ columns: model.columnMeta.value,
1664
+ limitRows: model.getRowCount() ?? 0,
1665
+ limitColumns: model.table.view?.target?.fields?.length ?? 0,
1666
+ onAxisResize: handleAxisResize,
1667
+ onClick: handleGridClick,
1668
+ onKeyDown: handleKeyDown,
1669
+ overscroll: "trap",
1670
+ ref: setDxGrid
1671
+ }), /* @__PURE__ */ import_react.default.createElement(RowActionsMenu, {
1672
+ model,
1673
+ modals
1674
+ }), /* @__PURE__ */ import_react.default.createElement(ColumnActionsMenu, {
1675
+ model,
1676
+ modals
1677
+ }), /* @__PURE__ */ import_react.default.createElement(ColumnSettings, {
1678
+ model,
1679
+ modals,
1680
+ onNewColumn: handleNewColumn
1681
+ }), /* @__PURE__ */ import_react.default.createElement(RefPanel, {
1682
+ model,
1683
+ modals
1684
+ }), /* @__PURE__ */ import_react.default.createElement(CreateRefPanel, {
1685
+ model,
1686
+ modals
1687
+ }));
1688
+ });
1689
+ var Table = {
1690
+ Root: TableRoot,
1691
+ Main: TableMain
1692
+ };
1693
+ var buttonStyles = "min-bs-0 p-2";
1694
+ var tooltipProps = {
1695
+ side: "top",
1696
+ classNames: "z-10"
1697
+ };
1698
+ var ToolbarSeparator = () => /* @__PURE__ */ import_react9.default.createElement("div", {
1699
+ role: "separator",
1700
+ className: "grow"
1701
+ });
1702
+ var ToolbarButton = ({ icon, children, ...props }) => {
1703
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Root, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Trigger, {
1704
+ asChild: true
1705
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Toolbar.Button, {
1706
+ variant: "ghost",
1707
+ ...props,
1708
+ classNames: buttonStyles
1709
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Icon, {
1710
+ icon,
1711
+ size: 5
1712
+ }), /* @__PURE__ */ import_react9.default.createElement("span", {
1713
+ className: "sr-only"
1714
+ }, children))), /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Portal, null, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Content, tooltipProps, children, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.Tooltip.Arrow, null))));
1715
+ };
1716
+ var [ToolbarContextProvider, useToolbarContext] = (0, import_react_context.createContext)("Toolbar");
1717
+ var ToolbarRoot = ({ classNames, children, onAction }) => {
1718
+ return /* @__PURE__ */ import_react8.default.createElement(ToolbarContextProvider, {
1719
+ onAction
1720
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Toolbar.Root, {
1721
+ classNames: [
1722
+ "is-full shrink-0 overflow-x-auto overflow-y-hidden p-1 attention-surface",
1723
+ classNames
1724
+ ]
1725
+ }, children));
1726
+ };
1727
+ var Editing = () => {
1728
+ const { onAction } = useToolbarContext("Editing");
1729
+ const { t } = (0, import_react_ui7.useTranslation)(translationKey);
1730
+ return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
1731
+ value: "add-row",
1732
+ icon: "ph--plus--regular",
1733
+ "data-testid": "table.toolbar.add-row",
1734
+ onClick: () => onAction?.({
1735
+ type: "add-row"
1736
+ })
1737
+ }, t("add row")));
1738
+ };
1739
+ var Actions = () => {
1740
+ const { onAction } = useToolbarContext("Actions");
1741
+ const { t } = (0, import_react_ui7.useTranslation)(translationKey);
1742
+ return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(ToolbarButton, {
1743
+ value: "comment",
1744
+ icon: "ph--chat-text--regular",
1745
+ "data-testid": "table.toolbar.comment",
1746
+ onClick: () => onAction?.({
1747
+ type: "comment"
1748
+ })
1749
+ }, t("create comment")));
1750
+ };
1751
+ var Toolbar = {
1752
+ Root: ToolbarRoot,
1753
+ Editing,
1754
+ Actions,
1755
+ Separator: ToolbarSeparator
1756
+ };
1562
1757
  var useTableModel = ({ objects, table, projection, ...props }) => {
1563
1758
  const [model, setModel] = (0, import_react10.useState)();
1564
1759
  (0, import_react10.useEffect)(() => {
@@ -1595,12 +1790,20 @@ var useTableModel = ({ objects, table, projection, ...props }) => {
1595
1790
  };
1596
1791
  // Annotate the CommonJS export names for ESM import in node:
1597
1792
  0 && (module.exports = {
1793
+ BUTTON_IDENTIFIERS,
1794
+ CONTROL_IDENTIFIERS,
1795
+ ModalController,
1598
1796
  Table,
1797
+ TableModel,
1798
+ TablePresentation,
1599
1799
  TableSchema,
1600
1800
  TableType,
1601
1801
  Toolbar,
1602
1802
  initializeTable,
1803
+ renderCheckbox,
1804
+ renderSwitch,
1603
1805
  tableButtons,
1806
+ tableControls,
1604
1807
  touch,
1605
1808
  translations,
1606
1809
  useTableModel,