@opencorestack/opengridx 3.0.0 → 3.0.1
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 +36 -0
- package/README.md +7 -5
- package/dist/index.d.ts +18 -8
- package/dist/opengridx.css +1 -1
- package/dist/opengridx.es.js +1371 -1365
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +10 -10
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +11 -7
- package/docs/components/column-resize.md +1 -1
- package/docs/components/datagrid.md +1 -1
- package/docs/customization/theming.md +1 -1
- package/docs/features/list-view.md +1 -1
- package/docs/features/pdf-export.md +16 -0
- package/docs/features/pinning.md +1 -0
- package/docs/features/virtualization.md +11 -9
- package/docs/migration/v2-to-v3.md +12 -1
- package/docs/roadmap.md +1 -1
- package/lib/components/Cell/Cell.css +4 -0
- package/lib/components/ColumnResizeHandle/ColumnResizeHandle.css +5 -3
- package/lib/components/DataGrid/DataGrid.css +8 -0
- package/lib/components/DataGrid/DataGrid.tsx +6 -2
- package/lib/components/DataGrid/GridListView.tsx +2 -1
- package/lib/components/Header/Header.css +3 -0
- package/lib/components/Header/Header.tsx +3 -1
- package/lib/hooks/core/gridApiPlaceholder.ts +2 -2
- package/lib/hooks/core/useGridApiRef.ts +7 -4
- package/lib/hooks/core/useGridDevWarnings.ts +23 -5
- package/lib/types/index.ts +14 -7
- package/llms.txt +6 -6
- package/package.json +1 -1
package/docs/API_REFERENCE.md
CHANGED
|
@@ -27,7 +27,7 @@ The main component for displaying and interacting with data.
|
|
|
27
27
|
| `onPaginationModelChange` | `(model: GridPaginationModel) => void` | — | Fired when page or page size changes. |
|
|
28
28
|
| `pageSizeOptions` | `number[]` | `[10, 25, 50, 100]` | Available page size options. The uncontrolled default page size is 100 when offered, else the first option. |
|
|
29
29
|
| `rowCount` | `number` | — | Server total for `paginationMode="server"` when you fetch pages yourself (read on every render). With a `dataSource`, the response's `rowCount` is used and this is only the fallback before the first response. |
|
|
30
|
-
| `height` | `number \| string` | `undefined` | Total height of the grid container. |
|
|
30
|
+
| `height` | `number \| string` | `undefined` | Total height of the grid. Without it the grid fills its container (`height: 100%`, or `flex: 1 1 auto; min-height: 0` as a flex item; v3.0.1+), and grows to fit every row in an auto-height container. |
|
|
31
31
|
| `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Visual row density: compact = the theme's `grid.rowHeightCompact` or 32 px, standard = `rowHeight`, comfortable = the theme's `grid.rowHeightComfortable` or 72 px. |
|
|
32
32
|
| `initialState` | `GridInitialState` | `undefined` | Starting state (sort, filter, pagination, columns, density), read on mount. Seeds the grid's uncontrolled state; see [State Persistence](features/state-persistence.md). |
|
|
33
33
|
| `slots` | `GridSlots` | — | Custom component overrides: `toolbar`, `pagination`, `noRowsOverlay`, `loadingOverlay`, `footer`. See [`GridSlots`](#gridslots-and-gridslotprops) and the [Slots API](customization/slots-api.md). |
|
|
@@ -156,7 +156,7 @@ The main component for displaying and interacting with data.
|
|
|
156
156
|
|
|
157
157
|
| Prop | Type | Default | Description |
|
|
158
158
|
| :--- | :--- | :--- | :--- |
|
|
159
|
-
| `apiRef` | `React.MutableRefObject<GridApi>` | — | Reactive ref to the imperative API. Create with `useGridApiRef()
|
|
159
|
+
| `apiRef` | `React.MutableRefObject<GridApi<R>> \| React.MutableRefObject<GridApi>` | — | Reactive ref to the imperative API. Create with `useGridApiRef()`, or `useGridApiRef<Row>()` for typed row getters (v3.0.1+). |
|
|
160
160
|
|
|
161
161
|
#### List View
|
|
162
162
|
|
|
@@ -197,7 +197,7 @@ const columns: GridColDef<Employee>[] = [
|
|
|
197
197
|
- A `GridColDef<Row>` for a type-alias row (or an interface that extends `GridRowModel`) can be used where a `GridColDef` is expected: the row callbacks are declared as methods, so they are checked bivariantly.
|
|
198
198
|
- `params.value` stays `unknown`; read typed values from `params.row`, or render `params.formattedValue`.
|
|
199
199
|
- The export functions, `usePivot` and `useAggregation` accept the same typed or untyped columns, and their options' `getRowId` takes your row type.
|
|
200
|
-
- `apiRef`
|
|
200
|
+
- `apiRef` row getters (`getRow`, `getAllRows`, `getVisibleRows`, `getAllFilteredRows`) return your row type when the ref is created with `useGridApiRef<Row>()` (v3.0.1+); a plain `useGridApiRef()` returns `GridRowModel`.
|
|
201
201
|
- For the component's props type, use `DataGridProps<R>`. `React.ComponentProps<typeof DataGrid>` resolves to the untyped-columns overload.
|
|
202
202
|
|
|
203
203
|
### `GridSlots` and `GridSlotProps`
|
|
@@ -279,9 +279,9 @@ Access these methods via the `apiRef` prop.
|
|
|
279
279
|
|
|
280
280
|
| Method | Return | Description |
|
|
281
281
|
| :--- | :--- | :--- |
|
|
282
|
-
| `getRow(id)` | `
|
|
283
|
-
| `getAllRows()` | `
|
|
284
|
-
| `getVisibleRows()` | `
|
|
282
|
+
| `getRow(id)` | `R \| null` | Get row data by ID (your row object, unchanged). `R` is the type passed to `useGridApiRef<R>()`, `GridRowModel` by default. |
|
|
283
|
+
| `getAllRows()` | `R[]` | Get all loaded rows. |
|
|
284
|
+
| `getVisibleRows()` | `R[]` | Get the rows on screen after filtering/sorting: pinned-top rows, the current page (or all rows without pagination), pinned-bottom rows. Under row grouping and tree data this is the visible hierarchy, group rows included. |
|
|
285
285
|
| `getColumn(field)` | `GridColDef \| null` | Get column definition by field. |
|
|
286
286
|
| `getVisibleColumns()` | `GridColDef[]` | Get the columns on screen, in render order (hidden columns excluded): left-pinned, unpinned, right-pinned, as the header shows them (v3.0+; before, pinned columns kept their unpinned position). |
|
|
287
287
|
| `selectRow(id, isSelected = true)` | `void` | Set selection for a single row. Fires `onRowSelectionModelChange`, unless nothing changes (selecting a selected row, deselecting an unselected one; v3.0+). Ids of rows the grid made (group headers, subtotals, auto-created tree parents, the pivot Grand Total) are ignored, as they are for the checkbox, click and keyboard (v3.0+). |
|
|
@@ -297,7 +297,7 @@ Access these methods via the `apiRef` prop.
|
|
|
297
297
|
| `getAllColumns()` | `GridColDef[]` | Get all defined columns. |
|
|
298
298
|
| `getAggregationResult()` | `Record<string, unknown> \| null` | Get current aggregation results (`null` without an `aggregationModel`, and in pivot mode). Live in a parent's `useLayoutEffect` on mount and current after every update (v3.0+; before, it was installed in a passive effect). The same holds for `getAggregationModel()` and `getGroupedExportRows()`. |
|
|
299
299
|
| `getAggregationModel()` | `GridAggregationModel \| null` | Get the active aggregation configuration. |
|
|
300
|
-
| `getAllFilteredRows()` | `
|
|
300
|
+
| `getAllFilteredRows()` | `R[]` | Get every row that passes the filter, sorted, regardless of pagination, including pinned rows. Under row grouping and tree data it returns the data rows (no group rows) in hierarchy order with every group expanded, ordered like the screen (also when sorting by the hierarchy column; v3.0+). With tree data and a filter, ancestors shown only to give a match its context are left out: the result is the set select-all and the aggregation footer act on (v3.0+). Use for full-dataset exports. |
|
|
301
301
|
| `getGroupedExportRows()` | `GridGroupedExportRow[] \| null` | Get a flat ordered list reflecting the active row-grouping tree (group-header, leaf, subtotal, grand-total), sorted and filtered like the screen. Collapsed groups are included with their rows, and subtotals are computed over each group's exported rows. Group-header and subtotal entries carry `groupLabel`, the label the grid shows (v3.0+). Returns `null` when row grouping is not active. |
|
|
302
302
|
| `copySelectedRows()` | `Promise<void>` | Copy every selected row that passes the filter (other pages, collapsed groups and pinned rows included) as TSV, with the visible columns in screen order. Resolves without writing when no selected row is found; rejects when the clipboard write fails. |
|
|
303
303
|
|
|
@@ -476,6 +476,10 @@ const apiRef = useGridApiRef();
|
|
|
476
476
|
// Then call methods imperiously
|
|
477
477
|
apiRef.current.scrollToIndexes({ rowIndex: 0 });
|
|
478
478
|
apiRef.current.setFilterModel({ items: [] });
|
|
479
|
+
|
|
480
|
+
// Typed row getters (v3.0.1+)
|
|
481
|
+
const invoiceApi = useGridApiRef<Invoice>();
|
|
482
|
+
const invoice = invoiceApi.current.getRow(42); // Invoice | null
|
|
479
483
|
```
|
|
480
484
|
|
|
481
485
|
See the [Imperative API (`GridApi`)](#%EF%B8%8F-imperative-api-gridapi) table above for the full method list.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
OpenGridX supports dynamic column resizing, allowing users to adjust the width of any column on the fly for better visibility of data. This is facilitated by the `ColumnResizeHandle`, an internal component (not exported) that `<Header />` renders invisibly on the edge of each resizable column header.
|
|
4
4
|
|
|
5
5
|
## 📑 Overview
|
|
6
|
-
- **Where the handle is**: on the right edge of each resizable column header. Right-pinned columns are anchored to the right edge of the grid and grow leftwards, so their handle is on their **left** edge, and the edge you grab follows the pointer.
|
|
6
|
+
- **Where the handle is**: on the right edge of each resizable column header. Right-pinned columns are anchored to the right edge of the grid and grow leftwards, so their handle is on their **left** edge, and the edge you grab follows the pointer. The handle is an 8px strip just inside the column, against that edge, and all of it can be grabbed (v3.0.1+; before, the neighbouring header cell clipped half of it).
|
|
7
7
|
- **Mouse, touch and pen**: the handle uses pointer events with pointer capture, so a resize keeps following the pointer outside the header and works on tablets and phones.
|
|
8
8
|
- **Keyboard**: with a column header focused, **Alt+ArrowRight** / **Alt+ArrowLeft** widen / narrow the column by 10px (hold **Shift** for 50px). The handle is a `role="separator"` that reports the width in `aria-valuenow` (and `aria-valuemin` / `aria-valuemax`).
|
|
9
9
|
- **Constraints**: `minWidth` and `maxWidth` from your `GridColDef` apply. Without `minWidth` a column can be narrowed to 50px; a column that is already narrower (a 30px icon column) is never snapped up to 50px. Without `maxWidth` there is no upper limit.
|
|
@@ -25,7 +25,7 @@ function MyGrid() {
|
|
|
25
25
|
| `rows` | `R[]` | — | **Required.** The dataset to display (`[]` when a `dataSource` supplies the rows). |
|
|
26
26
|
| `columns` | `GridColDef<R>[]` | — | **Required.** Column definitions. |
|
|
27
27
|
| `getRowId` | `(row: R) => GridRowId` | `row.id` | Unique ID for each row. Only keys the grid's store; row objects are never copied or given an `id` (v3.0+). Duplicate ids keep the first row and log a development warning. |
|
|
28
|
-
| `height` | `number \| string` | `undefined` | Height of the grid container. |
|
|
28
|
+
| `height` | `number \| string` | `undefined` | Height of the grid. Without it the grid fills its container (v3.0.1+); the container needs a bounded height for virtualization. See [Virtualization](../features/virtualization.md#the-grid-needs-a-bounded-height). |
|
|
29
29
|
| `loading` | `boolean` | `false` | Displays a loading skeleton/shimmer. |
|
|
30
30
|
| `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Row height preset: compact = 32 px, standard = `rowHeight`, comfortable = 72 px. Inside a `DataGridThemeProvider`, the theme's `grid.rowHeightCompact` / `rowHeightStandard` / `rowHeightComfortable` replace these defaults (an explicit `rowHeight` still wins for standard). |
|
|
31
31
|
| `checkboxSelection` | `boolean` | `false` | Enable row checkboxes. |
|
|
@@ -46,7 +46,7 @@ How the provider builds the variables (v3.0+):
|
|
|
46
46
|
- **Toolbar tokens follow the grid surface.** Unless you set `toolbar.*`, the toolbar uses the header background, header text and grid border colours.
|
|
47
47
|
- **Row and header heights reach the layout.** `grid.rowHeightStandard` / `grid.headerHeight` (and `rowHeightCompact` / `rowHeightComfortable` with `density`) are read by the grid itself, which virtualizes from them. They must be pixel values (`'36px'` or `'36'`); other units are ignored. The `rowHeight` / `headerHeight` props win over the theme.
|
|
48
48
|
|
|
49
|
-
> **Sizing:** the wrapper `div` (`.ogx-theme-provider`) is a normal auto-height block.
|
|
49
|
+
> **Sizing:** the wrapper `div` (`.ogx-theme-provider`) is a normal auto-height block. A grid without a `height` prop (or with `height="100%"`) fills its parent, which here is the wrapper, so inside a bounded container pass `style={{ height: '100%' }}` (or a `className` that sets a height) to the provider too. Otherwise the wrapper grows to fit every row and row virtualization is effectively off. See [Virtualization → The grid needs a bounded height](../features/virtualization.md#the-grid-needs-a-bounded-height).
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
@@ -78,7 +78,7 @@ List view pages exactly like the grid view: with `pagination`, one page of the (
|
|
|
78
78
|
|
|
79
79
|
`onRowsScrollEnd` fires when the list is scrolled to within 100px of its bottom, so the [infinite scroll](./infinite-scroll.md) pattern works in list view too. As in the grid view, it fires once per arrival: it fires again only after the list leaves that zone or the row count changes (for example, when the next page has loaded).
|
|
80
80
|
|
|
81
|
-
The list view is **not virtualized**: it renders every row it shows (one page with `pagination`, otherwise all rows). Use pagination for large datasets. `slots.footer` is rendered below the list (in place of its pagination controls); the aggregation footer row is not shown in list view.
|
|
81
|
+
The list view is **not virtualized**: it renders every row it shows (one page with `pagination`, otherwise all rows). Use pagination for large datasets: rendering tens of thousands of cards freezes the page, and in development the grid warns when the list view renders more than 2,000 items (v3.0.1+). `slots.footer` is rendered below the list (in place of its pagination controls); the aggregation footer row is not shown in list view.
|
|
82
82
|
|
|
83
83
|
## ♿ Accessibility
|
|
84
84
|
|
|
@@ -10,6 +10,14 @@ Generate a styled PDF report from grid data using `exportToPdf()`.
|
|
|
10
10
|
npm install jspdf jspdf-autotable
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
> **Currency symbols such as `₹` print as `?` by default.** The built-in Helvetica font only covers Latin-1. Pass the [`font` option](#non-latin-text-and-unicode-fonts) with a Unicode `.ttf`:
|
|
14
|
+
>
|
|
15
|
+
> ```ts
|
|
16
|
+
> await exportToPdf(rows, columns, { fileName: 'invoices', font: { name: 'NotoSans', data: notoSansBase64 } });
|
|
17
|
+
> ```
|
|
18
|
+
|
|
19
|
+
> **Large datasets:** PDF generation runs on the main thread, and time and file size grow with every row: 50,000 grouped rows took 10–16 s (the page is unresponsive meanwhile) and produced a file of about 120 MB. For more than a few thousand rows, export CSV (`exportToCsv`) or `.xlsx` (`exportToExcelAdvanced`) instead, or export a filtered subset.
|
|
20
|
+
|
|
13
21
|
## Basic Usage
|
|
14
22
|
|
|
15
23
|
```tsx
|
|
@@ -134,6 +142,14 @@ System columns (`__check__`, `__actions__`) and spacer columns (`isSpacer: true`
|
|
|
134
142
|
|
|
135
143
|
## Troubleshooting
|
|
136
144
|
|
|
145
|
+
**`₹` or other characters print as `?`**
|
|
146
|
+
|
|
147
|
+
Pass the `font` option with a Unicode TrueType font. See [Non-Latin text](#non-latin-text-and-unicode-fonts).
|
|
148
|
+
|
|
149
|
+
**Export is slow or the file is huge**
|
|
150
|
+
|
|
151
|
+
PDF is not suited to tens of thousands of rows (see Installation above). Use CSV or `.xlsx` for large exports.
|
|
152
|
+
|
|
137
153
|
**Error: "exportToPdf requires 'jspdf' and 'jspdf-autotable'"**
|
|
138
154
|
|
|
139
155
|
Run: `npm install jspdf jspdf-autotable`
|
package/docs/features/pinning.md
CHANGED
|
@@ -20,6 +20,7 @@ Columns can be pinned to the left or right edges of the grid. Pinned columns rem
|
|
|
20
20
|
|
|
21
21
|
### Order and widths
|
|
22
22
|
- Pinned columns render in the order of `pinnedColumns.left` / `pinnedColumns.right`, not in column order. Pinning from the column menu appends the column to the end of its side, so it lands next to the scrolling columns.
|
|
23
|
+
- When the columns are narrower than the grid, right-pinned columns sit at the grid's right edge, and the free space is between the scrolling columns and them (v3.0.1+).
|
|
23
24
|
- A pinned column is sized exactly as it would be unpinned: numbers, percentages, `flex` and `'auto'` all apply, clamped to `minWidth` / `maxWidth`. The sticky offsets use those widths, so pinned columns never overlap.
|
|
24
25
|
|
|
25
26
|
### Column Configuration
|
|
@@ -53,37 +53,39 @@ Without the stylesheet the viewport does not scroll, so the grid renders every r
|
|
|
53
53
|
|
|
54
54
|
Virtualization renders as many rows as fit in the grid's viewport. If the grid's container has no bounded height, the viewport grows to fit **every** row, so every row is rendered. Nothing errors; the grid just stops virtualizing.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
**Without a `height` prop the grid fills its container** (since 3.0.1): its root gets `height: 100%` and, as a flex item, `flex: 1 1 auto; min-height: 0`. So it fills a sized block parent, or the free space of a flex column, and virtualizes. In a container with no definite height, `100%` resolves to `auto` and the grid grows to fit its rows, exactly as before. Passing `height` (a number or any CSS length) sets the height instead; `autoHeight` always grows to fit every row.
|
|
57
|
+
|
|
58
|
+
The most common cause of an unbounded container is a flex child that is missing `min-height: 0`. A flex item defaults to `min-height: auto`, which lets it grow to its content:
|
|
57
59
|
|
|
58
60
|
```tsx
|
|
59
|
-
// ❌
|
|
61
|
+
// ❌ The wrapper grows to fit all rows — virtualization is effectively off
|
|
60
62
|
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
|
|
61
63
|
<div style={{ flex: 1 }}>
|
|
62
|
-
<DataGrid rows={rows} columns={columns}
|
|
64
|
+
<DataGrid rows={rows} columns={columns} />
|
|
63
65
|
</div>
|
|
64
66
|
</div>
|
|
65
67
|
|
|
66
68
|
// ✅ Bounded — only visible rows render
|
|
67
69
|
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
|
|
68
70
|
<div style={{ flex: 1, minHeight: 0 }}>
|
|
69
|
-
<DataGrid rows={rows} columns={columns}
|
|
71
|
+
<DataGrid rows={rows} columns={columns} />
|
|
70
72
|
</div>
|
|
71
73
|
</div>
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
Every flex (or grid) item between the grid and the element with a fixed height (`100vh`, `600px`, …) needs `min-height: 0`. The grid itself can also be the flex item: `<div style={{ display: 'flex', flexDirection: 'column', height: 600 }}><Toolbar /><DataGrid … /></div>` gives the grid the space left after the toolbar.
|
|
75
77
|
|
|
76
|
-
**`DataGridThemeProvider` counts as an ancestor.** It renders a plain `<div class="ogx-theme-provider">` around the grid, and that wrapper is auto-height like any other `div`.
|
|
78
|
+
**`DataGridThemeProvider` counts as an ancestor.** It renders a plain `<div class="ogx-theme-provider">` around the grid, and that wrapper is auto-height like any other `div`. Inside a bounded container, give the wrapper a height as well:
|
|
77
79
|
|
|
78
80
|
```tsx
|
|
79
81
|
<div style={{ flex: 1, minHeight: 0 }}>
|
|
80
82
|
<DataGridThemeProvider theme={theme} style={{ height: '100%' }}>
|
|
81
|
-
<DataGrid rows={rows} columns={columns}
|
|
83
|
+
<DataGrid rows={rows} columns={columns} />
|
|
82
84
|
</DataGridThemeProvider>
|
|
83
85
|
</div>
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
In development builds the grid logs a `console.warn` when it
|
|
88
|
+
In development builds the grid logs a `console.warn` when it is rendering every row of a dataset larger than 200 rows and its viewport is at least as tall as those rows, that is, when its container really is unbounded. The warning names the fixes above.
|
|
87
89
|
|
|
88
90
|
Pagination can hide this problem, because a paginated grid only has one page of rows to render. Row grouping switches pagination off (see below), so an unbounded container that looked fine with pagination can freeze the tab once grouping is enabled.
|
|
89
91
|
|
|
@@ -205,7 +207,7 @@ When using detail panels, row heights become variable. The grid automatically:
|
|
|
205
207
|
|
|
206
208
|
## Virtualization with Grouping/Tree Data
|
|
207
209
|
|
|
208
|
-
Grouped and tree rows go through the same virtualizer as flat rows. Expanding a group of any size adds its rows to the virtual row list, not to the DOM: in a bounded container, expanding a 25,000-row group renders ~20 DOM rows (verified in Chromium by `DataGrid.virtualization.browser.test.tsx`).
|
|
210
|
+
Grouped and tree rows go through the same virtualizer as flat rows. Expanding a group of any size adds its rows to the virtual row list, not to the DOM: in a bounded container, expanding a 25,000-row group renders ~20 DOM rows (verified in Chromium, Firefox and WebKit by `DataGrid.virtualization.browser.test.tsx`).
|
|
209
211
|
|
|
210
212
|
```tsx
|
|
211
213
|
// Tree data with virtualization
|
|
@@ -53,6 +53,8 @@ import '@opencorestack/opengridx/styles';
|
|
|
53
53
|
|
|
54
54
|
Without it the grid is unstyled and its viewport has no bounded height, so **every row renders** (virtualization is effectively off). If your v2 app looked fine, you already have this import. In development, 3.0.0 logs a warning when the stylesheet is not loaded.
|
|
55
55
|
|
|
56
|
+
> **3.0.1 note — height.** Without a `height` prop the grid now fills its container (root class `ogx--fill`: `height: 100%`, and as a flex item `flex: 1 1 auto; min-height: 0`). In 3.0.0 the root was auto-height, so inside a bounded flex layout it grew to fit every row. The container still needs a bounded height (a definite height, or `min-height: 0` on every flex / grid ancestor up to the sized one); in an auto-height container the grid still grows to fit. An explicit `height`, `style.height` or `autoHeight` is never stretched. The unbounded-container dev warning is only logged when the viewport really is as tall as its rows.
|
|
57
|
+
|
|
56
58
|
### Know the size limit
|
|
57
59
|
|
|
58
60
|
A single scrolling grid tops out at about 645,000 rows at the default 52px row height in Chromium (the browser's maximum element height). Above that, use pagination or a `dataSource`. The grid logs a dev warning when content is taller than browsers can scroll.
|
|
@@ -427,6 +429,8 @@ Pruning applies when the grid owns the rows: no `dataSource`, client pagination
|
|
|
427
429
|
|
|
428
430
|
**Fix it:** call the setter and let your change callback update controlled state; remove duplicate `setState` calls.
|
|
429
431
|
|
|
432
|
+
> **3.0.1 note — typed row getters.** `useGridApiRef<MyRow>()` returns a `GridApi<MyRow>` whose `getRow`, `getAllRows`, `getVisibleRows` and `getAllFilteredRows` return `MyRow`, so the casts v2 needed can go. `useGridApiRef()` without a type argument and `DataGridProps.apiRef` with an untyped ref still compile.
|
|
433
|
+
|
|
430
434
|
---
|
|
431
435
|
|
|
432
436
|
## 11. Editing
|
|
@@ -714,6 +718,8 @@ Keep `getRows` stable (`useCallback` or module scope) if you do not want a refet
|
|
|
714
718
|
| Sticky header and pinned rows | `.ogx__pinned-rows--top` / `--bottom` were sticky | wrapped in `div.ogx__sticky-top` / `div.ogx__sticky-bottom` (see [§24](#24-dom-and-css-class-changes)) |
|
|
715
719
|
| z-index of sticky body system cells | 4 / 5 / 11 | 12; header drag / expand cells have no inline z-index |
|
|
716
720
|
| Returning from list view | scroll reset | scroll position restored |
|
|
721
|
+
| Right-pinned columns when columns are narrower than the grid | followed the last unpinned column | at the grid's right edge (3.0.1; free space sits before the right-pinned section) |
|
|
722
|
+
| No `height` prop | auto height (3.0.0) | fills the container, `ogx--fill` (3.0.1; see [Before you start](#import-the-stylesheet)) |
|
|
717
723
|
|
|
718
724
|
**Who is affected:** apps with `onRowsScrollEnd` loaders that relied on repeated firing, apps with custom z-index or sticky CSS, and apps whose pinned columns were pinned out of column order.
|
|
719
725
|
|
|
@@ -751,6 +757,7 @@ export function Pinned({ rows, columns }: { rows: GridRowModel[]; columns: GridC
|
|
|
751
757
|
| Click on the resize handle without moving | resized / sorted | nothing |
|
|
752
758
|
| Resize events | mouse events on `document` | pointer events with capture on the handle (touch and pen work) |
|
|
753
759
|
| Right-pinned column resize | right edge | left edge (`ogx-column-resize-handle--start`); drag left to widen |
|
|
760
|
+
| Resize handle position | straddled the cell border (`right: -4px`); half was clipped, 3–4px grabbable | inside its own header cell against the resizing edge (`right: 0` / `left: 0`), all 8px grabbable (3.0.1) |
|
|
754
761
|
| `dragstart` data types | `text/plain` | `application/x-ogx-row` / `application/x-ogx-column` plus `text/plain` |
|
|
755
762
|
| Toolbar, pivot and standalone panels | portal mounted in render | mounted one layout effect later (invisible to users; matters for tests) |
|
|
756
763
|
|
|
@@ -967,6 +974,8 @@ CSS: `.ogx-col-group-row` no longer has `overflow: hidden`; new `ogx-col-group-c
|
|
|
967
974
|
| Tree data and grouping | no expand control | expand chevron and depth indent (`.ogx-list-view__expand`) |
|
|
968
975
|
| Summary and paging with a `dataSource` | loaded rows | server total |
|
|
969
976
|
| `onRowsScrollEnd` | never fired | fires once per arrival at the bottom, like the grid view |
|
|
977
|
+
| Large lists | not virtualized | still not virtualized; 3.0.1 warns in development above 2,000 rendered items — use pagination |
|
|
978
|
+
| Tab in Firefox | — | lands on the focused row, not the rows container (3.0.1, `tabIndex={-1}` on `.ogx-list-view__rows`) |
|
|
970
979
|
|
|
971
980
|
---
|
|
972
981
|
|
|
@@ -1002,6 +1011,7 @@ CSS: `.ogx-col-group-row` no longer has `overflow: hidden`; new `ogx-col-group-c
|
|
|
1002
1011
|
| `ogx__row--group-footer` | subtotal rows in `'footer'` position |
|
|
1003
1012
|
| `ogx__cell-image` | default `<img>` for `type: 'image'` |
|
|
1004
1013
|
| `ogx-column-resize-handle--start` | resize handle on the left edge (right-pinned columns) |
|
|
1014
|
+
| `ogx--fill` (3.0.1) | grid root when no `height`, `style.height` or `autoHeight` is set |
|
|
1005
1015
|
| `ogx-col-group-cell--pinned`, `ogx-col-group-cell--pinned-left`, `ogx-col-group-cell--pinned-right` | pinned column-group cells |
|
|
1006
1016
|
| `ogx-filter__hidden-note`, `ogx-filter__value-multiselect` | filter panel |
|
|
1007
1017
|
| `ogx-list-view__expand`, `ogx-list-view__loading` | list view |
|
|
@@ -1019,7 +1029,8 @@ CSS: `.ogx-col-group-row` no longer has `overflow: hidden`; new `ogx-col-group-c
|
|
|
1019
1029
|
| `.ogx-global-search--expanded` | shows the input border while expanded and unfocused; the primary border and focus shadow moved to `:focus-within` |
|
|
1020
1030
|
| `.ogx__cell--focused`, `.ogx__header-cell--focused`, `.ogx__header-cell--focus-visible` | outline colour reads `--ogx-grid-cell-focus-border` (falls back to `--ogx-color-primary`) |
|
|
1021
1031
|
| `.ogx__header-cell--drag-over` | background `--ogx-color-primary-light` (was the undefined `--ogx-color-blue-50`) |
|
|
1022
|
-
| `.ogx-column-resize-handle` | `touch-action: none`; a `:focus-visible` line colour |
|
|
1032
|
+
| `.ogx-column-resize-handle` | `touch-action: none`; a `:focus-visible` line colour; 3.0.1: `right: 0` (was `-4px`), `justify-content: flex-end`; `--start` is `left: 0`, `flex-start` |
|
|
1033
|
+
| `.ogx__header-cell--pinned-right-first`, `.ogx__cell--pinned-right-first`, `.ogx__aggregation-cell--pinned-right-first`, first right-pinned `.ogx-col-group-cell` (3.0.1) | `margin-left: auto`; `.ogx__content` width is `max(100%, <total>px)` when right-pinned columns exist |
|
|
1023
1034
|
| `.ogx-list-view__row` | `:focus-visible` outline (rows are focusable) |
|
|
1024
1035
|
| `.ogx-toolbar` and its buttons / chips, `.ogx-global-search`, scrollbars, filter-panel delete button | read the `--ogx-toolbar-*`, `--ogx-scrollbar-*` and `--ogx-overlay-item-danger-*` variables the theme provider sets (the filter-panel delete button used `--ogx-toolbar-btn-danger-*`); fallbacks match the v2 colours except the danger-button hover |
|
|
1025
1036
|
|
package/docs/roadmap.md
CHANGED
|
@@ -90,7 +90,7 @@ This document tracks the current status of features in `OpenGridX` and outlines
|
|
|
90
90
|
- `slots.footer`, `slots.noRowsOverlay` and `slots.loadingOverlay` are rendered (they were typed but ignored).
|
|
91
91
|
- New `onRowDoubleClick`; `ColumnVisibilityPanel` exported; `exportToExcelAdvanced` accepts `groupedRows`.
|
|
92
92
|
- Dev-mode warnings for an unbounded grid container and for `pagination` with row grouping.
|
|
93
|
-
- Real-browser test project (Vitest browser mode + Playwright
|
|
93
|
+
- Real-browser test project (Vitest browser mode + Playwright; Chromium, Firefox and WebKit), `npm run test:browser`; the npm publish workflow now runs unit and browser tests before publishing.
|
|
94
94
|
- Already shipped, previously listed as upcoming: npm publishing (since 0.1.0), native PDF export (v1.2.1), GitHub Pages deployment.
|
|
95
95
|
|
|
96
96
|
### Library Hardening *(completed 2026-09-02)*
|
|
@@ -58,6 +58,10 @@
|
|
|
58
58
|
.ogx__cell--pinned-right {
|
|
59
59
|
border-left: 1px solid var(--ogx-grid-border-color);
|
|
60
60
|
}
|
|
61
|
+
/* When the columns are narrower than the grid, the free space goes before the right-pinned section. */
|
|
62
|
+
.ogx__cell--pinned-right-first {
|
|
63
|
+
margin-left: auto;
|
|
64
|
+
}
|
|
61
65
|
.ogx:not(.ogx--row-spanning) .ogx__row:hover .ogx__cell--pinned-left,
|
|
62
66
|
.ogx:not(.ogx--row-spanning) .ogx__row:hover .ogx__cell--pinned-right {
|
|
63
67
|
background-color: var(--ogx-grid-row-hover-background);
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
.ogx-column-resize-handle {
|
|
2
2
|
position: absolute;
|
|
3
3
|
top: 0;
|
|
4
|
-
|
|
4
|
+
/* Inside the header cell: the cell clips overflow, so a handle straddling the border lost its outer half. */
|
|
5
|
+
right: 0;
|
|
5
6
|
width: 8px;
|
|
6
7
|
height: 100%;
|
|
7
8
|
cursor: col-resize;
|
|
8
9
|
z-index: 10;
|
|
9
10
|
display: flex;
|
|
10
11
|
align-items: center;
|
|
11
|
-
justify-content:
|
|
12
|
+
justify-content: flex-end;
|
|
12
13
|
user-select: none;
|
|
13
14
|
/* Touch and pen drags resize the column instead of scrolling the grid. */
|
|
14
15
|
touch-action: none;
|
|
@@ -16,7 +17,8 @@
|
|
|
16
17
|
/* Right-pinned columns grow leftwards: their handle sits on the left edge. */
|
|
17
18
|
.ogx-column-resize-handle--start {
|
|
18
19
|
right: auto;
|
|
19
|
-
left:
|
|
20
|
+
left: 0;
|
|
21
|
+
justify-content: flex-start;
|
|
20
22
|
}
|
|
21
23
|
.ogx-column-resize-handle:focus-visible .ogx-column-resize-handle__line {
|
|
22
24
|
background: var(--ogx-color-primary);
|
|
@@ -88,6 +88,13 @@
|
|
|
88
88
|
justify-content: center;
|
|
89
89
|
z-index: var(--ogx-z-index-modal);
|
|
90
90
|
}
|
|
91
|
+
/* No height prop: fill the container, as a block child of a sized box (height: 100%) or as a
|
|
92
|
+
flex item (flex: 1 with min-height: 0). In an auto-height parent 100% resolves to auto. */
|
|
93
|
+
.ogx--fill {
|
|
94
|
+
height: 100%;
|
|
95
|
+
flex: 1 1 auto;
|
|
96
|
+
min-height: 0;
|
|
97
|
+
}
|
|
91
98
|
.ogx--auto-height {
|
|
92
99
|
height: auto;
|
|
93
100
|
}
|
|
@@ -274,6 +281,7 @@
|
|
|
274
281
|
box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, 0.1);
|
|
275
282
|
}
|
|
276
283
|
.ogx__aggregation-cell--pinned-right-first {
|
|
284
|
+
margin-left: auto;
|
|
277
285
|
overflow: visible;
|
|
278
286
|
}
|
|
279
287
|
.ogx__aggregation-cell--pinned-right-first::before {
|
|
@@ -595,6 +595,7 @@ export function DataGrid<R extends GridRowModel = GridRowModel>(props: DataGridP
|
|
|
595
595
|
pinnedRowsIgnored: isHierarchyEnabled && Boolean(pinnedRows?.top?.length || pinnedRows?.bottom?.length),
|
|
596
596
|
scrollHeight: virtualization.totalHeight,
|
|
597
597
|
listViewWithoutColumn: listViewRequested && !listViewColumn,
|
|
598
|
+
listViewRowCount: listView && listViewColumn ? allRenderableRows.length : 0,
|
|
598
599
|
});
|
|
599
600
|
|
|
600
601
|
const { allSelected, someSelected } = rowSelection;
|
|
@@ -660,7 +661,7 @@ export function DataGrid<R extends GridRowModel = GridRowModel>(props: DataGridP
|
|
|
660
661
|
return (
|
|
661
662
|
<div
|
|
662
663
|
ref={containerRef}
|
|
663
|
-
className={['ogx', className, autoHeight && 'ogx--auto-height', hasRowSpanning && 'ogx--row-spanning', listView && 'ogx--list-view'].filter(Boolean).join(' ')}
|
|
664
|
+
className={['ogx', className, autoHeight && 'ogx--auto-height', !autoHeight && height === undefined && style?.height === undefined && 'ogx--fill', hasRowSpanning && 'ogx--row-spanning', listView && 'ogx--list-view'].filter(Boolean).join(' ')}
|
|
664
665
|
style={{
|
|
665
666
|
...style,
|
|
666
667
|
height: height ?? style?.height,
|
|
@@ -755,7 +756,10 @@ export function DataGrid<R extends GridRowModel = GridRowModel>(props: DataGridP
|
|
|
755
756
|
<div
|
|
756
757
|
className="ogx__content"
|
|
757
758
|
style={{
|
|
758
|
-
|
|
759
|
+
// With right-pinned columns the content spans at least the viewport, so they sit at its right edge.
|
|
760
|
+
width: effectivePinnedColumns?.right?.length
|
|
761
|
+
? `max(100%, ${virtualization.totalWidth}px)`
|
|
762
|
+
: virtualization.totalWidth
|
|
759
763
|
}}
|
|
760
764
|
role="presentation"
|
|
761
765
|
>
|
|
@@ -202,7 +202,8 @@ export function GridListView<R extends GridRowModel>({
|
|
|
202
202
|
</span>
|
|
203
203
|
</div>
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
{/* tabIndex -1: Firefox otherwise makes this scroll container a Tab stop of its own; the rows carry the roving tab stop. */}
|
|
206
|
+
<div className="ogx-list-view__rows" tabIndex={-1} onScroll={handleScroll} onKeyDown={handleKeyDown} ref={rowsRef}>
|
|
206
207
|
{allRenderableRows.length === 0 && loading ? (
|
|
207
208
|
// The grid's live region announces loading; the list shows no "No Data" meanwhile.
|
|
208
209
|
<div className="ogx-list-view__loading">
|
|
@@ -148,6 +148,9 @@
|
|
|
148
148
|
.ogx__header-cell--pinned-left {
|
|
149
149
|
box-shadow: var(--ogx-grid-pinned-left-shadow, 4px 0 12px -4px rgba(0, 0, 0, 0.05));
|
|
150
150
|
}
|
|
151
|
+
.ogx__header-cell--pinned-right-first {
|
|
152
|
+
margin-left: auto;
|
|
153
|
+
}
|
|
151
154
|
.ogx__header-cell--pinned-right {
|
|
152
155
|
box-shadow: var(--ogx-grid-pinned-right-shadow, -4px 0 12px -4px rgba(0, 0, 0, 0.05));
|
|
153
156
|
}
|
|
@@ -263,7 +263,7 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
|
|
|
263
263
|
aria-hidden="true"
|
|
264
264
|
/>
|
|
265
265
|
)}
|
|
266
|
-
{cells.map(cell => {
|
|
266
|
+
{cells.map((cell, cellIndex) => {
|
|
267
267
|
const pinnedClass = cell.pinned ? ` ogx-col-group-cell--pinned ogx-col-group-cell--pinned-${cell.pinned}` : '';
|
|
268
268
|
const style: React.CSSProperties = {
|
|
269
269
|
width: cell.width,
|
|
@@ -277,6 +277,8 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
|
|
|
277
277
|
} else if (cell.pinned === 'right') {
|
|
278
278
|
style.position = 'sticky';
|
|
279
279
|
style.right = pinnedPositions[cell.fields[cell.fields.length - 1]];
|
|
280
|
+
// Free space goes before the right-pinned section, as in the column header row.
|
|
281
|
+
if (cells[cellIndex - 1]?.pinned !== 'right') style.marginLeft = 'auto';
|
|
280
282
|
}
|
|
281
283
|
if (!cell.isGroup) {
|
|
282
284
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GridApi } from '../../types';
|
|
1
|
+
import type { GridApi, GridRowModel, GridValidRowModel } from '../../types';
|
|
2
2
|
|
|
3
3
|
const noop = () => {};
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ const noop = () => {};
|
|
|
7
7
|
* `apiRef.current` is never null (its type says it is not) before the grid has mounted;
|
|
8
8
|
* the grid replaces it with the live API when it mounts.
|
|
9
9
|
*/
|
|
10
|
-
export function createGridApiPlaceholder(): GridApi {
|
|
10
|
+
export function createGridApiPlaceholder<R extends GridValidRowModel = GridRowModel>(): GridApi<R> {
|
|
11
11
|
return {
|
|
12
12
|
getRow: () => null,
|
|
13
13
|
getAllRows: () => [],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useRef, useState } from 'react';
|
|
2
2
|
import type { MutableRefObject } from 'react';
|
|
3
|
-
import type { GridApi } from '../../types';
|
|
3
|
+
import type { GridApi, GridRowModel, GridValidRowModel } from '../../types';
|
|
4
4
|
import { createGridApiPlaceholder } from './gridApiPlaceholder';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -15,8 +15,11 @@ import { createGridApiPlaceholder } from './gridApiPlaceholder';
|
|
|
15
15
|
* which matches `DataGridProps.apiRef` under both @types/react 18 and 19. Left to inference,
|
|
16
16
|
* React 19's types emit `RefObject<GridApi>`, which React 18's types treat as read-only and
|
|
17
17
|
* nullable, so `apiRef={useGridApiRef()}` failed to type-check on React 18.
|
|
18
|
+
*
|
|
19
|
+
* Pass your row type to have the row getters typed: `useGridApiRef<Invoice>().current.getRow(id)`
|
|
20
|
+
* returns `Invoice | null`.
|
|
18
21
|
*/
|
|
19
|
-
export function useGridApiRef(): MutableRefObject<GridApi
|
|
20
|
-
const [placeholder] = useState(createGridApiPlaceholder);
|
|
21
|
-
return useRef<GridApi
|
|
22
|
+
export function useGridApiRef<R extends GridValidRowModel = GridRowModel>(): MutableRefObject<GridApi<R>> {
|
|
23
|
+
const [placeholder] = useState(createGridApiPlaceholder<R>);
|
|
24
|
+
return useRef<GridApi<R>>(placeholder);
|
|
22
25
|
}
|
|
@@ -14,11 +14,16 @@ export interface UseGridDevWarningsParams {
|
|
|
14
14
|
scrollHeight?: number;
|
|
15
15
|
/** `listView` is set but `listViewColumn` is not, so the grid view is shown. */
|
|
16
16
|
listViewWithoutColumn?: boolean;
|
|
17
|
+
/** Number of items the list view renders (0 when the list view is not shown). It does not virtualize. */
|
|
18
|
+
listViewRowCount?: number;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
// Below this many rows, rendering everything is harmless, so an unbounded container is not worth a warning.
|
|
20
22
|
const UNBOUNDED_WARN_THRESHOLD = 200;
|
|
21
23
|
|
|
24
|
+
/** The list view renders every item; above this many the page slows down noticeably. */
|
|
25
|
+
export const LIST_VIEW_WARN_THRESHOLD = 2000;
|
|
26
|
+
|
|
22
27
|
/**
|
|
23
28
|
* Browsers cap element heights (Firefox at about 17.9M px, Chromium and Safari at about 33.5M px):
|
|
24
29
|
* rows laid out below the cap cannot be scrolled to.
|
|
@@ -26,12 +31,22 @@ const UNBOUNDED_WARN_THRESHOLD = 200;
|
|
|
26
31
|
export const MAX_SCROLLABLE_HEIGHT = 17_800_000;
|
|
27
32
|
|
|
28
33
|
export function useGridDevWarnings(params: UseGridDevWarningsParams): void {
|
|
29
|
-
const { paginationRequested, isRowGrouping, autoHeight, viewportHeight, renderedRowCount, totalRowCount, pinnedRowsIgnored = false, scrollHeight = 0, listViewWithoutColumn = false } = params;
|
|
34
|
+
const { paginationRequested, isRowGrouping, autoHeight, viewportHeight, renderedRowCount, totalRowCount, pinnedRowsIgnored = false, scrollHeight = 0, listViewWithoutColumn = false, listViewRowCount = 0 } = params;
|
|
30
35
|
const warnedPaginationRef = useRef(false);
|
|
31
36
|
const warnedUnboundedRef = useRef(false);
|
|
32
37
|
const warnedPinnedRowsRef = useRef(false);
|
|
33
38
|
const warnedHeightRef = useRef(false);
|
|
34
39
|
const warnedListViewRef = useRef(false);
|
|
40
|
+
const warnedListViewSizeRef = useRef(false);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (process.env.NODE_ENV === 'production' || warnedListViewSizeRef.current || listViewRowCount <= LIST_VIEW_WARN_THRESHOLD) return;
|
|
44
|
+
warnedListViewSizeRef.current = true;
|
|
45
|
+
console.warn(
|
|
46
|
+
`[OpenGridX] The list view is rendering all ${listViewRowCount} items: it does not virtualize. ` +
|
|
47
|
+
'Above a few thousand items use `pagination`, server-side loading, or the grid view. See docs/features/list-view.md.'
|
|
48
|
+
);
|
|
49
|
+
}, [listViewRowCount]);
|
|
35
50
|
|
|
36
51
|
useEffect(() => {
|
|
37
52
|
if (process.env.NODE_ENV === 'production' || warnedListViewRef.current || !listViewWithoutColumn) return;
|
|
@@ -74,15 +89,18 @@ export function useGridDevWarnings(params: UseGridDevWarningsParams): void {
|
|
|
74
89
|
|
|
75
90
|
useEffect(() => {
|
|
76
91
|
if (process.env.NODE_ENV === 'production' || warnedUnboundedRef.current || autoHeight) return;
|
|
77
|
-
|
|
92
|
+
// Really unbounded: every row is rendered and the viewport is at least as tall as the rows, so it never scrolls.
|
|
93
|
+
if (viewportHeight > 0 && totalRowCount > UNBOUNDED_WARN_THRESHOLD && renderedRowCount >= totalRowCount && viewportHeight >= scrollHeight) {
|
|
78
94
|
warnedUnboundedRef.current = true;
|
|
79
95
|
console.warn(
|
|
80
96
|
`[OpenGridX] The grid viewport is ${Math.round(viewportHeight)}px tall and is rendering all ${totalRowCount} rows, ` +
|
|
81
|
-
'so row virtualization is effectively off
|
|
82
|
-
'
|
|
97
|
+
'so row virtualization is effectively off: the grid fills its container, and the container grows to fit every row. ' +
|
|
98
|
+
'Give the container a definite height (for example `height: 600px` or `100vh`). If the container, or any ancestor ' +
|
|
99
|
+
'up to the sized one, is a flex or grid item, add `min-height: 0` to it. Alternatively pass a `height` prop, ' +
|
|
100
|
+
'or `autoHeight` if rendering every row is intended. See docs/features/virtualization.md.'
|
|
83
101
|
);
|
|
84
102
|
}
|
|
85
|
-
}, [autoHeight, viewportHeight, renderedRowCount, totalRowCount]);
|
|
103
|
+
}, [autoHeight, viewportHeight, renderedRowCount, totalRowCount, scrollHeight]);
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
/**
|
package/lib/types/index.ts
CHANGED
|
@@ -912,8 +912,11 @@ export interface DataGridProps<R extends GridValidRowModel = GridRowModel> {
|
|
|
912
912
|
/** Callback fired when scrolling reaches the bottom of the grid viewport. */
|
|
913
913
|
onRowsScrollEnd?: (params: GridRowScrollEndParams) => void;
|
|
914
914
|
|
|
915
|
-
/**
|
|
916
|
-
|
|
915
|
+
/**
|
|
916
|
+
* Advanced: reactive reference to the internal API for imperative control. Pass
|
|
917
|
+
* `useGridApiRef<MyRow>()` to have the row getters typed as `MyRow`; a plain `useGridApiRef()` also works.
|
|
918
|
+
*/
|
|
919
|
+
apiRef?: React.MutableRefObject<GridApi<R>> | React.MutableRefObject<GridApi>;
|
|
917
920
|
|
|
918
921
|
/** Custom components to replace internal grid parts. */
|
|
919
922
|
slots?: {
|
|
@@ -1052,18 +1055,22 @@ export type GridDetailPanelHeight = number | 'auto';
|
|
|
1052
1055
|
* The Imperative API for interacting with the DataGrid.
|
|
1053
1056
|
* Access this via the `apiRef` prop or a ref passed to the component.
|
|
1054
1057
|
*/
|
|
1055
|
-
|
|
1058
|
+
/**
|
|
1059
|
+
* The imperative grid API. `R` types the row getters (`getRow`, `getAllRows`, `getVisibleRows`,
|
|
1060
|
+
* `getAllFilteredRows`); it defaults to `GridRowModel`, so `GridApi` alone keeps working.
|
|
1061
|
+
*/
|
|
1062
|
+
export interface GridApi<R extends GridValidRowModel = GridRowModel> {
|
|
1056
1063
|
/**
|
|
1057
1064
|
* Returns the row model with the given ID.
|
|
1058
1065
|
* @param id The row unique ID.
|
|
1059
1066
|
*/
|
|
1060
|
-
getRow: (id: GridRowId) =>
|
|
1067
|
+
getRow: (id: GridRowId) => R | null;
|
|
1061
1068
|
/** Returns all rows currently loaded into the grid. */
|
|
1062
|
-
getAllRows: () =>
|
|
1069
|
+
getAllRows: () => R[];
|
|
1063
1070
|
/** Returns all rows currently visible after filtering and sorting. */
|
|
1064
|
-
getVisibleRows: () =>
|
|
1071
|
+
getVisibleRows: () => R[];
|
|
1065
1072
|
/** Returns all filtered and sorted rows, ignoring pagination. Use this for full-dataset exports. */
|
|
1066
|
-
getAllFilteredRows: () =>
|
|
1073
|
+
getAllFilteredRows: () => R[];
|
|
1067
1074
|
/**
|
|
1068
1075
|
* Returns an ordered flat list of `GridGroupedExportRow` entries that mirrors the
|
|
1069
1076
|
* on-screen grouping tree: group-headers, leaf rows, per-group subtotals, and a
|