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

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 (90) hide show
  1. package/dist/lib/browser/{chunk-5XLSHLOG.mjs → chunk-ZAOSIG3L.mjs} +382 -319
  2. package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +399 -380
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +4 -2
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-Y66YLSTC.mjs → chunk-ZOFFI3JJ.mjs} +382 -319
  9. package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +399 -380
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +4 -2
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -1
  16. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  17. package/dist/types/src/components/Table/ColumnSettings.d.ts +1 -1
  18. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  19. package/dist/types/src/components/Table/CreateRefPanel.d.ts +1 -1
  20. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
  23. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Table/{relations.stories.d.ts → Relations.stories.d.ts} +2 -2
  25. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  26. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  27. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  28. package/dist/types/src/components/Table/Table.d.ts +1 -0
  29. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  30. package/dist/types/src/components/Table/Table.stories.d.ts +1 -1
  31. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  33. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +5 -5
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -1
  37. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  38. package/dist/types/src/hooks/useTableModel.d.ts +1 -1
  39. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  40. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  41. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  42. package/dist/types/src/model/table-model.d.ts +3 -2
  43. package/dist/types/src/model/table-model.d.ts.map +1 -1
  44. package/dist/types/src/model/table-presentation.d.ts +2 -1
  45. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  46. package/dist/types/src/model/table-sorting.d.ts +2 -2
  47. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  48. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  49. package/dist/types/src/translations.d.ts +2 -2
  50. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  51. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  52. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  53. package/dist/types/src/util/table.d.ts +2 -1
  54. package/dist/types/src/util/table.d.ts.map +1 -1
  55. package/dist/types/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +46 -46
  57. package/src/components/Table/ColumnActionsMenu.tsx +1 -1
  58. package/src/components/Table/ColumnSettings.tsx +1 -1
  59. package/src/components/Table/CreateRefPanel.tsx +1 -1
  60. package/src/components/Table/DynamicTable.stories.tsx +3 -2
  61. package/src/components/Table/DynamicTable.tsx +4 -3
  62. package/src/components/Table/{relations.stories.tsx → Relations.stories.tsx} +12 -4
  63. package/src/components/Table/RowActionsMenu.tsx +3 -3
  64. package/src/components/Table/Table.stories.tsx +12 -7
  65. package/src/components/Table/Table.tsx +49 -43
  66. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  67. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +4 -3
  68. package/src/components/TableCellEditor/TableCellEditor.tsx +16 -20
  69. package/src/components/TableCellEditor/extension.ts +2 -2
  70. package/src/components/TableToolbar/TableToolbar.tsx +2 -2
  71. package/src/components/testing.ts +1 -1
  72. package/src/hooks/useTableModel.ts +1 -1
  73. package/src/model/modal-controller.ts +1 -1
  74. package/src/model/selection-model.ts +3 -2
  75. package/src/model/table-model.test.ts +2 -1
  76. package/src/model/table-model.ts +13 -10
  77. package/src/model/table-presentation.test.ts +3 -2
  78. package/src/model/table-presentation.ts +28 -6
  79. package/src/model/table-sorting.ts +3 -3
  80. package/src/playwright/smoke.spec.ts +92 -0
  81. package/src/testing/useTestTableModel.ts +3 -2
  82. package/src/translations.ts +2 -2
  83. package/src/util/dynamic-table.ts +2 -2
  84. package/src/util/schema.ts +1 -1
  85. package/src/util/table-buttons.ts +2 -1
  86. package/src/util/table-controls.ts +4 -1
  87. package/src/util/table.ts +7 -3
  88. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +0 -7
  89. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +0 -7
  90. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
@@ -11,11 +11,11 @@ import {
11
11
  type ActionGraphEdges,
12
12
  type ActionGraphNodes,
13
13
  type ActionGraphProps,
14
- createGapSeparator,
15
- createMenuAction,
16
14
  type MenuAction,
17
15
  MenuProvider,
18
16
  ToolbarMenu,
17
+ createGapSeparator,
18
+ createMenuAction,
19
19
  useMenuActions,
20
20
  } from '@dxos/react-ui-menu';
21
21
  import { rxFromSignal } from '@dxos/react-ui-menu';
@@ -5,7 +5,7 @@
5
5
  import { Schema } from 'effect';
6
6
  import { useEffect } from 'react';
7
7
 
