@dxos/react-ui-table 0.8.4-main.c1de068 → 0.8.4-main.c4373fc

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-OZTXLZGM.mjs} +544 -491
  4. package/dist/lib/browser/chunk-OZTXLZGM.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +590 -675
  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-MK6OVUF6.mjs +67 -0
  12. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-S56Z4V4X.mjs} +544 -491
  14. package/dist/lib/node-esm/chunk-S56Z4V4X.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +590 -675
  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 +55 -50
  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 +248 -0
  84. package/src/components/Table/RowActionsMenu.tsx +3 -3
  85. package/src/components/Table/Table.stories.tsx +66 -54
  86. package/src/components/Table/Table.tsx +147 -117
  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 +2 -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,12 +1,12 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
- TableView
4
- } from "./chunk-NXZ4CJYX.mjs";
3
+ schema_exports
4
+ } from "./chunk-MK6OVUF6.mjs";
5
5
 
6
6
  // src/util/dynamic-table.ts
7
- import { Obj } from "@dxos/echo";
8
- import { getTypename, toJsonSchema } from "@dxos/echo-schema";
9
- import { createView, getSchemaFromPropertyDefinitions, ProjectionModel } from "@dxos/schema";
7
+ import { Filter, Obj, Query } from "@dxos/echo";
8
+ import { getTypename, toJsonSchema } from "@dxos/echo/internal";
9
+ import { ProjectionModel, createView, getSchemaFromPropertyDefinitions } from "@dxos/schema";
10
10
  var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
11
11
  if (typename && properties) {
12
12
  const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
@@ -28,12 +28,12 @@ var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
28
28
  throw new Error("invalid properties");
29
29
  }
30
30
  };
