@dxos/react-ui-table 0.8.4-main.2e9d522 → 0.8.4-main.548089c

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 (132) hide show
  1. package/dist/lib/browser/chunk-2PFAPQL4.mjs +66 -0
  2. package/dist/lib/browser/chunk-2PFAPQL4.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-GS2UNGJK.mjs} +493 -469
  4. package/dist/lib/browser/chunk-GS2UNGJK.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +614 -696
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +14 -9
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types/index.mjs +3 -3
  11. package/dist/lib/node-esm/chunk-6POOFFYF.mjs +67 -0
  12. package/dist/lib/node-esm/chunk-6POOFFYF.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-TRR3C5NX.mjs} +493 -469
  14. package/dist/lib/node-esm/chunk-TRR3C5NX.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +614 -696
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +14 -9
  19. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/types/index.mjs +3 -3
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -1
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -1
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/DynamicTable.d.ts +2 -2
  26. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +51 -3
  28. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Relations.stories.d.ts +107 -0
  30. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  31. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  32. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.d.ts +8 -4
  34. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  35. package/dist/types/src/components/Table/Table.stories.d.ts +42 -4
  36. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  38. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -6
  39. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  40. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +12 -17
  41. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  42. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -4
  43. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
  45. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
  46. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +2 -2
  47. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  48. package/dist/types/src/components/testing.d.ts +3 -3
  49. package/dist/types/src/components/testing.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useAddRow.d.ts +3 -2
  51. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  52. package/dist/types/src/hooks/useTableModel.d.ts +4 -4
  53. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  54. package/dist/types/src/model/modal-controller.d.ts +0 -7
  55. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  56. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  57. package/dist/types/src/model/table-model.d.ts +11 -9
  58. package/dist/types/src/model/table-model.d.ts.map +1 -1
  59. package/dist/types/src/model/table-presentation.d.ts +2 -1
  60. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  61. package/dist/types/src/model/table-sorting.d.ts +3 -4
  62. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  63. package/dist/types/src/testing/useTestTableModel.d.ts +3 -22
  64. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  65. package/dist/types/src/translations.d.ts +2 -2
  66. package/dist/types/src/types/index.d.ts +1 -1
  67. package/dist/types/src/types/index.d.ts.map +1 -1
  68. package/dist/types/src/types/schema.d.ts +25 -5
  69. package/dist/types/src/types/schema.d.ts.map +1 -1
  70. package/dist/types/src/util/dynamic-table.d.ts +5 -6
  71. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  72. package/dist/types/src/util/index.d.ts +0 -1
  73. package/dist/types/src/util/index.d.ts.map +1 -1
  74. package/dist/types/src/util/schema.d.ts +1 -1
  75. package/dist/types/src/util/schema.d.ts.map +1 -1
  76. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  77. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  78. package/dist/types/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +57 -51
  80. package/src/components/Table/ColumnActionsMenu.tsx +1 -1
  81. package/src/components/Table/ColumnSettings.tsx +1 -1
  82. package/src/components/Table/DynamicTable.stories.tsx +18 -14
  83. package/src/components/Table/DynamicTable.tsx +8 -10
  84. package/src/components/Table/Relations.stories.tsx +242 -0
  85. package/src/components/Table/RowActionsMenu.tsx +23 -15
  86. package/src/components/Table/Table.stories.tsx +72 -60
  87. package/src/components/Table/Table.tsx +147 -117
  88. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  89. package/src/components/TableCellEditor/FormCellEditor.tsx +153 -42
  90. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +25 -64
  91. package/src/components/TableCellEditor/TableCellEditor.tsx +74 -224
  92. package/src/components/TableCellEditor/index.ts +1 -0
  93. package/src/components/TableToolbar/TableToolbar.tsx +33 -23
  94. package/src/components/testing.ts +2 -2
  95. package/src/hooks/useAddRow.ts +7 -5
  96. package/src/hooks/useTableModel.ts +6 -6
  97. package/src/model/modal-controller.ts +1 -29
  98. package/src/model/selection-model.ts +3 -2
  99. package/src/model/table-model.test.ts +20 -11
  100. package/src/model/table-model.ts +46 -31
  101. package/src/model/table-presentation.test.ts +24 -22
  102. package/src/model/table-presentation.ts +74 -33
  103. package/src/model/table-sorting.ts +17 -8
  104. package/src/playwright/TableManager.ts +1 -1
  105. package/src/playwright/smoke.spec.ts +131 -37
  106. package/src/testing/useTestTableModel.ts +12 -8
  107. package/src/translations.ts +2 -2
  108. package/src/types/index.ts +1 -1
  109. package/src/types/schema.ts +63 -6
  110. package/src/util/dynamic-table.ts +16 -17
  111. package/src/util/index.ts +0 -1
  112. package/src/util/schema.ts +4 -4
  113. package/src/util/table-buttons.ts +4 -3
  114. package/src/util/table-controls.ts +4 -1
  115. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
  117. package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
  118. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
  119. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
  120. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
  121. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  122. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  123. package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
  124. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
  125. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  126. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  127. package/dist/types/src/util/table.d.ts +0 -11
  128. package/dist/types/src/util/table.d.ts.map +0 -1
  129. package/src/components/Table/CreateRefPanel.tsx +0 -86
  130. package/src/components/Table/relations.stories.tsx +0 -116
  131. package/src/components/TableCellEditor/extension.ts +0 -61
  132. package/src/util/table.ts +0 -49
@@ -1,11 +1,11 @@
1
1
  import {
2
- TableView
3
- } from "./chunk-L2LSB6KV.mjs";
2
+ schema_exports
3
+ } from "./chunk-2PFAPQL4.mjs";
4
4
 
5
5
  // src/util/dynamic-table.ts
6
- import { Obj } from "@dxos/echo";
7
- import { getTypename, toJsonSchema } from "@dxos/echo-schema";
8
- import { createView, getSchemaFromPropertyDefinitions, ProjectionModel } from "@dxos/schema";
6
+ import { Filter, Obj, Query } from "@dxos/echo";
7
+ import { getTypename, toJsonSchema } from "@dxos/echo/internal";
8
+ import { ProjectionModel, View, getSchemaFromPropertyDefinitions } from "@dxos/schema";
9
9
  var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
10
10
  if (typename && properties) {
11
11
  const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
@@ -27,12 +27,12 @@ var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
27
27
  throw new Error("invalid properties");
28
28
  }
29
29
  };
