@dxos/react-ui-table 0.8.4-main.28f8d3d → 0.8.4-main.2c6827d

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 (114) hide show
  1. package/dist/lib/browser/chunk-2PFAPQL4.mjs +66 -0
  2. package/dist/lib/browser/chunk-2PFAPQL4.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-ZAOSIG3L.mjs → chunk-GS2UNGJK.mjs} +174 -213
  4. package/dist/lib/browser/chunk-GS2UNGJK.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +411 -515
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +12 -9
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types/index.mjs +3 -3
  11. package/dist/lib/node-esm/chunk-6POOFFYF.mjs +67 -0
  12. package/dist/lib/node-esm/chunk-6POOFFYF.mjs.map +7 -0
  13. package/dist/lib/node-esm/{chunk-ZOFFI3JJ.mjs → chunk-TRR3C5NX.mjs} +174 -213
  14. package/dist/lib/node-esm/chunk-TRR3C5NX.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +411 -515
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +12 -9
  19. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/types/index.mjs +3 -3
  21. package/dist/types/src/components/Table/DynamicTable.d.ts +2 -2
  22. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +51 -3
  24. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/Relations.stories.d.ts +103 -5
  26. package/dist/types/src/components/Table/Relations.stories.d.ts.map +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 +8 -5
  29. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  30. package/dist/types/src/components/Table/Table.stories.d.ts +41 -3
  31. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -6
  33. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -13
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -4
  37. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
  39. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
  40. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +2 -2
  41. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  42. package/dist/types/src/components/testing.d.ts +3 -3
  43. package/dist/types/src/components/testing.d.ts.map +1 -1
  44. package/dist/types/src/hooks/useAddRow.d.ts +3 -2
  45. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useTableModel.d.ts +3 -3
  47. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  48. package/dist/types/src/model/modal-controller.d.ts +0 -7
  49. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  50. package/dist/types/src/model/table-model.d.ts +9 -8
  51. package/dist/types/src/model/table-model.d.ts.map +1 -1
  52. package/dist/types/src/model/table-presentation.d.ts +1 -1
  53. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  54. package/dist/types/src/model/table-sorting.d.ts +2 -3
  55. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  56. package/dist/types/src/testing/useTestTableModel.d.ts +3 -22
  57. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  58. package/dist/types/src/types/index.d.ts +1 -1
  59. package/dist/types/src/types/index.d.ts.map +1 -1
  60. package/dist/types/src/types/schema.d.ts +25 -5
  61. package/dist/types/src/types/schema.d.ts.map +1 -1
  62. package/dist/types/src/util/dynamic-table.d.ts +5 -6
  63. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  64. package/dist/types/src/util/index.d.ts +0 -1
  65. package/dist/types/src/util/index.d.ts.map +1 -1
  66. package/dist/types/src/util/schema.d.ts +1 -1
  67. package/dist/types/src/util/schema.d.ts.map +1 -1
  68. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  69. package/dist/types/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +53 -51
  71. package/src/components/Table/DynamicTable.stories.tsx +15 -12
  72. package/src/components/Table/DynamicTable.tsx +4 -7
  73. package/src/components/Table/Relations.stories.tsx +160 -42
  74. package/src/components/Table/RowActionsMenu.tsx +21 -13
  75. package/src/components/Table/Table.stories.tsx +63 -56
  76. package/src/components/Table/Table.tsx +109 -90
  77. package/src/components/TableCellEditor/FormCellEditor.tsx +153 -42
  78. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +24 -64
  79. package/src/components/TableCellEditor/TableCellEditor.tsx +62 -208
  80. package/src/components/TableCellEditor/index.ts +1 -0
  81. package/src/components/TableToolbar/TableToolbar.tsx +32 -22
  82. package/src/components/testing.ts +2 -2
  83. package/src/hooks/useAddRow.ts +7 -5
  84. package/src/hooks/useTableModel.ts +5 -5
  85. package/src/model/modal-controller.ts +0 -28
  86. package/src/model/table-model.test.ts +19 -11
  87. package/src/model/table-model.ts +36 -24
  88. package/src/model/table-presentation.test.ts +22 -21
  89. package/src/model/table-presentation.ts +58 -39
  90. package/src/model/table-sorting.ts +16 -7
  91. package/src/playwright/TableManager.ts +1 -1
  92. package/src/playwright/smoke.spec.ts +51 -49
  93. package/src/testing/useTestTableModel.ts +10 -7
  94. package/src/types/index.ts +1 -1
  95. package/src/types/schema.ts +63 -6
  96. package/src/util/dynamic-table.ts +15 -16
  97. package/src/util/index.ts +0 -1
  98. package/src/util/schema.ts +4 -4
  99. package/src/util/table-buttons.ts +3 -3
  100. package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
  101. package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
  102. package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +0 -7
  103. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
  104. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
  105. package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +0 -7
  106. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  107. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  108. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  109. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  110. package/dist/types/src/util/table.d.ts +0 -12
  111. package/dist/types/src/util/table.d.ts.map +0 -1
  112. package/src/components/Table/CreateRefPanel.tsx +0 -86
  113. package/src/components/TableCellEditor/extension.ts +0 -61
  114. package/src/util/table.ts +0 -53
