@dxos/react-ui-table 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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 (172) hide show
  1. package/dist/lib/browser/chunk-BF54SSNL.mjs +70 -0
  2. package/dist/lib/browser/chunk-BF54SSNL.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-F7Y374KL.mjs +1751 -0
  4. package/dist/lib/browser/chunk-F7Y374KL.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1195 -2846
  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 +114 -0
  9. package/dist/lib/browser/testing/index.mjs.map +7 -0
  10. package/dist/lib/browser/types/index.mjs +3 -5
  11. package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs +1753 -0
  12. package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs +71 -0
  14. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +1195 -2846
  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 +115 -0
  19. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  20. package/dist/lib/node-esm/types/index.mjs +3 -5
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +2 -3
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +4 -2
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/DynamicTable.d.ts +7 -7
  26. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +35 -3
  28. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Relations.stories.d.ts +110 -0
  30. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  31. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  32. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.d.ts +21 -18
  34. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  35. package/dist/types/src/components/Table/Table.stories.d.ts +109 -6
  36. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/Table/TableContent.d.ts +17 -0
  38. package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
  39. package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
  40. package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
  41. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
  42. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  43. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +14 -9
  44. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  45. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +12 -18
  46. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  47. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +38 -5
  48. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  49. package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
  50. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
  51. package/dist/types/src/components/index.d.ts +0 -1
  52. package/dist/types/src/components/index.d.ts.map +1 -1
  53. package/dist/types/src/components/testing.d.ts +26 -56
  54. package/dist/types/src/components/testing.d.ts.map +1 -1
  55. package/dist/types/src/hooks/index.d.ts +2 -1
  56. package/dist/types/src/hooks/index.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useAddRow.d.ts +6 -6
  58. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
  60. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  61. package/dist/types/src/hooks/useTableModel.d.ts +11 -10
  62. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  63. package/dist/types/src/index.d.ts +0 -1
  64. package/dist/types/src/index.d.ts.map +1 -1
  65. package/dist/types/src/model/modal-controller.d.ts +5 -8
  66. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  67. package/dist/types/src/model/selection-model.d.ts +17 -7
  68. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  69. package/dist/types/src/model/table-model.d.ts +116 -34
  70. package/dist/types/src/model/table-model.d.ts.map +1 -1
  71. package/dist/types/src/model/table-presentation.d.ts +5 -2
  72. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  73. package/dist/types/src/playwright/TableManager.d.ts +2 -1
  74. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  75. package/dist/types/src/testing/index.d.ts +2 -0
  76. package/dist/types/src/testing/index.d.ts.map +1 -0
  77. package/dist/types/src/testing/useTestTableModel.d.ts +25 -0
  78. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
  79. package/dist/types/src/translations.d.ts +21 -23
  80. package/dist/types/src/translations.d.ts.map +1 -1
  81. package/dist/types/src/types/Table.d.ts +26 -0
  82. package/dist/types/src/types/Table.d.ts.map +1 -0
  83. package/dist/types/src/types/index.d.ts +1 -1
  84. package/dist/types/src/types/index.d.ts.map +1 -1
  85. package/dist/types/src/util/dynamic-table.d.ts +15 -14
  86. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  87. package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
  88. package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
  89. package/dist/types/src/util/index.d.ts +2 -1
  90. package/dist/types/src/util/index.d.ts.map +1 -1
  91. package/dist/types/src/util/query-ast.d.ts +7 -0
  92. package/dist/types/src/util/query-ast.d.ts.map +1 -0
  93. package/dist/types/src/util/schema.d.ts +1 -1
  94. package/dist/types/src/util/schema.d.ts.map +1 -1
  95. package/dist/types/src/util/sort.d.ts +12 -0
  96. package/dist/types/src/util/sort.d.ts.map +1 -0
  97. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  98. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  99. package/dist/types/tsconfig.tsbuildinfo +1 -1
  100. package/package.json +70 -55
  101. package/src/components/Table/ColumnActionsMenu.tsx +16 -12
  102. package/src/components/Table/ColumnSettings.tsx +18 -15
  103. package/src/components/Table/DynamicTable.stories.tsx +38 -35
  104. package/src/components/Table/DynamicTable.tsx +38 -34
  105. package/src/components/Table/Relations.stories.tsx +245 -0
  106. package/src/components/Table/RowActionsMenu.tsx +26 -17
  107. package/src/components/Table/Table.stories.tsx +196 -218
  108. package/src/components/Table/Table.tsx +47 -376
  109. package/src/components/Table/TableContent.tsx +421 -0
  110. package/src/components/Table/TableToolbar.tsx +111 -0
  111. package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -6
  112. package/src/components/TableCellEditor/FormCellEditor.tsx +152 -49
  113. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +37 -77
  114. package/src/components/TableCellEditor/TableCellEditor.tsx +104 -233
  115. package/src/components/TableCellEditor/index.ts +1 -0
  116. package/src/components/index.ts +0 -1
  117. package/src/components/testing.ts +46 -37
  118. package/src/hooks/index.ts +2 -1
  119. package/src/hooks/useAddRow.ts +14 -14
  120. package/src/hooks/useProjectionModel.ts +39 -0
  121. package/src/hooks/useTableModel.ts +41 -35
  122. package/src/index.ts +0 -1
  123. package/src/model/modal-controller.ts +24 -41
  124. package/src/model/selection-model.ts +75 -41
  125. package/src/model/table-model.test.ts +91 -56
  126. package/src/model/table-model.ts +468 -187
  127. package/src/model/table-presentation.test.ts +69 -59
  128. package/src/model/table-presentation.ts +112 -66
  129. package/src/playwright/TableManager.ts +13 -6
  130. package/src/playwright/playwright.config.ts +1 -1
  131. package/src/playwright/smoke.spec.ts +180 -43
  132. package/src/testing/index.ts +5 -0
  133. package/src/testing/useTestTableModel.ts +133 -0
  134. package/src/translations.ts +20 -22
  135. package/src/types/Table.ts +79 -0
  136. package/src/types/index.ts +2 -2
  137. package/src/util/dynamic-table.test.ts +70 -0
  138. package/src/util/dynamic-table.ts +51 -36
  139. package/src/util/index.ts +2 -1
  140. package/src/util/query-ast.ts +22 -0
  141. package/src/util/schema.ts +4 -4
  142. package/src/util/sort.ts +90 -0
  143. package/src/util/table-buttons.ts +4 -3
  144. package/src/util/table-controls.ts +6 -3
  145. package/dist/lib/browser/chunk-Q5QQXJUO.mjs +0 -27
  146. package/dist/lib/browser/chunk-Q5QQXJUO.mjs.map +0 -7
  147. package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs +0 -29
  148. package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs.map +0 -7
  149. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  150. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  151. package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
  152. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
  153. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  154. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  155. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
  156. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
  157. package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
  158. package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
  159. package/dist/types/src/model/table-sorting.d.ts +0 -53
  160. package/dist/types/src/model/table-sorting.d.ts.map +0 -1
  161. package/dist/types/src/types/table.d.ts +0 -56
  162. package/dist/types/src/types/table.d.ts.map +0 -1
  163. package/dist/types/src/util/table.d.ts +0 -14
  164. package/dist/types/src/util/table.d.ts.map +0 -1
  165. package/src/components/Table/CreateRefPanel.tsx +0 -84
  166. package/src/components/Table/relations.stories.tsx +0 -123
  167. package/src/components/TableCellEditor/extension.ts +0 -61
  168. package/src/components/TableToolbar/TableToolbar.tsx +0 -102
  169. package/src/components/TableToolbar/index.ts +0 -5
  170. package/src/model/table-sorting.ts +0 -216
  171. package/src/types/table.ts +0 -27
  172. package/src/util/table.ts +0 -127