30
- var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
31
- const table = Obj.make(TableView, {
30
+ var makeDynamicTable = ({ jsonSchema, properties }) => {
31
+ const table = Obj.make(schema_exports.Table, {
32
32
  sizes: {}
33
33
  });
34
- const view = createView({
35
- typename,
34
+ const view = View.make({
35
+ query: Query.select(Filter.everything()),
36
36
  jsonSchema,
37
37
  presentation: table,
38
38
  ...properties && {
@@ -40,6 +40,7 @@ var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
40
40
  }
41
41
  });
42
42
  const projection = new ProjectionModel(jsonSchema, view.projection);
43
+ projection.normalizeView();
43
44
  if (properties && projection.fields) {
44
45
  setProperties(view, projection, table, properties);
45
46
  }
@@ -67,7 +68,7 @@ var setProperties = (view, projection, table, properties) => {
67
68
  }
68
69
  if (property.sort) {
69
70
  const fieldId = field.id;
70
- view.query.sort = [
71
+ view.sort = [
71
72
  {
72
73
  fieldId,
73
74
  direction: property.sort
@@ -81,40 +82,6 @@ var setProperties = (view, projection, table, properties) => {
81
82
  // src/util/signals.ts
82
83
  var touch = (value) => value;
83
84
 
84
- // src/util/table.ts
85
- import { Match } from "effect";
86
- import { Obj as Obj2 } from "@dxos/echo";
87
- import { toEffectSchema } from "@dxos/echo-schema";
88
- import { createViewFromSpace, getSchemaProperties } from "@dxos/schema";
89
- var createTable = async ({ sizes, ...props }) => {
90
- const table = Obj2.make(TableView, {
91
- sizes: {}
92
- });
93
- const { jsonSchema, view } = await createViewFromSpace({
94
- ...props,
95
- presentation: table
96
- });
97
- const schema = toEffectSchema(jsonSchema);
98
- const shouldIncludeId = props.fields?.find((field) => field === "id") !== void 0;
99
- const properties = getSchemaProperties(schema.ast, {}, shouldIncludeId);
100
- for (const property of properties) {
101
- if (sizes?.[property.name]) {
102
- table.sizes[property.name] = sizes[property.name];
103
- continue;
104
- }
105
- Match.type().pipe(Match.when("boolean", () => {
106
- table.sizes[property.name] = 100;
107
- }), Match.when("number", () => {
108
- table.sizes[property.name] = 100;
109
- }), Match.orElse(() => {
110
- }))(property.type);
111
- }
112
- return {
113
- jsonSchema,
114
- view
115
- };
116
- };
117
-
118
85
  // src/util/table-buttons.ts
119
86
  var BUTTON_IDENTIFIERS = {
120
87
  columnSettings: "data-table-column-settings-button",
@@ -124,10 +91,9 @@ var BUTTON_IDENTIFIERS = {
124
91
  saveDraftRow: "data-table-save-draft-row-button",
125
92
  sort: "data-table-sort-button"
126
93
  };
127
- var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
94
+ var createButton = ({ attr, data, disabled = false, icon, testId, type: _type = "primary" }) => {
128
95
  const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
129
- const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
130
- return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? "disabled" : ""}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
96
+ return `<button ${attr} data-testid="${testId}" class="dx-button is-6 aspect-square pli-0.5 min-bs-0" ${dataAttrs} ${disabled ? "disabled" : ""} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
131
97
  };
132
98
  var addColumnButton = {
133
99
  attr: BUTTON_IDENTIFIERS.newColumn,
@@ -153,7 +119,8 @@ var columnSettingsButton = {
153
119
  attr: BUTTON_IDENTIFIERS.columnSettings,
154
120
  icon: columnSettingsButton.icon,
155
121
  data: {
156
- "data-field-id": fieldId
122
+ "data-field-id": fieldId,
123
+ "data-variant": "ghost"
157
124
  },
158
125
  testId: "table-column-settings-button"
159
126
  });
@@ -213,7 +180,8 @@ var saveDraftRowButton = {
213
180
  icon: saveDraftRowButton.icon,
214
181
  disabled,
215
182
  data: {
216
- "data-row-index": rowIndex.toString()
183
+ "data-row-index": rowIndex.toString(),
184
+ "data-variant": "primary"
217
185
  },
218
186
  testId: "table-save-draft-row-button"
219
187
  });
@@ -232,6 +200,7 @@ var tableButtons = {
232
200
  };
233
201
 
234
202
  // src/util/table-controls.ts
203
+ import { accessoryHandlesPointerdownAttrs } from "@dxos/lit-grid";
235
204
  var CONTROL_IDENTIFIERS = {
236
205
  checkbox: "data-table-checkbox",
237
206
  switch: "data-table-switch"
@@ -244,7 +213,7 @@ var renderAttributes = (data) => {
244
213
  return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
245
214
  };
246
215
  var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
247
- return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
216
+ return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}" data-dx-grid-action="accessory"/>`;
248
217
  };
249
218
  var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
250
219
  const attrs = {
@@ -260,7 +229,8 @@ var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) =>
260
229
  const attrs = {
261
230
  [CONTROL_IDENTIFIERS.switch]: "",
262
231
  "data-row-index": rowIndex.toString(),
263
- "data-col-index": colIndex.toString()
232
+ "data-col-index": colIndex.toString(),
233
+ ...accessoryHandlesPointerdownAttrs
264
234
  };
265
235
  return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
266
236
  };
@@ -286,14 +256,14 @@ var tableControls = {
286
256
  };
287
257
 
288
258
  // src/util/schema.ts
289
- import { Schema } from "effect";
290
- import { isTypeLiteral, TypeLiteral } from "effect/SchemaAST";
259
+ import * as Schema from "effect/Schema";
260
+ import * as SchemaAST from "effect/SchemaAST";
291
261
  var narrowSchema = (schema, paths) => {
292
262
  const ast = schema?.ast;
293
- if (isTypeLiteral(ast)) {
263
+ if (SchemaAST.isTypeLiteral(ast)) {
294
264
  const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
295
265
  if (propertySignatures.length > 0) {
296
- const narrowType = new TypeLiteral(propertySignatures, []);
266
+ const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
297
267
  return Schema.make(narrowType);
298
268
  }
299
269
  }
@@ -303,67 +273,59 @@ var narrowSchema = (schema, paths) => {
303
273
  // src/model/table-model.ts
304
274
  import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
305
275
  import { Resource as Resource2 } from "@dxos/context";
306
- import { Obj as Obj3, Ref } from "@dxos/echo";
307
- import { FormatEnum as FormatEnum2, getValue as getValue2, setValue, getSnapshot, getSchema, toEffectSchema as toEffectSchema2 } from "@dxos/echo-schema";
276
+ import { Obj as Obj2, Ref } from "@dxos/echo";
277
+ import { FormatEnum as FormatEnum2, getSchema, getValue as getValue2, setValue, toEffectSchema } from "@dxos/echo/internal";
308
278
  import { invariant } from "@dxos/invariant";
309
279
  import { ObjectId } from "@dxos/keys";
310
- import { isLiveObject } from "@dxos/live-object";
311
- import { fullyQualifiedId } from "@dxos/react-client/echo";
280
+ import { getSnapshot, isLiveObject } from "@dxos/live-object";
312
281
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
313
282
  import { ProjectionModel as ProjectionModel2, validateSchema } from "@dxos/schema";
314
283
 
284
+ // src/util/tag.ts
285
+ var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
286
+ var extractTagIds = (value) => {
287
+ if (typeof value !== "string") {
288
+ return void 0;
289
+ }
290
+ const ids = [];
291
+ let match;
292
+ while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
293
+ if (match[2]) {
294
+ ids.push(match[2]);
295
+ }
296
+ }
297
+ return ids.length > 0 ? ids : void 0;
298
+ };
299
+
315
300
  // src/model/selection-model.ts
316
301
  import { computed, effect, signal } from "@preact/signals-core";
317
302
  import { Resource } from "@dxos/context";
318
303
  var SelectionModel = class extends Resource {
304
+ _rows;
305
+ _selectionMode;
306
+ _initialSelection;
307
+ _onSelectionChanged;
308
+ _selection;
309
+ _validSelectedIds = computed(() => {
310
+ const rows = this._rows.value;
311
+ if (!rows) {
312
+ return /* @__PURE__ */ new Set();
313
+ }
314
+ const validIds = new Set(rows.map((row) => row.id));
315
+ return new Set([
316
+ ...this._selection.value
317
+ ].filter((id) => validIds.has(id)));
318
+ });
319
+ _hasSelection = computed(() => this._validSelectedIds.value.size > 0);
320
+ _allSelected = computed(() => {
321
+ const rows = this._rows.value;
322
+ if (rows.length === 0) {
323
+ return false;
324
+ }
325
+ return rows.every((row) => this._selection.value.has(row.id));
326
+ });
319
327
  constructor(_rows, _selectionMode, _initialSelection, _onSelectionChanged) {
320
- super(), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged, this._validSelectedIds = computed(() => {
321
- const rows = this._rows.value;
322
- if (!rows) {
323
- return /* @__PURE__ */ new Set();
324
- }
325
- const validIds = new Set(rows.map((row) => row.id));
326
- return new Set([
327
- ...this._selection.value
328
- ].filter((id) => validIds.has(id)));
329
- }), this._hasSelection = computed(() => this._validSelectedIds.value.size > 0), this._allSelected = computed(() => {
330
- const rows = this._rows.value;
331
- if (rows.length === 0) {
332
- return false;
333
- }
334
- return rows.every((row) => this._selection.value.has(row.id));
335
- }), this.getSelectedRows = () => {
336
- const selectedIds = this._validSelectedIds.value;
337
- return this._rows.value.filter((row) => selectedIds.has(row.id));
338
- }, this.isRowIndexSelected = (rowIndex) => {
339
- const row = this._rows.value[rowIndex];
340
- return this._selection.value.has(row.id);
341
- }, this.isObjectSelected = (object) => {
342
- return this._selection.value.has(object.id);
343
- }, this.toggleSelectionForRowIndex = (rowIndex) => {
344
- const row = this._rows.value[rowIndex];
345
- const newSelection = new Set(this._selection.value);
346
- if (newSelection.has(row.id)) {
347
- newSelection.delete(row.id);
348
- } else {
349
- if (this._selectionMode === "single") {
350
- newSelection.clear();
351
- }
352
- newSelection.add(row.id);
353
- }
354
- this._selection.value = newSelection;
355
- }, this.setSelection = (mode) => {
356
- switch (mode) {
357
- case "all": {
358
- this._selection.value = new Set(this._rows.value.map((row) => row.id));
359
- break;
360
- }
361
- case "none": {
362
- this._selection.value = /* @__PURE__ */ new Set();
363
- break;
364
- }
365
- }
366
- };
328
+ super(), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged;
367
329
  this._selection = signal(new Set(this._initialSelection));
368
330
  }
369
331
  async _open() {
@@ -388,23 +350,67 @@ var SelectionModel = class extends Resource {
388
350
  get selectionMode() {
389
351
  return this._selectionMode;
390
352
  }
353
+ getSelectedRows = () => {
354
+ const selectedIds = this._validSelectedIds.value;
355
+ return this._rows.value.filter((row) => selectedIds.has(row.id));
356
+ };
357
+ isRowIndexSelected = (rowIndex) => {
358
+ const row = this._rows.value[rowIndex];
359
+ return this._selection.value.has(row.id);
360
+ };
361
+ isObjectSelected = (object) => {
362
+ return this._selection.value.has(object.id);
363
+ };
364
+ //
365
+ // Manipulation
366
+ //
367
+ toggleSelectionForRowIndex = (rowIndex) => {
368
+ const row = this._rows.value[rowIndex];
369
+ const newSelection = new Set(this._selection.value);
370
+ if (newSelection.has(row.id)) {
371
+ newSelection.delete(row.id);
372
+ } else {
373
+ if (this._selectionMode === "single") {
374
+ newSelection.clear();
375
+ }
376
+ newSelection.add(row.id);
377
+ }
378
+ this._selection.value = newSelection;
379
+ };
380
+ setSelection = (mode) => {
381
+ switch (mode) {
382
+ case "all": {
383
+ this._selection.value = new Set(this._rows.value.map((row) => row.id));
384
+ break;
385
+ }
386
+ case "none": {
387
+ this._selection.value = /* @__PURE__ */ new Set();
388
+ break;
389
+ }
390
+ }
391
+ };
391
392
  };
392
393
 
393
394
  // src/model/table-sorting.ts
394
395
  import { computed as computed2, signal as signal2 } from "@preact/signals-core";
395
396
  import orderBy from "lodash.orderby";
396
- import { getValue, FormatEnum, TypeEnum } from "@dxos/echo-schema";
397
+ import { FormatEnum, TypeEnum, getValue } from "@dxos/echo/internal";
397
398
  import { formatForDisplay } from "@dxos/react-ui-form";
398
399
  var TableSorting = class {
400
+ _view;
401
+ _projection;
402
+ _displayToDataIndex = /* @__PURE__ */ new Map();
403
+ _rows;
404
+ _localSort = signal2(void 0);
405
+ _isDirty;
406
+ sortedRows;
399
407
  constructor(rows, _view, _projection) {
400
408
  this._view = _view;
401
409
  this._projection = _projection;
402
- this._displayToDataIndex = /* @__PURE__ */ new Map();
403
- this._localSort = signal2(void 0);
404
410
  this._rows = rows;
405
411
  this._isDirty = computed2(() => {
406
412
  const local = this._localSort.value;
407
- const viewSort = this._view.query.sort?.[0];
413
+ const viewSort = this._view.sort?.[0];
408
414
  if (local?.type === "cleared") {
409
415
  return viewSort !== void 0;
410
416
  }
@@ -430,7 +436,7 @@ var TableSorting = class {
430
436
  if (local?.type === "active") {
431
437
  return local.sort;
432
438
  }
433
- return this._view.query.sort?.[0];
439
+ return this._view.sort?.[0];
434
440
  }
435
441
  /**
436
442
  * @reactive
@@ -474,11 +480,11 @@ var TableSorting = class {
474
480
  save() {
475
481
  if (this._localSort.value !== void 0) {
476
482
  if (this._localSort.value.type === "active") {
477
- this._view.query.sort = [
483
+ this._view.sort = [
478
484
  this._localSort.value.sort
479
485
  ];
480
486
  } else {
481
- this._view.query.sort = [];
487
+ this._view.sort = [];
482
488
  }
483
489
  this._localSort.value = void 0;
484
490
  }
@@ -555,22 +561,6 @@ var TableSorting = class {
555
561
  }
556
562
  };
557
563
 
558
- // src/util/tag.ts
559
- var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
560
- var extractTagIds = (value) => {
561
- if (typeof value !== "string") {
562
- return void 0;
563
- }
564
- const ids = [];
565
- let match;
566
- while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
567
- if (match[2]) {
568
- ids.push(match[2]);
569
- }
570
- }
571
- return ids.length > 0 ? ids : void 0;
572
- };
573
-
574
564
  // src/model/table-model.ts
575
565
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
576
566
  var defaultFeatures = {
@@ -582,231 +572,48 @@ var defaultFeatures = {
582
572
  schemaEditable: false
583
573
  };
584
574
  var TableModel = class extends Resource2 {
575
+ _view;
576
+ _projection;
577
+ _table;
578
+ _visibleRange = signal3({
579
+ start: {
580
+ row: 0,
581
+ col: 0
582
+ },
583
+ end: {
584
+ row: 0,
585
+ col: 0
586
+ }
587
+ });
588
+ _onInsertRow;
589
+ _onDeleteRows;
590
+ _onDeleteColumn;
591
+ _onCellUpdate;
592
+ _onRowOrderChange;
593
+ _onRowAction;
594
+ _rowActions;
595
+ _features;
596
+ _rows = signal3([]);
597
+ _draftRows = signal3([]);
598
+ _sorting;
599
+ _pinnedRows;
600
+ _selection;
601
+ _columnMeta;
585
602
  constructor({ view, schema, projection, features = {}, sorting = [], initialSelection = [], pinnedRows = {
586
603
  top: [],
587
604
  bottom: []
588
605
  }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
589
606
  super();
590
- this._visibleRange = signal3({
591
- start: {
592
- row: 0,
593
- col: 0
594
- },
595
- end: {
596
- row: 0,
597
- col: 0
598
- }
599
- });
600
- this._rows = signal3([]);
601
- this._draftRows = signal3([]);
602
- //
603
- // Data
604
- //
605
- this.setRows = (obj) => {
606
- this._rows.value = obj;
607
- };
608
- this.getRowCount = () => this._rows.value.length;
609
- /**
610
- * @reactive
611
- */
612
- this.getDraftRowCount = () => this._draftRows.value.length;
613
- this.getColumnCount = () => this._projection?.fields.length ?? 0;
614
- this.insertRow = () => {
615
- const result = this._onInsertRow?.();
616
- if (result === false && this._draftRows.value.length === 0) {
617
- this.createDraftRow();
618
- }
619
- };
620
- this.commitDraftRow = (draftRowIndex) => {
621
- if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
622
- return false;
623
- }
624
- const draftRow = this._draftRows.value[draftRowIndex];
625
- if (!draftRow.valid) {
626
- return false;
627
- }
628
- const success = this._onInsertRow?.(draftRow.data);
629
- if (success) {
630
- const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
631
- this._draftRows.value = newDraftRows;
632
- }
633
- return success ?? false;
634
- };
635
- this.deleteRow = (rowIndex) => {
636
- const row = this._sorting.getDataIndex(rowIndex);
637
- const obj = this._rows.value[row];
638
- const objectsToDelete = [];
639
- if (this.features.selection.enabled && this._selection.hasSelection.value) {
640
- const selectedRows = this._selection.getSelectedRows();
641
- objectsToDelete.push(...selectedRows);
642
- } else {
643
- objectsToDelete.push(obj);
644
- }
645
- this._onDeleteRows?.(row, objectsToDelete);
646
- };
647
- this.handleRowAction = (actionId, rowIndex) => {
648
- if (!this._onRowAction) {
649
- return;
650
- }
651
- const row = this._sorting.getDataIndex(rowIndex);
652
- const data = this._rows.value[row];
653
- if (data) {
654
- this._onRowAction(actionId, data);
655
- }
656
- };
657
- this.getCellData = (cell) => {
658
- const { col, row, plane } = cell;
659
- const fields = this._projection?.fields ?? [];
660
- if (col < 0 || col >= fields.length) {
661
- return void 0;
662
- }
663
- const field = fields[col];
664
- let value;
665
- if (plane === "frozenRowsEnd") {
666
- if (row >= 0 && row < this._draftRows.value.length) {
667
- value = getValue2(this._draftRows.value[row].data, field.path);
668
- } else {
669
- return void 0;
670
- }
671
- } else {
672
- const dataIndex = this._sorting.getDataIndex(row);
673
- value = getValue2(this._rows.value[dataIndex], field.path);
674
- }
675
- if (value == null) {
676
- return "";
677
- }
678
- const { props } = this._projection.getFieldProjection(field.id);
679
- switch (props.format) {
680
- case FormatEnum2.Ref: {
681
- if (!field.referencePath) {
682
- return "";
683
- }
684
- return getValue2(value.target, field.referencePath);
685
- }
686
- default: {
687
- return formatForEditing({
688
- type: props.type,
689
- format: props.format,
690
- value
691
- });
692
- }
693
- }
694
- };
695
- this.validateCellData = async ({ col, row, plane }, value) => {
696
- const fields = this._projection?.fields ?? [];
697
- if (col < 0 || col >= fields.length) {
698
- return {
699
- valid: false,
700
- error: "Invalid column index"
701
- };
702
- }
703
- const field = fields[col];
704
- const { props } = this._projection.getFieldProjection(field.id);
705
- const transformedValue = editorTextToCellValue(props, value);
706
- const isDraftRow = plane === "frozenRowsEnd";
707
- if (isDraftRow) {
708
- const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
709
- if (isInvalidDraftRowIndex) {
710
- return {
711
- valid: false,
712
- error: "Invalid draft row index"
713
- };
714
- }
715
- const draftRow = this._draftRows.value[row];
716
- const snapshot = {
717
- ...draftRow.data
718
- };
719
- setValue(snapshot, field.path, transformedValue);
720
- const validationErrors = this.validateDraftRowData(snapshot);
721
- if (validationErrors.length > 0) {
722
- const error = validationErrors.find((err) => err.path === field.path);
723
- if (error) {
724
- return {
725
- valid: false,
726
- error: error.message
727
- };
728
- }
729
- }
730
- return {
731
- valid: true
732
- };
733
- } else {
734
- const rowIdx = this._sorting.getDataIndex(row);
735
- const currentRow = this._rows.value[rowIdx];
736
- invariant(currentRow, "Invalid row index", {
737
- F: __dxlog_file,
738
- L: 510,
739
- S: this,
740
- A: [
741
- "currentRow",
742
- "'Invalid row index'"
743
- ]
744
- });
745
- const snapshot = getSnapshot(currentRow);
746
- setValue(snapshot, field.path, transformedValue);
747
- const schema = getSchema(currentRow);
748
- invariant(schema, void 0, {
749
- F: __dxlog_file,
750
- L: 516,
751
- S: this,
752
- A: [
753
- "schema",
754
- ""
755
- ]
756
- });
757
- const validationResult = validateSchema(schema, snapshot);
758
- if (validationResult && validationResult.length > 0) {
759
- const error = validationResult[0];
760
- invariant(error.path === field.path, void 0, {
761
- F: __dxlog_file,
762
- L: 521,
763
- S: this,
764
- A: [
765
- "error.path === field.path",
766
- ""
767
- ]
768
- });
769
- return {
770
- valid: false,
771
- error: error.message
772
- };
773
- }
774
- return {
775
- valid: true
776
- };
777
- }
778
- };
779
- this.setCellData = (cell, value) => {
780
- const { col, row, plane } = cell;
781
- const fields = this._projection?.fields ?? [];
782
- if (col < 0 || col >= fields.length) {
783
- return;
784
- }
785
- const field = fields[col];
786
- const { props } = this._projection.getFieldProjection(field.id);
787
- const transformedValue = editorTextToCellValue(props, value);
788
- if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
789
- return;
790
- }
791
- if (plane === "frozenRowsEnd") {
792
- if (row >= 0 && row < this._draftRows.value.length) {
793
- setValue(this._draftRows.value[row].data, field.path, transformedValue);
794
- this.validateDraftRow(row);
795
- }
796
- } else {
797
- const rowIdx = this._sorting.getDataIndex(row);
798
- setValue(this._rows.value[rowIdx], field.path, transformedValue);
799
- }
800
- };
801
607
  this._view = view;
802
608
  this._projection = projection ?? new ProjectionModel2(schema, view.projection);
609
+ this._projection.normalizeView();
803
610
  this._features = {
804
611
  ...defaultFeatures,
805
612
  ...features
806
613
  };
807
614
  invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
808
615
  F: __dxlog_file,
809
- L: 139,
616
+ L: 148,
810
617
  S: this,
811
618
  A: [
812
619
  "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
@@ -829,7 +636,7 @@ var TableModel = class extends Resource2 {
829
636
  this._onRowAction = onRowAction;
830
637
  }
831
638
  get id() {
832
- return fullyQualifiedId(this._view);
639
+ return Obj2.getDXN(this._view).toString();
833
640
  }
834
641
  get view() {
835
642
  return this._view;
@@ -837,7 +644,7 @@ var TableModel = class extends Resource2 {
837
644
  get table() {
838
645
  invariant(this._table, "Model not initialized", {
839
646
  F: __dxlog_file,
840
- L: 177,
647
+ L: 186,
841
648
  S: this,
842
649
  A: [
843
650
  "this._table",
@@ -876,7 +683,7 @@ var TableModel = class extends Resource2 {
876
683
  get columnMeta() {
877
684
  invariant(this._columnMeta, void 0, {
878
685
  F: __dxlog_file,
879
- L: 216,
686
+ L: 225,
880
687
  S: this,
881
688
  A: [
882
689
  "this._columnMeta",
@@ -900,12 +707,12 @@ var TableModel = class extends Resource2 {
900
707
  //
901
708
  async _open() {
902
709
  const presentation = this._view.presentation.target ?? await this._view.presentation.load();
903
- invariant(Obj3.instanceOf(TableView, presentation), void 0, {
710
+ invariant(Obj2.instanceOf(schema_exports.Table, presentation), void 0, {
904
711
  F: __dxlog_file,
905
- L: 239,
712
+ L: 248,
906
713
  S: this,
907
714
  A: [
908
- "Obj.instanceOf(TableView, presentation)",
715
+ "Obj.instanceOf(Table.Table, presentation)",
909
716
  ""
910
717
  ]
911
718
  });
@@ -934,7 +741,7 @@ var TableModel = class extends Resource2 {
934
741
  },
935
742
  frozenColsEnd: {
936
743
  0: {
937
- size: 40,
744
+ size: 32,
938
745
  resizeable: false
939
746
  }
940
747
  }
@@ -970,6 +777,17 @@ var TableModel = class extends Resource2 {
970
777
  });
971
778
  this._ctx.onDispose(draftRowsWatcher);
972
779
  }
780
+ //
781
+ // Data
782
+ //
783
+ setRows = (obj) => {
784
+ this._rows.value = obj;
785
+ };
786
+ getRowCount = () => this._rows.value.length;
787
+ /**
788
+ * @reactive
789
+ */
790
+ getDraftRowCount = () => this._draftRows.value.length;
973
791
  // TODO(ZaymonFC): Return .value instead of exposing the signal.
974
792
  get draftRows() {
975
793
  return this._draftRows;
@@ -988,6 +806,14 @@ var TableModel = class extends Resource2 {
988
806
  const validationErrors = draftRow.validationErrors || [];
989
807
  return validationErrors.some((error) => error.path === fieldPath);
990
808
  }
809
+ getColumnCount = () => this._projection?.fields.length ?? 0;
810
+ insertRow = () => {
811
+ const result = this._onInsertRow?.();
812
+ if (result === "draft" && this._draftRows.value.length === 0) {
813
+ this.createDraftRow();
814
+ }
815
+ return result ?? "final";
816
+ };
991
817
  createDraftRow() {
992
818
  if (!this._projection) {
993
819
  return;
@@ -1024,9 +850,190 @@ var TableModel = class extends Resource2 {
1024
850
  this._draftRows.value = newDraftRows;
1025
851
  }
1026
852
  validateDraftRowData(data) {
1027
- const schema = toEffectSchema2(this._projection.baseSchema);
853
+ const schema = toEffectSchema(this._projection.baseSchema);
1028
854
  return validateSchema(schema, data) || [];
1029
855
  }
856
+ commitDraftRow = (draftRowIndex) => {
857
+ if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
858
+ return false;
859
+ }
860
+ const draftRow = this._draftRows.value[draftRowIndex];
861
+ if (!draftRow.valid) {
862
+ return false;
863
+ }
864
+ const insertRowResult = this._onInsertRow?.(draftRow.data);
865
+ if (insertRowResult === "final") {
866
+ const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
867
+ this._draftRows.value = newDraftRows;
868
+ }
869
+ return insertRowResult === "final";
870
+ };
871
+ deleteRow = (rowIndex) => {
872
+ const row = this._sorting.getDataIndex(rowIndex);
873
+ const obj = this._rows.value[row];
874
+ const objectsToDelete = [];
875
+ if (this.features.selection.enabled && this._selection.hasSelection.value) {
876
+ const selectedRows = this._selection.getSelectedRows();
877
+ objectsToDelete.push(...selectedRows);
878
+ } else {
879
+ objectsToDelete.push(obj);
880
+ }
881
+ this._onDeleteRows?.(row, objectsToDelete);
882
+ };
883
+ handleRowAction = (actionId, rowIndex) => {
884
+ if (!this._onRowAction) {
885
+ return;
886
+ }
887
+ const row = this._sorting.getDataIndex(rowIndex);
888
+ const data = this._rows.value[row];
889
+ if (data) {
890
+ this._onRowAction(actionId, data);
891
+ }
892
+ };
893
+ getCellData = (cell) => {
894
+ const { col, row, plane } = cell;
895
+ const fields = this._projection?.fields ?? [];
896
+ if (col < 0 || col >= fields.length) {
897
+ return void 0;
898
+ }
899
+ const field = fields[col];
900
+ let value;
901
+ if (plane === "frozenRowsEnd") {
902
+ if (row >= 0 && row < this._draftRows.value.length) {
903
+ value = getValue2(this._draftRows.value[row].data, field.path);
904
+ } else {
905
+ return void 0;
906
+ }
907
+ } else {
908
+ const dataIndex = this._sorting.getDataIndex(row);
909
+ value = getValue2(this._rows.value[dataIndex], field.path);
910
+ }
911
+ if (value == null) {
912
+ return "";
913
+ }
914
+ const { props } = this._projection.getFieldProjection(field.id);
915
+ switch (props.format) {
916
+ case FormatEnum2.Ref: {
917
+ if (!field.referencePath) {
918
+ return "";
919
+ }
920
+ return getValue2(value.target, field.referencePath);
921
+ }
922
+ default: {
923
+ return formatForEditing({
924
+ type: props.type,
925
+ format: props.format,
926
+ value
927
+ });
928
+ }
929
+ }
930
+ };
931
+ validateCellData = async ({ col, row, plane }, value) => {
932
+ const fields = this._projection?.fields ?? [];
933
+ if (col < 0 || col >= fields.length) {
934
+ return {
935
+ valid: false,
936
+ error: "Invalid column index"
937
+ };
938
+ }
939
+ const field = fields[col];
940
+ const { props } = this._projection.getFieldProjection(field.id);
941
+ const transformedValue = editorTextToCellValue(props, value);
942
+ const isDraftRow = plane === "frozenRowsEnd";
943
+ if (isDraftRow) {
944
+ const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
945
+ if (isInvalidDraftRowIndex) {
946
+ return {
947
+ valid: false,
948
+ error: "Invalid draft row index"
949
+ };
950
+ }
951
+ const draftRow = this._draftRows.value[row];
952
+ const snapshot = {
953
+ ...draftRow.data
954
+ };
955
+ setValue(snapshot, field.path, transformedValue);
956
+ const validationErrors = this.validateDraftRowData(snapshot);
957
+ if (validationErrors.length > 0) {
958
+ const error = validationErrors.find((err) => err.path === field.path);
959
+ if (error) {
960
+ return {
961
+ valid: false,
962
+ error: error.message
963
+ };
964
+ }
965
+ }
966
+ return {
967
+ valid: true
968
+ };
969
+ } else {
970
+ const rowIdx = this._sorting.getDataIndex(row);
971
+ const currentRow = this._rows.value[rowIdx];
972
+ invariant(currentRow, "Invalid row index", {
973
+ F: __dxlog_file,
974
+ L: 525,
975
+ S: this,
976
+ A: [
977
+ "currentRow",
978
+ "'Invalid row index'"
979
+ ]
980
+ });
981
+ const snapshot = getSnapshot(currentRow);
982
+ setValue(snapshot, field.path, transformedValue);
983
+ const schema = getSchema(currentRow);
984
+ invariant(schema, void 0, {
985
+ F: __dxlog_file,
986
+ L: 531,
987
+ S: this,
988
+ A: [
989
+ "schema",
990
+ ""
991
+ ]
992
+ });
993
+ const validationResult = validateSchema(schema, snapshot);
994
+ if (validationResult && validationResult.length > 0) {
995
+ const error = validationResult[0];
996
+ invariant(error.path === field.path, void 0, {
997
+ F: __dxlog_file,
998
+ L: 536,
999
+ S: this,
1000
+ A: [
1001
+ "error.path === field.path",
1002
+ ""
1003
+ ]
1004
+ });
1005
+ return {
1006
+ valid: false,
1007
+ error: error.message
1008
+ };
1009
+ }
1010
+ return {
1011
+ valid: true
1012
+ };
1013
+ }
1014
+ };
1015
+ setCellData = (cell, value) => {
1016
+ const { col, row, plane } = cell;
1017
+ const fields = this._projection?.fields ?? [];
1018
+ if (col < 0 || col >= fields.length) {
1019
+ return;
1020
+ }
1021
+ const field = fields[col];
1022
+ const { props } = this._projection.getFieldProjection(field.id);
1023
+ const transformedValue = editorTextToCellValue(props, value);
1024
+ if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
1025
+ return;
1026
+ }
1027
+ if (plane === "frozenRowsEnd") {
1028
+ if (row >= 0 && row < this._draftRows.value.length) {
1029
+ setValue(this._draftRows.value[row].data, field.path, transformedValue);
1030
+ this.validateDraftRow(row);
1031
+ }
1032
+ } else {
1033
+ const rowIdx = this._sorting.getDataIndex(row);
1034
+ setValue(this._rows.value[rowIdx], field.path, transformedValue);
1035
+ }
1036
+ };
1030
1037
  /**
1031
1038
  * Updates a cell's value using a transform function.
1032
1039
  * @param {DxGridPlanePosition} position - The position of the cell to update.
@@ -1141,102 +1148,83 @@ var editorTextToCellValue = (props, value) => {
1141
1148
 
1142
1149
  // src/model/modal-controller.ts
1143
1150
  import { signal as signal4 } from "@preact/signals-core";
1144
- import { log } from "@dxos/log";
1145
- var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
1146
1151
  var ModalController = class {
1147
- constructor() {
1148
- this._state = signal4({
1149
- type: "closed"
1150
- });
1151
- this._triggerRef = {
1152
- current: null
1153
- };
1154
- this.setTrigger = (trigger) => {
1155
- this._triggerRef.current = trigger;
1156
- };
1157
- this.showRowMenu = (rowIndex) => {
1158
- this._state.value = {
1159
- type: "row",
1160
- rowIndex
1161
- };
1162
- };
1163
- this.showColumnMenu = (fieldId) => {
1164
- this._state.value = {
1165
- type: "column",
1166
- fieldId
1167
- };
1168
- };
1169
- this.showColumnCreator = () => {
1170
- this._state.value = {
1171
- type: "columnSettings",
1172
- mode: {
1173
- type: "create"
1174
- }
1175
- };
1152
+ _state = signal4({
1153
+ type: "closed"
1154
+ });
1155
+ _triggerRef = {
1156
+ current: null
1157
+ };
1158
+ get state() {
1159
+ return this._state;
1160
+ }
1161
+ get trigger() {
1162
+ return this._triggerRef;
1163
+ }
1164
+ setTrigger = (trigger) => {
1165
+ this._triggerRef.current = trigger;
1166
+ };
1167
+ showRowMenu = (rowIndex) => {
1168
+ this._state.value = {
1169
+ type: "row",
1170
+ rowIndex
1176
1171
  };
1177
- this.showReferencePanel = (targetId, schemaId) => {
1178
- this._state.value = {
1179
- type: "refPanel",
1180
- targetId,
1181
- typename: schemaId
1182
- };
1172
+ };
1173
+ showColumnMenu = (fieldId) => {
1174
+ this._state.value = {
1175
+ type: "column",
1176
+ fieldId
1183
1177
  };
1184
- this.openColumnSettings = () => {
1185
- if (this._state.value.type === "column") {
1186
- const fieldId = this._state.value.fieldId;
1187
- requestAnimationFrame(() => {
1188
- this._state.value = {
1189
- type: "columnSettings",
1190
- mode: {
1191
- type: "edit",
1192
- fieldId
1193
- }
1194
- };
1195
- });
1178
+ };
1179
+ showColumnCreator = () => {
1180
+ this._state.value = {
1181
+ type: "columnSettings",
1182
+ mode: {
1183
+ type: "create"
1196
1184
  }
1197
1185
  };
1198
- this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
1199
- if (anchorCell) {
1200
- this._triggerRef.current = anchorCell;
1186
+ };
1187
+ showReferencePanel = (targetId, schemaId) => {
1188
+ this._state.value = {
1189
+ type: "refPanel",
1190
+ targetId,
1191
+ typename: schemaId
1192
+ };
1193
+ };
1194
+ openColumnSettings = () => {
1195
+ if (this._state.value.type === "column") {
1196
+ const fieldId = this._state.value.fieldId;
1197
+ requestAnimationFrame(() => {
1201
1198
  this._state.value = {
1202
- type: "createRefPanel",
1203
- typename,
1204
- initialValues,
1205
- onCreate
1199
+ type: "columnSettings",
1200
+ mode: {
1201
+ type: "edit",
1202
+ fieldId
1203
+ }
1206
1204
  };
1207
- } else {
1208
- log.warn("anchor cell not found while creating new ref", void 0, {
1209
- F: __dxlog_file2,
1210
- L: 86,
1211
- S: this,
1212
- C: (f, a) => f(...a)
1213
- });
1214
- }
1215
- };
1216
- this.close = () => {
1217
- this._state.value = {
1218
- type: "closed"
1219
- };
1205
+ });
1206
+ }
1207
+ };
1208
+ close = () => {
1209
+ this._state.value = {
1210
+ type: "closed"
1220
1211
  };
1221
- }
1222
- get state() {
1223
- return this._state;
1224
- }
1225
- get trigger() {
1226
- return this._triggerRef;
1227
- }
1212
+ };
1228
1213
  };
1229
1214
 
1230
1215
  // src/model/table-presentation.ts
1231
1216
  import { signal as signal5 } from "@preact/signals-core";
1232
- import { isNotNullable } from "effect/Predicate";
1233
- import { Obj as Obj4 } from "@dxos/echo";
1234
- import { FormatEnum as FormatEnum3, getValue as getValue3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1217
+ import * as Predicate from "effect/Predicate";
1218
+ import { Obj as Obj3 } from "@dxos/echo";
1219
+ import { FormatEnum as FormatEnum3, TypeEnum as TypeEnum2, getValue as getValue3 } from "@dxos/echo/internal";
1235
1220
  import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
1236
1221
  import { toPlaneCellIndex } from "@dxos/react-ui-grid";
1237
1222
  import { mx } from "@dxos/react-ui-theme";
1238
1223
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
1239
1224
  var TablePresentation = class {
1225
+ model;
1226
+ _visibleRange;
1227
+ fieldProjectionCache = /* @__PURE__ */ new Map();
1240
1228
  constructor(model, _visibleRange = signal5({
1241
1229
  start: {
1242
1230
  row: 0,
@@ -1249,7 +1237,6 @@ var TablePresentation = class {
1249
1237
  })) {
1250
1238
  this.model = model;
1251
1239
  this._visibleRange = _visibleRange;
1252
- this.fieldProjectionCache = /* @__PURE__ */ new Map();
1253
1240
  }
1254
1241
  getCells(range, plane) {
1255
1242
  this.fieldProjectionCache.clear();
@@ -1277,6 +1264,9 @@ var TablePresentation = class {
1277
1264
  case "frozenRowsEnd":
1278
1265
  cells = this.getDraftRowCells(range);
1279
1266
  break;
1267
+ case "fixedEndStart":
1268
+ cells = this.getDraftIconCells(range);
1269
+ break;
1280
1270
  case "fixedEndEnd":
1281
1271
  cells = this.getDraftActionCells(range);
1282
1272
  break;
@@ -1335,10 +1325,7 @@ var TablePresentation = class {
1335
1325
  }
1336
1326
  };
1337
1327
  const classes = [];
1338
- const formatClasses = cellClassesForFieldType({
1339
- type: props.type,
1340
- format: props.format
1341
- });
1328
+ const formatClasses = cellClassesForFieldType(props);
1342
1329
  if (formatClasses) {
1343
1330
  classes.push(formatClasses);
1344
1331
  }
@@ -1346,9 +1333,7 @@ var TablePresentation = class {
1346
1333
  if (rowSelectionClasses) {
1347
1334
  classes.push(rowSelectionClasses);
1348
1335
  }
1349
- if (classes.length > 0) {
1350
- cell.className = mx(classes.flat());
1351
- }
1336
+ cell.className = mx(classes);
1352
1337
  if (props.type === TypeEnum2.Array) {
1353
1338
  const targetArray = getValue3(obj, field.path);
1354
1339
  if (targetArray && Array.isArray(targetArray)) {
@@ -1370,7 +1355,7 @@ var TablePresentation = class {
1370
1355
  }
1371
1356
  return "Object";
1372
1357
  };
1373
- const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
1358
+ const tags = targetArray.map(getLabel).filter(Predicate.isNotNullable).map((title) => {
1374
1359
  return `<span class="dx-tag" data-hue="neutral">${title}</span>`;
1375
1360
  }).join("");
1376
1361
  cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
@@ -1379,8 +1364,8 @@ var TablePresentation = class {
1379
1364
  if (props.format === FormatEnum3.Ref && props.referenceSchema) {
1380
1365
  const targetObj = getValue3(obj, field.path)?.target;
1381
1366
  if (targetObj) {
1382
- const dxn = Obj4.getDXN(targetObj)?.toString();
1383
- cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button is-6 pli-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
1367
+ const dxn = Obj3.getDXN(targetObj)?.toString();
1368
+ cell.accessoryHtml = `<div role="none" class="absolute inline-end-0 inset-block-0 p-[--dx-grid-cell-content-padding-block]"><dx-anchor refId=${dxn} class="dx-button is-6 aspect-square min-bs-0" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-anchor></div>`;
1384
1369
  }
1385
1370
  }
1386
1371
  if (props.format === FormatEnum3.Boolean) {
@@ -1442,24 +1427,37 @@ var TablePresentation = class {
1442
1427
  const cells = {};
1443
1428
  const fields = this.model.projection?.fields ?? [];
1444
1429
  const draftRows = this.model.draftRows.value;
1445
- for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1446
- const draftRow = draftRows[row];
1430
+ if (draftRows.length === 0) {
1447
1431
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1448
- const field = fields[col];
1449
- if (!field) {
1450
- continue;
1451
- }
1452
- this.createDataCell(cells, draftRow.data, field, col, row);
1453
- if (this.model.hasDraftRowValidationError(row, field.path)) {
1432
+ cells[toPlaneCellIndex({
1433
+ col,
1434
+ row: 0
1435
+ })] = {
1436
+ value: "",
1437
+ readonly: true,
1438
+ className: "dx-grid__row--cta__cell"
1439
+ };
1440
+ }
1441
+ } else {
1442
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1443
+ const draftRow = draftRows[row];
1444
+ for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1454
1445
  const cellIndex = toPlaneCellIndex({
1455
1446
  col,
1456
1447
  row
1457
1448
  });
1458
- const cellValue = cells[cellIndex];
1459
- if (cellValue) {
1460
- const existingClasses = cellValue.className || "";
1461
- const draftClasses = "dx-grid__cell--flagged";
1462
- cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
1449
+ const field = fields[col];
1450
+ if (!field) {
1451
+ continue;
1452
+ }
1453
+ this.createDataCell(cells, draftRow.data, field, col, row);
1454
+ if (this.model.hasDraftRowValidationError(row, field.path)) {
1455
+ const cellValue = cells[cellIndex];
1456
+ if (cellValue) {
1457
+ const existingClasses = cellValue.className || "";
1458
+ const draftClasses = "dx-grid__cell--flagged";
1459
+ cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
1460
+ }
1463
1461
  }
1464
1462
  }
1465
1463
  }
@@ -1478,10 +1476,10 @@ var TablePresentation = class {
1478
1476
  row: 0
1479
1477
  })] = {
1480
1478
  // TODO(burdon): Use same logic as form for fallback title.
1481
- value: props.title ?? field.path,
1482
- readonly: true,
1479
+ value: "",
1483
1480
  resizeHandle: "col",
1484
1481
  accessoryHtml: `
1482
+ <span class="grow min-is-0 truncate">${props.title ?? field.path}</span>
1485
1483
  ${direction !== void 0 ? tableButtons.sort.render({
1486
1484
  fieldId: field.id,
1487
1485
  direction
@@ -1490,7 +1488,7 @@ var TablePresentation = class {
1490
1488
  fieldId: field.id
1491
1489
  })}
1492
1490
  `,
1493
- className: "!bg-toolbarSurface"
1491
+ className: "!bg-toolbarSurface !text-description [&>div]:flex [&>div]:items-stretch"
1494
1492
  };
1495
1493
  }
1496
1494
  return cells;
@@ -1581,19 +1579,46 @@ var TablePresentation = class {
1581
1579
  getDraftActionCells(range) {
1582
1580
  const cells = {};
1583
1581
  const draftRows = this.model.draftRows.value;
1584
- for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1585
- const draftRow = draftRows[row];
1586
- const disabled = !draftRow.valid;
1582
+ if (draftRows.length === 0) {
1583
+ cells[toPlaneCellIndex({
1584
+ col: 0,
1585
+ row: 0
1586
+ })] = {
1587
+ value: "",
1588
+ className: "dx-grid__row--cta__cell",
1589
+ readonly: true
1590
+ };
1591
+ } else {
1592
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1593
+ const draftRow = draftRows[row];
1594
+ const disabled = !draftRow.valid;
1595
+ cells[toPlaneCellIndex({
1596
+ col: 0,
1597
+ row
1598
+ })] = {
1599
+ value: "",
1600
+ readonly: true,
1601
+ accessoryHtml: tableButtons.saveDraftRow.render({
1602
+ rowIndex: row,
1603
+ disabled
1604
+ })
1605
+ };
1606
+ }
1607
+ }
1608
+ return cells;
1609
+ }
1610
+ getDraftIconCells(range) {
1611
+ const cells = {};
1612
+ const draftRows = this.model.draftRows.value;
1613
+ for (let row = range.start.row; row <= range.end.row; row++) {
1587
1614
  cells[toPlaneCellIndex({
1588
1615
  col: 0,
1589
1616
  row
1590
1617
  })] = {
1591
1618
  value: "",
1592
1619
  readonly: true,
1593
- accessoryHtml: tableButtons.saveDraftRow.render({
1594
- rowIndex: row,
1595
- disabled
1596
- })
1620
+ accessoryHtml: '<dx-icon icon="ph--plus--regular" class="contents"></dx-icon>',
1621
+ className: mx("[&>div]:grid [&>div]:place-content-center", draftRows.length < 1 && "dx-grid__row--cta__cell")
1597
1622
  };
1598
1623
  }
1599
1624
  return cells;
@@ -1626,13 +1651,13 @@ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
1626
1651
  import { effect as effect3 } from "@preact/signals-core";
1627
1652
  import orderBy2 from "lodash.orderby";
1628
1653
  import { useEffect, useMemo, useState } from "react";
1629
- import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
1654
+ import { Obj as Obj4 } from "@dxos/echo";
1630
1655
  import { useSelected, useSelectionActions } from "@dxos/react-ui-attention";
1631
1656
  import { isNonNullable } from "@dxos/util";
1632
1657
  var useTableModel = ({ view, schema, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
1633
1658
  var _effect = _useSignals();
1634
1659
  try {
1635
- const selected = useSelected(view && fullyQualifiedId2(view), "multi");
1660
+ const selected = useSelected(view && Obj4.getDXN(view).toString(), "multi");
1636
1661
  const initialSelection = useMemo(() => selected, [
1637
1662
  view
1638
1663
  ]);
@@ -1717,12 +1742,12 @@ var useAddRow = ({ space, schema }) => {
1717
1742
  if (space && schema) {
1718
1743
  try {
1719
1744
  space.db.add(Obj5.make(schema, data ?? {}));
1720
- return true;
1745
+ return "final";
1721
1746
  } catch (error) {
1722
- return false;
1747
+ return "draft";
1723
1748
  }
1724
1749
  }
1725
- return false;
1750
+ return "final";
1726
1751
  }, [
1727
1752
  space,
1728
1753
  schema
@@ -1733,7 +1758,6 @@ export {
1733
1758
  getBaseSchema,
1734
1759
  makeDynamicTable,
1735
1760
  touch,
1736
- createTable,
1737
1761
  BUTTON_IDENTIFIERS,
1738
1762
  tableButtons,
1739
1763
  CONTROL_IDENTIFIERS,
@@ -1748,4 +1772,4 @@ export {
1748
1772
  useTableModel,
1749
1773
  useAddRow
1750
1774
  };
1751
- //# sourceMappingURL=chunk-5XLSHLOG.mjs.map
1775
+ //# sourceMappingURL=chunk-GS2UNGJK.mjs.map