@dxos/react-ui-table 0.8.4-main.67995b8 → 0.8.4-main.ae835ea

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 (130) hide show
  1. package/dist/lib/browser/chunk-4K7JPALT.mjs +66 -0
  2. package/dist/lib/browser/chunk-4K7JPALT.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-G7MGPBSR.mjs} +491 -466
  4. package/dist/lib/browser/chunk-G7MGPBSR.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +584 -673
  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 +13 -8
  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-Y66YLSTC.mjs → chunk-LD5JEBA6.mjs} +491 -466
  12. package/dist/lib/node-esm/chunk-LD5JEBA6.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs +67 -0
  14. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +584 -673
  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 +13 -8
  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 +108 -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.map +1 -1
  47. package/dist/types/src/components/testing.d.ts +3 -3
  48. package/dist/types/src/components/testing.d.ts.map +1 -1
  49. package/dist/types/src/hooks/useAddRow.d.ts +3 -2
  50. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  51. package/dist/types/src/hooks/useTableModel.d.ts +2 -2
  52. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  53. package/dist/types/src/model/modal-controller.d.ts +0 -7
  54. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  55. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  56. package/dist/types/src/model/table-model.d.ts +9 -7
  57. package/dist/types/src/model/table-model.d.ts.map +1 -1
  58. package/dist/types/src/model/table-presentation.d.ts +2 -1
  59. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  60. package/dist/types/src/model/table-sorting.d.ts +2 -3
  61. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  62. package/dist/types/src/testing/useTestTableModel.d.ts +3 -22
  63. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  64. package/dist/types/src/translations.d.ts +2 -2
  65. package/dist/types/src/types/index.d.ts +1 -1
  66. package/dist/types/src/types/index.d.ts.map +1 -1
  67. package/dist/types/src/types/schema.d.ts +25 -5
  68. package/dist/types/src/types/schema.d.ts.map +1 -1
  69. package/dist/types/src/util/dynamic-table.d.ts +4 -5
  70. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  71. package/dist/types/src/util/index.d.ts +0 -1
  72. package/dist/types/src/util/index.d.ts.map +1 -1
  73. package/dist/types/src/util/schema.d.ts +1 -1
  74. package/dist/types/src/util/schema.d.ts.map +1 -1
  75. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  76. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  77. package/dist/types/tsconfig.tsbuildinfo +1 -1
  78. package/package.json +59 -58
  79. package/src/components/Table/ColumnActionsMenu.tsx +1 -1
  80. package/src/components/Table/ColumnSettings.tsx +1 -1
  81. package/src/components/Table/DynamicTable.stories.tsx +15 -11
  82. package/src/components/Table/DynamicTable.tsx +8 -10
  83. package/src/components/Table/Relations.stories.tsx +241 -0
  84. package/src/components/Table/RowActionsMenu.tsx +3 -3
  85. package/src/components/Table/Table.stories.tsx +68 -56
  86. package/src/components/Table/Table.tsx +140 -115
  87. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  88. package/src/components/TableCellEditor/FormCellEditor.tsx +153 -42
  89. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +24 -64
  90. package/src/components/TableCellEditor/TableCellEditor.tsx +74 -224
  91. package/src/components/TableCellEditor/index.ts +1 -0
  92. package/src/components/TableToolbar/TableToolbar.tsx +5 -2
  93. package/src/components/testing.ts +2 -2
  94. package/src/hooks/useAddRow.ts +7 -5
  95. package/src/hooks/useTableModel.ts +2 -2
  96. package/src/model/modal-controller.ts +1 -29
  97. package/src/model/selection-model.ts +3 -2
  98. package/src/model/table-model.test.ts +19 -10
  99. package/src/model/table-model.ts +37 -25
  100. package/src/model/table-presentation.test.ts +23 -21
  101. package/src/model/table-presentation.ts +74 -33
  102. package/src/model/table-sorting.ts +16 -7
  103. package/src/playwright/smoke.spec.ts +129 -37
  104. package/src/testing/useTestTableModel.ts +11 -7
  105. package/src/translations.ts +2 -2
  106. package/src/types/index.ts +1 -1
  107. package/src/types/schema.ts +63 -6
  108. package/src/util/dynamic-table.ts +13 -13
  109. package/src/util/index.ts +0 -1
  110. package/src/util/schema.ts +4 -4
  111. package/src/util/table-buttons.ts +4 -3
  112. package/src/util/table-controls.ts +4 -1
  113. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
  114. package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
  115. package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
  116. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
  117. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
  118. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
  119. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  120. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  121. package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
  122. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
  123. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  124. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  125. package/dist/types/src/util/table.d.ts +0 -11
  126. package/dist/types/src/util/table.d.ts.map +0 -1
  127. package/src/components/Table/CreateRefPanel.tsx +0 -86
  128. package/src/components/Table/relations.stories.tsx +0 -116
  129. package/src/components/TableCellEditor/extension.ts +0 -61
  130. 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-4K7JPALT.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, createView, 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
