@opencorestack/opengridx 0.1.9 → 1.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +162 -19
  3. package/dist/index.d.ts +60 -41
  4. package/dist/opengridx.es.js +5045 -4549
  5. package/dist/opengridx.es.js.map +1 -1
  6. package/dist/opengridx.umd.js +11 -11
  7. package/dist/opengridx.umd.js.map +1 -1
  8. package/docs/API_REFERENCE.md +17 -7
  9. package/docs/README.md +14 -0
  10. package/docs/components/aggregation-footer.md +48 -0
  11. package/docs/components/datagrid.md +8 -3
  12. package/docs/components/empty-state.md +50 -0
  13. package/docs/components/error-overlay.md +40 -0
  14. package/docs/features/editing-reordering.md +11 -7
  15. package/docs/features/filtering.md +10 -8
  16. package/docs/features/selection.md +2 -1
  17. package/docs/features/sorting-pagination.md +3 -1
  18. package/docs/features/state-persistence.md +1 -2
  19. package/docs/roadmap.md +20 -1
  20. package/lib/components/Cell/Cell.tsx +9 -10
  21. package/lib/components/Cell/GridEditInputCell.tsx +4 -4
  22. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +3 -2
  23. package/lib/components/DataGrid/DataGrid.regression.test.tsx +132 -0
  24. package/lib/components/DataGrid/DataGrid.tsx +336 -1018
  25. package/lib/components/DataGrid/GridAggregationFooter.tsx +68 -0
  26. package/lib/components/DataGrid/GridEmptyState.tsx +16 -0
  27. package/lib/components/DataGrid/GridErrorOverlay.tsx +33 -0
  28. package/lib/components/DataGrid/GridListView.tsx +116 -0
  29. package/lib/components/DataGrid/GridPinnedRows.tsx +98 -0
  30. package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +124 -0
  31. package/lib/components/DataGrid/GridVirtualRows.tsx +202 -0
  32. package/lib/components/FilterPanel/FilterPanel.tsx +18 -10
  33. package/lib/components/Header/ColumnMenu.tsx +2 -2
  34. package/lib/components/Header/Header.tsx +4 -4
  35. package/lib/components/ListView/ListViewRow.tsx +2 -2
  36. package/lib/components/Row/Row.tsx +10 -10
  37. package/lib/components/SkeletonRow/SkeletonRow.tsx +9 -2
  38. package/lib/components/Toolbar/GridToolbar.tsx +6 -0
  39. package/lib/hooks/core/useDataGrid.regression.test.ts +66 -0
  40. package/lib/hooks/core/useDataGrid.ts +14 -34
  41. package/lib/hooks/core/useGridColumns.tsx +228 -0
  42. package/lib/hooks/core/useGridControlledState.ts +192 -0
  43. package/lib/hooks/core/useGridRowPipeline.ts +109 -0
  44. package/lib/hooks/core/useGridScrollSync.ts +52 -0
  45. package/lib/hooks/core/useGridStateSnapshot.ts +63 -0
  46. package/lib/hooks/core/useGridVirtualization.ts +186 -0
  47. package/lib/hooks/core/useGridVisibleRows.ts +66 -0
  48. package/lib/hooks/core/useLayout.ts +0 -6
  49. package/lib/hooks/features/useAggregation.ts +7 -7
  50. package/lib/hooks/features/useGridDataSource.ts +1 -1
  51. package/lib/hooks/features/useGridEditing.ts +31 -32
  52. package/lib/hooks/features/usePivot.test.ts +202 -0
  53. package/lib/hooks/features/usePivot.ts +0 -0
  54. package/lib/hooks/useColumnReorder.ts +1 -1
  55. package/lib/hooks/useRowGrouping.ts +14 -14
  56. package/lib/hooks/useTreeData.ts +1 -1
  57. package/lib/state/types.ts +1 -1
  58. package/lib/state/useGridStateStorage.ts +1 -1
  59. package/lib/types/index.ts +48 -32
  60. package/lib/utils/export/exportToExcelAdvanced.ts +14 -14
  61. package/lib/utils/export/index.ts +22 -17
  62. package/lib/utils/filtering/index.ts +20 -20
  63. package/lib/utils/sorting/index.ts +1 -1
  64. package/package.json +1 -1
