@opencorestack/opengridx 0.1.8 → 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 (67) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/index.d.ts +60 -41
  3. package/dist/opengridx.es.js +5271 -4660
  4. package/dist/opengridx.es.js.map +1 -1
  5. package/dist/opengridx.umd.js +12 -12
  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 +61 -64
  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.smoke.test.tsx +58 -0
  18. package/lib/components/DataGrid/DataGrid.tsx +396 -1654
  19. package/lib/components/DataGrid/GridAggregationFooter.tsx +68 -0
  20. package/lib/components/DataGrid/GridEmptyState.tsx +16 -0
  21. package/lib/components/DataGrid/GridErrorOverlay.tsx +33 -0
  22. package/lib/components/DataGrid/GridListView.tsx +116 -0
  23. package/lib/components/DataGrid/GridPinnedRows.tsx +98 -0
  24. package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +124 -0
  25. package/lib/components/DataGrid/GridVirtualRows.tsx +202 -0
  26. package/lib/components/FilterPanel/FilterPanel.tsx +18 -10
  27. package/lib/components/Header/ColumnMenu.tsx +2 -2
  28. package/lib/components/Header/Header.tsx +4 -4
  29. package/lib/components/ListView/ListViewRow.tsx +2 -2
  30. package/lib/components/Row/Row.tsx +46 -45
  31. package/lib/components/SkeletonRow/SkeletonRow.tsx +9 -2
  32. package/lib/components/Toolbar/GlobalSearch.tsx +1 -1
  33. package/lib/components/Toolbar/GridToolbar.tsx +26 -5
  34. package/lib/components/Toolbar/PivotPanel.tsx +7 -2
  35. package/lib/components/ui/DragHandleIcon.tsx +1 -1
  36. package/lib/hooks/core/useDataGrid.regression.test.ts +66 -0
  37. package/lib/hooks/core/useDataGrid.ts +15 -35
  38. package/lib/hooks/core/useGridColumns.tsx +228 -0
  39. package/lib/hooks/core/useGridControlledState.ts +192 -0
  40. package/lib/hooks/core/useGridKeyboardNavigation.ts +371 -0
  41. package/lib/hooks/core/useGridRowPipeline.ts +109 -0
  42. package/lib/hooks/core/useGridScrollSync.ts +52 -0
  43. package/lib/hooks/core/useGridStateSnapshot.ts +63 -0
  44. package/lib/hooks/core/useGridVirtualization.ts +186 -0
  45. package/lib/hooks/core/useGridVisibleRows.ts +66 -0
  46. package/lib/hooks/core/useLayout.ts +348 -0
  47. package/lib/hooks/features/useAggregation.test.ts +135 -0
  48. package/lib/hooks/features/useAggregation.ts +7 -7
  49. package/lib/hooks/features/useGridClipboard.ts +1 -1
  50. package/lib/hooks/features/useGridDataSource.ts +2 -2
  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 +2 -2
  59. package/lib/types/index.ts +48 -32
  60. package/lib/utils/export/exportToExcelAdvanced.ts +14 -14
  61. package/lib/utils/export/index.ts +23 -18
  62. package/lib/utils/filtering/filtering.test.ts +178 -0
  63. package/lib/utils/filtering/index.ts +20 -20
  64. package/lib/utils/sorting/index.ts +1 -1
  65. package/lib/utils/sorting/sorting.test.ts +88 -0
  66. package/package.json +12 -5
  67. package/lib/utils/virtualization/index.ts +0 -106
