@opencorestack/opengridx 3.0.1 → 3.2.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 CHANGED
@@ -5,6 +5,30 @@
5
5
 
6
6
  ---
7
7
 
8
+ ## [3.2.0] — 2026-09-29
9
+
10
+ ### Added
11
+
12
+ - **Non-blocking `exportToPdf`** — the export now works in ~30 ms slices and yields to the event loop between them, both while formatting rows (including grouped rows and WinAnsi conversion) and while drawing the table: the body is drawn by a series of `jspdf-autotable` calls that continue on the same page with fixed column widths, the header repeated on every new page and the footer only at the end. Pages, row positions, shading and page breaks are unchanged (verified against a single call in Chromium, Firefox and WebKit). Measured with 50,000 grouped rows in Chromium: longest main-thread block 6.3 s → ~0.4–0.6 s (jsPDF's final save, which cannot be split), total time about the same (~6–7 s), file size unchanged.
13
+ - **`PdfExportOptions.onProgress`** — `({ phase: 'prepare' | 'render' | 'save', done, total }) => void`; new exported type `PdfExportProgress`.
14
+ - **`PdfExportOptions.signal`** — an `AbortSignal`; aborting rejects the promise with a `DOMException` named `'AbortError'` and saves no file.
15
+ - **`PdfExportOptions.maxRows`** (default 20,000) — above it a development-mode `console.warn` recommends `exportToCsv` / `exportToExcelAdvanced`. The export still runs; nothing is thrown.
16
+ - Demo: the PDF export page has a row-count selector, a progress bar and a Cancel button.
17
+
18
+ ## [3.1.0] — 2026-09-29
19
+
20
+ ### Added
21
+
22
+ - **`GridColDef.sortComparator(v1, v2, params1, params2)`** — a per-column ascending comparator for client-side sorting, used instead of the built-in type-aware comparison. `v1` / `v2` are the cell values after `valueGetter`, **including `null` / `undefined`** (the comparator decides where empty values go); `params` are the new exported `GridSortCellParams` `{ id, field, row, value }`. The grid negates the result for `desc`. It is used for flat sorting, as one key in a multi-sort chain, to order row-grouping groups by their grouping value (the grouping column's comparator), for tree-data siblings and for pivot row-label columns, so `getAllFilteredRows()`, exports and clipboard follow the same order. A comparator that throws or returns `NaN` reads as `0` with a one-time dev warning. Ignored with `sortingMode="server"`.
23
+ - **Auto-size a column to its content** — double-click a column's resize handle (or press Enter with the handle focused) to fit the column to its header and the cells in the current render window (pinned rows included), measured in the DOM and clamped to `minWidth` (default 50px) / `maxWidth`. A flex column gets a fixed width, like after a drag; `resizable: false` columns are never auto-sized; the double-click never sorts. Works for left/right-pinned columns and under column groups. The width goes to `columnWidths` state, so `onStateChange` reports it.
24
+ - **`apiRef.current.autosizeColumn(field)`** and **`apiRef.current.autosizeColumns(fields?)`** — the same measurement, programmatically (every column when `fields` is omitted).
25
+
26
+ ### Changed
27
+
28
+ - Double-clicking a resize handle used to do nothing; it now auto-sizes the column.
29
+
30
+ ---
31
+
8
32
  ## [3.0.1] — 2026-09-29
9
33
 
10
34
  Fixes from a smoke test in a real application (Chromium, Firefox and WebKit).
package/README.md CHANGED
@@ -153,8 +153,9 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
153
153
  | `colSpan` | `number \| ((params) => number)` | — | Merge cells horizontally. |
154
154
  | `rowSpan` | `number \| ((params) => number)` | — | Merge cells vertically. |
155
155
  | `sortable` | `boolean` | `true` | Enable/disable column sorting. |
156
+ | `sortComparator` | `(v1, v2, p1, p2) => number` | — | Custom ascending comparator (sees nulls; negated for desc). v3.1.0+ |
156
157
  | `filterable` | `boolean` | `true` | Enable/disable column filtering. |
157
- | `resizable` | `boolean` | `true` | Allow drag-resize. |
158
+ | `resizable` | `boolean` | `true` | Allow drag-resize; double-click the handle to auto-size to content (v3.1.0+). |
158
159
  | `hideable` | `boolean` | `true` | Allow hiding via the column panel. |
159
160
  | `pinnable` | `boolean` | `true` | Allow pinning via the UI. |
160
161
  | `disableColumnMenu` | `boolean` | `false` | Hide the column header context menu. |
@@ -310,6 +311,7 @@ apiRef.current.setPageSize(50)
310
311
 
311
312
  // Scroll
312
313
  apiRef.current.scrollToIndexes({ rowIndex: 100, colIndex: 3 })
314
+ apiRef.current.autosizeColumn('name') // fit to content (v3.1.0+)
313
315
 
314
316
  // Clipboard
315
317
  apiRef.current.copySelectedRows() // → Promise<void>, rejects if the clipboard write fails
@@ -435,7 +437,7 @@ printGrid(rows, columns, 'Report Title');
435
437
 
436
438
  > **Optional peer dependencies:** `exportToExcelAdvanced` requires ExcelJS (`npm install exceljs`); `exportToPdf` requires `npm install jspdf jspdf-autotable`.
437
439
 
438
- > **Large exports:** PDF generation runs on the main thread and grows fast (about 120 MB and 10–16 s for 50,000 grouped rows, with the page blocked meanwhile). For more than a few thousand rows export CSV or `.xlsx`. PDF's built-in font only covers Latin-1: pass the `font` option (a Unicode `.ttf`) for characters such as `₹`, otherwise they print as `?`. See [PDF Export](docs/features/pdf-export.md).
440
+ > **Large exports:** PDF size and time grow fast (75–120 MB and several seconds for 50,000 grouped rows). Since v3.2 `exportToPdf` yields between slices so the page stays responsive, reports `onProgress` and accepts an abort `signal`; above `maxRows` (default 20,000) it warns in development. For more than a few thousand rows export CSV or `.xlsx`. PDF's built-in font only covers Latin-1: pass the `font` option (a Unicode `.ttf`) for characters such as `₹`, otherwise they print as `?`. See [PDF Export](docs/features/pdf-export.md).
439
441
 
440
442
  CSV and HTML-Excel exports neutralise spreadsheet formulas (text starting with `=`, `+`, `-`, `@`, a tab or a carriage return gets a leading `'`; opt out with `escapeFormulas: false`), and CSV starts with a UTF-8 BOM (`bom: false` omits it). `exportToExcel` writes an HTML table, so a `.xlsx` file name is saved as `.xls`. To export what the grid shows, pass `apiRef.current.getAllFilteredRows()` and `apiRef.current.getVisibleColumns()`; with a custom `getRowId`, also pass `getRowId` in the options so `selectedRows` match. See the [Export Guide](docs/features/export-guide.md).
441
443
 
package/dist/index.d.ts CHANGED
@@ -671,6 +671,15 @@ export declare interface GridApi<R extends GridValidRowModel = GridRowModel> {
671
671
  rowIndex?: number;
672
672
  colIndex?: number;
673
673
  }) => void;
674
+ /**
675
+ * Sizes a column to fit its header and the cells rendered right now (the virtualization window),
676
+ * clamped to `minWidth` (default 50px) / `maxWidth`, like double-clicking its resize handle.
677
+ * Does nothing for `resizable: false` columns or a column that is not rendered.
678
+ * A flex column gets a fixed width. @since v3.1
679
+ */
680
+ autosizeColumn: (field: string) => void;
681
+ /** `autosizeColumn` for several columns (default: every column). @since v3.1 */
682
+ autosizeColumns: (fields?: readonly string[]) => void;
674
683
  /**
675
684
  * Programmatically copies all currently selected rows to the clipboard as TSV: every selected
676
685
  * row that passes the filter (other pages, collapsed groups and pinned rows included), with the
@@ -756,6 +765,16 @@ export declare interface GridColDef<R extends GridValidRowModel = GridRowModel>
756
765
  * @since v3.0
757
766
  */
758
767
  valueSetter?(params: GridValueSetterParams<R>): R;
768
+ /**
769
+ * Custom ascending comparator for client-side sorting by this column, used instead of the built-in
770
+ * type-aware comparison. `v1` / `v2` are the cell values (`valueGetter` applied) and **include
771
+ * `null` / `undefined`**, so the comparator decides where empty values go. The grid reverses the
772
+ * result for 'desc' and chains it with the other sort keys in a multi-sort. Row grouping uses the
773
+ * grouping column's comparator to order groups by their grouping value. A comparator that throws
774
+ * or returns NaN is read as 0 (with a one-time dev warning). Ignored with `sortingMode="server"`.
775
+ * @since v3.1
776
+ */
777
+ sortComparator?(v1: unknown, v2: unknown, params1: GridSortCellParams<R>, params2: GridSortCellParams<R>): number;
759
778
  /** Function to format a value into a human-readable string. */
760
779
  valueFormatter?(params: GridValueFormatterParams<R>): string;
761
780
  /** Custom component or element to render in the cell. */
@@ -1200,6 +1219,18 @@ export declare type GridSlotProps = NonNullable<DataGridProps['slotProps']>;
1200
1219
  /** The `slots` prop of `DataGrid`: components that replace built-in parts of the grid. */
1201
1220
  export declare type GridSlots = NonNullable<DataGridProps['slots']>;
1202
1221
 
1222
+ /**
1223
+ * Parameters passed to `GridColDef.sortComparator` for each side of a comparison. For a row-grouping
1224
+ * group row, `row` is the synthetic group row and `value` its grouping value.
1225
+ * @since v3.1
1226
+ */
1227
+ export declare interface GridSortCellParams<R extends GridValidRowModel = GridRowModel> {
1228
+ id: GridRowId;
1229
+ field: string;
1230
+ row: R;
1231
+ value: unknown;
1232
+ }
1233
+
1203
1234
  export declare type GridSortDirection = 'asc' | 'desc' | null;
1204
1235
 
1205
1236
  export declare interface GridSortingState {
@@ -1576,6 +1607,8 @@ export declare interface HeaderProps<R extends GridRowModel = GridRowModel> {
1576
1607
  sort: 'asc' | 'desc';
1577
1608
  }>;
1578
1609
  onColumnResize?: (field: string, newWidth: number) => void;
1610
+ /** Fits a column to its content (double-click or Enter on its resize handle). */
1611
+ onColumnAutosize?: (field: string) => void;
1579
1612
  columnWidths?: Record<string, number>;
1580
1613
  pinnedColumns?: GridColumnPinning;
1581
1614
  hasDetailPanel?: boolean;
@@ -1734,6 +1767,34 @@ export declare interface PdfExportOptions<R extends GridValidRowModel = GridRowM
1734
1767
  * Has no effect when the grid has no active `rowGroupingModel`, or when `selectedRows` is non-empty.
1735
1768
  */
1736
1769
  groupedRows?: GridGroupedExportRow[];
1770
+ /**
1771
+ * Called as the export advances: `prepare` (formatting rows; `total` = source rows or grouped
1772
+ * entries), `render` (drawing table rows; `total` = table body rows) and `save` (`0/1` before the
1773
+ * file is written, `1/1` after). `done` never decreases within a phase and ends at `total`.
1774
+ * @since v3.2
1775
+ */
1776
+ onProgress?: (progress: PdfExportProgress) => void;
1777
+ /**
1778
+ * Cancels the export. When aborted, the returned promise rejects with a `DOMException` named
1779
+ * `'AbortError'` and no file is saved. Checked between slices of work, so cancellation takes
1780
+ * effect within one slice; the final save step cannot be interrupted once started.
1781
+ * @since v3.2
1782
+ */
1783
+ signal?: AbortSignal;
1784
+ /**
1785
+ * Table-row count above which a development-mode warning recommends `exportToCsv` or
1786
+ * `exportToExcelAdvanced`. The export still runs (nothing is thrown). Pass `Infinity` to silence it.
1787
+ * Default: 20000
1788
+ * @since v3.2
1789
+ */
1790
+ maxRows?: number;
1791
+ }
1792
+
1793
+ /** Progress reported by `PdfExportOptions.onProgress`. @since v3.2 */
1794
+ export declare interface PdfExportProgress {
1795
+ phase: 'prepare' | 'render' | 'save';
1796
+ done: number;
1797
+ total: number;
1737
1798
  }
1738
1799
 
1739
1800
  declare interface PivotResult {