@dxos/react-ui-table 0.7.4 → 0.7.5-main.499c70c
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-IYCSJDMB.mjs → chunk-AT7O4RAD.mjs} +4 -4
- package/dist/lib/browser/{chunk-IYCSJDMB.mjs.map → chunk-AT7O4RAD.mjs.map} +2 -2
- package/dist/lib/browser/index.mjs +1398 -1216
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{chunk-MHBMVCFZ.cjs → chunk-YSBXNBDJ.cjs} +6 -6
- package/dist/lib/node/{chunk-MHBMVCFZ.cjs.map → chunk-YSBXNBDJ.cjs.map} +2 -2
- package/dist/lib/node/index.cjs +1130 -934
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +3 -3
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs → chunk-6OH2NHUX.mjs} +4 -4
- package/dist/lib/node-esm/{chunk-BMWGPXPL.mjs.map → chunk-6OH2NHUX.mjs.map} +2 -2
- package/dist/lib/node-esm/index.mjs +1398 -1216
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts +1 -1
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +4 -3
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -2
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +3 -2
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/RefPanel.d.ts +4 -3
- package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +3 -2
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +2 -1
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -2
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +55 -71
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +1 -0
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +6 -2
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +8 -12
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +22 -0
- package/dist/types/src/model/table-presentation.d.ts.map +1 -0
- package/dist/types/src/model/table-presentation.test.d.ts +2 -0
- package/dist/types/src/model/table-presentation.test.d.ts.map +1 -0
- package/dist/types/src/playwright/TableManager.d.ts +2 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/types/table.d.ts +118 -154
- package/dist/types/src/types/table.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/table-buttons.d.ts +50 -20
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +32 -9
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/table.d.ts +2 -2
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +29 -29
- package/src/components/Table/ColumnActionsMenu.tsx +8 -8
- package/src/components/Table/ColumnSettings.tsx +11 -11
- package/src/components/Table/CreateRefPanel.tsx +10 -10
- package/src/components/Table/RefPanel.tsx +9 -9
- package/src/components/Table/RowActionsMenu.tsx +6 -7
- package/src/components/Table/Table.stories.tsx +40 -23
- package/src/components/Table/Table.tsx +235 -148
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +13 -12
- package/src/components/TableCellEditor/TableCellEditor.tsx +6 -4
- package/src/components/testing.ts +10 -8
- package/src/index.ts +2 -0
- package/src/model/index.ts +1 -0
- package/src/model/modal-controller.ts +15 -48
- package/src/model/selection-model.ts +12 -1
- package/src/model/table-model.test.ts +4 -71
- package/src/model/table-model.ts +59 -232
- package/src/model/table-presentation.test.ts +102 -0
- package/src/model/table-presentation.ts +214 -0
- package/src/playwright/TableManager.ts +5 -1
- package/src/playwright/smoke.spec.ts +64 -1
- package/src/types/table.ts +3 -3
- package/src/util/index.ts +1 -0
- package/src/util/table-buttons.ts +97 -48
- package/src/util/table-controls.ts +71 -7
- package/src/util/table.ts +21 -13
|
@@ -9,6 +9,8 @@ import React, {
|
|
|
9
9
|
useImperativeHandle,
|
|
10
10
|
useState,
|
|
11
11
|
type WheelEvent,
|
|
12
|
+
type MouseEvent,
|
|
13
|
+
useMemo,
|
|
12
14
|
} from 'react';
|
|
13
15
|
|
|
14
16
|
import { getValue } from '@dxos/echo-schema';
|
|
@@ -25,8 +27,9 @@ import { ColumnSettings } from './ColumnSettings';
|
|
|
25
27
|
import { CreateRefPanel } from './CreateRefPanel';
|
|
26
28
|
import { RefPanel } from './RefPanel';
|
|
27
29
|
import { RowActionsMenu } from './RowActionsMenu';
|
|
28
|
-
import { type TableModel } from '../../model';
|
|
30
|
+
import { ModalController, type TableModel, type TablePresentation } from '../../model';
|
|
29
31
|
import { translationKey } from '../../translations';
|
|
32
|
+
import { tableButtons, tableControls } from '../../util';
|
|
30
33
|
import { createOption, TableCellEditor, type TableCellEditorProps } from '../TableCellEditor';
|
|
31
34
|
|
|
32
35
|
// NOTE(Zan): These fragments add border to inline-end and block-end of the grid using pseudo-elements.
|
|
@@ -70,174 +73,258 @@ export type TableController = {
|
|
|
70
73
|
|
|
71
74
|
export type TableMainProps = {
|
|
72
75
|
model?: TableModel;
|
|
76
|
+
presentation?: TablePresentation;
|
|
73
77
|
ignoreAttention?: boolean;
|
|
74
78
|
};
|
|
75
79
|
|
|
76
|
-
const TableMain = forwardRef<TableController, TableMainProps>(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
const TableMain = forwardRef<TableController, TableMainProps>(
|
|
81
|
+
({ model, presentation, ignoreAttention }, forwardedRef) => {
|
|
82
|
+
const [dxGrid, setDxGrid] = useState<DxGridElement | null>(null);
|
|
83
|
+
const { hasAttention } = useAttention(model?.table ? fullyQualifiedId(model.table) : 'table');
|
|
84
|
+
const { t } = useTranslation(translationKey);
|
|
85
|
+
const modals = useMemo(() => new ModalController(), []);
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Provides an external controller that can be called to repaint the table.
|
|
89
|
+
*/
|
|
90
|
+
useImperativeHandle<TableController, TableController>(
|
|
91
|
+
forwardedRef,
|
|
92
|
+
() => {
|
|
93
|
+
if (!presentation || !dxGrid) {
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
|
|
98
|
+
return {
|
|
99
|
+
update: (cell) => {
|
|
100
|
+
if (cell) {
|
|
101
|
+
dxGrid.updateIfWithinBounds(cell);
|
|
102
|
+
} else {
|
|
103
|
+
dxGrid.updateCells(true);
|
|
104
|
+
dxGrid.requestUpdate();
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
[presentation, dxGrid],
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const handleGridClick = useCallback(
|
|
113
|
+
(event: MouseEvent) => {
|
|
114
|
+
if (!modals) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
90
117
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
const buttonSelector = Object.values(tableButtons)
|
|
119
|
+
.map((button) => `button[${button.attr}]`)
|
|
120
|
+
.join(',');
|
|
121
|
+
|
|
122
|
+
const tableButtonElement = (event.target as HTMLElement).closest(buttonSelector) as HTMLElement;
|
|
123
|
+
if (tableButtonElement) {
|
|
124
|
+
const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
|
|
125
|
+
if (!button) {
|
|
126
|
+
return;
|
|
98
127
|
}
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
[model, dxGrid],
|
|
103
|
-
);
|
|
104
128
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
129
|
+
modals.setTrigger(tableButtonElement);
|
|
130
|
+
const data = button.getData(tableButtonElement);
|
|
131
|
+
switch (data.type) {
|
|
132
|
+
case 'rowMenu': {
|
|
133
|
+
modals.showRowMenu(data.rowIndex);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case 'columnSettings': {
|
|
137
|
+
modals.showColumnMenu(data.fieldId);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case 'newColumn': {
|
|
141
|
+
modals.showColumnCreator();
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case 'referencedCell': {
|
|
145
|
+
modals.showReferencePanel(data.targetId, data.schemaId);
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
113
151
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
152
|
+
const controlSelector = Object.values(tableControls)
|
|
153
|
+
.map((control) => `input[${control.attr}]`)
|
|
154
|
+
.join(',');
|
|
155
|
+
|
|
156
|
+
const controlElement = (event.target as HTMLElement).closest(controlSelector) as HTMLElement;
|
|
157
|
+
if (controlElement) {
|
|
158
|
+
const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
|
|
159
|
+
if (!control) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const data = control.getData(controlElement);
|
|
164
|
+
switch (data.type) {
|
|
165
|
+
case 'checkbox': {
|
|
166
|
+
if (data.header) {
|
|
167
|
+
model?.selection.setSelection(model.selection.allRowsSeleted.value ? 'none' : 'all');
|
|
168
|
+
} else {
|
|
169
|
+
model?.selection.toggleSelectionForRowIndex(data.rowIndex);
|
|
170
|
+
}
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'switch': {
|
|
174
|
+
if (model) {
|
|
175
|
+
model.updateCellData({ row: data.rowIndex, col: data.colIndex }, (value) => !value);
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
[model, modals],
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const handleFocus = useCallback<NonNullable<TableCellEditorProps['onFocus']>>(
|
|
186
|
+
(increment, delta) => {
|
|
119
187
|
if (dxGrid) {
|
|
120
|
-
|
|
121
|
-
dxGrid?.scrollToRow(cell.row + 1);
|
|
122
|
-
dxGrid?.refocus('row', 1);
|
|
123
|
-
});
|
|
188
|
+
dxGrid.refocus(increment, delta);
|
|
124
189
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
);
|
|
190
|
+
},
|
|
191
|
+
[dxGrid],
|
|
192
|
+
);
|
|
129
193
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
194
|
+
const handleEnter = useCallback<NonNullable<TableCellEditorProps['onEnter']>>(
|
|
195
|
+
(cell) => {
|
|
196
|
+
// TODO(burdon): Insert row only if bottom row isn't completely blank already.
|
|
197
|
+
if (model && cell.row === model.getRowCount() - 1) {
|
|
198
|
+
model.insertRow(cell.row);
|
|
199
|
+
if (dxGrid) {
|
|
200
|
+
requestAnimationFrame(() => {
|
|
201
|
+
dxGrid?.scrollToRow(cell.row + 1);
|
|
202
|
+
dxGrid?.refocus('row', 1);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
[model, dxGrid],
|
|
208
|
+
);
|
|
136
209
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
210
|
+
const handleKeyDown = useCallback<NonNullable<GridContentProps['onKeyDown']>>(
|
|
211
|
+
(event) => {
|
|
212
|
+
const cell = closestCell(event.target);
|
|
213
|
+
if (!model || !cell) {
|
|
214
|
+
return;
|
|
142
215
|
}
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
[model],
|
|
146
|
-
);
|
|
147
216
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
217
|
+
switch (event.key) {
|
|
218
|
+
case 'Backspace':
|
|
219
|
+
case 'Delete': {
|
|
220
|
+
model.setCellData(cell, undefined);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
[model],
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
|
|
229
|
+
(event) => {
|
|
230
|
+
if (event.axis === 'col') {
|
|
231
|
+
const columnIndex = parseInt(event.index, 10);
|
|
232
|
+
model?.setColumnWidth(columnIndex, event.size);
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
[model],
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const handleWheel = useCallback(
|
|
239
|
+
(event: WheelEvent) => {
|
|
240
|
+
if (!ignoreAttention && !hasAttention) {
|
|
241
|
+
event.stopPropagation();
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
[hasAttention, ignoreAttention],
|
|
245
|
+
);
|
|
157
246
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (
|
|
161
|
-
|
|
247
|
+
const handleNewColumn = useCallback(() => {
|
|
248
|
+
const columns = model?.getColumnCount();
|
|
249
|
+
if (dxGrid && columns) {
|
|
250
|
+
dxGrid.scrollToColumn(columns - 1);
|
|
162
251
|
}
|
|
163
|
-
},
|
|
164
|
-
[hasAttention, ignoreAttention],
|
|
165
|
-
);
|
|
252
|
+
}, [model, dxGrid]);
|
|
166
253
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
254
|
+
// TODO(burdon): Factor out?
|
|
255
|
+
// TODO(burdon): Generalize to handle other value types (e.g., enums).
|
|
256
|
+
const handleQuery = useCallback<NonNullable<TableCellEditorProps['onQuery']>>(
|
|
257
|
+
async ({ field, props }, text) => {
|
|
258
|
+
if (model && props.referenceSchema && field.referencePath) {
|
|
259
|
+
const space = getSpace(model.table);
|
|
260
|
+
invariant(space);
|
|
261
|
+
const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
|
|
262
|
+
if (schema) {
|
|
263
|
+
const { objects } = await space.db.query(Filter.schema(schema)).run();
|
|
264
|
+
const options = objects
|
|
265
|
+
.map((obj) => {
|
|
266
|
+
const value = getValue(obj, field.referencePath!);
|
|
267
|
+
if (!value || typeof value !== 'string') {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
label: value,
|
|
273
|
+
data: obj,
|
|
274
|
+
};
|
|
275
|
+
})
|
|
276
|
+
.filter(isNotFalsy);
|
|
190
277
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
...options,
|
|
200
|
-
{
|
|
201
|
-
label: t('create new object label', { text }),
|
|
202
|
-
data: createOption(text),
|
|
203
|
-
},
|
|
204
|
-
];
|
|
278
|
+
return [
|
|
279
|
+
...options,
|
|
280
|
+
{
|
|
281
|
+
label: t('create new object label', { text }),
|
|
282
|
+
data: createOption(text),
|
|
283
|
+
},
|
|
284
|
+
];
|
|
285
|
+
}
|
|
205
286
|
}
|
|
206
|
-
}
|
|
207
287
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
288
|
+
return [];
|
|
289
|
+
},
|
|
290
|
+
[model],
|
|
291
|
+
);
|
|
212
292
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
293
|
+
if (!model || !modals) {
|
|
294
|
+
return <span role='none' className='attention-surface' />;
|
|
295
|
+
}
|
|
216
296
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
297
|
+
return (
|
|
298
|
+
<Grid.Root id={model.table.id ?? 'table-grid'}>
|
|
299
|
+
<TableCellEditor
|
|
300
|
+
model={model}
|
|
301
|
+
modals={modals}
|
|
302
|
+
onEnter={handleEnter}
|
|
303
|
+
onFocus={handleFocus}
|
|
304
|
+
onQuery={handleQuery}
|
|
305
|
+
/>
|
|
306
|
+
<Grid.Content
|
|
307
|
+
onWheelCapture={handleWheel}
|
|
308
|
+
className={mx('[--dx-grid-base:var(--surface-bg)]', inlineEndLine, blockEndLine)}
|
|
309
|
+
frozen={frozen}
|
|
310
|
+
columns={model.columnMeta.value}
|
|
311
|
+
limitRows={model.getRowCount() ?? 0}
|
|
312
|
+
limitColumns={model.table.view?.target?.fields?.length ?? 0}
|
|
313
|
+
onAxisResize={handleAxisResize}
|
|
314
|
+
onClick={handleGridClick}
|
|
315
|
+
onKeyDown={handleKeyDown}
|
|
316
|
+
overscroll='trap'
|
|
317
|
+
ref={setDxGrid}
|
|
318
|
+
/>
|
|
319
|
+
<RowActionsMenu model={model} modals={modals} />
|
|
320
|
+
<ColumnActionsMenu model={model} modals={modals} />
|
|
321
|
+
<ColumnSettings model={model} modals={modals} onNewColumn={handleNewColumn} />
|
|
322
|
+
<RefPanel model={model} modals={modals} />
|
|
323
|
+
<CreateRefPanel model={model} modals={modals} />
|
|
324
|
+
</Grid.Root>
|
|
325
|
+
);
|
|
326
|
+
},
|
|
327
|
+
);
|
|
241
328
|
|
|
242
329
|
//
|
|
243
330
|
// CellEditor
|
|
@@ -7,11 +7,11 @@ import '@dxos-theme';
|
|
|
7
7
|
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
8
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import { type
|
|
10
|
+
import { type EchoSchema } from '@dxos/echo-schema';
|
|
11
11
|
import { invariant } from '@dxos/invariant';
|
|
12
12
|
import { faker } from '@dxos/random';
|
|
13
|
-
import { Filter,
|
|
14
|
-
import { withClientProvider } from '@dxos/react-client/testing';
|
|
13
|
+
import { Filter, useQuery, create } from '@dxos/react-client/echo';
|
|
14
|
+
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
15
15
|
import { defaultSizeRow, Grid, type GridEditing } from '@dxos/react-ui-grid';
|
|
16
16
|
import { ViewProjection, ViewType } from '@dxos/schema';
|
|
17
17
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
@@ -27,23 +27,24 @@ type StoryProps = {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const DefaultStory = ({ editing }: StoryProps) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
30
|
+
const { space } = useClientProvider();
|
|
31
|
+
invariant(space);
|
|
32
|
+
|
|
32
33
|
const tables = useQuery(space, Filter.schema(TableType));
|
|
33
34
|
const [table, setTable] = useState<TableType>();
|
|
34
|
-
const [schema, setSchema] = useState<
|
|
35
|
+
const [schema, setSchema] = useState<EchoSchema>();
|
|
35
36
|
useEffect(() => {
|
|
36
|
-
if (tables.length && !table) {
|
|
37
|
+
if (space && tables.length && !table) {
|
|
37
38
|
const table = tables[0];
|
|
38
39
|
invariant(table.view);
|
|
39
40
|
setTable(table);
|
|
40
|
-
setSchema(space.db.schemaRegistry.getSchema(table.view.query.type));
|
|
41
|
+
setSchema(space.db.schemaRegistry.getSchema(table.view.target!.query.type));
|
|
41
42
|
}
|
|
42
|
-
}, [tables]);
|
|
43
|
+
}, [space, tables]);
|
|
43
44
|
|
|
44
45
|
const projection = useMemo(() => {
|
|
45
46
|
if (schema && table?.view) {
|
|
46
|
-
return new ViewProjection(schema, table.view);
|
|
47
|
+
return new ViewProjection(schema, table.view.target!);
|
|
47
48
|
}
|
|
48
49
|
}, [schema, table?.view]);
|
|
49
50
|
|
|
@@ -83,9 +84,9 @@ const meta: Meta<StoryProps> = {
|
|
|
83
84
|
types: [TableType, ViewType],
|
|
84
85
|
createIdentity: true,
|
|
85
86
|
createSpace: true,
|
|
86
|
-
onSpaceCreated: ({ space }) => {
|
|
87
|
+
onSpaceCreated: async ({ space }) => {
|
|
87
88
|
const table = space.db.add(create(TableType, {}));
|
|
88
|
-
const schema = initializeTable({ space, table });
|
|
89
|
+
const schema = await initializeTable({ space, table });
|
|
89
90
|
Array.from({ length: 10 }).forEach(() => {
|
|
90
91
|
space.db.add(
|
|
91
92
|
create(schema, {
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import { type FieldProjection } from '@dxos/schema';
|
|
25
25
|
|
|
26
26
|
import { completion } from './extension';
|
|
27
|
-
import { type TableModel } from '../../model';
|
|
27
|
+
import { type TableModel, type ModalController } from '../../model';
|
|
28
28
|
|
|
29
29
|
const newValue = Symbol.for('newValue');
|
|
30
30
|
|
|
@@ -39,6 +39,7 @@ export type QueryResult = Pick<Completion, 'label'> & { data: any };
|
|
|
39
39
|
|
|
40
40
|
export type TableCellEditorProps = {
|
|
41
41
|
model?: TableModel;
|
|
42
|
+
modals?: ModalController;
|
|
42
43
|
onEnter?: (cell: DxGridPlanePosition) => void;
|
|
43
44
|
onFocus?: DxGrid['refocus'];
|
|
44
45
|
onQuery?: (field: FieldProjection, text: string) => Promise<QueryResult[]>;
|
|
@@ -46,6 +47,7 @@ export type TableCellEditorProps = {
|
|
|
46
47
|
|
|
47
48
|
export const TableCellEditor = ({
|
|
48
49
|
model,
|
|
50
|
+
modals,
|
|
49
51
|
onEnter,
|
|
50
52
|
onFocus,
|
|
51
53
|
onQuery,
|
|
@@ -133,12 +135,12 @@ export const TableCellEditor = ({
|
|
|
133
135
|
completion({
|
|
134
136
|
onQuery: (text) => onQuery(fieldProjection, text),
|
|
135
137
|
onMatch: (data) => {
|
|
136
|
-
if (model && editing) {
|
|
138
|
+
if (model && editing && modals) {
|
|
137
139
|
if (isCreateOption(data)) {
|
|
138
140
|
const { field, props } = fieldProjection;
|
|
139
141
|
if (props.referenceSchema) {
|
|
140
142
|
suppressNextBlur.current = true;
|
|
141
|
-
|
|
143
|
+
modals.openCreateRef(
|
|
142
144
|
props.referenceSchema,
|
|
143
145
|
document.querySelector(cellQuery(editing.index, gridId)),
|
|
144
146
|
{
|
|
@@ -162,7 +164,7 @@ export const TableCellEditor = ({
|
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
return extension;
|
|
165
|
-
}, [model, editing, fieldProjection, handleClose]);
|
|
167
|
+
}, [model, modals, editing, fieldProjection, handleClose]);
|
|
166
168
|
|
|
167
169
|
const getCellContent = useCallback<GridCellEditorProps['getCellContent']>(() => {
|
|
168
170
|
if (model && editing) {
|
|
@@ -6,7 +6,7 @@ import { useEffect } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { setValue, toJsonSchema, S, TypeEnum, TypedObject, FormatEnum } from '@dxos/echo-schema';
|
|
8
8
|
import { faker } from '@dxos/random';
|
|
9
|
-
import { create } from '@dxos/react-client/echo';
|
|
9
|
+
import { create, makeRef } from '@dxos/react-client/echo';
|
|
10
10
|
import { createView, type ViewProjection } from '@dxos/schema';
|
|
11
11
|
import {} from '@dxos/schema';
|
|
12
12
|
|
|
@@ -22,11 +22,13 @@ export const TestSchema = TypedObject({ typename: 'example.com/type/Test', versi
|
|
|
22
22
|
|
|
23
23
|
export const createTable = (schema = TestSchema) => {
|
|
24
24
|
return create(TableType, {
|
|
25
|
-
view:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
view: makeRef(
|
|
26
|
+
createView({
|
|
27
|
+
name: 'Test',
|
|
28
|
+
typename: schema.typename,
|
|
29
|
+
jsonSchema: toJsonSchema(schema),
|
|
30
|
+
}),
|
|
31
|
+
),
|
|
30
32
|
});
|
|
31
33
|
};
|
|
32
34
|
|
|
@@ -71,7 +73,7 @@ export const useSimulator = ({ items, table, insertInterval, updateInterval }: S
|
|
|
71
73
|
|
|
72
74
|
const i = setInterval(() => {
|
|
73
75
|
const rowIdx = Math.floor(Math.random() * items.length);
|
|
74
|
-
const fields = table.view?.fields ?? [];
|
|
76
|
+
const fields = table.view?.target?.fields ?? [];
|
|
75
77
|
const columnIdx = Math.floor(Math.random() * fields.length);
|
|
76
78
|
const projection: ViewProjection = (table as any)._projection;
|
|
77
79
|
const field = fields[columnIdx];
|
|
@@ -111,5 +113,5 @@ export const useSimulator = ({ items, table, insertInterval, updateInterval }: S
|
|
|
111
113
|
}, updateInterval);
|
|
112
114
|
|
|
113
115
|
return () => clearInterval(i);
|
|
114
|
-
}, [items, table.view?.fields, updateInterval]);
|
|
116
|
+
}, [items, table.view?.target?.fields, updateInterval]);
|
|
115
117
|
};
|
package/src/index.ts
CHANGED
package/src/model/index.ts
CHANGED