@@ -50,7 +50,7 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
50
50
  return { treeNodes, rootIds, groupingRows };
51
51
  }
52
52
 
53
- const getGroupId = (field: string, value: any, parentId: GridRowId | null) => {
53
+ const getGroupId = (field: string, value: unknown, parentId: GridRowId | null) => {
54
54
  return `auto-group-${field}-${value}-${parentId || 'root'}`;
55
55
  };
56
56
 
@@ -75,7 +75,7 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
75
75
  }
76
76
 
77
77
  const field = rowGroupingModel[depth];
78
- const groups = new Map<any, R[]>();
78
+ const groups = new Map<string, R[]>();
79
79
 
80
80
  // Group current rows by value of the current field
81
81
  currentRows.forEach(row => {
@@ -99,18 +99,18 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
99
99
  groupIds.push(groupId);
100
100
 
101
101
  // Calculate Aggregations for this group
102
- const aggregatedValues: Record<string, any> = {};
102
+ const aggregatedValues: Record<string, unknown> = {};
103
103
  if (aggregationModel) {
104
104
  Object.entries(aggregationModel).forEach(([aggField, aggType]) => {
105
105
  const values = groupRowsList.map(r => r[aggField]);
106
106
  if (aggType === 'sum') {
107
- aggregatedValues[aggField] = values.reduce((a, b) => (Number(a) || 0) + (Number(b) || 0), 0);
107
+ aggregatedValues[aggField] = values.reduce((a: number, b) => a + (Number(b) || 0), 0);
108
108
  } else if (aggType === 'min') {
109
109
  aggregatedValues[aggField] = Math.min(...values.map(v => Number(v) || 0));
110
110
  } else if (aggType === 'max') {
111
111
  aggregatedValues[aggField] = Math.max(...values.map(v => Number(v) || 0));
112
112
  } else if (aggType === 'avg') {
113
- const sum = values.reduce((a, b) => (Number(a) || 0) + (Number(b) || 0), 0);
113
+ const sum = values.reduce((a: number, b) => a + (Number(b) || 0), 0);
114
114
  aggregatedValues[aggField] = values.length ? sum / values.length : 0;
115
115
  } else if (aggType === 'count') {
116
116
  aggregatedValues[aggField] = values.length;
@@ -118,11 +118,11 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
118
118
  });
119
119
  }
120
120
 
121
- const groupRow: any = {
122
- [field]: rawValue,
123
- ...aggregatedValues,
124
- id: groupId
125
- };
121
+ const groupRow = {
122
+ [field]: rawValue,
123
+ ...aggregatedValues,
124
+ id: groupId
125
+ } as unknown as R;
126
126
 
127
127
  groupingRows.set(groupId, groupRow);
128
128
 
@@ -183,7 +183,7 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
183
183
  setExpandedGroupIds(new Set());
184
184
  }
185
185
 
186
- }, [rowGroupingModel, defaultGroupingExpansionDepth]);
186
+ }, [rowGroupingModel, defaultGroupingExpansionDepth, treeNodes]);
187
187
 