31
- var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
32
- const table = Obj.make(TableView, {
31
+ var makeDynamicTable = ({ jsonSchema, properties }) => {
32
+ const table = Obj.make(schema_exports.Table, {
33
33
  sizes: {}
34
34
  });
35
35
  const view = createView({
36
- typename,
36
+ query: Query.select(Filter.everything()),
37
37
  jsonSchema,
38
38
  presentation: table,
39
39
  ...properties && {
@@ -41,6 +41,7 @@ var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
41
41
  }
42
42
  });
43
43
  const projection = new ProjectionModel(jsonSchema, view.projection);
44
+ projection.normalizeView();
44
45
  if (properties && projection.fields) {
45
46
  setProperties(view, projection, table, properties);
46
47
  }
@@ -68,7 +69,7 @@ var setProperties = (view, projection, table, properties) => {
68
69
  }
69
70
  if (property.sort) {
70
71
  const fieldId = field.id;
71
- view.query.sort = [
72
+ view.sort = [
72
73
  {
73
74
  fieldId,
74
75
  direction: property.sort
@@ -82,40 +83,6 @@ var setProperties = (view, projection, table, properties) => {
82
83
  // src/util/signals.ts
83
84
  var touch = (value) => value;
84
85
 
85
- // src/util/table.ts
86
- import { Match } from "effect";
87
- import { Obj as Obj2 } from "@dxos/echo";
88
- import { toEffectSchema } from "@dxos/echo-schema";
89
- import { createViewFromSpace, getSchemaProperties } from "@dxos/schema";
90
- var createTable = async ({ sizes, ...props }) => {
91
- const table = Obj2.make(TableView, {
92
- sizes: {}
93
- });
94
- const { jsonSchema, view } = await createViewFromSpace({
95
- ...props,
96
- presentation: table
97
- });
98
- const schema = toEffectSchema(jsonSchema);
99
- const shouldIncludeId = props.fields?.find((field) => field === "id") !== void 0;
100
- const properties = getSchemaProperties(schema.ast, {}, shouldIncludeId);
101
- for (const property of properties) {
102
- if (sizes?.[property.name]) {
103
- table.sizes[property.name] = sizes[property.name];
104
- continue;
105
- }
106
- Match.type().pipe(Match.when("boolean", () => {
107
- table.sizes[property.name] = 100;
108
- }), Match.when("number", () => {
109
- table.sizes[property.name] = 100;
110
- }), Match.orElse(() => {
111
- }))(property.type);
112
- }
113
- return {
114
- jsonSchema,
115
- view
116
- };
117
- };
118
-
119
86
  // src/util/table-buttons.ts
120
87
  var BUTTON_IDENTIFIERS = {
121
88
  columnSettings: "data-table-column-settings-button",
@@ -125,10 +92,9 @@ var BUTTON_IDENTIFIERS = {
125
92
  saveDraftRow: "data-table-save-draft-row-button",
126
93
  sort: "data-table-sort-button"
127
94
  };
128
- var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
95
+ var createButton = ({ attr, data, disabled = false, icon, testId, type: _type = "primary" }) => {
129
96
  const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
130
- const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
131
- 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>`;
97
+ 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>`;
132
98
  };
133
99
  var addColumnButton = {
134
100
  attr: BUTTON_IDENTIFIERS.newColumn,
@@ -154,7 +120,8 @@ var columnSettingsButton = {
154
120
  attr: BUTTON_IDENTIFIERS.columnSettings,
155
121
  icon: columnSettingsButton.icon,
156
122
  data: {
157
- "data-field-id": fieldId
123
+ "data-field-id": fieldId,
124
+ "data-variant": "ghost"
158
125
  },
159
126
  testId: "table-column-settings-button"
160
127
  });
@@ -214,7 +181,8 @@ var saveDraftRowButton = {
214
181
  icon: saveDraftRowButton.icon,
215
182
  disabled,
216
183
  data: {
217
- "data-row-index": rowIndex.toString()
184
+ "data-row-index": rowIndex.toString(),
185
+ "data-variant": "primary"
218
186
  },
219
187
  testId: "table-save-draft-row-button"
220
188
  });
@@ -233,6 +201,7 @@ var tableButtons = {
233
201
  };
234
202
 
235
203
  // src/util/table-controls.ts
204
+ import { accessoryHandlesPointerdownAttrs } from "@dxos/lit-grid";
236
205
  var CONTROL_IDENTIFIERS = {
237
206
  checkbox: "data-table-checkbox",
238
207
  switch: "data-table-switch"
@@ -245,7 +214,7 @@ var renderAttributes = (data) => {
245
214
  return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
246
215
  };
247
216
  var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
248
- return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
217
+ return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}" data-dx-grid-action="accessory"/>`;
249
218
  };
250
219
  var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
251
220
  const attrs = {
@@ -261,7 +230,8 @@ var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) =>
261
230
  const attrs = {
262
231
  [CONTROL_IDENTIFIERS.switch]: "",
263
232
  "data-row-index": rowIndex.toString(),
264
- "data-col-index": colIndex.toString()
233
+ "data-col-index": colIndex.toString(),
234
+ ...accessoryHandlesPointerdownAttrs
265
235
  };
266
236
  return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
267
237
  };
@@ -287,14 +257,14 @@ var tableControls = {
287
257
  };
288
258
 
289
259
  // src/util/schema.ts
290
- import { Schema } from "effect";
291
- import { isTypeLiteral, TypeLiteral } from "effect/SchemaAST";
260
+ import * as Schema from "effect/Schema";
261
+ import * as SchemaAST from "effect/SchemaAST";
292
262
  var narrowSchema = (schema, paths) => {
293
263
  const ast = schema?.ast;
294
- if (isTypeLiteral(ast)) {
264
+ if (SchemaAST.isTypeLiteral(ast)) {
295
265
  const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
296
266
  if (propertySignatures.length > 0) {
297
- const narrowType = new TypeLiteral(propertySignatures, []);
267
+ const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
298
268
  return Schema.make(narrowType);
299
269
  }
300
270
  }
@@ -304,21 +274,75 @@ var narrowSchema = (schema, paths) => {
304
274
  // src/model/table-model.ts
305
275
  import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
306
276
  import { Resource as Resource2 } from "@dxos/context";
307
- import { Obj as Obj3, Ref } from "@dxos/echo";
308
- import { FormatEnum as FormatEnum2, getValue as getValue2, setValue, getSnapshot, getSchema, toEffectSchema as toEffectSchema2 } from "@dxos/echo-schema";
277
+ import { Obj as Obj2, Ref } from "@dxos/echo";
278
+ import { FormatEnum as FormatEnum2, getSchema, getValue as getValue2, setValue, toEffectSchema } from "@dxos/echo/internal";
309
279
  import { invariant } from "@dxos/invariant";
310
280
  import { ObjectId } from "@dxos/keys";
311
- import { isLiveObject } from "@dxos/live-object";
281
+ import { getSnapshot, isLiveObject } from "@dxos/live-object";
312
282
  import { fullyQualifiedId } from "@dxos/react-client/echo";
313
283
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
314
284
  import { ProjectionModel as ProjectionModel2, validateSchema } from "@dxos/schema";
315
285
 
286
+ // src/util/tag.ts
287
+ var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
288
+ var extractTagIds = (value) => {
289
+ if (typeof value !== "string") {
290
+ return void 0;
291
+ }
292
+ const ids = [];
293
+ let match;
294
+ while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
295
+ if (match[2]) {
296
+ ids.push(match[2]);
297
+ }
298
+ }
299
+ return ids.length > 0 ? ids : void 0;
300
+ };
301
+
316
302
  // src/model/selection-model.ts
317
303
  import { computed, effect, signal } from "@preact/signals-core";
318
304
  import { Resource } from "@dxos/context";
305
+ function _define_property(obj, key, value) {
306
+ if (key in obj) {
307
+ Object.defineProperty(obj, key, {
308
+ value,
309
+ enumerable: true,
310
+ configurable: true,
311
+ writable: true
312
+ });
313
+ } else {
314
+ obj[key] = value;
315
+ }
316
+ return obj;
317
+ }
319
318
  var SelectionModel = class extends Resource {
319
+ async _open() {
320
+ const selectionWatcher = effect(() => {
321
+ touch(this._selection.value);
322
+ this._onSelectionChanged?.();
323
+ });
324
+ this._ctx.onDispose(selectionWatcher);
325
+ }
326
+ //
327
+ // Getters
328
+ //
329
+ get selection() {
330
+ return this._selection;
331
+ }
332
+ get hasSelection() {
333
+ return this._hasSelection;
334
+ }
335
+ get allRowsSeleted() {
336
+ return this._allSelected;
337
+ }
338
+ get selectionMode() {
339
+ return this._selectionMode;
340
+ }
320
341
  constructor(_rows, _selectionMode, _initialSelection, _onSelectionChanged) {
321
- super(), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged, this._validSelectedIds = computed(() => {
342
+ super(), _define_property(this, "_rows", void 0), _define_property(this, "_selectionMode", void 0), _define_property(this, "_initialSelection", void 0), _define_property(this, "_onSelectionChanged", void 0), _define_property(this, "_selection", void 0), _define_property(this, "_validSelectedIds", void 0), _define_property(this, "_hasSelection", void 0), _define_property(this, "_allSelected", void 0), _define_property(this, "getSelectedRows", void 0), _define_property(this, "isRowIndexSelected", void 0), _define_property(this, "isObjectSelected", void 0), //
343
+ // Manipulation
344
+ //
345
+ _define_property(this, "toggleSelectionForRowIndex", void 0), _define_property(this, "setSelection", void 0), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged, this._validSelectedIds = computed(() => {
322
346
  const rows = this._rows.value;
323
347
  if (!rows) {
324
348
  return /* @__PURE__ */ new Set();
@@ -367,58 +391,27 @@ var SelectionModel = class extends Resource {
367
391
  };
368
392
  this._selection = signal(new Set(this._initialSelection));
369
393
  }
370
- async _open() {
371
- const selectionWatcher = effect(() => {
372
- touch(this._selection.value);
373
- this._onSelectionChanged?.();
374
- });
375
- this._ctx.onDispose(selectionWatcher);
376
- }
377
- //
378
- // Getters
379
- //
380
- get selection() {
381
- return this._selection;
382
- }
383
- get hasSelection() {
384
- return this._hasSelection;
385
- }
386
- get allRowsSeleted() {
387
- return this._allSelected;
388
- }
389
- get selectionMode() {
390
- return this._selectionMode;
391
- }
392
394
  };
393
395
 
394
396
  // src/model/table-sorting.ts
395
397
  import { computed as computed2, signal as signal2 } from "@preact/signals-core";
396
398
  import orderBy from "lodash.orderby";
397
- import { getValue, FormatEnum, TypeEnum } from "@dxos/echo-schema";
399
+ import { FormatEnum, TypeEnum, getValue } from "@dxos/echo/internal";
398
400
  import { formatForDisplay } from "@dxos/react-ui-form";
399
- var TableSorting = class {
400
- constructor(rows, _view, _projection) {
401
- this._view = _view;
402
- this._projection = _projection;
403
- this._displayToDataIndex = /* @__PURE__ */ new Map();
404
- this._localSort = signal2(void 0);
405
- this._rows = rows;
406
- this._isDirty = computed2(() => {
407
- const local = this._localSort.value;
408
- const viewSort = this._view.query.sort?.[0];
409
- if (local?.type === "cleared") {
410
- return viewSort !== void 0;
411
- }
412
- if (local?.type === "active") {
413
- if (!viewSort) {
414
- return true;
415
- }
416
- return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
417
- }
418
- return false;
401
+ function _define_property2(obj, key, value) {
402
+ if (key in obj) {
403
+ Object.defineProperty(obj, key, {
404
+ value,
405
+ enumerable: true,
406
+ configurable: true,
407
+ writable: true
419
408
  });
420
- this.sortedRows = this.initialiseSortedRows();
409
+ } else {
410
+ obj[key] = value;
421
411
  }
412
+ return obj;
413
+ }
414
+ var TableSorting = class {
422
415
  /**
423
416
  * @reactive
424
417
  * @returns Local sort if present, falls back to view sort.
@@ -431,7 +424,7 @@ var TableSorting = class {
431
424
  if (local?.type === "active") {
432
425
  return local.sort;
433
426
  }
434
- return this._view.query.sort?.[0];
427
+ return this._view.sort?.[0];
435
428
  }
436
429
  /**
437
430
  * @reactive
@@ -475,11 +468,11 @@ var TableSorting = class {
475
468
  save() {
476
469
  if (this._localSort.value !== void 0) {
477
470
  if (this._localSort.value.type === "active") {
478
- this._view.query.sort = [
471
+ this._view.sort = [
479
472
  this._localSort.value.sort
480
473
  ];
481
474
  } else {
482
- this._view.query.sort = [];
475
+ this._view.sort = [];
483
476
  }
484
477
  this._localSort.value = void 0;
485
478
  }
@@ -554,25 +547,51 @@ var TableSorting = class {
554
547
  value
555
548
  });
556
549
  }
557
- };
558
-
559
- // src/util/tag.ts
560
- var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
561
- var extractTagIds = (value) => {
562
- if (typeof value !== "string") {
563
- return void 0;
564
- }
565
- const ids = [];
566
- let match;
567
- while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
568
- if (match[2]) {
569
- ids.push(match[2]);
570
- }
550
+ constructor(rows, _view, _projection) {
551
+ _define_property2(this, "_view", void 0);
552
+ _define_property2(this, "_projection", void 0);
553
+ _define_property2(this, "_displayToDataIndex", void 0);
554
+ _define_property2(this, "_rows", void 0);
555
+ _define_property2(this, "_localSort", void 0);
556
+ _define_property2(this, "_isDirty", void 0);
557
+ _define_property2(this, "sortedRows", void 0);
558
+ this._view = _view;
559
+ this._projection = _projection;
560
+ this._displayToDataIndex = /* @__PURE__ */ new Map();
561
+ this._localSort = signal2(void 0);
562
+ this._rows = rows;
563
+ this._isDirty = computed2(() => {
564
+ const local = this._localSort.value;
565
+ const viewSort = this._view.sort?.[0];
566
+ if (local?.type === "cleared") {
567
+ return viewSort !== void 0;
568
+ }
569
+ if (local?.type === "active") {
570
+ if (!viewSort) {
571
+ return true;
572
+ }
573
+ return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
574
+ }
575
+ return false;
576
+ });
577
+ this.sortedRows = this.initialiseSortedRows();
571
578
  }
572
- return ids.length > 0 ? ids : void 0;
573
579
  };
574
580
 
575
581
  // src/model/table-model.ts
582
+ function _define_property3(obj, key, value) {
583
+ if (key in obj) {
584
+ Object.defineProperty(obj, key, {
585
+ value,
586
+ enumerable: true,
587
+ configurable: true,
588
+ writable: true
589
+ });
590
+ } else {
591
+ obj[key] = value;
592
+ }
593
+ return obj;
594
+ }
576
595
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
577
596
  var defaultFeatures = {
578
597
  selection: {
@@ -583,252 +602,6 @@ var defaultFeatures = {
583
602
  schemaEditable: false
584
603
  };
585
604
  var TableModel = class extends Resource2 {
586
- constructor({ view, schema, projection, features = {}, sorting = [], initialSelection = [], pinnedRows = {
587
- top: [],
588
- bottom: []
589
- }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
590
- super();
591
- this._visibleRange = signal3({
592
- start: {
593
- row: 0,
594
- col: 0
595
- },
596
- end: {
597
- row: 0,
598
- col: 0
599
- }
600
- });
601
- this._rows = signal3([]);
602
- this._draftRows = signal3([]);
603
- //
604
- // Data
605
- //
606
- this.setRows = (obj) => {
607
- this._rows.value = obj;
608
- };
609
- this.getRowCount = () => this._rows.value.length;
610
- /**
611
- * @reactive
612
- */
613
- this.getDraftRowCount = () => this._draftRows.value.length;
614
- this.getColumnCount = () => this._projection?.fields.length ?? 0;
615
- this.insertRow = () => {
616
- const result = this._onInsertRow?.();
617
- if (result === false && this._draftRows.value.length === 0) {
618
- this.createDraftRow();
619
- }
620
- };
621
- this.commitDraftRow = (draftRowIndex) => {
622
- if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
623
- return false;
624
- }
625
- const draftRow = this._draftRows.value[draftRowIndex];
626
- if (!draftRow.valid) {
627
- return false;
628
- }
629
- const success = this._onInsertRow?.(draftRow.data);
630
- if (success) {
631
- const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
632
- this._draftRows.value = newDraftRows;
633
- }
634
- return success ?? false;
635
- };
636
- this.deleteRow = (rowIndex) => {
637
- const row = this._sorting.getDataIndex(rowIndex);
638
- const obj = this._rows.value[row];
639
- const objectsToDelete = [];
640
- if (this.features.selection.enabled && this._selection.hasSelection.value) {
641
- const selectedRows = this._selection.getSelectedRows();
642
- objectsToDelete.push(...selectedRows);
643
- } else {
644
- objectsToDelete.push(obj);
645
- }
646
- this._onDeleteRows?.(row, objectsToDelete);
647
- };
648
- this.handleRowAction = (actionId, rowIndex) => {
649
- if (!this._onRowAction) {
650
- return;
651
- }
652
- const row = this._sorting.getDataIndex(rowIndex);
653
- const data = this._rows.value[row];
654
- if (data) {
655
- this._onRowAction(actionId, data);
656
- }
657
- };
658
- this.getCellData = (cell) => {
659
- const { col, row, plane } = cell;
660
- const fields = this._projection?.fields ?? [];
661
- if (col < 0 || col >= fields.length) {
662
- return void 0;
663
- }
664
- const field = fields[col];
665
- let value;
666
- if (plane === "frozenRowsEnd") {
667
- if (row >= 0 && row < this._draftRows.value.length) {
668
- value = getValue2(this._draftRows.value[row].data, field.path);
669
- } else {
670
- return void 0;
671
- }
672
- } else {
673
- const dataIndex = this._sorting.getDataIndex(row);
674
- value = getValue2(this._rows.value[dataIndex], field.path);
675
- }
676
- if (value == null) {
677
- return "";
678
- }
679
- const { props } = this._projection.getFieldProjection(field.id);
680
- switch (props.format) {
681
- case FormatEnum2.Ref: {
682
- if (!field.referencePath) {
683
- return "";
684
- }
685
- return getValue2(value.target, field.referencePath);
686
- }
687
- default: {
688
- return formatForEditing({
689
- type: props.type,
690
- format: props.format,
691
- value
692
- });
693
- }
694
- }
695
- };
696
- this.validateCellData = async ({ col, row, plane }, value) => {
697
- const fields = this._projection?.fields ?? [];
698
- if (col < 0 || col >= fields.length) {
699
- return {
700
- valid: false,
701
- error: "Invalid column index"
702
- };
703
- }
704
- const field = fields[col];
705
- const { props } = this._projection.getFieldProjection(field.id);
706
- const transformedValue = editorTextToCellValue(props, value);
707
- const isDraftRow = plane === "frozenRowsEnd";
708
- if (isDraftRow) {
709
- const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
710
- if (isInvalidDraftRowIndex) {
711
- return {
712
- valid: false,
713
- error: "Invalid draft row index"
714
- };
715
- }
716
- const draftRow = this._draftRows.value[row];
717
- const snapshot = {
718
- ...draftRow.data
719
- };
720
- setValue(snapshot, field.path, transformedValue);
721
- const validationErrors = this.validateDraftRowData(snapshot);
722
- if (validationErrors.length > 0) {
723
- const error = validationErrors.find((err) => err.path === field.path);
724
- if (error) {
725
- return {
726
- valid: false,
727
- error: error.message
728
- };
729
- }
730
- }
731
- return {
732
- valid: true
733
- };
734
- } else {
735
- const rowIdx = this._sorting.getDataIndex(row);
736
- const currentRow = this._rows.value[rowIdx];
737
- invariant(currentRow, "Invalid row index", {
738
- F: __dxlog_file,
739
- L: 510,
740
- S: this,
741
- A: [
742
- "currentRow",
743
- "'Invalid row index'"
744
- ]
745
- });
746
- const snapshot = getSnapshot(currentRow);
747
- setValue(snapshot, field.path, transformedValue);
748
- const schema = getSchema(currentRow);
749
- invariant(schema, void 0, {
750
- F: __dxlog_file,
751
- L: 516,
752
- S: this,
753
- A: [
754
- "schema",
755
- ""
756
- ]
757
- });
758
- const validationResult = validateSchema(schema, snapshot);
759
- if (validationResult && validationResult.length > 0) {
760
- const error = validationResult[0];
761
- invariant(error.path === field.path, void 0, {
762
- F: __dxlog_file,
763
- L: 521,
764
- S: this,
765
- A: [
766
- "error.path === field.path",
767
- ""
768
- ]
769
- });
770
- return {
771
- valid: false,
772
- error: error.message
773
- };
774
- }
775
- return {
776
- valid: true
777
- };
778
- }
779
- };
780
- this.setCellData = (cell, value) => {
781
- const { col, row, plane } = cell;
782
- const fields = this._projection?.fields ?? [];
783
- if (col < 0 || col >= fields.length) {
784
- return;
785
- }
786
- const field = fields[col];
787
- const { props } = this._projection.getFieldProjection(field.id);
788
- const transformedValue = editorTextToCellValue(props, value);
789
- if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
790
- return;
791
- }
792
- if (plane === "frozenRowsEnd") {
793
- if (row >= 0 && row < this._draftRows.value.length) {
794
- setValue(this._draftRows.value[row].data, field.path, transformedValue);
795
- this.validateDraftRow(row);
796
- }
797
- } else {
798
- const rowIdx = this._sorting.getDataIndex(row);
799
- setValue(this._rows.value[rowIdx], field.path, transformedValue);
800
- }
801
- };
802
- this._view = view;
803
- this._projection = projection ?? new ProjectionModel2(schema, view.projection);
804
- this._features = {
805
- ...defaultFeatures,
806
- ...features
807
- };
808
- invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
809
- F: __dxlog_file,
810
- L: 139,
811
- S: this,
812
- A: [
813
- "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
814
- "'Single selection is not compatible with editable tables.'"
815
- ]
816
- });
817
- this._sorting = new TableSorting(this._rows, this._view, this._projection);
818
- if (sorting.length > 0) {
819
- const [sort] = sorting;
820
- this._sorting.setSort(sort.fieldId, sort.direction);
821
- }
822
- this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", initialSelection, () => this._onRowOrderChange?.());
823
- this._pinnedRows = pinnedRows;
824
- this._rowActions = rowActions;
825
- this._onInsertRow = onInsertRow;
826
- this._onDeleteRows = onDeleteRows;
827
- this._onDeleteColumn = onDeleteColumn;
828
- this._onCellUpdate = onCellUpdate;
829
- this._onRowOrderChange = onRowOrderChange;
830
- this._onRowAction = onRowAction;
831
- }
832
605
  get id() {
833
606
  return fullyQualifiedId(this._view);
834
607
  }
@@ -838,7 +611,7 @@ var TableModel = class extends Resource2 {
838
611
  get table() {
839
612
  invariant(this._table, "Model not initialized", {
840
613
  F: __dxlog_file,
841
- L: 177,
614
+ L: 187,
842
615
  S: this,
843
616
  A: [
844
617
  "this._table",
@@ -877,7 +650,7 @@ var TableModel = class extends Resource2 {
877
650
  get columnMeta() {
878
651
  invariant(this._columnMeta, void 0, {
879
652
  F: __dxlog_file,
880
- L: 216,
653
+ L: 226,
881
654
  S: this,
882
655
  A: [
883
656
  "this._columnMeta",
@@ -901,12 +674,12 @@ var TableModel = class extends Resource2 {
901
674
  //
902
675
  async _open() {
903
676
  const presentation = this._view.presentation.target ?? await this._view.presentation.load();
904
- invariant(Obj3.instanceOf(TableView, presentation), void 0, {
677
+ invariant(Obj2.instanceOf(schema_exports.Table, presentation), void 0, {
905
678
  F: __dxlog_file,
906
- L: 239,
679
+ L: 249,
907
680
  S: this,
908
681
  A: [
909
- "Obj.instanceOf(TableView, presentation)",
682
+ "Obj.instanceOf(Table.Table, presentation)",
910
683
  ""
911
684
  ]
912
685
  });
@@ -935,7 +708,7 @@ var TableModel = class extends Resource2 {
935
708
  },
936
709
  frozenColsEnd: {
937
710
  0: {
938
- size: 40,
711
+ size: 32,
939
712
  resizeable: false
940
713
  }
941
714
  }
@@ -1025,7 +798,7 @@ var TableModel = class extends Resource2 {
1025
798
  this._draftRows.value = newDraftRows;
1026
799
  }
1027
800
  validateDraftRowData(data) {
1028
- const schema = toEffectSchema2(this._projection.baseSchema);
801
+ const schema = toEffectSchema(this._projection.baseSchema);
1029
802
  return validateSchema(schema, data) || [];
1030
803
  }
1031
804
  /**
@@ -1090,23 +863,257 @@ var TableModel = class extends Resource2 {
1090
863
  this.table.sizes[field.path] = newWidth;
1091
864
  }
1092
865
  }
1093
- }
1094
- //
1095
- // Pinning
1096
- //
1097
- // TODO(burdon): Change to setPinned(on/off).
1098
- pinRow(rowIndex, side) {
1099
- this._pinnedRows[side].push(rowIndex);
1100
- }
1101
- unpinRow(rowIndex) {
1102
- this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
1103
- this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
1104
- }
1105
- //
1106
- // View operations
1107
- //
1108
- saveView() {
1109
- this._sorting.save();
866
+ }
867
+ //
868
+ // Pinning
869
+ //
870
+ // TODO(burdon): Change to setPinned(on/off).
871
+ pinRow(rowIndex, side) {
872
+ this._pinnedRows[side].push(rowIndex);
873
+ }
874
+ unpinRow(rowIndex) {
875
+ this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
876
+ this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
877
+ }
878
+ //
879
+ // View operations
880
+ //
881
+ saveView() {
882
+ this._sorting.save();
883
+ }
884
+ constructor({ view, schema, projection, features = {}, sorting = [], initialSelection = [], pinnedRows = {
885
+ top: [],
886
+ bottom: []
887
+ }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
888
+ super(), _define_property3(this, "_view", void 0), _define_property3(this, "_projection", void 0), _define_property3(this, "_table", void 0), _define_property3(this, "_visibleRange", signal3({
889
+ start: {
890
+ row: 0,
891
+ col: 0
892
+ },
893
+ end: {
894
+ row: 0,
895
+ col: 0
896
+ }
897
+ })), _define_property3(this, "_onInsertRow", void 0), _define_property3(this, "_onDeleteRows", void 0), _define_property3(this, "_onDeleteColumn", void 0), _define_property3(this, "_onCellUpdate", void 0), _define_property3(this, "_onRowOrderChange", void 0), _define_property3(this, "_onRowAction", void 0), _define_property3(this, "_rowActions", void 0), _define_property3(this, "_features", void 0), _define_property3(this, "_rows", signal3([])), _define_property3(this, "_draftRows", signal3([])), _define_property3(this, "_sorting", void 0), _define_property3(this, "_pinnedRows", void 0), _define_property3(this, "_selection", void 0), _define_property3(this, "_columnMeta", void 0), //
898
+ // Data
899
+ //
900
+ _define_property3(this, "setRows", (obj) => {
901
+ this._rows.value = obj;
902
+ }), _define_property3(this, "getRowCount", () => this._rows.value.length), /**
903
+ * @reactive
904
+ */
905
+ _define_property3(this, "getDraftRowCount", () => this._draftRows.value.length), _define_property3(this, "getColumnCount", () => this._projection?.fields.length ?? 0), _define_property3(this, "insertRow", () => {
906
+ const result = this._onInsertRow?.();
907
+ if (result === "draft" && this._draftRows.value.length === 0) {
908
+ this.createDraftRow();
909
+ }
910
+ return result ?? "final";
911
+ }), _define_property3(this, "commitDraftRow", (draftRowIndex) => {
912
+ if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
913
+ return false;
914
+ }
915
+ const draftRow = this._draftRows.value[draftRowIndex];
916
+ if (!draftRow.valid) {
917
+ return false;
918
+ }
919
+ const insertRowResult = this._onInsertRow?.(draftRow.data);
920
+ if (insertRowResult === "final") {
921
+ const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
922
+ this._draftRows.value = newDraftRows;
923
+ }
924
+ return insertRowResult === "final";
925
+ }), _define_property3(this, "deleteRow", (rowIndex) => {
926
+ const row = this._sorting.getDataIndex(rowIndex);
927
+ const obj = this._rows.value[row];
928
+ const objectsToDelete = [];
929
+ if (this.features.selection.enabled && this._selection.hasSelection.value) {
930
+ const selectedRows = this._selection.getSelectedRows();
931
+ objectsToDelete.push(...selectedRows);
932
+ } else {
933
+ objectsToDelete.push(obj);
934
+ }
935
+ this._onDeleteRows?.(row, objectsToDelete);
936
+ }), _define_property3(this, "handleRowAction", (actionId, rowIndex) => {
937
+ if (!this._onRowAction) {
938
+ return;
939
+ }
940
+ const row = this._sorting.getDataIndex(rowIndex);
941
+ const data = this._rows.value[row];
942
+ if (data) {
943
+ this._onRowAction(actionId, data);
944
+ }
945
+ }), _define_property3(this, "getCellData", (cell) => {
946
+ const { col, row, plane } = cell;
947
+ const fields = this._projection?.fields ?? [];
948
+ if (col < 0 || col >= fields.length) {
949
+ return void 0;
950
+ }
951
+ const field = fields[col];
952
+ let value;
953
+ if (plane === "frozenRowsEnd") {
954
+ if (row >= 0 && row < this._draftRows.value.length) {
955
+ value = getValue2(this._draftRows.value[row].data, field.path);
956
+ } else {
957
+ return void 0;
958
+ }
959
+ } else {
960
+ const dataIndex = this._sorting.getDataIndex(row);
961
+ value = getValue2(this._rows.value[dataIndex], field.path);
962
+ }
963
+ if (value == null) {
964
+ return "";
965
+ }
966
+ const { props } = this._projection.getFieldProjection(field.id);
967
+ switch (props.format) {
968
+ case FormatEnum2.Ref: {
969
+ if (!field.referencePath) {
970
+ return "";
971
+ }
972
+ return getValue2(value.target, field.referencePath);
973
+ }
974
+ default: {
975
+ return formatForEditing({
976
+ type: props.type,
977
+ format: props.format,
978
+ value
979
+ });
980
+ }
981
+ }
982
+ }), _define_property3(this, "validateCellData", async ({ col, row, plane }, value) => {
983
+ const fields = this._projection?.fields ?? [];
984
+ if (col < 0 || col >= fields.length) {
985
+ return {
986
+ valid: false,
987
+ error: "Invalid column index"
988
+ };
989
+ }
990
+ const field = fields[col];
991
+ const { props } = this._projection.getFieldProjection(field.id);
992
+ const transformedValue = editorTextToCellValue(props, value);
993
+ const isDraftRow = plane === "frozenRowsEnd";
994
+ if (isDraftRow) {
995
+ const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
996
+ if (isInvalidDraftRowIndex) {
997
+ return {
998
+ valid: false,
999
+ error: "Invalid draft row index"
1000
+ };
1001
+ }
1002
+ const draftRow = this._draftRows.value[row];
1003
+ const snapshot = {
1004
+ ...draftRow.data
1005
+ };
1006
+ setValue(snapshot, field.path, transformedValue);
1007
+ const validationErrors = this.validateDraftRowData(snapshot);
1008
+ if (validationErrors.length > 0) {
1009
+ const error = validationErrors.find((err) => err.path === field.path);
1010
+ if (error) {
1011
+ return {
1012
+ valid: false,
1013
+ error: error.message
1014
+ };
1015
+ }
1016
+ }
1017
+ return {
1018
+ valid: true
1019
+ };
1020
+ } else {
1021
+ const rowIdx = this._sorting.getDataIndex(row);
1022
+ const currentRow = this._rows.value[rowIdx];
1023
+ invariant(currentRow, "Invalid row index", {
1024
+ F: __dxlog_file,
1025
+ L: 522,
1026
+ S: this,
1027
+ A: [
1028
+ "currentRow",
1029
+ "'Invalid row index'"
1030
+ ]
1031
+ });
1032
+ const snapshot = getSnapshot(currentRow);
1033
+ setValue(snapshot, field.path, transformedValue);
1034
+ const schema2 = getSchema(currentRow);
1035
+ invariant(schema2, void 0, {
1036
+ F: __dxlog_file,
1037
+ L: 528,
1038
+ S: this,
1039
+ A: [
1040
+ "schema",
1041
+ ""
1042
+ ]
1043
+ });
1044
+ const validationResult = validateSchema(schema2, snapshot);
1045
+ if (validationResult && validationResult.length > 0) {
1046
+ const error = validationResult[0];
1047
+ invariant(error.path === field.path, void 0, {
1048
+ F: __dxlog_file,
1049
+ L: 533,
1050
+ S: this,
1051
+ A: [
1052
+ "error.path === field.path",
1053
+ ""
1054
+ ]
1055
+ });
1056
+ return {
1057
+ valid: false,
1058
+ error: error.message
1059
+ };
1060
+ }
1061
+ return {
1062
+ valid: true
1063
+ };
1064
+ }
1065
+ }), _define_property3(this, "setCellData", (cell, value) => {
1066
+ const { col, row, plane } = cell;
1067
+ const fields = this._projection?.fields ?? [];
1068
+ if (col < 0 || col >= fields.length) {
1069
+ return;
1070
+ }
1071
+ const field = fields[col];
1072
+ const { props } = this._projection.getFieldProjection(field.id);
1073
+ const transformedValue = editorTextToCellValue(props, value);
1074
+ if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
1075
+ return;
1076
+ }
1077
+ if (plane === "frozenRowsEnd") {
1078
+ if (row >= 0 && row < this._draftRows.value.length) {
1079
+ setValue(this._draftRows.value[row].data, field.path, transformedValue);
1080
+ this.validateDraftRow(row);
1081
+ }
1082
+ } else {
1083
+ const rowIdx = this._sorting.getDataIndex(row);
1084
+ setValue(this._rows.value[rowIdx], field.path, transformedValue);
1085
+ }
1086
+ });
1087
+ this._view = view;
1088
+ this._projection = projection ?? new ProjectionModel2(schema, view.projection);
1089
+ this._projection.normalizeView();
1090
+ this._features = {
1091
+ ...defaultFeatures,
1092
+ ...features
1093
+ };
1094
+ invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
1095
+ F: __dxlog_file,
1096
+ L: 149,
1097
+ S: this,
1098
+ A: [
1099
+ "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
1100
+ "'Single selection is not compatible with editable tables.'"
1101
+ ]
1102
+ });
1103
+ this._sorting = new TableSorting(this._rows, this._view, this._projection);
1104
+ if (sorting.length > 0) {
1105
+ const [sort] = sorting;
1106
+ this._sorting.setSort(sort.fieldId, sort.direction);
1107
+ }
1108
+ this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", initialSelection, () => this._onRowOrderChange?.());
1109
+ this._pinnedRows = pinnedRows;
1110
+ this._rowActions = rowActions;
1111
+ this._onInsertRow = onInsertRow;
1112
+ this._onDeleteRows = onDeleteRows;
1113
+ this._onDeleteColumn = onDeleteColumn;
1114
+ this._onCellUpdate = onCellUpdate;
1115
+ this._onRowOrderChange = onRowOrderChange;
1116
+ this._onRowAction = onRowAction;
1110
1117
  }
1111
1118
  };
1112
1119
  var editorTextToCellValue = (props, value) => {
@@ -1142,47 +1149,64 @@ var editorTextToCellValue = (props, value) => {
1142
1149
 
1143
1150
  // src/model/modal-controller.ts
1144
1151
  import { signal as signal4 } from "@preact/signals-core";
1145
- import { log } from "@dxos/log";
1146
- var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
1152
+ function _define_property4(obj, key, value) {
1153
+ if (key in obj) {
1154
+ Object.defineProperty(obj, key, {
1155
+ value,
1156
+ enumerable: true,
1157
+ configurable: true,
1158
+ writable: true
1159
+ });
1160
+ } else {
1161
+ obj[key] = value;
1162
+ }
1163
+ return obj;
1164
+ }
1147
1165
  var ModalController = class {
1166
+ get state() {
1167
+ return this._state;
1168
+ }
1169
+ get trigger() {
1170
+ return this._triggerRef;
1171
+ }
1148
1172
  constructor() {
1149
- this._state = signal4({
1173
+ _define_property4(this, "_state", signal4({
1150
1174
  type: "closed"
1151
- });
1152
- this._triggerRef = {
1175
+ }));
1176
+ _define_property4(this, "_triggerRef", {
1153
1177
  current: null
1154
- };
1155
- this.setTrigger = (trigger) => {
1178
+ });
1179
+ _define_property4(this, "setTrigger", (trigger) => {
1156
1180
  this._triggerRef.current = trigger;
1157
- };
1158
- this.showRowMenu = (rowIndex) => {
1181
+ });
1182
+ _define_property4(this, "showRowMenu", (rowIndex) => {
1159
1183
  this._state.value = {
1160
1184
  type: "row",
1161
1185
  rowIndex
1162
1186
  };
1163
- };
1164
- this.showColumnMenu = (fieldId) => {
1187
+ });
1188
+ _define_property4(this, "showColumnMenu", (fieldId) => {
1165
1189
  this._state.value = {
1166
1190
  type: "column",
1167
1191
  fieldId
1168
1192
  };
1169
- };
1170
- this.showColumnCreator = () => {
1193
+ });
1194
+ _define_property4(this, "showColumnCreator", () => {
1171
1195
  this._state.value = {
1172
1196
  type: "columnSettings",
1173
1197
  mode: {
1174
1198
  type: "create"
1175
1199
  }
1176
1200
  };
1177
- };
1178
- this.showReferencePanel = (targetId, schemaId) => {
1201
+ });
1202
+ _define_property4(this, "showReferencePanel", (targetId, schemaId) => {
1179
1203
  this._state.value = {
1180
1204
  type: "refPanel",
1181
1205
  targetId,
1182
1206
  typename: schemaId
1183
1207
  };
1184
- };
1185
- this.openColumnSettings = () => {
1208
+ });
1209
+ _define_property4(this, "openColumnSettings", () => {
1186
1210
  if (this._state.value.type === "column") {
1187
1211
  const fieldId = this._state.value.fieldId;
1188
1212
  requestAnimationFrame(() => {
@@ -1195,63 +1219,38 @@ var ModalController = class {
1195
1219
  };
1196
1220
  });
1197
1221
  }
1198
- };
1199
- this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
1200
- if (anchorCell) {
1201
- this._triggerRef.current = anchorCell;
1202
- this._state.value = {
1203
- type: "createRefPanel",
1204
- typename,
1205
- initialValues,
1206
- onCreate
1207
- };
1208
- } else {
1209
- log.warn("anchor cell not found while creating new ref", void 0, {
1210
- F: __dxlog_file2,
1211
- L: 86,
1212
- S: this,
1213
- C: (f, a) => f(...a)
1214
- });
1215
- }
1216
- };
1217
- this.close = () => {
1222
+ });
1223
+ _define_property4(this, "close", () => {
1218
1224
  this._state.value = {
1219
1225
  type: "closed"
1220
1226
  };
1221
- };
1222
- }
1223
- get state() {
1224
- return this._state;
1225
- }
1226
- get trigger() {
1227
- return this._triggerRef;
1227
+ });
1228
1228
  }
1229
1229
  };
1230
1230
 
1231
1231
  // src/model/table-presentation.ts
1232
1232
  import { signal as signal5 } from "@preact/signals-core";
1233
- import { isNotNullable } from "effect/Predicate";
1234
- import { Obj as Obj4 } from "@dxos/echo";
1235
- import { FormatEnum as FormatEnum3, getValue as getValue3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1233
+ import * as Predicate from "effect/Predicate";
1234
+ import { Obj as Obj3 } from "@dxos/echo";
1235
+ import { FormatEnum as FormatEnum3, TypeEnum as TypeEnum2, getValue as getValue3 } from "@dxos/echo/internal";
1236
1236
  import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "@dxos/react-ui-form";
1237
1237
  import { toPlaneCellIndex } from "@dxos/react-ui-grid";
1238
1238
  import { mx } from "@dxos/react-ui-theme";
1239
1239
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
1240
- var TablePresentation = class {
1241
- constructor(model, _visibleRange = signal5({
1242
- start: {
1243
- row: 0,
1244
- col: 0
1245
- },
1246
- end: {
1247
- row: 0,
1248
- col: 0
1249
- }
1250
- })) {
1251
- this.model = model;
1252
- this._visibleRange = _visibleRange;
1253
- this.fieldProjectionCache = /* @__PURE__ */ new Map();
1240
+ function _define_property5(obj, key, value) {
1241
+ if (key in obj) {
1242
+ Object.defineProperty(obj, key, {
1243
+ value,
1244
+ enumerable: true,
1245
+ configurable: true,
1246
+ writable: true
1247
+ });
1248
+ } else {
1249
+ obj[key] = value;
1254
1250
  }
1251
+ return obj;
1252
+ }
1253
+ var TablePresentation = class {
1255
1254
  getCells(range, plane) {
1256
1255
  this.fieldProjectionCache.clear();
1257
1256
  let cells;
@@ -1278,6 +1277,9 @@ var TablePresentation = class {
1278
1277
  case "frozenRowsEnd":
1279
1278
  cells = this.getDraftRowCells(range);
1280
1279
  break;
1280
+ case "fixedEndStart":
1281
+ cells = this.getDraftIconCells(range);
1282
+ break;
1281
1283
  case "fixedEndEnd":
1282
1284
  cells = this.getDraftActionCells(range);
1283
1285
  break;
@@ -1336,10 +1338,7 @@ var TablePresentation = class {
1336
1338
  }
1337
1339
  };
1338
1340
  const classes = [];
1339
- const formatClasses = cellClassesForFieldType({
1340
- type: props.type,
1341
- format: props.format
1342
- });
1341
+ const formatClasses = cellClassesForFieldType(props);
1343
1342
  if (formatClasses) {
1344
1343
  classes.push(formatClasses);
1345
1344
  }
@@ -1347,9 +1346,7 @@ var TablePresentation = class {
1347
1346
  if (rowSelectionClasses) {
1348
1347
  classes.push(rowSelectionClasses);
1349
1348
  }
1350
- if (classes.length > 0) {
1351
- cell.className = mx(classes.flat());
1352
- }
1349
+ cell.className = mx(classes);
1353
1350
  if (props.type === TypeEnum2.Array) {
1354
1351
  const targetArray = getValue3(obj, field.path);
1355
1352
  if (targetArray && Array.isArray(targetArray)) {
@@ -1371,7 +1368,7 @@ var TablePresentation = class {
1371
1368
  }
1372
1369
  return "Object";
1373
1370
  };
1374
- const tags = targetArray.map(getLabel).filter(isNotNullable).map((title) => {
1371
+ const tags = targetArray.map(getLabel).filter(Predicate.isNotNullable).map((title) => {
1375
1372
  return `<span class="dx-tag" data-hue="neutral">${title}</span>`;
1376
1373
  }).join("");
1377
1374
  cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
@@ -1380,8 +1377,8 @@ var TablePresentation = class {
1380
1377
  if (props.format === FormatEnum3.Ref && props.referenceSchema) {
1381
1378
  const targetObj = getValue3(obj, field.path)?.target;
1382
1379
  if (targetObj) {
1383
- const dxn = Obj4.getDXN(targetObj)?.toString();
1384
- 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>`;
1380
+ const dxn = Obj3.getDXN(targetObj)?.toString();
1381
+ 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>`;
1385
1382
  }
1386
1383
  }
1387
1384
  if (props.format === FormatEnum3.Boolean) {
@@ -1443,24 +1440,37 @@ var TablePresentation = class {
1443
1440
  const cells = {};
1444
1441
  const fields = this.model.projection?.fields ?? [];
1445
1442
  const draftRows = this.model.draftRows.value;
1446
- for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1447
- const draftRow = draftRows[row];
1443
+ if (draftRows.length === 0) {
1448
1444
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
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)) {
1445
+ cells[toPlaneCellIndex({
1446
+ col,
1447
+ row: 0
1448
+ })] = {
1449
+ value: "",
1450
+ readonly: true,
1451
+ className: "dx-grid__row--cta__cell"
1452
+ };
1453
+ }
1454
+ } else {
1455
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1456
+ const draftRow = draftRows[row];
1457
+ for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1455
1458
  const cellIndex = toPlaneCellIndex({
1456
1459
  col,
1457
1460
  row
1458
1461
  });
1459
- const cellValue = cells[cellIndex];
1460
- if (cellValue) {
1461
- const existingClasses = cellValue.className || "";
1462
- const draftClasses = "dx-grid__cell--flagged";
1463
- cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
1462
+ const field = fields[col];
1463
+ if (!field) {
1464
+ continue;
1465
+ }
1466
+ this.createDataCell(cells, draftRow.data, field, col, row);
1467
+ if (this.model.hasDraftRowValidationError(row, field.path)) {
1468
+ const cellValue = cells[cellIndex];
1469
+ if (cellValue) {
1470
+ const existingClasses = cellValue.className || "";
1471
+ const draftClasses = "dx-grid__cell--flagged";
1472
+ cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
1473
+ }
1464
1474
  }
1465
1475
  }
1466
1476
  }
@@ -1479,10 +1489,10 @@ var TablePresentation = class {
1479
1489
  row: 0
1480
1490
  })] = {
1481
1491
  // TODO(burdon): Use same logic as form for fallback title.
1482
- value: props.title ?? field.path,
1483
- readonly: true,
1492
+ value: "",
1484
1493
  resizeHandle: "col",
1485
1494
  accessoryHtml: `
1495
+ <span class="grow min-is-0 truncate">${props.title ?? field.path}</span>
1486
1496
  ${direction !== void 0 ? tableButtons.sort.render({
1487
1497
  fieldId: field.id,
1488
1498
  direction
@@ -1491,7 +1501,7 @@ var TablePresentation = class {
1491
1501
  fieldId: field.id
1492
1502
  })}
1493
1503
  `,
1494
- className: "!bg-toolbarSurface"
1504
+ className: "!bg-toolbarSurface !text-description [&>div]:flex [&>div]:items-stretch"
1495
1505
  };
1496
1506
  }
1497
1507
  return cells;
@@ -1582,23 +1592,67 @@ var TablePresentation = class {
1582
1592
  getDraftActionCells(range) {
1583
1593
  const cells = {};
1584
1594
  const draftRows = this.model.draftRows.value;
1585
- for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1586
- const draftRow = draftRows[row];
1587
- const disabled = !draftRow.valid;
1595
+ if (draftRows.length === 0) {
1596
+ cells[toPlaneCellIndex({
1597
+ col: 0,
1598
+ row: 0
1599
+ })] = {
1600
+ value: "",
1601
+ className: "dx-grid__row--cta__cell",
1602
+ readonly: true
1603
+ };
1604
+ } else {
1605
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
1606
+ const draftRow = draftRows[row];
1607
+ const disabled = !draftRow.valid;
1608
+ cells[toPlaneCellIndex({
1609
+ col: 0,
1610
+ row
1611
+ })] = {
1612
+ value: "",
1613
+ readonly: true,
1614
+ accessoryHtml: tableButtons.saveDraftRow.render({
1615
+ rowIndex: row,
1616
+ disabled
1617
+ })
1618
+ };
1619
+ }
1620
+ }
1621
+ return cells;
1622
+ }
1623
+ getDraftIconCells(range) {
1624
+ const cells = {};
1625
+ const draftRows = this.model.draftRows.value;
1626
+ for (let row = range.start.row; row <= range.end.row; row++) {
1588
1627
  cells[toPlaneCellIndex({
1589
1628
  col: 0,
1590
1629
  row
1591
1630
  })] = {
1592
1631
  value: "",
1593
1632
  readonly: true,
1594
- accessoryHtml: tableButtons.saveDraftRow.render({
1595
- rowIndex: row,
1596
- disabled
1597
- })
1633
+ accessoryHtml: '<dx-icon icon="ph--plus--regular" class="contents"></dx-icon>',
1634
+ className: mx("[&>div]:grid [&>div]:place-content-center", draftRows.length < 1 && "dx-grid__row--cta__cell")
1598
1635
  };
1599
1636
  }
1600
1637
  return cells;
1601
1638
  }
1639
+ constructor(model, _visibleRange = signal5({
1640
+ start: {
1641
+ row: 0,
1642
+ col: 0
1643
+ },
1644
+ end: {
1645
+ row: 0,
1646
+ col: 0
1647
+ }
1648
+ })) {
1649
+ _define_property5(this, "model", void 0);
1650
+ _define_property5(this, "_visibleRange", void 0);
1651
+ _define_property5(this, "fieldProjectionCache", void 0);
1652
+ this.model = model;
1653
+ this._visibleRange = _visibleRange;
1654
+ this.fieldProjectionCache = /* @__PURE__ */ new Map();
1655
+ }
1602
1656
  };
1603
1657
  var cellClassesForRowSelection = (selected, selectionMode) => {
1604
1658
  if (!selected) {
@@ -1712,18 +1766,18 @@ var useTableModel = ({ view, schema, projection, rows, rowActions, features, onS
1712
1766
 
1713
1767
  // src/hooks/useAddRow.ts
1714
1768
  import { useCallback } from "react";
1715
- import { Obj as Obj5 } from "@dxos/echo";
1769
+ import { Obj as Obj4 } from "@dxos/echo";
1716
1770
  var useAddRow = ({ space, schema }) => {
1717
1771
  return useCallback((data) => {
1718
1772
  if (space && schema) {
1719
1773
  try {
1720
- space.db.add(Obj5.make(schema, data ?? {}));
1721
- return true;
1774
+ space.db.add(Obj4.make(schema, data ?? {}));
1775
+ return "final";
1722
1776
  } catch (error) {
1723
- return false;
1777
+ return "draft";
1724
1778
  }
1725
1779
  }
1726
- return false;
1780
+ return "final";
1727
1781
  }, [
1728
1782
  space,
1729
1783
  schema
@@ -1734,7 +1788,6 @@ export {
1734
1788
  getBaseSchema,
1735
1789
  makeDynamicTable,
1736
1790
  touch,
1737
- createTable,
1738
1791
  BUTTON_IDENTIFIERS,
1739
1792
  tableButtons,
1740
1793
  CONTROL_IDENTIFIERS,
@@ -1749,4 +1802,4 @@ export {
1749
1802
  useTableModel,
1750
1803
  useAddRow
1751
1804
  };
1752
- //# sourceMappingURL=chunk-Y66YLSTC.mjs.map
1805
+ //# sourceMappingURL=chunk-S56Z4V4X.mjs.map