@@ -2,404 +2,75 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect/Schema';
6
- import React, {
7
- type MouseEvent,
8
- type PropsWithChildren,
9
- type WheelEvent,
10
- forwardRef,
11
- useCallback,
12
- useImperativeHandle,
13
- useState,
14
- useMemo,
15
- useEffect,
16
- } from 'react';
5
+ import { Atom } from '@effect-atom/atom-react';
6
+ import { createContext } from '@radix-ui/react-context';
7
+ import React, { type PropsWithChildren, type RefObject, forwardRef, useImperativeHandle, useRef } from 'react';
17
8
 
18
- import { type Client } from '@dxos/client';
19
- import { getValue } from '@dxos/echo-schema';
20
- import { invariant } from '@dxos/invariant';
21
- import { Filter } from '@dxos/react-client/echo';
22
- import { useTranslation } from '@dxos/react-ui';
23
- import { useAttention } from '@dxos/react-ui-attention';
24
- import {
25
- closestCell,
26
- type DxGridElement,
27
- type DxGridPosition,
28
- type GridContentProps,
29
- Grid,
30
- type DxGridPlane,
31
- type DxGridPlaneRange,
32
- gridSeparatorInlineEnd,
33
- gridSeparatorBlockEnd,
34
- } from '@dxos/react-ui-grid';
35
- import { mx } from '@dxos/react-ui-theme';
36
- import { isNotFalsy, safeParseInt } from '@dxos/util';
9
+ import { type DxGridAxisMeta, type DxGridPosition } from '@dxos/react-ui-grid';
37
10
 