@@ -5,6 +5,7 @@
5
5
  import { expect, test } from '@playwright/test';
6
6
 
7
7
  import { type DxGrid } from '@dxos/lit-grid';
8
+ import { faker } from '@dxos/random';
8
9
  import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
9
10
 
10
11
  import { TableManager } from './TableManager';
@@ -16,6 +17,7 @@ const relationsStoryUrl = storybookUrl('ui-react-ui-table-relations--default', 9
16
17
  test.describe('Table', () => {
17
18
  test('Loads', async ({ browser, browserName }) => {
18
19
  test.skip(browserName === 'webkit');
20
+ test.skip(browserName === 'firefox');
19
21
  const { page } = await setupPage(browser, { url: storyUrl });
20
22
  const table = new TableManager(page);
21
23
 
@@ -25,6 +27,7 @@ test.describe('Table', () => {
25
27
 
26
28
  test('sort', async ({ browser, browserName }) => {
27
29
  test.skip(browserName === 'webkit');
30
+ test.skip(browserName === 'firefox');
28
31
  const { page } = await setupPage(browser, { url: storyUrl });
29
32
  const table = new TableManager(page);
30
33
 
@@ -41,6 +44,7 @@ test.describe('Table', () => {
41
44
 
42
45
  test('selection', async ({ browser, browserName }) => {
43
46
  test.skip(browserName === 'webkit');
47
+ test.skip(browserName === 'firefox');
44
48
  const { page } = await setupPage(browser, { url: storyUrl });
45
49
  const table = new TableManager(page);
46
50
 
@@ -62,6 +66,7 @@ test.describe('Table', () => {
62
66
 
63
67
  test('delete row', async ({ browser, browserName }) => {
64
68
  test.skip(browserName === 'webkit');
69
+ test.skip(browserName === 'firefox');
65
70
  const { page } = await setupPage(browser, { url: storyUrl });
66
71
  const table = new TableManager(page);
67
72
 
@@ -73,6 +78,7 @@ test.describe('Table', () => {
73
78
 
74
79
  test('delete row--select all', async ({ browser, browserName }) => {
75
80
  test.skip(browserName === 'webkit');
81
+ test.skip(browserName === 'firefox');
76
82
  const { page } = await setupPage(browser, { url: storyUrl });
77
83
  const table = new TableManager(page);
78
84
 
@@ -90,6 +96,7 @@ test.describe('Table', () => {
90
96
 
91
97
  test('delete column', async ({ browser, browserName }) => {
92
98
  test.skip(browserName === 'webkit');
99
+ test.skip(browserName === 'firefox');
93
100
  const { page } = await setupPage(browser, { url: storyUrl });
94
101
  const table = new TableManager(page);
95
102
 
@@ -116,6 +123,7 @@ test.describe('Table', () => {
116
123
  // Rest of add column test remains the same as it's a more complex flow.
117
124
  test('add column', async ({ browser, browserName }) => {
118
125
  test.skip(browserName === 'webkit');
126
+ test.skip(browserName === 'firefox');
119
127
  const { page } = await setupPage(browser, { url: storyUrl });
120
128
  const table = new TableManager(page);
121
129
 
@@ -128,44 +136,9 @@ test.describe('Table', () => {
128
136
  await page.close();
129
137
  });
130
138
 
131
- test('reference > reference / create new object', async ({ browser, browserName }) => {
132
- test.skip(browserName === 'webkit');
133
- const { page } = await setupPage(browser, { url: storyUrl });
134
- const table = new TableManager(page);
135
-
136
- await table.grid.ready();
137
-
138
- // Reference existing object.
139
- // Scroll over to the manager column.
140
- await table.grid.panByWheel(10000, 0);
141
-
142
- await table.grid.cell(4, 0, 'grid').click();
143
- // TODO(wittjosiah): Surprisingly long delay needed here.
144
- await page.keyboard.press('A', { delay: 1_000 });
145
- await page.keyboard.press('u', { delay: 1_000 });
146
- await page.getByRole('option', { name: 'Aut.' }).click();
147
-
148
- // Assert that the value is shown in the cell.
149
- await expect(page.getByRole('gridcell', { name: 'Aut.' }).first()).toBeVisible();
150
-
151
- // Create new object.
152
- await table.grid.cell(4, 1, 'grid').click();
153
- // TODO(wittjosiah): Surprisingly long delay needed here.
154
- await page.keyboard.type('t', { delay: 1_000 });
155
- await page.keyboard.type('e', { delay: 1_000 });
156
- await page.keyboard.type('s', { delay: 1_000 });
157
- await page.keyboard.type('t', { delay: 1_000 });
158
- await page.getByText('Create new object', { exact: false }).click();
159
- await page.getByTestId('save-button').click();
160
-
161
- // Scroll to the left.
162
- await page.getByRole('gridcell', { name: 'test' }).first().click();
163
-
164
- await page.close();
165
- });
166
-
167
- test('test toggles', async ({ browser, browserName }) => {
139
+ test.skip('test toggles', async ({ browser, browserName }) => {
168
140
  test.skip(browserName === 'webkit');
141
+ test.skip(browserName === 'firefox');
169
142
  const { page } = await setupPage(browser, { url: storyUrl });
170
143
  const table = new TableManager(page);
171
144
 
@@ -186,8 +159,10 @@ test.describe('Table', () => {
186
159
  await page.close();
187
160
  });
188
161
 
189
- test('extant relations work as expected', async ({ browser, browserName }) => {
162
+ // TODO(wittjosiah): Remove? Conflicts with story play function which is run as a unit test anyways.
163
+ test.skip('extant relations work as expected', async ({ browser, browserName }) => {
190
164
  test.skip(browserName === 'webkit');
165
+ test.skip(browserName === 'firefox');
191
166
  const { page } = await setupPage(browser, { url: relationsStoryUrl });
192
167
 
193
168
  // Wait for the page to load
@@ -198,18 +173,22 @@ test.describe('Table', () => {
198
173
  const dxGrid = page.locator('dx-grid').nth(1);
199
174
  await dxGrid.waitFor({ state: 'visible' });
200
175
 
201
- // Scroll to the last column (column 8)
176
+ // Scroll to the last column (column 4)
202
177
  await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
203
- dxGridElement.scrollToColumn(8);
178
+ dxGridElement.scrollToColumn(4);
204
179
  });
205
180
 
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"]');
181
+ // Click on the cell at aria-rowindex=0 aria-colindex=4 to focus it
182
+ const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
208
183
  await targetCell.click();
209
184
 
210
185
  // Click again to engage edit mode
211
186
  await page.keyboard.press('Enter');
212
- await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
187
+
188
+ // Click on the combobox to open options
189
+ await page.getByRole('combobox').click();
190
+ await page.pause();
191
+ await page.getByPlaceholder('Search…').focus();
213
192
 
214
193
  // Type the first few letters of an org name.
215
194
  const orgName =
@@ -226,14 +205,19 @@ test.describe('Table', () => {
226
205
  // Type the enter key
227
206
  await page.keyboard.press('Enter');
228
207
 
208
+ // Save the result
209
+ await page.getByTestId('save-button').click();
210
+
229
211
  // Assert that the cell element has the org name
230
212
  await expect(targetCell).toHaveText(orgName);
231
213
 
232
214
  await page.close();
233
215
  });
234
216
 
235
- test('new relations work as expected', async ({ browser, browserName }) => {
217
+ // TODO(wittjosiah): Remove? Conflicts with story play function which is run as a unit test anyways.
218
+ test.skip('new relations work as expected', async ({ browser, browserName }) => {
236
219
  test.skip(browserName === 'webkit');
220
+ test.skip(browserName === 'firefox');
237
221
  const { page } = await setupPage(browser, { url: relationsStoryUrl });
238
222
 
239
223
  // Wait for the page to load
@@ -244,18 +228,21 @@ test.describe('Table', () => {
244
228
  const dxGrid = page.locator('dx-grid').nth(1);
245
229
  await dxGrid.waitFor({ state: 'visible' });
246
230
 
247
- // Scroll to the last column (column 8)
231
+ // Scroll to the last column (column 4)
248
232
  await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
249
- dxGridElement.scrollToColumn(8);
233
+ dxGridElement.scrollToColumn(4);
250
234
  });
251
235
 
252
236
  // 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"]');
237
+ const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
254
238
  await targetCell.click();
255
239
 
256
240
  // Click again to engage edit mode
257
241
  await page.keyboard.press('Enter');
258
- await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
242
+
243
+ // Click on the combobox to open options
244
+ await page.getByRole('combobox').click();
245
+ await page.getByPlaceholder('Search…').focus();
259
246
 
260
247
  // Type the first few letters of an org name.
261
248
  const orgName = 'Sally';
@@ -266,13 +253,28 @@ test.describe('Table', () => {
266
253
 
267
254
  // Type the enter key
268
255
  await page.keyboard.press('Enter');
256
+ await page.pause();
269
257
 
270
258
  // Click the save button in the popover
271
- await page.getByTestId('save-button').click();
259
+ await page.getByTestId('create-referenced-object-form').getByTestId('save-button').click();
272
260
 
273
261
  // Assert that the cell element has the org name
274
262
  await expect(targetCell).toHaveText(orgName);
275
263
 
264
+ // Make a change to a non-ref cell to check that populated refs don’t cause problems with snapshots or schemas.
265
+ await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
266
+ dxGridElement.scrollToColumn(6);
267
+ });
268
+
269
+ const nonRefContent = faker.lorem.words(3);
270
+ const nonRefCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="6"]');
271
+ await nonRefCell.click();
272
+ await page.keyboard.press('Enter');
273
+ await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
274
+ await page.keyboard.type(nonRefContent, { delay: 500 });
275
+ await page.keyboard.press('Enter');
276
+ await expect(nonRefCell).toHaveText(nonRefContent);
277
+
276
278
  await page.close();
277
279
  });
278
280
  });
@@ -4,13 +4,13 @@
4
4
 
5
5
  import { useCallback, useMemo, useRef } from 'react';
6
6
 
7
- import { isMutable, toJsonSchema } from '@dxos/echo-schema';
7
+ import { isMutable, toJsonSchema } from '@dxos/echo/internal';
8
8
  import { useGlobalFilteredObjects } from '@dxos/plugin-search';
9
9
  import { faker } from '@dxos/random';
10
10
  import { useClient } from '@dxos/react-client';
11
11
  import { Filter, useQuery, useSchema } from '@dxos/react-client/echo';
12
12
  import { useClientProvider } from '@dxos/react-client/testing';
13
- import { DataType, ProjectionModel } from '@dxos/schema';
13
+ import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
14
14
 
15
15
  import { type TableController } from '../components';
16
16
  import { useAddRow, useTableModel } from '../hooks';
@@ -26,14 +26,17 @@ export const useTestTableModel = () => {
26
26
  const client = useClient();
27
27
  const { space } = useClientProvider();
28
28
 
29
- const views = useQuery(space, Filter.type(DataType.View));
29
+ const views = useQuery(space, Filter.type(View.View));
30
30
  const view = useMemo(() => views.at(0), [views]);
31
- const schema = useSchema(client, space, view?.query.typename);
31
+ const typename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
32
+ const schema = useSchema(client, space, typename);
32
33
  const jsonSchema = useMemo(() => (schema ? toJsonSchema(schema) : undefined), [schema]);
33
34
 
34
35
  const projection = useMemo(() => {
35
36
  if (schema && view?.projection) {
36
- return new ProjectionModel(toJsonSchema(schema), view.projection);
37
+ const projection = new ProjectionModel(toJsonSchema(schema), view.projection);
38
+ projection.normalizeView();
39
+ return projection;
37
40
  }
38
41
  }, [schema, view?.projection]);
39
42
 
@@ -92,8 +95,8 @@ export const useTestTableModel = () => {
92
95
  });
93
96
 
94
97
  const handleInsertRow = useCallback(() => {
95
- model?.insertRow();
96
- tableRef.current?.focusDraft?.();
98
+ const insertResult = model?.insertRow();
99
+ tableRef.current?.handleInsertRowResult?.(insertResult);
97
100
  }, [model, tableRef.current]);
98
101
 
99
102
  const handleSaveView = useCallback(() => {
@@ -2,4 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './schema';
5
+ export * as Table from './schema';
@@ -2,15 +2,72 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Match from 'effect/Match';
6
+ import * as Schema from 'effect/Schema';
6
7
 
7
- import { Type } from '@dxos/echo';
8
- import { JsonPath } from '@dxos/effect';
8
+ import { Obj, Type } from '@dxos/echo';
9
+ import { JsonPath, type JsonSchemaType, toEffectSchema } from '@dxos/echo/internal';
10
+ import { ViewAnnotation } from '@dxos/echo/internal';
11
+ import { type SimpleType } from '@dxos/effect';
12
+ import { View, getSchemaProperties } from '@dxos/schema';
9
13
 
10
- export const TableView = Schema.Struct({
14
+ export const Table = Schema.Struct({
11
15
  sizes: Schema.Record({
12
16
  key: JsonPath,
13
17
  value: Schema.Number,
14
18
  }).pipe(Schema.mutable),
15
- }).pipe(Type.Obj({ typename: 'dxos.org/type/TableView', version: '0.1.0' }));
16
- export type TableView = Schema.Schema.Type<typeof TableView>;
19
+ }).pipe(
20
+ Type.Obj({
21
+ typename: 'dxos.org/type/Table',
22
+ version: '0.1.0',
23
+ }),
24
+ ViewAnnotation.set(true),
25
+ );
26
+
27
+ export type Table = Schema.Schema.Type<typeof Table>;
28
+
29
+ /**
30
+ * Make a table view.
31
+ */
32
+ export const make = (props: Partial<Obj.MakeProps<typeof Table>> = {}) => Obj.make(Table, { sizes: {}, ...props });
33
+
34
+ type MakeViewProps = Omit<View.MakeFromSpaceProps, 'presentation'> & {
35
+ sizes?: Record<string, number>;
36
+ };
37
+
38
+ export const makeView = async ({
39
+ sizes,
40
+ ...props
41
+ }: MakeViewProps): Promise<{
42
+ jsonSchema: JsonSchemaType;
43
+ view: View.View;
44
+ schema: ReturnType<typeof toEffectSchema>;
45
+ }> => {
46
+ const table = Obj.make(Table, { sizes: {} });
47
+ const { jsonSchema, view } = await View.makeFromSpace({ ...props, presentation: table });
48
+
49
+ // Preset sizes.
50
+ const schema = toEffectSchema(jsonSchema);
51
+ const shouldIncludeId = props.fields?.find((field) => field === 'id') !== undefined;
52
+ const properties = getSchemaProperties(schema.ast, {}, shouldIncludeId);
53
+ for (const property of properties) {
54
+ if (sizes?.[property.name]) {
55
+ table.sizes[property.name as JsonPath] = sizes[property.name];
56
+ continue;
57
+ }
58
+
59
+ Match.type<SimpleType>().pipe(
60
+ Match.when('boolean', () => {
61
+ table.sizes[property.name as JsonPath] = 100;
62
+ }),
63
+ Match.when('number', () => {
64
+ table.sizes[property.name as JsonPath] = 100;
65
+ }),
66
+ Match.orElse(() => {
67
+ // Noop.
68
+ }),
69
+ )(property.type);
70
+ }
71
+
72
+ return { jsonSchema, schema, view };
73
+ };
@@ -2,20 +2,20 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
5
+ import type * as Schema from 'effect/Schema';
6
6
 
7
- import { Obj } from '@dxos/echo';
8
- import { getTypename, toJsonSchema } from '@dxos/echo-schema';
9
- import type { JsonSchemaType, SortDirectionType } from '@dxos/echo-schema';
7
+ import { Filter, Obj, Query } from '@dxos/echo';
8
+ import { getTypename, toJsonSchema } from '@dxos/echo/internal';
9
+ import type { JsonSchemaType } from '@dxos/echo/internal';
10
10
  import {
11
- type DataType,
12
11
  ProjectionModel,
13
12
  type SchemaPropertyDefinition,
14
- createView,
13
+ type SortDirectionType,
14
+ View,
15
15
  getSchemaFromPropertyDefinitions,
16
16
  } from '@dxos/schema';
17
17
 
18
- import { TableView } from '../types';
18
+ import { Table } from '../types';
19
19
 
20
20
  // TODO(ZaymonFC): Upstream these extra fields to SchemaPropertyDefinition to enhance schema-tools schema creation.
21
21
  type PropertyDisplayProps = {
@@ -54,23 +54,22 @@ export const getBaseSchema = ({
54
54
  };
55
55
 
56
56
  export const makeDynamicTable = ({
57
- typename,
58
57
  jsonSchema,
59
58
  properties,
60
59
  }: {
61
- typename: string;
62
60
  jsonSchema: JsonSchemaType;
63
61
  properties?: TablePropertyDefinition[];
64
- }): { projection: ProjectionModel; view: DataType.View } => {
65
- const table = Obj.make(TableView, { sizes: {} });
66
- const view = createView({
67
- typename,
62
+ }): { projection: ProjectionModel; view: View.View } => {
63
+ const table = Obj.make(Table.Table, { sizes: {} });
64
+ const view = View.make({
65
+ query: Query.select(Filter.everything()),
68
66
  jsonSchema,
69
67
  presentation: table,
70
68
  ...(properties && { fields: properties.map((property) => property.name) }),
71
69
  });
72
70
 
73
71
  const projection = new ProjectionModel(jsonSchema, view.projection);
72
+ projection.normalizeView();
74
73
  if (properties && projection.fields) {
75
74
  setProperties(view, projection, table, properties);
76
75
  }
@@ -79,9 +78,9 @@ export const makeDynamicTable = ({
79
78
  };
80
79
 
81
80
  const setProperties = (
82
- view: DataType.View,
81
+ view: View.View,
83
82
  projection: ProjectionModel,
84
- table: TableView,
83
+ table: Table.Table,
85
84
  properties: TablePropertyDefinition[],
86
85
  ) => {
87
86
  for (const property of properties) {
@@ -101,7 +100,7 @@ const setProperties = (
101
100
 
102
101
  if (property.sort) {
103
102
  const fieldId = field.id;
104
- view.query.sort = [{ fieldId, direction: property.sort }];
103
+ view.sort = [{ fieldId, direction: property.sort }];
105
104
  }
106
105
  }
107
106
  }
package/src/util/index.ts CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  export * from './dynamic-table';
6
6
  export * from './signals';
7
- export * from './table';
8
7
  export * from './table-buttons';
9
8
  export * from './table-controls';
10
9
  export * from './schema';
@@ -2,8 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
- import { TypeLiteral, isTypeLiteral } from 'effect/SchemaAST';
5
+ import * as Schema from 'effect/Schema';
6
+ import * as SchemaAST from 'effect/SchemaAST';
7
7
 
8
8
  /**
9
9
  * Creates a narrowed schema from an original schema that only includes
@@ -20,14 +20,14 @@ export const narrowSchema = <S extends Schema.Schema.AnyNoContext>(
20
20
  ): Schema.Schema<unknown, unknown> | undefined => {
21
21
  const ast = (schema as any)?.ast;
22
22
 
23
- if (isTypeLiteral(ast)) {
23
+ if (SchemaAST.isTypeLiteral(ast)) {
24
24
  // Filter property signatures that match any of the provided paths
25
25
  const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
26
26
 
27
27
  // If we found at least one matching property
28
28
  if (propertySignatures.length > 0) {
29
29
  // Create a new TypeLiteral with only the matching properties
30
- const narrowType = new TypeLiteral(propertySignatures, []);
30
+ const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
31
31
  return Schema.make(narrowType);
32
32
  }
33
33
  }
@@ -26,7 +26,7 @@ const createButton = ({
26
26
  disabled = false,
27
27
  icon,
28
28
  testId,
29
- type = 'primary',
29
+ type: _type = 'primary',
30
30
  }: {
31
31
  attr: string;
32
32
  data: Record<string, string>;
@@ -39,8 +39,7 @@ const createButton = ({
39
39
  .map(([k, v]) => `${k}="${v}"`)
40
40
  .join(' ');
41
41
 
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' : ''} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
42
+ return `<button ${attr} data-testid="${testId}" class="dx-button is-6 aspect-square pli-0.5 min-bs-0" ${dataAttrs} ${disabled ? 'disabled' : ''} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
44
43
  };
45
44
 
46
45
  const addColumnButton = {
@@ -67,6 +66,7 @@ const columnSettingsButton = {
67
66
  icon: columnSettingsButton.icon,
68
67
  data: {
69
68
  'data-field-id': fieldId,
69
+ 'data-variant': 'ghost',
70
70
  },
71
71
  testId: 'table-column-settings-button',
72
72
  });
@@ -1,18 +0,0 @@
1
- // src/types/schema.ts
2
- import { Schema } from "effect";
3
- import { Type } from "@dxos/echo";
4
- import { JsonPath } from "@dxos/effect";
5
- var TableView = Schema.Struct({
6
- sizes: Schema.Record({
7
- key: JsonPath,
8
- value: Schema.Number
9
- }).pipe(Schema.mutable)
10
- }).pipe(Type.Obj({
11
- typename: "dxos.org/type/TableView",
12
- version: "0.1.0"
13
- }));
14
-
15
- export {
16
- TableView
17
- };
18
- //# sourceMappingURL=chunk-L2LSB6KV.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/types/schema.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { Type } from '@dxos/echo';\nimport { JsonPath } from '@dxos/effect';\n\nexport const TableView = Schema.Struct({\n sizes: Schema.Record({\n key: JsonPath,\n value: Schema.Number,\n }).pipe(Schema.mutable),\n}).pipe(Type.Obj({ typename: 'dxos.org/type/TableView', version: '0.1.0' }));\nexport type TableView = Schema.Schema.Type<typeof TableView>;\n"],
5
- "mappings": ";AAIA,SAASA,cAAc;AAEvB,SAASC,YAAY;AACrB,SAASC,gBAAgB;AAElB,IAAMC,YAAYC,OAAOC,OAAO;EACrCC,OAAOF,OAAOG,OAAO;IACnBC,KAAKC;IACLC,OAAON,OAAOO;EAChB,CAAA,EAAGC,KAAKR,OAAOS,OAAO;AACxB,CAAA,EAAGD,KAAKE,KAAKC,IAAI;EAAEC,UAAU;EAA2BC,SAAS;AAAQ,CAAA,CAAA;",
6
- "names": ["Schema", "Type", "JsonPath", "TableView", "Schema", "Struct", "sizes", "Record", "key", "JsonPath", "value", "Number", "pipe", "mutable", "Type", "Obj", "typename", "version"]
7
- }