@dxos/react-ui-table 0.8.3-main.672df60 → 0.8.3-staging.0fa589b

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 (61) hide show
  1. package/dist/lib/browser/{chunk-U6LL2AVU.mjs → chunk-TL7CKQQV.mjs} +4 -3
  2. package/dist/lib/browser/chunk-TL7CKQQV.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +272 -145
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types/index.mjs +1 -1
  7. package/dist/lib/node/{chunk-CXDGXPM6.cjs → chunk-O2VPBNS5.cjs} +6 -5
  8. package/dist/lib/node/chunk-O2VPBNS5.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +260 -135
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/types/index.cjs +3 -3
  13. package/dist/lib/node/types/index.cjs.map +1 -1
  14. package/dist/lib/node-esm/{chunk-EFSM52KQ.mjs → chunk-GBT6GD4G.mjs} +4 -3
  15. package/dist/lib/node-esm/chunk-GBT6GD4G.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +272 -145
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/types/index.mjs +1 -1
  20. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/Table.d.ts +2 -0
  23. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  24. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +7 -0
  27. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -0
  28. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  29. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  30. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/testing.d.ts +2 -2
  32. package/dist/types/src/components/testing.d.ts.map +1 -1
  33. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  34. package/dist/types/src/model/table-model.d.ts +7 -0
  35. package/dist/types/src/model/table-model.d.ts.map +1 -1
  36. package/dist/types/src/types/table.d.ts +5 -4
  37. package/dist/types/src/types/table.d.ts.map +1 -1
  38. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  39. package/package.json +34 -33
  40. package/src/components/Table/ColumnSettings.tsx +11 -11
  41. package/src/components/Table/CreateRefPanel.tsx +5 -3
  42. package/src/components/Table/DynamicTable.stories.tsx +3 -2
  43. package/src/components/Table/Table.stories.tsx +19 -16
  44. package/src/components/Table/Table.tsx +13 -3
  45. package/src/components/Table/relations.stories.tsx +15 -10
  46. package/src/components/TableCellEditor/CellValidationMessage.tsx +38 -0
  47. package/src/components/TableCellEditor/FormCellEditor.tsx +3 -1
  48. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +2 -1
  49. package/src/components/TableCellEditor/TableCellEditor.tsx +54 -22
  50. package/src/components/testing.ts +5 -4
  51. package/src/hooks/useTableModel.ts +8 -1
  52. package/src/model/table-model.test.ts +3 -2
  53. package/src/model/table-model.ts +88 -39
  54. package/src/model/table-presentation.test.ts +3 -2
  55. package/src/model/table-presentation.ts +1 -1
  56. package/src/types/table.ts +3 -2
  57. package/src/util/dynamic-table.ts +2 -2
  58. package/src/util/table.ts +11 -10
  59. package/dist/lib/browser/chunk-U6LL2AVU.mjs.map +0 -7
  60. package/dist/lib/node/chunk-CXDGXPM6.cjs.map +0 -7
  61. package/dist/lib/node-esm/chunk-EFSM52KQ.mjs.map +0 -7
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  TableSchema,
3
3
  TableType
4
- } from "./chunk-U6LL2AVU.mjs";
4
+ } from "./chunk-TL7CKQQV.mjs";
5
5
 
6
6
  // packages/ui/react-ui-table/src/translations.ts
7
7
  var translationKey = "table";
@@ -36,8 +36,8 @@ var translations_default = [
36
36
  ];
37
37
 
38
38
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
39
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
40
- import React7, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as useState2, useMemo as useMemo5, useEffect as useEffect3 } from "react";
39
+ import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
40
+ import React8, { forwardRef, useCallback as useCallback5, useImperativeHandle, useState as useState3, useMemo as useMemo5, useEffect as useEffect3 } from "react";
41
41
  import { getValue as getValue4 } from "@dxos/echo-schema";
42
42
  import { invariant as invariant4 } from "@dxos/invariant";
43
43
  import { Filter } from "@dxos/react-client/echo";
@@ -91,7 +91,7 @@ var ColumnActionsMenu = ({ model, modals }) => {
91
91
  // packages/ui/react-ui-table/src/components/Table/ColumnSettings.tsx
92
92
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
93
93
  import React2, { useCallback, useEffect, useMemo, useState } from "react";
94
- import { DropdownMenu as DropdownMenu2 } from "@dxos/react-ui";
94
+ import { Popover } from "@dxos/react-ui";
95
95
  import { FieldEditor } from "@dxos/react-ui-form";
96
96
  var ColumnSettings = ({ model, modals, onNewColumn }) => {
97
97
  var _effect = _useSignals2();
@@ -142,21 +142,21 @@ var ColumnSettings = ({ model, modals, onNewColumn }) => {
142
142
  if (!model?.view || !model.projection || !field) {
143
143
  return null;
144
144
  }
145
- return /* @__PURE__ */ React2.createElement(DropdownMenu2.Root, {
145
+ return /* @__PURE__ */ React2.createElement(Popover.Root, {
146
146
  modal: false,
147
147
  open: state?.type === "columnSettings"
148
- }, /* @__PURE__ */ React2.createElement(DropdownMenu2.VirtualTrigger, {
148
+ }, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
149
149
  virtualRef: modals.trigger
150
- }), /* @__PURE__ */ React2.createElement(DropdownMenu2.Portal, null, /* @__PURE__ */ React2.createElement(DropdownMenu2.Content, {
150
+ }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
151
151
  classNames: "md:is-64"
152
- }, /* @__PURE__ */ React2.createElement(DropdownMenu2.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
152
+ }, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(FieldEditor, {
153
153
  view: model.view,
154
154
  projection: model.projection,
155
155
  field,
156
156
  registry: space?.db.schemaRegistry,
157
157
  onSave: handleSave,
158
158
  onCancel: handleCancel
159
- })), /* @__PURE__ */ React2.createElement(DropdownMenu2.Arrow, null))));
159
+ })), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))));
160
160
  } finally {
161
161
  _effect.f();
162
162
  }
