@dxos/react-ui-table 0.8.4-main.406dc2a → 0.8.4-main.548089c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/lib/browser/{chunk-4K7JPALT.mjs → chunk-2PFAPQL4.mjs} +3 -3
  2. package/dist/lib/browser/chunk-2PFAPQL4.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-OZTXLZGM.mjs → chunk-GS2UNGJK.mjs} +434 -463
  4. package/dist/lib/browser/chunk-GS2UNGJK.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +41 -38
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +4 -4
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types/index.mjs +1 -1
  11. package/dist/lib/node-esm/{chunk-MK6OVUF6.mjs → chunk-6POOFFYF.mjs} +3 -3
  12. package/dist/lib/node-esm/chunk-6POOFFYF.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-S56Z4V4X.mjs → chunk-TRR3C5NX.mjs} +434 -463
  14. package/dist/lib/node-esm/chunk-TRR3C5NX.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +41 -38
  16. package/dist/lib/node-esm/index.mjs.map +3 -3
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +4 -4
  19. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/types/index.mjs +1 -1
  21. package/dist/types/src/components/Table/Relations.stories.d.ts +2 -3
  22. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  24. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +2 -2
  26. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  27. package/dist/types/src/hooks/useTableModel.d.ts +2 -2
  28. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  29. package/dist/types/src/model/table-model.d.ts +3 -3
  30. package/dist/types/src/model/table-model.d.ts.map +1 -1
  31. package/dist/types/src/model/table-sorting.d.ts +2 -2
  32. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  33. package/dist/types/src/testing/useTestTableModel.d.ts +2 -2
  34. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  35. package/dist/types/src/types/schema.d.ts +3 -3
  36. package/dist/types/src/types/schema.d.ts.map +1 -1
  37. package/dist/types/src/util/dynamic-table.d.ts +2 -2
  38. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +41 -40
  41. package/src/components/Table/DynamicTable.stories.tsx +3 -3
  42. package/src/components/Table/Relations.stories.tsx +16 -22
  43. package/src/components/Table/RowActionsMenu.tsx +21 -13
  44. package/src/components/Table/Table.stories.tsx +12 -12
  45. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +6 -5
  46. package/src/components/TableToolbar/TableToolbar.tsx +31 -21
  47. package/src/hooks/useTableModel.ts +4 -4
  48. package/src/model/table-model.test.ts +2 -2
  49. package/src/model/table-model.ts +10 -7
  50. package/src/model/table-presentation.test.ts +2 -2
  51. package/src/model/table-sorting.ts +8 -8
  52. package/src/playwright/TableManager.ts +1 -1
  53. package/src/playwright/smoke.spec.ts +7 -5
  54. package/src/testing/useTestTableModel.ts +2 -2
  55. package/src/types/schema.ts +4 -4
  56. package/src/util/dynamic-table.ts +4 -5
  57. package/dist/lib/browser/chunk-4K7JPALT.mjs.map +0 -7
  58. package/dist/lib/browser/chunk-OZTXLZGM.mjs.map +0 -7
  59. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +0 -7
  60. package/dist/lib/node-esm/chunk-S56Z4V4X.mjs.map +0 -7
@@ -1,12 +1,12 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  schema_exports
4
- } from "./chunk-MK6OVUF6.mjs";
4
+ } from "./chunk-6POOFFYF.mjs";
5
5
 
6
6
  // src/util/dynamic-table.ts
7
7
  import { Filter, Obj, Query } from "@dxos/echo";
8
8
  import { getTypename, toJsonSchema } from "@dxos/echo/internal";
9
- import { ProjectionModel, createView, getSchemaFromPropertyDefinitions } from "@dxos/schema";
9
+ import { ProjectionModel, View, getSchemaFromPropertyDefinitions } from "@dxos/schema";
10
10
  var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
