@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.
- package/CHANGELOG.md +51 -0
- package/README.md +162 -19
- package/dist/index.d.ts +60 -41
- package/dist/opengridx.es.js +5045 -4549
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +11 -11
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +17 -7
- package/docs/README.md +14 -0
- package/docs/components/aggregation-footer.md +48 -0
- package/docs/components/datagrid.md +8 -3
- package/docs/components/empty-state.md +50 -0
- package/docs/components/error-overlay.md +40 -0
- package/docs/features/editing-reordering.md +11 -7
- package/docs/features/filtering.md +10 -8
- package/docs/features/selection.md +2 -1
- package/docs/features/sorting-pagination.md +3 -1
- package/docs/features/state-persistence.md +1 -2
- package/docs/roadmap.md +20 -1
- package/lib/components/Cell/Cell.tsx +9 -10
- package/lib/components/Cell/GridEditInputCell.tsx +4 -4
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +3 -2
- package/lib/components/DataGrid/DataGrid.regression.test.tsx +132 -0
- package/lib/components/DataGrid/DataGrid.tsx +336 -1018
- package/lib/components/DataGrid/GridAggregationFooter.tsx +68 -0
- package/lib/components/DataGrid/GridEmptyState.tsx +16 -0
- package/lib/components/DataGrid/GridErrorOverlay.tsx +33 -0
- package/lib/components/DataGrid/GridListView.tsx +116 -0
- package/lib/components/DataGrid/GridPinnedRows.tsx +98 -0
- package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +124 -0
- package/lib/components/DataGrid/GridVirtualRows.tsx +202 -0
- package/lib/components/FilterPanel/FilterPanel.tsx +18 -10
- package/lib/components/Header/ColumnMenu.tsx +2 -2
- package/lib/components/Header/Header.tsx +4 -4
- package/lib/components/ListView/ListViewRow.tsx +2 -2
- package/lib/components/Row/Row.tsx +10 -10
- package/lib/components/SkeletonRow/SkeletonRow.tsx +9 -2
- package/lib/components/Toolbar/GridToolbar.tsx +6 -0
- package/lib/hooks/core/useDataGrid.regression.test.ts +66 -0
- package/lib/hooks/core/useDataGrid.ts +14 -34
- package/lib/hooks/core/useGridColumns.tsx +228 -0
- package/lib/hooks/core/useGridControlledState.ts +192 -0
- package/lib/hooks/core/useGridRowPipeline.ts +109 -0
- package/lib/hooks/core/useGridScrollSync.ts +52 -0
- package/lib/hooks/core/useGridStateSnapshot.ts +63 -0
- package/lib/hooks/core/useGridVirtualization.ts +186 -0
- package/lib/hooks/core/useGridVisibleRows.ts +66 -0
- package/lib/hooks/core/useLayout.ts +0 -6
- package/lib/hooks/features/useAggregation.ts +7 -7
- package/lib/hooks/features/useGridDataSource.ts +1 -1
- package/lib/hooks/features/useGridEditing.ts +31 -32
- package/lib/hooks/features/usePivot.test.ts +202 -0
- package/lib/hooks/features/usePivot.ts +0 -0
- package/lib/hooks/useColumnReorder.ts +1 -1
- package/lib/hooks/useRowGrouping.ts +14 -14
- package/lib/hooks/useTreeData.ts +1 -1
- package/lib/state/types.ts +1 -1
- package/lib/state/useGridStateStorage.ts +1 -1
- package/lib/types/index.ts +48 -32
- package/lib/utils/export/exportToExcelAdvanced.ts +14 -14
- package/lib/utils/export/index.ts +22 -17
- package/lib/utils/filtering/index.ts +20 -20
- package/lib/utils/sorting/index.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for bugs fixed in the DataGrid render layer.
|
|
3
|
+
*
|
|
4
|
+
* Tests cover:
|
|
5
|
+
* - getVisibleRows() respects pagination (not returning all rows)
|
|
6
|
+
* - Row DOM nodes are not remounted when column widths change
|
|
7
|
+
*
|
|
8
|
+
* Not covered here (require a real browser / ResizeObserver):
|
|
9
|
+
* - translateY offset — depends on computed cumulativeHeights, which requires
|
|
10
|
+
* a real viewport; jsdom reports all dimensions as 0
|
|
11
|
+
* - scroll-ref RAF batching — requires scroll events that jsdom fires but
|
|
12
|
+
* requestAnimationFrame does not execute by default
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import React from 'react';
|
|
16
|
+
import { describe, it, expect } from 'vitest';
|
|
17
|
+
import { render, act } from '@testing-library/react';
|
|
18
|
+
import { DataGrid } from './DataGrid';
|
|
19
|
+
import { useGridApiRef } from '../../hooks/core/useGridApiRef';
|
|
20
|
+
import type { GridColDef } from '../../types';
|
|
21
|
+
|
|
22
|
+
const COLS: GridColDef[] = [
|
|
23
|
+
{ field: 'id', headerName: 'ID', width: 80 },
|
|
24
|
+
{ field: 'name', headerName: 'Name', width: 150 },
|
|
25
|
+
{ field: 'age', headerName: 'Age', width: 100 },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// 10 rows so pagination actually clips the visible set
|
|
29
|
+
const ROWS = Array.from({ length: 10 }, (_, i) => ({
|
|
30
|
+
id: i + 1,
|
|
31
|
+
name: `User ${i + 1}`,
|
|
32
|
+
age: 20 + i,
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
// Bug: getVisibleRows() was returning sortedUnpinnedRows (all rows) regardless
|
|
37
|
+
// of whether pagination was active. Fixed: now returns paginatedUnpinnedRows
|
|
38
|
+
// when a paginationModel is set.
|
|
39
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
describe('getVisibleRows respects pagination', () => {
|
|
42
|
+
it('returns only the current page rows, not all rows', () => {
|
|
43
|
+
const assigningRef = React.createRef<import('../../types').GridApi>();
|
|
44
|
+
|
|
45
|
+
function GridWithRef() {
|
|
46
|
+
const ref = useGridApiRef();
|
|
47
|
+
// expose ref to test scope after render
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
(assigningRef as React.MutableRefObject<import('../../types').GridApi>).current = ref.current;
|
|
50
|
+
});
|
|
51
|
+
return (
|
|
52
|
+
<DataGrid
|
|
53
|
+
rows={ROWS}
|
|
54
|
+
columns={COLS}
|
|
55
|
+
apiRef={ref}
|
|
56
|
+
pagination
|
|
57
|
+
paginationModel={{ page: 0, pageSize: 3 }}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
act(() => {
|
|
63
|
+
render(<GridWithRef />);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// pageSize=3, total=10 → page 0 should expose 3 rows, not 10.
|
|
67
|
+
const visible = assigningRef.current?.getVisibleRows() ?? [];
|
|
68
|
+
expect(visible.length).toBe(3);
|
|
69
|
+
expect(visible.map(r => r.id)).toEqual([1, 2, 3]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('returns all rows when no pagination is provided', () => {
|
|
73
|
+
const assigningRef = React.createRef<import('../../types').GridApi>();
|
|
74
|
+
|
|
75
|
+
function GridNoPagination() {
|
|
76
|
+
const ref = useGridApiRef();
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
(assigningRef as React.MutableRefObject<import('../../types').GridApi>).current = ref.current;
|
|
79
|
+
});
|
|
80
|
+
return <DataGrid rows={ROWS} columns={COLS} apiRef={ref} />;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
act(() => {
|
|
84
|
+
render(<GridNoPagination />);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const visible = assigningRef.current?.getVisibleRows() ?? [];
|
|
88
|
+
// Without pagination the full sorted set is returned.
|
|
89
|
+
expect(visible.length).toBe(ROWS.length);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
94
|
+
// Bug: row keys were `${row.id}-${virtualization.totalWidth}`, so every column
|
|
95
|
+
// resize unmounted and remounted every DOM row node.
|
|
96
|
+
// Fixed: key is now simply `row.id`.
|
|
97
|
+
//
|
|
98
|
+
// Test strategy: capture DOM element identity before and after a column prop
|
|
99
|
+
// change. If the key includes totalWidth the elements will be new nodes; if
|
|
100
|
+
// the key is stable they will be the exact same DOM nodes.
|
|
101
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
describe('row DOM nodes are stable across column width changes', () => {
|
|
104
|
+
it('does not remount rows when column widths change', () => {
|
|
105
|
+
const { rerender, container } = render(
|
|
106
|
+
<DataGrid rows={ROWS.slice(0, 3)} columns={COLS} />
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Collect the row cell elements before the update.
|
|
110
|
+
const cellsBefore = Array.from(
|
|
111
|
+
container.querySelectorAll('[role="gridcell"]')
|
|
112
|
+
);
|
|
113
|
+
expect(cellsBefore.length).toBeGreaterThan(0);
|
|
114
|
+
|
|
115
|
+
// Update the Name column width — simulates a resize.
|
|
116
|
+
const updatedCols: GridColDef[] = COLS.map(c =>
|
|
117
|
+
c.field === 'name' ? { ...c, width: 250 } : c
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
rerender(<DataGrid rows={ROWS.slice(0, 3)} columns={updatedCols} />);
|
|
121
|
+
|
|
122
|
+
const cellsAfter = Array.from(
|
|
123
|
+
container.querySelectorAll('[role="gridcell"]')
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Same number of cells, and critically the same DOM node instances.
|
|
127
|
+
expect(cellsAfter.length).toBe(cellsBefore.length);
|
|
128
|
+
cellsBefore.forEach((node, i) => {
|
|
129
|
+
expect(cellsAfter[i]).toBe(node);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|