@@ -167,7 +167,7 @@ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking"
167
167
  import { Schema } from "effect";
168
168
  import React3, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
169
169
  import { live } from "@dxos/react-client/echo";
170
- import { Popover } from "@dxos/react-ui";
170
+ import { Popover as Popover2 } from "@dxos/react-ui";
171
171
  import { Form } from "@dxos/react-ui-form";
172
172
  import { useGridContext } from "@dxos/react-ui-grid";
173
173
  var CreateRefPanel = ({ model, modals, __gridScope }) => {
@@ -218,7 +218,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
218
218
  if (!model?.view || !model.projection) {
219
219
  return null;
220
220
  }
221
- return /* @__PURE__ */ React3.createElement(Popover.Root, {
221
+ return /* @__PURE__ */ React3.createElement(Popover2.Root, {
222
222
  modal: false,
223
223
  open: state?.type === "createRefPanel" && !!schema,
224
224
  onOpenChange: (nextOpen) => {
@@ -226,17 +226,17 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
226
226
  return modals.close();
227
227
  }
228
228
  }
229
- }, /* @__PURE__ */ React3.createElement(Popover.VirtualTrigger, {
229
+ }, /* @__PURE__ */ React3.createElement(Popover2.VirtualTrigger, {
230
230
  virtualRef: modals.trigger
231
- }), /* @__PURE__ */ React3.createElement(Popover.Portal, null, /* @__PURE__ */ React3.createElement(Popover.Content, {
231
+ }), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
232
232
  classNames: "md:is-64",
233
233
  "data-grid": gridId
234
- }, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
234
+ }, /* @__PURE__ */ React3.createElement(Popover2.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ React3.createElement(Form, {
235
235
  schema,
236
236
  values: state.initialValues ?? {},
237
237
  onSave: handleSave,
238
238
  onCancel: handleCancel
239
- }), /* @__PURE__ */ React3.createElement(Popover.Arrow, null))));
239
+ })), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null))));
240
240
  } finally {
241
241
  _effect.f();
242
242
  }
@@ -245,7 +245,7 @@ var CreateRefPanel = ({ model, modals, __gridScope }) => {
245
245
  // packages/ui/react-ui-table/src/components/Table/RowActionsMenu.tsx
246
246
  import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
247
247
  import React4 from "react";
248
- import { DropdownMenu as DropdownMenu3, useTranslation as useTranslation2 } from "@dxos/react-ui";
248
+ import { DropdownMenu as DropdownMenu2, useTranslation as useTranslation2 } from "@dxos/react-ui";
249
249
  var RowActionsMenu = ({ model, modals }) => {
250
250
  var _effect = _useSignals4();
251
251
  try {
@@ -255,23 +255,23 @@ var RowActionsMenu = ({ model, modals }) => {
255
255
  if (state?.type !== "row") {
256
256
  return null;
257
257
  }
258
- return /* @__PURE__ */ React4.createElement(DropdownMenu3.Root, {
258
+ return /* @__PURE__ */ React4.createElement(DropdownMenu2.Root, {
259
259
  modal: false,
260
260
  open: true,
261
261
  onOpenChange: modals.close
262
- }, /* @__PURE__ */ React4.createElement(DropdownMenu3.VirtualTrigger, {
262
+ }, /* @__PURE__ */ React4.createElement(DropdownMenu2.VirtualTrigger, {
263
263
  virtualRef: modals.trigger
264
- }), /* @__PURE__ */ React4.createElement(DropdownMenu3.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu3.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu3.Item, {
264
+ }), /* @__PURE__ */ React4.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
265
265
  "data-testid": "row-menu-delete",
266
266
  onClick: () => model.deleteRow(state.rowIndex)
267
- }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu3.Item, {
267
+ }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React4.createElement(DropdownMenu2.Item, {
268
268
  key: action.id,
269
269
  "data-testid": `row-action-${action.id}`,
270
270
  onClick: () => {
271
271
  modals.close();
272
272
  model.handleRowAction(action.id, state.rowIndex);
273
273
  }
274
- }, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu3.Arrow, null)));
274
+ }, t(action.translationKey)))), /* @__PURE__ */ React4.createElement(DropdownMenu2.Arrow, null)));
275
275
  } finally {
276
276
  _effect.f();
277
277
  }
