@opencorestack/opengridx 0.1.9 → 1.0.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/index.d.ts +60 -41
  3. package/dist/opengridx.es.js +5045 -4549
  4. package/dist/opengridx.es.js.map +1 -1
  5. package/dist/opengridx.umd.js +11 -11
  6. package/dist/opengridx.umd.js.map +1 -1
  7. package/docs/README.md +14 -0
  8. package/docs/components/aggregation-footer.md +48 -0
  9. package/docs/components/datagrid.md +3 -0
  10. package/docs/components/empty-state.md +50 -0
  11. package/docs/components/error-overlay.md +40 -0
  12. package/docs/roadmap.md +20 -1
  13. package/lib/components/Cell/Cell.tsx +9 -10
  14. package/lib/components/Cell/GridEditInputCell.tsx +4 -4
  15. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +3 -2
  16. package/lib/components/DataGrid/DataGrid.regression.test.tsx +132 -0
  17. package/lib/components/DataGrid/DataGrid.tsx +336 -1018
  18. package/lib/components/DataGrid/GridAggregationFooter.tsx +68 -0
  19. package/lib/components/DataGrid/GridEmptyState.tsx +16 -0
  20. package/lib/components/DataGrid/GridErrorOverlay.tsx +33 -0
  21. package/lib/components/DataGrid/GridListView.tsx +116 -0
  22. package/lib/components/DataGrid/GridPinnedRows.tsx +98 -0
  23. package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +124 -0
  24. package/lib/components/DataGrid/GridVirtualRows.tsx +202 -0
  25. package/lib/components/FilterPanel/FilterPanel.tsx +18 -10
  26. package/lib/components/Header/ColumnMenu.tsx +2 -2
  27. package/lib/components/Header/Header.tsx +4 -4
  28. package/lib/components/ListView/ListViewRow.tsx +2 -2
  29. package/lib/components/Row/Row.tsx +10 -10
  30. package/lib/components/SkeletonRow/SkeletonRow.tsx +9 -2
  31. package/lib/components/Toolbar/GridToolbar.tsx +6 -0
  32. package/lib/hooks/core/useDataGrid.regression.test.ts +66 -0
  33. package/lib/hooks/core/useDataGrid.ts +14 -34
  34. package/lib/hooks/core/useGridColumns.tsx +228 -0
  35. package/lib/hooks/core/useGridControlledState.ts +192 -0
  36. package/lib/hooks/core/useGridRowPipeline.ts +109 -0
  37. package/lib/hooks/core/useGridScrollSync.ts +52 -0
  38. package/lib/hooks/core/useGridStateSnapshot.ts +63 -0
  39. package/lib/hooks/core/useGridVirtualization.ts +186 -0
  40. package/lib/hooks/core/useGridVisibleRows.ts +66 -0
  41. package/lib/hooks/core/useLayout.ts +0 -6
  42. package/lib/hooks/features/useAggregation.ts +7 -7
  43. package/lib/hooks/features/useGridDataSource.ts +1 -1
  44. package/lib/hooks/features/useGridEditing.ts +31 -32
  45. package/lib/hooks/features/usePivot.test.ts +202 -0
  46. package/lib/hooks/features/usePivot.ts +0 -0
  47. package/lib/hooks/useColumnReorder.ts +1 -1
  48. package/lib/hooks/useRowGrouping.ts +14 -14
  49. package/lib/hooks/useTreeData.ts +1 -1
  50. package/lib/state/types.ts +1 -1
  51. package/lib/state/useGridStateStorage.ts +1 -1
  52. package/lib/types/index.ts +48 -32
  53. package/lib/utils/export/exportToExcelAdvanced.ts +14 -14
  54. package/lib/utils/export/index.ts +22 -17
  55. package/lib/utils/filtering/index.ts +20 -20
  56. package/lib/utils/sorting/index.ts +1 -1
  57. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