188
188
  const toggleExpansion = useCallback((id: GridRowId) => {
189
189
  setExpandedGroupIds(prev => {
@@ -243,8 +243,8 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
243
243
  if (!rowA || !rowB) return 0;
244
244
 
245
245
  for (const sortItem of sortModel) {
246
- const valA = (rowA as any)[sortItem.field];
247
- const valB = (rowB as any)[sortItem.field];
246
+ const valA = rowA[sortItem.field];
247
+ const valB = rowB[sortItem.field];
248
248
  const compareResult = compareValues(valA, valB, sortItem.sort);
249
249
  if (compareResult !== 0) return compareResult;
250
250
  }
@@ -287,7 +287,7 @@ export function useRowGrouping<R extends GridRowModel>(params: UseRowGroupingPar
287
287
 
288
288
  return result;
289
289
 
290
- }, [rows, getRowId, treeNodes, rootIds, groupingRows, filterModel, sortModel, expandedGroupIds]);
290
+ }, [rows, getRowId, treeNodes, rootIds, groupingRows, filterModel, sortModel, expandedGroupIds, rowGroupingModel]);
291
291
 
292
292
  const getNode = useCallback((id: GridRowId) => treeNodes.get(id), [treeNodes]);
293
293
 
@@ -277,7 +277,7 @@ export function useTreeData<R extends GridRowModel>(props: UseTreeDataProps<R>)
277
277
  ...row,
278
278
  _treeDepth: node.depth,
279
279
  _isExpanded: expandedGroupIds.has(id),
280
- _hasChildren: (node.children && node.children.length > 0) || (node.serverChildrenCount && node.serverChildrenCount > 0),
280
+ _hasChildren: Boolean((node.children && node.children.length > 0) || (node.serverChildrenCount && node.serverChildrenCount > 0)),
281
281
  _descendantCount: node.children ? node.children.length : 0
282
282
  };
283
283
  result.push(enhancedRow);
@@ -22,7 +22,7 @@ export interface GridPaginationState {
22
22
 
23
23
  export interface GridDataSourceState {
24
24
  loading: boolean;
25
- error?: any;
25
+ error?: unknown;
26
26
  }
27
27
 
28
28
  export interface GridColumnsState {
@@ -70,7 +70,7 @@ export function useGridStateStorage(
70
70
  if (!storage) return undefined;
71
71
  return readFromStorage(key, storage);
72
72
 
73
- }, [key]);
73
+ }, [key, storage]);
74
74
 
75
75
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
76
76
  const latestStateRef = useRef<GridState | null>(null);
@@ -7,8 +7,24 @@ export type GridRowId = string | number;
7
7
  export interface GridRowModel {
8
8
  /** Uniquely identifies the row. */
9
9
  id: GridRowId;
10
+ /** Internal: row has child nodes (tree data / row grouping). */
11
+ _hasChildren?: boolean;
12
+ /** Internal: row is a skeleton placeholder during infinite-scroll loading. */
13
+ _isSkeleton?: boolean;
14
+ /** Internal: depth in the tree or grouping hierarchy. */
15
+ _treeDepth?: number;
16
+ /** Internal: whether the group/tree node is currently expanded. */
17
+ _isExpanded?: boolean;
18
+ /** Internal: field used for grouping at this level. */
19
+ _groupingField?: string;
20
+ /** Internal: grouping field value at this level. */
21
+ _groupingValue?: unknown;
22
+ /** Internal: total descendant count for tree/grouping nodes. */
23
+ _descendantCount?: number;
24
+ /** Internal: server-reported child count for lazy-loaded tree nodes. */
25
+ serverChildrenCount?: number;
10
26
  /** Any other dynamic row properties. */
11
- [key: string]: any;
27
+ [key: string]: unknown;
12
28
  }
13
29
 
14
30
  export type GridAlignment = 'left' | 'center' | 'right';