@@ -280,18 +280,19 @@ var RowActionsMenu = ({ model, modals }) => {
280
280
  // packages/ui/react-ui-table/src/model/table-model.ts
281
281
  import { computed as computed3, effect as effect2, signal as signal3 } from "@preact/signals-core";
282
282
  import { Resource as Resource2 } from "@dxos/context";
283
- import { FormatEnum as FormatEnum3, getValue as getValue2, setValue } from "@dxos/echo-schema";
283
+ import { FormatEnum as FormatEnum3, getValue as getValue2, setValue, getSnapshot, getSchema } from "@dxos/echo-schema";
284
284
  import { invariant } from "@dxos/invariant";
285
- import { isLiveObject, makeRef as makeRef2 } from "@dxos/live-object";
285
+ import { isLiveObject, makeRef } from "@dxos/live-object";
286
286
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
287
+ import { validateSchema } from "@dxos/schema";
287
288
 
288
289
  // packages/ui/react-ui-table/src/model/selection-model.ts
289
290
  import { computed, effect, signal } from "@preact/signals-core";
290
291
  import { Resource } from "@dxos/context";
291
292
 
292
293
  // packages/ui/react-ui-table/src/util/dynamic-table.ts
294
+ import { Obj, Ref } from "@dxos/echo";
293
295
  import { getTypename, toJsonSchema } from "@dxos/echo-schema";
294
- import { live as live2, makeRef } from "@dxos/live-object";
295
296
  import { createView, getSchemaFromPropertyDefinitions, ViewProjection } from "@dxos/schema";
296
297
  var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
297
298
  if (typename && properties) {
@@ -323,9 +324,9 @@ var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
323
324
  fields: properties.map((property) => property.name)
324
325
  }
325
326
  });