2
  import type {
3
3
  GridFilterModel,
4
4
  GridFilterItem,
@@ -30,34 +30,42 @@ const FilterRow: React.FC<{
30
30
  const currentOperator = item?.operator ?? operators[0];
31
31
 
32
32
  // Local input state to prevent full filter-panel re-render on every keystroke
33
- const [localValue, setLocalValue] = useState(item?.value ?? '');
33
+ const [localValue, setLocalValue] = useState<string>(item?.value != null ? String(item.value) : '');
34
34
  const onChangeRef = useRef(onChange);
35
- onChangeRef.current = onChange;
35
+ const itemRef = useRef(item);
36
+ const colFieldRef = useRef(col.field);
37
+ const operatorRef = useRef(currentOperator);
38
+ useLayoutEffect(() => {
39
+ onChangeRef.current = onChange;
40
+ itemRef.current = item;
41
+ colFieldRef.current = col.field;
42
+ operatorRef.current = currentOperator;
43
+ });
36
44
 
37
45
  // Sync when the external item changes (e.g. operator change, clear)
38
46
  const prevItemValue = useRef(item?.value);
39
47
  useEffect(() => {
40
48
  if (item?.value !== prevItemValue.current) {
41
49
  prevItemValue.current = item?.value;
42
- setLocalValue(item?.value ?? '');
50
+ setLocalValue(item?.value != null ? String(item.value) : '');
43
51
  }
44
52
  }, [item?.value]);
45
53
 
46
54
  // Debounce propagating the value upward (300ms)
47
55
  useEffect(() => {
48
56
  const handler = setTimeout(() => {
49
- const currentValue = item?.value ?? '';
57
+ const currentItem = itemRef.current;
58
+ const currentValue = currentItem?.value ?? '';
50
59
  if (localValue !== currentValue) {
51
60
  onChangeRef.current({
52
- id: item?.id ?? `${col.field}-${Date.now()}`,
53
- field: col.field,
54
- operator: currentOperator as GridFilterOperator,
61
+ id: currentItem?.id ?? `${colFieldRef.current}-${Date.now()}`,
62
+ field: colFieldRef.current,
63
+ operator: operatorRef.current as GridFilterOperator,
55
64
  value: localValue,
56
65
  });
57
66
  }
58
67
  }, 300);
59
68
  return () => clearTimeout(handler);
60
- // eslint-disable-next-line react-hooks/exhaustive-deps
61
69
  }, [localValue]);
62
70
 
63
71
  const handleOperatorChange = (op: string) => {
@@ -158,7 +166,7 @@ const FilterRow: React.FC<{
158
166
  // ── Root panel ────────────────────────────────────────────────────────────────
159
167
 
160
168
  export const FilterPanel: React.FC<FilterPanelProps> = ({ filterModel, columns, onFilterModelChange }) => {
161
- const items: GridFilterItem[] = (filterModel.items ?? []) as GridFilterItem[];
169
+ const items = useMemo<GridFilterItem[]>(() => (filterModel.items ?? []) as GridFilterItem[], [filterModel.items]);
162
170
  const logicOperator = filterModel.logicOperator ?? 'and';
163
171
 
164
172
  const handleItemChange = useCallback((field: string, newItem: GridFilterItem | null) => {
@@ -1,10 +1,10 @@
1
1
  import React, { useRef, useEffect, useState } from 'react';
2
2
  import ReactDOM from 'react-dom';
3
- import type { GridColDef, GridSortDirection, GridColumnPinning } from '../../types';
3
+ import type { GridColDef, GridRowModel, GridSortDirection, GridColumnPinning } from '../../types';
4
4
 
5
5
 
6
6
  interface ColumnMenuProps {
7
- colDef: GridColDef<any>;
7
+ colDef: GridColDef<GridRowModel>;
8
8
  sortModel?: Array<{ field: string; sort: 'asc' | 'desc' }>;
9
9
  onSort?: (field: string, direction: GridSortDirection) => void;
10
10
  onHide?: (field: string) => void;
@@ -236,7 +236,7 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
236
236
  // All non-spacer fields in order (for group-span math) with their effective physical width
237
237
  const allCols = allColumns ?? columns;
238
238
  const allLeafFields = allCols
239
- .filter(c => !(c as any).isSpacer)
239
+ .filter(c => !c.isSpacer)
240
240
  .map(c => ({
241
241
  field: c.field,
242
242
  width: columnWidths[c.field] ?? c.width ?? 100
@@ -354,7 +354,7 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
354
354
  )}
355
355
 
356
356
  {columns.map((colDef, index) => {
357
- if ((colDef as any).isSpacer) {
357
+ if (colDef.isSpacer) {
358
358
  return (
359
359
  <div
360
360
  key={colDef.field}
@@ -409,7 +409,7 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
409
409
  }
410
410
 
411
411
  const headerContent = colDef.renderHeader
412
- ? colDef.renderHeader({ field: colDef.field, colDef: colDef as any, colIndex: index })
412
+ ? colDef.renderHeader({ field: colDef.field, colDef: colDef as unknown as GridColDef, colIndex: index })
413
413
  : colDef.headerName || colDef.field;
414
414
 
415
415
  const handleHeaderClick = (e: React.MouseEvent) => {
@@ -499,7 +499,7 @@ export function Header<R extends GridRowModel = GridRowModel>(props: HeaderProps
499
499
 
500
500
  {menuOpenParams && (
501
501
  <ColumnMenu
502
- colDef={menuOpenParams.colDef}
502
+ colDef={menuOpenParams.colDef as unknown as GridColDef<GridRowModel>}
503
503
  sortModel={sortModel}
504
504
  onSort={onSort}
505
505
  onHide={onHideColumn}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { GridRowModel, GridRowId, GridListViewColDef, GridRenderCellParams } from '../../types';
2
+ import type { GridColDef, GridRowModel, GridRowId, GridListViewColDef, GridRenderCellParams } from '../../types';
3
3
 
4
4
  export interface ListViewRowProps<R extends GridRowModel = GridRowModel> {
5
5
  row: R;
@@ -26,7 +26,7 @@ export function ListViewRow<R extends GridRowModel = GridRowModel>({
26
26
  row,
27
27
  value: undefined,
28
28
  field: listViewColumn.field,
29
- colDef: { field: listViewColumn.field } as any,
29
+ colDef: { field: listViewColumn.field } as unknown as GridColDef<R>,
30
30
  rowIndex,
31
31
  colIndex: 0,
32
32
  };
@@ -40,10 +40,10 @@ export interface RowProps<R extends GridRowModel = GridRowModel> {
40
40
  isDragging?: boolean;
41
41
  isDragOver?: boolean;
42
42
 
43
- editingCell?: { id: GridRowId; field: string; value: any; } | null;
44
- onEditStart?: (params: { id: GridRowId, field: string, value: any }) => void;
43
+ editingCell?: { id: GridRowId; field: string; value: unknown; } | null;
44
+ onEditStart?: (params: { id: GridRowId, field: string, value: unknown }) => void;
45
45
  onEditStop?: (params?: { cancel?: boolean }) => void;
46
- onEditCellValueChange?: (params: { id: GridRowId, field: string, value: any }) => void;
46
+ onEditCellValueChange?: (params: { id: GridRowId, field: string, value: unknown }) => void;
47
47
 
48
48
  focusedCellField?: string | null;
49
49
  isFocusVisible?: boolean;
@@ -120,15 +120,15 @@ export function Row<R extends GridRowModel = GridRowModel>(props: RowProps<R>) {
120
120
  );
121
121
  }, [columns, columnWidths, pinnedColumns, checkboxSelection, pinCheckboxColumn, hasDetailPanel, pinExpandColumn, rowReordering]);
122
122
 
123
- const isGroupRow = (row as any)._hasChildren === true;
123
+ const isGroupRow = row._hasChildren === true;
124
124
 
125
- const handleCellEditStart = React.useCallback((field: string, value: any) => {
125
+ const handleCellEditStart = React.useCallback((field: string, value: unknown) => {
126
126
  if (!isGroupRow) {
127
127
  onEditStart?.({ id: row.id, field, value });
128
128
  }
129
129
  }, [isGroupRow, row.id, onEditStart]);
130
130
 
131
- const handleCellValueChange = React.useCallback((field: string, newValue: any) => {
131
+ const handleCellValueChange = React.useCallback((field: string, newValue: unknown) => {
132
132
  onEditCellValueChange?.({ id: row.id, field, value: newValue });
133
133
  }, [onEditCellValueChange, row.id]);
134
134
 
@@ -137,7 +137,7 @@ export function Row<R extends GridRowModel = GridRowModel>(props: RowProps<R>) {
137
137
  }, [onEditStop]);
138
138
 
139
139
  // ── Skeleton row (shown during infinite-scroll fetch) ─────────────────────
140
- if ((row as any)._isSkeleton) {
140
+ if (row._isSkeleton) {
141
141
  // Render shimmer placeholders — one per visible column, matching row height
142
142
  const cellCount = Math.max(columns.length, 5);
143
143
  return (
@@ -250,7 +250,7 @@ export function Row<R extends GridRowModel = GridRowModel>(props: RowProps<R>) {
250
250
  row,
251
251
  field: '__expand_col__',
252
252
  value: isDetailPanelExpanded,
253
- colDef: { field: '__expand_col__', width: 48 } as any,
253
+ colDef: { field: '__expand_col__', width: 48 } as unknown as GridColDef<R>,
254
254
  rowIndex,
255
255
  colIndex: -1
256
256
  });
@@ -284,7 +284,7 @@ export function Row<R extends GridRowModel = GridRowModel>(props: RowProps<R>) {
284
284
  row,
285
285
  field: '__checkbox_col__',
286
286
  value: isSelected,
287
- colDef: { field: '__checkbox_col__', width: 48 } as any,
287
+ colDef: { field: '__checkbox_col__', width: 48 } as unknown as GridColDef<R>,
288
288
  rowIndex,
289
289
  colIndex: -1
290
290
  });
@@ -305,7 +305,7 @@ export function Row<R extends GridRowModel = GridRowModel>(props: RowProps<R>) {
305
305
 
306
306
  { }
307
307
  {columns.map((colDef, colIndex) => {
308
- if ((colDef as any).isSpacer) {
308
+ if (colDef.isSpacer) {
309
309
  return (
310
310
  <div
311
311
  key={colDef.field}
@@ -1,8 +1,15 @@
1
1
  import React from 'react';
2
+ import type { GridColDef } from '../../types';
2
3
 
4
+ interface SkeletonColumn extends GridColDef {
5
+ left?: number;
6
+ right?: number;
7
+ pinned?: 'left' | 'right';
8
+ zIndex?: number;
9
+ }
3
10
 
4
11
  interface SkeletonRowProps {
5
- columns: any[];
12
+ columns: SkeletonColumn[];
6
13
  rowHeight: number;
7
14
  checkboxSelection?: boolean;
8
15
  hasDetailPanel?: boolean;
@@ -54,7 +61,7 @@ export const SkeletonRow: React.FC<SkeletonRowProps> = ({
54
61
 
55
62
  { }
56
63
  {columns.map((col, index) => {
57
- const width = col.width || 150;
64
+ const width = typeof col.width === 'number' ? col.width : 150;
58
65
  const skeletonWidth = Math.min(width * 0.7, width - 20);
59
66
 
60
67
  return (
@@ -23,6 +23,7 @@ export interface GridToolbarProps {
23
23
  columnVisibilityModel?: Record<string, boolean>;
24
24
  onColumnVisibilityModelChange?: (model: Record<string, boolean>) => void;
25
25
  onColumnReorder?: (fromField: string, toField: string) => void;
26
+ onColumnOrderReset?: () => void;
26
27
  forceColumnsOpen?: boolean;
27
28
  onColumnsPanelClose?: () => void;
28
29
  children?: React.ReactNode;
@@ -201,6 +202,7 @@ function ColumnsPanelWrapper({
201
202
  onShowAll,
202
203
  onHideAll,
203
204
  onColumnReorder,
205
+ onColumnOrderReset,
204
206
  onClose
205
207
  }: {
206
208
  anchorRef: React.RefObject<HTMLButtonElement | null>;
@@ -210,6 +212,7 @@ function ColumnsPanelWrapper({
210
212
  onShowAll: () => void;
211
213
  onHideAll: () => void;
212
214
  onColumnReorder?: (fromField: string, toField: string) => void;
215
+ onColumnOrderReset?: () => void;
213
216
  onClose: () => void;
214
217
  }) {
215
218
  const panelRef = useRef<HTMLDivElement>(null);
@@ -268,6 +271,7 @@ function ColumnsPanelWrapper({
268
271
  onShowAll={onShowAll}
269
272
  onHideAll={onHideAll}
270
273
  onColumnReorder={onColumnReorder}
274
+ onColumnOrderReset={onColumnOrderReset}
271
275
  />
272
276
  </div>
273
277
  );
@@ -403,6 +407,7 @@ export function GridToolbar({
403
407
  columnVisibilityModel = {},
404
408
  onColumnVisibilityModelChange,
405
409
  onColumnReorder,
410
+ onColumnOrderReset,
406
411
  forceColumnsOpen,
407
412
  onColumnsPanelClose,
408
413
  children,
@@ -553,6 +558,7 @@ export function GridToolbar({
553
558
  onShowAll={handleShowAllColumns}
554
559
  onHideAll={handleHideAllColumns}
555
560
  onColumnReorder={onColumnReorder}
561
+ onColumnOrderReset={onColumnOrderReset}
556
562
  onClose={() => { setColsOpen(false); onColumnsPanelClose?.(); }}
557
563
  />
558
564
  )}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Regression tests for bugs fixed in the useDataGrid reducer.
3
+ *
4
+ * Each describe block names the bug and the commit that fixed it, so a
5
+ * future failure tells you exactly what regressed and where to look.
6
+ */
7
+
8
+ import { describe, it, expect } from 'vitest';
9
+ import { renderHook, act } from '@testing-library/react';
10
+ import { useDataGrid } from './useDataGrid';
11
+ import type { GridColDef } from '../../types';
12
+
13
+ const COLS: GridColDef[] = [
14
+ { field: 'id', headerName: 'ID', width: 80 },
15
+ { field: 'name', headerName: 'Name', width: 150 },
16
+ { field: 'age', headerName: 'Age', width: 100 },
17
+ ];
18
+
19
+ const ROWS = [
20
+ { id: 1, name: 'Alice', age: 30 },
21
+ { id: 2, name: 'Bob', age: 25 },
22
+ ];
23
+
24
+ // ─────────────────────────────────────────────────────────────────────────────
25
+ // Bug: SET_COLUMNS reducer was hardcoding columnVisibilityModel: {} on every
26
+ // column update, silently wiping any hidden columns.
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+ describe('SET_COLUMNS preserves columnVisibilityModel', () => {
29
+ it('keeps hidden columns hidden after setColumns is called', () => {
30
+ const { result } = renderHook(() =>
31
+ useDataGrid({
32
+ rows: ROWS,
33
+ columns: COLS,
34
+ columnVisibilityModel: { age: false },
35
+ })
36
+ );
37
+
38
+ // Confirm the initial visibility model was applied.
39
+ expect(result.current.state.columns.columnVisibilityModel).toEqual({ age: false });
40
+
41
+ // Simulate a column update (e.g. a width change coming from a resize handler).
42
+ const updatedCols: GridColDef[] = COLS.map(c =>
43
+ c.field === 'name' ? { ...c, width: 200 } : c
44
+ );
45
+
46
+ act(() => {
47
+ result.current.setColumns(updatedCols);
48
+ });
49
+
50
+ // The visibility model must survive the column update — not reset to {}.
51
+ expect(result.current.state.columns.columnVisibilityModel).toEqual({ age: false });
52
+ });
53
+
54
+ it('does not gain a visibility entry for columns that were already visible', () => {
55
+ const { result } = renderHook(() =>
56
+ useDataGrid({ rows: ROWS, columns: COLS })
57
+ );
58
+
59
+ act(() => {
60
+ result.current.setColumns(COLS);
61
+ });
62
+
63
+ // No spurious entries: an empty model means all columns are visible.
64
+ expect(result.current.state.columns.columnVisibilityModel).toEqual({});
65
+ });
66
+ });
@@ -1,7 +1,7 @@
1
1
 
2
- import { useReducer, useCallback, useMemo, useRef, useEffect, useLayoutEffect } from 'react';
2
+ import { useReducer, useCallback, useState, useRef, useEffect, useLayoutEffect } from 'react';
3
3
  import type {
4
- GridState,
4
+ GridInternalState as GridState,
5
5
  GridRowModel,
6
6
  GridColDef,
7
7
  GridRowId,
@@ -19,27 +19,25 @@ type GridAction =
19
19
  | { type: 'SET_FILTER_MODEL'; payload: GridFilterModel }
20
20
  | { type: 'SET_PAGINATION_MODEL'; payload: GridPaginationModel }
21
21
  | { type: 'SET_SELECTION'; payload: Set<GridRowId> }
22
- | { type: 'SET_SCROLL'; payload: { scrollTop: number; scrollLeft: number } }
23
22
  | { type: 'SET_DIMENSIONS'; payload: { viewportWidth: number; viewportHeight: number } }
24
23
  | { type: 'SET_DATASOURCE_LOADING'; payload: boolean }
25
- | { type: 'SET_DATASOURCE_ERROR'; payload: any }
24
+ | { type: 'SET_DATASOURCE_ERROR'; payload: unknown }
26
25
  | { type: 'SET_ROW_COUNT'; payload: number };
27
26
 
28
- function createInitialState(rows: GridRowModel[], columns: GridColDef[], columnVisibilityModel: GridColumnVisibilityModel = {}): GridState {
27
+ function createInitialState<R extends GridRowModel>(rows: R[], columns: GridColDef<R>[], columnVisibilityModel: GridColumnVisibilityModel = {}): GridState {
29
28
  const idRowsLookup = new Map<GridRowId, GridRowModel>();
30
29
  const allRows: GridRowId[] = [];
31
30
 
32
31
  rows.forEach(row => {
33
- const id = row.id;
34
- idRowsLookup.set(id, row);
35
- allRows.push(id);
32
+ idRowsLookup.set(row.id, row);
33
+ allRows.push(row.id);
36
34
  });
37
35
 
38
36
  const columnLookup = new Map<string, GridColDef>();
39
37
  const orderedFields: string[] = [];
40
38
 
41
39
  columns.forEach(col => {
42
- columnLookup.set(col.field, col);
40
+ columnLookup.set(col.field, col as unknown as GridColDef);
43
41
  orderedFields.push(col.field);
44
42
  });
45
43
 
@@ -49,7 +47,7 @@ function createInitialState(rows: GridRowModel[], columns: GridColDef[], columnV
49
47
  allRows
50
48
  },
51
49
  columns: {
52
- all: columns,
50
+ all: columns as unknown as GridColDef[],
53
51
  lookup: columnLookup,
54
52
  orderedFields,
55
53
  columnVisibilityModel
@@ -78,8 +76,6 @@ function createInitialState(rows: GridRowModel[], columns: GridColDef[], columnV
78
76
  firstColumnIndex: 0,
79
77
  lastColumnIndex: 0
80
78
  },
81
- scrollTop: 0,
82
- scrollLeft: 0
83
79
  },
84
80
  dimensions: {
85
81
  rowHeight: 52,
@@ -137,7 +133,7 @@ function gridReducer(state: GridState, action: GridAction): GridState {
137
133
  all: action.payload,
138
134
  lookup: columnLookup,
139
135
  orderedFields,
140
- columnVisibilityModel: {}
136
+ columnVisibilityModel: state.columns.columnVisibilityModel
141
137
  }
142
138
  };
143
139
  }
@@ -169,16 +165,6 @@ function gridReducer(state: GridState, action: GridAction): GridState {
169
165
  selection: { selectedRows: action.payload }
170
166
  };
171
167
 
172
- case 'SET_SCROLL':
173
- return {
174
- ...state,
175
- virtualization: {
176
- ...state.virtualization,
177
- scrollTop: action.payload.scrollTop,
178
- scrollLeft: action.payload.scrollLeft
179
- }
180
- };
181
-
182
168
  case 'SET_DIMENSIONS':
183
169
  return {
184
170
  ...state,
@@ -234,18 +220,17 @@ export interface UseDataGridParams<R extends GridRowModel = GridRowModel> {
234
220
  export function useDataGrid<R extends GridRowModel = GridRowModel>(params: UseDataGridParams<R>) {
235
221
  const { rows, columns, rowHeight = 52, headerHeight = 56, columnVisibilityModel, initialState: propInitialState } = params;
236
222
 
237
- const internalInitialState = useMemo(
238
- () => createInitialState(rows, columns as any, columnVisibilityModel),
239
- []
223
+ const [internalInitialState] = useState(() =>
224
+ createInitialState(rows, columns, columnVisibilityModel)
240
225
  );
241
226
 
242
227
  const [state, dispatch] = useReducer(gridReducer, {
243
228
  ...internalInitialState,
244
229
  sorting: propInitialState?.sorting || internalInitialState.sorting,
245
230
  filter: propInitialState?.filter || internalInitialState.filter,
246
- dataSource: (propInitialState?.dataSource
231
+ dataSource: propInitialState?.dataSource
247
232
  ? { ...internalInitialState.dataSource, ...propInitialState.dataSource }
248
- : internalInitialState.dataSource) as any,
233
+ : internalInitialState.dataSource,
249
234
  pagination: {
250
235
  ...internalInitialState.pagination,
251
236
  ...(propInitialState?.pagination || {}),
@@ -294,10 +279,6 @@ export function useDataGrid<R extends GridRowModel = GridRowModel>(params: UseDa
294
279
  dispatch({ type: 'SET_SELECTION', payload: selectedRows });
295
280
  }, []);
296
281
 
297
- const setScroll = useCallback((scrollTop: number, scrollLeft: number) => {
298
- dispatch({ type: 'SET_SCROLL', payload: { scrollTop, scrollLeft } });
299
- }, []);
300
-
301
282
  const setDimensions = useCallback((viewportWidth: number, viewportHeight: number) => {
302
283
  dispatch({ type: 'SET_DIMENSIONS', payload: { viewportWidth, viewportHeight } });
303
284
  }, []);
@@ -306,7 +287,7 @@ export function useDataGrid<R extends GridRowModel = GridRowModel>(params: UseDa
306
287
  dispatch({ type: 'SET_DATASOURCE_LOADING', payload: loading });
307
288
  }, []);
308
289
 
309
- const setDataSourceError = useCallback((error: any) => {
290
+ const setDataSourceError = useCallback((error: unknown) => {
310
291
  dispatch({ type: 'SET_DATASOURCE_ERROR', payload: error });
311
292
  }, []);
312
293
 
@@ -383,7 +364,6 @@ export function useDataGrid<R extends GridRowModel = GridRowModel>(params: UseDa
383
364
  setFilterModel,
384
365
  setPaginationModel,
385
366
  setSelection,
386
- setScroll,
387
367
  setDimensions,
388
368
  setDataSourceLoading,
389
369
  setDataSourceError,