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