@dxos/react-ui-table 0.8.4-main.28f8d3d → 0.8.4-main.406dc2a
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.
- package/dist/lib/browser/chunk-4K7JPALT.mjs +66 -0
- package/dist/lib/browser/chunk-4K7JPALT.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZAOSIG3L.mjs → chunk-OZTXLZGM.mjs} +526 -536
- package/dist/lib/browser/chunk-OZTXLZGM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +373 -481
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +11 -8
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/types/index.mjs +3 -3
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs +67 -0
- package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ZOFFI3JJ.mjs → chunk-S56Z4V4X.mjs} +526 -536
- package/dist/lib/node-esm/chunk-S56Z4V4X.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +373 -481
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +11 -8
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/types/index.mjs +3 -3
- package/dist/types/src/components/Table/DynamicTable.d.ts +2 -2
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +51 -3
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +104 -5
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +8 -5
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +41 -3
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -6
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +8 -13
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +39 -4
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +3 -3
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +3 -2
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +0 -7
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +7 -6
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +1 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +1 -2
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +3 -22
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +25 -5
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +4 -5
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +51 -50
- package/src/components/Table/DynamicTable.stories.tsx +12 -9
- package/src/components/Table/DynamicTable.tsx +4 -7
- package/src/components/Table/Relations.stories.tsx +162 -38
- package/src/components/Table/Table.stories.tsx +59 -52
- package/src/components/Table/Table.tsx +109 -90
- package/src/components/TableCellEditor/FormCellEditor.tsx +153 -42
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +22 -63
- package/src/components/TableCellEditor/TableCellEditor.tsx +62 -208
- package/src/components/TableCellEditor/index.ts +1 -0
- package/src/components/testing.ts +2 -2
- package/src/hooks/useAddRow.ts +7 -5
- package/src/hooks/useTableModel.ts +1 -1
- package/src/model/modal-controller.ts +0 -28
- package/src/model/table-model.test.ts +18 -10
- package/src/model/table-model.ts +26 -17
- package/src/model/table-presentation.test.ts +21 -20
- package/src/model/table-presentation.ts +58 -39
- package/src/model/table-sorting.ts +15 -6
- package/src/playwright/smoke.spec.ts +46 -46
- package/src/testing/useTestTableModel.ts +9 -6
- package/src/types/index.ts +1 -1
- package/src/types/schema.ts +63 -6
- package/src/util/dynamic-table.ts +11 -11
- package/src/util/index.ts +0 -1
- package/src/util/schema.ts +4 -4
- package/src/util/table-buttons.ts +3 -3
- package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +0 -7
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/util/table.d.ts +0 -12
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/Table/CreateRefPanel.tsx +0 -86
- package/src/components/TableCellEditor/extension.ts +0 -61
- 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('
|
|
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
|
|
|
@@ -188,6 +161,7 @@ test.describe('Table', () => {
|
|
|
188
161
|
|
|
189
162
|
test('extant relations work as expected', async ({ browser, browserName }) => {
|
|
190
163
|
test.skip(browserName === 'webkit');
|
|
164
|
+
test.skip(browserName === 'firefox');
|
|
191
165
|
const { page } = await setupPage(browser, { url: relationsStoryUrl });
|
|
192
166
|
|
|
193
167
|
// Wait for the page to load
|
|
@@ -198,18 +172,22 @@ test.describe('Table', () => {
|
|
|
198
172
|
const dxGrid = page.locator('dx-grid').nth(1);
|
|
199
173
|
await dxGrid.waitFor({ state: 'visible' });
|
|
200
174
|
|
|
201
|
-
// Scroll to the last column (column
|
|
175
|
+
// Scroll to the last column (column 4)
|
|
202
176
|
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
203
|
-
dxGridElement.scrollToColumn(
|
|
177
|
+
dxGridElement.scrollToColumn(4);
|
|
204
178
|
});
|
|
205
179
|
|
|
206
|
-
// Click on the cell at aria-rowindex=0 aria-colindex=
|
|
207
|
-
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="
|
|
180
|
+
// Click on the cell at aria-rowindex=0 aria-colindex=4 to focus it
|
|
181
|
+
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
|
|
208
182
|
await targetCell.click();
|
|
209
183
|
|
|
210
184
|
// Click again to engage edit mode
|
|
211
185
|
await page.keyboard.press('Enter');
|
|
212
|
-
|
|
186
|
+
|
|
187
|
+
// Click on the combobox to open options
|
|
188
|
+
await page.getByRole('combobox').click();
|
|
189
|
+
await page.pause();
|
|
190
|
+
await page.getByPlaceholder('Search...').focus();
|
|
213
191
|
|
|
214
192
|
// Type the first few letters of an org name.
|
|
215
193
|
const orgName =
|
|
@@ -226,6 +204,9 @@ test.describe('Table', () => {
|
|
|
226
204
|
// Type the enter key
|
|
227
205
|
await page.keyboard.press('Enter');
|
|
228
206
|
|
|
207
|
+
// Save the result
|
|
208
|
+
await page.getByTestId('save-button').click();
|
|
209
|
+
|
|
229
210
|
// Assert that the cell element has the org name
|
|
230
211
|
await expect(targetCell).toHaveText(orgName);
|
|
231
212
|
|
|
@@ -234,6 +215,7 @@ test.describe('Table', () => {
|
|
|
234
215
|
|
|
235
216
|
test('new relations work as expected', async ({ browser, browserName }) => {
|
|
236
217
|
test.skip(browserName === 'webkit');
|
|
218
|
+
test.skip(browserName === 'firefox');
|
|
237
219
|
const { page } = await setupPage(browser, { url: relationsStoryUrl });
|
|
238
220
|
|
|
239
221
|
// Wait for the page to load
|
|
@@ -244,18 +226,21 @@ test.describe('Table', () => {
|
|
|
244
226
|
const dxGrid = page.locator('dx-grid').nth(1);
|
|
245
227
|
await dxGrid.waitFor({ state: 'visible' });
|
|
246
228
|
|
|
247
|
-
// Scroll to the last column (column
|
|
229
|
+
// Scroll to the last column (column 4)
|
|
248
230
|
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
249
|
-
dxGridElement.scrollToColumn(
|
|
231
|
+
dxGridElement.scrollToColumn(4);
|
|
250
232
|
});
|
|
251
233
|
|
|
252
234
|
// 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="
|
|
235
|
+
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
|
|
254
236
|
await targetCell.click();
|
|
255
237
|
|
|
256
238
|
// Click again to engage edit mode
|
|
257
239
|
await page.keyboard.press('Enter');
|
|
258
|
-
|
|
240
|
+
|
|
241
|
+
// Click on the combobox to open options
|
|
242
|
+
await page.getByRole('combobox').click();
|
|
243
|
+
await page.getByPlaceholder('Search...').focus();
|
|
259
244
|
|
|
260
245
|
// Type the first few letters of an org name.
|
|
261
246
|
const orgName = 'Sally';
|
|
@@ -266,6 +251,7 @@ test.describe('Table', () => {
|
|
|
266
251
|
|
|
267
252
|
// Type the enter key
|
|
268
253
|
await page.keyboard.press('Enter');
|
|
254
|
+
await page.pause();
|
|
269
255
|
|
|
270
256
|
// Click the save button in the popover
|
|
271
257
|
await page.getByTestId('save-button').click();
|
|
@@ -273,6 +259,20 @@ test.describe('Table', () => {
|
|
|
273
259
|
// Assert that the cell element has the org name
|
|
274
260
|
await expect(targetCell).toHaveText(orgName);
|
|
275
261
|
|
|
262
|
+
// Make a change to a non-ref cell to check that populated refs don’t cause problems with snapshots or schemas.
|
|
263
|
+
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
264
|
+
dxGridElement.scrollToColumn(6);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const nonRefContent = faker.lorem.words(3);
|
|
268
|
+
const nonRefCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="6"]');
|
|
269
|
+
await nonRefCell.click();
|
|
270
|
+
await page.keyboard.press('Enter');
|
|
271
|
+
await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
|
|
272
|
+
await page.keyboard.type(nonRefContent, { delay: 500 });
|
|
273
|
+
await page.keyboard.press('Enter');
|
|
274
|
+
await expect(nonRefCell).toHaveText(nonRefContent);
|
|
275
|
+
|
|
276
276
|
await page.close();
|
|
277
277
|
});
|
|
278
278
|
});
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import { useCallback, useMemo, useRef } from 'react';
|
|
6
6
|
|
|
7
|
-
import { isMutable, toJsonSchema } from '@dxos/echo
|
|
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 { DataType, ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
|
|
14
14
|
|
|
15
15
|
import { type TableController } from '../components';
|
|
16
16
|
import { useAddRow, useTableModel } from '../hooks';
|
|
@@ -28,12 +28,15 @@ export const useTestTableModel = () => {
|
|
|
28
28
|
|
|
29
29
|
const views = useQuery(space, Filter.type(DataType.View));
|
|
30
30
|
const view = useMemo(() => views.at(0), [views]);
|
|
31
|
-
const
|
|
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
|
-
|
|
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?.
|
|
98
|
+
const insertResult = model?.insertRow();
|
|
99
|
+
tableRef.current?.handleInsertRowResult?.(insertResult);
|
|
97
100
|
}, [model, tableRef.current]);
|
|
98
101
|
|
|
99
102
|
const handleSaveView = useCallback(() => {
|
package/src/types/index.ts
CHANGED
package/src/types/schema.ts
CHANGED
|
@@ -2,15 +2,72 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
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/
|
|
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 { type CreateViewFromSpaceProps, type DataType, createViewFromSpace, getSchemaProperties } from '@dxos/schema';
|
|
9
13
|
|
|
10
|
-
export const
|
|
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(
|
|
16
|
-
|
|
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<CreateViewFromSpaceProps, '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: DataType.View;
|
|
44
|
+
schema: ReturnType<typeof toEffectSchema>;
|
|
45
|
+
}> => {
|
|
46
|
+
const table = Obj.make(Table, { sizes: {} });
|
|
47
|
+
const { jsonSchema, view } = await createViewFromSpace({ ...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,21 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import type * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { Obj } from '@dxos/echo';
|
|
8
|
-
import { getTypename, toJsonSchema } from '@dxos/echo
|
|
9
|
-
import type { JsonSchemaType
|
|
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
11
|
type DataType,
|
|
12
12
|
ProjectionModel,
|
|
13
13
|
type SchemaPropertyDefinition,
|
|
14
|
+
type SortDirectionType,
|
|
14
15
|
createView,
|
|
15
16
|
getSchemaFromPropertyDefinitions,
|
|
16
17
|
} from '@dxos/schema';
|
|
17
18
|
|
|
18
|
-
import {
|
|
19
|
+
import { Table } from '../types';
|
|
19
20
|
|
|
20
21
|
// TODO(ZaymonFC): Upstream these extra fields to SchemaPropertyDefinition to enhance schema-tools schema creation.
|
|
21
22
|
type PropertyDisplayProps = {
|
|
@@ -54,23 +55,22 @@ export const getBaseSchema = ({
|
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
export const makeDynamicTable = ({
|
|
57
|
-
typename,
|
|
58
58
|
jsonSchema,
|
|
59
59
|
properties,
|
|
60
60
|
}: {
|
|
61
|
-
typename: string;
|
|
62
61
|
jsonSchema: JsonSchemaType;
|
|
63
62
|
properties?: TablePropertyDefinition[];
|
|
64
63
|
}): { projection: ProjectionModel; view: DataType.View } => {
|
|
65
|
-
const table = Obj.make(
|
|
64
|
+
const table = Obj.make(Table.Table, { sizes: {} });
|
|
66
65
|
const view = createView({
|
|
67
|
-
|
|
66
|
+
query: Query.select(Filter.everything()),
|
|
68
67
|
jsonSchema,
|
|
69
68
|
presentation: table,
|
|
70
69
|
...(properties && { fields: properties.map((property) => property.name) }),
|
|
71
70
|
});
|
|
72
71
|
|
|
73
72
|
const projection = new ProjectionModel(jsonSchema, view.projection);
|
|
73
|
+
projection.normalizeView();
|
|
74
74
|
if (properties && projection.fields) {
|
|
75
75
|
setProperties(view, projection, table, properties);
|
|
76
76
|
}
|
|
@@ -81,7 +81,7 @@ export const makeDynamicTable = ({
|
|
|
81
81
|
const setProperties = (
|
|
82
82
|
view: DataType.View,
|
|
83
83
|
projection: ProjectionModel,
|
|
84
|
-
table:
|
|
84
|
+
table: Table.Table,
|
|
85
85
|
properties: TablePropertyDefinition[],
|
|
86
86
|
) => {
|
|
87
87
|
for (const property of properties) {
|
|
@@ -101,7 +101,7 @@ const setProperties = (
|
|
|
101
101
|
|
|
102
102
|
if (property.sort) {
|
|
103
103
|
const fieldId = field.id;
|
|
104
|
-
view.
|
|
104
|
+
view.sort = [{ fieldId, direction: property.sort }];
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
package/src/util/index.ts
CHANGED
package/src/util/schema.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
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
|
-
|
|
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
|
-
}
|