@@ -0,0 +1,228 @@
1
+ import { useState, useMemo, useCallback, useEffect } from 'react';
2
+ import { useColumnReorder } from '../useColumnReorder';
3
+ import { ExpandIcon } from '../../components/ui/ExpandIcon';
4
+ import type {
5
+ GridColDef,
6
+ GridRowModel,
7
+ GridRowId,
8
+ GridColumnOrderChangeParams,
9
+ GridRenderCellParams,
10
+ } from '../../types';
11
+ import type { GridInitialState } from '../../state/types';
12
+
13
+ interface HierarchyHandlers {
14
+ toggleExpansion: (id: GridRowId) => void;
15
+ }
16
+
17
+ export interface UseGridColumnsParams<R extends GridRowModel> {
18
+ activeColumns: GridColDef<R>[];
19
+ isHierarchyEnabled: boolean;
20
+ isRowGrouping: boolean;
21
+ isTreeData: boolean;
22
+ activeHierarchyHandlers: HierarchyHandlers | null;
23
+ columnVisibilityModel: Record<string, boolean>;
24
+ columnOrder?: string[];
25
+ onColumnOrderChange?: (params: GridColumnOrderChangeParams) => void;
26
+ disableColumnReorder: boolean;
27
+ pivotMode: boolean;
28
+ checkboxSelection: boolean;
29
+ hasDetailPanel: boolean;
30
+ rowReordering: boolean;
31
+ initialState?: GridInitialState;
32
+ setColumns: (cols: GridColDef[]) => void;
33
+ }
34
+
35
+ export interface UseGridColumnsResult<R extends GridRowModel> {
36
+ effectiveColumns: GridColDef<R>[];
37
+ orderedColumns: GridColDef<R>[];
38
+ visibleOrderedColumns: GridColDef<R>[];
39
+ navigationColumns: Array<GridColDef<R> | { field: string }>;
40
+ columnWidths: Record<string, number>;
41
+ effectiveColumnOrder: string[];
42
+ setInternalColumnOrder: React.Dispatch<React.SetStateAction<string[]>>;
43
+ columnReorderHandlers: ReturnType<typeof useColumnReorder>;
44
+ handleColumnResize: (field: string, newWidth: number) => void;
45
+ }
46
+
47
+ export function useGridColumns<R extends GridRowModel>(
48
+ params: UseGridColumnsParams<R>
49
+ ): UseGridColumnsResult<R> {
50
+ const {
51
+ activeColumns,
52
+ isHierarchyEnabled,
53
+ isRowGrouping,
54
+ isTreeData,
55
+ activeHierarchyHandlers,
56
+ columnVisibilityModel,
57
+ columnOrder,
58
+ onColumnOrderChange,
59
+ disableColumnReorder,
60
+ pivotMode,
61
+ checkboxSelection,
62
+ hasDetailPanel,
63
+ rowReordering,
64
+ initialState,
65
+ setColumns,
66
+ } = params;
67
+
68
+ // ── Effective columns (hierarchy cell renderer injection) ─────────────────
69
+ const effectiveColumns = useMemo<GridColDef<R>[]>(() => {
70
+ if (!isHierarchyEnabled) return activeColumns;
71
+
72
+ return activeColumns.map((col, index) => {
73
+ if (index === 0) {
74
+ return {
75
+ ...col,
76
+ renderCell: (cellParams: GridRenderCellParams<R>) => {
77
+ const r = cellParams.row as Record<string, unknown>;
78
+ const depth = typeof r._treeDepth === 'number' ? r._treeDepth : 0;
79
+ const hasChildren = Boolean(r._hasChildren);
80
+ const isExpanded = Boolean(r._isExpanded);
81
+ const groupingField = typeof r._groupingField === 'string' ? r._groupingField : undefined;
82
+ const groupingValue = r._groupingValue;
83
+ const descendantCount = typeof r._descendantCount === 'number' ? r._descendantCount : undefined;
84
+ const isGroupRow = Boolean(r._isGroupRow);
85
+
86
+ let content: React.ReactNode = col.renderCell ? col.renderCell(cellParams) : cellParams.value as React.ReactNode;
87
+
88
+ if (isTreeData && hasChildren && isGroupRow) {
89
+ content = (
90
+ <div className="ogx__group-cell-content">
91
+ {cellParams.value as React.ReactNode}
92
+ {descendantCount !== undefined && descendantCount > 0 ? ` (${descendantCount})` : ''}
93
+ </div>
94
+ );
95
+ }
96
+
97
+ if (isRowGrouping && hasChildren && groupingField) {
98
+ content = (
99
+ <div className="ogx__group-cell-content">
100
+ {col.field === groupingField ? '' : `${groupingField}: `}
101
+ {String(groupingValue)}
102
+ {descendantCount !== undefined ? ` (${descendantCount})` : ''}
103
+ </div>
104
+ );
105
+ }
106
+
107
+ return (
108
+ <div style={{ display: 'flex', alignItems: 'center', paddingLeft: depth * 24, width: '100%', height: '100%' }}>
109
+ <div style={{ marginRight: 4, width: 24, height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: hasChildren ? 'pointer' : 'default', flexShrink: 0 }}>
110
+ {hasChildren ? (
111
+ <div
112
+ onClick={(e) => { e.stopPropagation(); e.preventDefault(); activeHierarchyHandlers?.toggleExpansion(cellParams.row.id); }}
113
+ onMouseDown={(e) => { e.stopPropagation(); }}
114
+ style={{ cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', pointerEvents: 'auto', zIndex: 10, position: 'relative' }}
115
+ >
116
+ <ExpandIcon
117
+ isExpanded={isExpanded}
118
+ onClick={(e) => { e.stopPropagation(); e.preventDefault(); activeHierarchyHandlers?.toggleExpansion(cellParams.row.id); }}
119
+ />
120
+ </div>
121
+ ) : null}
122
+ </div>
123
+ <div style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{content}</div>
124
+ </div>
125
+ );
126
+ }
127
+ };
128
+ }
129
+
130
+ return {
131
+ ...col,
132
+ renderCell: (cellParams: GridRenderCellParams<R>) => {
133
+ const r = cellParams.row as Record<string, unknown>;
134
+ const hasChildren = Boolean(r._hasChildren);
135
+ const groupingField = typeof r._groupingField === 'string' ? r._groupingField : undefined;
136
+
137
+ if (isRowGrouping && hasChildren) {
138
+ if (col.field === groupingField) return null;
139
+ if (cellParams.value !== undefined && cellParams.value !== null) {
140
+ return col.renderCell ? col.renderCell(cellParams) : cellParams.value;
141
+ }
142
+ return null;
143
+ }
144
+
145
+ return col.renderCell ? col.renderCell(cellParams) : cellParams.value;
146
+ }
147
+ };
148
+ }) as GridColDef<R>[];
149
+ }, [activeColumns, isHierarchyEnabled, isRowGrouping, isTreeData, activeHierarchyHandlers]);
150
+
151
+ // ── Column widths ─────────────────────────────────────────────────────────
152
+ const [columnWidths, setColumnWidths] = useState<Record<string, number>>(
153
+ () => initialState?.columns?.columnWidths ?? {}
154
+ );
155
+
156
+ const handleColumnResize = useCallback((field: string, newWidth: number) => {
157
+ setColumnWidths(prev => ({ ...prev, [field]: newWidth }));
158
+ }, []);
159
+
160
+ // ── Column order ──────────────────────────────────────────────────────────
161
+ const [internalColumnOrder, setInternalColumnOrder] = useState<string[]>(
162
+ () => initialState?.columns?.columnOrder ?? activeColumns.map(col => col.field)
163
+ );
164
+
165
+ const effectiveColumnOrder = columnOrder ?? internalColumnOrder;
166
+
167
+ useEffect(() => {
168
+ setColumns(activeColumns as unknown as GridColDef[]);
169
+ }, [activeColumns, setColumns]);
170
+
171
+ useEffect(() => {
172
+ if (pivotMode) {
173
+ setInternalColumnOrder(activeColumns.map(col => col.field));
174
+ }
175
+ }, [pivotMode, activeColumns]);
176
+
177
+ // ── Ordered / visible columns ─────────────────────────────────────────────
178
+ const orderedColumns = useMemo<GridColDef<R>[]>(() => {
179
+ if (disableColumnReorder) return effectiveColumns;
180
+
181
+ const orderMap = new Map(effectiveColumnOrder.map((field, idx) => [field, idx]));
182
+ return [...effectiveColumns].sort((a, b) => {
183
+ const ai = orderMap.get(a.field) ?? effectiveColumns.indexOf(a);
184
+ const bi = orderMap.get(b.field) ?? effectiveColumns.indexOf(b);
185
+ return ai - bi;
186
+ });
187
+ }, [effectiveColumns, effectiveColumnOrder, disableColumnReorder]);
188
+
189
+ const visibleOrderedColumns = useMemo<GridColDef<R>[]>(
190
+ () => orderedColumns.filter(col => columnVisibilityModel[col.field] !== false),
191
+ [orderedColumns, columnVisibilityModel]
192
+ );
193
+
194
+ // ── Column reorder handlers ───────────────────────────────────────────────
195
+ const columnReorderHandlers = useColumnReorder({
196
+ columns: orderedColumns,
197
+ onColumnOrderChange: useCallback((reorderParams: GridColumnOrderChangeParams) => {
198
+ const { oldIndex, targetIndex } = reorderParams;
199
+ const newOrder = [...effectiveColumnOrder];
200
+ const [movedField] = newOrder.splice(oldIndex, 1);
201
+ newOrder.splice(targetIndex, 0, movedField);
202
+ if (!columnOrder) setInternalColumnOrder(newOrder);
203
+ onColumnOrderChange?.(reorderParams);
204
+ }, [effectiveColumnOrder, columnOrder, onColumnOrderChange]),
205
+ disableColumnReorder,
206
+ });
207
+
208
+ // ── Navigation columns (system cols + data cols for keyboard nav) ─────────
209
+ const navigationColumns = useMemo(() => {
210
+ const specials: { field: string }[] = [];
211
+ if (rowReordering) specials.push({ field: '__reorder_col__' });
212
+ if (hasDetailPanel) specials.push({ field: '__expand_col__' });
213
+ if (checkboxSelection) specials.push({ field: '__checkbox_col__' });
214
+ return [...specials, ...orderedColumns] as Array<GridColDef<R> | { field: string }>;
215
+ }, [orderedColumns, checkboxSelection, hasDetailPanel, rowReordering]);
216
+
217
+ return {
218
+ effectiveColumns,
219
+ orderedColumns,
220
+ visibleOrderedColumns,
221
+ navigationColumns,
222
+ columnWidths,
223
+ effectiveColumnOrder,
224
+ setInternalColumnOrder,
225
+ columnReorderHandlers,
226
+ handleColumnResize,
227
+ };
228
+ }
@@ -0,0 +1,192 @@
1
+ import { useState, useCallback, useMemo } from 'react';
2
+ import type {
3
+ GridRowId,
4
+ GridSortItem,
5
+ GridColumnPinning,
6
+ GridPaginationModel,
7
+ GridAggregationModel,
8
+ GridPivotModel,
9
+ } from '../../types';
10
+ import type { GridInitialState } from '../../state/types';
11
+
12
+ export interface UseGridControlledStateParams {
13
+ initialState?: GridInitialState;
14
+
15
+ sortModel?: GridSortItem[];
16
+ onSortModelChange?: (model: GridSortItem[]) => void;
17
+
18
+ aggregationModel?: GridAggregationModel;
19
+ onAggregationModelChange?: (model: GridAggregationModel) => void;
20
+
21
+ columnVisibilityModel?: Record<string, boolean>;
22
+ onColumnVisibilityModelChange?: (model: Record<string, boolean>) => void;
23
+
24
+ pinnedColumns?: GridColumnPinning;
25
+ onPinnedColumnsChange?: (model: GridColumnPinning) => void;
26
+
27
+ pivotModel?: GridPivotModel;
28
+ onPivotModelChange?: (model: GridPivotModel) => void;
29
+
30
+ paginationModel?: GridPaginationModel;
31
+ onPaginationModelChange?: (model: GridPaginationModel) => void;
32
+
33
+ rowSelectionModel?: GridRowId[];
34
+ onRowSelectionModelChange?: (model: GridRowId[]) => void;
35
+ }
36
+
37
+ export interface UseGridControlledStateReturn {
38
+ // sort
39
+ sortModel: GridSortItem[];
40
+ isSortControlled: boolean;
41
+ setInternalSortModel: React.Dispatch<React.SetStateAction<GridSortItem[]>>;
42
+
43
+ // aggregation
44
+ aggregationModel: GridAggregationModel;
45
+ handleAggregationModelChange: (model: GridAggregationModel) => void;
46
+
47
+ // column visibility
48
+ columnVisibilityModel: Record<string, boolean>;
49
+ handleColumnVisibilityModelChange: (model: Record<string, boolean>) => void;
50
+
51
+ // pinned columns
52
+ pinnedColumns: GridColumnPinning;
53
+ handlePinnedColumnsChange: (model: GridColumnPinning) => void;
54
+
55
+ // pivot
56
+ currentPivotModel: GridPivotModel;
57
+ handlePivotModelChange: (model: GridPivotModel) => void;
58
+
59
+ // pagination
60
+ effectivePaginationModel: GridPaginationModel;
61
+ handlePaginationModelChange: (model: GridPaginationModel) => void;
62
+
63
+ // selection
64
+ rowSelectionModel: GridRowId[];
65
+ selectedRowIds: Set<GridRowId>;
66
+ isSelectionControlled: boolean;
67
+ setInternalRowSelectionModel: React.Dispatch<React.SetStateAction<GridRowId[]>>;
68
+ }
69
+
70
+ const EMPTY_PIVOT_MODEL: GridPivotModel = { rowFields: [], columnFields: [], valueFields: [] };
71
+
72
+ export function useGridControlledState(params: UseGridControlledStateParams): UseGridControlledStateReturn {
73
+ const {
74
+ initialState,
75
+ sortModel: propSortModel,
76
+ aggregationModel: propAggregationModel,
77
+ onAggregationModelChange,
78
+ columnVisibilityModel: propColumnVisibilityModel,
79
+ onColumnVisibilityModelChange,
80
+ pinnedColumns: propPinnedColumns,
81
+ onPinnedColumnsChange,
82
+ pivotModel: propPivotModel,
83
+ onPivotModelChange,
84
+ paginationModel: propPaginationModel = { page: 0, pageSize: 100 },
85
+ onPaginationModelChange,
86
+ rowSelectionModel: propRowSelectionModel,
87
+ onRowSelectionModelChange,
88
+ } = params;
89
+
90
+ // ── Sort ─────────────────────────────────────────────────────────────────
91
+ const [internalSortModel, setInternalSortModel] = useState<GridSortItem[]>(
92
+ () => initialState?.sorting?.sortModel ?? []
93
+ );
94
+ const isSortControlled = propSortModel !== undefined;
95
+ const sortModel = isSortControlled ? propSortModel! : internalSortModel;
96
+
97
+ // ── Aggregation ──────────────────────────────────────────────────────────
98
+ const isAggregationControlled = propAggregationModel !== undefined;
99
+ const [internalAggregationModel, setInternalAggregationModel] = useState<GridAggregationModel>(
100
+ () => propAggregationModel ?? {}
101
+ );
102
+ const aggregationModel = isAggregationControlled ? propAggregationModel! : internalAggregationModel;
103
+
104
+ const handleAggregationModelChange = useCallback((model: GridAggregationModel) => {
105
+ if (!isAggregationControlled) setInternalAggregationModel(model);
106
+ onAggregationModelChange?.(model);
107
+ }, [isAggregationControlled, onAggregationModelChange]);
108
+
109
+ // ── Column visibility ────────────────────────────────────────────────────
110
+ const isColumnVisibilityControlled = propColumnVisibilityModel !== undefined;
111
+ const [internalColumnVisibilityModel, setInternalColumnVisibilityModel] = useState<Record<string, boolean>>(
112
+ () => initialState?.columns?.columnVisibilityModel ?? {}
113
+ );
114
+ const columnVisibilityModel = isColumnVisibilityControlled
115
+ ? propColumnVisibilityModel!
116
+ : internalColumnVisibilityModel;
117
+
118
+ const handleColumnVisibilityModelChange = useCallback((model: Record<string, boolean>) => {
119
+ if (!isColumnVisibilityControlled) setInternalColumnVisibilityModel(model);
120
+ onColumnVisibilityModelChange?.(model);
121
+ }, [isColumnVisibilityControlled, onColumnVisibilityModelChange]);
122
+
123
+ // ── Pinned columns ───────────────────────────────────────────────────────
124
+ const isPinnedColumnsControlled = propPinnedColumns !== undefined;
125
+ const [internalPinnedColumns, setInternalPinnedColumns] = useState<GridColumnPinning>(
126
+ () => initialState?.columns?.pinnedColumns ?? {}
127
+ );
128
+ const pinnedColumns = isPinnedColumnsControlled ? propPinnedColumns! : internalPinnedColumns;
129
+
130
+ const handlePinnedColumnsChange = useCallback((model: GridColumnPinning) => {
131
+ if (!isPinnedColumnsControlled) setInternalPinnedColumns(model);
132
+ onPinnedColumnsChange?.(model);
133
+ }, [isPinnedColumnsControlled, onPinnedColumnsChange]);
134
+
135
+ // ── Pivot ────────────────────────────────────────────────────────────────
136
+ const [internalPivotModel, setInternalPivotModel] = useState<GridPivotModel>(
137
+ () => propPivotModel ?? EMPTY_PIVOT_MODEL
138
+ );
139
+ const currentPivotModel = propPivotModel ?? internalPivotModel;
140
+
141
+ const handlePivotModelChange = useCallback((model: GridPivotModel) => {
142
+ setInternalPivotModel(model);
143
+ onPivotModelChange?.(model);
144
+ }, [onPivotModelChange]);
145
+
146
+ // ── Pagination ───────────────────────────────────────────────────────────
147
+ const isPaginationControlled = propPaginationModel !== undefined && params.paginationModel !== undefined;
148
+ const [internalPaginationModel, setInternalPaginationModel] = useState<GridPaginationModel>(
149
+ () => initialState?.pagination?.paginationModel ?? propPaginationModel
150
+ );
151
+ const effectivePaginationModel = isPaginationControlled ? propPaginationModel : internalPaginationModel;
152
+
153
+ const handlePaginationModelChange = useCallback((newModel: GridPaginationModel) => {
154
+ if (!isPaginationControlled) setInternalPaginationModel(newModel);
155
+ onPaginationModelChange?.(newModel);
156
+ }, [isPaginationControlled, onPaginationModelChange]);
157
+
158
+ // ── Row selection ────────────────────────────────────────────────────────
159
+ const isSelectionControlled = propRowSelectionModel !== undefined;
160
+ const [internalRowSelectionModel, setInternalRowSelectionModel] = useState<GridRowId[]>([]);
161
+ const rowSelectionModel = isSelectionControlled ? propRowSelectionModel! : internalRowSelectionModel;
162
+ const selectedRowIds = useMemo(() => new Set(rowSelectionModel), [rowSelectionModel]);
163
+
164
+ // onRowSelectionModelChange is consumed by the caller directly (they call it when selection changes)
165
+ void onRowSelectionModelChange;
166
+
167
+ return {
168
+ sortModel: sortModel as GridSortItem[],
169
+ isSortControlled,
170
+ setInternalSortModel: setInternalSortModel as React.Dispatch<React.SetStateAction<GridSortItem[]>>,
171
+
172
+ aggregationModel,
173
+ handleAggregationModelChange,
174
+
175
+ columnVisibilityModel,
176
+ handleColumnVisibilityModelChange,
177
+
178
+ pinnedColumns,
179
+ handlePinnedColumnsChange,
180
+
181
+ currentPivotModel,
182
+ handlePivotModelChange,
183
+
184
+ effectivePaginationModel,
185
+ handlePaginationModelChange,
186
+
187
+ rowSelectionModel,
188
+ selectedRowIds,
189
+ isSelectionControlled,
190
+ setInternalRowSelectionModel,
191
+ };
192
+ }