11
11
  if (typename && properties) {
12
12
  const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
@@ -32,7 +32,7 @@ var makeDynamicTable = ({ jsonSchema, properties }) => {
32
32
  const table = Obj.make(schema_exports.Table, {
33
33
  sizes: {}
34
34
  });
35
- const view = createView({
35
+ const view = View.make({
36
36
  query: Query.select(Filter.everything()),
37
37
  jsonSchema,
38
38
  presentation: table,
@@ -279,7 +279,6 @@ import { FormatEnum as FormatEnum2, getSchema, getValue as getValue2, setValue,
279
279
  import { invariant } from "@dxos/invariant";
280
280
  import { ObjectId } from "@dxos/keys";
281
281
  import { getSnapshot, isLiveObject } from "@dxos/live-object";
282
- import { fullyQualifiedId } from "@dxos/react-client/echo";
283
282
  import { formatForEditing, parseValue } from "@dxos/react-ui-form";
284
283
  import { ProjectionModel as ProjectionModel2, validateSchema } from "@dxos/schema";
285
284
 
@@ -302,20 +301,34 @@ var extractTagIds = (value) => {
302
301
  // src/model/selection-model.ts
303
302
  import { computed, effect, signal } from "@preact/signals-core";
304
303
  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
- }
318
304
  var SelectionModel = class extends Resource {
305
+ _rows;
306
+ _selectionMode;
307
+ _initialSelection;
308
+ _onSelectionChanged;
309
+ _selection;
310
+ _validSelectedIds = computed(() => {
311
+ const rows = this._rows.value;
312
+ if (!rows) {
313
+ return /* @__PURE__ */ new Set();
314
+ }
315
+ const validIds = new Set(rows.map((row) => row.id));
316
+ return new Set([
317
+ ...this._selection.value
318
+ ].filter((id) => validIds.has(id)));
319
+ });
320
+ _hasSelection = computed(() => this._validSelectedIds.value.size > 0);
321
+ _allSelected = computed(() => {
322
+ const rows = this._rows.value;
323
+ if (rows.length === 0) {
324
+ return false;
325
+ }
326
+ return rows.every((row) => this._selection.value.has(row.id));
327
+ });
328
+ constructor(_rows, _selectionMode, _initialSelection, _onSelectionChanged) {
329
+ super(), this._rows = _rows, this._selectionMode = _selectionMode, this._initialSelection = _initialSelection, this._onSelectionChanged = _onSelectionChanged;
330
+ this._selection = signal(new Set(this._initialSelection));
331
+ }
319
332
  async _open() {
320
333
  const selectionWatcher = effect(() => {
321
334
  touch(this._selection.value);
@@ -338,59 +351,45 @@ var SelectionModel = class extends Resource {
338
351
  get selectionMode() {
339
352
  return this._selectionMode;
340
353
  }
341
- constructor(_rows, _selectionMode, _initialSelection, _onSelectionChanged) {
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(() => {
346
- const rows = this._rows.value;
347
- if (!rows) {
348
- return /* @__PURE__ */ new Set();
349
- }
350
- const validIds = new Set(rows.map((row) => row.id));
351
- return new Set([
352
- ...this._selection.value
353
- ].filter((id) => validIds.has(id)));
354
- }), this._hasSelection = computed(() => this._validSelectedIds.value.size > 0), this._allSelected = computed(() => {
355
- const rows = this._rows.value;
356
- if (rows.length === 0) {
357
- return false;
354
+ getSelectedRows = () => {
355
+ const selectedIds = this._validSelectedIds.value;
356
+ return this._rows.value.filter((row) => selectedIds.has(row.id));
357
+ };
358
+ isRowIndexSelected = (rowIndex) => {
359
+ const row = this._rows.value[rowIndex];
360
+ return this._selection.value.has(row.id);
361
+ };
362
+ isObjectSelected = (object) => {
363
+ return this._selection.value.has(object.id);
364
+ };
365
+ //
366
+ // Manipulation
367
+ //
368
+ toggleSelectionForRowIndex = (rowIndex) => {
369
+ const row = this._rows.value[rowIndex];
370
+ const newSelection = new Set(this._selection.value);
371
+ if (newSelection.has(row.id)) {
372
+ newSelection.delete(row.id);
373
+ } else {
374
+ if (this._selectionMode === "single") {
375
+ newSelection.clear();
358
376
  }
359
- return rows.every((row) => this._selection.value.has(row.id));
360
- }), this.getSelectedRows = () => {
361
- const selectedIds = this._validSelectedIds.value;
362
- return this._rows.value.filter((row) => selectedIds.has(row.id));
363
- }, this.isRowIndexSelected = (rowIndex) => {
364
- const row = this._rows.value[rowIndex];
365
- return this._selection.value.has(row.id);
366
- }, this.isObjectSelected = (object) => {
367
- return this._selection.value.has(object.id);
368
- }, this.toggleSelectionForRowIndex = (rowIndex) => {
369
- const row = this._rows.value[rowIndex];
370
- const newSelection = new Set(this._selection.value);
371
- if (newSelection.has(row.id)) {
372
- newSelection.delete(row.id);
373
- } else {
374
- if (this._selectionMode === "single") {
375
- newSelection.clear();
376
- }
377
- newSelection.add(row.id);
377
+ newSelection.add(row.id);
378
+ }
379
+ this._selection.value = newSelection;
380
+ };
381
+ setSelection = (mode) => {
382
+ switch (mode) {
383
+ case "all": {
384
+ this._selection.value = new Set(this._rows.value.map((row) => row.id));
385
+ break;
378
386
  }
379
- this._selection.value = newSelection;
380
- }, this.setSelection = (mode) => {
381
- switch (mode) {
382
- case "all": {
383
- this._selection.value = new Set(this._rows.value.map((row) => row.id));
384
- break;
385
- }
386
- case "none": {
387
- this._selection.value = /* @__PURE__ */ new Set();
388
- break;
389
- }
387
+ case "none": {
388
+ this._selection.value = /* @__PURE__ */ new Set();
389
+ break;
390
390
  }
391
- };
392
- this._selection = signal(new Set(this._initialSelection));
393
- }
391
+ }
392
+ };
394
393
  };
395
394
 
396
395
  // src/model/table-sorting.ts
@@ -398,20 +397,34 @@ import { computed as computed2, signal as signal2 } from "@preact/signals-core";
398
397
  import orderBy from "lodash.orderby";
399
398
  import { FormatEnum, TypeEnum, getValue } from "@dxos/echo/internal";
400
399
  import { formatForDisplay } from "@dxos/react-ui-form";
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
400
+ var TableSorting = class {
401
+ _view;
402
+ _projection;
403
+ _displayToDataIndex = /* @__PURE__ */ new Map();
404
+ _rows;
405
+ _localSort = signal2(void 0);
406
+ _isDirty;
407
+ sortedRows;
408
+ constructor(rows, _view, _projection) {
409
+ this._view = _view;
410
+ this._projection = _projection;
411
+ this._rows = rows;
412
+ this._isDirty = computed2(() => {
413
+ const local = this._localSort.value;
414
+ const viewSort = this._view.sort?.[0];
415
+ if (local?.type === "cleared") {
416
+ return viewSort !== void 0;
417
+ }
418
+ if (local?.type === "active") {
419
+ if (!viewSort) {
420
+ return true;
421
+ }
422
+ return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
423
+ }
424
+ return false;
408
425
  });
409
- } else {
410
- obj[key] = value;
426
+ this.sortedRows = this.initialiseSortedRows();
411
427
  }
412
- return obj;
413
- }
414
- var TableSorting = class {
415
428
  /**
416
429
  * @reactive
417
430
  * @returns Local sort if present, falls back to view sort.
@@ -547,51 +560,9 @@ var TableSorting = class {
547
560
  value
548
561
  });
549
562
  }
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();
578
- }
579
563
  };
580
564
 
581
565
  // 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
- }
595
566
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
596
567
  var defaultFeatures = {
597
568
  selection: {
@@ -602,8 +573,71 @@ var defaultFeatures = {
602
573
  schemaEditable: false
603
574
  };
604
575
  var TableModel = class extends Resource2 {
576
+ _view;
577
+ _projection;
578
+ _table;
579
+ _visibleRange = signal3({
580
+ start: {
581
+ row: 0,
582
+ col: 0
583
+ },
584
+ end: {
585
+ row: 0,
586
+ col: 0
587
+ }
588
+ });
589
+ _onInsertRow;
590
+ _onDeleteRows;
591
+ _onDeleteColumn;
592
+ _onCellUpdate;
593
+ _onRowOrderChange;
594
+ _onRowAction;
595
+ _rowActions;
596
+ _features;
597
+ _rows = signal3([]);
598
+ _draftRows = signal3([]);
599
+ _sorting;
600
+ _pinnedRows;
601
+ _selection;
602
+ _columnMeta;
603
+ constructor({ view, schema, projection, features = {}, sorting = [], initialSelection = [], pinnedRows = {
604
+ top: [],
605
+ bottom: []
606
+ }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
607
+ super();
608
+ this._view = view;
609
+ this._projection = projection ?? new ProjectionModel2(schema, view.projection);
610
+ this._projection.normalizeView();
611
+ this._features = {
612
+ ...defaultFeatures,
613
+ ...features
614
+ };
615
+ invariant(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
616
+ F: __dxlog_file,
617
+ L: 148,
618
+ S: this,
619
+ A: [
620
+ "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
621
+ "'Single selection is not compatible with editable tables.'"
622
+ ]
623
+ });
624
+ this._sorting = new TableSorting(this._rows, this._view, this._projection);
625
+ if (sorting.length > 0) {
626
+ const [sort] = sorting;
627
+ this._sorting.setSort(sort.fieldId, sort.direction);
628
+ }
629
+ this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", initialSelection, () => this._onRowOrderChange?.());
630
+ this._pinnedRows = pinnedRows;
631
+ this._rowActions = rowActions;
632
+ this._onInsertRow = onInsertRow;
633
+ this._onDeleteRows = onDeleteRows;
634
+ this._onDeleteColumn = onDeleteColumn;
635
+ this._onCellUpdate = onCellUpdate;
636
+ this._onRowOrderChange = onRowOrderChange;
637
+ this._onRowAction = onRowAction;
638
+ }
605
639
  get id() {
606
- return fullyQualifiedId(this._view);
640
+ return Obj2.getDXN(this._view).toString();
607
641
  }
608
642
  get view() {
609
643
  return this._view;
@@ -611,7 +645,7 @@ var TableModel = class extends Resource2 {
611
645
  get table() {
612
646
  invariant(this._table, "Model not initialized", {
613
647
  F: __dxlog_file,
614
- L: 187,
648
+ L: 186,
615
649
  S: this,
616
650
  A: [
617
651
  "this._table",
@@ -650,7 +684,7 @@ var TableModel = class extends Resource2 {
650
684
  get columnMeta() {
651
685
  invariant(this._columnMeta, void 0, {
652
686
  F: __dxlog_file,
653
- L: 226,
687
+ L: 225,
654
688
  S: this,
655
689
  A: [
656
690
  "this._columnMeta",
@@ -676,7 +710,7 @@ var TableModel = class extends Resource2 {
676
710
  const presentation = this._view.presentation.target ?? await this._view.presentation.load();
677
711
  invariant(Obj2.instanceOf(schema_exports.Table, presentation), void 0, {
678
712
  F: __dxlog_file,
679
- L: 249,
713
+ L: 248,
680
714
  S: this,
681
715
  A: [
682
716
  "Obj.instanceOf(Table.Table, presentation)",
@@ -744,6 +778,17 @@ var TableModel = class extends Resource2 {
744
778
  });
745
779
  this._ctx.onDispose(draftRowsWatcher);
746
780
  }
781
+ //
782
+ // Data
783
+ //
784
+ setRows = (obj) => {
785
+ this._rows.value = obj;
786
+ };
787
+ getRowCount = () => this._rows.value.length;
788
+ /**
789
+ * @reactive
790
+ */
791
+ getDraftRowCount = () => this._draftRows.value.length;
747
792
  // TODO(ZaymonFC): Return .value instead of exposing the signal.
748
793
  get draftRows() {
749
794
  return this._draftRows;
@@ -762,6 +807,14 @@ var TableModel = class extends Resource2 {
762
807
  const validationErrors = draftRow.validationErrors || [];
763
808
  return validationErrors.some((error) => error.path === fieldPath);
764
809
  }
810
+ getColumnCount = () => this._projection?.fields.length ?? 0;
811
+ insertRow = () => {
812
+ const result = this._onInsertRow?.();
813
+ if (result === "draft" && this._draftRows.value.length === 0) {
814
+ this.createDraftRow();
815
+ }
816
+ return result ?? "final";
817
+ };
765
818
  createDraftRow() {
766
819
  if (!this._projection) {
767
820
  return;
@@ -801,6 +854,187 @@ var TableModel = class extends Resource2 {
801
854
  const schema = toEffectSchema(this._projection.baseSchema);
802
855
  return validateSchema(schema, data) || [];
803
856
  }
857
+ commitDraftRow = (draftRowIndex) => {
858
+ if (draftRowIndex < 0 || draftRowIndex >= this._draftRows.value.length) {
859
+ return false;
860
+ }
861
+ const draftRow = this._draftRows.value[draftRowIndex];
862
+ if (!draftRow.valid) {
863
+ return false;
864
+ }
865
+ const insertRowResult = this._onInsertRow?.(draftRow.data);
866
+ if (insertRowResult === "final") {
867
+ const newDraftRows = this._draftRows.value.filter((_, index) => index !== draftRowIndex);
868
+ this._draftRows.value = newDraftRows;
869
+ }
870
+ return insertRowResult === "final";
871
+ };
872
+ deleteRow = (rowIndex) => {
873
+ const row = this._sorting.getDataIndex(rowIndex);
874
+ const obj = this._rows.value[row];
875
+ const objectsToDelete = [];
876
+ if (this.features.selection.enabled && this._selection.hasSelection.value) {
877
+ const selectedRows = this._selection.getSelectedRows();
878
+ objectsToDelete.push(...selectedRows);
879
+ } else {
880
+ objectsToDelete.push(obj);
881
+ }
882
+ this._onDeleteRows?.(row, objectsToDelete);
883
+ };
884
+ handleRowAction = (actionId, rowIndex) => {
885
+ if (!this._onRowAction) {
886
+ return;
887
+ }
888
+ const row = this._sorting.getDataIndex(rowIndex);
889
+ const data = this._rows.value[row];
890
+ if (data) {
891
+ this._onRowAction(actionId, data);
892
+ }
893
+ };
894
+ getCellData = (cell) => {
895
+ const { col, row, plane } = cell;
896
+ const fields = this._projection?.fields ?? [];
897
+ if (col < 0 || col >= fields.length) {
898
+ return void 0;
899
+ }
900
+ const field = fields[col];
901
+ let value;
902
+ if (plane === "frozenRowsEnd") {
903
+ if (row >= 0 && row < this._draftRows.value.length) {
904
+ value = getValue2(this._draftRows.value[row].data, field.path);
905
+ } else {
906
+ return void 0;
907
+ }
908
+ } else {
909
+ const dataIndex = this._sorting.getDataIndex(row);
910
+ value = getValue2(this._rows.value[dataIndex], field.path);
911
+ }
912
+ if (value == null) {
913
+ return "";
914
+ }
915
+ const { props } = this._projection.getFieldProjection(field.id);
916
+ switch (props.format) {
917
+ case FormatEnum2.Ref: {
918
+ if (!field.referencePath) {
919
+ return "";
920
+ }
921
+ return getValue2(value.target, field.referencePath);
922
+ }
923
+ default: {
924
+ return formatForEditing({
925
+ type: props.type,
926
+ format: props.format,
927
+ value
928
+ });
929
+ }
930
+ }
931
+ };
932
+ validateCellData = async ({ col, row, plane }, value) => {
933
+ const fields = this._projection?.fields ?? [];
934
+ if (col < 0 || col >= fields.length) {
935
+ return {
936
+ valid: false,
937
+ error: "Invalid column index"
938
+ };
939
+ }
940
+ const field = fields[col];
941
+ const { props } = this._projection.getFieldProjection(field.id);
942
+ const transformedValue = editorTextToCellValue(props, value);
943
+ const isDraftRow = plane === "frozenRowsEnd";
944
+ if (isDraftRow) {
945
+ const isInvalidDraftRowIndex = row < 0 || row >= this._draftRows.value.length;
946
+ if (isInvalidDraftRowIndex) {
947
+ return {
948
+ valid: false,
949
+ error: "Invalid draft row index"
950
+ };
951
+ }
952
+ const draftRow = this._draftRows.value[row];
953
+ const snapshot = {
954
+ ...draftRow.data
955
+ };
956
+ setValue(snapshot, field.path, transformedValue);
957
+ const validationErrors = this.validateDraftRowData(snapshot);
958
+ if (validationErrors.length > 0) {
959
+ const error = validationErrors.find((err) => err.path === field.path);
960
+ if (error) {
961
+ return {
962
+ valid: false,
963
+ error: error.message
964
+ };
965
+ }
966
+ }
967
+ return {
968
+ valid: true
969
+ };
970
+ } else {
971
+ const rowIdx = this._sorting.getDataIndex(row);
972
+ const currentRow = this._rows.value[rowIdx];
973
+ invariant(currentRow, "Invalid row index", {
974
+ F: __dxlog_file,
975
+ L: 525,
976
+ S: this,
977
+ A: [
978
+ "currentRow",
979
+ "'Invalid row index'"
980
+ ]
981
+ });
982
+ const snapshot = getSnapshot(currentRow);
983
+ setValue(snapshot, field.path, transformedValue);
984
+ const schema = getSchema(currentRow);
985
+ invariant(schema, void 0, {
986
+ F: __dxlog_file,
987
+ L: 531,
988
+ S: this,
989
+ A: [
990
+ "schema",
991
+ ""
992
+ ]
993
+ });
994
+ const validationResult = validateSchema(schema, snapshot);
995
+ if (validationResult && validationResult.length > 0) {
996
+ const error = validationResult[0];
997
+ invariant(error.path === field.path, void 0, {
998
+ F: __dxlog_file,
999
+ L: 536,
1000
+ S: this,
1001
+ A: [
1002
+ "error.path === field.path",
1003
+ ""
1004
+ ]
1005
+ });
1006
+ return {
1007
+ valid: false,
1008
+ error: error.message
1009
+ };
1010
+ }
1011
+ return {
1012
+ valid: true
1013
+ };
1014
+ }
1015
+ };
1016
+ setCellData = (cell, value) => {
1017
+ const { col, row, plane } = cell;
1018
+ const fields = this._projection?.fields ?? [];
1019
+ if (col < 0 || col >= fields.length) {
1020
+ return;
1021
+ }
1022
+ const field = fields[col];
1023
+ const { props } = this._projection.getFieldProjection(field.id);
1024
+ const transformedValue = editorTextToCellValue(props, value);
1025
+ if (props.format === FormatEnum2.Ref && !isLiveObject(value)) {
1026
+ return;
1027
+ }
1028
+ if (plane === "frozenRowsEnd") {
1029
+ if (row >= 0 && row < this._draftRows.value.length) {
1030
+ setValue(this._draftRows.value[row].data, field.path, transformedValue);
1031
+ this.validateDraftRow(row);
1032
+ }
1033
+ } else {
1034
+ const rowIdx = this._sorting.getDataIndex(row);
1035
+ setValue(this._rows.value[rowIdx], field.path, transformedValue);
1036
+ }
1037
+ };
804
1038
  /**
805
1039
  * Updates a cell's value using a transform function.
806
1040
  * @param {DxGridPlanePosition} position - The position of the cell to update.
@@ -881,240 +1115,6 @@ var TableModel = class extends Resource2 {
881
1115
  saveView() {
882
1116
  this._sorting.save();
883
1117
  }
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;
1117
- }
1118
1118
  };
1119
1119
  var editorTextToCellValue = (props, value) => {
1120
1120
  switch (props.format) {
@@ -1149,83 +1149,68 @@ var editorTextToCellValue = (props, value) => {
1149
1149
 
1150
1150
  // src/model/modal-controller.ts
1151
1151
  import { signal as signal4 } from "@preact/signals-core";
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
- }
1165
1152
  var ModalController = class {
1153
+ _state = signal4({
1154
+ type: "closed"
1155
+ });
1156
+ _triggerRef = {
1157
+ current: null
1158
+ };
1166
1159
  get state() {
1167
1160
  return this._state;
1168
1161
  }
1169
1162
  get trigger() {
1170
1163
  return this._triggerRef;
1171
1164
  }
1172
- constructor() {
1173
- _define_property4(this, "_state", signal4({
1174
- type: "closed"
1175
- }));
1176
- _define_property4(this, "_triggerRef", {
1177
- current: null
1178
- });
1179
- _define_property4(this, "setTrigger", (trigger) => {
1180
- this._triggerRef.current = trigger;
1181
- });
1182
- _define_property4(this, "showRowMenu", (rowIndex) => {
1183
- this._state.value = {
1184
- type: "row",
1185
- rowIndex
1186
- };
1187
- });
1188
- _define_property4(this, "showColumnMenu", (fieldId) => {
1189
- this._state.value = {
1190
- type: "column",
1191
- fieldId
1192
- };
1193
- });
1194
- _define_property4(this, "showColumnCreator", () => {
1195
- this._state.value = {
1196
- type: "columnSettings",
1197
- mode: {
1198
- type: "create"
1199
- }
1200
- };
1201
- });
1202
- _define_property4(this, "showReferencePanel", (targetId, schemaId) => {
1203
- this._state.value = {
1204
- type: "refPanel",
1205
- targetId,
1206
- typename: schemaId
1207
- };
1208
- });
1209
- _define_property4(this, "openColumnSettings", () => {
1210
- if (this._state.value.type === "column") {
1211
- const fieldId = this._state.value.fieldId;
1212
- requestAnimationFrame(() => {
1213
- this._state.value = {
1214
- type: "columnSettings",
1215
- mode: {
1216
- type: "edit",
1217
- fieldId
1218
- }
1219
- };
1220
- });
1165
+ setTrigger = (trigger) => {
1166
+ this._triggerRef.current = trigger;
1167
+ };
1168
+ showRowMenu = (rowIndex) => {
1169
+ this._state.value = {
1170
+ type: "row",
1171
+ rowIndex
1172
+ };
1173
+ };
1174
+ showColumnMenu = (fieldId) => {
1175
+ this._state.value = {
1176
+ type: "column",
1177
+ fieldId
1178
+ };
1179
+ };
1180
+ showColumnCreator = () => {
1181
+ this._state.value = {
1182
+ type: "columnSettings",
1183
+ mode: {
1184
+ type: "create"
1221
1185
  }
1222
- });
1223
- _define_property4(this, "close", () => {
1224
- this._state.value = {
1225
- type: "closed"
1226
- };
1227
- });
1228
- }
1186
+ };
1187
+ };
1188
+ showReferencePanel = (targetId, schemaId) => {
1189
+ this._state.value = {
1190
+ type: "refPanel",
1191
+ targetId,
1192
+ typename: schemaId
1193
+ };
1194
+ };
1195
+ openColumnSettings = () => {
1196
+ if (this._state.value.type === "column") {
1197
+ const fieldId = this._state.value.fieldId;
1198
+ requestAnimationFrame(() => {
1199
+ this._state.value = {
1200
+ type: "columnSettings",
1201
+ mode: {
1202
+ type: "edit",
1203
+ fieldId
1204
+ }
1205
+ };
1206
+ });
1207
+ }
1208
+ };
1209
+ close = () => {
1210
+ this._state.value = {
1211
+ type: "closed"
1212
+ };
1213
+ };
1229
1214
  };
1230
1215
 
1231
1216
  // src/model/table-presentation.ts
@@ -1237,20 +1222,23 @@ import { cellClassesForFieldType, formatForDisplay as formatForDisplay2 } from "
1237
1222
  import { toPlaneCellIndex } from "@dxos/react-ui-grid";
1238
1223
  import { mx } from "@dxos/react-ui-theme";
1239
1224
  import { VIEW_FIELD_LIMIT } from "@dxos/schema";
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;
1250
- }
1251
- return obj;
1252
- }
1253
1225
  var TablePresentation = class {
1226
+ model;
1227
+ _visibleRange;
1228
+ fieldProjectionCache = /* @__PURE__ */ new Map();
1229
+ constructor(model, _visibleRange = signal5({
1230
+ start: {
1231
+ row: 0,
1232
+ col: 0
1233
+ },
1234
+ end: {
1235
+ row: 0,
1236
+ col: 0
1237
+ }
1238
+ })) {
1239
+ this.model = model;
1240
+ this._visibleRange = _visibleRange;
1241
+ }
1254
1242
  getCells(range, plane) {
1255
1243
  this.fieldProjectionCache.clear();
1256
1244
  let cells;
@@ -1636,23 +1624,6 @@ var TablePresentation = class {
1636
1624
  }
1637
1625
  return cells;
1638
1626
  }
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
- }
1656
1627
  };
1657
1628
  var cellClassesForRowSelection = (selected, selectionMode) => {
1658
1629
  if (!selected) {
@@ -1681,13 +1652,13 @@ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
1681
1652
  import { effect as effect3 } from "@preact/signals-core";
1682
1653
  import orderBy2 from "lodash.orderby";
1683
1654
  import { useEffect, useMemo, useState } from "react";
1684
- import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
1655
+ import { Obj as Obj4 } from "@dxos/echo";
1685
1656
  import { useSelected, useSelectionActions } from "@dxos/react-ui-attention";
1686
1657
  import { isNonNullable } from "@dxos/util";
1687
1658
  var useTableModel = ({ view, schema, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
1688
1659
  var _effect = _useSignals();
1689
1660
  try {
1690
- const selected = useSelected(view && fullyQualifiedId2(view), "multi");
1661
+ const selected = useSelected(view && Obj4.getDXN(view).toString(), "multi");
1691
1662
  const initialSelection = useMemo(() => selected, [
1692
1663
  view
1693
1664
  ]);
@@ -1766,12 +1737,12 @@ var useTableModel = ({ view, schema, projection, rows, rowActions, features, onS
1766
1737
 
1767
1738
  // src/hooks/useAddRow.ts
1768
1739
  import { useCallback } from "react";
1769
- import { Obj as Obj4 } from "@dxos/echo";
1740
+ import { Obj as Obj5 } from "@dxos/echo";
1770
1741
  var useAddRow = ({ space, schema }) => {
1771
1742
  return useCallback((data) => {
1772
1743
  if (space && schema) {
1773
1744
  try {
1774
- space.db.add(Obj4.make(schema, data ?? {}));
1745
+ space.db.add(Obj5.make(schema, data ?? {}));
1775
1746
  return "final";
1776
1747
  } catch (error) {
1777
1748
  return "draft";
@@ -1802,4 +1773,4 @@ export {
1802
1773
  useTableModel,
1803
1774
  useAddRow
1804
1775
  };
1805
- //# sourceMappingURL=chunk-S56Z4V4X.mjs.map
1776
+ //# sourceMappingURL=chunk-TRR3C5NX.mjs.map