34
  const view = createView({
35
- typename,
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,60 @@ 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";
280
+ import { getSnapshot, isLiveObject } from "@dxos/live-object";
311
281
  import { fullyQualifiedId } from "@dxos/react-client/echo";
312
282
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
313
283
  import { ProjectionModel as ProjectionModel2, validateSchema } from "@dxos/schema";
314
284
 
285
+ // src/util/tag.ts
286
+ var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
287
+ var extractTagIds = (value) => {
288
+ if (typeof value !== "string") {
289
+ return void 0;
290
+ }
291
+ const ids = [];
292
+ let match;
293
+ while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
294
+ if (match[2]) {
295
+ ids.push(match[2]);
296
+ }
297
+ }
298
+ return ids.length > 0 ? ids : void 0;
299
+ };
300
+
315
301
  // src/model/selection-model.ts
316
302
  import { computed, effect, signal } from "@preact/signals-core";
317
303
  import { Resource } from "@dxos/context";
318
304
  var SelectionModel = class extends Resource {
305
+ _rows;
306
+ _selectionMode;
307
+ _initialSelection;
308
+ _onSelectionChanged;
309
+ _selection;
310
+ _validSelectedIds = computed(() => {
311
+ const rows = this._rows.value;
312
+ if (!rows) {
313
+ return /* @__PURE__ */ new Set();
314
+ }
315
+ const validIds = new Set(rows.map((row) => row.id));
316
+ return new Set([
317
+ ...this._selection.value
318
+ ].filter((id) => validIds.has(id)));
319
+ });
320
+ _hasSelection = computed(() => this._validSelectedIds.value.size > 0);
321
+ _allSelected = computed(() => {
322
+ const rows = this._rows.value;
323
+ if (rows.length === 0) {
324
+ return false;
325
+ }
326
+ return rows.every((row) => this._selection.value.has(row.id));
327
+ });
319
328
  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
- };
329
+ super(), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged;
367
330
  this._selection = signal(new Set(this._initialSelection));
368
331
  }