@@ -27,10 +43,10 @@ export interface GridTreeNode {
27
43
  /** The field this node is grouping by. */
28
44
  groupingField?: string;
29
45
  /** The actual value being grouped. */
30
- groupingValue?: any;
46
+ groupingValue?: unknown;
31
47
 
32
48
  /** Computed aggregation results for this group. */
33
- aggregatedValues?: Record<string, any>;
49
+ aggregatedValues?: Record<string, unknown>;
34
50
  /** Position of the aggregation row relative to the group. */
35
51
  aggregationPosition?: 'inline' | 'footer' | null;
36
52
  /** Current expansion state. */
@@ -91,13 +107,15 @@ export interface GridColDef<R extends GridRowModel = GridRowModel> {
91
107
  hideable?: boolean;
92
108
  /** If false, the column cannot be pinned. */
93
109
  pinnable?: boolean;
110
+ /** Internal: marks this column as a virtual spacer used for horizontal virtualization. */
111
+ isSpacer?: boolean;
94
112
  /** Type used to determine default operators and formatting logic. */
95
113
  type?: 'string' | 'number' | 'date' | 'boolean' | 'singleSelect' | 'image';
96
114
  /** Options used for 'singleSelect' type. */
97
- valueOptions?: Array<string | number | { value: any; label: string }>;
115
+ valueOptions?: Array<string | number | { value: unknown; label: string }>;
98
116
 
99
117
  /** Function to compute a cell value from raw row data. */
100
- valueGetter?: (params: GridValueGetterParams<R>) => any;
118
+ valueGetter?: (params: GridValueGetterParams<R>) => unknown;
101
119
  /** Function to format a value into a human-readable string. */
102
120
  valueFormatter?: (params: GridValueFormatterParams<R>) => string;
103
121
  /** Custom component or element to render in the cell. */
@@ -186,13 +204,13 @@ export interface GridValueGetterParams<R extends GridRowModel = GridRowModel> {
186
204
  /** The field name. */
187
205
  field: string;
188
206
  /** The raw value from the row object. */
189
- value: any;
207
+ value: unknown;
190
208
  }
191
209
 
192
210
  /** Parameters passed to the `valueFormatter` function. */
193
211
  export interface GridValueFormatterParams<R extends GridRowModel = GridRowModel> {
194
212
  /** The raw value to format. */
195
- value: any;
213
+ value: unknown;
196
214
  /** The row object. */
197
215
  row: R;
198
216
  /** The field name. */
@@ -202,7 +220,7 @@ export interface GridValueFormatterParams<R extends GridRowModel = GridRowModel>
202
220
  /** Parameters passed to the `renderCell` function. */
203
221
  export interface GridRenderCellParams<R extends GridRowModel = GridRowModel> {
204
222
  /** The current cell value. */
205
- value: any;
223
+ value: unknown;
206
224
  /** The row object. */
207
225
  row: R;
208
226
  /** The field name and unique ID. */
@@ -256,7 +274,7 @@ export interface GridFilterItem {
256
274
  /** The comparison operator. */
257
275
  operator: GridFilterOperator;
258
276
  /** The value to compare against. */
259
- value?: any;
277
+ value?: unknown;
260
278
  }
261
279
 
262
280
  /** Describes a group of filters combined with a logical operator. */
@@ -325,7 +343,7 @@ export interface GridGetRowsParams {
325
343
  export interface GridGetRowsResponse<R extends GridRowModel = GridRowModel> {
326
344
  rows: R[];
327
345
  rowCount?: number;
328
- aggregationResults?: Record<string, any>;
346
+ aggregationResults?: Record<string, unknown>;
329
347
  }
330
348
 
331
349
  /**
@@ -341,7 +359,7 @@ export interface GridDataSource<R extends GridRowModel = GridRowModel> {
341
359
  /**
342
360
  * Optional: Fetches aggregation results for the entire dataset.
343
361
  */
344
- getAggregations?: (params: Omit<GridGetRowsParams, 'startRow' | 'endRow'>) => Promise<Record<string, any>>;
362
+ getAggregations?: (params: Omit<GridGetRowsParams, 'startRow' | 'endRow'>) => Promise<Record<string, unknown>>;
345
363
  }
346
364
 
347
365
  export interface GridPaginationModel {
@@ -363,19 +381,17 @@ export interface GridPinnedRows<R extends GridRowModel = GridRowModel> {
363
381
 
364
382
  export interface GridVirtualizationState {
365
383
  renderContext: GridRenderContext;
366
- scrollTop: number;
367
- scrollLeft: number;
368
384
  }
369
385
 
370
386
  export type GridRowGroupingModel = string[];
371
387
 
372
- export type GridAggregationFunction = (values: any[]) => any;
388
+ export type GridAggregationFunction = (values: unknown[]) => unknown;
373
389
 
374
390
  export interface GridAggregationModel {
375
- [field: string]: string;
391
+ [field: string]: string;
376
392
  }
377
393
 
378
- export type GridAggregationResult = Record<string, any>;
394
+ export type GridAggregationResult = Record<string, unknown>;
379
395
 
380
396
  export type GridAggregationPosition = 'footer' | 'inline' | 'both';
381
397
 
@@ -400,7 +416,7 @@ export interface GridRenderContext {
400
416
  lastColumnIndex: number;
401
417
  }
402
418
 
403
- export interface GridState {
419
+ export interface GridInternalState {
404
420
  rows: {
405
421
  idRowsLookup: Map<GridRowId, GridRowModel>;
406
422
  allRows: GridRowId[];
@@ -437,7 +453,7 @@ export interface GridState {
437
453
  };
438
454
  dataSource: {
439
455
  loading: boolean;
440
- error: any;
456
+ error: unknown;
441
457
  };
442
458
  }
443
459
 
@@ -603,7 +619,7 @@ export interface DataGridProps<R extends GridRowModel = GridRowModel> {
603
619
  /** Callback to process an updated row after inline editing. Supports promises and validation. */
604
620
  processRowUpdate?: (newRow: R, oldRow: R) => R | Promise<R>;
605
621
  /** Callback fired if `processRowUpdate` throws or rejects. */
606
- onProcessRowUpdateError?: (error: any) => void;
622
+ onProcessRowUpdateError?: (error: unknown) => void;
607
623
 
608
624
  /** Interface for connecting the grid to an external (server-side) data source. */
609
625
  dataSource?: GridDataSource<R>;
@@ -616,23 +632,23 @@ export interface DataGridProps<R extends GridRowModel = GridRowModel> {
616
632
  /** Custom components to replace internal grid parts. */
617
633
  slots?: {
618
634
  /** Component rendered as the grid toolbar. */
619
- toolbar?: React.ComponentType<any>;
635
+ toolbar?: React.ComponentType<Record<string, unknown>>;
620
636
  /** Component rendered as the pagination control. */
621
- pagination?: React.ComponentType<any>;
637
+ pagination?: React.ComponentType<Record<string, unknown>>;
622
638
  /** Component rendered when the grid is empty. */
623
- noRowsOverlay?: React.ComponentType<any>;
639
+ noRowsOverlay?: React.ComponentType<Record<string, unknown>>;
624
640
  /** Component rendered during loading states. */
625
- loadingOverlay?: React.ComponentType<any>;
641
+ loadingOverlay?: React.ComponentType<Record<string, unknown>>;
626
642
  /** Component rendered at the very bottom of the grid. */
627
- footer?: React.ComponentType<any>;
643
+ footer?: React.ComponentType<Record<string, unknown>>;
628
644
  };
629
645
  /** Properties passed directly to custom slots. */
630
646
  slotProps?: {
631
- toolbar?: any;
632
- pagination?: any;
633
- noRowsOverlay?: any;
634
- loadingOverlay?: any;
635
- footer?: any;
647
+ toolbar?: Record<string, unknown>;
648
+ pagination?: Record<string, unknown>;
649
+ noRowsOverlay?: Record<string, unknown>;
650
+ loadingOverlay?: Record<string, unknown>;
651
+ footer?: Record<string, unknown>;
636
652
  };
637
653
 
638
654
  /** When true, renders the grid as a single-column list of cards. Perfect for mobile/responsive views. */
@@ -647,7 +663,7 @@ export interface DataGridProps<R extends GridRowModel = GridRowModel> {
647
663
  columnGroupingModel?: GridColumnGroupingModel;
648
664
  }
649
665
 
650
- export interface GridEditCellProps<V = any> {
666
+ export interface GridEditCellProps<V = unknown> {
651
667
  id: GridRowId;
652
668
  field: string;
653
669
  value?: V;
@@ -669,7 +685,7 @@ export interface GridRowParams<R extends GridRowModel = GridRowModel> {
669
685
  export interface GridCellParams<R extends GridRowModel = GridRowModel> {
670
686
  row: R;
671
687
  field: string;
672
- value: any;
688
+ value: unknown;
673
689
  colDef: GridColDef<R>;
674
690
  rowIndex: number;
675
691
  colIndex: number;
@@ -707,7 +723,7 @@ export interface GridApi {
707
723
  /** Returns all rows currently visible after filtering and sorting. */
708
724
  getVisibleRows: () => GridRowModel[];
709
725
  /** Returns the current aggregation results. */
710
- getAggregationResult: () => Record<string, any> | null;
726
+ getAggregationResult: () => Record<string, unknown> | null;
711
727
  /** Returns the active aggregation configuration. */
712
728
  getAggregationModel: () => GridAggregationModel | null;
713
729
 
@@ -63,7 +63,7 @@ export interface ExcelAdvancedExportOptions {
63
63
  /** Body font size (default: 10) */
64
64
  bodyFontSize?: number;
65
65
  /** Current aggregation result */
66
- aggregationResult?: Record<string, any> | null;
66
+ aggregationResult?: Record<string, unknown> | null;
67
67
  /** Current aggregation model */
68
68
  aggregationModel?: GridAggregationModel | null;
69
69
  /** Currently selected row IDs */
@@ -72,7 +72,7 @@ export interface ExcelAdvancedExportOptions {
72
72
 
73
73
  // ─── Cell type inference ──────────────────────────────────────────────────────
74
74
 
75
- function inferCellType(colDef: GridColDef<any>, value: any): 'number' | 'boolean' | 'date' | 'string' {
75
+ function inferCellType(colDef: GridColDef<GridRowModel>, value: unknown): 'number' | 'boolean' | 'date' | 'string' {
76
76
  if (colDef.type === 'number') return 'number';
77
77
  if (colDef.type === 'boolean') return 'boolean';
78
78
  if (colDef.type === 'date') return 'date';
@@ -84,7 +84,7 @@ function inferCellType(colDef: GridColDef<any>, value: any): 'number' | 'boolean
84
84
 
85
85
  // ─── Default numFmt per column type ──────────────────────────────────────────
86
86
 
87
- function defaultNumFmt(colDef: GridColDef<any>): string | undefined {
87
+ function defaultNumFmt(colDef: GridColDef<GridRowModel>): string | undefined {
88
88
  if (colDef.type === 'number') return '#,##0.##';
89
89
  if (colDef.type === 'date') return 'yyyy-mm-dd';
90
90
  return undefined;
@@ -92,7 +92,7 @@ function defaultNumFmt(colDef: GridColDef<any>): string | undefined {
92
92
 
93
93
  // ─── Column display width (chars) ────────────────────────────────────────────
94
94
 
95
- function colWidth(colDef: GridColDef<any>, override?: number): number {
95
+ function colWidth(colDef: GridColDef<GridRowModel>, override?: number): number {
96
96
  if (override != null) return override;
97
97
  const px = (colDef.width ?? 120) as number;
98
98
  return Math.min(60, Math.max(8, (px - 5) / 7));
@@ -195,18 +195,18 @@ export async function exportToExcelAdvanced<R extends GridRowModel>(
195
195
  workbook.creator = 'OpenGridX';
196
196
  workbook.created = new Date();
197
197
 
198
- // Filter system columns — cast to GridColDef<any> to avoid generic covariance issues
199
- const exportColumns: GridColDef<any>[] = (columns as GridColDef<any>[]).filter(col =>
198
+ // Filter system columns
199
+ const exportColumns: GridColDef<GridRowModel>[] = (columns as unknown as GridColDef<GridRowModel>[]).filter(col =>
200
200
  col.exportable !== false &&
201
201
  col.field !== '__check__' &&
202
202
  col.field !== '__actions__' &&
203
- !(col as any).isSpacer
203
+ !col.isSpacer
204
204
  );
205
205
 
206
- const allRows: any[] = rows as any[];
207
- const sRows: any[] = (selectedRows && selectedRows.length > 0
206
+ const allRows: GridRowModel[] = rows as GridRowModel[];
207
+ const sRows: GridRowModel[] = (selectedRows && selectedRows.length > 0
208
208
  ? rows.filter(r => selectedRows.includes(r.id))
209
- : rows) as any[];
209
+ : rows) as GridRowModel[];
210
210
 
211
211
  // Normalise sheet definitions
212
212
  const resolvedSheets: (ExcelSheetDefinition | { type: 'summary'; name?: string })[] =
@@ -279,7 +279,7 @@ export async function exportToExcelAdvanced<R extends GridRowModel>(
279
279
  const seen = new Set<string>();
280
280
  rowsToExport.forEach(row => {
281
281
  imageColumns.forEach(col => {
282
- const val = (row as any)[col.field];
282
+ const val = row[col.field];
283
283
  if (typeof val === 'string' && val && !imageCache.has(val) && !seen.has(val)) {
284
284
  urlsNeeded.push(val);
285
285
  seen.add(val);
@@ -348,7 +348,7 @@ export async function exportToExcelAdvanced<R extends GridRowModel>(
348
348
  // Image columns: write empty string; image placed below
349
349
  if (columnStyles[col.field]?.embedImage) return '';
350
350
 
351
- let value: any = (row as any)[col.field];
351
+ let value: unknown = row[col.field];
352
352
  if (col.valueGetter) {
353
353
  value = col.valueGetter({ row, field: col.field, value });
354
354
  }
@@ -399,7 +399,7 @@ export async function exportToExcelAdvanced<R extends GridRowModel>(
399
399
 
400
400
  imageColumns.forEach(col => {
401
401
  const colIdx = exportColumns.indexOf(col);
402
- const url = (row as any)[col.field];
402
+ const url = row[col.field];
403
403
  const imgId = typeof url === 'string' ? imageCache.get(url) : undefined;
404
404
 
405
405
  if (imgId === undefined) {
@@ -433,7 +433,7 @@ export async function exportToExcelAdvanced<R extends GridRowModel>(
433
433
  },
434
434
  ext: { width: imgW, height: imgH },
435
435
  editAs: 'oneCell',
436
- } as any);
436
+ } as unknown as import('exceljs').ImageRange);
437
437
  });
438
438
  } else {
439
439
  dataRow.height = 16;
@@ -7,7 +7,7 @@ export interface CsvExportOptions {
7
7
  includeHeaders?: boolean;
8
8
  delimiter?: string;
9
9
  selectedRows?: (string | number)[];
10
- aggregationResult?: Record<string, any> | null;
10
+ aggregationResult?: Record<string, unknown> | null;
11
11
  aggregationModel?: GridAggregationModel | null;
12
12
  }
13
13
 
@@ -48,7 +48,7 @@ export function exportToCsv<R extends GridRowModel>(
48
48
 
49
49
  rowsToExport.forEach(row => {
50
50
  const values = exportColumns.map(col => {
51
- let value: any = row[col.field as keyof R];
51
+ let value: unknown = (row as GridRowModel)[col.field];
52
52
 
53
53
  if (col.valueGetter) {
54
54
  value = col.valueGetter({ row, field: col.field, value });
@@ -109,7 +109,7 @@ export interface ExcelExportOptions {
109
109
  sheetName?: string;
110
110
  includeHeaders?: boolean;
111
111
  selectedRows?: (string | number)[];
112
- aggregationResult?: Record<string, any> | null;
112
+ aggregationResult?: Record<string, unknown> | null;
113
113
  aggregationModel?: GridAggregationModel | null;
114
114
  }
115
115
 
@@ -159,7 +159,7 @@ export function exportToExcel<R extends GridRowModel>(
159
159
  rowsToExport.forEach(row => {
160
160
  html += '<tr>';
161
161
  exportColumns.forEach(col => {
162
- let value: any = row[col.field as keyof R];
162
+ let value: unknown = (row as GridRowModel)[col.field];
163
163
 
164
164
  if (col.valueGetter) {
165
165
  value = col.valueGetter({ row, field: col.field, value });
@@ -227,7 +227,7 @@ export interface JsonExportOptions {
227
227
  fileName?: string;
228
228
  pretty?: boolean;
229
229
  selectedRows?: (string | number)[];
230
- aggregationResult?: Record<string, any> | null;
230
+ aggregationResult?: Record<string, unknown> | null;
231
231
  aggregationModel?: GridAggregationModel | null;
232
232
  }
233
233
 
@@ -264,9 +264,9 @@ export function exportToJson<R extends GridRowModel>(
264
264
 
265
265
  // Build JSON data
266
266
  const data = rowsToExport.map(row => {
267
- const obj: any = {};
267
+ const obj: Record<string, unknown> = {};
268
268
  exportColumns.forEach(col => {
269
- let value: any = row[col.field as keyof R];
269
+ let value: unknown = (row as GridRowModel)[col.field];
270
270
 
271
271
  // Use valueGetter if available
272
272
  if (col.valueGetter) {
@@ -278,23 +278,27 @@ export function exportToJson<R extends GridRowModel>(
278
278
  return obj;
279
279
  });
280
280
 
281
- let outData: any = data;
281
+ type ExportJsonPayload =
282
+ | Record<string, unknown>[]
283
+ | { data: Record<string, unknown>[]; aggregation: { labels: Record<string, unknown>; values: Record<string, unknown> } };
284
+
285
+ let outData: ExportJsonPayload = data;
282
286
 
283
287
  if (options.aggregationResult) {
284
288
  const aggResult = options.aggregationResult;
285
289
  const aggModel = options.aggregationModel || {};
286
-
287
- const summaryLabelObj: any = {};
290
+
291
+ const summaryLabelObj: Record<string, unknown> = {};
288
292
  exportColumns.forEach((col) => {
289
293
  if (aggModel[col.field]) {
290
294
  summaryLabelObj[col.field] = aggModel[col.field].toUpperCase();
291
295
  }
292
296
  });
293
297
 
294
- const summaryDataObj: any = {};
298
+ const summaryDataObj: Record<string, unknown> = {};
295
299
  exportColumns.forEach((col) => {
296
300
  if (aggResult[col.field] !== undefined && aggResult[col.field] !== null) {
297
- let aggVal = aggResult[col.field];
301
+ let aggVal: unknown = aggResult[col.field];
298
302
  if (col.valueFormatter) {
299
303
  aggVal = col.valueFormatter({ value: aggVal, row: {} as R, field: col.field });
300
304
  } else if (aggModel[col.field]) {
@@ -326,7 +330,7 @@ export function exportToJson<R extends GridRowModel>(
326
330
  export interface PrintOptions {
327
331
  title?: string;
328
332
  selectedRows?: (string | number)[];
329
- aggregationResult?: Record<string, any> | null;
333
+ aggregationResult?: Record<string, unknown> | null;
330
334
  aggregationModel?: GridAggregationModel | null;
331
335
  }
332
336
 
@@ -376,7 +380,7 @@ export async function printGrid<R extends GridRowModel>(
376
380
  try {
377
381
  let title = 'Print';
378
382
  let selectedRows: (string | number)[] | undefined;
379
- let aggregationResult: Record<string, any> | null = null;
383
+ let aggregationResult: Record<string, unknown> | null = null;
380
384
  let aggregationModel: GridAggregationModel | null = null;
381
385
 
382
386
  if (typeof titleOrOptions === 'string') {
@@ -447,7 +451,7 @@ export async function printGrid<R extends GridRowModel>(
447
451
  rowsToExport.forEach(row => {
448
452
  html += '<tr>';
449
453
  exportColumns.forEach(col => {
450
- let value: any = row[col.field as keyof R];
454
+ let value: unknown = (row as GridRowModel)[col.field];
451
455
 
452
456
  if (col.valueGetter) {
453
457
  value = col.valueGetter({ row, field: col.field, value });
@@ -529,10 +533,11 @@ export async function printGrid<R extends GridRowModel>(
529
533
  }
530
534
  }, 500);
531
535
 
532
- } catch (e: any) {
536
+ } catch (e) {
533
537
  console.error('Print generation failed:', e);
534
538
  if (printWindow && !printWindow.closed) {
535
- printWindow.document.body.innerHTML = `<div style="color: red; padding: 20px;"><h3>Error Generating Print Preview</h3><p>${e.message}</p></div>`;
539
+ const message = e instanceof Error ? e.message : String(e);
540
+ printWindow.document.body.innerHTML = `<div style="color: red; padding: 20px;"><h3>Error Generating Print Preview</h3><p>${message}</p></div>`;
536
541
  }
537
542
  }
538
543
  }