38
- import { ColumnActionsMenu } from './ColumnActionsMenu';
39
- import { ColumnSettings } from './ColumnSettings';
40
- import { CreateRefPanel } from './CreateRefPanel';
41
- import { RowActionsMenu } from './RowActionsMenu';
42
- import { ModalController, type TableModel, type TablePresentation } from '../../model';
43
- import { translationKey } from '../../translations';
44
- import { tableButtons, tableControls } from '../../util';
45
- import { createOption, TableValueEditor, type TableCellEditorProps } from '../TableCellEditor';
11
+ import { type InsertRowResult } from '../../model';
12
+ import { TableContent } from './TableContent';
13
+ import { TableToolbar } from './TableToolbar';
14
+
15
+ const columnDefault = { grid: { minSize: 80, maxSize: 640 } };
16
+ const rowDefault = { frozenRowsStart: { readonly: true, focusUnfurl: false } };
17
+ const emptyColumnMeta = Atom.make<DxGridAxisMeta>({ grid: {} });
46
18
 
47
19
  //
48
- // Table.Root
20
+ // Context
49
21
  //
50
22
 
51
- export type TableRootProps = PropsWithChildren<{ role?: string }>;
52
-
53
- const TableRoot = ({ children, role }: TableRootProps) => {
54
- return (
55
- <div
56
- role='none'
57
- className={mx(
58
- 'relative !border-separator',
59
- role === 'section' // TODO(burdon): This leaks composer plugin concepts? Standardize for react-ui?
60
- ? 'attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]'
61
- : 'flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]',
62
- )}
63
- >
64
- {children}
65
- </div>
66
- );
23
+ type TableContextValue = {
24
+ /** Mutable ref populated by Content so Root can expose the controller. */
25
+ controllerRef: RefObject<TableController>;
67
26
  };
68
27
 
28
+ const [TableContextProvider, useTableContext] = createContext<TableContextValue>('Table');
29
+
69
30
  //
70
- // Table.Main
31
+ // Controller
71
32
  //
72
33
 
73
- export type TableController = {
34
+ type TableController = {
74
35
  update?: (cell?: DxGridPosition) => void;
36
+ handleInsertRowResult?: (insertRowResult?: InsertRowResult) => void;
75
37
  };
76
38
 
77
- export type TableMainProps = {
78
- model?: TableModel;
79
- presentation?: TablePresentation;
80
- schema?: Schema.AnyNoContext;
81
- client?: Client;
82
- // TODO(burdon): Rename since attention isn't a useful concept here? Standardize across other components. Pass property into useAttention.
83
- ignoreAttention?: boolean;
84
- onRowClick?: (row: any) => void;
85
- };
86
-
87
- const TableMain = forwardRef<TableController, TableMainProps>(
88
- ({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
89
- const [dxGrid, setDxGrid] = useState<DxGridElement | null>(null);
90
- const { hasAttention } = useAttention(model?.id ?? 'table');
91
- const { t } = useTranslation(translationKey);
92
- const modals = useMemo(() => new ModalController(), []);
93
-
94
- const draftRowCount = model?.getDraftRowCount() ?? 0;
95
-
96
- const frozen = useMemo(() => {
97
- const noActionColumn =
98
- model?.features.dataEditable === false &&
99
- model?.features.schemaEditable === false &&
100
- model.rowActions.length === 0;
101
-
102
- return {
103
- frozenRowsStart: 1,
104
- frozenRowsEnd: draftRowCount,
105
- frozenColsStart: model?.features.selection.enabled ? 1 : 0,
106
- frozenColsEnd: noActionColumn ? 0 : 1,
107
- };
108
- }, [model, draftRowCount]);
109
-
110
- const getCells = useCallback<NonNullable<GridContentProps['getCells']>>(
111
- (range: DxGridPlaneRange, plane: DxGridPlane) => presentation?.getCells(range, plane) ?? {},
112
- [presentation],
113
- );
114
-
115
- useEffect(() => {
116
- if (!presentation || !dxGrid) {
117
- return;
118
- }
119
- dxGrid.getCells = getCells;
120
- }, [presentation, dxGrid, getCells]);
121
-
122
- /**
123
- * Provides an external controller that can be called to repaint the table.
124
- */
125
- useImperativeHandle<TableController, TableController>(
126
- forwardedRef,
127
- () => {
128
- if (!presentation || !dxGrid) {
129
- return {};
130
- }
131
-
132
- return {
133
- update: (cell) => {
134
- if (cell) {
135
- dxGrid.updateIfWithinBounds(cell);
136
- } else {
137
- dxGrid.updateCells(true);
138
- dxGrid.requestUpdate();
139
- }
140
- },
141
- };
142
- },
143
- [presentation, dxGrid],
144
- );
145
-
146
- const handleGridClick = useCallback(
147
- (event: MouseEvent) => {
148
- const rowIndex = safeParseInt((event.target as HTMLElement).ariaRowIndex ?? '');
149
- if (rowIndex != null) {
150
- if (onRowClick) {
151
- const row = model?.getRowAt(rowIndex);
152
- row && onRowClick(row);
153
- }
154
-
155
- if (model?.features.selection.enabled && model?.selection.selectionMode === 'single') {
156
- model.selection.toggleSelectionForRowIndex(rowIndex);
157
- }
158
- }
159
-
160
- if (!modals) {
161
- return;
162
- }
163
-
164
- const buttonSelector = Object.values(tableButtons)
165
- .map((button) => `button[${button.attr}]`)
166
- .join(',');
167
-
168
- const tableButtonElement = (event.target as HTMLElement).closest(buttonSelector) as HTMLElement;
169
- if (tableButtonElement) {
170
- const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
171
- if (!button) {
172
- return;
173
- }
174
-
175
- modals.setTrigger(tableButtonElement);
176
- const data = button.getData(tableButtonElement);
177
- switch (data.type) {
178
- case 'rowMenu': {
179
- modals.showRowMenu(data.rowIndex);
180
- break;
181
- }
182
- case 'columnSettings': {
183
- modals.showColumnMenu(data.fieldId);
184
- break;
185
- }
186
- case 'newColumn': {
187
- modals.showColumnCreator();
188
- break;
189
- }
190
- case 'sort': {
191
- model?.sorting?.toggleSort(data.fieldId);
192
- break;
193
- }
194
- case 'saveDraftRow': {
195
- if (model) {
196
- const didCommitSuccessfully = model.commitDraftRow(data.rowIndex);
197
- if (dxGrid && didCommitSuccessfully) {
198
- requestAnimationFrame(() => {
199
- dxGrid.scrollToEndRow();
200
- });
201
- }
202
- }
203
- break;
204
- }
205
- }
206
- return;
207
- }
208
-
209
- const controlSelector = Object.values(tableControls)
210
- .map((control) => `input[${control.attr}]`)
211
- .join(',');
212
-
213
- const controlElement = (event.target as HTMLElement).closest(controlSelector) as HTMLElement;
214
- if (controlElement) {
215
- const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
216
- if (!control) {
217
- return;
218
- }
219
-
220
- const data = control.getData(controlElement);
221
- switch (data.type) {
222
- case 'checkbox': {
223
- if (data.header) {
224
- model?.selection.setSelection(model.selection.allRowsSeleted.value ? 'none' : 'all');
225
- } else {
226
- model?.selection.toggleSelectionForRowIndex(data.rowIndex);
227
- }
228
- break;
229
- }
230
- case 'switch': {
231
- if (model) {
232
- model.updateCellData({ row: data.rowIndex, col: data.colIndex }, (value) => !value);
233
- }
234
- break;
235
- }
236
- }
237
- }
238
- },
239
- [model, modals, dxGrid],
240
- );
241
-
242
- const handleFocus = useCallback<NonNullable<TableCellEditorProps['onFocus']>>(
243
- (increment, delta) => {
244
- if (dxGrid) {
245
- dxGrid.refocus(increment, delta);
246
- }
247
- },
248
- [dxGrid],
249
- );
250
-
251
- const handleEnter = useCallback<NonNullable<TableCellEditorProps['onEnter']>>(
252
- (cell) => {
253
- if (!model?.features.dataEditable) {
254
- return;
255
- }
256
-
257
- // TODO(burdon): Insert row only if bottom row isn't completely blank already.
258
- if (model && cell.row === model.getRowCount() - 1) {
259
- model.insertRow();
260
- if (dxGrid) {
261
- requestAnimationFrame(() => {
262
- dxGrid?.scrollToRow(cell.row + 1);
263
- dxGrid?.refocus('row', 1);
264
- });
265
- }
266
- }
267
- },
268
- [model, dxGrid],
269
- );
270
-
271
- const handleKeyDown = useCallback<NonNullable<GridContentProps['onKeyDown']>>(
272
- (event) => {
273
- if (!model?.features.dataEditable) {
274
- return;
275
- }
276
-
277
- const cell = closestCell(event.target);
278
- if (!model || !cell) {
279
- return;
280
- }
281
-
282
- switch (event.key) {
283
- case 'Backspace':
284
- case 'Delete': {
285
- model.setCellData(cell, undefined);
286
- break;
287
- }
288
- }
289
- },
290
- [model],
291
- );
292
-
293
- const handleAxisResize = useCallback<NonNullable<GridContentProps['onAxisResize']>>(
294
- (event) => {
295
- if (event.axis === 'col') {
296
- const columnIndex = parseInt(event.index, 10);
297
- model?.setColumnWidth(columnIndex, event.size);
298
- }
299
- },
300
- [model],
301
- );
302
-
303
- const handleWheel = useCallback(
304
- (event: WheelEvent) => {
305
- if (!ignoreAttention && !hasAttention) {
306
- event.stopPropagation();
307
- }
308
- },
309
- [hasAttention, ignoreAttention],
310
- );
311
-
312
- const handleNewColumn = useCallback(() => {
313
- const columns = model?.getColumnCount();
314
- if (dxGrid && columns) {
315
- dxGrid.scrollToColumn(columns - 1);
316
- }
317
- }, [model, dxGrid]);
318
-
319
- // TODO(burdon): Factor out?
320
- // TODO(burdon): Generalize to handle other value types (e.g., enums).
321
- const handleQuery = useCallback<NonNullable<TableCellEditorProps['onQuery']>>(
322
- async ({ field, props }, text) => {
323
- if (model && props.referenceSchema && field.referencePath) {
324
- const space = model.space;
325
- invariant(space);
39
+ //
40
+ // Root
41
+ //
326
42
 
327
- let schema;
328
- if (client) {
329
- schema = client.graph.schemaRegistry.getSchema(props.referenceSchema);
330
- }
331
- if (!schema) {
332
- schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
333
- }
43
+ const TABLE_ROOT_NAME = 'Table.Root';
334
44
 
335
- if (schema) {
336
- const { objects } = await space.db.query(Filter.type(schema)).run();
337
- const options = objects
338
- .map((obj) => {
339
- const value = getValue(obj, field.referencePath!);
340
- if (!value || typeof value !== 'string') {
341
- return undefined;
342
- }
45
+ type TableRootProps = PropsWithChildren;
343
46
 
344
- return {
345
- label: value,
346
- data: obj,
347
- };
348
- })
349
- .filter(isNotFalsy);
47
+ const TableRoot = forwardRef<TableController, TableRootProps>(({ children }, forwardedRef) => {
48
+ const controllerRef = useRef<TableController>({});
350
49
 
351
- return [
352
- ...options,
353
- {
354
- label: t('create new object label', { text }),
355
- data: createOption(text),
356
- },
357
- ];
358
- }
359
- }
50
+ useImperativeHandle(
51
+ forwardedRef,
52
+ () => ({
53
+ update: (cell) => controllerRef.current?.update?.(cell),
54
+ handleInsertRowResult: (result) => controllerRef.current?.handleInsertRowResult?.(result),
55
+ }),
56
+ [],
57
+ );
360
58
 
361
- return [];
362
- },
363
- [model, client, t],
364
- );
59
+ return <TableContextProvider controllerRef={controllerRef}>{children}</TableContextProvider>;
60
+ });
365
61
 
366
- if (!model || !modals) {
367
- return <span role='none' className='attention-surface' />;
368
- }
62
+ TableRoot.displayName = TABLE_ROOT_NAME;
369
63
 
370
- return (
371
- <Grid.Root id={model.id ?? 'table-grid'}>
372
- <TableValueEditor
373
- model={model}
374
- modals={modals}
375
- schema={schema}
376
- onEnter={handleEnter}
377
- onFocus={handleFocus}
378
- onQuery={handleQuery}
379
- />
380
- <Grid.Content
381
- className={mx('[--dx-grid-base:var(--baseSurface)]', gridSeparatorInlineEnd, gridSeparatorBlockEnd)}
382
- frozen={frozen}
383
- columns={model.columnMeta.value}
384
- limitRows={model.getRowCount() ?? 0}
385
- limitColumns={model.view?.fields?.length ?? 0}
386
- overscroll='trap'
387
- onAxisResize={handleAxisResize}
388
- onClick={handleGridClick}
389
- onKeyDown={handleKeyDown}
390
- onWheelCapture={handleWheel}
391
- ref={setDxGrid}
392
- />
393
- <RowActionsMenu model={model} modals={modals} />
394
- <ColumnActionsMenu model={model} modals={modals} />
395
- <ColumnSettings model={model} modals={modals} onNewColumn={handleNewColumn} />
396
- <CreateRefPanel model={model} modals={modals} />
397
- </Grid.Root>
398
- );
399
- },
400
- );
64
+ //
65
+ // Table
66
+ //
401
67
 
402
68
  export const Table = {
403
69
  Root: TableRoot,
404
- Main: TableMain,
70
+ Toolbar: TableToolbar,
71
+ Content: TableContent,
405
72
  };
73
+
74
+ export type { TableController, TableRootProps };
75
+
76
+ export { useTableContext };