326
- const table = live2(TableType, {
327
+ const table = Obj.make(TableType, {
327
328
  name: "dynamic-table",
328
- view: makeRef(view)
329
+ view: Ref.make(view)
329
330
  });
330
331
  const projection = new ViewProjection(jsonSchema, view);
331
332
  if (properties && view.fields) {
@@ -371,9 +372,9 @@ var touch = (value) => value;
371
372
 
372
373
  // packages/ui/react-ui-table/src/util/table.ts
373
374
  import { Schema as Schema2 } from "effect";
374
- import { Format, FormatEnum, Ref, TypedObject, TypeEnum } from "@dxos/echo-schema";
375
+ import { Format, FormatEnum, Ref as Ref2, TypedObject, TypeEnum } from "@dxos/echo-schema";
375
376
  import { PublicKey } from "@dxos/react-client";
376
- import { live as live3 } from "@dxos/react-client/echo";
377
+ import { live as live2 } from "@dxos/react-client/echo";
377
378
  import { createFieldId, createView as createView2, getSchemaProperties, ViewProjection as ViewProjection2 } from "@dxos/schema";
378
379
  var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
379
380
  if (typename) {
@@ -382,7 +383,7 @@ var initializeTable = async ({ client, space, table, typename, initialRow = true
382
383
  throw new Error(`Schema not found: ${typename}`);
383
384
  }
384
385
  const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
385
- table.view = Ref.make(createView2({
386
+ table.view = Ref2.make(createView2({
386
387
  // TODO(ZaymonFC): Don't hardcode name?
387
388
  name: "View",
388
389
  typename: schema.typename,
@@ -392,10 +393,10 @@ var initializeTable = async ({ client, space, table, typename, initialRow = true
392
393
  return schema;
393
394
  } else {
394
395
  const [schema] = await space.db.schemaRegistry.register([
395
- ContactSchema
396
+ createContactSchema()
396
397
  ]);
397
398
  const fields = ContactFields;
398
- table.view = Ref.make(createView2({
399
+ table.view = Ref2.make(createView2({
399
400
  name: "View",
400
401
  typename: schema.typename,
401
402
  jsonSchema: schema.jsonSchema,
@@ -403,19 +404,21 @@ var initializeTable = async ({ client, space, table, typename, initialRow = true
403
404
  }));
404
405
  createProjection(schema, table.view.target);
405
406
  if (initialRow) {
406
- space.db.add(live3(schema, {}));
407
+ space.db.add(live2(schema, {}));
407
408
  }
408
409
  return schema;
409
410
  }
410
411
  };
411
- var ContactSchema = TypedObject({
412
+ var createContactSchema = () => TypedObject({
412
413
  typename: `example.com/type/${PublicKey.random().truncate()}`,
413
414
  version: "0.1.0"
414
415
  })({
415
416
  name: Schema2.optional(Schema2.String).annotations({
416
417
  title: "Name"
417
418
  }),
418
- active: Schema2.optional(Schema2.Boolean),
419
+ active: Schema2.optional(Schema2.Boolean).annotations({
420
+ title: "Active"
421
+ }),
419
422
  email: Schema2.optional(Format.Email),
420
423
  salary: Schema2.optional(Format.Currency()).annotations({
421
424
  title: "Salary"
@@ -969,6 +972,61 @@ var TableModel = class extends Resource2 {
969
972
  }
970
973
  }
971
974
  };
975
+ this.validateCellData = async ({ col, row }, value) => {
976
+ const rowIdx = this._sorting.getDataIndex(row);
977
+ const fields = this._view?.fields ?? [];
978
+ if (col < 0 || col >= fields.length) {
979
+ return {
980
+ valid: false,
981
+ error: "Invalid column index"
982
+ };
983
+ }
984
+ const field = fields[col];
985
+ const { props } = this._projection.getFieldProjection(field.id);
986
+ const currentRow = this._rows.value[rowIdx];
987
+ invariant(currentRow, "Invalid row index", {
988
+ F: __dxlog_file,
989
+ L: 355,
990
+ S: this,
991
+ A: [
992
+ "currentRow",
993
+ "'Invalid row index'"
994
+ ]
995
+ });
996
+ const snapshot = getSnapshot(currentRow);
997
+ const transformedValue = editorTextToCellValue(props, value);
998
+ setValue(snapshot, field.path, transformedValue);
999
+ const schema = getSchema(currentRow);
1000
+ invariant(schema, void 0, {
1001
+ F: __dxlog_file,
1002
+ L: 365,
1003
+ S: this,
1004
+ A: [
1005
+ "schema",
1006
+ ""
1007
+ ]
1008
+ });
1009
+ const validationResult = validateSchema(schema, snapshot);
1010
+ if (validationResult && validationResult.length > 0) {
1011
+ const error = validationResult[0];
1012
+ invariant(error.path === field.path, void 0, {
1013
+ F: __dxlog_file,
1014
+ L: 370,
1015
+ S: this,
1016
+ A: [
1017
+ "error.path === field.path",
1018
+ ""
1019
+ ]
1020
+ });
1021
+ return {
1022
+ valid: false,
1023
+ error: error.message
1024
+ };
1025
+ }
1026
+ return {
1027
+ valid: true
1028
+ };
1029
+ };
972
1030
  this.setCellData = ({ col, row }, value) => {
973
1031
  const rowIdx = this._sorting.getDataIndex(row);
974
1032
  const fields = this._view?.fields ?? [];
@@ -977,36 +1035,11 @@ var TableModel = class extends Resource2 {
977
1035
  }
978
1036
  const field = fields[col];
979
1037
  const { props } = this._projection.getFieldProjection(field.id);
980
- switch (props.format) {
981
- case FormatEnum3.Ref: {
982
- if (isLiveObject(value)) {
983
- setValue(this._rows.value[rowIdx], field.path, makeRef2(value));
984
- }
985
- break;
986
- }
987
- case FormatEnum3.SingleSelect: {
988
- const ids = extractTagIds(value);
989
- if (ids && ids.length > 0) {
990
- setValue(this._rows.value[rowIdx], field.path, ids[0]);
991
- }
992
- break;
993
- }
994
- case FormatEnum3.MultiSelect: {
995
- const ids = extractTagIds(value);
996
- if (ids) {
997
- setValue(this._rows.value[rowIdx], field.path, ids);
998
- }
999
- break;
1000
- }
1001
- default: {
1002
- setValue(this._rows.value[rowIdx], field.path, parseValue({
1003
- type: props.type,
1004
- format: props.format,
1005
- value
1006
- }));
1007
- break;
1008
- }
1038
+ const transformedValue = editorTextToCellValue(props, value);
1039
+ if (props.format === FormatEnum3.Ref && !isLiveObject(value)) {
1040
+ return;
1009
1041
  }
1042
+ setValue(this._rows.value[rowIdx], field.path, transformedValue);
1010
1043
  };
1011
1044
  this._id = id;
1012
1045
  this._space = space;
@@ -1018,7 +1051,7 @@ var TableModel = class extends Resource2 {
1018
1051
  };
1019
1052
  invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
1020
1053
  F: __dxlog_file,
1021
- L: 115,
1054
+ L: 126,
1022
1055
  S: this,
1023
1056
  A: [
1024
1057
  "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
@@ -1078,7 +1111,7 @@ var TableModel = class extends Resource2 {
1078
1111
  get columnMeta() {
1079
1112
  invariant(this._columnMeta, void 0, {
1080
1113
  F: __dxlog_file,
1081
- L: 184,
1114
+ L: 195,
1082
1115
  S: this,
1083
1116
  A: [
1084
1117
  "this._columnMeta",
@@ -1213,6 +1246,36 @@ var TableModel = class extends Resource2 {
1213
1246
  this._sorting.save();
1214
1247
  }
1215
1248
  };
1249
+ var editorTextToCellValue = (props, value) => {
1250
+ switch (props.format) {
1251
+ case FormatEnum3.Ref: {
1252
+ if (isLiveObject(value)) {
1253
+ return makeRef(value);
1254
+ } else {
1255
+ return value;
1256
+ }
1257
+ }
1258
+ case FormatEnum3.SingleSelect: {
1259
+ const ids = extractTagIds(value);
1260
+ if (ids && ids.length > 0) {
1261
+ return ids[0];
1262
+ } else {
1263
+ return value;
1264
+ }
1265
+ }
1266
+ case FormatEnum3.MultiSelect: {
1267
+ const ids = extractTagIds(value);
1268
+ return ids || value;
1269
+ }
1270
+ default: {
1271
+ return parseValue({
1272
+ type: props.type,
1273
+ format: props.format,
1274
+ value
1275
+ });
1276
+ }
1277
+ }
1278
+ };
1216
1279
 
1217
1280
  // packages/ui/react-ui-table/src/model/modal-controller.ts
1218
1281
  import { signal as signal4 } from "@preact/signals-core";
@@ -1438,7 +1501,7 @@ var TablePresentation = class {
1438
1501
  const targetObj = getValue3(obj, field.path)?.target;
1439
1502
  if (targetObj) {
1440
1503
  const dxn = getObjectDXN(targetObj)?.toString();
1441
- cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button block is-6 pli-[3px] plb-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
1504
+ 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>`;
1442
1505
  }
1443
1506
  }
1444
1507
  if (props.format === FormatEnum4.Boolean) {
@@ -1630,29 +1693,58 @@ var cellClassesForRowSelection = (selected, selectionMode) => {
1630
1693
  };
1631
1694
 
1632
1695
  // packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx
1633
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
1634
- import React6, { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef2 } from "react";
1696
+ import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
1697
+ import React7, { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef2, useState as useState2 } from "react";
1635
1698
  import { FormatEnum as FormatEnum5, TypeEnum as TypeEnum4 } from "@dxos/echo-schema";
1636
1699
  import { invariant as invariant3 } from "@dxos/invariant";
1637
1700
  import { useThemeContext } from "@dxos/react-ui";
1638
1701
  import { createMarkdownExtensions } from "@dxos/react-ui-editor";
1639
- import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3, GridCellEditor } from "@dxos/react-ui-grid";
1702
+ import { cellQuery, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext4, GridCellEditor } from "@dxos/react-ui-grid";
1640
1703
  import { tagPickerExtension, createLinks } from "@dxos/react-ui-tag-picker";
1641
1704
 
1642
- // packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx
1705
+ // packages/ui/react-ui-table/src/components/TableCellEditor/CellValidationMessage.tsx
1643
1706
  import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
1644
- import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
1645
- import { getSnapshot } from "@dxos/echo-schema";
1707
+ import React5 from "react";
1708
+ import { useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
1709
+ var CellValidationMessage = ({ validationError, __gridScope }) => {
1710
+ var _effect = _useSignals5();
1711
+ try {
1712
+ const { editing, editBox: box } = useGridContext2("GridSheetCellEditor", __gridScope);
1713
+ if (!editing || !validationError) {
1714
+ return null;
1715
+ }
1716
+ return /* @__PURE__ */ React5.createElement("div", {
1717
+ role: "none",
1718
+ className: "absolute bg-errorSurface text-errorSurfaceText rounded-bs-sm text-xs p-1",
1719
+ style: {
1720
+ ...{
1721
+ "--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
1722
+ },
1723
+ zIndex: 10,
1724
+ insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
1725
+ insetInlineStart: box.insetInlineStart,
1726
+ inlineSize: box.inlineSize
1727
+ }
1728
+ }, validationError);
1729
+ } finally {
1730
+ _effect.f();
1731
+ }
1732
+ };
1733
+
1734
+ // packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx
1735
+ import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
1736
+ import React6, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useRef } from "react";
1737
+ import { getSnapshot as getSnapshot2 } from "@dxos/echo-schema";
1646
1738
  import { invariant as invariant2 } from "@dxos/invariant";
1647
- import { Popover as Popover2 } from "@dxos/react-ui";
1739
+ import { Popover as Popover3 } from "@dxos/react-ui";
1648
1740
  import { Form as Form2 } from "@dxos/react-ui-form";
1649
- import { parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
1741
+ import { parseCellIndex, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
1650
1742
  import { getDeep, setDeep } from "@dxos/util";
1651
1743
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
1652
1744
  var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
1653
- var _effect = _useSignals5();
1745
+ var _effect = _useSignals6();
1654
1746
  try {
1655
- const { editing, setEditing } = useGridContext2("ArrayEditor", __gridScope);
1747
+ const { editing, setEditing } = useGridContext3("ArrayEditor", __gridScope);
1656
1748
  const cellRef = useRef(null);
1657
1749
  useEffect2(() => {
1658
1750
  if (editing && editing.cellElement) {
@@ -1694,7 +1786,7 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
1694
1786
  ]);
1695
1787
  const formValues = useMemo3(() => {
1696
1788
  if (originalRow) {
1697
- return getSnapshot(originalRow);
1789
+ return getSnapshot2(originalRow);
1698
1790
  }
1699
1791
  }, [
1700
1792
  originalRow
@@ -1722,19 +1814,19 @@ var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
1722
1814
  if (!editing) {
1723
1815
  return null;
1724
1816
  }
1725
- return /* @__PURE__ */ React5.createElement(Popover2.Root, {
1817
+ return /* @__PURE__ */ React6.createElement(Popover3.Root, {
1726
1818
  open: editing !== null,
1727
1819
  onOpenChange: handleOpenChange
1728
- }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
1820
+ }, /* @__PURE__ */ React6.createElement(Popover3.VirtualTrigger, {
1729
1821
  virtualRef: cellRef
1730
- }), /* @__PURE__ */ React5.createElement(Popover2.Content, {
1822
+ }), /* @__PURE__ */ React6.createElement(Popover3.Content, {
1731
1823
  tabIndex: -1,
1732
1824
  classNames: "popover-card-width"
1733
- }, /* @__PURE__ */ React5.createElement(Popover2.Arrow, null), /* @__PURE__ */ React5.createElement(Form2, {
1825
+ }, /* @__PURE__ */ React6.createElement(Popover3.Arrow, null), /* @__PURE__ */ React6.createElement(Popover3.Viewport, null, /* @__PURE__ */ React6.createElement(Form2, {
1734
1826
  values: formValues,
1735
1827
  schema: narrowedSchema,
1736
1828
  onSave: handleSave
1737
- })));
1829
+ }))));
1738
1830
  } finally {
1739
1831
  _effect.f();
1740
1832
  }
@@ -1788,9 +1880,9 @@ var createOption = (text) => ({
1788
1880
  });
1789
1881
  var isCreateOption = (data) => typeof data === "object" && data[newValue];
1790
1882
  var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gridScope }) => {
1791
- var _effect = _useSignals6();
1883
+ var _effect = _useSignals7();
1792
1884
  try {
1793
- const { editing } = useGridContext3("TableValueEditor", __gridScope);
1885
+ const { editing } = useGridContext4("TableValueEditor", __gridScope);
1794
1886
  const fieldProjection = useMemo4(() => {
1795
1887
  if (!model || !editing) {
1796
1888
  return;
@@ -1800,7 +1892,7 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
1800
1892
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
1801
1893
  invariant3(fieldProjection2, void 0, {
1802
1894
  F: __dxlog_file4,
1803
- L: 73,
1895
+ L: 74,
1804
1896
  S: void 0,
1805
1897
  A: [
1806
1898
  "fieldProjection",
@@ -1813,14 +1905,14 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
1813
1905
  editing
1814
1906
  ]);
1815
1907
  if (fieldProjection?.props.type === TypeEnum4.Array) {
1816
- return /* @__PURE__ */ React6.createElement(FormCellEditor, {
1908
+ return /* @__PURE__ */ React7.createElement(FormCellEditor, {
1817
1909
  fieldProjection,
1818
1910
  model,
1819
1911
  schema,
1820
1912
  __gridScope
1821
1913
  });
1822
1914
  }
1823
- return /* @__PURE__ */ React6.createElement(TableCellEditor, {
1915
+ return /* @__PURE__ */ React7.createElement(TableCellEditor, {
1824
1916
  model,
1825
1917
  modals,
1826
1918
  onEnter,
@@ -1833,11 +1925,12 @@ var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gr
1833
1925
  }
1834
1926
  };
1835
1927
  var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
1836
- var _effect = _useSignals6();
1928
+ var _effect = _useSignals7();
1837
1929
  try {
1838
- const { id: gridId, editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
1930
+ const { id: gridId, editing, setEditing } = useGridContext4("TableCellEditor", __gridScope);
1839
1931
  const suppressNextBlur = useRef2(false);
1840
1932
  const { themeMode } = useThemeContext();
1933
+ const [_validationError, setValidationError] = useState2(null);
1841
1934
  const fieldProjection = useMemo4(() => {
1842
1935
  if (!model || !editing) {
1843
1936
  return;
@@ -1847,7 +1940,7 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1847
1940
  const fieldProjection2 = model.projection.getFieldProjection(field.id);
1848
1941
  invariant3(fieldProjection2, void 0, {
1849
1942
  F: __dxlog_file4,
1850
- L: 114,
1943
+ L: 116,
1851
1944
  S: void 0,
1852
1945
  A: [
1853
1946
  "fieldProjection",
@@ -1859,15 +1952,21 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1859
1952
  model,
1860
1953
  editing
1861
1954
  ]);
1862
- const handleEnter = useCallback4((value) => {
1955
+ const handleEnter = useCallback4(async (value) => {
1863
1956
  if (!model || !editing) {
1864
1957
  return;
1865
1958
  }
1866
1959
  const cell = parseCellIndex2(editing.index);
1867
- model.setCellData(cell, value);
1868
- onEnter?.(cell);
1869
- onFocus?.();
1870
- setEditing(null);
1960
+ const result = await model.validateCellData(cell, value);
1961
+ if (result.valid) {
1962
+ setValidationError(null);
1963
+ model.setCellData(cell, value);
1964
+ onEnter?.(cell);
1965
+ onFocus?.();
1966
+ setEditing(null);
1967
+ } else {
1968
+ setValidationError(result.error);
1969
+ }
1871
1970
  }, [
1872
1971
  model,
1873
1972
  editing,
@@ -1875,37 +1974,49 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1875
1974
  onFocus,
1876
1975
  setEditing
1877
1976
  ]);
1878
- const handleBlur = useCallback4((value) => {
1977
+ const handleBlur = useCallback4(async (value) => {
1879
1978
  if (!model || !editing) {
1880
1979
  return;
1881
1980
  }
1882
1981
  if (suppressNextBlur.current) {
1883
1982
  suppressNextBlur.current = false;
1884
- return;
1885
- }
1886
- const cell = parseCellIndex2(editing.index);
1887
- if (value !== void 0) {
1888
- model.setCellData(cell, value);
1889
1983
  }
1890
1984
  }, [
1891
1985
  model,
1892
1986
  editing
1893
1987
  ]);
1894
- const handleClose = useCallback4((value, event) => {
1988
+ const handleClose = useCallback4(async (value, event) => {
1895
1989
  if (!model || !editing || !fieldProjection) {
1896
1990
  return;
1897
1991
  }
1898
1992
  const cell = parseCellIndex2(editing.index);
1899
- onEnter?.(cell);
1900
- if (event && onFocus) {
1901
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
1993
+ if (value !== void 0) {
1994
+ const result = await model.validateCellData(cell, value);
1995
+ if (result.valid) {
1996
+ setValidationError(null);
1997
+ model.setCellData(cell, value);
1998
+ setEditing(null);
1999
+ onEnter?.(cell);
2000
+ if (event && onFocus) {
2001
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
2002
+ }
2003
+ } else {
2004
+ setValidationError(result.error);
2005
+ }
2006
+ } else {
2007
+ setValidationError(null);
2008
+ setEditing(null);
2009
+ if (event && onFocus) {
2010
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
2011
+ }
1902
2012
  }
1903
2013
  }, [
1904
2014
  model,
1905
2015
  editing,
1906
2016
  onFocus,
1907
2017
  onEnter,
1908
- fieldProjection
2018
+ fieldProjection,
2019
+ setEditing
1909
2020
  ]);
1910
2021
  const extension = useMemo4(() => {
1911
2022
  if (!fieldProjection) {
@@ -1942,9 +2053,9 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1942
2053
  return;
1943
2054
  }
1944
2055
  if (mode === "single-select") {
1945
- handleEnter(ids[0]);
2056
+ void handleEnter(ids[0]);
1946
2057
  } else {
1947
- handleEnter(ids);
2058
+ void handleEnter(ids);
1948
2059
  }
1949
2060
  }
1950
2061
  }
@@ -1965,11 +2076,11 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
1965
2076
  modals.openCreateRef(props.referenceSchema, document.querySelector(cellQuery(editing.index, gridId)), {
1966
2077
  [field.referencePath]: data.text
1967
2078
  }, (data2) => {
1968
- handleEnter(data2);
2079
+ void handleEnter(data2);
1969
2080
  });
1970
2081
  }
1971
2082
  } else {
1972
- handleEnter(data);
2083
+ void handleEnter(data);
1973
2084
  }
1974
2085
  }
1975
2086
  }
@@ -2034,11 +2145,14 @@ var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }
2034
2145
  model,
2035
2146
  editing
2036
2147
  ]);
2037
- return /* @__PURE__ */ React6.createElement(GridCellEditor, {
2148
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(CellValidationMessage, {
2149
+ validationError: _validationError,
2150
+ __gridScope
2151
+ }), /* @__PURE__ */ React7.createElement(GridCellEditor, {
2038
2152
  extension,
2039
2153
  getCellContent,
2040
2154
  onBlur: handleBlur
2041
- });
2155
+ }));
2042
2156
  } finally {
2043
2157
  _effect.f();
2044
2158
  }
@@ -2071,9 +2185,9 @@ var determineNavigationDelta = ({ key, shift }) => {
2071
2185
  // packages/ui/react-ui-table/src/components/Table/Table.tsx
2072
2186
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
2073
2187
  var TableRoot = ({ children, role }) => {
2074
- var _effect = _useSignals7();
2188
+ var _effect = _useSignals8();
2075
2189
  try {
2076
- return /* @__PURE__ */ React7.createElement("div", {
2190
+ return /* @__PURE__ */ React8.createElement("div", {
2077
2191
  role: "none",
2078
2192
  className: mx2("relative !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
2079
2193
  }, children);
@@ -2081,10 +2195,10 @@ var TableRoot = ({ children, role }) => {
2081
2195
  _effect.f();
2082
2196
  }
2083
2197
  };
2084
- var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, onRowClick }, forwardedRef) => {
2085
- var _effect = _useSignals7();
2198
+ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
2199
+ var _effect = _useSignals8();
2086
2200
  try {
2087
- const [dxGrid, setDxGrid] = useState2(null);
2201
+ const [dxGrid, setDxGrid] = useState3(null);
2088
2202
  const { hasAttention } = useAttention(model?.id ?? "table");
2089
2203
  const { t } = useTranslation3(translationKey);
2090
2204
  const modals = useMemo5(() => new ModalController(), []);
@@ -2276,14 +2390,20 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
2276
2390
  const space = model.space;
2277
2391
  invariant4(space, void 0, {
2278
2392
  F: __dxlog_file5,
2279
- L: 309,
2393
+ L: 311,
2280
2394
  S: void 0,
2281
2395
  A: [
2282
2396
  "space",
2283
2397
  ""
2284
2398
  ]
2285
2399
  });
2286
- const schema2 = space.db.schemaRegistry.getSchema(props.referenceSchema);
2400
+ let schema2;
2401
+ if (client) {
2402
+ schema2 = client.graph.schemaRegistry.getSchema(props.referenceSchema);
2403
+ }
2404
+ if (!schema2) {
2405
+ schema2 = space.db.schemaRegistry.getSchema(props.referenceSchema);
2406
+ }
2287
2407
  if (schema2) {
2288
2408
  const { objects } = await space.db.query(Filter.type(schema2)).run();
2289
2409
  const options = objects.map((obj) => {
@@ -2310,24 +2430,25 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
2310
2430
  return [];
2311
2431
  }, [
2312
2432
  model,
2433
+ client,
2313
2434
  t
2314
2435
  ]);
2315
2436
  if (!model || !modals) {
2316
- return /* @__PURE__ */ React7.createElement("span", {
2437
+ return /* @__PURE__ */ React8.createElement("span", {
2317
2438
  role: "none",
2318
2439
  className: "attention-surface"
2319
2440
  });
2320
2441
  }
2321
- return /* @__PURE__ */ React7.createElement(Grid.Root, {
2442
+ return /* @__PURE__ */ React8.createElement(Grid.Root, {
2322
2443
  id: model.id ?? "table-grid"
2323
- }, /* @__PURE__ */ React7.createElement(TableValueEditor, {
2444
+ }, /* @__PURE__ */ React8.createElement(TableValueEditor, {
2324
2445
  model,
2325
2446
  modals,
2326
2447
  schema,
2327
2448
  onEnter: handleEnter,
2328
2449
  onFocus: handleFocus,
2329
2450
  onQuery: handleQuery
2330
- }), /* @__PURE__ */ React7.createElement(Grid.Content, {
2451
+ }), /* @__PURE__ */ React8.createElement(Grid.Content, {
2331
2452
  className: mx2("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
2332
2453
  frozen,
2333
2454
  // getCells={getCells}
@@ -2340,17 +2461,17 @@ var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttenti
2340
2461
  onKeyDown: handleKeyDown,
2341
2462
  onWheelCapture: handleWheel,
2342
2463
  ref: setDxGrid
2343
- }), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
2464
+ }), /* @__PURE__ */ React8.createElement(RowActionsMenu, {
2344
2465
  model,
2345
2466
  modals
2346
- }), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
2467
+ }), /* @__PURE__ */ React8.createElement(ColumnActionsMenu, {
2347
2468
  model,
2348
2469
  modals
2349
- }), /* @__PURE__ */ React7.createElement(ColumnSettings, {
2470
+ }), /* @__PURE__ */ React8.createElement(ColumnSettings, {
2350
2471
  model,
2351
2472
  modals,
2352
2473
  onNewColumn: handleNewColumn
2353
- }), /* @__PURE__ */ React7.createElement(CreateRefPanel, {
2474
+ }), /* @__PURE__ */ React8.createElement(CreateRefPanel, {
2354
2475
  model,
2355
2476
  modals
2356
2477
  }));
@@ -2364,22 +2485,23 @@ var Table = {
2364
2485
  };
2365
2486
 
2366
2487
  // packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
2367
- import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
2368
- import React8, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
2488
+ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
2489
+ import React9, { useRef as useRef3, useMemo as useMemo6, useCallback as useCallback6 } from "react";
2369
2490
  import { useDefaultValue } from "@dxos/react-ui";
2370
2491
  import { mx as mx3 } from "@dxos/react-ui-theme";
2371
2492
 
2372
2493
  // packages/ui/react-ui-table/src/hooks/useTableModel.ts
2373
- import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
2494
+ import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
2374
2495
  import { effect as effect3 } from "@preact/signals-core";
2375
- import { useEffect as useEffect4, useState as useState3 } from "react";
2496
+ import orderBy2 from "lodash.orderby";
2497
+ import { useEffect as useEffect4, useState as useState4 } from "react";
2376
2498
  import { fullyQualifiedId, getSpace } from "@dxos/react-client/echo";
2377
2499
  import { useSelectionActions } from "@dxos/react-ui-attention";
2378
2500
  import { isNonNullable } from "@dxos/util";
2379
2501
  var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
2380
- var _effect = _useSignals8();
2502
+ var _effect = _useSignals9();
2381
2503
  try {
2382
- const [model, setModel] = useState3();
2504
+ const [model, setModel] = useState4();
2383
2505
  useEffect4(() => {
2384
2506
  if (!table || !projection) {
2385
2507
  return;
@@ -2412,7 +2534,12 @@ var useTableModel = ({ table, projection, rows, rowActions, features, onSelectio
2412
2534
  ]);
2413
2535
  useEffect4(() => {
2414
2536
  if (rows) {
2415
- model?.setRows(rows);
2537
+ const sortedRows = orderBy2(rows, [
2538
+ (row) => String(row.id)
2539
+ ], [
2540
+ "asc"
2541
+ ]);
2542
+ model?.setRows(sortedRows);
2416
2543
  }
2417
2544
  }, [
2418
2545
  model,
@@ -2449,7 +2576,7 @@ var useTableModel = ({ table, projection, rows, rowActions, features, onSelectio
2449
2576
 
2450
2577
  // packages/ui/react-ui-table/src/components/Table/DynamicTable.tsx
2451
2578
  var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
2452
- var _effect = _useSignals9();
2579
+ var _effect = _useSignals10();
2453
2580
  try {
2454
2581
  const { table, projection } = useMemo6(() => {
2455
2582
  const props2 = getBaseSchema({
@@ -2498,13 +2625,13 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
2498
2625
  }, [
2499
2626
  model
2500
2627
  ]);
2501
- return /* @__PURE__ */ React8.createElement("div", {
2628
+ return /* @__PURE__ */ React9.createElement("div", {
2502
2629
  role: "none",
2503
2630
  className: mx3("is-full bs-full grow grid", classNames)
2504
- }, /* @__PURE__ */ React8.createElement("div", {
2631
+ }, /* @__PURE__ */ React9.createElement("div", {
2505
2632
  role: "none",
2506
2633
  className: "grid min-bs-0 overflow-hidden"
2507
- }, /* @__PURE__ */ React8.createElement(Table.Root, null, /* @__PURE__ */ React8.createElement(Table.Main, {
2634
+ }, /* @__PURE__ */ React9.createElement(Table.Root, null, /* @__PURE__ */ React9.createElement(Table.Main, {
2508
2635
  ref: tableRef,
2509
2636
  model,
2510
2637
  presentation,
@@ -2517,10 +2644,10 @@ var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, prop
2517
2644
  };
2518
2645
 
2519
2646
  // packages/ui/react-ui-table/src/components/TableToolbar/TableToolbar.tsx
2520
- import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
2647
+ import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
2521
2648
  import { Rx } from "@effect-rx/rx-react";
2522
- import React9, { useMemo as useMemo7 } from "react";
2523
- import { live as live4 } from "@dxos/live-object";
2649
+ import React10, { useMemo as useMemo7 } from "react";
2650
+ import { live as live3 } from "@dxos/live-object";
2524
2651
  import { createGapSeparator, createMenuAction, MenuProvider, ToolbarMenu, useMenuActions } from "@dxos/react-ui-menu";
2525
2652
  import { rxFromSignal } from "@dxos/react-ui-menu";
2526
2653
  var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
@@ -2569,9 +2696,9 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
2569
2696
  };
2570
2697
  });
2571
2698
  var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
2572
- var _effect = _useSignals10();
2699
+ var _effect = _useSignals11();
2573
2700
  try {
2574
- const state = useMemo7(() => live4({
2701
+ const state = useMemo7(() => live3({
2575
2702
  viewDirty
2576
2703
  }), []);
2577
2704
  const actionsCreator = useMemo7(() => createTableToolbarActions({
@@ -2586,10 +2713,10 @@ var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, custom
2586
2713
  customActions
2587
2714
  ]);
2588
2715
  const menu = useMenuActions(actionsCreator);
2589
- return /* @__PURE__ */ React9.createElement(MenuProvider, {
2716
+ return /* @__PURE__ */ React10.createElement(MenuProvider, {
2590
2717
  ...menu,
2591
2718
  attendableId
2592
- }, /* @__PURE__ */ React9.createElement(ToolbarMenu, {
2719
+ }, /* @__PURE__ */ React10.createElement(ToolbarMenu, {
2593
2720
  classNames
2594
2721
  }));
2595
2722
  } finally {