369
332
  async _open() {
@@ -388,23 +351,67 @@ var SelectionModel = class extends Resource {
388
351
  get selectionMode() {
389
352
  return this._selectionMode;
390
353
  }
354
+ getSelectedRows = () => {
355
+ const selectedIds = this._validSelectedIds.value;
356
+ return this._rows.value.filter((row) => selectedIds.has(row.id));
357
+ };
358
+ isRowIndexSelected = (rowIndex) => {
359
+ const row = this._rows.value[rowIndex];
360
+ return this._selection.value.has(row.id);
361
+ };
362
+ isObjectSelected = (object) => {
363
+ return this._selection.value.has(object.id);
364
+ };
365
+ //
366
+ // Manipulation
367
+ //
368
+ toggleSelectionForRowIndex = (rowIndex) => {
369
+ const row = this._rows.value[rowIndex];
370
+ const newSelection = new Set(this._selection.value);
371
+ if (newSelection.has(row.id)) {
372
+ newSelection.delete(row.id);
373
+ } else {
374
+ if (this._selectionMode === "single") {
375
+ newSelection.clear();
376
+ }
377
+ newSelection.add(row.id);
378
+ }
379
+ this._selection.value = newSelection;
380
+ };
381
+ setSelection = (mode) => {
382
+ switch (mode) {
383
+ case "all": {
384
+ this._selection.value = new Set(this._rows.value.map((row) => row.id));
385
+ break;
386
+ }
387
+ case "none": {
388
+ this._selection.value = /* @__PURE__ */ new Set();
389
+ break;
390
+ }
391
+ }
392
+ };
391
393
  };
392
394
 
393
395
  // src/model/table-sorting.ts
394
396
  import { computed as computed2, signal as signal2 } from "@preact/signals-core";
395
397
  import orderBy from "lodash.orderby";
396
- import { getValue, FormatEnum, TypeEnum } from "@dxos/echo-schema";
398
+ import { FormatEnum, TypeEnum, getValue } from "@dxos/echo/internal";
397
399
  import { formatForDisplay } from "@dxos/react-ui-form";
398
400
  var TableSorting = class {
401
+ _view;
402
+ _projection;
403
+ _displayToDataIndex = /* @__PURE__ */ new Map();
404
+ _rows;
405
+ _localSort = signal2(void 0);
406
+ _isDirty;
407
+ sortedRows;
399
408
  constructor(rows, _view, _projection) {
400
409
  this._view = _view;
401
410
  this._projection = _projection;
402
- this._displayToDataIndex = /* @__PURE__ */ new Map();
403
- this._localSort = signal2(void 0);
404
411
  this._rows = rows;
405
412
  this._isDirty = computed2(() => {
406
413
  const local = this._localSort.value;
407
- const viewSort = this._view.query.sort?.[0];
414
+ const viewSort = this._view.sort?.[0];
408
415
  if (local?.type === "cleared") {
409
416
  return viewSort !== void 0;
410
417
  }
@@ -430,7 +437,7 @@ var TableSorting = class {
430
437
  if (local?.type === "active") {
431
438
  return local.sort;
432
439
  }
433
- return this._view.query.sort?.[0];
440
+ return this._view.sort?.[0];
434
441
  }
435
442
  /**
436
443
  * @reactive
@@ -474,11 +481,11 @@ var TableSorting = class {
474
481
  save() {
475
482
  if (this._localSort.value !== void 0) {
476
483
  if (this._localSort.value.type === "active") {
477
- this._view.query.sort = [
484
+ this._view.sort = [
478
485
  this._localSort.value.sort
479
486
  ];
480
487
  } else {
481
- this._view.query.sort = [];
488
+ this._view.sort = [];
482
489
  }
483
490
  this._localSort.value = void 0;
484
491
  }
@@ -555,22 +562,6 @@ var TableSorting = class {
555
562
  }
556
563
  };
557
564
 
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
565
  // src/model/table-model.ts
575
566
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
576
567
  var defaultFeatures = {
@@ -582,231 +573,48 @@ var defaultFeatures = {
582
573
  schemaEditable: false
583
574
  };
584
575
  var TableModel = class extends Resource2 {
576
+ _view;
577
+ _projection;
578
+ _table;
579
+ _visibleRange = signal3({
580
+ start: {
581
+ row: 0,
582
+ col: 0
583
+ },
584
+ end: {
585
+ row: 0,
586
+ col: 0
587
+ }
588
+ });
589
+ _onInsertRow;
590
+ _onDeleteRows;
591
+ _onDeleteColumn;
592
+ _onCellUpdate;
593
+ _onRowOrderChange;
594
+ _onRowAction;
595
+ _rowActions;
596
+ _features;
597
+ _rows = signal3([]);
598
+ _draftRows = signal3([]);
599
+ _sorting;
600
+ _pinnedRows;
601
+ _selection;
602
+ _columnMeta;
585
603
  constructor({ view, schema, projection, features = {}, sorting = [], initialSelection = [], pinnedRows = {
586
604
  top: [],
587
605
  bottom: []
588
606
  }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
589
607
  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
608
  this._view = view;
802
609
  this._projection = projection ?? new ProjectionModel2(schema, view.projection);
610
+ this._projection.normalizeView();
803
611
  this._features = {
804
612
  ...defaultFeatures,
805
613
  ...features
806
614
  };
807
615
  invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
808
616
  F: __dxlog_file,
809
- L: 139,
617
+ L: 149,
810
618
  S: this,
811
619
  A: [
812
620
  "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
@@ -837,7 +645,7 @@ var TableModel = class extends Resource2 {
837
645
  get table() {
838
646
  invariant(this._table, "Model not initialized", {
839
647
  F: __dxlog_file,
840
- L: 177,
648
+ L: 187,
841
649
  S: this,
842
650
  A: [
843
651
  "this._table",
@@ -876,7 +684,7 @@ var TableModel = class extends Resource2 {
876
684
  get columnMeta() {
877
685
  invariant(this._columnMeta, void 0, {
878
686
  F: __dxlog_file,
879
- L: 216,
687
+ L: 226,
880
688
  S: this,
881
689
  A: [
882
690
  "this._columnMeta",
@@ -900,12 +708,12 @@ var TableModel = class extends Resource2 {
900
708
  //
901
709
  async _open() {
902
710
  const presentation = this._view.presentation.target ?? await this._view.presentation.load();
903
- invariant(Obj3.instanceOf(TableView, presentation), void 0, {
711
+ invariant(Obj2.instanceOf(schema_exports.Table, presentation), void 0, {
904
712
  F: __dxlog_file,
905
- L: 239,
713
+ L: 249,
906
714
  S: this,
907
715
  A: [
908
- "Obj.instanceOf(TableView, presentation)",
716
+ "Obj.instanceOf(Table.Table, presentation)",
909
717
  ""
910
718
  ]
911
719
  });
@@ -934,7 +742,7 @@ var TableModel = class extends Resource2 {
934
742
  },
935
743
  frozenColsEnd: {
936
744
  0: {
937
- size: 40,
745
+ size: 32,
938
746
  resizeable: false
939
747
  }
940
748
  }
@@ -970,6 +778,17 @@ var TableModel = class extends Resource2 {
970
778
  });
971
779
  this._ctx.onDispose(draftRowsWatcher);
972
780
  }
781
+ //
782
+ // Data
783
+ //
784
+ setRows = (obj) => {
785
+ this._rows.value = obj;
786
+ };
787
+ getRowCount = () => this._rows.value.length;
788
+ /**
789
+ * @reactive
790
+ */
791
+ getDraftRowCount = () => this._draftRows.value.length;
973
792
  // TODO(ZaymonFC): Return .value instead of exposing the signal.
974
793
  get draftRows() {
975
794
  return this._draftRows;
@@ -988,6 +807,14 @@ var TableModel = class extends Resource2 {
988
807
  const validationErrors = draftRow.validationErrors || [];
989
808
  return validationErrors.some((error) => error.path === fieldPath);
990
809
  }
810
+ getColumnCount = () => this._projection?.fields.length ?? 0;
811
+ insertRow = () => {
812
+ const result = this._onInsertRow?.();
813
+ if (result === "draft" && this._draftRows.value.length === 0) {
814
+ this.createDraftRow();
815
+ }
816
+ return result ?? "final";
817
+ };
991
818
  createDraftRow() {
992
819
  if (!this._projection) {
993
820
  return;
@@ -1024,9 +851,190 @@ var TableModel = class extends Resource2 {
1024
851
  this._draftRows.value = newDraftRows;
1025
852
  }
1026
853
  validateDraftRowData(data) {
1027
- const schema = toEffectSchema2(this._projection.baseSchema);
854
+ const schema = toEffectSchema(this._projection.baseSchema);
1028
855
  return validateSchema(schema, data) || [];
1029
856
  }
857
+ commitDraftRow = (draftRowIndex) => {
858
+ if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
859
+ return false;
860
+ }
861
+ const draftRow = this._draftRows.value[draftRowIndex];
862
+ if (!draftRow.valid) {
863
+ return false;
864
+ }
865
+ const insertRowResult = this._onInsertRow?.(draftRow.data);
866
+ if (insertRowResult === "final") {
867
+ const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
868
+ this._draftRows.value = newDraftRows;
869
+ }
870
+ return insertRowResult === "final";
871
+ };
872
+ deleteRow = (rowIndex) => {
873
+ const row = this._sorting.getDataIndex(rowIndex);
874
+ const obj = this._rows.value[row];
875
+ const objectsToDelete = [];
876
+ if (this.features.selection.enabled && this._selection.hasSelection.value) {
877
+ const selectedRows = this._selection.getSelectedRows();
878
+ objectsToDelete.push(...selectedRows);
879
+ } else {
880
+ objectsToDelete.push(obj);
881
+ }
882
+ this._onDeleteRows?.(row, objectsToDelete);
883
+ };
884
+ handleRowAction = (actionId, rowIndex) => {
885
+ if (!this._onRowAction) {
886
+ return;
887
+ }
888
+ const row = this._sorting.getDataIndex(rowIndex);
889
+ const data = this._rows.value[row];
890
+ if (data) {
891
+ this._onRowAction(actionId, data);
892
+ }
893
+ };
894
+ getCellData = (cell) => {
895
+ const { col, row, plane } = cell;
896
+ const fields = this._projection?.fields ?? [];
897
+ if (col < 0 || col >= fields.length) {
898
+ return void 0;
899
+ }
900
+ const field = fields[col];
901
+ let value;
902
+ if (plane === "frozenRowsEnd") {
903
+ if (row >= 0 && row < this._draftRows.value.length) {
904
+ value = getValue2(this._draftRows.value[row].data, field.path);
905
+ } else {
906
+ return void 0;
907
+ }
908
+ } else {
909
+ const dataIndex = this._sorting.getDataIndex(row);
910
+ value = getValue2(this._rows.value[dataIndex], field.path);
911
+ }
912
+ if (value == null) {
913
+ return "";
914
+ }
915
+ const { props } = this._projection.getFieldProjection(field.id);
916
+ switch (props.format) {
917
+ case FormatEnum2.Ref: {
918
+ if (!field.referencePath) {
919
+ return "";
920
+ }
921
+ return getValue2(value.target, field.referencePath);
922
+ }
923
+ default: {
924
+ return formatForEditing({
925
+ type: props.type,
926
+ format: props.format,
927
+ value
928
+ });
929
+ }
930
+ }
931
+ };
932
+ validateCellData = async ({ col, row, plane }, value) => {
933
+ const fields = this._projection?.fields ?? [];
934
+ if (col < 0 || col >= fields.length) {
935
+ return {
936
+ valid: false,
937
+ error: "Invalid column index"
938
+ };
939
+ }
940
+ const field = fields[col];
941
+ const { props } = this._projection.getFieldProjection(field.id);
942
+ const transformedValue = editorTextToCellValue(props, value);
943
+ const isDraftRow = plane === "frozenRowsEnd";
944
+ if (isDraftRow) {
945
+ const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
946
+ if (isInvalidDraftRowIndex) {
947
+ return {
948
+ valid: false,
949
+ error: "Invalid draft row index"
950
+ };
951
+ }
952
+ const draftRow = this._draftRows.value[row];
953
+ const snapshot = {
954
+ ...draftRow.data
955
+ };
956
+ setValue(snapshot, field.path, transformedValue);
957
+ const validationErrors = this.validateDraftRowData(snapshot);
958
+ if (validationErrors.length > 0) {
959
+ const error = validationErrors.find((err) => err.path === field.path);
960
+ if (error) {
961
+ return {
962
+ valid: false,
963
+ error: error.message
964
+ };
965
+ }
966
+ }
967
+ return {
968
+ valid: true
969
+ };
970
+ } else {
971
+ const rowIdx = this._sorting.getDataIndex(row);
972
+ const currentRow = this._rows.value[rowIdx];
973
+ invariant(currentRow, "Invalid row index", {
974
+ F: __dxlog_file,
975
+ L: 522,
976
+ S: this,
977
+ A: [
978
+ "currentRow",
979
+ "'Invalid row index'"
980
+ ]
981
+ });
982
+ const snapshot = getSnapshot(currentRow);
983
+ setValue(snapshot, field.path, transformedValue);
984
+ const schema = getSchema(currentRow);
985
+ invariant(schema, void 0, {
986
+ F: __dxlog_file,
987
+ L: 528,
988
+ S: this,
989
+ A: [
990
+ "schema",
991
+ ""
992
+ ]
993
+ });
994
+ const validationResult = validateSchema(schema, snapshot);
995
+ if (validationResult && validationResult.length > 0) {
996
+ const error = validationResult[0];
997
+ invariant(error.path === field.path, void 0, {
998
+ F: __dxlog_file,
999
+ L: 533,
1000
+ S: this,
1001
+ A: [
1002
+ "error.path === field.path",
1003
+ ""
1004
+ ]
1005
+ });
1006
+ return {
1007
+ valid: false,
1008
+ error: error.message
1009
+ };
1010
+ }
1011
+ return {
1012
+ valid: true
1013
+ };
1014
+ }
1015
+ };
1016
+ setCellData = (cell, value) => {
1017
+ const { col, row, plane } = cell;
1018
+ const fields = this._projection?.fields ?? [];
1019
+ if (col < 0 || col >= fields.length) {
1020
+ return;
1021
+ }
1022
+ const field = fields[col];
1023
+ const { props } = this._projection.getFieldProjection(field.id);
1024
+ const transformedValue = editorTextToCellValue(props, value);
1025
+ if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
1026
+ return;
1027
+ }
1028
+ if (plane === "frozenRowsEnd") {
1029
+ if (row >= 0 && row < this._draftRows.value.length) {
1030
+ setValue(this._draftRows.value[row].data, field.path, transformedValue);
1031
+ this.validateDraftRow(row);
1032
+ }
1033
+ } else {
1034
+ const rowIdx = this._sorting.getDataIndex(row);
1035
+ setValue(this._rows.value[rowIdx], field.path, transformedValue);
1036
+ }
1037
+ };
1030
1038
  /**
1031
1039
  * Updates a cell's value using a transform function.
1032
1040
  * @param {DxGridPlanePosition} position - The position of the cell to update.
@@ -1141,102 +1149,83 @@ var editorTextToCellValue = (props, value) => {
1141
1149
 
1142
1150
  // src/model/modal-controller.ts
1143
1151
  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
1152
  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
- };
1153
+ _state = signal4({
1154
+ type: "closed"
1155
+ });
1156
+ _triggerRef = {
1157
+ current: null
1158
+ };
1159
+ get state() {
1160
+ return this._state;
1161
+ }
1162
+ get trigger() {
1163
+ return this._triggerRef;
1164
+ }
1165
+ setTrigger = (trigger) => {
1166
+ this._triggerRef.current = trigger;
1167
+ };
1168
+ showRowMenu = (rowIndex) => {
1169
+ this._state.value = {
1170
+ type: "row",
1171
+ rowIndex
1176
1172
  };
1177
- this.showReferencePanel = (targetId, schemaId) => {
1178
- this._state.value = {
1179
- type: "refPanel",
1180
- targetId,
1181
- typename: schemaId
1182
- };
1173
+ };
1174
+ showColumnMenu = (fieldId) => {
1175
+ this._state.value = {
1176
+ type: "column",
1177
+ fieldId
1183
1178
  };
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
- });
1179
+ };
1180
+ showColumnCreator = () => {
1181
+ this._state.value = {
1182
+ type: "columnSettings",
1183
+ mode: {
1184
+ type: "create"
1196
1185
  }
1197
1186
  };
1198
- this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
1199
- if (anchorCell) {
1200
- this._triggerRef.current = anchorCell;
1187
+ };
1188
+ showReferencePanel = (targetId, schemaId) => {
1189
+ this._state.value = {
1190
+ type: "refPanel",
1191
+ targetId,
1192
+ typename: schemaId
1193
+ };
1194
+ };
1195
+ openColumnSettings = () => {
1196
+ if (this._state.value.type === "column") {
1197
+ const fieldId = this._state.value.fieldId;
1198
+ requestAnimationFrame(() => {
1201
1199
  this._state.value = {
1202
- type: "createRefPanel",
1203
- typename,
1204
- initialValues,
1205
- onCreate
1200
+ type: "columnSettings",
1201
+ mode: {
1202
+ type: "edit",
1203
+ fieldId
1204
+ }
1206
1205
  };
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
- };
1206
+ });
1207
+ }
1208
+ };
1209
+ close = () => {
1210
+ this._state.value = {
1211
+ type: "closed"
1220
1212
  };
1221
- }
1222
- get state() {
1223
- return this._state;
1224
- }
1225
- get trigger() {
1226
- return this._triggerRef;
1227
- }
1213
+ };
1228
1214
  };
1229
1215
 
1230
1216
  // src/model/table-presentation.ts
1231
1217
  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";
1218
+ import * as Predicate from "effect/Predicate";
1219
+ import { Obj as Obj3 } from "@dxos/echo";
1220
+ import { FormatEnum as FormatEnum3, TypeEnum as TypeEnum2, getValue as getValue3 } from "@dxos/echo/internal";
1235
1221
  import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
1236
1222
  import { toPlaneCellIndex } from "@dxos/react-ui-grid";
1237
1223
  import { mx } from "@dxos/react-ui-theme";
1238
1224
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
1239
1225
  var TablePresentation = class {
1226
+ model;
1227
+ _visibleRange;
1228
+ fieldProjectionCache = /* @__PURE__ */ new Map();
1240
1229
  constructor(model, _visibleRange = signal5({
1241
1230
  start: {
1242
1231
  row: 0,
@@ -1249,7 +1238,6 @@ var TablePresentation = class {
1249
1238
  })) {
1250
1239
  this.model = model;
1251
1240
  this._visibleRange = _visibleRange;
1252
- this.fieldProjectionCache = /* @__PURE__ */ new Map();
1253
1241
  }
1254
1242
  getCells(range, plane) {
1255
1243
  this.fieldProjectionCache.clear();
@@ -1277,6 +1265,9 @@ var TablePresentation = class {
1277
1265
  case "frozenRowsEnd":
1278
1266
  cells = this.getDraftRowCells(range);
1279
1267
  break;
1268
+ case "fixedEndStart":
1269
+ cells = this.getDraftIconCells(range);
1270
+ break;
1280
1271
  case "fixedEndEnd":
1281
1272
  cells = this.getDraftActionCells(range);
1282
1273
  break;
@@ -1335,10 +1326,7 @@ var TablePresentation = class {
1335
1326
  }
1336
1327
  };
1337
1328
  const classes = [];
1338
- const formatClasses = cellClassesForFieldType({
1339
- type: props.type,
1340
- format: props.format
1341
- });
1329
+ const formatClasses = cellClassesForFieldType(props);
1342
1330
  if (formatClasses) {
1343
1331
  classes.push(formatClasses);
1344
1332
  }
@@ -1346,9 +1334,7 @@ var TablePresentation = class {
1346
1334
  if (rowSelectionClasses) {
1347
1335
  classes.push(rowSelectionClasses);
1348
1336
  }
1349
- if (classes.length > 0) {
1350
- cell.className = mx(classes.flat());
1351
- }
1337
+ cell.className = mx(classes);
1352
1338
  if (props.type === TypeEnum2.Array) {
1353
1339
  const targetArray = getValue3(obj, field.path);
1354
1340
  if (targetArray && Array.isArray(targetArray)) {
@@ -1370,7 +1356,7 @@ var TablePresentation = class {
1370
1356
  }
1371
1357
  return "Object";
1372
1358
  };
1373
- const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
1359
+ const tags = targetArray.map(getLabel).filter(Predicate.isNotNullable).map((title) => {
1374
1360
  return `<span class="dx-tag" data-hue="neutral">${title}</span>`;
1375
1361
  }).join("");
1376
1362
  cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
@@ -1379,8 +1365,8 @@ var TablePresentation = class {
1379
1365
  if (props.format === FormatEnum3.Ref && props.referenceSchema) {
1380
1366
  const targetObj = getValue3(obj, field.path)?.target;
1381
1367
  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>`;
1368
+ const dxn = Obj3.getDXN(targetObj)?.toString();
1369
+ 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
1370
  }
1385
1371
  }
1386
1372
  if (props.format === FormatEnum3.Boolean) {
@@ -1442,24 +1428,37 @@ var TablePresentation = class {
1442
1428
  const cells = {};
1443
1429
  const fields = this.model.projection?.fields ?? [];
1444
1430
  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];
1431
+ if (draftRows.length === 0) {
1447
1432
  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)) {
1433
+ cells[toPlaneCellIndex({
1434
+ col,
1435
+ row: 0
1436
+ })] = {
1437
+ value: "",
1438
+ readonly: true,
1439
+ className: "dx-grid__row--cta__cell"
1440
+ };
1441
+ }
1442
+ } else {
1443
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1444
+ const draftRow = draftRows[row];
1445
+ for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1454
1446
  const cellIndex = toPlaneCellIndex({
1455
1447
  col,
1456
1448
  row
1457
1449
  });
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;
1450
+ const field = fields[col];
1451
+ if (!field) {
1452
+ continue;
1453
+ }
1454
+ this.createDataCell(cells, draftRow.data, field, col, row);
1455
+ if (this.model.hasDraftRowValidationError(row, field.path)) {
1456
+ const cellValue = cells[cellIndex];
1457
+ if (cellValue) {
1458
+ const existingClasses = cellValue.className || "";
1459
+ const draftClasses = "dx-grid__cell--flagged";
1460
+ cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
1461
+ }
1463
1462
  }
1464
1463
  }
1465
1464
  }
@@ -1478,10 +1477,10 @@ var TablePresentation = class {
1478
1477
  row: 0
1479
1478
  })] = {
1480
1479
  // TODO(burdon): Use same logic as form for fallback title.
1481
- value: props.title ?? field.path,
1482
- readonly: true,
1480
+ value: "",
1483
1481
  resizeHandle: "col",
1484
1482
  accessoryHtml: `
1483
+ <span class="grow min-is-0 truncate">${props.title ?? field.path}</span>
1485
1484
  ${direction !== void 0 ? tableButtons.sort.render({
1486
1485
  fieldId: field.id,
1487
1486
  direction
@@ -1490,7 +1489,7 @@ var TablePresentation = class {
1490
1489
  fieldId: field.id
1491
1490
  })}
1492
1491
  `,
1493
- className: "!bg-toolbarSurface"
1492
+ className: "!bg-toolbarSurface !text-description [&>div]:flex [&>div]:items-stretch"
1494
1493
  };
1495
1494
  }
1496
1495
  return cells;
@@ -1581,19 +1580,46 @@ var TablePresentation = class {
1581
1580
  getDraftActionCells(range) {
1582
1581
  const cells = {};
1583
1582
  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;
1583
+ if (draftRows.length === 0) {
1584
+ cells[toPlaneCellIndex({
1585
+ col: 0,
1586
+ row: 0
1587
+ })] = {
1588
+ value: "",
1589
+ className: "dx-grid__row--cta__cell",
1590
+ readonly: true
1591
+ };
1592
+ } else {
1593
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1594
+ const draftRow = draftRows[row];
1595
+ const disabled = !draftRow.valid;
1596
+ cells[toPlaneCellIndex({
1597
+ col: 0,
1598
+ row
1599
+ })] = {
1600
+ value: "",
1601
+ readonly: true,
1602
+ accessoryHtml: tableButtons.saveDraftRow.render({
1603
+ rowIndex: row,
1604
+ disabled
1605
+ })
1606
+ };
1607
+ }
1608
+ }
1609
+ return cells;
1610
+ }
1611
+ getDraftIconCells(range) {
1612
+ const cells = {};
1613
+ const draftRows = this.model.draftRows.value;
1614
+ for (let row = range.start.row; row <= range.end.row; row++) {
1587
1615
  cells[toPlaneCellIndex({
1588
1616
  col: 0,
1589
1617
  row
1590
1618
  })] = {
1591
1619
  value: "",
1592
1620
  readonly: true,
1593
- accessoryHtml: tableButtons.saveDraftRow.render({
1594
- rowIndex: row,
1595
- disabled
1596
- })
1621
+ accessoryHtml: '<dx-icon icon="ph--plus--regular" class="contents"></dx-icon>',
1622
+ className: mx("[&>div]:grid [&>div]:place-content-center", draftRows.length < 1 && "dx-grid__row--cta__cell")
1597
1623
  };
1598
1624
  }
1599
1625
  return cells;
@@ -1711,18 +1737,18 @@ var useTableModel = ({ view, schema, projection, rows, rowActions, features, onS
1711
1737
 
1712
1738
  // src/hooks/useAddRow.ts
1713
1739
  import { useCallback } from "react";
1714
- import { Obj as Obj5 } from "@dxos/echo";
1740
+ import { Obj as Obj4 } from "@dxos/echo";
1715
1741
  var useAddRow = ({ space, schema }) => {
1716
1742
  return useCallback((data) => {
1717
1743
  if (space && schema) {
1718
1744
  try {
1719
- space.db.add(Obj5.make(schema, data ?? {}));
1720
- return true;
1745
+ space.db.add(Obj4.make(schema, data ?? {}));
1746
+ return "final";
1721
1747
  } catch (error) {
1722
- return false;
1748
+ return "draft";
1723
1749
  }
1724
1750
  }
1725
- return false;
1751
+ return "final";
1726
1752
  }, [
1727
1753
  space,
1728
1754
  schema
@@ -1733,7 +1759,6 @@ export {
1733
1759
  getBaseSchema,
1734
1760
  makeDynamicTable,
1735
1761
  touch,
1736
- createTable,
1737
1762
  BUTTON_IDENTIFIERS,
1738
1763
  tableButtons,
1739
1764
  CONTROL_IDENTIFIERS,
@@ -1748,4 +1773,4 @@ export {
1748
1773
  useTableModel,
1749
1774
  useAddRow
1750
1775
  };
1751
- //# sourceMappingURL=chunk-5XLSHLOG.mjs.map
1776
+ //# sourceMappingURL=chunk-G7MGPBSR.mjs.map