8
- import { FormatEnum, ObjectId, setValue, TypedObject, TypeEnum } from '@dxos/echo-schema';
8
+ import { FormatEnum, ObjectId, TypeEnum, TypedObject, setValue } from '@dxos/echo-schema';
9
9
  import { live } from '@dxos/live-object';
10
10
  import { faker } from '@dxos/random';
11
11
  import { type ProjectionModel } from '@dxos/schema';
@@ -13,7 +13,7 @@ import { useSelected, useSelectionActions } from '@dxos/react-ui-attention';
13
13
  import { type DataType, type ProjectionModel } from '@dxos/schema';
14
14
  import { isNonNullable } from '@dxos/util';
15
15
 
16
- import { type TableRow, TableModel, type TableModelProps, type TableRowAction } from '../model';
16
+ import { TableModel, type TableModelProps, type TableRow, type TableRowAction } from '../model';
17
17
 
18
18
  export type UseTableModelParams<T extends TableRow = TableRow> = {
19
19
  view?: DataType.View;
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { signal } from '@preact/signals-core';
6
- import { type RefObject, type MutableRefObject } from 'react';
6
+ import { type MutableRefObject, type RefObject } from 'react';
7
7
 
8
8
  import { type Live } from '@dxos/live-object';
9
9
  import { log } from '@dxos/log';
@@ -2,13 +2,14 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { computed, effect, type Signal, signal, type ReadonlySignal } from '@preact/signals-core';
5
+ import { type ReadonlySignal, type Signal, computed, effect, signal } from '@preact/signals-core';
6
6
 
7
7
  import { Resource } from '@dxos/context';
8
8
 
9
- import { type TableRow } from './table-model';
10
9
  import { touch } from '../util';
11
10
 
11
+ import { type TableRow } from './table-model';
12
+
12
13
  export type SelectionMode = 'single' | 'multiple';
13
14
 
14
15
  export class SelectionModel<T extends TableRow> extends Resource {
@@ -14,9 +14,10 @@ import { live } from '@dxos/live-object';
14
14
  import { createEchoSchema } from '@dxos/live-object/testing';
15
15
  import { createView } from '@dxos/schema';
16
16
 
17
- import { TableModel, type TableModelProps } from './table-model';
18
17
  import { TableView } from '../types';
19
18
 
19
+ import { TableModel, type TableModelProps } from './table-model';
20
+
20
21
  // TODO(burdon): Tests are disabled in project.json since they bring in plugin deps.
21
22
  // Restore once factored out into react-ui-table.
22
23
 
@@ -2,40 +2,42 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { computed, effect, signal, type ReadonlySignal } from '@preact/signals-core';
5
+ import { type ReadonlySignal, computed, effect, signal } from '@preact/signals-core';
6
6
 
7
7
  import { Resource } from '@dxos/context';
8
8
  import { Obj, Ref } from '@dxos/echo';
9
9
  import {
10
10
  type FieldSortType,
11
11
  FormatEnum,
12
- getValue,
13
- setValue,
14
12
  type JsonProp,
15
- getSnapshot,
13
+ type JsonSchemaType,
16
14
  getSchema,
15
+ getSnapshot,
16
+ getValue,
17
+ setValue,
17
18
  toEffectSchema,
18
- type JsonSchemaType,
19
19
  } from '@dxos/echo-schema';
20
20
  import { invariant } from '@dxos/invariant';
21
21
  import { ObjectId } from '@dxos/keys';
22
22
  import { isLiveObject } from '@dxos/live-object';
23
23
  import { fullyQualifiedId } from '@dxos/react-client/echo';
24
+ import { type Label } from '@dxos/react-ui';
24
25
  import { formatForEditing, parseValue } from '@dxos/react-ui-form';
25
26
  import {
26
27
  type DxGridAxisMeta,
27
- type DxGridPlaneRange,
28
28
  type DxGridPlanePosition,
29
+ type DxGridPlaneRange,
29
30
  type DxGridPosition,
30
31
  } from '@dxos/react-ui-grid';
31
- import { type DataType, ProjectionModel, type PropertyType, validateSchema, type ValidationError } from '@dxos/schema';
32
+ import { type DataType, ProjectionModel, type PropertyType, type ValidationError, validateSchema } from '@dxos/schema';
32
33
 
33
- import { type SelectionMode, SelectionModel } from './selection-model';
34
- import { TableSorting } from './table-sorting';
35
34
  import { TableView } from '../types';
36
35
  import { touch } from '../util';
37
36
  import { extractTagIds } from '../util/tag';
38
37
 
38
+ import { type SelectionMode, SelectionModel } from './selection-model';
39
+ import { TableSorting } from './table-sorting';
40
+
39
41
  // Domain types for cell classification
40
42
  export type TableCellType = 'standard' | 'draft' | 'header';
41
43
 
@@ -53,7 +55,7 @@ export type TableRow = Record<JsonProp, any> & { id: string };
53
55
 
54
56
  export type TableRowAction = {
55
57
  id: string;
56
- translationKey: string;
58
+ label: Label;
57
59
  };
58
60
 
59
61
  export type TableFeatures = {
@@ -497,6 +499,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
497
499
  setValue(snapshot, field.path, transformedValue);
498
500
 
499
501
  const validationErrors = this.validateDraftRowData(snapshot);
502
+ // TODO(thure): These errors sometimes result in a useless message like “is missing” (what is missing?)
500
503
  if (validationErrors.length > 0) {
501
504
  const error = validationErrors.find((err) => err.path === field.path);
502
505
  if (error) {
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Schema } from 'effect';
6
- import { describe, expect, it, beforeEach } from 'vitest';
6
+ import { beforeEach, describe, expect, it } from 'vitest';
7
7
 
8
8
  import { Obj } from '@dxos/echo';
9
9
  import { TypedObject } from '@dxos/echo-schema';
@@ -11,9 +11,10 @@ import { live } from '@dxos/live-object';
11
11
  import { createEchoSchema } from '@dxos/live-object/testing';
12
12
  import { createView } from '@dxos/schema';
13
13
 
14
+ import { TableView } from '../types';
15
+
14
16
  import { TableModel, type TableModelProps } from './table-model';
15
17
  import { TablePresentation } from './table-presentation';
16
- import { TableView } from '../types';
17
18
 
18
19
  describe('TablePresentation', () => {
19
20
  describe('row reactivity', () => {
@@ -6,7 +6,7 @@ import { signal } from '@preact/signals-core';
6
6
  import { isNotNullable } from 'effect/Predicate';
7
7
 
8
8
  import { Obj } from '@dxos/echo';
9
- import { FormatEnum, getValue, TypeEnum } from '@dxos/echo-schema';
9
+ import { FormatEnum, TypeEnum, getValue } from '@dxos/echo-schema';
10
10
  import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
11
11
  import {
12
12
  type DxGridCellValue,
@@ -16,12 +16,13 @@ import {
16
16
  toPlaneCellIndex,
17
17
  } from '@dxos/react-ui-grid';
18
18
  import { mx } from '@dxos/react-ui-theme';
19
- import { VIEW_FIELD_LIMIT, type FieldType } from '@dxos/schema';
19
+ import { type FieldType, VIEW_FIELD_LIMIT } from '@dxos/schema';
20
20
 
21
- import { type SelectionMode } from './selection-model';
22
- import { type TableRow, type TableModel } from './table-model';
23
21
  import { tableButtons, tableControls } from '../util';
24
22
 
23
+ import { type SelectionMode } from './selection-model';
24
+ import { type TableModel, type TableRow } from './table-model';
25
+
25
26
  /**
26
27
  * Presentation layer for a table component, handling cell rendering and grid display logic.
27
28
  * Manages rendering of table cells, headers, selection columns, and action columns across
@@ -67,6 +68,9 @@ export class TablePresentation<T extends TableRow = TableRow> {
67
68
  case 'frozenRowsEnd':
68
69
  cells = this.getDraftRowCells(range);
69
70
  break;
71
+ case 'fixedEndStart':
72
+ cells = this.getDraftSelectCells(range);
73
+ break;
70
74
  case 'fixedEndEnd':
71
75
  cells = this.getDraftActionCells(range);
72
76
  break;
@@ -199,7 +203,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
199
203
  const targetObj = getValue(obj, field.path)?.target;
200
204
  if (targetObj) {
201
205
  const dxn = Obj.getDXN(targetObj)?.toString();
202
- 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>`;
206
+ cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button is-6 pli-[3px] pbe-[2px] min-bs-0 absolute inline-end-2 block-start-[.2rem]" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
203
207
  }
204
208
  }
205
209
 
@@ -278,6 +282,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
278
282
  for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
279
283
  const draftRow = draftRows[row];
280
284
  for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
285
+ const cellIndex = toPlaneCellIndex({ col, row });
281
286
  const field = fields[col];
282
287
  if (!field) {
283
288
  continue;
@@ -286,7 +291,6 @@ export class TablePresentation<T extends TableRow = TableRow> {
286
291
  this.createDataCell(cells, draftRow.data, field, col, row);
287
292
 
288
293
  if (this.model.hasDraftRowValidationError(row, field.path)) {
289
- const cellIndex = toPlaneCellIndex({ col, row });
290
294
  const cellValue = cells[cellIndex];
291
295
  if (cellValue) {
292
296
  const existingClasses = cellValue.className || '';
@@ -294,6 +298,8 @@ export class TablePresentation<T extends TableRow = TableRow> {
294
298
  cellValue.className = existingClasses ? `${existingClasses} ${draftClasses}` : draftClasses;
295
299
  }
296
300
  }
301
+
302
+ cells[cellIndex].className += ' !bg-toolbarSurface';
297
303
  }
298
304
  }
299
305
 
@@ -408,6 +414,22 @@ export class TablePresentation<T extends TableRow = TableRow> {
408
414
  value: '',
409
415
  readonly: true,
410
416
  accessoryHtml: tableButtons.saveDraftRow.render({ rowIndex: row, disabled }),
417
+ className: '!bg-toolbarSurface',
418
+ };
419
+ }
420
+
421
+ return cells;
422
+ }
423
+
424
+ private getDraftSelectCells(range: DxGridPlaneRange): DxGridPlaneCells {
425
+ const cells: DxGridPlaneCells = {};
426
+ const draftRows = this.model.draftRows.value;
427
+
428
+ for (let row = range.start.row; row <= range.end.row && row < draftRows.length; row++) {
429
+ cells[toPlaneCellIndex({ col: 0, row })] = {
430
+ value: '',
431
+ readonly: true,
432
+ className: '!bg-toolbarSurface',
411
433
  };
412
434
  }
413
435
 
@@ -2,12 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { computed, signal, type Signal, type ReadonlySignal } from '@preact/signals-core';
5
+ import { type ReadonlySignal, type Signal, computed, signal } from '@preact/signals-core';
6
6
  import orderBy from 'lodash.orderby';
7
7
 
8
- import { getValue, FormatEnum, TypeEnum, type SortDirectionType, type FieldSortType } from '@dxos/echo-schema';
8
+ import { type FieldSortType, FormatEnum, type SortDirectionType, TypeEnum, getValue } from '@dxos/echo-schema';
9
9
  import { formatForDisplay } from '@dxos/react-ui-form';
10
- import type { PropertyType, FieldType, DataType, ProjectionModel } from '@dxos/schema';
10
+ import type { DataType, FieldType, ProjectionModel, PropertyType } from '@dxos/schema';
11
11
 
12
12
  import { type TableRow } from './table-model';
13
13
 
@@ -4,11 +4,13 @@
4
4
 
5
5
  import { expect, test } from '@playwright/test';
6
6
 
7
+ import { type DxGrid } from '@dxos/lit-grid';
7
8
  import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
8
9
 
9
10
  import { TableManager } from './TableManager';
10
11
 
11
12
  const storyUrl = storybookUrl('ui-react-ui-table-table--default', 9004);
13
+ const relationsStoryUrl = storybookUrl('ui-react-ui-table-relations--default', 9004);
12
14
 
13
15
  // NOTE(ZaymonFC): This test suite relies on the faker seed being set to 0 in the story.
14
16
  test.describe('Table', () => {
@@ -183,4 +185,94 @@ test.describe('Table', () => {
183
185
 
184
186
  await page.close();
185
187
  });
188
+
189
+ test('extant relations work as expected', async ({ browser, browserName }) => {
190
+ test.skip(browserName === 'webkit');
191
+ const { page } = await setupPage(browser, { url: relationsStoryUrl });
192
+
193
+ // Wait for the page to load
194
+ await page.locator('dx-grid > .dx-grid').nth(1).waitFor({ state: 'visible' });
195
+
196
+ // Find the dx-grid element for the contactModel (second table)
197
+ // The contactModel is used in the second Table.Main component in the story
198
+ const dxGrid = page.locator('dx-grid').nth(1);
199
+ await dxGrid.waitFor({ state: 'visible' });
200
+
201
+ // Scroll to the last column (column 8)
202
+ await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
203
+ dxGridElement.scrollToColumn(8);
204
+ });
205
+
206
+ // Click on the cell at aria-rowindex=0 aria-colindex=8 to focus it
207
+ const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="8"]');
208
+ await targetCell.click();
209
+
210
+ // Click again to engage edit mode
211
+ await page.keyboard.press('Enter');
212
+ await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
213
+
214
+ // Type the first few letters of an org name.
215
+ const orgName =
216
+ (await page
217
+ .locator('dx-grid')
218
+ .nth(0)
219
+ .locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="0"] .dx-grid__cell__content')
220
+ .textContent()) ?? 'never';
221
+ await page.keyboard.type(orgName.substring(0, 4), { delay: 500 });
222
+
223
+ // Assert that there is an element with aria-selected on the page
224
+ await expect(page.locator('[role="option"][aria-selected]')).toBeVisible();
225
+
226
+ // Type the enter key
227
+ await page.keyboard.press('Enter');
228
+
229
+ // Assert that the cell element has the org name
230
+ await expect(targetCell).toHaveText(orgName);
231
+
232
+ await page.close();
233
+ });
234
+
235
+ test('new relations work as expected', async ({ browser, browserName }) => {
236
+ test.skip(browserName === 'webkit');
237
+ const { page } = await setupPage(browser, { url: relationsStoryUrl });
238
+
239
+ // Wait for the page to load
240
+ await page.locator('dx-grid > .dx-grid').nth(1).waitFor({ state: 'visible' });
241
+
242
+ // Find the dx-grid element for the contactModel (second table)
243
+ // The contactModel is used in the second Table.Main component in the story
244
+ const dxGrid = page.locator('dx-grid').nth(1);
245
+ await dxGrid.waitFor({ state: 'visible' });
246
+
247
+ // Scroll to the last column (column 8)
248
+ await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
249
+ dxGridElement.scrollToColumn(8);
250
+ });
251
+
252
+ // Click on the cell at aria-rowindex=0 aria-colindex=8 to focus it
253
+ const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="8"]');
254
+ await targetCell.click();
255
+
256
+ // Click again to engage edit mode
257
+ await page.keyboard.press('Enter');
258
+ await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
259
+
260
+ // Type the first few letters of an org name.
261
+ const orgName = 'Sally';
262
+ await page.keyboard.type(orgName, { delay: 500 });
263
+
264
+ // Assert that there is an element with aria-selected on the page
265
+ await expect(page.locator('[role="option"][aria-selected]')).toBeVisible();
266
+
267
+ // Type the enter key
268
+ await page.keyboard.press('Enter');
269
+
270
+ // Click the save button in the popover
271
+ await page.getByTestId('save-button').click();
272
+
273
+ // Assert that the cell element has the org name
274
+ await expect(targetCell).toHaveText(orgName);
275
+
276
+ await page.close();
277
+ });
186
278
  });
@@ -13,7 +13,7 @@ import { useClientProvider } from '@dxos/react-client/testing';
13
13
  import { DataType, ProjectionModel } from '@dxos/schema';
14
14
 
15
15
  import { type TableController } from '../components';
16
- import { useTableModel, useAddRow } from '../hooks';
16
+ import { useAddRow, useTableModel } from '../hooks';
17
17
  import { TablePresentation } from '../model';
18
18
 
19
19
  faker.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
@@ -93,7 +93,8 @@ export const useTestTableModel = () => {
93
93
 
94
94
  const handleInsertRow = useCallback(() => {
95
95
  model?.insertRow();
96
- }, [model]);
96
+ tableRef.current?.focusDraft?.();
97
+ }, [model, tableRef.current]);
97
98
 
98
99
  const handleSaveView = useCallback(() => {
99
100
  model?.saveView();
@@ -14,8 +14,8 @@ export const translations = [
14
14
  'create object label': 'Create table',
15
15
  'table name placeholder': 'Table name',
16
16
  'settings title': 'Table settings',
17
- 'table schema label': 'Schema',
18
- 'new schema': 'New schema',
17
+ 'table schema label': 'Record type',
18
+ 'new schema': 'New record type',
19
19
  'continue label': 'Continue',
20
20
  'create stack section label': 'Create table',
21
21
  'add row label': 'Add row',
@@ -8,11 +8,11 @@ import { Obj } from '@dxos/echo';
8
8
  import { getTypename, toJsonSchema } from '@dxos/echo-schema';
9
9
  import type { JsonSchemaType, SortDirectionType } from '@dxos/echo-schema';
10
10
  import {
11
- createView,
12
11
  type DataType,
13
- getSchemaFromPropertyDefinitions,
14
12
  ProjectionModel,
15
13
  type SchemaPropertyDefinition,
14
+ createView,
15
+ getSchemaFromPropertyDefinitions,
16
16
  } from '@dxos/schema';
17
17
 
18
18
  import { TableView } from '../types';
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Schema } from 'effect';
6
- import { isTypeLiteral, TypeLiteral } from 'effect/SchemaAST';
6
+ import { TypeLiteral, isTypeLiteral } from 'effect/SchemaAST';
7
7
 
8
8
  /**
9
9
  * Creates a narrowed schema from an original schema that only includes
@@ -40,7 +40,7 @@ const createButton = ({
40
40
  .join(' ');
41
41
 
42
42
  const positionClass = type === 'primary' ? 'inline-end-2' : 'inline-end-9';
43
- return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? 'disabled' : ''}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
43
+ return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? 'disabled' : ''} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
44
44
  };
45
45
 
46
46
  const addColumnButton = {
@@ -130,6 +130,7 @@ const saveDraftRowButton = {
130
130
  disabled,
131
131
  data: {
132
132
  'data-row-index': rowIndex.toString(),
133
+ 'data-variant': 'primary',
133
134
  },
134
135
  testId: 'table-save-draft-row-button',
135
136
  });
@@ -3,6 +3,8 @@
3
3
  //
4
4
 
5
5
  // Core types.
6
+ import { accessoryHandlesPointerdownAttrs } from '@dxos/lit-grid';
7
+
6
8
  export type TableControl = 'checkbox' | 'switch';
7
9
 
8
10
  export type ControlData =
@@ -41,7 +43,7 @@ const renderInput = (
41
43
  preventToggle = false,
42
44
  testId: string,
43
45
  ) => {
44
- return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? 'checked' : ''} ${preventToggle ? 'onclick="return false"' : ''} ${disabled ? 'disabled' : ''} data-testid="${testId}"/>`;
46
+ return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? 'checked' : ''} ${preventToggle ? 'onclick="return false"' : ''} ${disabled ? 'disabled' : ''} data-testid="${testId}" data-dx-grid-action="accessory"/>`;
45
47
  };
46
48
 
47
49
  export const CheckboxStory = ({
@@ -64,6 +66,7 @@ export const SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = fa
64
66
  [CONTROL_IDENTIFIERS.switch]: '',
65
67
  'data-row-index': rowIndex.toString(),
66
68
  'data-col-index': colIndex.toString(),
69
+ ...accessoryHandlesPointerdownAttrs,
67
70
  };
68
71
 
69
72
  return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, 'table-switch');
package/src/util/table.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  import { Match } from 'effect';
6
6
 
7
7
  import { Obj } from '@dxos/echo';
8
- import { type JsonPath, toEffectSchema, type JsonSchemaType } from '@dxos/echo-schema';
8
+ import { type JsonPath, type JsonSchemaType, toEffectSchema } from '@dxos/echo-schema';
9
9
  import { type SimpleType } from '@dxos/effect';
10
10
  import { type CreateViewFromSpaceProps, type DataType, createViewFromSpace, getSchemaProperties } from '@dxos/schema';
11
11
 
@@ -18,7 +18,11 @@ type CreateTableProps = Omit<CreateViewFromSpaceProps, 'presentation'> & {
18
18
  export const createTable = async ({
19
19
  sizes,
20
20
  ...props
21
- }: CreateTableProps): Promise<{ jsonSchema: JsonSchemaType; view: DataType.View }> => {
21
+ }: CreateTableProps): Promise<{
22
+ jsonSchema: JsonSchemaType;
23
+ view: DataType.View;
24
+ schema: ReturnType<typeof toEffectSchema>;
25
+ }> => {
22
26
  const table = Obj.make(TableView, { sizes: {} });
23
27
  const { jsonSchema, view } = await createViewFromSpace({ ...props, presentation: table });
24
28
 
@@ -45,5 +49,5 @@ export const createTable = async ({
45
49
  )(property.type);
46
50
  }
47
51
 
48
- return { jsonSchema, view };
52
+ return { jsonSchema, schema, view };
49
53
  };