@dxos/react-ui-table 0.7.4 → 0.7.5-main.937ce75

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