@opencorestack/opengridx 3.6.0 → 3.7.0
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/CHANGELOG.md +17 -0
- package/dist/index.d.ts +30 -0
- package/dist/opengridx.css +1 -1
- package/dist/opengridx.es.js +8566 -8130
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +15 -15
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +3 -2
- package/docs/architecture/datagrid-orchestration.md +46 -29
- package/docs/architecture/grid-row-meta.md +1 -1
- package/docs/customization/slots-api.md +1 -1
- package/docs/customization/theming.md +43 -0
- package/docs/features/virtualization.md +16 -2
- package/docs/performance.md +3 -1
- package/lib/components/AiAssistant/GridAiAssistantPanel.css +3 -1
- package/lib/components/Cell/Cell.css +4 -2
- package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +2 -2
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +3 -1
- package/lib/components/DataGrid/DataGrid.css +9 -9
- package/lib/components/DataGrid/DataGrid.tsx +163 -671
- package/lib/components/DataGrid/GridRoot.tsx +239 -0
- package/lib/components/DataGrid/GridViewport.tsx +314 -0
- package/lib/components/FilterPanel/FilterPanel.css +9 -8
- package/lib/components/Header/ColumnMenu.css +4 -3
- package/lib/components/Header/Header.css +5 -4
- package/lib/components/HeaderFilter/HeaderFilter.css +1 -1
- package/lib/components/Pagination/Pagination.css +1 -1
- package/lib/components/Row/Row.css +2 -2
- package/lib/components/Toolbar/GridToolbar.css +8 -7
- package/lib/components/Toolbar/PivotPanel.css +3 -3
- package/lib/hooks/core/useGridDevWarnings.ts +3 -1
- package/lib/hooks/core/useGridEditPipeline.ts +55 -0
- package/lib/hooks/core/useGridRangeEditing.ts +129 -0
- package/lib/hooks/core/useGridRenderWindow.ts +66 -0
- package/lib/hooks/core/useGridScrollViewport.ts +42 -0
- package/lib/hooks/core/useGridSelectionAndStateApi.ts +61 -0
- package/lib/hooks/core/useGridToolbarStack.ts +49 -0
- package/lib/hooks/core/useGridViewApis.ts +46 -0
- package/lib/styles/base/variables.css +12 -0
- package/lib/theme/DataGridThemeProvider.tsx +15 -0
- package/lib/theme/__baseline__/default-theme.darwin.chromium.json +1503 -0
- package/lib/theme/__baseline__/default-theme.darwin.firefox.json +1503 -0
- package/lib/theme/__baseline__/default-theme.darwin.webkit.json +1503 -0
- package/lib/theme/types.ts +31 -0
- package/lib/types/ai.ts +109 -0
- package/lib/types/api.ts +169 -0
- package/lib/types/columns.ts +341 -0
- package/lib/types/dataSource.ts +40 -0
- package/lib/types/editing.ts +77 -0
- package/lib/types/export.ts +164 -0
- package/lib/types/filtering.ts +52 -0
- package/lib/types/grouping.ts +27 -0
- package/lib/types/index.ts +18 -1702
- package/lib/types/locale.ts +51 -0
- package/lib/types/props.ts +405 -0
- package/lib/types/rows.ts +132 -0
- package/lib/types/selection.ts +66 -0
- package/lib/types/slots.ts +56 -0
- package/lib/types/sorting.ts +25 -0
- package/lib/types/state.ts +35 -0
- package/llms.txt +1 -1
- package/package.json +4 -2
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
font-size: var(--ogx-font-size-sm);
|
|
10
10
|
color: var(--ogx-grid-row-text);
|
|
11
11
|
min-height: 52px;
|
|
12
|
-
border-radius: 0 0 var(--ogx-border-radius-lg) var(--ogx-border-radius-lg);
|
|
12
|
+
border-radius: 0 0 var(--ogx-grid-border-radius, var(--ogx-border-radius-lg)) var(--ogx-grid-border-radius, var(--ogx-border-radius-lg));
|
|
13
13
|
}
|
|
14
14
|
.ogx-pagination__page-size {
|
|
15
15
|
display: flex;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.ogx__row {
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: stretch;
|
|
4
|
-
border-bottom:
|
|
4
|
+
border-bottom: var(--ogx-grid-row-divider-width) solid var(--ogx-grid-row-divider-color, var(--ogx-grid-border-color));
|
|
5
5
|
background: var(--ogx-grid-background);
|
|
6
6
|
position: relative;
|
|
7
7
|
min-height: var(--ogx-row-height);
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
}
|
|
95
95
|
.ogx__row--skeleton {
|
|
96
96
|
pointer-events: none;
|
|
97
|
-
border-bottom:
|
|
97
|
+
border-bottom: var(--ogx-grid-row-divider-width) solid var(--ogx-grid-row-divider-color, var(--ogx-grid-border-color));
|
|
98
98
|
background-color: var(--ogx-grid-background);
|
|
99
99
|
}
|
|
100
100
|
.ogx__row--skeleton .ogx__skeleton-cell {
|
|
@@ -80,6 +80,7 @@
|
|
|
80
80
|
z-index: 9999;
|
|
81
81
|
overflow: hidden;
|
|
82
82
|
animation: ogx-panel-in 0.15s ease-out;
|
|
83
|
+
font-family: var(--ogx-overlay-font-family, inherit);
|
|
83
84
|
}
|
|
84
85
|
@keyframes ogx-panel-in {
|
|
85
86
|
from { opacity: 0; transform: translateY(-6px) scale(0.98); }
|
|
@@ -97,7 +98,7 @@
|
|
|
97
98
|
display: flex;
|
|
98
99
|
align-items: center;
|
|
99
100
|
gap: var(--ogx-spacing-xs);
|
|
100
|
-
font-family: var(--ogx-font-family);
|
|
101
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
101
102
|
font-size: var(--ogx-font-size-sm);
|
|
102
103
|
font-weight: 600;
|
|
103
104
|
color: var(--ogx-grid-header-text);
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
border-radius: var(--ogx-border-radius-sm);
|
|
109
110
|
background: transparent;
|
|
110
111
|
color: var(--ogx-toolbar-btn-danger-text, var(--ogx-color-error, #ef4444));
|
|
111
|
-
font-family: var(--ogx-font-family);
|
|
112
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
112
113
|
font-size: var(--ogx-font-size-xs);
|
|
113
114
|
font-weight: 500;
|
|
114
115
|
cursor: pointer;
|
|
@@ -124,7 +125,7 @@
|
|
|
124
125
|
border-radius: var(--ogx-border-radius-sm);
|
|
125
126
|
background: transparent;
|
|
126
127
|
color: var(--ogx-grid-header-text);
|
|
127
|
-
font-family: var(--ogx-font-family);
|
|
128
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
128
129
|
font-size: var(--ogx-font-size-xs);
|
|
129
130
|
font-weight: 500;
|
|
130
131
|
cursor: pointer;
|
|
@@ -142,7 +143,7 @@
|
|
|
142
143
|
}
|
|
143
144
|
.ogx-toolbar__empty {
|
|
144
145
|
padding: var(--ogx-spacing-md) var(--ogx-spacing-md);
|
|
145
|
-
font-family: var(--ogx-font-family);
|
|
146
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
146
147
|
font-size: var(--ogx-font-size-sm);
|
|
147
148
|
color: var(--ogx-grid-header-text);
|
|
148
149
|
line-height: 1.5;
|
|
@@ -171,9 +172,9 @@
|
|
|
171
172
|
}
|
|
172
173
|
.ogx-toolbar__agg-label {
|
|
173
174
|
flex: 0 0 100px;
|
|
174
|
-
font-family: var(--ogx-font-family);
|
|
175
|
-
font-size: var(--ogx-font-size-xs);
|
|
176
|
-
font-weight: 500;
|
|
175
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
176
|
+
font-size: var(--ogx-overlay-font-size, var(--ogx-font-size-xs));
|
|
177
|
+
font-weight: var(--ogx-overlay-font-weight, 500);
|
|
177
178
|
color: var(--ogx-grid-row-text);
|
|
178
179
|
overflow: hidden;
|
|
179
180
|
text-overflow: ellipsis;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
z-index: 9999;
|
|
10
10
|
overflow: hidden;
|
|
11
11
|
animation: ogx-panel-in 0.15s ease-out;
|
|
12
|
-
font-family: var(--ogx-font-family);
|
|
12
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
13
13
|
}
|
|
14
14
|
@keyframes ogx-panel-in {
|
|
15
15
|
from { opacity: 0; transform: translateY(-6px) scale(0.98); }
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
border-radius: var(--ogx-border-radius-sm);
|
|
38
38
|
background: transparent;
|
|
39
39
|
color: var(--ogx-color-error, #ef4444);
|
|
40
|
-
font-family: var(--ogx-font-family);
|
|
40
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
41
41
|
font-size: var(--ogx-font-size-xs);
|
|
42
42
|
font-weight: 500;
|
|
43
43
|
cursor: pointer;
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
border-radius: 999px;
|
|
164
164
|
background: var(--ogx-grid-header-background);
|
|
165
165
|
color: var(--ogx-grid-row-text);
|
|
166
|
-
font-family: var(--ogx-font-family);
|
|
166
|
+
font-family: var(--ogx-overlay-font-family, var(--ogx-font-family));
|
|
167
167
|
font-size: 12px;
|
|
168
168
|
font-weight: 500;
|
|
169
169
|
cursor: pointer;
|
|
@@ -87,7 +87,9 @@ export function useGridDevWarnings(params: UseGridDevWarningsParams): void {
|
|
|
87
87
|
console.warn(
|
|
88
88
|
`[OpenGridX] The grid content is ${Math.round(scrollHeight)}px tall, more than this browser lays out ` +
|
|
89
89
|
'(about 17.9M px in Firefox, 33.5M px in Chrome and Safari). ' + reach +
|
|
90
|
-
'
|
|
90
|
+
'Load the rows on demand with a `dataSource` (server-side pages or infinite scroll, ' +
|
|
91
|
+
'docs/features/data-source.md), use `pagination`, or a smaller rowHeight (density="compact"). ' +
|
|
92
|
+
'See docs/features/virtualization.md#the-browser-height-limit.'
|
|
91
93
|
);
|
|
92
94
|
}, [scrollHeight, maxContentHeight, reachableRowCount, unpinnedRowCount]);
|
|
93
95
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { GridColDef, GridRowId, GridRowModel } from '../../types';
|
|
2
|
+
import { useGridEditCommitChannel } from './useGridUndoRedo';
|
|
3
|
+
import { useGridBatchEdit, type UseGridBatchEditParams } from '../features/useGridBatchEdit';
|
|
4
|
+
import { useGridEditing } from '../features/useGridEditing';
|
|
5
|
+
|
|
6
|
+
export interface UseGridEditPipelineParams<R extends GridRowModel> {
|
|
7
|
+
/** The row store's lookup (rows stored since the last render are read through `batchEdit.getRow`). */
|
|
8
|
+
rowsLookup: ReadonlyMap<GridRowId, R>;
|
|
9
|
+
/** The stored rows, in store order. */
|
|
10
|
+
rows: R[];
|
|
11
|
+
getRowId: (row: R) => GridRowId;
|
|
12
|
+
columns: GridColDef<R>[];
|
|
13
|
+
processRowUpdate: UseGridBatchEditParams<R>['processRowUpdate'];
|
|
14
|
+
onProcessRowUpdateError: UseGridBatchEditParams<R>['onProcessRowUpdateError'];
|
|
15
|
+
replaceRows: UseGridBatchEditParams<R>['replaceRows'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Steps 12a–13 of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: the edit
|
|
20
|
+
* commit channel, the batch edit and single-cell editing. Single edits store through `batchEdit.storeRow`
|
|
21
|
+
* and report to the channel; the undo/redo history (`useGridRangeEditing`, later) listens on it.
|
|
22
|
+
*/
|
|
23
|
+
export function useGridEditPipeline<R extends GridRowModel>(params: UseGridEditPipelineParams<R>) {
|
|
24
|
+
const { rowsLookup, rows, getRowId, columns, processRowUpdate, onProcessRowUpdateError, replaceRows } = params;
|
|
25
|
+
|
|
26
|
+
// Commits (single edits and batch edits) reach the undo/redo history created further down.
|
|
27
|
+
const editCommitChannel = useGridEditCommitChannel();
|
|
28
|
+
// Batch edits (paste, range clear, undo, redo): one processRowUpdate per row, one store update.
|
|
29
|
+
const batchEdit = useGridBatchEdit<R>({
|
|
30
|
+
rowsLookup,
|
|
31
|
+
columns,
|
|
32
|
+
processRowUpdate,
|
|
33
|
+
onProcessRowUpdateError,
|
|
34
|
+
replaceRows,
|
|
35
|
+
onCommitted: editCommitChannel.emit,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const editingHandlers = useGridEditing({
|
|
39
|
+
rows,
|
|
40
|
+
getRowId,
|
|
41
|
+
columns,
|
|
42
|
+
processRowUpdate,
|
|
43
|
+
onProcessRowUpdateError,
|
|
44
|
+
onRowChange: (updatedRow, rowId) => {
|
|
45
|
+
// Replaces the edited row in the *current* store, under the edited row's id: this runs
|
|
46
|
+
// after an awaited processRowUpdate, by which time the rows prop (or a dataSource
|
|
47
|
+
// fetch) may have replaced the rows this render saw. The returned row is stored as is
|
|
48
|
+
// (the grid never writes an id onto it), even if it does not carry its key itself.
|
|
49
|
+
batchEdit.storeRow(rowId, updatedRow);
|
|
50
|
+
},
|
|
51
|
+
onCommitted: (changes) => editCommitChannel.emit(changes, 'edit'),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return { editCommitChannel, batchEdit, editingHandlers };
|
|
55
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
import type { DataGridProps, GridApi, GridCellParams, GridCellSelectionModel, GridColDef, GridRowId, GridRowMeta, GridRowModel } from '../../types';
|
|
3
|
+
import type { UseGridCellSelectionReturn } from './useGridCellSelection';
|
|
4
|
+
import type { FocusedCell } from './useGridKeyboardNavigation';
|
|
5
|
+
import type { LayoutResult } from './useLayout';
|
|
6
|
+
import type { UseGridBatchEditReturn } from '../features/useGridBatchEdit';
|
|
7
|
+
import { useGridCellSelectionApi } from './useGridCellSelectionApi';
|
|
8
|
+
import { useGridClipboardPaste } from './useGridClipboardPaste';
|
|
9
|
+
import { useGridUndoRedo, UNDO_HISTORY_LIMIT, type GridEditCommitChannel } from './useGridUndoRedo';
|
|
10
|
+
import { useGridFillHandle } from './useGridFillHandle';
|
|
11
|
+
|
|
12
|
+
/** The `DataGrid` props the range editing hooks read. */
|
|
13
|
+
export type GridRangeEditingProps<R extends GridRowModel> = Pick<DataGridProps<R>,
|
|
14
|
+
'disableClipboardPaste' | 'disableRangeClear' | 'onClipboardPaste' | 'onBeforeClipboardPaste' |
|
|
15
|
+
'undoRedo' | 'onHistoryChange' | 'disableFillHandle' | 'onFill'>;
|
|
16
|
+
|
|
17
|
+
export interface UseGridRangeEditingParams<R extends GridRowModel> {
|
|
18
|
+
props: GridRangeEditingProps<R>;
|
|
19
|
+
apiRef: MutableRefObject<GridApi>;
|
|
20
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
21
|
+
viewportRef: RefObject<HTMLDivElement | null>;
|
|
22
|
+
selection: UseGridCellSelectionReturn;
|
|
23
|
+
model: GridCellSelectionModel;
|
|
24
|
+
getPendingModel: () => GridCellSelectionModel | null;
|
|
25
|
+
focusedCell: FocusedCell | null;
|
|
26
|
+
setFocusedCell: React.Dispatch<React.SetStateAction<FocusedCell | null>>;
|
|
27
|
+
allRenderableRows: R[];
|
|
28
|
+
getRowId: (row: R) => GridRowId;
|
|
29
|
+
navigationColumns: GridColDef<R>[];
|
|
30
|
+
columnIndexMap: Map<string, number>;
|
|
31
|
+
isCellEditable?: (params: GridCellParams<R>) => boolean;
|
|
32
|
+
rowMetaMap: Map<GridRowId, GridRowMeta>;
|
|
33
|
+
getSpanOrigin?: (rowId: GridRowId, field: string) => { rowId: GridRowId; field: string } | null;
|
|
34
|
+
isEditing: boolean;
|
|
35
|
+
batchEdit: UseGridBatchEditReturn<R>;
|
|
36
|
+
channel: GridEditCommitChannel;
|
|
37
|
+
layout: LayoutResult<R>;
|
|
38
|
+
rowHeight: number;
|
|
39
|
+
pinnedTopRowCount: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Steps 36a–36d of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: the cell
|
|
44
|
+
* selection API (anchor and focus kept together), clipboard paste and range clear, undo/redo, and the fill
|
|
45
|
+
* handle. Returns the fill handle (its position goes to the row renderers).
|
|
46
|
+
*/
|
|
47
|
+
export function useGridRangeEditing<R extends GridRowModel>(params: UseGridRangeEditingParams<R>) {
|
|
48
|
+
const {
|
|
49
|
+
props, apiRef, containerRef, viewportRef, selection, model, getPendingModel, focusedCell, setFocusedCell,
|
|
50
|
+
allRenderableRows, getRowId, navigationColumns, columnIndexMap, isCellEditable, rowMetaMap, getSpanOrigin,
|
|
51
|
+
isEditing, batchEdit, channel, layout, rowHeight, pinnedTopRowCount,
|
|
52
|
+
} = params;
|
|
53
|
+
const {
|
|
54
|
+
disableClipboardPaste = false,
|
|
55
|
+
disableRangeClear = false,
|
|
56
|
+
onClipboardPaste,
|
|
57
|
+
onBeforeClipboardPaste,
|
|
58
|
+
undoRedo = false,
|
|
59
|
+
disableFillHandle = false,
|
|
60
|
+
onFill,
|
|
61
|
+
onHistoryChange,
|
|
62
|
+
} = props;
|
|
63
|
+
|
|
64
|
+
// Keeps the range anchor and the focused cell together; installs the cell selection API.
|
|
65
|
+
useGridCellSelectionApi({
|
|
66
|
+
apiRef,
|
|
67
|
+
selection,
|
|
68
|
+
model,
|
|
69
|
+
getPendingModel,
|
|
70
|
+
focusedCell,
|
|
71
|
+
setFocusedCell,
|
|
72
|
+
containerRef,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Ctrl/Cmd+V and Delete on a range (cellSelection); apiRef.pasteText.
|
|
76
|
+
useGridClipboardPaste<R>({
|
|
77
|
+
apiRef, containerRef, viewportRef,
|
|
78
|
+
selection,
|
|
79
|
+
disableClipboardPaste, disableRangeClear,
|
|
80
|
+
focusedCell,
|
|
81
|
+
allRenderableRows,
|
|
82
|
+
getRowId,
|
|
83
|
+
navigationColumns,
|
|
84
|
+
isCellEditable,
|
|
85
|
+
rowMetaMap,
|
|
86
|
+
getSpanOrigin,
|
|
87
|
+
isEditing,
|
|
88
|
+
batchEdit,
|
|
89
|
+
onClipboardPaste,
|
|
90
|
+
onBeforeClipboardPaste,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Undo / redo (undoRedo): history of committed edits, keys and apiRef methods.
|
|
94
|
+
useGridUndoRedo<R>({
|
|
95
|
+
apiRef,
|
|
96
|
+
enabled: Boolean(undoRedo),
|
|
97
|
+
limit: (typeof undoRedo === 'object' && undoRedo.limit) || UNDO_HISTORY_LIMIT,
|
|
98
|
+
onHistoryChange,
|
|
99
|
+
channel,
|
|
100
|
+
batchEdit,
|
|
101
|
+
isEditing,
|
|
102
|
+
containerRef, viewportRef,
|
|
103
|
+
selection,
|
|
104
|
+
setFocusedCell,
|
|
105
|
+
allRenderableRows,
|
|
106
|
+
getRowId,
|
|
107
|
+
navigationColumns,
|
|
108
|
+
layout,
|
|
109
|
+
rowHeight,
|
|
110
|
+
pinnedTopRowCount,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Fill handle (cellSelection): drag the range's corner, Ctrl/Cmd+D and Ctrl/Cmd+R.
|
|
114
|
+
return useGridFillHandle<R>({
|
|
115
|
+
containerRef, viewportRef,
|
|
116
|
+
selection,
|
|
117
|
+
disableFillHandle,
|
|
118
|
+
isEditing,
|
|
119
|
+
allRenderableRows,
|
|
120
|
+
getRowId,
|
|
121
|
+
navigationColumns,
|
|
122
|
+
columnIndexMap,
|
|
123
|
+
isCellEditable,
|
|
124
|
+
rowMetaMap,
|
|
125
|
+
getSpanOrigin,
|
|
126
|
+
batchEdit,
|
|
127
|
+
onFill,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { GridColDef, GridRowId, GridRowModel } from '../../types';
|
|
2
|
+
import type { GridAriaRowLayout } from '../../utils/aria';
|
|
3
|
+
import type { GridSpanningResult } from '../features/useGridSpanning';
|
|
4
|
+
import { useGridSpanRowWindow, useGridSpanColumnWindow } from '../features/useGridSpanRenderWindow';
|
|
5
|
+
import { useGridAriaRows, type UseGridAriaRowsParams } from './useGridAriaRows';
|
|
6
|
+
import { useGridVisibleRows, type GridVisibleRow } from './useGridVisibleRows';
|
|
7
|
+
import type { GridVirtualizationResult } from './useGridVirtualization';
|
|
8
|
+
import type { LayoutResult } from './useLayout';
|
|
9
|
+
|
|
10
|
+
export interface UseGridRenderWindowParams<R extends GridRowModel> {
|
|
11
|
+
aria: UseGridAriaRowsParams;
|
|
12
|
+
spanning: GridSpanningResult;
|
|
13
|
+
virtualization: GridVirtualizationResult<R>;
|
|
14
|
+
layout: LayoutResult<R>;
|
|
15
|
+
pinnedTopRows: R[];
|
|
16
|
+
pinnedBottomRows: R[];
|
|
17
|
+
paginatedUnpinnedRows: R[];
|
|
18
|
+
sortedUnpinnedRows: R[];
|
|
19
|
+
pagination: boolean;
|
|
20
|
+
getRowId: (row: R) => GridRowId;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UseGridRenderWindowResult<R extends GridRowModel> {
|
|
24
|
+
ariaRows: GridAriaRowLayout;
|
|
25
|
+
spanRowWindow: ReturnType<typeof useGridSpanRowWindow>;
|
|
26
|
+
visibleRows: GridVisibleRow<R>[];
|
|
27
|
+
renderColumns: GridColDef<R>[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Steps 38–41 of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: the
|
|
32
|
+
* `aria-rowcount` / `aria-rowindex` bases, the render window widened to whole row spans, the rows to
|
|
33
|
+
* render (pinned + virtual centre) and the columns to render, widened to whole column spans.
|
|
34
|
+
*/
|
|
35
|
+
export function useGridRenderWindow<R extends GridRowModel>(params: UseGridRenderWindowParams<R>): UseGridRenderWindowResult<R> {
|
|
36
|
+
const {
|
|
37
|
+
aria, spanning, virtualization, layout, pinnedTopRows, pinnedBottomRows, paginatedUnpinnedRows, sortedUnpinnedRows,
|
|
38
|
+
pagination, getRowId,
|
|
39
|
+
} = params;
|
|
40
|
+
|
|
41
|
+
const ariaRows = useGridAriaRows(aria);
|
|
42
|
+
|
|
43
|
+
const spanRowWindow = useGridSpanRowWindow({
|
|
44
|
+
spanning,
|
|
45
|
+
renderContext: virtualization.renderContext,
|
|
46
|
+
offsetTop: virtualization.offsetTop,
|
|
47
|
+
cumulativeHeights: layout.cumulativeHeights,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const visibleRows = useGridVisibleRows<R>({
|
|
51
|
+
renderContext: spanRowWindow.renderContext,
|
|
52
|
+
pinnedTopRows, pinnedBottomRows, paginatedUnpinnedRows, sortedUnpinnedRows, pagination,
|
|
53
|
+
getRowId,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const renderColumns = useGridSpanColumnWindow<R>({
|
|
57
|
+
spanning,
|
|
58
|
+
firstColumnIndex: virtualization.renderContext.firstColumnIndex,
|
|
59
|
+
lastColumnIndex: virtualization.renderContext.lastColumnIndex,
|
|
60
|
+
virtualColumns: virtualization.virtualColumns,
|
|
61
|
+
layout,
|
|
62
|
+
rows: visibleRows,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return { ariaRows, spanRowWindow, visibleRows, renderColumns };
|
|
66
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
import type { GridRowModel } from '../../types';
|
|
3
|
+
import { useGridViewport, type UseGridViewportParams } from './useGridViewport';
|
|
4
|
+
import { useGridMaxContentHeight } from './useGridMaxContentHeight';
|
|
5
|
+
import { useGridVirtualization, type UseGridVirtualizationParams } from './useGridVirtualization';
|
|
6
|
+
import type { LayoutResult } from './useLayout';
|
|
7
|
+
|
|
8
|
+
export interface UseGridScrollViewportParams<R extends GridRowModel> {
|
|
9
|
+
viewport: Omit<UseGridViewportParams, 'viewportRef' | 'rowCount'>;
|
|
10
|
+
viewportRef: MutableRefObject<HTMLDivElement | null>;
|
|
11
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
12
|
+
layout: LayoutResult<R>;
|
|
13
|
+
viewportWidth: number;
|
|
14
|
+
viewportHeight: number;
|
|
15
|
+
/** The virtualization inputs that do not come from the viewport. */
|
|
16
|
+
virtualization: Pick<UseGridVirtualizationParams<R>,
|
|
17
|
+
'autoHeight' | 'rowReordering' | 'hasDetailPanel' | 'checkboxSelection' | 'pinCheckboxColumn' | 'pinExpandColumn'>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Steps 32–33 of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: scroll sync
|
|
22
|
+
* and viewport measurement, the tallest element this browser lays out (32a), and the render window.
|
|
23
|
+
*/
|
|
24
|
+
export function useGridScrollViewport<R extends GridRowModel>(params: UseGridScrollViewportParams<R>) {
|
|
25
|
+
const { viewport, viewportRef, containerRef, layout, viewportWidth, viewportHeight, virtualization: options } = params;
|
|
26
|
+
|
|
27
|
+
const { scrollTop, scrollLeft, overscanRows, handleScroll, setViewportElement } = useGridViewport({
|
|
28
|
+
...viewport, rowCount: layout.unpinnedRowsLength, viewportRef,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const maxContentHeight = useGridMaxContentHeight(containerRef);
|
|
32
|
+
const virtualization = useGridVirtualization({
|
|
33
|
+
layout, scrollTop, scrollLeft,
|
|
34
|
+
viewportWidth,
|
|
35
|
+
viewportHeight,
|
|
36
|
+
...options,
|
|
37
|
+
overscanRows,
|
|
38
|
+
maxContentHeight: maxContentHeight ?? Infinity,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return { handleScroll, setViewportElement, maxContentHeight, virtualization };
|
|
42
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { GridRowModel } from '../../types';
|
|
2
|
+
import { useGridRowInteractions, type UseGridRowInteractionsParams, type UseGridRowInteractionsResult } from './useGridRowInteractions';
|
|
3
|
+
import { useGridApiMethods, type UseGridApiMethodsParams } from './useGridApiMethods';
|
|
4
|
+
import type { UseGridControlledStateReturn } from './useGridControlledState';
|
|
5
|
+
|
|
6
|
+
/** The state API inputs that do not come from `useGridControlledState`. */
|
|
7
|
+
export type GridStateApiParams = Pick<UseGridApiMethodsParams,
|
|
8
|
+
'apiRef' | 'multiSort' | 'selectedRowIds' | 'disableMultipleRowSelection' | 'isSyntheticRowId' | 'getVisibleRows' |
|
|
9
|
+
'getAllFilteredRows' | 'visibleColumns'>;
|
|
10
|
+
|
|
11
|
+
export interface UseGridSelectionAndStateApiParams<R extends GridRowModel> {
|
|
12
|
+
controlledState: UseGridControlledStateReturn;
|
|
13
|
+
interactions: Omit<UseGridRowInteractionsParams<R>, 'selectedRowIds' | 'onSelectionModelChange' | 'disableMultipleRowSelection'>;
|
|
14
|
+
api: GridStateApiParams;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Steps 23–24 of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: row
|
|
19
|
+
* selection and the row click / checkbox handlers, then the state API methods (sort, filter, pagination,
|
|
20
|
+
* selection, row grouping, aggregation, visibility and pivot setters, `getGridAiState`) installed on `apiRef`.
|
|
21
|
+
*/
|
|
22
|
+
export function useGridSelectionAndStateApi<R extends GridRowModel>(
|
|
23
|
+
params: UseGridSelectionAndStateApiParams<R>
|
|
24
|
+
): UseGridRowInteractionsResult<R> {
|
|
25
|
+
const { controlledState, interactions, api } = params;
|
|
26
|
+
const {
|
|
27
|
+
sortModel, handleSortModelChange, filterModel, handleFilterModelChange, effectivePaginationModel,
|
|
28
|
+
handlePaginationModelChange, handleRowSelectionModelChange, rowGroupingModel, handleRowGroupingModelChange,
|
|
29
|
+
aggregationModel, handleAggregationModelChange, columnVisibilityModel, handleColumnVisibilityModelChange,
|
|
30
|
+
currentPivotModel, handlePivotModelChange,
|
|
31
|
+
} = controlledState;
|
|
32
|
+
|
|
33
|
+
const result = useGridRowInteractions<R>({
|
|
34
|
+
...interactions,
|
|
35
|
+
selectedRowIds: api.selectedRowIds,
|
|
36
|
+
onSelectionModelChange: handleRowSelectionModelChange,
|
|
37
|
+
disableMultipleRowSelection: api.disableMultipleRowSelection,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
useGridApiMethods({
|
|
41
|
+
...api,
|
|
42
|
+
onSortModelChange: handleSortModelChange,
|
|
43
|
+
sortModel,
|
|
44
|
+
filterModel,
|
|
45
|
+
onFilterModelChange: handleFilterModelChange,
|
|
46
|
+
paginationModel: effectivePaginationModel,
|
|
47
|
+
onPaginationModelChange: handlePaginationModelChange,
|
|
48
|
+
getPendingRowSelectionModel: controlledState.getPendingRowSelectionModel,
|
|
49
|
+
onRowSelectionModelChange: handleRowSelectionModelChange,
|
|
50
|
+
rowGroupingModel,
|
|
51
|
+
onRowGroupingModelChange: handleRowGroupingModelChange,
|
|
52
|
+
aggregationModel,
|
|
53
|
+
onAggregationModelChange: handleAggregationModelChange,
|
|
54
|
+
columnVisibilityModel,
|
|
55
|
+
onColumnVisibilityModelChange: handleColumnVisibilityModelChange,
|
|
56
|
+
pivotModel: currentPivotModel,
|
|
57
|
+
onPivotModelChange: handlePivotModelChange,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
import type { GridApi, GridLocaleText, GridRowModel } from '../../types';
|
|
3
|
+
import { useGridColumnsPanel } from './useGridColumnsPanel';
|
|
4
|
+
import { useGridStylesheetWarning } from './useGridDevWarnings';
|
|
5
|
+
import { useGridAiAssistant, type UseGridAiAssistantParams } from '../features/useGridAiAssistant';
|
|
6
|
+
import { useGridToolbarProps, type UseGridToolbarPropsParams } from './useGridToolbarProps';
|
|
7
|
+
|
|
8
|
+
/** What `useGridToolbarProps` needs besides the columns panel and the AI assistant built here. */
|
|
9
|
+
export type GridToolbarStackToolbarParams<R extends GridRowModel> = Omit<UseGridToolbarPropsParams<R>,
|
|
10
|
+
'forceColumnsOpen' | 'onColumnsPanelClose' | 'aiAssistantEnabled' | 'aiAssistantOpen' | 'onAiAssistantToggle' |
|
|
11
|
+
'aiAssistantLabel' | 'forceFiltersOpen' | 'onFiltersPanelClose' | 'apiRef'>;
|
|
12
|
+
|
|
13
|
+
export interface UseGridToolbarStackParams<R extends GridRowModel> {
|
|
14
|
+
apiRef: MutableRefObject<GridApi>;
|
|
15
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
16
|
+
aiAssistant: Omit<UseGridAiAssistantParams, 'apiRef'>;
|
|
17
|
+
toolbar: GridToolbarStackToolbarParams<R>;
|
|
18
|
+
localeText: GridLocaleText | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Steps 44–46 of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: the columns
|
|
23
|
+
* panel (toolbar or standalone), the missing-stylesheet warning, the `aiAssistant` panel, and the props for
|
|
24
|
+
* `slots.toolbar` (which gets its Ask AI button from the assistant).
|
|
25
|
+
*/
|
|
26
|
+
export function useGridToolbarStack<R extends GridRowModel>(params: UseGridToolbarStackParams<R>) {
|
|
27
|
+
const { apiRef, containerRef, aiAssistant, toolbar, localeText } = params;
|
|
28
|
+
|
|
29
|
+
const columnsPanel = useGridColumnsPanel();
|
|
30
|
+
useGridStylesheetWarning(containerRef);
|
|
31
|
+
|
|
32
|
+
// The aiAssistant prompt panel (v3.5): applies validated replies through apiRef; apiRef.openAiAssistant.
|
|
33
|
+
const aiAssistantPanel = useGridAiAssistant({ apiRef, ...aiAssistant });
|
|
34
|
+
|
|
35
|
+
const toolbarProps = useGridToolbarProps<R>({
|
|
36
|
+
...toolbar,
|
|
37
|
+
apiRef,
|
|
38
|
+
forceColumnsOpen: columnsPanel.toolbarPanelRequested,
|
|
39
|
+
onColumnsPanelClose: columnsPanel.closeToolbarPanel,
|
|
40
|
+
aiAssistantEnabled: aiAssistantPanel.enabled,
|
|
41
|
+
aiAssistantOpen: aiAssistantPanel.open,
|
|
42
|
+
onAiAssistantToggle: aiAssistantPanel.togglePanel,
|
|
43
|
+
aiAssistantLabel: localeText?.aiAssistantButton,
|
|
44
|
+
forceFiltersOpen: columnsPanel.toolbarFiltersRequested,
|
|
45
|
+
onFiltersPanelClose: columnsPanel.closeToolbarFiltersPanel,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return { columnsPanel, aiAssistantPanel, toolbarProps };
|
|
49
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MutableRefObject, RefObject } from 'react';
|
|
2
|
+
import type { GridApi, GridColDef, GridRowId, GridRowModel } from '../../types';
|
|
3
|
+
import { useGridClipboardApi } from './useGridClipboardApi';
|
|
4
|
+
import { useGridScrollToIndexesApi } from './useGridScrollToIndexesApi';
|
|
5
|
+
import { useGridColumnAutosize } from './useGridColumnAutosize';
|
|
6
|
+
import type { LayoutResult } from './useLayout';
|
|
7
|
+
|
|
8
|
+
export interface UseGridViewApisParams<R extends GridRowModel> {
|
|
9
|
+
apiRef: MutableRefObject<GridApi>;
|
|
10
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
11
|
+
viewportRef: RefObject<HTMLDivElement | null>;
|
|
12
|
+
/** Rendered data columns with their layout-resolved widths, in render order (what Ctrl/Cmd+C copies). */
|
|
13
|
+
copyColumns: GridColDef[];
|
|
14
|
+
getRowId: (row: GridRowModel) => GridRowId;
|
|
15
|
+
disableClipboardCopy: boolean;
|
|
16
|
+
/** The cell range's copy text while `cellSelection` is on. */
|
|
17
|
+
getCellRangeCopyText: (() => string | null) | undefined;
|
|
18
|
+
layout: LayoutResult<R>;
|
|
19
|
+
rowHeight: number;
|
|
20
|
+
/** Every column in display order (what auto-size measures). */
|
|
21
|
+
orderedColumns: GridColDef<R>[];
|
|
22
|
+
onColumnResize: (field: string, width: number) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Steps 30–31a of `DataGrid` (docs/architecture/datagrid-orchestration.md), in their call order: the
|
|
27
|
+
* `apiRef` installers that need the laid-out view — copy, `scrollToIndexes` and column auto-size.
|
|
28
|
+
* Returns the resize handle's auto-size handler.
|
|
29
|
+
*/
|
|
30
|
+
export function useGridViewApis<R extends GridRowModel>(params: UseGridViewApisParams<R>): (field: string) => void {
|
|
31
|
+
const {
|
|
32
|
+
apiRef, containerRef, viewportRef, copyColumns, getRowId, disableClipboardCopy, getCellRangeCopyText, layout, rowHeight,
|
|
33
|
+
orderedColumns, onColumnResize,
|
|
34
|
+
} = params;
|
|
35
|
+
|
|
36
|
+
useGridClipboardApi({
|
|
37
|
+
apiRef,
|
|
38
|
+
columns: copyColumns,
|
|
39
|
+
getRowId,
|
|
40
|
+
containerRef,
|
|
41
|
+
disableKeyboardShortcut: disableClipboardCopy,
|
|
42
|
+
getCellRangeCopyText,
|
|
43
|
+
});
|
|
44
|
+
useGridScrollToIndexesApi<R>({ apiRef, viewportRef, layout, rowHeight });
|
|
45
|
+
return useGridColumnAutosize<R>({ apiRef, containerRef, columns: orderedColumns, onColumnResize });
|
|
46
|
+
}
|
|
@@ -81,6 +81,18 @@
|
|
|
81
81
|
--ogx-grid-cell-font-size: 13px;
|
|
82
82
|
--ogx-grid-header-font-size: 13px;
|
|
83
83
|
--ogx-grid-line-height: var(--ogx-line-height-normal);
|
|
84
|
+
/* Outer border and divider widths (v3.7). 0 hides a divider. Their colours,
|
|
85
|
+
--ogx-grid-column-divider-color and --ogx-grid-row-divider-color, are unset here and fall back
|
|
86
|
+
to --ogx-grid-border-color where they are used. So do the other theme-builder variables:
|
|
87
|
+
--ogx-grid-border-radius (--ogx-border-radius-lg), --ogx-grid-header-padding-x
|
|
88
|
+
(--ogx-grid-cell-padding-x), --ogx-grid-header-font-family / -font-weight and
|
|
89
|
+
--ogx-grid-cell-font-family / -font-weight (inherited; header weight 600), and
|
|
90
|
+
--ogx-overlay-font-family / -font-weight / -font-size (the grid font, each item's own weight,
|
|
91
|
+
--ogx-font-size-xs for menu and panel items). */
|
|
92
|
+
--ogx-grid-border-width: 1px;
|
|
93
|
+
--ogx-grid-column-divider-width: 1px;
|
|
94
|
+
--ogx-grid-header-column-divider-width: 1px;
|
|
95
|
+
--ogx-grid-row-divider-width: 1px;
|
|
84
96
|
--ogx-grid-background: var(--ogx-color-white);
|
|
85
97
|
--ogx-grid-border-color: var(--ogx-color-gray-200);
|
|
86
98
|
--ogx-grid-header-background: var(--ogx-color-gray-50);
|
|
@@ -272,6 +272,18 @@ function themeToCSS(theme: GridTheme): Record<string, string> {
|
|
|
272
272
|
set('--ogx-grid-cell-padding-y', g.cellPaddingY);
|
|
273
273
|
set('--ogx-grid-cell-font-size', g.cellFontSize);
|
|
274
274
|
set('--ogx-grid-header-font-size', g.headerFontSize);
|
|
275
|
+
set('--ogx-grid-header-font-family', g.headerFontFamily);
|
|
276
|
+
set('--ogx-grid-header-font-weight', g.headerFontWeight);
|
|
277
|
+
set('--ogx-grid-cell-font-family', g.cellFontFamily);
|
|
278
|
+
set('--ogx-grid-cell-font-weight', g.cellFontWeight);
|
|
279
|
+
set('--ogx-grid-header-padding-x', g.headerPaddingX);
|
|
280
|
+
set('--ogx-grid-border-width', g.borderWidth);
|
|
281
|
+
set('--ogx-grid-border-radius', g.borderRadius);
|
|
282
|
+
set('--ogx-grid-column-divider-width', g.columnDividerWidth);
|
|
283
|
+
set('--ogx-grid-header-column-divider-width', g.headerColumnDividerWidth);
|
|
284
|
+
set('--ogx-grid-row-divider-width', g.rowDividerWidth);
|
|
285
|
+
set('--ogx-grid-column-divider-color', g.columnDividerColor);
|
|
286
|
+
set('--ogx-grid-row-divider-color', g.rowDividerColor);
|
|
275
287
|
set('--ogx-grid-background', g.background);
|
|
276
288
|
set('--ogx-grid-border-color', g.borderColor);
|
|
277
289
|
set('--ogx-grid-header-background', g.headerBackground);
|
|
@@ -338,6 +350,9 @@ function themeToCSS(theme: GridTheme): Record<string, string> {
|
|
|
338
350
|
set('--ogx-overlay-item-selected-text', o.itemSelectedText);
|
|
339
351
|
set('--ogx-overlay-item-danger-bg', o.itemDangerBackground);
|
|
340
352
|
set('--ogx-overlay-item-danger-text', o.itemDangerText);
|
|
353
|
+
set('--ogx-overlay-font-family', o.fontFamily);
|
|
354
|
+
set('--ogx-overlay-font-weight', o.fontWeight);
|
|
355
|
+
set('--ogx-overlay-font-size', o.fontSize);
|
|
341
356
|
}
|
|
342
357
|
|
|
343
358
|
if (theme.scrollbar) {
|